PHP Dashboard für HmIP Smartmeter
09.10.2024
Elektronik | Funk | Software
Der Technik-Blog
Ein netzwerkfähiger Mikrocontroller kann über das lokale LAN Netzwerk oder über W-LAN recht unkompliziert gesteuert werden. Auch eine bidirektionale Verbindung zwischen zwei Systemen ist in der Regel ohne viel Aufwand möglich. Möchte man einen Controller wie den Arduino aber nicht nur im eigenen LAN steuern, sondern von überall auf der Welt, dann wird es wesentlich komplizierter, aber trotzdem ist es machbar. In diesem Artikel geht es um den Aufbau einer bidirektionalen Verbindung zwischen einem Client (Smartphone, Webseite oder anderer Mikrocontroller) und dem Arduino über ein UDP Server Relay. Dieses Beispiel funktioniert in der Regel auch hinter jeder Firewall oder einem NAT-Router. Eine öffentliche IP-Adresse oder ein Port-Forwarding zum Arduino sind nicht notwendig!
Code Dokumentation: Python UDP Server Relay
Code Dokumentation: Python UDP Relay
Artikel 2: Arduino über PHP steuern
Obwohl das Projekt recht einfach aufgebaut ist, werden Grundkenntnisse in der Arduino-Programmierung, Serveradministration und in Python benötigt. Außerdem werden Linux-Kenntnisse auf Kommandozeilenebene benötigt. Damit das Projekt funktioniert, wird ein Server benötigt, der öffentlich erreichbar ist. Virtuelle Server für dieses Projekt bekommt man bereits um einige wenige Euro im Monat. Alternativ kann man auch einen Raspberry Pi verwenden, der öffentlich erreichbar ist.
Eine bidirektionale Verbindung besteht aus mindestens zwei Geräten, die in beide Richtungen kommunizieren können. In einem lokalen LAN oder bei einer direkten Verbindung funktioniert das auch recht einfach. Über das Internet funktioniert dies in der Regel nicht so einfach. Firewalls und NAT Router blockieren dies oder verschieben die Ports einzelner Protokolle. Ziel ist es, einen Arduino Uno zu jederzeit über das Internet ansprechen zu können. Außerdem soll der Arduino an den Client eine entsprechende Rückmeldung senden können. Die Verbindung sollte zuverlässig sein, kaum Datenmengen erzeugen und auch über sehr langsame Leitungen wie DSL oder GSM (GPRS) funktionieren.
Die größte Hürde im Internet ist meistens die eigene Firewall. Denn die Firewall verhindert, dass unerwünschte Datenpakete aus dem Internet in das eigene LAN kommen. Diese grundsätzliche Funktion einer Firewall ist essenziell und sollte auch nicht deaktiviert werden. Damit jedoch ein Server dem Client eine Antwort senden kann oder ein Server unseren Arduino im lokalen LAN ein Datenpaket senden kann, muss die Firewall entsprechend offen sein. Sendet ein Gerät aus dem lokalen Netzwerk ein Datenpaket zu einem Server, muss dieses Paket die Firewall passieren. Ausgehende Verbindungen lässt die Firewall in der Regel immer zu, weshalb das Datenpaket recht unkompliziert durch die Firewall hinaus zum Webserver kommt. Parallel dazu merken sich sowohl Firewall, als auch alle beteiligten Router, woher das Datenpaket kommt und wohin es will. Denn sendet der Server ein Datenpaket zurück, sollte dieses auch wieder beim absendenden Gerät ankommen. Für ein bestimmtes Zeitfenster bleibt die Firewall daher geöffnet und alle Router merken sich den Herkunftsweg. Man spricht hier von einer TTL-Zeit (Time to Live), was einen Zeitraum in Sekunden bestimmt, in der Firewalls geöffnet bleiben und die Routen aufrecht gehalten werden. In der Regel sind das etwa 30 bis 90 Sekunden, höchstens jedoch 255 Sekunden. Die Zeit hängt auch vom verwendeten Protokoll ab. Damit unser Arduino auch ständig erreichbar bleibt, müssen wir trotzdem vom Arduino aus in einem bestimmten Intervall ein Datenpaket an den Server senden. Dieses Datenpaket muss auch nicht unbedingt eine Steuerinformation enthalten, es könnte daher auch "leer" sein.
Ein weiteres wichtiges Thema ist die NAT. Denn die NAT ändert die Ports, über die die einzelnen Protokolle laufen. Dadurch ersparen sich die Internetanbieter unter anderem speziell bei mobilen Produkten öffentliche IP-Adressen. Nebenbei wird auch die Sicherheit erhöht, da sich die geöffneten Ports immer wieder ändern und nur temporär offen sind. Für dieses Projekt bedeutet das, dass sich der am Arduino definierte Empfangsport am Weg zum Server mehrmals ändert. Da dies von den Routern automatisch erledigt wird, sind die Ports (mit Ausnahme des Serverports) für dieses Projekt nicht weiter relevant.
Für den Testaufbau wird ein Arduino Uno mit aufgestecktem Ethernet Shield verwendet. Es muss nicht zwingend ein Arduino sein, denn dieses Projekt funktioniert auch mit minimalen Modifikationen auf einem ESP32, ESP8266, NodeMCU oder auch auf STM Boards. In weiterer Folge wurde am Mikrocontroller eine LED mit entsprechenden Vorwiderstand angeschlossen, die über einen digitalen Output geschaltet werden kann. Wird der Arduino aktiviert, so wird als erstes das Netzwerk gestartet, IP Adresse bezogen und versucht, den Server zu kontaktieren. Erst wenn sich der Arduino einmalig beim Server gemeldet hat, kann er Steuerbefehle vom Server empfangen. Zudem muss ja auch die Firewall entsprechend öffnen und ein Routing erstellt werden. Anschließend wechselt der Arduino in dem Empfangsmodus. Sollte ein entsprechendes Datenpaket ankommen, wird der Arduino dieses Datenpaket lesen. Ist im Datenpaket die Steuerinformation "LED=1" enthalten, wird die angeschlossene LED aktiviert. Der Arduino sendet anschließend eine Rückmeldung mit der Ausführungsbestätigung an den Server zurück. Der Server leitet diese Bestätigung an den Client weiter. Kommt der Befehl "LED=0" wird die LED wieder abgeschaltet und die entsprechende Rückmeldung wird gesendet. Außerdem sendet der Arduino alle 30 Sekunden ein "Keep-Alive" Datenpaket an Server, damit die Routen und Firewalls geöffnet bleiben. Die Software, Dokumentation und den Quellcode gibt es hier.
Das Serverprogramm besteht aus einem einfachen Pythonscript, der einen TCP/UPD Socket an einem bestimmten Port (9999) öffnet. Der Server fungiert grundsätzlich als Relay, was bedeutet, dass empfangene Datenpakete von den Clients an das Arduino Board weitergeleitet werden. Primär regelt der Server die Kommunikation zwischen den Client und dem Arduino und filtert ungültige Datenpakete heraus. Das Programm kann hier heruntergeladen werden. Eine Dokumentation zu dieser Software und den Quellcode gibt es hier.
Als Client kann jedes Gerät bzw. jede Software verwendet werden, die in der Lage ist, UDP Pakte auszusenden und zu empfangen. Dies kann beispielsweise ein PHP-Script einer Webseite sein, eine Desktopanwendung oder auch anderer Mikrocontroller sein. Für iOS & Android gibt es sehr viele Apps, die als ein TCP/UDP Terminal funktionieren. Dadurch kann der Arduino recht komfortabel weltweit und mobil über das Smartphone gesteuert werden. Nachfolgend die im YouTube Video verwendeten Apps:
Um den Arduino zu steuern, müssen bestimmte Befehle im Datenpaket vorkommen. Wichtig ist, dass jeder Steuerbefehl mit "CMD:" beginnt. Dadurch kann der Server erkennen, dass es sich um einen Steuerbefehl für den Arduino handelt. Nur dann wird das Paket auch vom Server weiter zum Controller gesendet. Der Grund für die Notwenigkeit besteht darin, dass leider auch sehr viele Datenpakte aus dem Internet am Server ankommen, die gar nicht dafür bestimmt sind. Dadurch wird verhindert, dass keine unnötigen UDP-Pakete weitergeleitet werden. Der eigentliche Steuerbefehl (Bsp. "LED=1") wird vom Server nicht geprüft und direkt an den Controller weitergeleitet. Dies hat den Vorteil, dass jederzeit neue Steuerbefehle eingeführt werden können, ohne dabei Änderungen an der Serversoftware durchführen zu müssen. Folgende Befehle können derzeit im Beispielprojekt verwendet werden und über jeden UDP Client an den Server gesendet werden:
Befehl zum Einschalten der LED am Arduino:
CMD:LED=1
Rückmeldung vom Controller/Server im Erfolgsfall:
MSG-DEV: DONE
Befehl zum Ausschalten der LED am Arduino:
CMD:LED=0
Rückmeldung vom Controller/Server im Erfolgsfall:
MSG-DEV: DONE
Befehl zum Abfragen vom Gerätestatus (IP, Laufzeit):
CMD:INFO
Rückmeldung vom Controller/Server im Erfolgsfall:
MSG-DEV: Arduino-IP: 10.1.1.117 Uptime: 17 sec
PT1000 Sensoren können nicht direkt analog mit einem Mikrocontroller gemessen werden. Wie baut man einen Messwandler mit dem LM358 für den PT1000 und Arduino?
WeiterlesenDer PT100 ist ein sehr präziser industrieller Temperatursensor. In diesem Artikel geht es um den Bau eines Messverstärkers zum Einlesen eines PT100 am Arduino
WeiterlesenAEQ-WEB © 2015-2024 All Right Reserved