Du bist nicht angemeldet.

Werbeanzeige

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 712

Wohnort: Würzburg

Beruf: Student / Junior Software Engineer

  • Private Nachricht senden

1

08.02.2018, 01:22

State sichern bis er wieder gesetzt werden kann

Hi,
aktuell verdiene ich mein Geld, indem ich eine Steuerung in Python 3 für ein Gerät entwickle, dessen Protokoll ich z.T. reverse engineeren musste (die interne Dokumentation ist Schrott.). Kommuniziert wird mit dem Gerät über eine (formell halb-duplex) TCP-Verbindung. In der Umgebung ist leider mit gelegentlichen Verbindungsabbrüchen und Timeouts zu rechnen.

Da durch das Nichtausführens eines Befehls/Statechange erhebliche Schäden am Inventar folgen können (beispielsweise, wenn das Gerät über mehrere Stunden mit falschen Parametern läuft), muss der State möglichst schnell nachgebessert werden.

Meine aktuelle (naive) Lösung sieht so aus, dass ich mir den letzten Befehl stets merke und ggf. nochmals ausführen (z.B. wenn eine Timeout exception etc. kam. Das diese Lösung nicht gerade ausgereift ist, möchte ich da nachbessern.

Die Frage / TL;DR:
Wie würde man solche "Statedifferenzen" am besten Speichern bzw. mit Klassen modellieren?
Die einfachste Lösung, die mir dafür einfällt, ist eine Kopie von allen Parametern anzufertigen und dann diese mit den Werten vom Gerät auf Übereinstimmung überprüfen.

LG Julien
Dir hat dieser Post gefallen? Dann schau doch bei mir auf Twitter vorbei!

BlueCobold

Community-Fossil

Beiträge: 10 703

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

08.02.2018, 06:31

Meine aktuelle (naive) Lösung sieht so aus, dass ich mir den letzten Befehl stets merke und ggf. nochmals ausführen (z.B. wenn eine Timeout exception etc. kam. Das diese Lösung nicht gerade ausgereift ist, möchte ich da nachbessern.
Ich verstehe nicht ganz, warum du an diesem Vorgehen etwas ändern willst. Ein Befehl sollte irgendwie ein Ack zurück senden. Bekommst du das Ack, ist alles gut. Wenn nicht, sendest du's nochmal. Falls du Angst vor Doppel-Ausführung hast, gib jedem Befehl eine Unique ID oder sowas. Stichwort Quality of Service - Exactly once. Am besten vielleicht auch gar nicht selbst implementieren, sondern ein Protokoll verwenden, was das kann. Zum Beispiel MQTT (Achtung: Nicht jede MQTT Implementierung bietet auch tatsächlich QoS Level 2).
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 712

Wohnort: Würzburg

Beruf: Student / Junior Software Engineer

  • Private Nachricht senden

3

09.02.2018, 00:40

Ich kann jetzt leider nicht auf ein anderes Protokoll umsteigen, da das Projekt sprichwörtlich gestern hätte fertig sein müssen (#StartUp) zum testen.


Ich verstehe nicht ganz, warum du an diesem Vorgehen etwas ändern willst.


Die Befehle können sich widersprechen. Einfaches Beispiel:
>Setze gewünschte Hb-Träger-Temperatur 1 von 6° auf 4°< dann nach 5 min oder so, wird ein weiteres Kommando geschickt:
>Setze gewünschte Ery-Träger-Temperatur 2 von -40° auf -80°<.

Würde der erste Befehl immer wieder einen Timeout generieren, bis der zweite Befehl versendet wird, dann würde der erste im Zweifelsfall nie ausgeführt werden, was u.a. Proben etc. unwiederbringlich zerstören könnte.

--- Out Of Flow
Habe gerade das erste Mal etwas vom dem "Memorandum"-Pattern gehört, einer der etwas weniger bekannten GoF-Pattern.
Eine modifizierte Version würde es wohl tun.

Werde meine (abstrahierte) Lösung hier posten, damit die Nachwelt was davon hat, wenn ich fertig bin. :thumbup:
Dir hat dieser Post gefallen? Dann schau doch bei mir auf Twitter vorbei!

BlueCobold

Community-Fossil

Beiträge: 10 703

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

09.02.2018, 06:27

Dann verstehe ich deinen Use-Case wohl falsch. Ich dachte du willst, dass Befehle in jedem Fall ausgeführt werden. Scheint jetzt nicht so zu sein. Oder doch? Wie gesagt, "exactly once" klang für mich nach der gewünschten Lösung, damit jeder Befehl auch wirklich ausgeführt wird. MQTT bietet das. Wenn die Befehle unabhängig voneinander sind, sollten sie über verschiedene Kanäle parallel versendet werden. Auch das kann MQTT. Aber du scheinst ja bereits eine Lösung zu haben.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

David Scherfgen

Administrator

Beiträge: 10 089

Wohnort: Bonn

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

5

09.02.2018, 17:23

Du könntest dir einfach den aktuellen gewünschten Status merken und ständig (z. B. jede Minute) beim Gerät nachfragen, was sein aktueller Status ist, und dann ggf. Kommandos zum Ändern senden.

Chromanoid

Alter Hase

Beiträge: 1 399

Wohnort: Lüneburg

  • Private Nachricht senden

6

09.02.2018, 17:55

Du könntest das ganze sehr schön über persistente Queues abbilden. Jedes Gerät das du ansprechen kannst, hat eine Queue. In die Queue werden Befehle geschrieben, die das Gerät ausführen soll. Für jedes Gerät holst Du Dir den auszuführenden Befehl und bestätigst das Löschen aus der Queue erst, wenn die Ausführung des Befehls erfolgreich war. An den Befehlen speicherst Du noch Sachen wie Time-to-live o.Ä. Wenn ein Befehl zu lange nicht verarbeitet werden kann, kannst Du dann die gesamte Queue leeren und Alarm schlagen oder den Befehl in eine Fehler-Queue o.Ä. schmeißen, die dann separat verarbeitet werden kann. Wichtig dabei wäre, dass in der Queue für ein Gerät nur die Befehle landen, die direkt ausgeführt werden sollen, alles andere würde es wesentlich verkomplizieren. Wenn Du Befehle für die Zukunft an das Gerät nicht direkt absetzen kannst, musst Du die separat speichern und dann erst wenn es soweit ist, die Befehle in die Gerät-Queue packen.

Ein Problem an Deinem gesamten Problem ist, dass Du nie ganz sicher sein kannst, ob Du einen Befehl wirklich ausgeführt hast, wenn Dein Programm mal abstürzt. Das ginge nur, wenn die Geräte verteilte Transaktionen unterstützen oder Du zumindest abfragen kannst, was für Befehle beim Gerät angekommen sind.

BlueCobold

Community-Fossil

Beiträge: 10 703

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

09.02.2018, 17:56

Du könntest das ganze sehr schön über persistente Queues abbilden.
Willkommen bei (z.B.) MQTT ;)
(Alternativen/Implementierungen: RabbitMQ, Kafka, JMS)
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Chromanoid

Alter Hase

Beiträge: 1 399

Wohnort: Lüneburg

  • Private Nachricht senden

8

09.02.2018, 18:01

@BlueCobold Ja, genau ich fand Deine Idee eigentlich ziemlich gut. Da die Geräte das ja nicht direkt unterstützen, muss das alles in der Anwendung laufen. Und das wollte ich mit meinem Post ausdrücken :)
@Julien Damit Du nicht eine Infrastruktur für RabbitMQ oder so aufbauen musst, könntest Du das ganze auch in deine Anwendung einbetten. Ich habe eben mal kurz gegooglet und das hier gefunden: https://pypi.python.org/pypi/queuelib edit: vergiss letztere Bibliothek, die hat kein peek bei den Queues, so dass Du nicht lesen kannst ohne das Zeug aus der Queue zu nehmen. Die hier scheint vielversprechender: https://pypi.python.org/pypi/python_persistent_queue/1.3.0

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Chromanoid« (09.02.2018, 18:10)


Werbeanzeige