Save config
Bad
Büro Franz
Büro Marianne
Dachstudio
Diele
Esszimmer
GoogleAssistant
Heizungsraum
Keller Süd
Küche
MQTT2_DEVICE
PV
Schlafzimmer
Unsorted
Vorratskeller
WC
Wohnzimmer
_Extern
_FS20
_Heizung
_Homematic
_Logs
_Presence
_Raspi
_Rollos
Everything
Logfile
Commandref
Remote doc
Edit files
Select style
Event monitor
############################################## # $Id: myUtilsTemplate.pm 7570 2015-01-14 18:31:44Z rudolfkoenig $ # # Save this file as 99_myUtils.pm, and create your own functions in the new # file. They are then available in every Perl expression. package main; use strict; use warnings; use POSIX; sub fhUtils_Initialize($$) { my ($hash) = @_; } # Enter you functions below _this_ line. my %this; my $RolloCount=0; my $RepeatActorCount=0; sub SecondsSinceMidnight2TimeOfDay($) { my ($Seconds)=@_; my $ToD=sprintf("%02d:%02d:%02d",$Seconds/3600,($Seconds/60)%60,$Seconds%60); return $ToD; } sub TimeOfDay2SecondsSinceMidnight($) { my ($ToD)=@_; my ($h,$m,$s) = split(":", $ToD); $m = 0 if(!$m); $s = 0 if(!$s); my $SsM = 3600*($h%24)+60*$m+$s; return $SsM; } ########################################################## # Move a roller shutter to an absolute position. # # Arguments: # Rollo: Device name of the UNIRoll roller shutter. # SecsToClose: Seconds to close. # SecsToOpen: Seconds to open. # TargetPos: Target position ("up" or "down"). # TargetPerc: Percent of target position to be moved to. # # The shutter will first move to the target position, then # wait the maximum time needed to reach this position and # then move back to the given percentage. Example: # TargetPos="down", TargetPerc=75 -> shutter will start to # move down, wait for SecsToClose and then move up for # (100-75)=25% of SecsToOpen. sub RollerShutterMoveAbs($$$$$) { my ($Rollo,$SecsToClose,$SecsToOpen,$TargetPos,$TargetPerc) = @_; my $RolloType=InternalVal($Rollo,"TYPE",""); my $CmdDown=($RolloType eq "FS20")?"off":($RolloType eq "CUL_HM")?"off":"down"; my $CmdUp=($RolloType eq "FS20")?"on":($RolloType eq "CUL_HM")?"on":"up"; my $InternalTargetPos=$TargetPos; if (($RolloType eq "FS20") || ($RolloType eq "CUL_HM")) { $InternalTargetPos=($TargetPos eq "up")?"on":($TargetPos eq "down")?"off":"Hilfe"; } if ($TargetPerc<100) { if ($TargetPos eq "up") { my $ReboundTime=$SecsToOpen+$SecsToClose*(100-$TargetPerc)/100; fhem("define ".$Rollo."_1_at at +".SecondsSinceMidnight2TimeOfDay($SecsToOpen)." set ".$Rollo." $CmdDown"); fhem("define ".$Rollo."_2_at at +".SecondsSinceMidnight2TimeOfDay($ReboundTime)." set ".$Rollo." stop"); } elsif ($TargetPos eq "down") { my $ReboundTime=$SecsToClose+$SecsToOpen*(100-$TargetPerc)/100; fhem("define ".$Rollo."_1_at at +".SecondsSinceMidnight2TimeOfDay($SecsToClose)." set ".$Rollo." $CmdUp"); fhem("define ".$Rollo."_2_at at +".SecondsSinceMidnight2TimeOfDay($ReboundTime)." set ".$Rollo." stop"); } } else { # Fully close or open -> repeat command to make sure it's executed. fhem("define ".$Rollo."_1_at at +".SecondsSinceMidnight2TimeOfDay($SecsToOpen+30)." set ".$Rollo." ".$InternalTargetPos); } $this{$Rollo}{"Pos"}=$TargetPos; $this{$Rollo}{"Perc"}=$TargetPerc; fhem("set ".$Rollo." ".$InternalTargetPos); } ########################################################## # Move a roller shutter to a position defined by the relative # opening. # # Arguments: # Rollo: Device name of the UNIRoll roller shutter. # SecsToClose: Seconds to close. # SecsToOpen: Seconds to open. # TargetOpeningPerc: Percent of opening to be moved to. # 0 --> closed. # 100 --> open. # Between --> partly open; it will move for a certain time, # depending on the current and the target opening and on # the closing and opening times. # sub RollerShutterMoveRel($$$$) { my ($Rollo,$SecsToClose,$SecsToOpen,$TargetOpeningPerc) = @_; my $RolloType=InternalVal($Rollo,"TYPE",""); my $CmdDown=($RolloType eq "FS20")?"off":($RolloType eq "CUL_HM")?"off":"down"; my $CmdUp=($RolloType eq "FS20")?"on":($RolloType eq "CUL_HM")?"on":"up"; my $CmdStop="stop"; my $OldOpeningPerc=$this{$Rollo}{"OpeningPerc"}; # if ($TargetOpeningPerc<=0) { fhem("set ".$Rollo." ".$CmdDown); } elsif ($TargetOpeningPerc>=100) { fhem("set ".$Rollo." ".$CmdUp); } else { my $diffPerc=($TargetOpeningPerc-$OldOpeningPerc); my $SecsToMove=0; my $CmdStart=$CmdStop; if ($diffPerc > 0) { $SecsToMove=($SecsToOpen*$diffPerc)/100; $CmdStart=$CmdUp; } elsif ($diffPerc < 0) { $SecsToMove=-($SecsToClose*$diffPerc)/100; $CmdStart=$CmdDown; } $SecsToMove=int($SecsToMove); if ($SecsToMove != 0) { fhem("define ".$Rollo."_1_at at +".SecondsSinceMidnight2TimeOfDay($SecsToMove)." set ".$Rollo." ".$CmdStop); fhem("set ".$Rollo." ".$CmdStart); } else { $TargetOpeningPerc=$OldOpeningPerc; } } $this{$Rollo}{"OpeningPerc"}=$TargetOpeningPerc; } ########################################################## # Control a UNIRoll roller shutter. # If there are calls for several devices, the set commands # will be done with a time offset of 2 seconds. # The time to open or close is taken from the rMin and rMax # attributes of the UNIRoll device. # # Arguments: # Rollo: Device name of the UNIRoll roller shutter. # Mode: 0: Dont move. 1: close at night, open all day. 2: 1 + shadow to cool. 3: 2 + open all night if cooling required. 4: Dont move at night, shadow to cool. # MorningTime: Time of day when day begins. # EveningTime: Time of day when night begins. # CoolingBeginTime: Time of day when cooling by shadowing begins. # CoolingEndTime: Time of day when cooling by shadowing ends. # CoolingGoal: The desired temperature difference to be reached by cooling. Positive values to cool, negative to heat. sub RollerShutterAuto($$$$$$$) { my ($Rollo,$Mode,$MorningTime,$EveningTime,$CoolingBeginTime,$CoolingEndTime,$CoolingGoal) = @_; # To avoid overflow in CUL, each Rollo gets an index to be used for a time offset. my $RolloIndex = $this{$Rollo}{"Index"}; if (!defined $RolloIndex) { $RolloIndex=$RolloCount; $RolloCount+=1; $this{$Rollo}{"Index"}=$RolloIndex; $this{$Rollo}{"OpeningPerc"}=101; } if ($Mode==0) { return; } my $OldOpeningPerc=$this{$Rollo}{"OpeningPerc"}; my $TargetOpeningPerc=$OldOpeningPerc; Log 4, "RollerShutterAuto($Rollo,$Mode,$MorningTime,$EveningTime,$CoolingBeginTime,$CoolingEndTime,$CoolingGoal)"; if (Value("VtAlleRollos") eq "auto") { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(); my $NowSsM=$hour*3600+$min*60+$sec; my $MorningTimeSsM=TimeOfDay2SecondsSinceMidnight($MorningTime); my $EveningTimeSsM=TimeOfDay2SecondsSinceMidnight($EveningTime); my $CoolingBeginTimeSsM=TimeOfDay2SecondsSinceMidnight($CoolingBeginTime); my $CoolingEndTimeSsM=TimeOfDay2SecondsSinceMidnight($CoolingEndTime); if (!defined($CoolingGoal)) { $CoolingGoal=0; } #Log 4, "SsM=$NowSsM, MorningTime=$MorningTime=".$MorningTimeSsM."s, EveningTime=$EveningTime=".$EveningTimeSsM."s"; if ($Mode==1) { # Simple time driven mode. if ($NowSsM>=$MorningTimeSsM && $NowSsM<$EveningTimeSsM) { $TargetOpeningPerc=100; } else { $TargetOpeningPerc=0; } } elsif (($Mode==2 || $Mode==3 || $Mode==4) && $NowSsM>=$CoolingBeginTimeSsM && $NowSsM<$CoolingEndTimeSsM && $CoolingGoal>0) { # It's shadowing time. $TargetOpeningPerc=100-minNum(80,20*$CoolingGoal); } elsif (($Mode==4) && $NowSsM>=$CoolingEndTimeSsM && $NowSsM<$CoolingEndTimeSsM+14*60) { # It's end of shadowing time --> close fully for short time to prevent wasp nesting. $TargetOpeningPerc=0; } elsif (($Mode==4) && $NowSsM>=$CoolingEndTimeSsM && $NowSsM<$CoolingEndTimeSsM+20*60) { # It's end of shadowing time --> open fully. $TargetOpeningPerc=100; } elsif ($Mode==2 || $Mode==3) { if ($NowSsM>=$MorningTimeSsM && $NowSsM<$EveningTimeSsM) { # It's daytime without shadowing. $TargetOpeningPerc=100; } else { # It's night. if ($Mode==3) { $TargetOpeningPerc=(20+minNum(80,20*$CoolingGoal)); } else { $TargetOpeningPerc=0; } } } } elsif (Value("VtAlleRollos") eq "up") { $TargetOpeningPerc=100; } elsif (Value("VtAlleRollos") eq "down") { $TargetOpeningPerc=0; } elsif (Value("VtAlleRollos") eq "stop") { } if ($TargetOpeningPerc > 100) { $TargetOpeningPerc=100; } elsif ($TargetOpeningPerc < 0) { $TargetOpeningPerc=0; } $TargetOpeningPerc=int($TargetOpeningPerc); if ($TargetOpeningPerc != $OldOpeningPerc) { my $SecsToClose=AttrVal($Rollo,'rMax',19); my $SecsToOpen=AttrVal($Rollo,'rMin',20); Log 3, "RollerShutterAuto($Rollo,$Mode,$MorningTime,$EveningTime,$CoolingBeginTime,$CoolingEndTime,$CoolingGoal) --> RollerShutterMoveRel('$Rollo',$SecsToClose,$SecsToOpen,$OldOpeningPerc --> $TargetOpeningPerc)"; fhem("define ".$Rollo."_Move_at at +".SecondsSinceMidnight2TimeOfDay($RolloIndex*2)." {RollerShutterMoveRel('$Rollo',$SecsToClose,$SecsToOpen,$TargetOpeningPerc)}"); } } ########################################################## # Repeat setting an actor like an InterTechno switch. # The current value of the actor will be set again. # If there are calls for several devices, the set commands # will be done with a time offset of 3 seconds. # # Arguments: # DeviceName: Device name of the actor. sub RepeatActor($) { my ($DeviceName) = @_; # To avoid overflow in CUL, each actor gets an index to be used for a time offset. my $RepeatActorIndex = $this{$DeviceName}{"Index"}; if (!defined $RepeatActorIndex) { $RepeatActorIndex=$RepeatActorCount; $RepeatActorCount+=1; $this{$DeviceName}{"Index"}=$RepeatActorIndex; } Log 4, "RepeatActor($DeviceName)"; if (Value($DeviceName) ne "???") { fhem("define ".$DeviceName."_Repeat_at at +".SecondsSinceMidnight2TimeOfDay($RepeatActorIndex*3)." set ".$DeviceName." ".Value($DeviceName)); } } ########################################################## # Get current roller shutter opening in percent. # # Arguments: # Rollo: Device name of the UNIRoll roller shutter. # sub GetOpeningPerc($) { my ($Rollo) = @_; return $this{$Rollo}{"OpeningPerc"}; } ########################################################## # Get sunrise time limited by a minimum and maximum time. # The sunrise function from SUNRISE_EL is used. # # Arguments: # Horizon: The horizon argument from sunrise(). # Offset: The time offset argument from sunrise(). # LowerLimit: The earliest time of day to be returned. # UpperLimit: The latest time of day to be returned. # sub sunrise_limited($$$$) { my ($Horizon,$Offset,$LowerLimit,$UpperLimit) = @_; my $t1=TimeOfDay2SecondsSinceMidnight(sunrise($Horizon,$Offset)); my $tMin=TimeOfDay2SecondsSinceMidnight($LowerLimit); my $tMax=TimeOfDay2SecondsSinceMidnight($UpperLimit); my $tLim=maxNum($tMin,minNum($tMax,$t1)); my $ToD=SecondsSinceMidnight2TimeOfDay($tLim); return $ToD; } ########################################################## # Execute one of several given Perl expressions. The Perl # expressions are given in a hash with an event name as # key. The event name of the command to be executed is # provided as the first argument. # # Arguments: # Event: The event name of the command to be executed. # Commands: A hash table containing an event name as key # and a Perl expression to be executed. # # Example: # define SystemCommandsNotify notify (SystemCommands) {\ # eval_switched($EVENT,(\ # "Ausschalten" => "system('sudo shutdown now')",\ # "Neustarten" => "system 'sudo reboot'",\ # "Aktualisieren" => "system 'svn up';;fhem 'shutdown restart'"\ # ))} # sub eval_switched($%) { my ($Event,%Commands) = @_; my $Command = $Commands{$Event}; Log 3, "eval_switched($Event): Command=$Command"; eval $Command; } 1;