Hallo,
ich habe mir im Frühjahr ein Modul zusammengeschustert um eine persönliche Anforderung umzusetzen. Das ganze ist schlecht programmiert und nutzt z.B. Threads und andere böse Sachen. Ich möchte es jetzt mal hier posten aus 2 Gründen:
- das Ding läuft bei mir seit Monaten und erfüllt seinen Zweck - trotz schlechter Programmierung
- mit Aufwand ist da vll. mehr draus zu machen und ich hoffe jemand findet es interessant.
Worum geht es? Ich wollte mein TV und Musiksystem im Haus in fhem mit steuern. Was für ein "System" habe ich? Ich habe 2 Linux-PCs auf denen ein Video Disk Recorder (VDR) läuft. das nutze ich zum TV schauen (ich habe auch einen VDR-Server, der ist jetzt hier nicht wichtig). Auf diesen zwei Linux-PCs ist neben dem VDR auch noch ein Audiosystem installiert (ein Pulseaudioclient). Ich nutze die PCs also sozusagen in 2 Betriebsarten. TV-Modus und Musik-Modus. Die PCs werden über eine FS20-Steckdose betrieen lassen sich damit also komplett vom Netz trennen und fahren bei Einschalten der Steckdose automatisch hoch. Außerdem ist der Fernseher an einer FS20-Steckdose. Im Musikmodus braucht man den Fernseher ja nicht kann ihn also ausschalten, wenn der VDR nicht läuft.
Weiterhin habe ich 3 Mini-Linux PCs (raspberry, Dockstar, OpenWRT-Router) auf denen ich ebenfalls einen Pulseaudio-Client laufen habe und an denen Boxen angeschlossen sind. Also reine Audiosysteme. Dort lassen sich auch die Rechner selber über FS20 Dosen als auch teilweise die Boxen über eigene FS20 Dosen schalten.
Was wollte ich erreichen: Der Anwender sagt nur noch was er an oder aus haben will: Z.B. Fernseh an. Ok jetzt lieber Musik an, und bitte auch in Raum x y. FHEM soll dann basierend auf dem Ist-zustand agieren
Beispiel: Musik im Wohnzimmer läuft. Nun will der Anwender Fernseh schauen. Der PC ist also schon an. Das erkennt fhem und stoppt einfach die VDR Applikation und startet den Pulseaudioclient, außerdem wird der Fernseher über FS20 abgeschaltet.
Implementiert habe ich das also als Workflows, dazu habe ich das CPAN Workflow Modul genutzt. Außerdem habe ich noch CPAN Graphenmodule genutzt um den Weg durch einen Baum zu finden zu einem Sollzustand ("desire")
Es gibt ein zentrales File 96_Workflow.pm wo die normalen benötigten FHEM Routinen Init, Define, Set usw. definiert sind. Außerdem ist dort der Hautpzweig für die Threads. Jeder per "define" erstellte Workflow bekommt einen eigenen Thread und per IPC holt sich fhem regelmaessig die Informationen daraus bzw. setzt neue Sollzustände.
Für jeden Workflowtypen der unterstützt wird, wird im Ordner workflow (unterhalb FHEM) ein eigenes .pm File mit dem Workflownamen abgelegt.
Jedes dieser .pm-Files muss bestimmte Routinen haben:
GetInfos -> liefert an
96_workflow.pm zurück, welche Parameter der Workflow unterstützt und erfordert
BUILD -> zur Konfigurations des Workflows (das kommt aus dem Workflow CPAN Modul)
set_desired -> zum setzen des gewünschten Soll-Zustandes des Workflows
process_automation -> Der Workflow wird angetriggert, um den nächsten Schritt zu durchlaufen. Aus den Eingangsgrößen "Desired" und "Ist-Zustand" und durch erfüllte oder nicht erfüllte "Conditions" wird ermittelt, ob ein Zustandswechsel durch den Workflow stattfinden muss (eine Action) oder nicht. Dann wird es durchgeführt.
jeder Workflow wird weiterhin durch mehrere XML-Dateien konfiguriert (dies ist nicht von mir, denn so funktioniert das CPAN Modul). in diesen werden die notwendigen Conditions, Actions und der Workflow sozusagen als Graph definiert incl. der erlaubten Zustandsübergänge. Darüber werden dann wiederum Helper-pm-Files eingebunden die den Code enthalten, um Conditions zu prüfen und um Actions auszuführen.
Soweit erstmal Schritt 1. Anbei ein ZIP File mit dem Modul und mit 3 Beispielen (genau so verwende ich sie). Wie gesagt es gibt noch ne Menge Nachteile, bevor jemand außer mir das sinnvoll nutzen kann
- Einige spezielle Sachen sind hartkodiert, weil ich nicht wusste, wie ich sie generisch machen soll oder dazu am Anfang "keine Lust" hatte weil ich es erstmal grundsätzlich testen wolle, und als es dann lief, hab ich es so gelassen
- das ganze ist immens ressourcenverbrauchend und total ineffizient entwickelt!
- 1 Thread pro Workflow
- schlecht dokumentiert.
Das erstmal für heute - ich versuche in Kürze meine beispiele noch besser zu dokumentieren. In den Beispielen sind Dinge drin, die so wohl nur für mich Sinn machen. Z.B. teste ich bei einer Condition "shellable" ob eine Telnet-Verbindung zu Port 23 aufgebaut werden kann und dort eine Shell Befehle ausführt - natürlich total unsicher - aber bei mir im Netz egal.
Würde mich freuen wenn sich jemand dafür interessiert, vll. mal reinschaut und den ein oder anderen Kommentar abgibt.