Struktureller Modulaufbau für die Modbus-Kommunikation im Thread

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Hannibal87
User
Beiträge: 8
Registriert: Freitag 17. Januar 2020, 18:03

Guten Tag,

ich möchte gerne Controller über ModusTCP steuern. Die Steuerung der Controller ist Teil eines größeren Projektes und soll daher ausgelagert in einem Modul erfolgen.
Es handelt sich um insgesamt 6 Controller. Von den Controllern sollen im 5 Sekundentakt ca. 10 Messwerte (je 4 Register) ausgelesen und im Minutentakt 1 Steuerbefehl gesendet werden.
So als grobe Schätzung über den anfallenden Datenaustausch.

Da die Ansteuerung der Controller nur ein Teil des Projekt ist, welches nicht durch andere Programmabläufe gestört oder verzögert werden soll, soll die Kommunikation in einem eigenen Thread laufen.

Da ich an dem Projekt nicht alleine arbeite, soll das Modul benutzerfreundlich programmiert werden. Ich habe dabei an einzelne Funktionen für jedes Register gedacht, welche mit einem Doc-String Hinweise liefert, um was für ein Register es sich handelt, wie der Rückgabe Wert zu interpretieren ist oder wie der zuschreibende Wert auszusehen hat.

Ich habe noch keine Erfahrungen mit so großen Projekten und bin mir bei dem Programmaufbau unsicher.

Mein Ansätze sind:
Threading Events
Ich erstelle einen Thread, welche dauerhaft läuft und erstelle einzelne Funktionen, welche nur das jeweilige Event setzt.
Für die einzelnen Funktionen könnte ich dann DocStrings mit Funktionen erstellen und müsste mir auch keine Gedanken machen, über die Zugriffe von verschieden Threads auf die unterschiedlichen Controller.
Das Problem wäre dabei, dass der Thread dauerhaft in der Schleife laufen würde, obwohl er nur alle 5 Sekunden, bzw bei einem Sterungsbefehl laufen müsste.
Zudem werden viele Events benötigt, da ich keine Übergabewerte bei den Events übergeben kann. Vielleicht könnte man das Problem über die Queue oder durch auslesen mehrerer Register gleichzeitig verringern.

Mehrere Threads
Die andere Idee, wäre für jede Aufgabe (das zyklische Auslesen und Steuerbefehle) einen neuen Thread zu starten. Somit würde ich für jeden Zyklus einen Thread starten, welcher einmal alle Daten einsammelt. Und falls eine Steuerbefehl kommt, für diesen einen zusätzliche Thread erstellen, würde dann über einen Lock, das zeitgleiche zugreifen verhindern.
Hierbei sehe ich die hohe Anzahl an Threads problematisch. Ich würde die Threads im Modul erstellen lassen, um den Modulnutzer zu entlasten, jedoch verliert man so schnell den Überblick über die Anzahl der verschiedene Threads. Des Weitern ist es hier schwieriger die Benutzerfreundlichkeit zu gewährleisten. Denn desto mehr Daten aufeinmal ausgelsen werden (führt zu einer kleineren Anzahl an benötigten Threads) desto unübersichtlicher wird es für den Benutzer/ wird der DocString komplizierter.

Ich bin mit beiden Varianten nicht zufrieden.

Habt Ihr Vorschläge, wie man das Modul am besten aufbaut?

Vielen Dank!
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ohne sonst viel zu wissen, kann schon mal mit Sicherheit ausgeschlossen werden, dass mehr threads mehr gut. Maximal einer reicht. Es fehlen mir noch einige Details zum Problem. Woher kommen die Steuer Befehle? Gibt es Anforderungen a die Aktualität der Daten, wenn das Programm darauf zugreift? Worin ist das geschrieben (GUI, Konsole, Web)?
Sirius3
User
Beiträge: 17799
Registriert: Sonntag 21. Oktober 2012, 17:20

Mir wird aus der Beschreibung nicht klar, wie dieses Modul verwendet werden soll. Was soll parallel laufen und warum. Bei gethreadeder Ausführung muß ja die aufrufende Seite das koordinieren, stellt sich also hier die Frage, ob die Kommunikation nicht thread-agnostisch sein sollte.
Hannibal87
User
Beiträge: 8
Registriert: Freitag 17. Januar 2020, 18:03

Das Projekt soll später ein Energiemanagmentsystem sein. Über eine Frontend (webbasierte Oberfläche (React)) soll man verschiedene Geräte einschalten und abschalten können. Die Steuerbefehle laufen auf einem Server zusammen und anhand der Steuerbefehle und aktuellen Messwerte entscheidet der Server, welches Gerät wann läuft. (Bsp. Waschmaschine läuft erst in einer Stunde, da da der Strom günstiger ist).
Der Aufbau gliedert sich also in Web-Frontend -- Server mit Datenbank -- Peripherie. Steuerbefehle kommen vom Backend.
Die Datenaktualität ist nicht zeitkritisch, sollte aber schon möglichst gleichmäßig erfolgen.
Steuerbefehle hingegen sollten zügig ausgeführt werden. Nicht, dass der Bediener sein Licht ausschalten möchte und 5 Sekunden darauf warten muss bis es ausgeht.
Bei dem aktuellen Projekt sind es 6 zu steuernde Geräte, perspektivisch können auch mehr Geräte vllt. so bis 30 vorstellbar sein. Also nicht Laufzeit kritisch, es sollte aber auf eine möglichst geringe Laufzeit geachtet werden.
Das Backend hat also verschiedene Schnittstellen. Datenerfassung, Steuerung, Speicherung der Daten in Datenbank, Kommunikation mit dem Frontend, Abrufen von Strompreisen. Aus diesem Grund hatte ich die Überlegung die Aufgaben in verschieden Threads aufzuteilen.
Die Kommunikationsarten auf dem Backend laufen dabei wie folgt:
Datenerfassung/Steuerung - ModbusTCP und eine Socketverbindung
Kommunikation Frontend - Websocketverbindung
Abrufen von Strompreisen - API

Ich dachte mir die verschiedenen Aufgaben und Kommunikationen mit verschieden Threads zu entkoppeln um sie von einander unabhängig zumachen.
paddie
User
Beiträge: 101
Registriert: Donnerstag 11. Oktober 2018, 18:09

Wieso nimmst du dafür nicht eins der Smarthome-Systeme die es schon gibt (FHEM, openHAB, HomeAssistent usw...) und guckst, was mit denen schon out of the box geht. Da mußt du dann "nur noch" die fehlenden Funktionen selbst entwickeln.

Falls du bei Python bleiben möchtest, wäre HomeAssistent einen Blick wert.

Ansonsten wäre (sofern dir die etwas "altbackene" Optik gefällt ;-)) FHEM ein Blick wert. Das deutsche Forum ist sehr aktiv. Es werden SEHR viele unterschiedliche Systeme unterstützt und auch mehr oder weniger regelmässig erweitert/gewartet. Für FHEM kann über eine kleine Erweiterung auch auch Module in Python schreiben. Ansonsten wird da Perl benutzt.
Hannibal87
User
Beiträge: 8
Registriert: Freitag 17. Januar 2020, 18:03

Vielen Dank für die Hinweise.
Wir programmieren das Programm nicht nur um ein Energiemanagement zuhaben, sondern um unsere Programmierfähigkeiten zu verbessern und zu lernen, größere Projekte möglichst professionell zu erstellen. Aus diesem Grund wollen wir das Programm selber erstellen.
Sirius3
User
Beiträge: 17799
Registriert: Sonntag 21. Oktober 2012, 17:20

Dann läuft das letztlich auf einen der vielen Messagequeuing-Systeme hinaus. Damit hast Du eine starke Entkopplung Deiner Geräte vom Web-Server.
Hannibal87
User
Beiträge: 8
Registriert: Freitag 17. Januar 2020, 18:03

Also der Austausch er Daten zwischen den Threads läuft ja eh über Queues. Bei einer größeren Anzahl an Teilnehmern vllt ein Message Queuing-Systemezu verwenden wäre eine Überlegung.
Aber dann würde ich das Programm auf einige (möglichst wenige) Threads aufteilen und diese über ein Message Queuing-Systeme kommunizieren lassen?
Antworten