First sort of working mqtt routines

This commit is contained in:
marcel
2025-08-11 21:31:31 +02:00
parent f722f8aec1
commit 8afdc890f1
15 changed files with 443 additions and 31 deletions

View File

@@ -21,12 +21,68 @@ import sys
import logging
import minimalmodbus
import datetime
import subprocess
import os
from pathlib import Path
from modbus_control import ModBusController
from config_reader import config_reader
from modbus_definition_file_reader import definition_file_reader
import paho.mqtt.client as mqtt
from paho.mqtt.client import CallbackAPIVersion
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes
properties=Properties(PacketTypes.PUBLISH)
properties.MessageExpiryInterval=30 # in seconds
import ssl
version = '3' # or '5'
mqtt_transport = 'tcp' # or 'websockets'
if version == '5':
client = mqtt.Client(CallbackAPIVersion.VERSION2, client_id="myPy",
transport=mqtt_transport,
protocol=mqtt.MQTTv5)
if version == '3':
client = mqtt.Client(CallbackAPIVersion.VERSION2, client_id="myPy",
transport=mqtt_transport,
protocol=mqtt.MQTTv311,
clean_session=True)
#client.username_pw_set("user", "password")
import mqtt_callbacks
client.on_message = mqtt_callbacks.on_message;
client.on_connect = mqtt_callbacks.on_connect;
#client.on_publish = mqtt_callbacks.on_publish;
client.on_subscribe = mqtt_callbacks.on_subscribe;
mqtt_broker = 'mqtt.meezenest.nl'
mqtt_port = 1883
mqtt_keepalalive=60
mqtt_topic = 'topic/important'
if version == '5':
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes
properties=Properties(PacketTypes.CONNECT)
properties.SessionExpiryInterval=30*60 # in seconds
client.connect(mqtt_broker,
port=mqtt_port,
clean_start=mqtt.MQTT_CLEAN_START_FIRST_ONLY,
properties=properties,
keepalive=60);
elif version == '3':
client.connect(mqtt_broker, port=mqtt_port, keepalive=mqtt_keepalalive);
client.loop_start();
while 1:
client.publish(mqtt_topic,'Cedalo Mosquitto is awesome',2,properties=properties);
time.sleep(1)
def setup():
config_file = "config.yml"
definition_file = "modbus_registers.yaml"
@@ -104,6 +160,35 @@ def data_logger(data, configuration):
except:
logging.warning("Could not write to file: " + new_filename)
# It is not possible to send multiple beacons in a short time. Call this function not faster than every 3 seconds or so.
def send_data_to_aprs(weather_data, configuration):
# Define the Bash script and its arguments as a list
script = "/usr/sbin/beacon"
if configuration['digi_path'] == 0:
arguments = ["-d", f"{configuration['destination']}", "-s", "ax1", ":PE1RXF-3 :test2"]
else:
arguments = ["-d", f"{configuration['destination']} {configuration['digi_path']}", "-s", "ax1", ":PE1RXF-3 :test3"]
# Combine the script and its arguments into a single list
command = [script] + arguments
# Run the script
logging.debug(command)
try:
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Check the result
if result.returncode == 0:
logging.info("Send data to APRS radio.")
else:
logging.error("Failed to send data to APRS radio.")
logging.error(f"Reason: {result.stderr}")
except Exception as e:
logging.error("Failed to send data to APRS radio.")
logging.error(f"Command returned: {e}")
def send_data_to_mqtt(data, configuration, modbus_registers):
#logging.debug(modbus_registers)
@@ -117,7 +202,10 @@ def send_data_to_mqtt(data, configuration, modbus_registers):
# Go through every input register and match the unit and description with the value
for index2, entry2 in enumerate(data['InputRegisters']):
logging.debug(entry1['input_register_names'][index2][0] + ": " + str(entry2) + entry1['input_register_names'][index2][1])
print(entry1['input_register_names'][index2][2])
# Scale values
entry2 = entry2/ (10^entry1['input_register_names'][index2][2])
logging.debug(entry1['input_register_names'][index2][0] + ": " + str(round(entry2,1)) + entry1['input_register_names'][index2][1])
logging.debug("Send data to MQTT broker.")
@@ -137,13 +225,24 @@ def ReconnectModBus(configuration):
logging.info("Reconnected to ModBus dongle.")
#print("Enable heater function")
#controller.enable_heater()
Configuration, Controller, ModbusAddresses, ModbusRegisters = 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:
# 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']:
send_data_to_aprs(1, entry)
# We cannot send multiple APRS messages in a short period of time, so we wait 3 deconds between messages.
time.sleep(3)
LoopCounter = 0
ModBusData={}
# Loop through all configured ModBus devices and try to read the sensor data
@@ -157,6 +256,10 @@ while (1):
ModBusData['Type'] = Controller[index].get_type()
ModBusData['TypeString'] = Controller[index].get_type_string()
ModBusData['InputRegisters'] = Controller[index].read_all_input_registers()
# Keep the watchdog from resetting the ModBusdevice
#Controller[index].toggle_watchdog()
NoError = True
except minimalmodbus.NoResponseError:
# Handle communication timeout
@@ -183,7 +286,6 @@ while (1):
if NoError == True:
try:
DeviceType = ModbusRegisters.definition_file_data['devices'][ModBusData['Type']]
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'] + ")")
@@ -198,3 +300,5 @@ while (1):
# Send sensor data to MQTT broker
send_data_to_mqtt(ModBusData, Configuration, ModbusRegisters.definition_file_data)