Mit diesem Demonstrator zeigen wir unser Messuhr Funkmodul M8 und unser externes Display 280.
Beide Messuhr-Module sind zur ständigen Übertragung der Messwerte konfiguriert. Die Messwerte werden an einen MQTT Broker gesendet. Ein Python Programm im Hintergrund übernimmt diese Messwerte, subtrahiert sie und sendet das Ergebnis an das externe Display.

Konfiguration der Messuhr-Funkmodule

Für das Demo-Projekt werden die Messuhrmodule über eine USB Stromversorgung mit Energie versorgt. Genauso wäre eine Energieversorgung über Akku möglich.
Nach dem Einschalten der Module werden diese zunächst über eine Web-Oberfläche konfiguriert. Hierzu stellen die Module einen eigenen Access-Point zur Verfügung „raaare_[mac-adresse]“. Nach der WLAN-Verbindung mit diesem Accesspoint kann über einen beliebigen Browser unter der Adresse http://192.168.33.1 eine Verbindung zum Device aufgebaut werden.
In der Konfigurationsoberfläche werden die wesentlichen Parameter eingestellt.

Die Verbindungsparameter zum WLAN Netzwerk und zum MQTT Broker werden eingegeben.
Es wird ein zyklischer Messintervall von 200ms gewählt. Damit werden 5 Messungen pro Sekunde ausgeführt und zum MQTT Broker gesendet.
Für jede Messuhr wird ein individueller MQTT Topic gewählt, z.B.
rare/gauge1 und rare/gauge2.

Konfiguration des Displays

Ebenso wie die Funkmodule der Messmittel hat auch das Display eine eigene Konfigurationsoberfläche. Nachdem die Stromversorgung zum Display hergestellt ist öffnet auch das Display einen eigenen Accesspoint. Nach der WLAN Verbindung zum Accesspoint erfolgt die Konfiguration durch den Aufruf von „http://192.168.4.1“ im Browser.

Auch hier wird die Verbindung zum WLAN und MQTT Broker eingetragen. Der MQTT topic kann frei gewählt werden.

In unserem Beispiel verwenden wir ein Python Programm um die Messwerte zu übernehmen, zu subtrahieren und dann an das Display zu senden:

import paho.mqtt.client as mqttcli
import time

MQTT_SERVER = "localhost"
MQTT_PORT = 1883
MQTT_SUB = "rare/"
MQTT_CLI = 'mqtt-cli-python-1'
USERNAME = '' # optional
PASSWORD = 'secret'
RECONNECT_RATE = 2
MAX_RECONNECT_COUNT = 999
MAX_RECONNECT_DELAY = 30

# gauge:
#   get data:
# M4: rare/<id>/digimatic/value
# M8: rare/<id>/meas/value     
#   request data:
# M4: rare/<id>/digimatic/request/set   (no payload)
# M8: rare/<id>/in/meas/rep_cnt    payload=1
MQTT_CH1_TOKEN = "gauge1"
MQTT_CH1_ISM4 = False
MQTT_CH1_INTERVAL = True
MQTT_CH2_TOKEN = "gauge2"
MQTT_CH2_ISM4 = False
MQTT_CH2_INTERVAL = True
# display:
# mqtt: free to configure
MQTT_DISP = "rare/display/1/value"

value1 = 0.0
value2 = 0.0
hasValue1 = False

# mqtt client connect
def on_connect(client, userdata, flags, rc):
    if rc == 0 and client.is_connected():
        print("mqtt connected")
        # client.subscribe(MQTT_SUB+'#')
        if (MQTT_CH1_ISM4):
            client.subscribe(MQTT_SUB+MQTT_CH1_TOKEN+'/digimatic/value')
        else:
            client.subscribe(MQTT_SUB+MQTT_CH1_TOKEN+'/meas/value')
        if (MQTT_CH2_ISM4):
            client.subscribe(MQTT_SUB+MQTT_CH2_TOKEN+'/digimatic/value')
        else:
            client.subscribe(MQTT_SUB+MQTT_CH2_TOKEN+'/meas/value')
    else:
        print(f'mqtt connect failed. code={rc}')

# auto reconnect if connection get lost
def on_disconnect(client, userdata, rc):
    print(f'mqtt disconnected, code={rc}')
    reconnect_count = 0
    reconnect_delay = 1
    while reconnect_count < MAX_RECONNECT_COUNT:
        print(f"mqtt reconnecting in {reconnect_delay} sec")
        time.sleep(reconnect_delay)
        try:
            client.reconnect()
            print("mqtt reconnected")
            return
        except Exception as err:
            print("mqtt reconnect failed: {err}")
        reconnect_delay *= RECONNECT_RATE
        reconnect_delay = min(reconnect_delay, MAX_RECONNECT_DELAY)
        reconnect_count += 1
    print("mqtt reconnect failed after {reconnect_count} attempts")
    global doExit
    doExit = True

# mqtt client receiver
def on_message(client, userdata, msg):
    global hasValue1
    global value1
    global value2
    topics = msg.topic.rsplit('/')
    payload = str(msg.payload.decode("utf-8"))
    print(f"mqtt data received: {topics} = {payload}")
    time.sleep(0.03) # secs - avoid "bad char in struct format"
    if ((topics[2] == "meas") or ((topics[2] == "digimatic"))) and (topics[3] == "value"):
        if (topics[1] == MQTT_CH1_TOKEN) and (len(topics)==4):
            try:
                value1 = float(payload)
            except:
                print(f"payload invalid") # e.g. "E:001" if no value available
        elif (topics[1] == MQTT_CH2_TOKEN) and (len(topics)==4):
            try:
                value2 = float(payload)
            except:
                print(f"payload invalid")
        sendToDisp(value2-value1)

def doPublish(topic,value):
    if mqtt.is_connected():
        result = mqtt.publish(topic, value)
        # result: [0, 1]
        status = result[0]
        if status == 0:
            print(f'  mqtt send ok: {topic}={value}')
        else:
            print(f'  mqtt send failed: {topic}={value}')
        time.sleep(0.05) # secs - avoid "bad char in struct format" 0.04

def sendToDisp(value):
    # send value to display
    # mqtt.publish(MQTT_DISP,str(value))
    doPublish(MQTT_DISP,round(value, 3))

print(f"mqtt connect...")
mqtt = mqttcli.Client(client_id = MQTT_CLI)
if USERNAME != "":
    mqtt.username_pw_set(USERNAME, PASSWORD)
mqtt.on_connect = on_connect
mqtt.on_message = on_message
mqtt.on_disconnect = on_disconnect
mqtt.connect(MQTT_SERVER, MQTT_PORT, keepalive=120)
mqtt.loop_start()
time.sleep(1) # secs
print(f"press ctrl-c to stop")
try:
    while not doExit:
        mqtt.loop_forever()
finally:
    print("done.")
    mqtt.disconnect()

Ein kleines Video zeigt den Demostrator in Aktion.

Comments are closed, but trackbacks and pingbacks are open.