Rollladensteuerung: Alternativen zu DOIF

Begonnen von spi3845, 27 März 2017, 13:28:59

Vorheriges Thema - Nächstes Thema

Beta-User

Hallo zusammen,

habe derweil auch meine Gedanken in Code gegossen, scheint zu funktionieren, ist aber noch nicht umfassen getestet.

Achtung: Bitte die notifys prüfen.
Es gibt jetzt 2 Stück:
Eins für die Basisfunktionalität, die auf das stop wartet und sich jetzt nur noch einmal selbst unnötig triggert.
Das Andere fängt Set-Befehle ab.

Code ist wieder auf github, wobei ich den Dev-tree geschlossen habe, es ist alles also wieder in Master zu finden.

Über Rückmeldungen (und ggf. Testergebnisse) würde ich mich freuen. Wenn es alles zufriedenstellend läuft, mach' ich vielleicht auch eine schöne Doku ;).

@Hugo:  nochmals Danke für dieses sehr anspruchsvolle Beispiel, Deine neuen Kommentare schaue ich mir vermutlich über die Feiertage mal an, jetzt schnaufe ich erst mal durch, bevor es an's Erstellen einer eventuellen Timer-Funktionalität geht.

@spi: Interessanter Ansatz, die weekdaytimer-Funktionalität zu generalisieren!

Gruß, Beta-User
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

Beta-User

Noch ein update nach etwas testen und weiterüberlegen:

Auch das Unterbrechen von Fahrten scheint jetzt gut zu funktionieren, ohne dass sich das ununterbrochen selbst triggert.

Code liegt wieder im dev-tree auf Github.

Wesentlicher Unterschied: Es gibt jetzt nur noch ein notify! Die Idee dahinter ist, das tatsächlich in Richtung eines Moduls auszubauen. Vorläufiger Name: HM-Shuttertools?

So ganz habe ich allerdings die Dokumente zur Modulentwicklung noch nicht verstanden, wenn da also jemand Hilfestellung leisten möchte: GERNE!!!

Was soll das Modul können:
1. (Version 0.1) Die Fenster-auf/gekippt-Lüftungs-/Aussperrschutzfunktion durch Überwachung aller HM-Rolladenaktoren übernehmen
2. (Später, Version 0.5): Zeitgrenzen + Bedingung (optional) für Öffnen und Schließen (je Rolladen individuell per Attribute einstellbar)
3. (evtl., Version 0.9): Beschattungsteuerung über Attribute je Rolladen

Da die sehr speziellen Readings der HM-Devices ausgewertet werden, ist die Einsatzmöglichkeit - jedenfalls was die Rolladensteuerung angeht - bis auf weiteres auf diese Geräteart beschränkt.

Das HM-Shuttertools-Device soll dabei dazu dienen, die zu überwachenden Rolladen und Tür/Fensterkontakte miteinander bekannt zu machen und die notwendigen Attribute zu generieren, dafür default-Werte vorzuhalten und dann bei Erweiterung der Funktionalität auf einfachem Weg die Ersteinrichtung erleichtern.

Die weitere Einstellung für die einzelnen Rolläden könnte man dann z.B. per Readingsgroup recht komfortabel vornehmen.

Zu Version 0.1 (Aussperrschutz etc.) dürfte eigentlich mit Unterstützung eines erfahrenen Modulentwicklers nicht mehr so viel fehlen?

Was Version 0.5 angeht, soll im Prinzip einmal am Tag (bzw. bei Änderung der Attribute) eine Berechnung der Werte erfolgen, wobei es eigentlich möglich sein sollte, auch perl-code (sunrise, sunset) als Attribut zu hinterlegen und $we zu verwenden (zwei "Zeitzonen"); schön wäre es, wenn man das optional über eine "Gruppen"zugehörigkeit regeln könnte (und darüber ggf. auch ausschalten, also "Manuell"=keine Automatik, "SingleMode"=die beim Rolladen eingstellten Werte, "Gruppe1" (-3)=Gruppenwerte nehmen). Zum frühesten Schaltzeitpunkt wäre dann eine optionale Bedingung zu prüfen (hell genug?) und ggf. ein notify zu definieren, das das dann bis zum spätesten Zeitpunkt überwacht usw..

Zu Beschattung: noch keine konkrete Vorstellung, das darf wachsen...

Über Rückmeldung (und Hilfe beim "Modulieren") würde ich mich freuen!

Gruß, Beta-User
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

Cluni

Hallo Zusammen,

ihr scheint ja ganz schön Gas zu geben hier!  :o
Ich war bis heute im Urlaub und schaue erst jetzt wieder richtig rein. Ich muss gestehen, dass ich in euer Projekt noch nicht hineingeschaut habe. Die Zeitsteuerung ist bei mir während des Urlaubs gut gelaufen. Ich habe bis jetzt aber nur die Zeitsteuerung fertig. Abschattung und die Automatik beim Öffnen eines Fensters wollte ich aber auch noch einbauen.
Bis jetzt habe ich meine Rolllanden mit einigen User-Attributen versehen. Für jeden Rollladen wird nach Aufruf der Perl-Routine "Auto_Rol_calc_at" in meiner 99_myUtils.pm mehrere ats angelegt. Für 00:05Uhr wird auf jeden Fall ein tägliches at angelegt, welches diese Perl-Routine für diesen Rollladen ausführt und die aktuellen ats für Öffnen und Schließen anlegt. Dabei werden die Vorgaben direkt aus den User-Attributen des Rollladen gelesen und verwendet. Ist dort kein automatisches Öffnen und/oder Schließen ausgewählt, dann wird auch kein at dafür erzeugt.

Eventuell könnt ihr den Code ja für das Modul brauchen - Ich kann die aktuelle Routine (da wird sich aber bestimmt noch was dran ändern) gerne nochmal posten, wenn ihr Interesse habt!?

Für die Abschattung habe ich mir überlegt, dass man dafür entweder ein doif oder irgendwie ein Notify an Twilight oder ähnliches heften könnte (welches dann auch über die Perl-Routine automatisch generiert werden könnte). Damit könnte man dann die Abschaltung triggern...

Gruß, Bernd

Cluni

Hier mal ein Screenshot-Ausschnitt der erzeugten Timer...

spi3845

Zitat von: Beta-User am 15 April 2017, 14:47:27
Wesentlicher Unterschied: Es gibt jetzt nur noch ein notify! Die Idee dahinter ist, das tatsächlich in Richtung eines Moduls auszubauen. Vorläufiger Name: HM-Shuttertools?
Wow, hätte nicht gedacht, dass sich das so rasant entwickelt! Perfekt!

Wenn ich das recht sehe, gibt es einige in diesem Thread, die sich an Rollladensteuerungen versuchen oder versucht haben. Können wir unsere gemeinsamen Ansätze irgendwie organisieren? Hinsichtlich eines Moduls wäre die Entwicklung neuer Funktionen, Doku, Test, Support dann einfacher.

Persönlich ist mein Problem aktuell, dass ich versuche, mehrere Code-Versionen, darunter meine eigene und die von Beta-User, zu testen und abzubilden und gleichzeitig die von anderen (z.B. hugomckinley) zu verstehen. Das kostet nicht nur viel Zeit, es ist auch extrem schwierig, die Ideen und Ansätze dahinter zu greifen. Einiges erschließt sich mir auch nicht auf den ersten oder zweiten Blick... 8)

Das Codieren einer Rollladensteuerung ist das eine, das andere ist der grundlegende Ablauf dahinter im Sinne eines Zustandsautomaten, also welcher neue Zustand tritt ein, wenn ein Rollladen ganz offen ist und Ereignis x oder y tritt ein. Das ist erst einmal Aufwand für die Erzeugung der Darstellung, ich glaube aber, dass es für ein Modul extrem hilfreich ist, um die unterschiedlichen Zustände und Ereignisse abzubilden. Es hilft dann später bei der Codierung und auch beim Verstehen des Codes, ganz zu schweigen vom Testen...

Ein Beispiel einer wirklich simplen Rollladensteuerung hatte ich zuvor schon mal gepostet, anbei nochmal die Datei. Erstellt mit LibreOffice Draw, das ich hierfür nicht wirklich gut finde.

  • Was haltet ihr von der Idee, wenn wir eine generelle Rollladensteuerung grafisch als Zustandsautomat abbilden (dabei den Zuständen Kurznamen geben, um sie im Code wiederzufinden)?
  • Wenn Zustimmung, habt ihr einen Vorschlag, wie man mit wenig Aufwand die grafische Darstellung erreichen kann? Wie gesagt, halte ich LibreOffice Draw für zu aufwendig. Ich denke da an irgendetwas textbasiertes, das über git verteilt werden kann.
Grüße,
spi

Cluni

#95

spi3845

Zitat von: Cluni am 16 April 2017, 01:24:46
https://www.draw.io
Cool, gefällt mir. Wie ist deine Erfahrung in der Zusammenarbeit mit mehreren bzgl. Änderungen nachverfolgen?

Habe parallel GraphViz getestet (http://www.graphviz.org/). Könnte als Textdatei über git verteilt werden (mit Nachverfolgen der Änderungen). Beispiel anbei - ist noch nicht schön, aber schnell und einfach :)

ea_rollo_001.gv

digraph finite_state_machine {
        rankdir=TB; /* LR für von links nach rechts */
        size="8,5"
        node [shape=box,style="rounded,bold"];
        ro [color=black,label="Rollo oben\n[ro]",labelloc=b];
        lv [color=blue,label="Lüften viel\n[lv]",labelloc=b];
        lw [color=blue,label="Lüften wenig\n[lw]",labelloc=b];
        ru [color=black,label="Rollo unten\n[ru]",labelloc=b];
        ro -> ru [ label = "Rollo zu" ];
        ru -> ro [ label = "Rollo auf && Tür!=offen" ];
        ro -> lw [ label = "Rollo zu && Tür=gekippt" ];
        lv -> lw [ label = "Tür kippen" ];
        lw -> ru [ label = "Tür zu" ];
        lv -> ru [ label = "Tür zu" ];
        ru -> lw [ label = "Tür kippen" ];
        ru -> lv [ label = "Tür öffnen" ];
        lw -> lv [ label = "Tür öffnen" ];
        lw -> ro [ label = "Rollo auf && Tür!=offen" ];
}


Png erstellen durch:
dot -T png ea_rollo_001.gv -o ea_rollo.png

Grüße,
spi

spi3845

#97
digraph finite_state_machine {
rankdir=TB; /* LR für von links nach rechts */
node [shape=box,style="rounded,bold"];
ro [color=black,label="Rollo steht oben\n[ro]",labelloc=b];
rülo [color=blue,label="Rollo steht oberhalb Position\n'Lüften bei offener Tür'\n[rülo]",labelloc=b];
rfülo [color=red,label="Rollo fährt oberhalb Position\n'Lüften bei offener Tür'\n[rfülo]",labelloc=b];
rfalo [color=red,label="Rollo fährt an Position\n'Lüften bei offener Tür'\n[rfalo]",labelloc=b];
lo [color=green,label="Rollo steht in Position\n'Lüften bei offener Tür'\n[lo]",labelloc=b];
rülg [color=blue,label="Rollo steht oberhalb Position\n'Lüften bei gekippter Tür'\n[rülg]",labelloc=b];
rfülg [color=red,label="Rollo fährt oberhalb Position\n'Lüften bei gekippter Tür'\n[rfülg]",labelloc=b];
rfalg [color=red,label="Rollo fährt an Position\n'Lüften bei gekippter Tür'\n[rfalg]",labelloc=b];
lg [color=green,label="Rollo steht in Position\n'Lüften bei gekippter Tür'\n[lg]",labelloc=b];
rulg [color=blue,label="Rollo steht unterhalb Position\n'Lüften bei gekippter Tür'\n[rulg]",labelloc=b];
rfulg [color=red,label="Rollo fährt unterhalb Position\n'Lüften bei gekippter Tür'\n[rfulg]",labelloc=b];
ru [color=black,label="Rollo steht unten\n[ru]",labelloc=b];
ro -> ru [ label = "Rollo zu" ];
ru -> ro [ label = "Rollo auf && Tür!=offen (Einbruchschutz)" ];
ro -> ro [ label = "Rollo auf && Tür=offen (Aussperrschutz)" ];
ro -> lg [ label = "Rollo zu && Tür=gekippt" ];
lo -> lg [ color=green,fontcolor=green,label = "Tür kippen" ];
lg -> ru [ label = "Tür zu" ];
lo -> ru [ label = "Tür zu" ];
ru -> lg [ color=green,fontcolor=green,label = "Tür kippen" ];
ru -> lo [ color=green,fontcolor=green,label = "Tür öffnen" ];
lg -> lo [ color=green,fontcolor=green,label = "Tür öffnen" ];
lg -> ro [ label = "Rollo auf && Tür!=offen" ];

ro -> rfülo [ label = "Rollo zu" ];
rfülo -> rülo [ color=red,fontcolor=red,label = "Stopp gedrückt" ];
rfülo -> rfalo [ color=orange,fontcolor=orange,label = "weiter 'Rollo zu'" ];
rfalo -> rfülg [ color=orange,fontcolor=orange,label = "weiter 'Rollo zu'" ];
rfülg -> rülg [ color=red,fontcolor=red,label = "Stopp gedrückt" ];
rfülg -> rfalg [ color=orange,fontcolor=orange,label = "weiter 'Rollo zu'" ];
rfalg -> rfulg [ color=orange,fontcolor=orange,label = "weiter 'Rollo zu'" ];
rfalo -> lo [ color=red,fontcolor=red,label = "Stopp gedrückt" ];
rfalg -> lg [ color=red,fontcolor=red,label = "Stopp gedrückt" ];
rfulg -> rulg [ color=red,fontcolor=red,label = "Stopp gedrückt" ];
rülo -> rfülo [ label = "Rollo auf/zu" ];
rfülo -> ro [ color=orange,fontcolor=orange,label = "weiter 'Rollo auf'" ];
rülg -> rfülg [ label = "Rollo auf/zu" ];
rfülg -> rfalo [ color=orange,fontcolor=orange,label = "weiter 'Rollo auf'" ];
rulg -> rfulg [ label = "Rollo auf/zu" ];
rfulg -> rfalg [ color=orange,fontcolor=orange,label = "weiter 'Rollo auf'" ];
{ rülo,rülg,rulg -> lo [ color=purple,fontcolor=purple, label = "Tür öffnen" ] };
{ rülo,rülg,rulg -> lg [ color=purple,fontcolor=purple, label = "Tür kippen" ] };
{ rfülo,rfalo,rfülg,rfalg,rfulg -> lo [ color=purple,fontcolor=purple, label = "Tür öffnen" ] };
{ rfülo,rfalo,rfülg,rfalg,rfulg -> lg [ color=purple,fontcolor=purple, label = "Tür kippen" ] };

}

@Beta-User: ein quick&dirty-Versuch, die Zustände deiner Funktion abzubilden (Ereignisse zu prüfen, insbesondere die in lila Farbe).

Zustände:
Schwarz = Rollo im Anschlag ober oder unten
Grün = Rollo bei geöffneter/gekippter Tür
Blau = Rollo in anderen Positionen
Rot = Rollo in Bewegung


Ist das ein gangbarer Weg, eine Rollladensteuerung abzubilden? Oder über https://www.draw.io? Was meint ihr?
Auf jeden Fall gilt es, das Modell zu vereinfachen - nicht alle Zustände werden gebraucht...

Grüße,
spi

Beta-User

Moin zusammen,

Danke für den Versuch eine Visualisierung! Es erinnert an die HM-Statemachine-Beschreibung im Einsteigerdokument, die wirklich hilfreich war, um zu verstehen, wie so ein Gerät "denkt" (und das dann ggf. auch mit einem Arduino etc. für andere Bereiche abzubilden).

Was ich in der Abbildung so nicht gefunden habe, ist die "Mitnahme" der "Soll-Position" beim Schließen des Fensters (wenn unterhalb des aktuellen Levels). Ansonsten bleiben ja auch alle Zwischenaktionen zulässig, also bei offenem Fenster ein "set 50" zu machen, wenn "40" der Offen-Level ist. Ansonsten ist meine Feststellung in der Praxis, dass jeder Versuch der Vereinfachung der Zustände zu unerwünschten Ergebnissen führt... Nichts schlimmes, aber eben auch nicht intuitiv. Dazu kommt, dass es manchmal nicht so einfach ist, bis man die "richtigen" Ereignisse und Informationen abgreift (bzw. alle); das führt dann zu solchen "Hä, warum denn jetzt auf einmal dieser Parameter hier?!?.." - ??? -Erlebnissen und Knoten im Hirn. Habe aber den Eindruck, dass der code so langsam aber sicher alle Varianten abbildet.

Auch gut wäre eine einheitliche Namenskonvention. (Bisher habe ich aus dem Grund nur 4 "verattributiert", 2 Jalousien und 2 Rolläden). Das ist auch mit ein Grund für die Modul-Idee, dann geht es nämlich relativ einfach, die Attribute einheitlich setzen zu lassen und die erforderlichen notifys intern zu verwalten (?).

"Mein" Code und Hugos Lösung sind auch nicht grundsätzlich unterschiedlich, sondern lösen jeweils andere Teilaspekte, wobei meine Motivation erst mal die war, perl zu verstehen, um die Grundlage dafür zu haben, das in die Richtung zu lösen, wie @cluni das mit den Timern schon geschafft hat. Damit könnte ich weitere 6 DOIF's aus der Konfiguration werfen, die nicht immer so reagieren, wie ich das nach dem code vermuten würde ;). Damit wäre dann nur noch die Urlaubssimulation in Teilen (Licht) nach weekdaytimer zu überführen und ich dann DOIF-los 8).

@cluni: Für Code-Beispiele wäre ich also dankbar, wobei es m.E. in der "Modulvariante" so sein sollte, dass diese Timer nicht als eigene Geräte aufgeführt werden, sondern als interne Timer beim "HM-ShutterTools-Gerät". Das würde dann auch die zeitgesteuerte Neugenerierung übernehmen (den regelmäßigen Timer beim starten selbst setzen).

Der Ansatz, das gemeinsam weiterzuentwickeln, gefüllt mir sehr gut! Hätte nur 2 Bedingungen: Möglichst keine weiteren Abhängigkeiten (perl-Module) und (zwingend!) in der Doku keine DOIF. (Wer mag, kann das verwenden, es schließt sich nicht aus. Aber es geht sicher auch ohne...).

Zu Hugos code noch:
- Er hat m.E. den "Nachteil", dass es recht schwierig zu verstehen ist, welcher Parameter was bewirkt und er mit seiner großen Lösung eben auch viele Parameter braucht. Es wäre für ein Modul m.E. besser, wenn es mit dem Verständnis des Benutzers wachsen könnte (neue Teilfunktionen nur bei Bedarf, zusätzliche Gruppen für Beschattung usw.).
- Dann braucht es eben noch relativ viele einzelne Geräte (Timer, DOIF, ...) die konfiguriert werden wollen. Das geht ohne Modul wohl nur so (?), macht es aber nicht eben intuitiv vom Verständnis.
- Ansonsten sind mir bei der Durchsicht nur 2 Dinge aufgefallen, die eventuell "eleganter" gelöst werden können:
-- devspec2array statt alle Geräte zur Konfiguration zu durchlaufen und
-- (zu den ReadingsGroups): ob die Readings in den userattr nicht teilweise direkter gesetzt werden könnten (?)

Es wäre jedenfalls klasse, wenn wir da was miteinander hinbekämen, das es allen einfacher macht, zu einer (halbwegs) intuitiven und gut skalier- und konfigurierbaren Lösung zu kommen.

Frohe Ostern allseits,

Beta-User
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

Cluni

Hallo zusammen und frohe Ostern!

Bin momentan nicht zu Hause, daher kann ich grade den Code nicht posten. Grundsätzlich könnte man (wenn sie denn stören) die Timer auch verstecken. Das hatte ich auch schon überlegt, aber finde es momentan zum Fehler suchen einfacher, wenn sie sichtbar sind.
Mit einem Durchlauf für alle Geräte wollte ich auch noch einbauen. Dürfte auch eigentlich nicht zu schwierig sein - man müsste nur die Geräte mit dem entsprechenden Namen auslesen und alle in einer for- oder while-Schleife durchlaufen. Die einzelnen Timer für hoch und runter wurden natürlich bleiben, aber das ist ja logisch. Vielleicht baue ich das nachher noch schnell um, bevor ich den Code poste....


Gesendet von iPhone mit Tapatalk

spi3845

#100
Zitat von: Beta-User am 16 April 2017, 08:02:22
Danke für den Versuch eine Visualisierung! Es erinnert an die HM-Statemachine-Beschreibung im Einsteigerdokument, die wirklich hilfreich war, um zu verstehen, wie so ein Gerät "denkt" (und das dann ggf. auch mit einem Arduino etc. für andere Bereiche abzubilden).

Was ich in der Abbildung so nicht gefunden habe, ist die "Mitnahme" der "Soll-Position" beim Schließen des Fensters (wenn unterhalb des aktuellen Levels).
Ich kann die Mitnahme "Soll-Position" mit einzeichnen, würde aber gerne erst einmal diskutieren, ob wir die Darstellung fortführen wollen. Sie ist jetzt schon ziemlich umfangreich. Habe geute etwas mit GraphViz rumgespielt und es ist zwar einfach, neue Zustände und Übergänge aufzunehmen, auf die Darstellung selbst hat man aber wenig Einfluss. Das Ergebnis kann dann etwas überwältigend sein 8) Anbei eine aktualisierte Grafik. Wenn gewünscht, kann ich die pflegen, würde dann aber vorschlagen, dass wir

  • sie auf github ablegen (wg. Änderungen verfolgen)
  • im Code die Zustände aus der Grafik in den Kommentaren kenntlich machen (ich kann gerne andere Kürzel einbauen)
  • die Zustandsgrafik prüfen auf redundante Zustände und Ereignisse, um sie zu vereinfachen

Zitat von: Beta-User am 16 April 2017, 08:02:22
Der Ansatz, das gemeinsam weiterzuentwickeln, gefüllt mir sehr gut! Hätte nur 2 Bedingungen: Möglichst keine weiteren Abhängigkeiten (perl-Module) und (zwingend!) in der Doku keine DOIF. (Wer mag, kann das verwenden, es schließt sich nicht aus. Aber es geht sicher auch ohne...).
Also doch keine DOIFs? Damit ist meine allererste Frage beantwortet  :D
Im Ernst, pflichte dem bei, keine Abhängigkeiten und Einfachheit/Schlichtheit, damit das ganze pflegbar bleibt.

Zitat von: Beta-User am 16 April 2017, 08:02:22
- Ansonsten sind mir bei der Durchsicht nur 2 Dinge aufgefallen, die eventuell "eleganter" gelöst werden können:
-- devspec2array statt alle Geräte zur Konfiguration zu durchlaufen und
-- (zu den ReadingsGroups): ob die Readings in den userattr nicht teilweise direkter gesetzt werden könnten (?)
devspec2array klingt interessant, würde dann aber auch Rollläden erwischen, für die wir keine Automatik wollen (wer kann so etwas wollen?). Wie würden dann die entsprechenden Fensterkontakte zugeordnet werden? Über Namenskonvention (z.B. Name FK = Name des Rollos mit angehängtem FK?) oder standardmässig none zuweisen und dann manuell in den userattr setzen? Oder eine zweispaltige Liste, die wir über die GUI zuordnen... Geht so etwas überhaupt?

Was meinst Du mit Readings in den userattr direkter setzen?

Zitat von: Beta-User am 16 April 2017, 08:02:22
Frohe Ostern allseits,
Ebenso!

Grüße,
spi

Beta-User

Zitat von: spi3845 am 16 April 2017, 18:26:24
Ich kann die Mitnahme "Soll-Position" mit einzeichnen, würde aber gerne erst einmal diskutieren, ob wir die Darstellung fortführen wollen. Sie ist jetzt schon ziemlich umfangreich.
Fehlt da nicht noch die Unterscheidung beim Fahren, ob eine Zielposition gegeben ist (FHEM-veranlaßt) oder nicht (Tastendruck). Im ersteren Fall muß man m.E. noch unterscheiden, ob die Zielposition oberhalb der aktuellen ist (dann reagieren wir erst wieder bei "stop") oder unterhalb (dann generieren wir daraus eine neue on-Hold-Position)...
M.E. ist eine graphische Darstellung hilfreich, um das erst mal zu verstehen, aber wenn es mal funktioniert, sollte es intuitiv sein, so dass man das eher als Referenz für Fragen sehen sollte, wenn es welche gibt.
Kann das bei Bedarf gerne auf Github einpflegen.
Zitatdevspec2array klingt interessant, würde dann aber auch Rollläden erwischen, für die wir keine Automatik wollen (wer kann so etwas wollen?).
"Mein"  notify reagiert schon heute auf alle Rolläden und Tür-/Fensterkontakte im Haus und prüft, ob was getan werden soll. Das ist im Moment eben nur bei 4 Rolläden und 2 Drehkontakten sowie 2 "Auf/Zu"-Kontakten der Fall. Damit etwas passiert, braucht es die entsprechenden Attribute.
ZitatWie würden dann die entsprechenden Fensterkontakte zugeordnet werden?
Die Zuordnung soll über eine "set"-Funktion des Moduls erfolgen, was man 1x pro Paar für diesen Teil der Funktionalität machen müßte. Dafür ist man in der Wahl der Namen frei, kann also nehmen, was da ist, man braucht kein "Name FK = Name des Rollos mit angehängtem FK?".
Über eine GUI wäre schön, aber ich denke, wenn man z.B. sowas wie set RolloTools softpair Rolladen_WZ_SSO Fenster_Wohnzimmer_1 <offenWert><tiltedWert> einmalig eingeben muß und die letzten beiden Werte auch als Default nehmen bzw. später einfach über eine Readingsgroup ändern kann, ist das ok.
ZitatWas meinst Du mit Readings in den userattr direkter setzen?
Hugo verwendet in der ReadingsGroup noch eine command-definition, um darüber dann ein "attr ..." auszuführen. M.E. braucht es das nicht, habe das aber - außer für die max-Level - noch nicht weiter ausprobiert.

Ein bißchen "moduliert" habe ich schon, bin aber nicht recht weitergekommen, weil trotz "copy/paste" nicht mal ein "define" klappen wollte. Werde das mal bei Gelegenheit auf github legen, vielleicht hat ja jemand einen Tip dazu.

Gruß, Beta-User
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

Cluni

#102
Moin zusammen!

Soooo, ich habe noch ein wenig herumgespielt und möchte mal meinen aktuellen Stand posten. Es wird nun nur noch ein Timer für die Nacht erzeugt, worüber alle Rollladen abgearbeitet werden. (siehe Anhang)
Momentan ist nur die Zeitsteuerung fertig. Abschattung und Reaktionen auf z.B. Fenster-Öffnen fehlen noch gänzlich.

Damit alles so funktioniert, wie ich es mir gedacht habe, gibt es ein paar Vorbedingungen:

1. Meine Rollladen haben den Namen "Rol.xxx", wobei "xxx" für das Zimmer steht (Bsp: "Rol.Bad" oder "Rol.WZ.Seitentuer")

2. Allen Rollladen werden neue User-Attribute zugeordnet (die aber momentan noch nicht alle in Benutzung sind):
attr Rol\..* userattr Auto_Modus:bei_Abwesenheit,immer Auto_hoch:aus,Zeit,Astro Auto_runter:aus,Zeit,Astro Auto_offen_Pos:on,Luft,10,20,30,40,50,60,70,80,90 Auto_Himmelsrichtung Auto_Abschattung:ja,nein,verspaetet Auto_Zeit_hoch_frueh Auto_Zeit_hoch_spaet Auto_Zeit_hoch_WE_Urlaub Auto_Zeit_runter_frueh Auto_Zeit_runter_spaet Auto_Zufall_Minuten Auto_Fensterkontakt Auto_Luft_Fenster_offen:ja,nein Auto_Sperre_Fenster_offen:ja,nein
Initialisiert habe ich ein paar der Attribute wie folgt:
attr Rol\..* Auto_Modus immer
attr Rol\..* Auto_hoch aus
attr Rol\..* Auto_runter aus
attr Rol\..* Auto_offen_Pos Luft
attr Rol\..* Auto_Himmelsrichtung 178
attr Rol\..* Auto_Abschattung nein
attr Rol\..* Auto_Zeit_hoch_frueh 07:30:00
attr Rol\..* Auto_Zeit_hoch_spaet 09:00:00 
attr Rol\..* Auto_Zeit_hoch_WE_Urlaub 09:30:00
attr Rol\..* Auto_Zeit_runter_frueh 16:30:00
attr Rol\..* Auto_Zeit_runter_spaet 21:30:00
attr Rol\..* Auto_Luft_Fenster_offen ja
attr Rol\..* Auto_Sperre_Fenster_offen nein


3. Um die komplette Automatik auf einen Schlag ein- bzw auszuschalten habe ich mir zwei Dummies angelegt, die ich auch über Apple Home ändern kann:
Internals:
   NAME       Rolllanden.Automatik.morgens
   NR         273
   STATE      on
   TYPE       dummy
   Readings:
     2017-04-17 09:49:46   state           on
Attributes:
   alias      Automatik morgens
   genericDeviceType switch
   group      Rollladen_Automatik
   icon       weather_sun
   room       Haus,Homekit,Rollladen
   setList    on off
   sortby     2
   webCmd     on:off

Internals:
   NAME       Rolllanden.Automatik.abends
   NR         274
   STATE      on
   TYPE       dummy
   Readings:
     2017-04-17 09:49:42   state           on
Attributes:
   alias      Automatik abends
   genericDeviceType switch
   group      Rollladen_Automatik
   icon       weather_moon_phases_8
   room       Haus,Homekit,Rollladen
   setList    on off
   sortby     3
   webCmd     on:off


Hier der Code, der in der 99_myUtils.pm einzufügen ist (für Neulinge: nach dem Abspeichern nicht das "reload 99_myUtils.pm" vergessen!):
sub randomtime_with_realtime($;$;$)
{
  my $ZtA;
  my ($MeH,$MeM,$MeS)=split(':',shift(@_));
  my $MeB=shift(@_);
  my $MeD=shift(@_);
  if ($MeD eq '+') {$ZtA = int($MeH*3600 + $MeM*60 + rand($MeB*60) + $MeS);} # Minuten addieren
  else {$ZtA = int($MeH*3600 + $MeM*60 - rand($MeB*60) + $MeS);} # Minuten subtrahiern

  my $ZtH = int($ZtA/3600);
  my $ZtM = int(($ZtA-$ZtH*3600)/60);
  my $ZtS = int($ZtA-($ZtH*3600+$ZtM*60));
  return sprintf("%2.2d:%2.2d:%2.2d",$ZtH,$ZtM,$ZtS);


sub Auto_Rol_group_at($)
{
    #Als Parameter muss der Anfang der device-Namen übergeben werden, der bei allen Rollladen gleich ist
    my $group_name=shift(@_);
my @monitored=devspec2array("($group_name\..*)");

foreach my $dev (@monitored) {
    #Erst mal prüfen, ob das übergebene device überhaupt existiert und ob es ein Rollladen ist
    if (($defs{$dev}) and (AttrVal($dev,'subType','nv') eq 'blindActuator')) {

my $Hoch_Zeit;
my $Runter_Zeit;
my $hoch_at;
my $runter_at;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time());

my $Ferien=ReadingsVal('Ferientag','state',-1);
my $Feiertag=ReadingsVal('Feiertag','state',-1);


        #Aus dem device werden nun, sofern vorhanden, die ganzen Attribut ausgelesen.
        #Wenn das Attribut nicht vorhanden ist, bekommt es einen Standardwert (z.B. 'nv' für nicht vorhanden)
        my $A_Modus=AttrVal($dev,'Auto_Modus','immer');
        my $A_hoch=AttrVal($dev,'Auto_hoch','aus');
        my $A_runter=AttrVal($dev,'Auto_runter','aus');
        my $A_offen_Pos=AttrVal($dev,'Auto_offen_Pos','Luft');
        #my $A_Himmelsrichtung=AttrVal($dev,'Auto_Himmelsrichtung',0);
        #my $A_Abschattung=AttrVal($dev,'Auto_Abschattung','nein');
        my $A_Zeit_hoch_frueh=AttrVal($dev,'Auto_Zeit_hoch_frueh','07:30:00');
        my $A_Zeit_hoch_spaet=AttrVal($dev,'Auto_Zeit_hoch_spaet','09:00:00');
        my $A_Zeit_hoch_WE_Urlaub=AttrVal($dev,'Auto_Zeit_hoch_WE_Urlaub','09:30:00');
        my $A_Zeit_runter_frueh=AttrVal($dev,'Auto_Zeit_runter_frueh','16:30:00');
        my $A_Zeit_runter_spaet=AttrVal($dev,'Auto_Zeit_runter_spaet','21:30:00');
my $A_Zufall_Minuten=AttrVal($dev,'Auto_Zufall_Minuten','30');
my $A_Zufall_Sekunden=$A_Zufall_Minuten*60;
#my $Raeume=AttrVal($dev,'room','');

        #Festlegen des Namens für die Timer, die angelegt werden um den Rollladen zu gewünschter
        #Zeit zu fahren.
        my $Rol_hoch_Timername='Rol_Timer_hoch_'.$dev;
        my $Rol_runter_Timername='Rol_Timer_runter_'.$dev;
my $Rol_at='Timer_build_at_'.$dev;
        # #Sollten diese Timer bereits existieren, so werden sie zunächst gelöscht.
        Log 1,"delete $Rol_hoch_Timername" if ($defs{$Rol_hoch_Timername});
        fhem("delete $Rol_hoch_Timername") if ($defs{$Rol_hoch_Timername});
        Log 1,"delete $Rol_runter_Timername" if ($defs{$Rol_runter_Timername});
        fhem("delete $Rol_runter_Timername") if ($defs{$Rol_runter_Timername});
        Log 1,"delete Timer_build_at_$dev" if ($defs{$Rol_at});
fhem("delete Timer_build_at_$dev") if ($defs{$Rol_at});


if ($A_Modus eq 'immer') {fhem("setreading $dev Auto_Modus Automatik auch bei Anwesenheit");}
elsif ($A_Modus eq 'bei_Abwesenheit') {fhem("setreading $dev Auto_Modus Automatik nur, wenn niemand zu Hause ist");}
fhem("setreading $dev Auto_hoch_Zeit --:--:--");
fhem("setreading $dev Auto_hoch_Pos ---");
fhem("setreading $dev Auto_hoch_Zeit --:--:--");

$Hoch_Zeit = randomtime_with_realtime("$A_Zeit_hoch_WE_Urlaub","$A_Zufall_Minuten","+"); # Zeit zum Hochfahren mit der Wochenend- bzw. Urlaubs-Zeit vorbesetzen

if ($A_hoch eq 'aus') {goto CHECK_SET_DOWN_TIME;} # Automatik für morgens (für diesen Rollladen) ausgeschaltet? ==> dann Sprung!
if (($wday > 5) or ($wday == 0) or ($Ferien == 1) or ($Feiertag == 1)) {goto ABWESENHEITSCHECK;} # Wochenende, Urlaub oder Feiertag? ==> dann Sprung

elsif ($A_hoch eq 'Astro'){ # Automatik (für diesen Rollladen) auf Astro-Programm?
$Hoch_Zeit = sunrise_abs("REAL",$A_Zufall_Sekunden-rand($A_Zufall_Sekunden*2),randomtime_with_realtime("$A_Zeit_hoch_frueh","$A_Zufall_Minuten","+"),randomtime_with_realtime("$A_Zeit_hoch_spaet","$A_Zufall_Minuten","-"));
}
elsif ($A_hoch eq 'Zeit'){ # Automatik (für diesen Rollladen) auf normalem Zeitprogramm?
$Hoch_Zeit = randomtime_with_realtime("$A_Zeit_hoch_frueh","$A_Zufall_Minuten","+");
}

ABWESENHEITSCHECK:
if ($A_Modus eq 'immer') {$hoch_at = "define $Rol_hoch_Timername at $Hoch_Zeit { if (ReadingsVal(\"Rolllanden.Automatik.morgens\",\"state\",\"nv\") eq \"on\" ) { fhem(\"set $dev $A_offen_Pos\") }}";}
elsif ($A_Modus eq 'bei_Abwesenheit') {$hoch_at = "define $Rol_hoch_Timername at $Hoch_Zeit { if ((ReadingsVal(\"jemand_zu_Hause\",\"state\",\"\") eq \"absent\" ) and (ReadingsVal(\"Rolllanden.Automatik.morgens\",\"state\",\"nv\") eq \"on\" )) { fhem(\"set $dev $A_offen_Pos\") }}";}

fhem("$hoch_at");
fhem("attr $Rol_hoch_Timername room Timer");
fhem("attr $Rol_hoch_Timername icon fts_shutter_automatic\@yellow");
fhem("setreading $dev Auto_hoch_Zeit $Hoch_Zeit");
fhem("setreading $dev Auto_hoch_Pos $A_offen_Pos");


CHECK_SET_DOWN_TIME:
if ($A_runter eq 'aus') {goto ENDE;} # Automatik (für diesen Rollladen) für abends ausgeschaltet? ==> dann Sprung!
elsif ($A_runter eq 'Astro'){ # Automatik (für diesen Rollladen) auf Astro-Programm?
$Runter_Zeit = sunset_abs("REAL",$A_Zufall_Sekunden-rand($A_Zufall_Sekunden*2),randomtime_with_realtime("$A_Zeit_runter_frueh","$A_Zufall_Minuten","+"),randomtime_with_realtime("$A_Zeit_runter_spaet","$A_Zufall_Minuten","-"));
}
elsif ($A_runter eq 'Zeit'){ # Automatik (für diesen Rollladen) auf normalem Zeitprogramm?
$Runter_Zeit = randomtime_with_realtime("$A_Zeit_runter_spaet","$A_Zufall_Minuten","-");
}

if ($A_Modus eq 'immer') {$runter_at = "define $Rol_runter_Timername at $Runter_Zeit { if (ReadingsVal(\"Rolllanden.Automatik.abends\",\"state\",\"nv\") eq \"on\" ) { fhem(\"set $dev off\") }}";}
elsif ($A_Modus eq 'bei_Abwesenheit') {$runter_at = "define $Rol_runter_Timername at $Runter_Zeit { if ((ReadingsVal(\"jemand_zu_Hause\",\"state\",\"\") eq \"absent\" ) and (ReadingsVal(\"Rolllanden.Automatik.abends\",\"state\",\"nv\") eq \"on\" )) { fhem(\"set $dev off\") }}";}


fhem("$runter_at");
fhem("attr $Rol_runter_Timername room Timer");
fhem("attr $Rol_runter_Timername icon fts_shutter_automatic\@green");
fhem("setreading $dev Auto_runter_Zeit $Runter_Zeit");


ENDE:
}
}

my $TimerErzeugerName='TimerErzeuger_'.$group_name;
fhem("define $TimerErzeugerName at *00:05:00 {Auto_Rol_group_at(\"$group_name\")}") if (!($defs{$TimerErzeugerName}));  # Timer zum Starten dieser Funktion erzeugen, falls noch nicht vorhanden
fhem("attr $TimerErzeugerName room Timer");
fhem("attr $TimerErzeugerName icon clock\@blue");
fhem("attr $TimerErzeugerName webCmd execNow"); # Webcmd zur einfachen Neuberechnung anlegen


# nun noch ein Notify erzeugen, damit bei einem Neustart von Fhem die temporaeren Timer berechnet werden (die sind sonst naemlich weg)
fhem("define TimerSystemStart.ntfy notify global:INITIALIZED {fhem(\"set $TimerErzeugerName execNow\")}") if (!($defs{"TimerSystemStart.ntfy"}));  # Notify erzeugen, falls noch nicht vorhanden
fhem("attr TimerSystemStart.ntfy room Timer");
fhem("attr TimerSystemStart.ntfy icon system_fhem_reboot\@orange");




Mit einem einmaligen Aufruf der Routine für meine Rollladen mit dem Befehl:
{Auto_Rol_group_at("Rol")}

...wird ein nächtlicher Timer um 00:05:00Uhr mit dem Namen "TimerErzeuger_Rol" angelegt. Dieser ist permanent und wird jede Nacht ausgeführt, damit die at (Timer) für die einzelnen Rollladen täglich neu berechnet werden. Da hierbei eine permanente Sache generiert wird, muss die Konfiguration einmal gespeichert werden (rotes ?). Dies ist aber nur beim allerersten Aufruf der Fall. Die automatisch angelegten Timer für die einzelnen Rollladen sind einmalige Timer, die sich nach Ausführung selber löschen und dann in der Nacht neu angelegt werden.

Möchte man die Timer manuell neu berechnen lassen (z.B., weil irgendwelche User-Attribute geändert wurden), dann kann man das mit einem der beiden folgenden Befehle machen:
{Auto_Rol_group_at("Rol")}

oder

set TimerErzeuger_Rol execNow


Es kann nun auch das webCmd "execNow" am Timer gedrückt werden, damit eine Neuberechnung angestoßen wird.

So - ich hoffe, dass ich nichts vergessen habe. Bei Rückfragen und/oder Unstimmigkeiten gerne her damit. ;)

Gruß Bernd

Cluni

Oh, ich sehe grade, dass ich den Ferien- und Feiertagskalender vergessen habe zu erwähnen. Diesen habe ich wie an diversen Stellen beschrieben angelegt. Damit ich den aktuellen Status auswerten kann, lege ich mir im Falle von Ferien bzw Feiertagen den Wert "1" auf das jeweilige Dummy (mit dem Namen "Ferien" bzw. "Feiertag")...

Cluni

Ich habe meine Routine in der 99_myUtils.pm oben noch etwas ergänzt. Am Ende lege ich nun noch ein Notify an, welches beim Systemstart getriggert wird. Daraufhin werden die Timer einmal neu generiert. Dies ist notwendig, wenn man nach 00:05:00Uhr einen Neustart von Fhem macht (aus welchem Grund auch immer). Bei einem Neustart werden die temporären ats gelöscht, was wiederum zur Folge hat, dass die vorher berechneten Rollladenfahrten nicht mehr ausgeführt würden. Dies ist nun behoben.