Alpha version of ModBus-MQTT and MQTT-APRS software.

This commit is contained in:
marcel
2025-08-14 15:39:50 +02:00
parent f5a6937786
commit ce1b59fb6f
6 changed files with 71 additions and 72 deletions

View File

@@ -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:

View File

@@ -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

View File

@@ -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()