Forum: Haus & Smart Home mqtt von extern steuren


von mehraltfraumann (Gast)


Lesenswert?

Hallo guten Tag,

ich habe hier ein Gerät was auf MQTT reagiert.
Mein mosquitto Broker läuft auf einem Raspberry.

Ich würde gerne über eine  Website das Gerät von überall aus Steuern.
Da gibt es bestimmt leichte Wege. Aber ich habe noch keinen gefunden....
...
Ich habe schon versucht mit ngrok eine Apache2 Html Seite zu starten und 
öffentlich zu machen.
Diese HTML Seite soll an einen python-Server, der auf dem Port 8000 
hört,  Daten senden wenn,  man auf einen Button klickt.

Der Python Server soll dann den Befehl os.system('mosquitto_pub  ( 
...)') durchführen.
Das klappt aber irgendwie nur wenn ich die öffentliche Seite auf meinem 
PC ausführe. Man sieht dann, dass sich jemand einloggt beim Python 
Server.

Wenn  ich die Seite auf meinem Handy ausführe sehe ich keine Aktivität 
mehr beim Python Server. Somit funktionieren die mosquitto_pub  ( ...) 
Befehle auch nicht.

Also wie mache ich es, dass der Python server auch erreicht wird?
1
    const socket = new WebSocket('ws://127.0.0.1:8000');  /// ??????????

Hier ist der Server:
1
import asyncio
2
import websockets
3
import os
4
5
# create handler for each connection
6
7
async def handler(websocket, path):
8
9
    data = await websocket.recv()
10
11
    reply = f"Data12312312 recieved as:{data}!"
12
    os.system('mosquitto_pub -t /test -h xxx.xxx.xxx.xxx -m "1"') 
13
    await websocket.send(reply)
14
15
 ## handles messages?
16
async def handler(websocket):
17
    async for message in websocket:
18
        print(message)
19
        reply = f" recieved data from browser:!"
20
        if '1' in message:
21
            print ('there was a one')
22
            os.system('mosquitto_pub -t /test -h xxx.xxx.xxx.xxx -m "1"')
23
        if '2' in message:
24
             print ('there was a 2')
25
             os.system('mosquitto_pub -t /test -h xxx.xxx.xxx.xxx -m "2"')
26
        if '3' in message:
27
            print ('there was a 3')
28
            os.system('mosquitto_pub -t /test -h xxx.xxx.xxx.xxx -m "3"')
29
        if '4' in message:
30
            print ('there was a 4')
31
            os.system('mosquitto_pub -t /test -h xxx.xxx.xxx.xxx -m "4"')
32
33
start_server = websockets.serve(handler, "localhost", 8000)
34
35
asyncio.get_event_loop().run_until_complete(start_server)
36
asyncio.get_event_loop().run_forever()

Danke ...

von Thomas W. (Gast)


Lesenswert?

mehraltfraumann schrieb:

So richtig zu Verstehen ist Dein Beitrag nicht, aber
>
1
>     const socket = new WebSocket('ws://127.0.0.1:8000');  /// ??????????
2
>
ist genau das, was Du willst: Nur Zugriff von Localhost (vulgo die 
eigene Maschine).

Willst Du willst dass andere darauf spielen sollen, musst Du die 
IP-Adresse des Netzwerk-Interface (WLAN, Ethernet) angeben.

Gruesse

Th.

von J. S. (jojos)


Lesenswert?

Die Default Einstellungen für die Sicherheit verbieten erstmal den 
Zugriff außerhalb von 127.1, muss man in der mosquito configuration 
angeben wenn es erlaubt sein soll.

von Εrnst B. (ernst)


Lesenswert?

Das hier:
mehraltfraumann schrieb:
> os.system('mosquitto_pub -t /test -h xxx.xxx.xxx.xxx -m "1"')

ist auch ganz schlechter und potentiell gefährlicher Stil.
Sobald du statt "1" da irgendwelche Daten einsetzt die du durch den 
Websocket bekommen hast, bist du nur noch eine kleine Unachtsamkeit von 
der Remote Code Execution entfernt.

Python kann auch selber mqtt "sprechen", z.B.

pip3 install paho-mqtt,

from paho.mqtt import client as mqtt_client

usw.

Damit fällt dann auch die umgekehrte Richtung leichter, wenn die 
Webseite z.B. auch noch Messwerte aus dem mqtt anzeigen soll.


Ach ja, wenn dein Python-Programm nicht viel mehr machen soll, als MQTT 
-> Websocket zu übersetzen: Der mosquitto-Server kann das auch selber.
Einfach in der mosquitto-conf eintragen
1
listener 8000
2
protocol websockets
3
http_dir /irgendwo/htdocs
aus dem http_dir kann der auch gleich deine Webseite + JS ausliefern, 
d.H. den apache bist du im selben Schritt auch gleich los.

von mehraltfraumann (Gast)


Angehängte Dateien:

Lesenswert?

Thomas W. schrieb:
> zu Verstehen ist Dein Beitrag n

ich weiß.

Meine Website ist öffentlich ( immer nur kurzzeitig, um das zu testen)
Durch einen Button-Klick soll diese Website eine Nachricht an meinen 
Broker senden können.

Aber wie ?

Er ist von außen ja gar nicht zugänglich.
Er ist  lokal zugänglich über mqtt 1883 und 8080 als websocket  per 
mqtt.
Der python Server ist auch nicht erreichbar denke ich?
Er hört auf Port 8000.
Aber meine öffentlich  Website mit dem Button hat ja keine Ahnung wo der 
Python-Server ist.
Bzw.
1
const socket = new WebSocket('ws://127.0.0.1:8000');  /// ??????????
reicht nicht aus.

Kann man den den auch öffentlich machen?
Oder kann die Website den trotzdem erreichen?

Εrnst B. schrieb:
> aus dem http_dir kann der auch gleich deine Webseite + JS ausliefern,
> d.H. den apache bist du im selben Schritt auch gleich los.

Die ersten beiden Zeilen habe ich schon ( bloß mit 8080)
listener 8000
protocol websockets

Das hier habe ich noch  nicht:

http_dir /irgendwo/htdocs

Werde ich mal testen.

Danke :D

von mehraltfraumann (Gast)


Lesenswert?

Mosquitto hat jetzt die Html seite auf  dem 80 am laufen.

Ich kann auch darauf von extern zugreifen.

Soll ich jetzt ein Javascript dazu einbinden auf der html-Seite, dass 
dann den Broker ansprechen kann bei Button-Click?

von Εrnst B. (ernst)


Lesenswert?

mehraltfraumann schrieb:
> Soll ich jetzt ein Javascript dazu einbinden auf der html-Seite

musst du. Ohne Javascript spricht der Webbrowser kein Websocket und erst 
recht kein Mqtt-over-Websocket.

"Eclipse Paho" ist zwar etwas älter, tut aber:

Dokumentation hier:
https://www.eclipse.org/paho/files/jsdoc/Paho.MQTT.Client.html

Download hier:
https://projects.eclipse.org/projects/iot.paho/downloads
-> JavaScript client 1.0.3

von mehraltfraumann (Gast)


Lesenswert?

habe das jetzt mit paho getestet.
Kann zwar lokal zu meinem Broker senden  und auch zu test.mosquitto.org.
Aber wenn ich die Seite veröffentliche sendet der gar nicht zu meinem 
broker oder wenn ich an test.mosquitto.org senden möchte kommt 
folgendes:

Also in der Konsole bei Firefox:
1
Laden fehlgeschlagen für das <script> mit der Quelle "https://b663-188-96-145-0.ngrok.io/mqttws31.js". b663-188-96-145-0.ngrok.io:8:1
2
Uncaught DOMException: The operation is insecure. mqttws31.js:979
3
    _doConnect https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js:979
4
    connect https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js:849
5
    connect https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js:1799
6
    <anonym> https://b663-188-96-145-0.ngrok.io/:74
7
Mutations-Ereignisse sollten nicht mehr verwendet werden. Verwenden Sie MutationObserver stattdessen. analyser.js:485:17

von mehraltfraumann (Gast)


Lesenswert?

hier sagen die am Ende dass sie ssl verwenden, damit der Fehler nicht 
auftritt ...
keine Ahnung was man da beachten muss bei Mosquitto..

https://github.com/eclipse/paho.mqtt.javascript/issues/207

Ich könnte ja  testweise irgendeinen sicheren Server ansteuern.

von Jörg (Gast)


Lesenswert?

Hmm, das scheint mir alles etwas kompliziert...

Ich würde komplett auf JS und Websockets verzichten und eine simple 
Flask App in Python schreiben:
1
from flask import Flask
2
app = Flask(__name__)
3
 
4
@app.route('/dingelchen/an')
5
def dingelchen_an():
6
    # Paho Code zum publishen hier einfügen #
7
    return 'Dingelchen eingeschaltet'
8
9
@app.route('/dingelchen/aus')
10
def dingelchen_aus():
11
    # Paho Code zum publishen hier einfügen #
12
    return 'Dingelchen ausgeschaltet'
13
14
if __name__ == '__main__':
15
   app.run()

Dazu vll. noch einen Auth Header checken und es sollte gut sein.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.