diff --git a/software/mqqt_to_pe1rxf_telemetry/config.yaml b/software/mqqt_to_pe1rxf_telemetry/config.yaml index c4400c0..ffb02bb 100644 --- a/software/mqqt_to_pe1rxf_telemetry/config.yaml +++ b/software/mqqt_to_pe1rxf_telemetry/config.yaml @@ -6,6 +6,7 @@ global: #program-log: /home/marcel/rs458.log # All program output will be written to this file (0 = do not log to file) mqtt-server: mqtt.meezenest.nl mqtt-port: 1883 + telemetry-interval: 10 # number of seconds between transmissions # APRS settings aprs: @@ -14,12 +15,10 @@ aprs: to_call: PE1RXF-1 # Call of the receiver destination: APZMDM # APRS destination digipath: 0 # Digipeater path for weather reports (0 = no path) - interval: 30 # - port: ax1 # Linux AX.25 port to which APRS weather report is sent # call: PE1RXF-13 # Call from which transmissions are made (can be a different call from the call assigned to the AX.25 port) # destination: APZMDM # APRS destination # digipath: WIDE2-1 # Digipeater path for weather reports (0 = no path) -# interval: 30 # Define the MQTT data to transmit over AX25. The order of the items is the order the data is combined to the telemetry string. mqtt: diff --git a/software/mqqt_to_pe1rxf_telemetry/config_reader.py b/software/mqqt_to_pe1rxf_telemetry/config_reader.py index 6f0a1e3..95dfd22 100644 --- a/software/mqqt_to_pe1rxf_telemetry/config_reader.py +++ b/software/mqqt_to_pe1rxf_telemetry/config_reader.py @@ -58,6 +58,7 @@ class config_reader: tmp = self.config_file_settings['global']['program-log'] tmp = self.config_file_settings['global']['mqtt-server'] tmp = self.config_file_settings['global']['mqtt-port'] + tmp = self.config_file_settings['global']['telemetry-interval'] except: print ("Error in the global section of the configuration file.") return 0 @@ -72,7 +73,6 @@ class config_reader: tmp = entry['to_call'] tmp = entry['destination'] tmp = entry['digipath'] - tmp = entry['interval'] except: print ("Error in the aprs section of the configuration file.") return 0 diff --git a/software/mqqt_to_pe1rxf_telemetry/mqtt_to_pe1rxf_telemetry.py b/software/mqqt_to_pe1rxf_telemetry/mqtt_to_pe1rxf_telemetry.py index 09da443..f191db3 100644 --- a/software/mqqt_to_pe1rxf_telemetry/mqtt_to_pe1rxf_telemetry.py +++ b/software/mqqt_to_pe1rxf_telemetry/mqtt_to_pe1rxf_telemetry.py @@ -43,7 +43,7 @@ class MqttHandler: self.config = config # Define list with length equal to the number of subscriptions defined in the config file self.number_of_mqtt_subscriptions = len(config['mqtt']['subscribe']) - self.aprs_telemetry_data = ['0.0']*self.number_of_mqtt_subscriptions + self.aprs_telemetry_data = [bytes(b'0.0')]*self.number_of_mqtt_subscriptions def process_message(self, client, userdata, message): @@ -191,16 +191,13 @@ def send_data_to_aprs(weather_data, configuration): logging.error("Failed to send data to APRS radio.") logging.error(f"Command returned: {e}") +def main(): -Configuration, MqttClient, mqtt_handler = setup() -LoopCounter = 0 + Configuration, MqttClient, mqtt_handler = setup() + LoopCounter = 0 -while (1): - time.sleep(3) # Sleep for 3 seconds - - # Send APRS telemetry every 10 cycles = every 10 minutes - LoopCounter = LoopCounter + 1 - if LoopCounter >= 1: + while (1): + time.sleep(Configuration.config_file_settings['global']['telemetry-interval']) # Sleep for number of seconds set in config.yaml # Send data to LoRa radio via external program (/usr/sbin/beacon). Make sure we use all radios defined in the configuration file. for entry in Configuration.config_file_settings['aprs']: @@ -209,7 +206,6 @@ while (1): # We cannot send multiple APRS messages in a short period of time, so we wait 3 deconds between messages. time.sleep(3) - LoopCounter = 0 - - +if __name__ == '__main__': + main() diff --git a/software/rs485_client_to_mqtt/config.yaml b/software/rs485_client_to_mqtt/config.yaml index a633b85..666f103 100644 --- a/software/rs485_client_to_mqtt/config.yaml +++ b/software/rs485_client_to_mqtt/config.yaml @@ -13,6 +13,7 @@ global: modbus: #port: /dev/serial/by-path/platform-3f980000.usb-usb-0:1.3:1.0-port0 # USB port to which RS-485 dongle is connected port: /dev/ttyUSB0 + poll_speed: 60 # Polling speed in seconds # Modbus servers settings modbus_servers: diff --git a/software/rs485_client_to_mqtt/config_reader.py b/software/rs485_client_to_mqtt/config_reader.py index 2c38e1b..578c4a3 100644 --- a/software/rs485_client_to_mqtt/config_reader.py +++ b/software/rs485_client_to_mqtt/config_reader.py @@ -70,6 +70,7 @@ class config_reader: # Test is all expected settings are present try: tmp = self.config_file_settings['modbus']['port'] + tmp = self.config_file_settings['modbus']['poll_speed'] except: print ("Error in the modbus section of the configuration file.") return 0 diff --git a/software/rs485_client_to_mqtt/rs485_client_to_mqtt.py b/software/rs485_client_to_mqtt/rs485_client_to_mqtt.py index cb8a90b..3a43867 100644 --- a/software/rs485_client_to_mqtt/rs485_client_to_mqtt.py +++ b/software/rs485_client_to_mqtt/rs485_client_to_mqtt.py @@ -175,7 +175,7 @@ def data_logger(data, configuration): except: logging.warning("Could not write to file: " + new_filename) -def send_data_to_mqtt(data, configuration, modbus_registers, mqtt_client): +def send_data_to_mqtt(data, configuration, modbus_registers, MqttClient): mqtt_top_topic = [] mqtt_full_topic = [] @@ -208,8 +208,7 @@ def send_data_to_mqtt(data, configuration, modbus_registers, mqtt_client): # Go through every input register and match the unit and description with the value for index2, entry2 in enumerate(data['InputRegisters']): # Scale values - entry2 = entry2/ (10^entry1['input_register_names'][index2][2]) - + entry2 = entry2/ pow(10, entry1['input_register_names'][index2][2]) message_topic = entry1['input_register_names'][index2][0] mqtt_message = str(round(entry2,1)) mqtt_full_topic = mqtt_top_topic + message_topic @@ -234,68 +233,71 @@ def ReconnectModBus(configuration): logging.info("Reconnected to ModBus dongle.") -Configuration, Controller, ModbusAddresses, ModbusRegisters, MqttClient = setup() -LoopCounter = 0 +def main(): -while (1): - time.sleep(3) # Sleep for 3 seconds + Configuration, Controller, ModbusAddresses, ModbusRegisters, MqttClient = setup() + LoopCounter = 0 - ModBusData={} + while (1): + time.sleep(Configuration.config_file_settings['modbus']['poll_speed']) # Sleep for number of seconds given in config.yaml - # Loop through all configured ModBus devices and try to read the sensor data - for index, current_modbus_device in enumerate(ModbusAddresses): - logging.debug("Reading device on ModBus address: " + str(current_modbus_device)) + ModBusData={} - try: - ModBusData['DateTime'] = datetime.datetime.now().replace(microsecond=0).isoformat() - ModBusData['ID'] = Controller[index].get_id() - if ModBusData['ID'][0] == 0x4D45: - ModBusData['Type'] = Controller[index].get_type() - ModBusData['TypeString'] = Controller[index].get_type_string() - ModBusData['InputRegisters'] = Controller[index].read_all_input_registers() + # Loop through all configured ModBus devices and try to read the sensor data + for index, current_modbus_device in enumerate(ModbusAddresses): + logging.debug("Reading device on ModBus address: " + str(current_modbus_device)) - # Keep the watchdog from resetting the ModBusdevice - Controller[index].toggle_watchdog() - - NoError = True - except minimalmodbus.NoResponseError: - # Handle communication timeout - logging.warning("No response from the instrument on ModBus address: " + str(current_modbus_device)) - NoError = False - except minimalmodbus.InvalidResponseError: - # Handle invalid Modbus responses - logging.warning("Invalid response from the instrument on ModBus address: " + str(current_modbus_device)) - NoError = False - except minimalmodbus.SlaveReportedException as e: - # Handle errors reported by the slave device - logging.error(f"The instrument reported an error: {e}") - NoError = False - except minimalmodbus.ModbusException as e: - # Handle all other Modbus-related errors - logging.error(f"Modbus error: {e}") - NoError = False - except Exception as e: - # Handle unexpected errors, probably I/O error in USB/serial - logging.error(f"Unexpected error: {e}" + ", serial port " + Configuration.config_file_settings['modbus']['port'] + " not available while reading device on ModBus address " + str(ModbusAddresses[index]) + ". Try to reconnect.") - Controller[index].serial.close() - ReconnectModBus(Configuration) - NoError = False - - if NoError == True: try: - logging.debug("Found Mees Electronics sensor on ModBus address " + str(current_modbus_device)) - logging.debug("Serial number: " + hex(ModBusData['ID'][1]) + " " + hex(ModBusData['ID'][2]) + " " + hex(ModBusData['ID'][3])) - logging.debug("Device type: " + str(ModBusData['Type']) + " (" + ModBusData['TypeString'] + ")") - logging.debug (ModBusData['InputRegisters']) - #logging.debug (json.dumps(ModBusData, indent=1, sort_keys=False)) + ModBusData['DateTime'] = datetime.datetime.now().replace(microsecond=0).isoformat() + ModBusData['ID'] = Controller[index].get_id() + if ModBusData['ID'][0] == 0x4D45: + ModBusData['Type'] = Controller[index].get_type() + ModBusData['TypeString'] = Controller[index].get_type_string() + ModBusData['InputRegisters'] = Controller[index].read_all_input_registers() - except: - logging.warning("Modbus device type " + str(ModBusData['Type']) + " not found in register definition file. Ignoring sensor data.") + # Keep the watchdog from resetting the ModBusdevice + Controller[index].toggle_watchdog() - # Log sensor data to file if enabled in configuration file - data_logger(ModBusData, Configuration) + NoError = True + except minimalmodbus.NoResponseError: + # Handle communication timeout + logging.warning("No response from the instrument on ModBus address: " + str(current_modbus_device)) + NoError = False + except minimalmodbus.InvalidResponseError: + # Handle invalid Modbus responses + logging.warning("Invalid response from the instrument on ModBus address: " + str(current_modbus_device)) + NoError = False + except minimalmodbus.SlaveReportedException as e: + # Handle errors reported by the slave device + logging.error(f"The instrument reported an error: {e}") + NoError = False + except minimalmodbus.ModbusException as e: + # Handle all other Modbus-related errors + logging.error(f"Modbus error: {e}") + NoError = False + except Exception as e: + # Handle unexpected errors, probably I/O error in USB/serial + logging.error(f"Unexpected error: {e}" + ", serial port " + Configuration.config_file_settings['modbus']['port'] + " not available while reading device on ModBus address " + str(ModbusAddresses[index]) + ". Try to reconnect.") + Controller[index].serial.close() + ReconnectModBus(Configuration) + NoError = False - # Send sensor data to MQTT broker - send_data_to_mqtt(ModBusData, Configuration, ModbusRegisters.definition_file_data, MqttClient) + if NoError == True: + try: + logging.debug("Found Mees Electronics sensor on ModBus address " + str(current_modbus_device)) + logging.debug("Serial number: " + hex(ModBusData['ID'][1]) + " " + hex(ModBusData['ID'][2]) + " " + hex(ModBusData['ID'][3])) + logging.debug("Device type: " + str(ModBusData['Type']) + " (" + ModBusData['TypeString'] + ")") + #logging.debug (ModBusData['InputRegisters']) + #logging.debug (json.dumps(ModBusData, indent=1, sort_keys=False)) + except: + logging.warning("Modbus device type " + str(ModBusData['Type']) + " not found in register definition file. Ignoring sensor data.") + # Log sensor data to file if enabled in configuration file + data_logger(ModBusData, Configuration) + + # Send sensor data to MQTT broker + send_data_to_mqtt(ModBusData, Configuration, ModbusRegisters.definition_file_data, MqttClient) + +if __name__ == '__main__': + main()