Events

:

:

Elektronik | Funk | Software

Der Technik-Blog

  • Social Media

    Werbung:


    Neue Artikel


    Events

    • Keine zukünftigen Events vorhanden

    Der Technik-Blog

    Arduino Worldwide Bidirectional Communication

    UDP Message Server Code

    Alex @ AEQ-WEB

    Für das Projekt "Arduino weltweit steuern" wird ein Server benötigt, der als UDP Paket Relay funktioniert. Das Script wurde in Python programmiert und ist somit ohne Einschränkungen in der Regel mit allen Betriebssystemen kompatibel. Auf dieser Seite gibt es die Dokumentation zur Serversoftware.

    Die Voraussetzungen

    Damit das UDP Relay gestartet werden kann, wird die Installation von Python benötigt. Sollte das Relay öffentlich erreichbar sein, wird ein öffentlicher Server benötigt. Alternativ kann dieser Server auch Zuhause mit entsprechenden Portforwarding und einem dynamischen IP-Updater (DynDNS, NO-IP...) auf einem Raspberry betrieben werden. Das Script wurde unter Python3 getestet.

    Werbung:

    Wie das Relay funktioniert

    Das Relay wird je nach Betriebssystem meistens über einen entsprechenden Befehl gestartet. Dadurch wird ein Socket auf den Port 9999 gestartet. Die Software wechselt anschließend in eine Schleife und wartet auf ein "Keep-Alive" vom Controller. Sobald sich dieser meldet und sich als "Arduino" ausgibt, ist dem Server der offene Port und die öffentliche IP-Adresse vom Controller bekannt. Ab sofort werden alle gültigen Befehle an diese IP-Adresse weitergeleitet. Sollte sich der Controller noch nicht beim Server gemeldet haben und es kommen trotzdem bereits Steuerbefehle vom Client, so sendet der Server eine entsprechende Fehlermeldung an den Client zurück. Wichtig ist, dass sich nach dem Programmstart zuerst immer der Controller beim Server melden muss, damit Steuerbefehle vom Client über den Server zum Controller gesendet werden können.

    Hat sich der Controller beim Server angemeldet, so kann ab sofort über den Client jederzeit ein Steuerbefehl empfangen und weitergeleitet werden. Da aus dem Internet auch sehr viel "Müll" am Server ankommt, müssen die UDP Pakete entsprechend gefiltert werden. Unter "Müll" versteht man in diesem Fall UDP-Pakete, die von einem anderen System an den Server gesendet werden, aber eigentlich nicht dafür bestimmt sind (z. B. VoIP Anfragen usw.). Um eine Weiterleitung von falschen UDP-Paketen an den Controller zu verhindern, prüft die Software alle ankommenden Steuerbefehle. Sobald ein Befehl "CMD:" enthält, wird er an den Controller weitergeleitet. Umgekehrt erkennt der Server ein Datenpaket vom Controller, da sich dieser mit seinen Namen (Arduino) meldet. Kommt vom Controller ein Paket, wird es an die Adresse vom zuletzt verbundenen Client gesendet. Es können daher Steuerbefehle von beliebig vielen Clients gesendet werden, aber nur der Client, der zuletzt etwas zum Server gesendet hat, bekommt die Antwort.

    Download Python Server (ZIP)

    Python UDP Relay
    Download

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    import socket
    
    server_address = '0.0.0.0'  # Listen on all
    server_port = 9999  # Listen on Port 9999
    controller_name = "Arduino"  # Name or ID of your Controller
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    controller_address = ""
    controller_reg = False
    client_adr = ""
    client_reg = False
    RECV_BUFFER = ""  # Buffer for received data
    server = (server_address, server_port)
    sock.bind(server)  # Start Socket on Server and bind address
    print("Listening on " + server_address + ":" + str(server_port))
    
    while True:
        print("---")
        payload, client_address = sock.recvfrom(1024)
        print("OK     <-Received: " + str(payload) + " From: " + str(client_address))
        RECV_BUFFER = str(payload)  # Save received data into buffer
        data = RECV_BUFFER.split(";")  # Create array split by ; ( eg. ;Arduino;Parameter;... )
        datalen = len(data)  # Get length of elements in data array
        if datalen == 4:
            device = str(data[1])
            device_cmd = str(data[2])
            if device == controller_name:  # If your controller (eg. Arduino) has connected
                controller_reg = True
                controller_address = client_address
                print("OK     ->Send Response to Controller at " + str(controller_address))
                if client_reg and device_cmd != "Keep-Alive":
                    sent = sock.sendto(bytes("MSG-DEV: " + device_cmd, 'utf-8'), client_adr)
                    print("OK     ->Controller confirmed command")
            sent = sock.sendto(b"MSG-SRV: Received!", controller_address)  # Send "M:MSG Received! to connected Controller
        else:
            if controller_address != "" and controller_reg == True:
                if datalen == 1:
                    if "CMD:" in str(data[0]):
                        print("OK     ->Send Command to Controller (" + data[0] + ")")
                        sent = sock.sendto(bytes(data[0], 'utf-8'), controller_address)
                        sent = sock.sendto(bytes("MSG-SRV: CMD forwarded to " + controller_name, 'utf-8'), client_address)
                        client_reg = True
                        client_adr = client_address
                    else:
                        sent = sock.sendto(b"Warning: Message received, but not forwarded to client!", client_address)
                        client_reg = True
                        client_adr = client_address
                else:
                    print("OK     <-Received unknown Control Command")
            else:
                print("Error: Controller is not connected")
                sent = sock.sendto(b"Error: Controller is not connected", client_address)
    


    Code Beschreibung

    In diesem Absatz sind die einzelnen Befehlszeilen beschrieben:

    1: Import die Socket Bibliothek von Python
    3: Aktiviert den Server auf allen Netzwerken
    4: Definiert den Port, auf dem UDP Datenpakete empfangen werden
    5: Der Name, mit dem sich der Mikrocontroller als dieser Identifiziert (Arduino)
    7,13,14: Startet den Socket Server
    8-12: Reservierung von Variablen, die vom Code automatisch beschrieben werden
    15: Ausgabe -> Server wurde gestartet
    17-52: Dieser Teil des Programmes läuft durchgehend in einer Schleife
    19: Wenn der Server ein UDP-Paket empfängt, werden daraus die Nutzdaten und Informationen zu IP und Port übergeben 1024 = maximale Paketgröße
    20: Ausgabe -> Inhalt des Datenpaketes und Absender IP, Port
    21: Empfangene Nutzdaten (Steuerbefehle) werden in einen Buffer geladen
    22: Der empfange Befehlssatz wird durch ";" aufgetrennt und in ein Array (data) zerlegt
    23: Die Anzahl der Elemente im Array (data) werden ermittelt. | Bsp: ;Controllername;Steuerbefehl; = 4 Elemente (0;1;2;3)
    24: Wenn das Array "data" vier Elemente enthält, wird der Code bis einschließlich Zeile 34 ausgeführt. (Trifft nur zu, wenn der Controller ein Paket sendet)
    25,26: Deklariert Controllername und Controllerbefehl aus dem Array (data)
    27: Prüft, ob das Datenpaket vom Arduino kommt (Vergleich mit Zeile 5)
    28, 29: Identifiziert den Controller und speichert seine Adresse. An diese Adresse werden alle vom Client empfangenen Steuerbefehle gesendet
    32: Leitet die Rückantwort vom Arduino nach einem Steuerbefehl an den Client weiter
    34: Bestätigt dem Controller den Erhalt vom empfangenen Datenpaket
    35: Führt die folgenden Befehle nur aus, wenn sich der Arduino zuvor bereits verbunden hat
    36: Führt die folgenden Befehle nur aus, wenn das Array nur ein Element enthält (Ist nur der Fall, wenn ein Befehl vom Client kommt)
    37: Führt die folgenden Befehle nur aus, wenn im Datenpaket "CMD:" vorkommt (Bsp: CMD:LED=1 -> wird verarbeitet, LED=1 -> wird abgelehnt)
    40: Sendet empfangenen Steuerbefehl vom Client an den Controller weiter
    41: Informiert den Client über die Weiterleitung vom Datenpaket zum Controller
    42,43: Identifiziert den Client und speichert seine Adresse. An diese Adresse werden alle vom Controller empfangenen Datenpakete weitergeleitet
    44-47: Fehlerfall: Wenn der Steuerbefehl vom Client nicht "CMD:" enthält
    50-52: Fehlerfall: Wenn ein Steuerbefehl an den Server gesendet wird, aber der Controller noch nicht verbunden ist

    Werbung:


    122X122

    Über den Autor

    Alex, der Gründer von AEQ-WEB. Seit über 10 Jahren beschäftigt er sich mit Computern und elektronischen Bauteilen aller Art. Neben den Hardware-Projekten entwickelt er auch Webseiten, Apps und Software für Computer.

    Top Artikel in dieser Kategorie:

    Arduino IRFZ44N PWM MOSFET Load Control

    Arduino MOSFET Steuerung

    • Video
    • DE/EN

    In diesen Artikel zeigen wir wie man große Lasten mittels eines MOSFET-Transistors über das Arduino Board steuert und die Drehzahl von einem Motor regelt

    Weiterlesen
    Arduino LM358 PT1000 Sensor Converter

    Temperatur messen mit PT1000 & Arduino

    • Video
    • DE/EN

    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?

    Weiterlesen

    Social Media

    Werbung:


    Neue Artikel


    Events

    • Keine zukünftigen Events vorhanden