Hallo liebe Gemeinde
nun habe ich nach vielem lesen und erfolgreichen programieren doch eine Frage!
Ausgangsstellung:
Meine Rollosteuerung mit Homematic ist soweit fertig eingerichtet und wird von mir nun nur noch optimiert. Leider habe ich einen "Fehler" festgestellt, welchen ich nicht recht zu händel weiß.
Events:
2015-09-11 20:07:33 CUL_HM wz_ro_tuer level: set_0
2015-09-11 20:07:33 CUL_HM wz_ro_tuer set_0
2015-09-11 20:07:33 CUL_HM wz_ro_tuer level: set_0
2015-09-11 20:07:33 CUL_HM wz_ro_tuer set_0
2015-09-11 20:07:33 readingsGroup rg_Rollosteuerung du_Tageslicht: 0
2015-09-11 20:07:33 dummy du_Tageslicht 0
Logs:
2015.09.11 20:07:33 3: CUL_HM set wz_ro_tuer 0
2015.09.11 20:07:33 3: CUL_HM set wz_ro_tuer 0
Frage:
Wie verhindere ich, dass das Kommando "set wz_ro_tuer 0" zweimal aufgerufen wird.
Erklärung:
Der Ursprung kann nur in diesem at liegen, bei welchem du_Tageslicht verändert wird.
*{sunset(0,"18:00","22:00")} set wz_ro_essecke 0; set wz_ro_sofa 0; set ke_ro 0; set ba_ro 0; set ku_ro 0; set du_Tageslicht 0
Leider gibt es zwei Events, weshalb mein notify nt_WzGriff
wz_gr_tuer:(open|closed)|du_Tageslicht:.*{
if (Value("du_xx_ro_auto") eq "an"){
if (Value("wz_gr_tuer") eq "closed" && Value("du_Tageslicht") == 0){
fhem "set wz_ro_tuer 0"
} elsif (Value("wz_gr_tuer") eq "open" && Value("wz_ro_tuer") ne "offen"){
fhem "set wz_ro_tuer 100"
}
}
}
zweimal ausgeführt wird.
Die Stelle du_Tageslicht:.* ist also nach meiner Meinung nicht ganz 100%. Leider habe ich keine Idee, wie ich die beiden Events
2015-09-11 20:07:33 readingsGroup rg_Rollosteuerung du_Tageslicht: 0
2015-09-11 20:07:33 dummy du_Tageslicht 0
auseinander halten kann.
Anmerkung:
Der Griff löst bei jeder Bewegung vier Events aus, weshalb ich im notify nun das "oder" für wz_gr_tuer:(open|closed) gesetzt hatte um diese auseinander zu halten. Das Problem war also ein ähnliches, was sich jedoch auf den Platzhalter beschränkte
Schau dir event-on-change reading an.
ZitatLeider habe ich keine Idee, wie ich die beiden Events
Über das Device behaupte ich mal.
Einmal ist es die RG und einmal der Dummy.
(wz_gr_tuer|<Name_des_dummy>):(open|closed|du_Tageslicht):.*{
wäre einen Versuch wert.
Zitat von: marvin78 am 11 September 2015, 20:41:01
Schau dir event-on-change reading an.
Wird wohl nichts bringen bei 2 Device.Für jedes Device setzen bringt das durchaus was ::)
Edith: Im Forum gibt es bereits eine Diskussion das RG auch Events (mehrere) auslöst - ich hab den aber nicht weiter verfolgt.
Vielen Dank für deinen Tip! Leider kann mir diese Idee vermutlich keinen Fortschritt bringen, da der Dummy du_Tageslicht nur ein einziges reading hat und somit der Tip nicht hier her passt.
Die beiden Events sind ein state und ein reading. Auf beide reagiert das notify (von mir ungewollt).
Zitat von: RomanticBoy83 am 11 September 2015, 20:47:11
Vielen Dank für deinen Tip! Leider kann mir diese Idee vermutlich keinen Fortschritt bringen, da der Dummy du_Tageslicht nur ein einziges reading hat und somit der Tip nicht hier her passt.
Die beiden Events sind ein state und ein reading. Auf beide reagiert das notify (von mir ungewollt).
Aber du versuchst es auch nicht - ok.
Dann eben nicht.
Boh die Antwortfunktion - gewöhnungsbedürftig!!!
zu marvin78:
Vielen Dank für deinen Tip! Leider kann mir diese Idee vermutlich keinen Fortschritt bringen, da der Dummy du_Tageslicht nur ein einziges reading hat und somit der Tip nicht hier her passt.
Die beiden Events sind ein state und ein reading. Auf beide reagiert das notify (von mir ungewollt).
zu Puschel74:
Vielen Dank für dein Codeschnipsel. Leider ist die Syntax des codes falsch. Wenn ich es jedoch richtig interpretiere, dann ist es nur eine andere Schreibweise, welche mit der Boolschenalgebra erreicht wurde.
(wz_gr_tuer|<Name_des_dummy>):(open|closed|du_Tageslicht):.*{
soll warscheinlich heißen (der Wert von du_Tageslicht kann 0 oder 100 sein):
(wz_gr_tuer|du_Tageslicht):(open|closed|0|100){
( wz_gr_tuer:(open|closed|0|100) | du_Tageslicht:(open|closed|0|100) ) {
( wz_gr_tuer:(open|closed) | du_Tageslicht:(0|100) ) {
( wz_gr_tuer:(open|closed) | du_Tageslicht:.* ) {
Das wäre also das, was ich bereits implementiert hätte.
Meine Idee:
Ich versuche die ganze Zeit mit einem +,? etc als präfix zu arbeiten. Das habe ich bereits in der readinggroups getan, wodurch man die verschiedenen internals, readings, attributes auseinanderhalten konnte
Das <Name_des_dummy> musst du durch den Namen deines Dummy ersetzen.
Ich hätte den gerne für dich eingesetzt aber ich hab den Namen nicht gefunden.
Edith: Sinnvolle Namensgebung setze ich mal voraus ;)
An Puschel74:
Das habe ich auch schon so verstanden. Der Name des Dummy lautet du_Tageslicht.
Wenn ich den so einsetze, und die Syntax anpasse, dann kommt die von mir verfasste Rechnung zum gleichen Ergebnis, welches ich bereits implementiert habe.
Und das:
(wz_gr_tuer|du_Tageslicht):(open|closed).*:.*{
Mit dem regexp musst du noch spielen -
es kann (und wird vermutlich auch) sein das der .* VOR dem : noch mit einem | in die Klammer muss.Blödsinn - dann triggert das regexp ja wieder auf jedes Event.
Gib dem Dummy doch ein Reading und nimm dieses in das regexp mit auf - das wäre einfacher und würde auch eher klappen.
Edith: Aus dem
set du_Tageslicht
muss dann ein
setreading du_Tageslicht <Name_des_Reading> Wert
werden.
Und aus dem regexp dann ein
(wz_gr_tuer|du_Tageslicht):(open|closed|<Name_des_Reading_von_du_Tageslicht>).*{
Edith:
Zitatsoll warscheinlich heißen (der Wert von du_Tageslicht kann 0 oder 100 sein):
Nö, das heisst nur das du_Tageslicht irgendwas schickt - egal was.
Das kann auch on oder Wupp oder 27 sein.
Ich schlag aber mal vor du stellst einen Code-Zustand her auf dessen Ebene wir hier weiter helfen können und postest diesen auch bitte.
OK, jetzt kommen wir der Sache schon sehr viel näher. Den Gedanken kann ich nachvollziehen.
Problem:
Das "set" kommt bei mir aus einer sub-Methode(Perlcode), welches natürlich für das "Allgemeine" programmiert ist und deshalb nicht einfach so in "setirgendetwasanderes" verändert werden kann. Grund sind die Rolloaktoren, welche mit dem Kommando "set" gefahren werden.
Frage:
Kann ich einem Rolloaktor (HM-LC-Bl1PBU-FM) mehrere eigene readings verpassen?
Grund für meine Frage ist, dass ich nicht weiß, wie ich den Satz:
ZitatGib dem Dummy doch ein Reading und nimm dieses in das regexp mit auf - das wäre einfacher und würde auch eher klappen.
umsetzen kann. Ich muss mich also ersteinmal belesen.
Zum Verständnis hier meine Funktion, welches das Notify erzeugt:
################################################################################
### Rollosteuerung #############################################################
################################################################################
sub makeAutoRolloAts() {
Log(3,"Rebuild all at_autoRolloXX to control the window-shutters!");
fhem("delete at_autoRollo.");
if (Value("du_xx_ro_auto") eq "an"){
my $upTime = "{sunrise(0,\"06:00\",\"07:30\")}";
my $downTime = "{sunset(0,\"18:00\",\"22:00\")}";
my @devices = (#["wz_ro_tuer",Value("du_wz_ro_auto"),Value("du_wz_ro_schatten"),Value("du_wz_ro_hoch"),Value("du_wz_ro_runter"),"ost"],
["wz_ro_essecke",Value("du_wz_ro_auto"),Value("du_wz_ro_schatten"),Value("du_wz_ro_hoch"),Value("du_wz_ro_runter"),"ost"],
["wz_ro_sofa",Value("du_wz_ro_auto"),Value("du_wz_ro_schatten"),Value("du_wz_ro_hoch"),Value("du_wz_ro_runter"),"ost"],
["ke_ro",Value("du_ke_ro_auto"),Value("du_ke_ro_schatten"),Value("du_ke_ro_hoch"),Value("du_ke_ro_runter"),"ost"],
["kz_ro",Value("du_kz_ro_auto"),Value("du_kz_ro_schatten"),Value("du_kz_ro_hoch"),Value("du_kz_ro_runter"),"west"],
["ba_ro",Value("du_ba_ro_auto"),Value("du_ba_ro_schatten"),Value("du_ba_ro_hoch"),Value("du_ba_ro_runter"),"west"],
["ku_ro",Value("du_ku_ro_auto"),Value("du_ku_ro_schatten"),Value("du_ku_ro_hoch"),Value("du_ku_ro_runter"),"west"],
["du_Tageslicht","auto","aus","auto","auto",""]
);
# alle rolladen, welche keine automatik aktiviert haben löschen
for (my $index = 0; $index < @devices;){
if ( $devices[$index][1] eq "aus" ){
splice(@devices,$index,1); # lösche device
}else{
if ( $devices[$index][3] eq "auto" ) { $devices[$index][3] = $upTime; }
if ( $devices[$index][4] eq "auto" ) { $devices[$index][4] = $downTime; }
$index++;
}
}
my @devicesUp = @devices; # copy to remove used devices
my @devicesDown = @devices; # copy to remove used devices
my @events; # list of all events for fhem
my $eventsCounter = -1; # how many events are existing in the list
my $currentTime;
# Events zum Hochfahren erstellen
while(@devicesUp > 0){
$currentTime = $devicesUp[0][3];
# füge alle mit gleicher "hoch" Zeit als ein Event hinzu
push(@events,[$currentTime]);
$eventsCounter++;
for (my $index = 0; $index < @devicesUp;){
if ($devicesUp[$index][3] eq $currentTime){
# Beschattung berücksichtigen
if ($devicesUp[$index][5] eq "ost" && $devicesUp[$index][2] ne "aus"){
push($events[$eventsCounter],"set ".$devicesUp[$index][0]." ".getAbsPosRollo($devicesUp[$index][0],$devicesUp[$index][2]));
}else{
# Beschattung ist "aus"
push($events[$eventsCounter],"set ".$devicesUp[$index][0]." 100");
}
splice(@devicesUp,$index,1); #lösche das aktuell hinzugefügte Rollo aus der Liste
}else{
$index++;
}
}
# Rest der Liste($devicesUp) hat andere Zeit zum hochfahren
}
# Events zum Herunterfahren erstellen
while(@devicesDown > 0){
$currentTime = $devicesDown[0][4];
# füge alle mit gleicher "herunter" Zeit als ein Event hinzu
push(@events,[$currentTime]);
$eventsCounter++;
for (my $index = 0; $index < @devicesDown;){
if ($devicesDown[$index][4] eq $currentTime){
push($events[$eventsCounter],"set ".$devicesDown[$index][0]." 0");
splice(@devicesDown,$index,1); #lösche das aktuell hinzugefügte Rollo aus der Liste
}else{
$index++;
}
}
# Rest der Liste($devicesDown) hat spezielle Zeit zum herunterfahren
}
# Event zum Beschattungswechsel erstellen
for (my $index = 0; $index < @devices;){
if ( $devices[$index][2] eq "aus" ){
splice(@devices,$index,1); # lösche device
}else{
$index++;
}
}
if (@devices > 0){
push(@events,["12:00"]);
$eventsCounter++;
foreach my $currentDevice (@devices) {
if (@$currentDevice[5] eq "ost") {
push($events[$eventsCounter],"set ".@$currentDevice[0]." 100");
}else{
push($events[$eventsCounter],"set ".@$currentDevice[0]." ".getAbsPosRollo(@$currentDevice[0],@$currentDevice[2]));
}
}
}
# erstelle alle events als at
$eventsCounter = 0;
foreach my $currentEvent (@events){
$currentTime = shift(@$currentEvent);
fhem( "define at_autoRollo".$eventsCounter." at *".$currentTime." ".(join(";; ",@$currentEvent)."\n") );
$eventsCounter++;
}
fhem ("attr at_autoRollo. group Rolladensteuerung");
fhem ("attr at_autoRollo. room Server");
}
fhem ("save");
}
Mit setreading kannst du jedem Device eigene Readings zuweisen und diese mit <Wert> füllen.
Versuch macht kluch ;)
Mit ReadingsVal kannst du diese Readings auch wieder auslesen und weiter verarbeiten.
Edith: Auch ein Dummy darf Readings haben - und nicht nur einen state.
Diesen kannst du aber mit stateFormat beeinflussen.
Edith1: Grad getestet - setreading löst ja kein Event aus. Was ja logisch ist und auch so gedacht ist ::)
Mist - tut mir leid aber ich lag mit meiner Idee leider daneben :-[
Jetzt wo du es mir sagst - kann ich mich wage dran erinnern, dass ich damit einmal herumgespielt habe um die Beschattungsposition in die Aktoren zu bekommen.
Hab' ich gerade auch ein wenig mit herumgedoktort, das Ergebnis bleibt ersteinmal gleich.
Weiterführung:
Das Problem liegt ein wenig versteckter: Die ReadingGroup mit dem Namen rg_Rollosteuerung.
Das hätten wir auch aus dem eventlog ganz am Anfang sehen können.
Sowol der Dummy du_Tageslicht als auch die ReadingGroup rg_Rollosteuerung, welche den state des du_Tageslicht beinhaltet, lösen ein Event aus, welches den gleichen Namen hat.
2015-09-11 20:07:33 readingsGroup rg_Rollosteuerung du_Tageslicht: 0
2015-09-11 20:07:33 dummy du_Tageslicht 0
Mein Versuch wird sein, das notify dahingehend zu ändern, dass ich die erste Zeile abänder in genau den String, welcher im Eventmonitor auftaucht und berücksichtigt werden soll:
wz_gr_tuer:(open|closed)|du_Tageslicht:.*{ #ändern in wz_gr_tuer:(open|closed)|dummy du_Tageslicht:.*{
if (Value("du_xx_ro_auto") eq "an"){
if (Value("wz_gr_tuer") eq "closed" && Value("du_Tageslicht") == 0){
fhem "set wz_ro_tuer 0"
} elsif (Value("wz_gr_tuer") eq "open" && Value("wz_ro_tuer") ne "offen"){
fhem "set wz_ro_tuer 100"
}
}
}
Zitat von: Puschel74 am 11 September 2015, 20:42:43
Einmal ist es die RG und einmal der Dummy.
Hab ich aber geschrieben :P
Zitat von: Puschel74 am 11 September 2015, 22:35:39
Hab ich aber geschrieben :P
Schön - hab' ich wohl ganz schnell gelesen - zu schnell um es zu verarbeiten!
Zusammenfassung:
Das notify reagiert ungewollt auf zwei events, welche Zeitgleich erscheinen. Deshalb wird etwas zweimal ausgeführt, was unnötig ist (Stichwort DutyCycle, Rechenzeit etc).
Auf die Markierten Stellen reagiert das notify (Platzhalter ist extra unterstrichen)
du_Tageslicht:.*
2015-09-11 20:07:33 readingsGroup rg_Rollosteuerung du_Tageslicht
: 02015-09-11 20:07:33 dummy du_Tageslicht
0 Die Lösung:
Ich habe das notify dahingehend geändert, dass ich jedes Event expliziet angebe (keine Platzhalter) und mit "oder" verknüpfe. Ohne den Platzhalter rutscht der "dumme" Doppelpunkt nun zum Glück durch.
wz_gr_tuer:open|wz_gr_tuer:closed|du_Tageslicht:0|du_Tageslicht:100 {
2015-09-11 20:07:33 readingsGroup rg_Rollosteuerung du_Tageslicht: 0
2015-09-11 20:07:33 dummy du_Tageslicht 0