Hilfe bei der Datenübertragung von 2 Raspberry Pis im selben Netzwerk

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
knl146
User
Beiträge: 4
Registriert: Dienstag 15. Dezember 2020, 15:22

Hallo zusammen,

mein aktueller Stand: ich habe einen Raspberry Pi (RP A)(Abkürzung) kombiniert mit einem Mikrofon. Auf diesem habe ich ein Pythonscript laufen, das auf ein Wakeword, wartet. Sobald dieses erkannt wird, nimmt das Mikrofon meine Stimme auf und wandelt es mit GoogleSpeechToText in ein String um. Aus diesem String wird mit einer Methode ein Event und maximal 2 weitere Variablen als String ausgelesen. Falls es z.B. nur eine Variable ist, wird Variable 2 einfach leer gelassen.

Bsp1: "Mach das Schreibtisch Licht auf rot". event="SetLightColour"; variable1="Schreibtisch"; variable2="rot"
Bsp2: "Halte die Musik an". event="StopMusic", variable1="", variable2""

Es wird dann mit einem anderen Script jeweils der herausgelesene Befehl ausgeführt. Also hier im Beispiel wird das die Schreibtisch LED auf rot gesetzt und die Musik wird angehalten. Alles bis hierher funktioniert perfekt.

Jetzt meine Frage: Ich habe mir nun einen 2. Raspberri Pi (RP B) gekauft. RP A soll weiterhin das Mikrofon verwenden und das Event und die 2 Variablen auslesen, aber soll das Event jetzt nicht selber ausführen sondern diese 3 Variablen an den RP B übergeben. RP B soll also als zentrale Steuereinheit dienen und alle Events ausführen, die er vom RP A und eventuell noch weiteren bekommt.
Ich habe bis hierher fast keine Probleme gehabt, das ganze zu Programmieren, da ich mich zu jeder Sache einfach im Internet informieren konnte, allerdings weiß ich jetzt bei diesem Thema nicht, nach was ich googeln kann.

RP A soll ein Event in Form der 3 Strings an RP B übergeben und RP B soll dieses dann mit Python verarbeiten.
RP A soll jedoch auch einfach nur einzelne Werte vom RB B erhalten können z.B. aktuelle Farbe einer LED.
RP B soll auf Anfrage aber auch ganze MP3 Dateien zurück an RP A übertragen/schicken können.

Was ist für mein Beispiel die beste Möglichkeit diese Daten zu übertragen?
Ich brauch gar keinen Code an sich sondern einfach nur einen paar Begriffe, mit denen ich es leichter habe darüber was zu recherchieren. Ich habe z.B. schon ein bisschen zu Sockets und Webservern gefunden, weiß aber nicht, ob das jetzt das richtige für mein Problem ist.

Vielen Dank für eure Hilfe schon mal im Voraus:)
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@knl146: Sofern das immer von RP A angestossen wird, ist das einfach eine kleine Webanwendung. Man kann die Werte leicht per HTTP übertragen und als Antwort auch ganze Dateien senden, beispielsweise Musikdateien.

Die Anfrage kann man als JSON übertragen. Da solltest Du dann aber auch a) keine unnötigen leeren Werte übertragen und b) die nicht `variable1` und `variable2` nennen, sondern ordentliche, sinnvolle Namen verwenden.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
knl146
User
Beiträge: 4
Registriert: Dienstag 15. Dezember 2020, 15:22

Vielen Dank für die Antwort, hat mir sehr weitergeholfen.
Thants
User
Beiträge: 34
Registriert: Dienstag 1. Dezember 2020, 12:00

Ein weiteres Stichwort wäre hier "Remote Procedure Call" (RPC). Das bezeichnet Mechanismen, wie man in einem Programm Funktionen bzw. Methoden (oder eben "Prozeduren") aufrufen kann, die dann aber auf einem anderen Rechner ausgeführt werden. Es gibt da eine ganze Reihe von Bibliotheken mit unterschiedlichen Eigenschaften. z.B. gRPC von Google oder xmlrpc, was von Python bereits von Haus aus unterstützt wird (es gibt aber auch andere, da müsstest du eben mal schauen, was bei dir am besten passt).

Für den Hausgebrauch und/oder erste Tests würde es vielleicht ja sogar schon ausreichen, einfach per ssh ein Kommando auf dem anderen Rechner auszuführen, was dann die eigentliche Operation anstößt.

(falls das auch außerhalb von deinem Heimnetzwerk laufen soll, müsste man allerdings noch strenger darauf achten, dass man sich keine Sicherheitslücken einbaut. Da kämen dann noch so Sachen wie Authentifizierung und Verschlüsselung ins Spiel)
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Thants: Was gegen die meisten RPC Mechanismen sprechen würde sind die Dateiübertragungen. Eine MP3-Datei möchte man beispielsweise eher nicht in eine XML-RPC-Antwort verpacken.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Thants
User
Beiträge: 34
Registriert: Dienstag 1. Dezember 2020, 12:00

@__blackjack__: Das ist richtig. Als reines Datenübertragungsprotokoll für größere Binärdaten ist sowas wie xmlrpc wohl eher ungeeignet. Ich habe die Eingangsfrage allerdings so verstanden, dass er/sie sich erstmal einen Überblick über mögliche Optionen verschaffen will.
Wir kennen ja auch noch nicht wirklich die Details der Anwendung. Man muss ja nicht sämtliche Daten per RPC übertragen. Wenn die Raspis im gleichen lokalen Netz sind, könnte man schauen, ob man denen nicht Zugriff auf ein gemeinsames Netzlaufwerk geben kann (evtl. sogar von einem der beiden selbst bereitgestellt). Die mp3-Dateien könnten dann per normalem Schreibzugriff in den gemeinsamen Dateibaum geschrieben werden und RPC wäre dann immer noch eine Option, wo man dann nur noch den Dateipfad übergeben muss.
Man könnte auch schlicht und einfach die mp3-Dateien per scp übertragen. Ich denke, es gibt da viele Möglichkeiten, es hängt dann eben von den Anforderungen der Anwendung ab, welche Optionen am besten geeignet sind. Man muss aber die Optionen erstmal kennen, bevor man die beste aussuchen kann. :)
knl146
User
Beiträge: 4
Registriert: Dienstag 15. Dezember 2020, 15:22

Hey ihr beiden,

ich möchte vom RP A angestoßene Events im json Format irgendwie an RP B posten (alles nur innerhalb des eigenen Netzwerkes). Vom RP B sollen dann alle Variablen die ich geschickt habe direkt in ein anderes Pythonscript übergeben werden (siehe Code unten). Und je nach Eventtyp (ChangeLightColour, ChangeLightState, PlayMusic, AddToMusicQueue, SkipSong usw.. oder einfach nur sowas wie GetLightColour) sollen dann entweder einzelne Variablen, oder auch eben wie gesagt MP3- Dateien wieder zurück an meinen Client (RP A oder eventuell noch weitere) geschickt werden oder auch einfach nur eine Bestätigung, dass das Event erfolgreich war.

Ich habe mir jetzt gestern http.server, Flask und requests bisschen angeschaut und muss sagen, dass das eigentlich das ist nach dem gesucht habe. Ich werde zwar keine GUI für den Webserver brauchen, da ich nicht mit dem Handy das Licht z.B. mit irgendwelchen HTML Buttons steuern will, sondern es reicht ja wie gesagt aus, wenn meine Raspis unteranander automatisiert kommunizieren können. Aber das ist ja auch kein Problem, dann lass ich einfach den gesamten HTML code weg (falls das so funktioniert wie ich mir das vorstelle).

Ich habe noch nicht wirklich viel jetzt dazu ausprobiert, wie das ganze funktioniert, sondern habe mir eher noch paar code Beispiele angeschaut. Ich versuche jetzt einfach mal einen kleinen Webserver mit Server.py und Client.py zu schreiben. Hier soll jetzt der Client eine random Zahl zwischen 1 und 10 schicken und der Server soll , wenn die Zahl größer als 5 ist mit True antworten, anderen falls mit False. Mal schauen wie gut ich damit zurecht komme.



Hier noch eine kleine Frage: Ich habe bis jetzt immer das Event und die 2 dazugehörigen Variablen an folgendes Script weitergegeben:

Code: Alles auswählen

import os

def main(event, value1, value2):
    for filename in os.listdir('./events'):
        if filename.endswith('.py'):
            if event == filename[:-3]:
                string = f'from events import {event}'
                exec(string)
                string = f"{event}.main(\'{value1}\',\'{value2}\')"
                exec(string)
                break
Kann ich diese Methode auch weiterhin, wenn ich das, wie beschrieben, mit http.server umsetze, verwenden?
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@knl146: Die Frage ist nicht ob Du das einsetzen kannst, denn Du solltest das nicht einsetzen. Das ist extrem gruselig und nicht robust was Du da machst.

Warum gehst Du mit `os.listdir()` in einer Schleife alle Dateinamen durch um eine passend benannte Datei zu finden? Ein ``if os.exists(f"events/{event}.py")`` wäre viel kürzer und direkter. Das was Du da machst ist letztlich das hier:

Code: Alles auswählen

def main(event, value1, value2):
    if os.path.exists(f"events/{event}.py"):
        exec(f"from events import {event}")
        exec(f"{event}.main('{value1}', '{value2}')")
Aber von `exec()` bzw. Quelltext generieren sollte man die Finger lassen solange man das nicht wirklich braucht. Was sehr selten ist. In der Regel ist das ein Zeichen, dass die Programmiersprache nicht mächtig oder dynamisch genug ist, für das was man da vorhat. Python ist aber ziemlich mächtig und dynamisch:

Code: Alles auswählen

from importlib import import_module


def main(event, value1, value2):
    try:
        module = import_module(f"events/{event}")
    except ImportError:
        pass  # Ignored, like in the original.
    else:
        module.main(value1, value2)
Hier hat man jetzt auch das Problem umgangen das Quelltext generieren erfordert, das man Werte ordentlich escaped. Denn Dein Code wäre sehr leicht auf die Nase gefallen wenn einer der Werte beispielsweise Zeilenumbrüche oder '-Zeichen enthält.

Was hier jetzt noch stört sind die nummerierten Wertenamen. Warum die auf zwei festnageln?

Code: Alles auswählen

from importlib import import_module


def main(event, values):
    try:
        module = import_module(f"events/{event}")
    except ImportError:
        pass  # Ignored, like in the original.
    else:
        module.main(*values)
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
knl146
User
Beiträge: 4
Registriert: Dienstag 15. Dezember 2020, 15:22

Dankeschön für den Verbesserungsvorschlag.
Jakob97
User
Beiträge: 1
Registriert: Donnerstag 17. Dezember 2020, 19:12

Hey ich interessiere mich auch an diesem Thema. Ich möchte von meinem Computer(Client) wie knl146, sowie ich dass verstanden habe im json Format x-viele variablen an einen anderen Linux PC (Server) schicken und will dass der dann auch im json Format eine variable zurückschickt .
Ich bin aber noch nicht so gut mit Python und weiß nicht so ganz wie ich jetzt z.b. bei http anfangen kann

Wie weit bist du schon mit deinem Code @knl146 und können mir andere vllt auch bisschen helfen
Antworten