Seite 1 von 1

Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 15:22
von roliver
Hallo @all,

ich habe eine Verständnis Frage...

Code: Alles auswählen

def on_message(client, userdata, message):
  if topic == '/mach/was':
    if msg == 'NIX':
       print("ENDE")
        ... Publish eine Nachricht in ein topic ...
   if msg == 'START':
       ... oder wie kann ich das tun ...
 
Wie kann ich ein PUBLISH in einen TOPIC senden? oder wie kann ich das anders auswerten?

Gruß

Oliver

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 15:29
von __deets__
Da fehlt mir zu viel Kontext. Welche Bibliothek benutzt du, woher kommt denn das topic (so gibt's nen NameError), was soll "oder wie kann ich das tun" heissen?

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 15:49
von __blackjack__
`msg` ist auch undefiniert und die Einrückung ist kaputt. Wäre schön wenn man tatsächlichen Code zu sehen bekäme. 🙂

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 20:53
von roliver
Hallo,

klar, habe jetzt mal so "gelöst"..

Code: Alles auswählen

#!/usr/bin/python3.5

import paho.mqtt.client as mqtt
global runme

def on_connect( client, userdata, flags, rc):
    print ("Connected with Code :" +str(rc))
    # Subscribe Topic from here
    client.subscribe("/abstand/#")


def on_message(client, userdata, message):
 msg = str(message.payload.decode("utf-8"))
 topic = str(message.topic)
 global runme
 if topic == '/abstand/pumpe':
   if msg == 'STOP':
       print("STOPen")
       runme = 1
       #mqtt.publish("/wassertonne/relay/", "0") # Versuch geht nicht
   if msg == 'START':
       print("STARTEN")
       #client.publish("/wassertonne/relay/", "0", hostname="iot.eclipse.org") # Auch der Versuch mit .loop_forever()
       runme = 2
       

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.username_pw_set("agent", "geheim")
client.connect("localhost", 1883, 60)

# client.loop_forever() # war vorher...
client.loop_start()
time.sleep(1)
runme = 0
while True:
    if runme == 1:
        client.publish("/wassertonne/relay/", "0")
        client.publish("/abstand/set", "pumpoff")
        runme = 0
        
    if runme == 2:
        client.publish("/wassertonne/relay/", "1")
        client.publish("/abstand/set", "pumpan")
        runme = 0
        
    time.sleep(0.5)

client.loop_stop()
client.disconnect()
geht das besser?

Gruß

Oliver

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 21:34
von __deets__
In on_message hast du doch den Client - warum rufst du da nicht einfach publish auf? So kann der Loop wieder für immer laufen.

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 22:03
von roliver
weil das nicht geht bei mir, da passiert nix...

Code: Alles auswählen

if msg == 'STOP':
       print("STOPen")
       mqtt.publish("/wassertonne/relay/", "0")
       print("fertig")
auf der console erscheint nur "STOPen" aber "fertig" nicht und es erfolgt kein Publish..

das war mein erster Ansatz...

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 22:06
von __blackjack__
@roliver: Die Frage war warum Du auf dem *Client*-Exemplar das Du ja als *Argument* übergeben bekommst, nicht `publish()` aufrufst.

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 22:07
von __deets__
Du sollst ja auch nicht mqtt nehmen. Sondern client. Das erste Argument für on_message. Steht in der Doku: https://pypi.org/project/paho-mqtt/#callbacks

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 22:21
von roliver
bitte um Beispiel, stehe jetzt ganz auf dem Schlauch.. sorry

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 22:25
von __deets__
Schau in deinen eigenen Code. In die Funktion on_message. Wieviele Argumente hat die? Und wie heißen die?

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 22:31
von __blackjack__
@roliver: Eine `publish()`-*Funktion* gibt es in dem Modul doch auch überhaupt gar nicht. Wie kommst Du also darauf so etwas wie ``mqtt.publish(…)`` zu schreiben? Es ist also auch falsch zu behaupten da passiere gar nichts – das gibt eindeutig einen `AttributeError` und das folgende `print()` wird nicht ausgeführt. 'fertig' erscheint da also sicher nicht. Die Fehlerbeschreibung passt also nicht zum gezeigten Quelltext.

Den Verdacht erhärtet auch das `time.sleep()` das mysteriöserweise verwendet wird ohne das Modul importiert zu haben.

``global`` ist schlecht – schmeiss das raus und programmiere das ordentlich. Alles was in einer Funktion oder Methode ausser Konstanten verwendet wird, sollte als Argument(e) übergeben werden. Auf Modulebene hat ``global`` zudem überhaupt gar keinen Effekt. Vergiss das Schlüsselwort am besten sofort wieder.

Eingerückt wird in Python mit vier Leerzeichen pro Ebene. Bring das Deinem Editor bei.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

`decode()` liefert bereits eine Zeichenkette, es macht keinen Sinn da noch mal `str()` mit aufzurufen. Bevor man `payload` dekodiert sollte man vielleicht auch *erst* prüfen ob das überhaupt das `topic` ist was einen interessiert, denn andere können da ja etwas ganz anderes kodiert haben als Zeichenketten in UTF-8.

Da sich die Kommandos gegenseitig ausschliessen ist nur im ersten Fall ein ``if`` sinnvoll und ab da ``elif``. Und zum Schluss noch ein ``else`` das dafür sorgt das unbekannte oder vielleicht falsch geschriebene Kommandos nicht einfach ohne irgendeine Meldung ignoriert werden. So zum Beispiel das irgendwer statt "pumpon" etwas wie "pumpan" in den Quelltext schreibt.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3.5
import paho.mqtt.client as mqtt


def on_connect(client, _userdata, _flags, return_code):
    print("Connected with Code:", return_code)
    client.subscribe("/abstand/#")


def on_message(client, _userdata, message):
    if message.topic == "/abstand/pumpe":
        command = message.payload.decode("utf-8")
        if command == "STOP":
            print("STOPen")
            client.publish("/wassertonne/relay/", "0")
            client.publish("/abstand/set", "pumpoff")
        elif command == "START":
            print("STARTEN")
            client.publish("/wassertonne/relay/", "1")
            client.publish("/abstand/set", "pumpon")
        else:
            print("Unbekanntes Kommando {!r}!".format(command))


def main():
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.username_pw_set("agent", "geheim")
    client.connect("localhost", 1883, 60)
    try:
        client.loop_forever()
    except KeyboardInterrupt:
        pass  # Ignored intentionally.
    finally:
        client.loop_stop()
        client.disconnect()


if __name__ == "__main__":
    main()

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 22:34
von roliver

Code: Alles auswählen

if msg == 'START':
       print("STARTEN")   # Erscheint auf der console
       client.publish("/wassertonne/relay/", "0", hostname="mywatercli") # auch keine Meldung auf Server
       print("STARTEN")  # Erscheint NICHT auf der console
das hat ich doch auch getestet aber auch ohne erfolg...

Re: Python mqtt on_message und Publish

Verfasst: Mittwoch 4. September 2019, 22:46
von __blackjack__
@roliver: Wenn Du schon nicht verraten magst wie Du auf ``mqtt.publish()`` gekommen bist, verrate doch mal wie Du darauf kommst das `Client.publish()` ein Argument mit dem Namen `hostname` hat? Zeig doch bitte mal die Stelle in der Dokumentation wo die `Client.publish()`-Methode dokumentiert ist und dort dann dieses Argument…

Re: Python mqtt on_message und Publish

Verfasst: Donnerstag 5. September 2019, 00:38
von roliver
Hallo,

erst mal danke an __blackjack__.
Es ist meine erstes Python Programm, ja ich habe da wohl ein paar Fehler gemacht. Das mit dem mqtt.publish war so eine Blitz Idee, warum auch immer. Sorry jetzt klar, wenn ich als client übergebe kann ich auf nix anders auch zugreifen.
Das mit dem Hostname, hat mir Frau Google gezeigt. Und Nein, habe noch nicht RTFM gemacht...

Danke für die Hilfe, hoffe darf noch dumme Fragen stellen...


PS.: __blackjack__ dein Code geht, Danke habe ihn auch soweit verstanden.

Wozu ist das ganze.. habe ein paar Kapazitive feuchte Sensoren erhalten für Bewässerung. Damit kann ich jetzt die Pumpe starten und stoppen, so das sich alles selbst bewässert. Passieren kann nix, nur 12V, außer Kanister leer, Pumpe trocken... naja das löse ich noch.. es läuft schon mal...

Gruß

Oliver

Re: Python mqtt on_message und Publish

Verfasst: Donnerstag 5. September 2019, 09:39
von __deets__
Wenn das auf Dauer laufen soll, wuerde ich den PI eliminieren, und stattdessen einen ESP32 oder aehnliches damit beauftragen. Den kannst du auch mit micropython programmieren. Ein PI ist viel zu fehleranfaellig. Da sind die Pflanzen dann schnell vertrocknet.

Re: Python mqtt on_message und Publish

Verfasst: Donnerstag 5. September 2019, 23:02
von roliver
klar geht das auch ohne Linux PC aber ich wollt auch die Sprache etwas lernen, naja verstehen. Eines noch off Topic, kann Python auch als Service/Dienst laufen oder geht das nur über den Screen weg?

Re: Python mqtt on_message und Publish

Verfasst: Donnerstag 5. September 2019, 23:22
von __blackjack__
@roliver: Die Frage ist nicht ob das auch ohne Linux-PC geht, sondern ob es wirklich *mit* geht. Je komplexer das System, Hardware und Software, desto mehr kann schief laufen.

Man kann auch Services/Dienste mit Python programmieren. Wie eigentlich in jeder anderen Programmiersprache auch.

Re: Python mqtt on_message und Publish

Verfasst: Freitag 6. September 2019, 06:58
von Tholo
https://www.heise.de/ratgeber/Automatis ... 21096.html

Vielleicht findest du ja Inspirationen in diesem Artikel.

Re: Python mqtt on_message und Publish

Verfasst: Freitag 6. September 2019, 09:55
von __blackjack__
@Tholo: Ich vermute mal Du hast ein Heise+-Abo, bist angemeldet, und kannst den Artikel komplett lesen. Falls nicht wird ab dem Absatz „Notwendig ist eine Lösung, …“ der Text ausgeblendet und es folgt Werbung und Anmeldemöglichkeit für's Abo.