Messwerte über MQTT auslesen und verarbeiten

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
amophylus
User
Beiträge: 5
Registriert: Montag 17. August 2020, 10:18

Hallo,

ich möchte mir eine kleine, eigene Wetterstation bauen und die Daten entsprechend visualisieren. Dazu habe ich erstmal einen Sensor gebaut welcher mittels MQTT seine Messwerte (Temperatur, Luftfeuchte, Luftdruck) alle 5 sec an den Broker sendet.
Nun plane ich ein Pythonprogramm welches die Messwerte empfängt und für den Anfang in eine .csv Datei schreibt, daran versuche ich mich seit einigen Tagen erfolglos. Die Messwerte kommen in verschiedenen Topics um sie nicht durcheinander zu würfeln( "/innen/temp", "/innen/humidity", "innen/pressure" am liebsten wäre es mir ich würde alles in einer Datei erhalten zusammen mit einem Zeitstempel (Muster) "Datum, Uhrzeit, Temperatur(XX.X),Luftfeuchte(XX),Luftdruck(XXXX.XX)". Allerdings schaffe ich es nicht einmal die daten in einer gemeinsamen Zeile der Konsole auszugeben.

Code: Alles auswählen

import paho.mqtt.client as mqtt
temp = []
def on_message(client, userdata, msg):
	#print(msg.topic+" "+(msg.payload))
	if "/innen/temp" in (msg.topic):
		temp = (msg.payload)
		print(temp)
	if "/innen/humidity" in (msg.topic):
		humidity = int(msg.payload)
		print(humidity)
	if "/innen/pressure" in (msg.topic):
		pressure = float(msg.payload)
		print(pressure)

client = mqtt.Client()
client.on_message = on_message
client.connect("localhost", 1883)
client.subscribe("/innen/#")
client.loop_forever()


mittels diesem Code habe ich zumindest die Ausgabe in der Konsole, füge ich unter das letzte "if" noch

Code: Alles auswählen

print(temp, humidity, pressure)


hinzu, erscheint keine Ausgabe.

Nun bin ich mit meinem Latein am Ende und hoffe auf Hilfe.
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

So wie ich das sehe, bekommst du ja pro "on_message"-Aufruf nur einen Wert. Deine print-Zeile sollte nach dem letzten if sollte daher nicht "keine Ausgabe" sondern eine Fehlermeldung verursachen, weil mindestens 2 Variablen nicht definiert sind.
Wenn du die 3 Werte gleichzeitig haben willst, musst du sie in einer entsprechenden Datenstruktur sammeln.
amophylus
User
Beiträge: 5
Registriert: Montag 17. August 2020, 10:18

Hallo,

das ist leider nicht der Fall, ich habe vergessen das temp= [ ] zu löschen, das war einer der Tests...

Bei diesem Code:

Code: Alles auswählen

import paho.mqtt.client as mqtt
def on_message(client, userdata, msg):
	#print(msg.topic+" "+(msg.payload))
	if "/innen/temp" in (msg.topic):
		temp = float(msg.payload)
		print(temp)
	if "/innen/humidity" in (msg.topic):
		humidity = int(msg.payload)
		print(humidity)
	if "/innen/pressure" in (msg.topic):
		pressure = float(msg.payload)
		print(pressure)
	
	print(temp, humidity, pressure)
client = mqtt.Client()
client.on_message = on_message
client.connect("localhost", 1883)
client.subscribe("/innen/#")
client.loop_forever()

kommt diese ausgabe:

pi@Pi3:~ $ sudo python mqtt_empfang.py
24.7
67
993.05

Die werte würden nach 5 sec kommen nach 5 sec wieder.

Das wird ignoriert.

Code: Alles auswählen

 print(temp, humidity, pressure) 
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@amophylus: Das wird nicht ignoriert das führt zu einer Ausnahme weil da immer zwei der drei Namen undefiniert sind.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
amophylus
User
Beiträge: 5
Registriert: Montag 17. August 2020, 10:18

Hallo,

nun versuche ich es in einer Liste zu sammeln, das klappt auch, aber leider sieht die ausgabe nun so aus:

pi@Pi3:~ $ sudo python mqtt_empfang.py
[24.9]
[24.9, 64]
[24.9, 64, 992.23]

das ist der Code dazu:

Code: Alles auswählen


import paho.mqtt.client as mqtt

werte = []

def on_message(client, userdata, msg):

	#print(msg.topic+" "+(msg.payload))

	if "/innen/temp" in (msg.topic):
		werte.append(float(msg.payload))
	if "/innen/humidity" in (msg.topic):
		werte.append(int(msg.payload))
	if "/innen/pressure" in (msg.topic):
		werte.append(float(msg.payload))
		
	print(werte)

client = mqtt.Client()
client.on_message = on_message
client.connect("localhost", 1883)
client.subscribe("/innen/#")
client.loop_forever()

Gibt es eine Möglichkeit das Ganze in einer "normalen" for Schleife einzubinden? oder vielleicht gibts eine andere Möglichkeit die Werte zuzuordnen
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich verstehe die Frage nicht. Warum willst du eine for-Schleife? Und was soll da zugeordnet werden? Meinst du damit, dass die verschiedenen Topics verschieden verarbeitet werden?
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Du willst hier ein ereignisbasiertes callback in einen seriellen Ablauf umwandeln. Da du Zustand über den Funktionsaufruf hinaus merkten musst, brauchst du eine Klassendefinition. Und wenn pressure immer als letztes kommt, dann darfst du die Werte erst dort ausgeben.
amophylus
User
Beiträge: 5
Registriert: Montag 17. August 2020, 10:18

Hallo,

@ _deets_ Ich arbeite das erste Mal mit MQTT und bin mir des genauen Ablaufes nicht bewusst. Im Prinzip benötige ich (fürs erste) erstmal ein Programm welches die Messwerte meines Sensor aufnimmt und verarbeitet. ich möchte die 3 unterschiedlichen Werte welche später als Verlauf (letzte 24h als Graph) und als Aktuell angezeigt werden sollen, prinzipell ist die Verarbeitung immer gleich. Die for schleife ist nur eine idee. für alle anderen Lösungen bin ich auch offen da ich es aktuell nicht durchschaue.

@Sirius3 Das klingt grundsätzlich nach dem wie ich es möchte, aber wie funktioniert das? Im Aktuellen Programm stapeln sich die Daten und werden nicht so ausgegeben wie ich eigentlich möchte.

Ziel des ganzen wäre:

Erstmal eine .csv Datei mit

Datum, Uhrzeit, Temperatur, Luftfeuchte, Luftdruck

welche die Messwerte speichert.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Also eine for-Schleife wird hier nicht helfen. Du bekommst nunmal die einzelnen Ereignisse per callback geliefert, und das ist dem Funktionsprinzip von MQTT geschuldet. Eine weitere Komplikation ist aber deine eigene Entscheidung: dass du alle drei Daten *getrennt* uebermittelst, aber gleichzeitig alle drei Werte in eine Zeile bekommen willst. Wenn du nicht das MQTT QOS Level auf 2 gesetzt hast, ist nicht garantiert, dass du immer 3 Werte bekommst. Und ich glaube auch nicht, dass dir da jemand die Reihenfolge garantiert. QOS 2 wiederum ist nich immer von allen Clients unterstuetz, und ich wuerde das nur machen, wenn es wirklich notwendig waere. Was bei sowas wie der Temperatur einfach nicht der Fall ist, wenn da von 10 Werten einer fehlt, ist das wurscht.

Ich wuerde also diese Randbedingungen aendern. Entweder strukturierst du deine CSV-Datei um, so dass sie

Datum, Groesse, Wert

enthaelt, dann kannst du naemlich einfach bei jedem Ereignis eine Zeile schreiben.

Oder du aenderst deinen MQTT Client im Sensor so, dass er einfach immer gleich alle drei Werte gleichzeitig uebertraegt, statt nacheinander.
amophylus
User
Beiträge: 5
Registriert: Montag 17. August 2020, 10:18

Hallo,

Das wäre ein erster Ansatz für den Weg zu Werten in einer Datei, längerfristig würde ich nicht mehr in eine Datei sondern in einen "Zwischenspeicher" schreiben wollen und mir damit nur die letzten 24h sichern und den Rest verwerfen um Platz zu sparen, eine Live-Anzeige ist geplant mit dann einem Graphen zum Verlauf der letzten 24h... Wäre es da nicht sinnvoll die entsprechenden getrennten topics zu behalten? Leider ist dieses Projekt etwas ausgeufert und ich weiß noch nicht wie genau ich es verwirklichen kann
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein, es ist nicht sinnvoller. Ich benutze MQTT via mosquitto und Telegraf um die Zeitreihen in einer InfluxDB zu speichern. Das ist im Grunde das, wo du enden willst. Und auch ich schicke nur *ein* Paket, mit allen Sensorwerten gleichzeitg.

*GEHEN* tut es mit drei Datenstroemen natuerlich, aber dann kannst du genauso auch einfach drei Dateien schreiben. Warum machst du das dann nicht einfach? Glaub mir, wenn dich das jetzt schon ueberfordert, dann ueberfordert es dich erst recht, eine robuste Erkennung zu schreiben, mit der du feststellst, dass du gerade genug Daten beisammen hast, um eine weitere Zeile zu schreiben...
Antworten