Daten zwischenspeichern

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.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Ok, ich bin jetzt endlich dazu gekommen das Programm zu testen, also deine Modifikation @Sirius3

Leider wird keine Verbindung aufgebaut, ich glaube ich muss auch json als Bib importieren oder?

Muss ich dann Clientseitig ebenfalls mit json arbeiten, also ich weiß jetzt natürlich nicht, ob das mit JS kompatibel ist? Vielleicht könntest du noch mal drüber schauen, Danke!

Sirius3 hat geschrieben: Sonntag 26. Juni 2022, 22:43
Typischerweise schickt man über Websockets JSON-kodierte Wörterbücher. Da kann man auf strukturierte Weise alle möglichen Daten kodieren, z.B: {"relais1": "off", "temp1": "on"}

Code: Alles auswählen

class Echo(WebSocket):

    def __init__(self, client, server, sock, address):
        super().__init__(server, sock, address)
        self.modbus = client
        self.functions = {
            "relais1": partial(self.simple_switch, COILBASE + 16),
            "relais2": partial(self.simple_switch, COILBASE + 1),
            "relais3": partial(self.simple_switch, COILBASE + 2),
            "temperatur1": partial(self.read_temperature, 0),
            "temperatur2": partial(self.read_temperature, 3),
            "heizen1": partial(self.heating, 525),
            "heizen2": partial(self.heating, 526),
            "heatread": partial(self.simple_read, 524),
            "systemp": self.systemp
        }

    def simple_switch(self, address, value):
        """ value can be one of "on", "off" or "get" """
        if value in ["on", "off"]:
            rq = self.modbus.write_coil(address, value == "on", unit=UNIT)
            time.sleep(0.1)
        elif value != 'get':
            raise ValueError(value)
        # Relaisregister lesen
        rp = self.modbus.read_coils(address, unit=UNIT)
        return "on" if rp.bits[0] else "off"

    def simple_read(self, address, value):
        if value != 'get':
            raise ValueError(value)
        # Relaisregister lesen
        rp = self.modbus.read_coils(address, unit=UNIT)
        return "on" if rp.bits[0] else "off"

    def read_temperature(self, address, value):
        if value != "get":
            raise ValueError(value)
        response = self.modbus.read_holding_registers(0x00, 4, unit=1)
        return response.registers[address]

    def heating(self, address, value):
        # Heizen an | Modul an dem der Heizdraht geschaltet wird
        if value in ["on", "off"]:
            rq = self.modbus.write_coil(524, value == "on", unit=UNIT)
            time.sleep(0.01)
            rq = self.modbus.write_coil(address, value == "on", unit=UNIT)
            time.sleep(0.1)
        elif value != 'get':
            raise ValueError(value)
        rp = self.modbus.read_coils(address, unit=UNIT)
        return "on" if rp.bits[0] else "off"

    def systemp(self, value):
        result = subprocess.run(["vcgencmd", "measure_temp"], stdout=subprocess.PIPE)
        temperature = result.stdout.partition("temp=")[-1].partition("'C\n")[0]
        return temperature

    def handleMessage(self):
        new_state = {}
        commands = json.loads(self.data)
        for key, value in commands.items():
            function = self.functions[key]
            new_state[key] = function(value)
        self.sendMessage(json.dumps(new_stat))
Entsprechend einfach ist es, den Code um weitere Schalter zu erweitern.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Ok, ich habe noch mal try: und except Exception rein gebaut und bekomme folgende Fehlermeldung:

Code: Alles auswählen

Connected
ERROR:__main__:handle message
Traceback (most recent call last):
  File "/home/fx/python-skripte/websock_neu6.py", line 83, in handleMessage
    commands = json.loads(self.data)
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.9/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Disconnected
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Muss ich dann Clientseitig ebenfalls mit json arbeiten, also ich weiß jetzt natürlich nicht, ob das mit JS kompatibel ist? Vielleicht könntest du noch mal drüber schauen, Danke!
Ich meinte nicht kompatibel, sondern der Datentyp der gesendet wird, sollte dieser dann ebenfalls json sein?

Das würde mit der
encode
Errormeldung zusammen passen.
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Könnte hier bitte kurz jemand drüber schauen?

Code: Alles auswählen

def handleMessage(self):
        new_state = {}
        [b]commands = json.loads(self.data)[/b]
        for key, value in commands.items():
            function = self.functions[key]
            new_state[key] = function(value)
        self.sendMessage(json.dumps(new_stat))
Ich glaube, dass es an dem Datentyp liegt, der JS Client sendet aktuell nur strings und deswegen bekomme ich hier im Server (Python) Part einen Fehler, siehe vorheriger Post. Wie kann ich mit jason strings empfangen? [ich will vorerst nicht den ganzen client Part json tauglich machen, weil ich nicht weiß, wo und wie ich da anfangen müsste]
Benutzeravatar
__blackjack__
User
Beiträge: 13122
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Soulpilot: Was heisst „sendet […] strings“? Die Nachrichten die ausgetauscht werden sind Bytes. Wenn die Nachrichten irgendwie strukturiert sein sollen, muss man das selbst machen. Ein übliches Format ist JSON, weil das etwas ist was Browser (de)serialisieren können und es für so ziemlich jede gängige Sprache mindestens externe Bibliotheken gibt, mit denen man JSON (de)serialisieren kann, falls das nicht schon Bestandteil der Standardbibliothek der Sprache ist. Was es bei Python ist.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

__blackjack__ hat geschrieben: Samstag 30. Juli 2022, 16:57 @Soulpilot: Was heisst „sendet […] strings“? Die Nachrichten die ausgetauscht werden sind Bytes. Wenn die Nachrichten irgendwie strukturiert sein sollen, muss man das selbst machen. Ein übliches Format ist JSON, weil das etwas ist was Browser (de)serialisieren können und es für so ziemlich jede gängige Sprache mindestens externe Bibliotheken gibt, mit denen man JSON (de)serialisieren kann, falls das nicht schon Bestandteil der Standardbibliothek der Sprache ist. Was es bei Python ist.
Was das heißt? Das heißt das der Websocket Client einen String an den Websocket Server sendet. Deine Antwort verstehe ich nicht, sorry.

Was heißt "weil das etwas ist was Browser (de)serialisieren können"? Hier geht es nicht um den Browser, sondern um eine Client/Server Anwendung, bei der Daten ausgetauscht werden.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@Soulpilot: Über Sockets werden Bytes ausgetauscht, die dann wieder zu (Python-) Datenstrukturen konvertiert werden. Das können z.B. Integer, Floats oder auch Abfolgen von Unicode-Codepoints sein (vulgo Strings, in Python 3). Wenn es nicht um den Browser geht, was fungiert bei dir dann als Client?
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

kbr hat geschrieben: Samstag 30. Juli 2022, 18:59 @Soulpilot: Über Sockets werden Bytes ausgetauscht, die dann wieder zu (Python-) Datenstrukturen konvertiert werden. Das können z.B. Integer, Floats oder auch Abfolgen von Unicode-Codepoints sein (vulgo Strings, in Python 3). Wenn es nicht um den Browser geht, was fungiert bei dir dann als Client?
Ok, ja es ist eine Web API, das schon aber mir ging es jetzt speziell darum, wie ich vom client, der in JS geschrieben ist, korrekt die Daten an den Python Server übermittle, so das die Daten verarbeitet werden können. Also, sirius3 hat mir das Programm quasi entwickelt siehe Seite 1 des Threads, dort ist auch der JS Client zu finden.

Also JSON ist föllig neu für mich aber scheinbar der Königsweg bei websocket und generell webaplications.

Also meine Frage noch mal konkret, wenn sich mal einer bitte den code kurz anschauen könnte unter "handelMessage"! Was muss ich im JS Client schreiben (siehe Thread Seite 1), in konkreter JSON Syntax, damit der Server etwas damit anfangen kann, eine Zeile Syntax als Beispiel würde mir vielleicht schon reichen um weiter machen zu können: zB.: websock.send(JSON.stringify('auslesen, xyz'));

Also für mich gerade total der Braincrash mich da rein zu denken... im py Server Programm wird das, was vom Client kommt, über command dann an die Funktion weiter gegeben bzw. die entsprechende Funktion aufgerufen.

Ich habe wenig Ahnung davon, will das Projekt dennoch weiter voranbringen und auch was lernen, auch wenn ich auf der langen Leitung sitzen (sorry dafür)!
Benutzeravatar
noisefloor
User
Beiträge: 3857
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

Beispiel für Websocket und JSON: https://developer.mozilla.org/en-US/doc ... plications

Das gut an JSON ist, dass es ziemlich simpel ist und das sich die Datenstrukturen von JSON und Python ziemlich gut aufeinander abbilden lassen.

Und ich möchte nochmal auf
Der Server ist so gemacht, dass er nur auf Client Anfragen reagiert,
zurückkommen. Wenn das alles über einen normalen Request - Response Zyklus läuft, dann kann man das über Websockets machen - ist aber IMHO unnötig kompliziert / komplett. Clientseitig kann man stattdessen AJAX oder die neuere fetch-API nehmen und serverseitig eines der gängigen Webframeworks (Django, Flask, Bottle, ggf. FastAPI etc.). Wann Websockets wirklich sinnvoll sind wurde ja schon weiter oben gesagt.

Gruß, noisefloor
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

noisefloor hat geschrieben: Samstag 30. Juli 2022, 19:59 Hallo,

Beispiel für Websocket und JSON: https://developer.mozilla.org/en-US/doc ... plications

Das gut an JSON ist, dass es ziemlich simpel ist und das sich die Datenstrukturen von JSON und Python ziemlich gut aufeinander abbilden lassen.

Und ich möchte nochmal auf
Der Server ist so gemacht, dass er nur auf Client Anfragen reagiert,
zurückkommen. Wenn das alles über einen normalen Request - Response Zyklus läuft, dann kann man das über Websockets machen - ist aber IMHO unnötig kompliziert / komplett. Clientseitig kann man stattdessen AJAX oder die neuere fetch-API nehmen und serverseitig eines der gängigen Webframeworks (Django, Flask, Bottle, ggf. FastAPI etc.). Wann Websockets wirklich sinnvoll sind wurde ja schon weiter oben gesagt.

Gruß, noisefloor
Hi, das hilft schon ein kleines bisschen weiter, vielen Dank!

Ich möchte aber auch darauf hinweisen, dass ich pymodbus verwende und deswegen diese "verrückte" Konstellation enstanden ist, ich hatte mich vor Monaten hier beraten lassen und dann sagte man mir, wenn ich sowohl python als auch js haben will und diese miteinander kommunizieren sollen, dann sollte ich mir websocket anschauen. Bitte nicht falls verstehen, ist auch keine Kritik, ich finde das Thema faszinierend auch wenn kompliziert und meine Lernkurve sehr niedrig ist... Ich schaue mir Bottle oder FastAPI vielleicht mal an, wenn das hier mal rudimentär läuft... ist ja dann nicht fertig nur weil es funktioniert, sondern der Prozess ist das entscheidende ;-)

Ich glaube das hat bei mir nicht funktionier exampleSocket.send(JSON.stringify(msg));

Ich habe halt diese Fehlermeldung 4 Posts weiter oben bekommen... könntest du dir diese vielleicht mal anschauen bitte?

Code: Alles auswählen

Connected
ERROR:__main__:handle message
Traceback (most recent call last):
  File "/home/fx/python-skripte/websock_neu6.py", line 83, in handleMessage
    commands = json.loads(self.data)
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.9/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Disconnected
Normalerweise steuert der Server....
oder so ähnlich ja ich erinne mich auch daran... Kann man zeitlich bzw. periodische Funktionsausführung eigentlich in Python mittels Threading machen, ist Threading ähnlich wie intervall in JS?
Benutzeravatar
noisefloor
User
Beiträge: 3857
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Ich schaue mir Bottle oder FastAPI vielleicht mal an, wenn das hier mal rudimentär läuft...
Würde ich dann nicht. Ob Websocket oder "normaler" Request - Response Zyklus ist eine grundlegend Designentscheidung. Das schreibt nicht einfach mal so um. Wenn du dich jetzt auf Websockets festgelegt hast - ok. Aber, wie gesagt, ist ein (großer) Vorteil von Websockets, dass der Server aktiv Daten an den Client pushen kann und eben nicht auf eine Anfrage des Clients warten muss.
Kann man zeitlich bzw. periodische Funktionsausführung eigentlich in Python mittels Threading machen, ist Threading ähnlich wie intervall in JS?
Nein und nein. Threading fällt in den Bereich "nebenläufige Programmierung". Also ja, du kannst ein Funktion in einen Thread auslagern und diesen mittels `sleep` immer X Sekunden pausieren . Bei JavaScript funktioniert das anders, weil das Konzept anders ist.

Periodische Ausführung geht natürlich in Python auch, über verschiedene Weg. Welcher der beste ist hängt davon ab, a) was man vorhat und b) was noch so gleichzeitig läuft. Startest du am besten einen neuen Thread zu, hier geht es ja um was anders.

Den Fehler bekommst du AFAIR, wenn `json.loads` einen leeren String bzw. nichts übergeben bekommt. Sprich bei dir ist dann wohl `self.data` leer.

Gruß, noisefloor
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Hi und vielen Dank!
noisefloor hat geschrieben: Samstag 30. Juli 2022, 20:49 Hallo,
Ich schaue mir Bottle oder FastAPI vielleicht mal an, wenn das hier mal rudimentär läuft...
Würde ich dann nicht. Ob Websocket oder "normaler" Request - Response Zyklus ist eine grundlegend Designentscheidung. Das schreibt nicht einfach mal so um. Wenn du dich jetzt auf Websockets festgelegt hast - ok. Aber, wie gesagt, ist ein (großer) Vorteil von Websockets, dass der Server aktiv Daten an den Client pushen kann und eben nicht auf eine Anfrage des Clients warten muss.
Ah, ok gut.
noisefloor hat geschrieben: Samstag 30. Juli 2022, 20:49
Kann man zeitlich bzw. periodische Funktionsausführung eigentlich in Python mittels Threading machen, ist Threading ähnlich wie intervall in JS?
Nein und nein. Threading fällt in den Bereich "nebenläufige Programmierung". Also ja, du kannst ein Funktion in einen Thread auslagern und diesen mittels `sleep` immer X Sekunden pausieren . Bei JavaScript funktioniert das anders, weil das Konzept anders ist.

Periodische Ausführung geht natürlich in Python auch, über verschiedene Weg. Welcher der beste ist hängt davon ab, a) was man vorhat und b) was noch so gleichzeitig läuft. Startest du am besten einen neuen Thread zu, hier geht es ja um was anders.
Multithreading kann man damit auch machen, habe vor längerem mal eine Video darüber gesehen... bei Stackoverlflow wurde immer threading für ein intervall empfohlen, hatte ich mal gegooglet... aber ok es ist echt schwer manchmal die richtigen Infos zu rechachieren, vorallem wenn man ein kompliziertes Projekt vorhat und keine Ahnung von den Grundlagen... da hat mir die Vorlesung "Programmieren 1 für Ingeneure" echt nen schei* gebracht und der zweite Teil war auch nicht viel aufschlussreicher, komme mir so dermaßen dumm vor hier...
noisefloor hat geschrieben: Samstag 30. Juli 2022, 20:49 Den Fehler bekommst du AFAIR, wenn `json.loads` einen leeren String bzw. nichts übergeben bekommt. Sprich bei dir ist dann wohl `self.data` leer.
Gruß, noisefloor
Ok danke danke!!! Gut, wie kann ich es machen, das er keinen Fehler wirft sondern das ignoriert? =)

Eigentlich sollte der String nicht leer sein:

websock.send(JSON.stringify{relaise1: 'on'});
Soulpilot
User
Beiträge: 63
Registriert: Sonntag 24. April 2022, 12:19

Seltsam, jetzt wirft er keinen Fehler und es passiert nichts, also auf der webseite bekomme ich nur disconnected ausgegeben...

websock.send(JSON.stringify{ relais1: 'on' });

wie kann ich das debuggen oder herausfinden warum nichts passiert?
Antworten