MQTT Werte des subscribe werden nur während Wertübertragung des websocket verarbeitet- ansonsten nicht

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
jensgulow
User
Beiträge: 2
Registriert: Sonntag 1. September 2024, 10:57

Hallo,

eins vornweg - ich bin blutiger python-Neuling und bitte um Nachsicht, falls mein in Folge geschildertes Problem auf grundsätzliche Dummheit des Anwenders zurückzuführen ist ;-)

Ich habe es geschafft mein Gardena-Smart-Irrigation-System mittels websocket-Verbindung dazu zu bringen mir in Echtzeit Werte zu senden. Das klappt sehr gut. Da sich der Websocket bei Inaktivität disconnectet wird alle 150 sec. ein ping gesandt. Ausserdem wird der websocket nach 2h geschlossen - daher das rel-Konstrukt.
Nun möchte ich gerne mittels MQTT Befehle zu den Ventilen senden. Bisher passierte da gar nix. Nur durch Zufall habe ich einmal direkt während der Wertübermittlung des websockets eine Nachricht auf das topic MQTT_IN gesandt - und siehe da....die Nachricht kam an.

Nun meine Frage: wieso wird die MQTT-Nachricht nur direkt während der Wertübermittlung des websocket durchgeführt und ausserhalb dieser Übertragung passiert gar nichts wenn die MQTT-Nachricht gesandt wird?

MQTT während aktiver websocket Übertragung (der funktionale Teil dieses Codes wurde zu dem Zeitpunkt im Programm auskommentiert....es sollte nur das prizipielle Verhalten getestet werden):

Code: Alles auswählen

2024-08-31T13:13:13.304244150+02:00 ++Rcv decoded: fin=1 opcode=8 data=b'\x03\xe9Going away',
2024-08-31T13:13:13.304893903+02:00 ++Sent raw: b'\x88\x82@\x99\xa6\xf2Cq',
2024-08-31T13:13:13.305283017+02:00 ++Sent decoded: fin=1 opcode=8 data=b'\x03\xe8',
2024-08-31T13:13:13.308227385+02:00 msg {"id":"8ab391b8-0db6-42fd-b087-00xxxxxxxxxx","type":"COMMON","attributes":{"name":{"value":"Sensor Innenbeete"},"batteryLevel":{"value":76,"timestamp":"2024-08-24T19:04:22.000+00:00"},"batteryState":{"value":"UNKNOWN","timestamp":"2024-08-24T19:04:22.000+00:00"},"rfLinkLevel":{"value":100,"timestamp":"2024-08-31T09:04:25.000+00:00"},"serial":{"value":"00076841"},"modelType":{"value":"GARDENA smart Sensor"},"rfLinkState":{"value":"ONLINE"}}},
2024-08-31T13:13:13.308312161+02:00 msg {"id":"8ab391b8-0db6-42fd-b087-00xxxxxxxxxx","type":"SENSOR","attributes":{"soilHumidity":{"value":75,"timestamp":"2024-08-31T10:04:24.000+00:00"},"soilTemperature":{"value":21,"timestamp":"2024-08-31T10:04:25.000+00:00"}}},
2024-08-31T13:13:13.308355450+02:00 msg {"id":"8ab391b8-0db6-42fd-b087-00xxxxxxxxxx","type":"COMMON","attributes":{"name":{"value":"Sensor Innenbeete"},"batteryLevel":{"value":76,"timestamp":"2024-08-24T19:04:22.000+00:00"},"batteryState":{"value":"UNKNOWN","timestamp":"2024-08-24T19:04:22.000+00:00"},"rfLinkLevel":{"value":100,"timestamp":"2024-08-31T09:04:25.000+00:00"},"serial":{"value":"00076841"},"modelType":{"value":"GARDENA smart Sensor"},"rfLinkState":{"value":"ONLINE"}}},
[b]2024-08-31T13:13:13.308391847+02:00 ###geht los###,
2024-08-31T13:13:13.308444659+02:00 mqtt_in b'{\n            "data":{\n                    "type": "VALVE_CONTROL",\n                    "id": "d1f51a16-b89a-41ce-a1d8-27692ef2af1e:5",\n                    "attributes": {\n                                    "command": "START_SECONDS_TO_OVERRIDE",\n                                    "seconds": 60\n                                }\n                    }\n        }',
2024-08-31T13:13:13.308467524+02:00 ###geht los###,
2024-08-31T13:13:13.308489565+02:00 mqtt_in b'{\n            "data":{\n                    "type": "VALVE_CONTROL",\n                    "id": "d1f51a16-b89a-41ce-a1d8-27692ef2af1e:5",\n                    "attributes": {\n                                    "command": "START_SECONDS_TO_OVERRIDE",\n                                    "seconds": 60\n                                }\n                    }\n        }',
2024-08-31T13:13:13.308511574+02:00 ###geht los###,
2024-08-31T13:13:13.308595867+02:00 mqtt_in b'{\n            "data":{\n                    "type": "VALVE_CONTROL",\n                    "id": "d1f51a16-b89a-41ce-a1d8-27692ef2af1e:5",\n                    "attributes": {\n                                    "command": "START_SECONDS_TO_OVERRIDE",\n                                    "seconds": 60\n                                }\n                    }\n        }',[/b]
2024-08-31T13:13:13.308622184+02:00 msg {"id":"70cd0a17-3c76-437e-99xxxxxxxxxx","type":"SENSOR","attributes":{"soilHumidity":{"value":5,"timestamp":"2024-08-31T10:15:01.000+00:00"},"soilTemperature":{"value":20,"timestamp":"2024-08-31T08:15:02.000+00:00"}}},
2024-08-31T13:13:13.308645086+02:00 msg {"id":"70cd0a17-3c76-437e-99xxxxxxxxxx","type":"COMMON","attributes":{"name":{"value":"Sensor Aussenbeete"},"batteryLevel":{"value":76,"timestamp":"2024-06-29T15:14:44.000+00:00"},"batteryState":{"value":"UNKNOWN","timestamp":"2024-06-29T15:14:44.000+00:00"},"rfLinkLevel":{"value":80,"timestamp":"2024-08-31T09:15:01.000+00:00"},"serial":{"value":"00076993"},"modelType":{"value":"GARDENA smart Sensor"},"rfLinkState":{"value":"ONLINE"}}},
während solcher Zeiträume passiert beim Senden der MQTT-Nachricht gar nichts:

Code: Alles auswählen

2024-08-31T12:58:13.494757986+02:00 ++Rcv raw: b'\x8a\x00',
2024-08-31T12:58:13.494899785+02:00 ++Rcv decoded: fin=1 opcode=10 data=b'',
2024-08-31T13:00:43.459773605+02:00 Sending ping,
2024-08-31T13:00:43.460361370+02:00 ++Sent raw: b'\x89\x80\x95\xce\xce\xca',
2024-08-31T13:00:43.460741167+02:00 ++Sent decoded: fin=1 opcode=9 data=b'',
2024-08-31T13:00:43.497784480+02:00 ++Rcv raw: b'\x8a\x00',
2024-08-31T13:00:43.498089008+02:00 ++Rcv decoded: fin=1 opcode=10 data=b'',
2024-08-31T13:03:13.462573512+02:00 Sending ping,
2024-08-31T13:03:13.463146618+02:00 ++Sent raw: b'\x89\x80\x9d\xd3\xc8;',
2024-08-31T13:03:13.463542822+02:00 ++Sent decoded: fin=1 opcode=9 data=b'',
2024-08-31T13:03:13.500007019+02:00 ++Rcv raw: b'\x8a\x00',
2024-08-31T13:03:13.500256221+02:00 ++Rcv decoded: fin=1 opcode=10 data=b'',
2024-08-31T13:05:43.465400241+02:00 Sending ping,
2024-08-31T13:05:43.466025838+02:00 ++Sent raw: b'\x89\x80\xde\x99\xabe',
2024-08-31T13:05:43.466388601+02:00 ++Sent decoded: fin=1 opcode=9 data=b'',
2024-08-31T13:05:43.503160100+02:00 ++Rcv raw: b'\x8a\x00',
2024-08-31T13:05:43.503267470+02:00 ++Rcv decoded: fin=1 opcode=10 data=b'',
Anbei das py-Programm (läuft in einem DOCKER-Container)

Denkanstösse und/oder Lösungsvorschläge sind herzlich willkommen!

Code: Alles auswählen

import websocket
import datetime
from threading import Thread
import time
import sys
import requests
import os
import json
import paho.mqtt.client as mqtt
import rel

# account specific values
CLIENT_ID = os.environ['CLIENT_ID']
CLIENT_SECRET = os.environ['CLIENT_SECRET']
API_KEY = os.environ['API_KEY']

#MQTT Broker
BROKER = os.environ['BROKER_IP']
BROKER_PORT = int(os.environ['BROKER_PORT'])

#MQTT Topics
MQTT_OUT = os.environ['MQTT_OUT']
MQTT_IN = os.environ['MQTT_IN']
MQTT_ERROR = os.environ['MQTT_ERROR']

# other constants
AUTHENTICATION_HOST = 'https://api.authentication.husqvarnagroup.dev'
SMART_HOST = 'https://api.smart.gardena.dev'

AUTH_TOKEN =''

class Client:
    def on_message(self, any, message):
        print("msg", message)

        mclient.publish(MQTT_OUT, message)

    def on_error(self, error, *args):
        print("error", error)
        mclient.publish(MQTT_ERROR, error)

    def on_close(self, *args):
        self.live = False
        print("### closed ###")
        sys.exit(0)

    def on_open(self, any):
        print("### connected ###")



        self.live = True

        def run(*args):
            while self.live:
                time.sleep(1)

        Thread(target=run).start()

def format(response):
    formatted = [response.url, "%s %s" % (response.status_code, response.reason)]
    for k,v in response.headers.items():
        formatted.append("%s: %s" % (k, v))
    formatted.append("")
    formatted.append(r.text)
    return "\n".join(formatted)


class mqttClient:

    def on_close(self,*args):
        self.live = False
        print("### closed ###")
        sys.exit(0)

    def on_connect(self, client: mqtt.Client, userdata, flags, rc, properties):
        print("Connected with result code: "+str(rc))
        mclient.subscribe(MQTT_IN, 0)

    def on_subscribe(self, client: mqtt.Client, userdata, mid, reason_code_list, properties):
        print("Subscribed: " + str(mid) + " " + str(reason_code_list)+" " + str(properties))
        
    def on_message(self, client: mqtt.Client, userdata, msg): # hier wird garnichts ausgeführt
        print("###geht los###")
        print('mqtt_in', msg.payload)
        jsPayload = json.loads(msg.payload)
        jdata = jsPayload['data']
        ServiceID = jdata['id']
        headers = {
        "Content-Type": "application/vnd.api+json",
        "X-Api-Key": API_KEY,
        "Authorization": "Bearer " + AUTH_TOKEN}
        url = "https://api.smart.gardena.dev/v1/command/" + ServiceID
        response = requests.put(url, data=msg.payload, headers=  headers)

        print(response)


if __name__ == "__main__":
    payload = {'grant_type': 'client_credentials', 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET}

    print("Logging into authentication system...")
    r = requests.post(f'{AUTHENTICATION_HOST}/v1/oauth2/token', data=payload)
    assert r.status_code == 200, format(r)
    auth_token = r.json()["access_token"]
    print("Logged in auth_token=(%s)" % auth_token)

    headers = {
        "Content-Type": "application/vnd.api+json",
        "x-api-key": API_KEY,
        "Authorization": "Bearer " + auth_token
    }

    print("### get locations ###")
    r = requests.get(f'{SMART_HOST}/v1/locations', headers=headers)
    assert r.status_code == 200, format(r)
    assert len(r.json()["data"]) > 0, 'location missing - user has not setup system'
    location_id = r.json()["data"][0]["id"]
    print("LocationId=(%s)" % location_id)


    payload = {
        "data": {
            "type": "WEBSOCKET",
            "attributes": {
                "locationId": location_id
            },
            "id": "does-not-matter"
        }
    }
    print("getting websocket ID...")
    r = requests.post(f'{SMART_HOST}/v1/websocket', json=payload, headers=headers)

    assert r.status_code == 201, format(r)
    print("Websocket ID obtained, connecting...")
    response = r.json()
    websocket_url = response["data"]["attributes"]["url"]

    websocket.enableTrace(True)

    mclient = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
    
    MqttClient = mqttClient()
    mclient.on_connect = MqttClient.on_connect
    mclient.on_subscribe = MqttClient.on_subscribe
    mclient.on_message = MqttClient.on_message
    
    mclient.connect(BROKER,BROKER_PORT)
    mclient.loop_start()
    
    client = Client()    
    ws = websocket.WebSocketApp(
        websocket_url,
        on_message=client.on_message,
        on_error=client.on_error,
        on_close=client.on_close)
    ws.on_open = client.on_open
    ws.run_forever(dispatcher=rel, reconnect=5, ping_interval=150, ping_timeout=1)
    rel.signal(2, rel.abort)
    rel.dispatch()
Viele Grüße

Jens
jensgulow
User
Beiträge: 2
Registriert: Sonntag 1. September 2024, 10:57

Kann als gelöst bezeichnet werden ....es fehlte eine Zeile ;-)

Code: Alles auswählen

if __name__ == "__main__":
    payload = {'grant_type': 'client_credentials', 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET}

    print("Logging into authentication system...")
    r = requests.post(f'{AUTHENTICATION_HOST}/v1/oauth2/token', data=payload)
    assert r.status_code == 200, format(r)
    auth_token = r.json()["access_token"]
    print("Logged in auth_token=(%s)" % auth_token)
    
    AUTH_TOKEN = auth_token								####### <----- DIESE ZEILE fehlte !!!#########

    headers = {
        "Content-Type": "application/vnd.api+json",
        "x-api-key": API_KEY,
        "Authorization": "Bearer " + auth_token
Antworten