Enable/Disable Button für WeekdayTimer via readingsGroup

Begonnen von tpm88, 16 Mai 2014, 10:49:27

Vorheriges Thema - Nächstes Thema

tpm88

EDIT: Ab Version 98_WeekdayTimer.pm 6057 2014-06-04 vereinfacht sich die Lösung wie weiter unten in http://forum.fhem.de/index.php/topic,23655.msg176087.html#msg176087 beschrieben.

Hallo zusammen,

Aufgabe war es, einen (WAF kompatiblen) Enable/Disable Button für zwei WeekdayTimer zu realisieren, die eine einfache Bewässerung steuern. Die Lösung lässt sich natürlich auf alle Objekte übertragen, die das "disable" Attribut haben.

Ich habe das wie folgt gelöst - möglicherweise lässt sich das an der einen oder anderen Ecke auch noch etwas eleganter oder weniger komplex lösen - Feedback ist ausdrücklich erwünscht.

Grundidee: Eine readingsGroup für die Timer mit einem zusätzlichen userReading "active" als Button. Die in der RG hinterlegten commands für den Button setzen bzw. löschen jeweils das Attribut "disable" der Timer. Falls der Timer aktiv ist, wird der nächste Schaltzeitpunkt und Kommando für das geschaltete Device angezeigt, falls inaktiv, wird "disabled" angezeigt.

Kurzversion:

1. zusätzliches userReading "active" für die WeekdayTimer definieren mit den möglichen Werten "enabled" und "disabled"
2. readingsGroup für die WeekdayTimer anlegen mit folgenden readings: "active", "+DEF", "nextUpdate", "nextValue"
3. die Attribute valueFormat, valueIcon und commands wie unten detailliert beschrieben setzen
4. ein zusätzliches jede Minute ausgeführtes at aktualisiert das userReading "active", falls doch einmal das Attribut "disable" manuell für einen Timer verändert wird

Hier die Details:

Punkt 1  - userReading für WeekdayTimer:


attr timer_Wasser_01 userReadings active { return "enabled" if ! ($attr{$hash->{NAME}}{disable}); return "disabled" }


Punkt 2 - readingsGroup definieren:


define rg_Timer_Wasser readingsGroup timer_Wasser_..:active,+DEF,nextUpdate,nextValue

Das interne Attribut "+DEF" zeigt die definierten Schaltpunkte an - der in +DEF enthaltene Name des WeekdayTimer wird mit Hilfe von valueFormat noch ausgeblendet.

Punkt 3 - Attribute für die RG:

attr rg_Timer_Wasser valueFormat { my @text = split(" ", $VALUE); shift @text;  if ( $READING =~ m/.*DEF/ ) { return join(" ", @text) }; return $VALUE if  (ReadingsVal($DEVICE, "active", "enabled") eq "enabled"); return "disabled"; }

Hiermit wird für das Reading "+DEF" wie oben erwähnt der voranstehende Name des WeekdayTimer entfernt und nur die definierten Schaltpunkte angezeigt. Die Readings nextUpdate und nextValue werden nur angezeigt, wenn der Timer "enabled" ist - sonst wird "disabled" ausgegeben.

Das Kommando kann so nicht direkt eingegeben werden. Sonst tritt der u.a. Fehler auf: http://forum.fhem.de/index.php/topic,23655.msg169379.html#msg169379
Über die Detailsansicht des Webfrontends kann das Attribut valueFormat aber mit dem String:
{ my @text = split(" ", $VALUE); shift @text;  if ( $READING =~ m/.*DEF/ ) { return join(" ", @text) }; return $VALUE if  (ReadingsVal($DEVICE, "active", "enabled") eq "enabled"); return "disabled"; }
angelegt werden.


attr rg_Timer_Wasser valueIcon { 'active.enabled' => 'Restart', 'active.disabled' => 'Shutdown' }

Stellt das Reading "active" je nach Zustand enabled/disabled als roten (Default Icon Shutdown) bzw. grünen (Default Icon Restart) da.


attr rg_Timer_Wasser commands { 'active.enabled' => 'attr $DEVICE disable 1; setreading $DEVICE active disabled', 'active.disabled' => 'attr $DEVICE disable 0; setreading $DEVICE active enabled' }

Definiert die Aktionen, die beim Drücken auf den Button ausgelöst werden. Wenn der Timer "enabled" ist, führt ein Drücken des Button zum Setzen des Attributs disable, gleichzeitig wird das UserReading active auf "disabled" aktualisiert. Analog der Fall für Button Drücken, wenn "disabled". Das setreading Kommando sorgt auch dafür, daß der neue Zustand sofort im Frontend dargestellt wird.

Punkt 4 - Zusätzliches at Kommando (Hilfskonstrukt)


define update_timer_status at +*00:01 { my $timer;
          foreach $timer ('timer_Wasser_01', 'timer_Wasser_02')
            { if ($attr{$timer}{disable}) { fhem "setreading $timer active disabled" }
              else { fhem "setreading $timer active enabled" }
            }
        }

Dieser at sorgt ggf. minütlich für einen Update des UserReadings "active", falls manuell das Attribut "disable" für einen Timer verändert wird. Diese Krücke benötige ich, da mir kein Weg bekannt ist, einen Trigger auf das Setzen eines Attributs zu definieren.

Fertig sieht die readingGroup "Scheduling" in der Gruppe "Bewässerung" dann so aus - siehe Screenshot.

Gruss
Tobias


Edit: attr Kommandos korrigiert. Hinweis zum valueFormat.
Test FHEM Server on RPi, CUL_HM
Prod FHEM Server on Odroid HC1, HM-USB, JeeLink
Devices: diverse HM, IT1500, 1wire, LaCrosse, MQTT

justme1968

magst du das nicht so schön beschrieben ins wiki stellen.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

T.ihmann

Habe das mal versucht nachzuvollziehen: Es kommen leider mehrere Fehlermeldungen:

Unknown command attribute, try help.
Unknown command shift, try help.
IF: no left bracket:  { return join(" ", @text) }
Unknown command return, try help.
Unknown command return, try help.
Unknown command }, try help.


1.) attribute sollte wohl attr heißen

tpm88

Zitat von: T.ihmann am 17 Mai 2014, 09:31:59
1.) attribute sollte wohl attr heißen

Ja klar - danke für den Hinweis - hab ich oben korrigiert.

Tobias
Test FHEM Server on RPi, CUL_HM
Prod FHEM Server on Odroid HC1, HM-USB, JeeLink
Devices: diverse HM, IT1500, 1wire, LaCrosse, MQTT

T.ihmann

#4
Die Fehlermeldung ist weg, aber bei Punkt 3

attr rg_Timer_Wasser valueFormat { my @text = split(" ", $VALUE); shift @text;  if ( $READING =~ m/.*DEF/ ) { return join(" ", @text) }; return $VALUE if  (ReadingsVal($DEVICE, "active", "enabled") eq "enabled"); return "disabled"; }

kommt immer noch diese Fehlermeldung


Unknown command shift, try help.
IF: no left bracket:  { return join(" ", @text) }
Unknown command return, try help.
Unknown command return, try help.
Unknown command }, try help.


Da scheint noch etwas nicht zu stimmen. Ich habe das mal versucht zu analysieren, sind aber mir zu viele Verschachtelungen

tpm88

Zitat von: T.ihmann am 17 Mai 2014, 11:30:14
Die Fehlermeldung ist weg, aber bei Punkt 3

attr rg_Timer_Wasser valueFormat { my @text = split(" ", $VALUE); shift @text;  if ( $READING =~ m/.*DEF/ ) { return join(" ", @text) }; return $VALUE if  (ReadingsVal($DEVICE, "active", "enabled") eq "enabled"); return "disabled"; }

kommt immer noch diese Fehlermeldung


Unknown command shift, try help.
IF: no left bracket:  { return join(" ", @text) }
...


Ich habe keine Ahnung, warum sich da das IF (nicht if!!) Modul einmischt...

Was jedoch funktioniert ist, das Attribut über das WebFrontend anzulegen - d.h. in der Detailansicht zur angelegten readingsGroup aus dem Pull-Down-Menu bei attr "valueFormat" auswählen und dann den String

{ my @text = split(" ", $VALUE); shift @text;  if ( $READING =~ m/.*DEF/ ) { return join(" ", @text) }; return $VALUE if  (ReadingsVal($DEVICE, "active", "enabled") eq "enabled"); return "disabled"; }

in das leere Eingabefeld dahinter kopieren und mit Druck auf den "attr" Button abschliessen.

Gruss
Tobias
Test FHEM Server on RPi, CUL_HM
Prod FHEM Server on Odroid HC1, HM-USB, JeeLink
Devices: diverse HM, IT1500, 1wire, LaCrosse, MQTT

T.ihmann


Jens_B

Das gefällt mir. Damit könnte ich die Rollladenschaltung auf dem Frontend bisschen schöner machen. Ich habe für Wochenende und Wochentag unterschiedliche Schaltzeiten, leider zeigt Weekdaytimer immer nur "active" oder "inactive" an. Dabei wären die Schaltzeiten viel Interessanter :)
Vielleicht kann das ja so auch irgendwann mal direkt in Weekdaytimer eingebaut werden?
Ich finde das minütliche Abfrage des Readings etwas unglücklich auf schwachbrüstigen CPUs ;)

Grundsätzlich fände ich es für manche Device schön, wenn man bestimmte Readings direkt im frontend platzieren könnte (ohne den Umweg mit Readingsgroup)
So ein Attribut wie "show_reading_web" oder so...


Gruß
Jens
RaspberryPi 4 (Raspian Buster)FHEM+Homebridge
HMLAN für Homematic
Z-Wave USB Stick
Shelly Devices
Fritz!Box 7590Ax

tpm88

Hallo Jens,

Dietmar wird beim WeekdayTimer und Heating_Control einige Anpassungen vornehmen, sodaß man zumindest ohne das UserReading und das minütliche Polling auskommen wird (siehe: http://forum.fhem.de/index.php/topic,10011.msg169505.html#msg169505).

Sobald diese Änderungen da sind, werde ich obiges HowTo entsprechend aktualisieren  - vermutlich wird es aber nicht ohne readingsGroup gehen.

Gruss
Tobias
Test FHEM Server on RPi, CUL_HM
Prod FHEM Server on Odroid HC1, HM-USB, JeeLink
Devices: diverse HM, IT1500, 1wire, LaCrosse, MQTT

tpm88

Wie angekündigt hat Dietmar die Module WeekdayTimer und Heating_Control mit einem set Kommando zum Setzen und Löschen  des disable Attributs und einem Reading "disabled" erweitert. Damit vereinfacht sich der Enable/Disable Button für WeekdayTimer ab Version 98_WeekdayTimer.pm 6057 2014-06-04 wie folgt:

Punkt 1  - userReading für WeekdayTimer: - entfällt, da es jetzt ein Standardreading "disabled" gibt

Punkt 2 - readingsGroup definieren:

define rg_Timer_Wasser readingsGroup  timer_Wasser_..:disabled,+DEF,<{rg_timer_Wasser_show_conditional($DEVICE)}@disabled>

Das interne Attribut "+DEF" zeigt die definierten Schaltpunkte an - der in +DEF enthaltene Name des WeekdayTimer wird mit Hilfe von valueFormat noch ausgeblendet.

Zusätzlich sorgt die folgende Funktion rg_timer_Wasser_show_conditional in der 99_myUtils.pm dafür, daß das Reading nextUpdate  des Timers nur angezeigt wird, wenn der Timer aktiv ist. Ansonsten wird "disabled" angezeigt. Das abschließende @disabled sorgt dafür, daß der LongPoll Mechanismus die Anzeige sofort ändert, wenn der Button betätigt wird.

sub rg_timer_Wasser_show_conditional($)
{
  my ($DEVICE) = @_;
  return ( ReadingsVal($DEVICE, "disabled", "1") eq "0" )? "Next: ".ReadingsVal($DEVICE, "nextUpdate", "ERROR_next_value") : "disabled";
}


Punkt 3 - Attribute für die RG:

Erläuterung zu den Attributen und Handling siehe den (ersten) Originalpost ganz oben.

attr rg_Timer_Wasser valueFormat  { if ( $READING =~ m/.*DEF/ ) { my @text = split(" ", $VALUE); shift @text; return join(" ", @text) }}

attr rg_Timer_Wasser valueIcon { 'disabled.0' => 'Restart', 'disabled.1' => 'Shutdown' }

attr rg_Timer_Wasser commands  { 'disabled.0' => 'set $DEVICE disable', 'disabled.1' => 'set $DEVICE enable' }


Punkt 4 - Zusätzliches at Kommando (Hilfskonstrukt) - entfällt, da die Änderung des "disable" Attributs automatisch das "disabled" Reading triggert

Tobias
Test FHEM Server on RPi, CUL_HM
Prod FHEM Server on Odroid HC1, HM-USB, JeeLink
Devices: diverse HM, IT1500, 1wire, LaCrosse, MQTT

tpm88

Test FHEM Server on RPi, CUL_HM
Prod FHEM Server on Odroid HC1, HM-USB, JeeLink
Devices: diverse HM, IT1500, 1wire, LaCrosse, MQTT

justme1968

hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Tipetan

#12
Guten Abend,
ich habe versucht diese Anleitung mit meinen eingeschränkten Programmierkenntnissen zu  implementieren.
http://www.fhemwiki.de/wiki/ReadingsGroup#Enable.2FDisable_Button_am_Beispiel_eines_WeekdayTimer
Nur leider bekomme ich ein komisches Fehlerbild wie ich es im Anhang dargestellt habe.

Hat Jemand eine Idee worann das liegen könnte?

Hier der Auszug aus meinem Config-File an der Stelle an der ich den Weekdaytimer und den Enable/Disable Button definiere.
define Timer.Rollo.EG1 WeekdayTimer EGRollo1 1234567|06:00|rauf
  attr Timer.Rollo.EG1 alias Timer_Wohnzimmer
  attr Timer.Rollo.EG1 group Timer
  attr Timer.Rollo.EG1 room Timer
  attr Timer.Rollo.EG1 devStateIcon rauf:black_up.png runter:black_down.png
  attr Timer.Rollo.EG1 icon timer
  attr Timer.Rollo.EG1 sortby 1

define rg_timer_Rollo readingsGroup Timer.Rollo.EG1:disabled,+DEF,<{rg_timer_Rollo_show_conditional($DEVICE,"nextUpdate")}@disabled>,<{rg_timer_Rollo_show_conditional($DEVICE,"nextValue")}@disabled>
  attr rg_timer_Rollo valueFormat if ( $READING =~ m/.*DEF/ ) { my @text = split(" ", $VALUE); shift @text; return join(" ", @text) }
  attr rg_timer_Rollo valueIcon  {'disabled.0' => 'timer_on', 'disabled.1' => 'timer_off'}
  attr rg_timer_Rollo commands  {'disabled.0' => 'set $DEVICE disable', 'disabled.1' => 'set $DEVICE enable'}
  attr rg_timer_Rollo group Timer
  attr rg_timer_Rollo room Timer
  attr rg_timer_Rollo sortby 2


Auszug aus der 99_myUtils.pm
sub rg_timer_Rollo_show_conditional($$)
{
  my ($DEVICE,$READING) = @_;
  return ( ReadingsVal($DEVICE, "disabled", "1") eq "0" )?
     ReadingsVal($DEVICE, $READING, "reading_undef") : "disabled";
}


Weiterhin kommt nach dem rereadcfg folgende Fehlermeldung
ZitatUnknown command shift, try help.
Unknown command return, try help.

Vielen Dank für eure Unterstützung
Tipetan

>-> Eine NULL kann ein bestehendes Problem verzehnfach <-<
Raspberry Pi 2 Model B | FHEM 5.6 | CUL V3.4 (culfw 1.58 + Insta) | HMLAN | Berker (INSTA) Funkkomponenten
Entwicklung auf Raspberry Pi 2 B+

justme1968

du musst auf jeden fall valueFormat in { } einschliessen:{if ( $READING =~ m/.*DEF/ ) { my @text = split(" ", $VALUE); shift @text; return join(" ", @text) } }

den rest habe ich mir nicht weiter angeschaut.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Tipetan

Hallo,
danke für den Tipp. Das war noch ein altes Rudiment aus meiner Phase: Ich Probiere erst mal selber!
Ich habe die geschweiften klammern nun gesetzt aber ohne Erfolg. Die Geschweiften Klammer tauchen jetzt ebenfalls mit auf.

Noch weitere Ideen?

Gruß
Tipetan
>-> Eine NULL kann ein bestehendes Problem verzehnfach <-<
Raspberry Pi 2 Model B | FHEM 5.6 | CUL V3.4 (culfw 1.58 + Insta) | HMLAN | Berker (INSTA) Funkkomponenten
Entwicklung auf Raspberry Pi 2 B+