diff --git a/fhem/FHEM/98_Heating_Control.pm b/fhem/FHEM/98_Heating_Control.pm index 3a4780aa9..5018a8a67 100644 --- a/fhem/FHEM/98_Heating_Control.pm +++ b/fhem/FHEM/98_Heating_Control.pm @@ -28,8 +28,7 @@ use warnings; use POSIX; ##################################### -sub -Heating_Control_Initialize($) +sub Heating_Control_Initialize($) { my ($hash) = @_; @@ -38,12 +37,11 @@ Heating_Control_Initialize($) $hash->{UndefFn} = "Heating_Control_Undef"; $hash->{GetFn} = "Heating_Control_Get"; $hash->{UpdFn} = "Heating_Control_Update"; - $hash->{AttrList}= "disable:0,1 ". + $hash->{AttrList}= "disable:0,1 windowSensor ". $readingFnAttributes; } - -sub -Heating_Control_Get($@) +################################################################################ +sub Heating_Control_Get($@) { my ($hash, @a) = @_; return "argument is missing" if(int(@a) != 2); @@ -60,39 +58,60 @@ Heating_Control_Get($@) } return "$a[0] $reading => $value"; } - - -sub -Heating_Control_Define($$) +################################################################################ +sub Heating_Control_Define($$) { my ($hash, $def) = @_; + my %longDays = ( "de" => ["Sonntag", "Montag","Dienstag","Mittwoch", "Donnerstag","Freitag", "Samstag" ], + "en" => ["Sunday", "Monday","Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], + "fr" => ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi","Samedi" ]); + my %shortDays = ( "de" => ["so","mo","di","mi","do","fr","sa"], + "en" => ["su","mo","tu","we","th","fr","sa"], + "fr" => ["di","lu","ma","me","je","ve","sa"]); + my @a = split("[ \t]+", $def); - return "Usage: define $hash->{TYPE} " + return "Usage: define $hash->{TYPE} " if(@a < 4); my $name = shift @a; my $type = shift @a; my $device = shift @a; + my @switchingtimes; my $conditionOrCommand = ""; - my @Wochentage_de = ("Sonntag", "Montag","Dienstag","Mittwoch", "Donnerstag","Freitag", "Samstag" ); - my @Wochentage_en = ("Sunday", "Monday","Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"); - my @Wochentage_fr = ("Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi","Samedi"); + # ggf. language optional Parameter + my $language = shift @a; + my $langRegExp = "("; + foreach my $l (keys(%shortDays)) { + $langRegExp .= $l . "|"; + } + $langRegExp =~ s/\|$//g; + $langRegExp .= ")"; + if ($language =~ m/^$langRegExp$/g) { + $hash->{LANGUAGE} = $language; + } else { + Log3 $hash, 3, "[$name] illegal language: $language, use one of $langRegExp" if (length() == 2); + unshift (@a,$language) if (length($language) != 2) ; + $hash->{LANGUAGE} = "de"; + } + $language = $hash->{LANGUAGE}; + # test if device is defined return "invalid Device, given Device <$device> not found" if(!$defs{$device}); #Altlasten bereinigen + delete($hash->{TIME_AS_PERL}) if($hash->{TIME_AS_PERL}); delete($hash->{helper}{CONDITION}) if($hash->{helper}{CONDITION}); delete($hash->{helper}{COMMAND}) if($hash->{helper}{COMMAND}); delete($hash->{helper}{SWITCHINGTIMES}) if($hash->{helper}{SWITCHINGTIMES}); delete($hash->{helper}{SWITCHINGTIME}) if($hash->{helper}{SWITCHINGTIME}); - for (my $w=0; $w<@Wochentage_de; $w++) { - delete($hash->{"PROFILE ".($w).": ".$Wochentage_de[$w]}) if($hash->{"PROFILE ".($w).": ".$Wochentage_de[$w]}); - delete($hash->{"PROFILE ".($w).": ".$Wochentage_en[$w]}) if($hash->{"PROFILE ".($w).": ".$Wochentage_en[$w]}); - delete($hash->{"PROFILE ".($w).": ".$Wochentage_fr[$w]}) if($hash->{"PROFILE ".($w).": ".$Wochentage_fr[$w]}); + foreach my $l (keys(%shortDays)) { + for (my $w=0; $w<7; $w++) { + delete($hash->{"PROFILE ".($w).": ".$longDays{$l}[$w]}) if($hash->{"PROFILE ".($w).": ".$longDays{$l}[$w]}); + } } for(my $i=0; $i<@a; $i++) { @@ -107,6 +126,8 @@ Heating_Control_Define($$) last; } } + # wenn keine switchintime angegeben ist, dann Fehler + Log3 $hash, 3, "no Switchingtime found in <$conditionOrCommand>, check first parameter" if (@switchingtimes == 0); $hash->{NAME} = $name; $hash->{DEVICE} = $device; @@ -118,30 +139,58 @@ Heating_Control_Define($$) $hash->{helper}{COMMAND} = $conditionOrCommand; } - my $daysRegExp = "(mo|di|mi|do|fr|sa|so|tu|we|th|su|lu|ma|me|je|ve)"; - my $daysRegExp_en = "(tu|we|th|su)"; - my $daysRegExp_fr = "(lu|ma|me|je|ve)"; + # jetzt die switchingtimes und Tagesangaben verarbeiten. + Heating_Control_ParseSwitchingProfile($hash, \@switchingtimes, \$shortDays{$language}); + + # Profile sortiert aufbauen + for (my $d=0; $d<=6; $d++) { + foreach my $st (sort (keys %{ $hash->{helper}{SWITCHINGTIME}{$d} })) { + my $para = $hash->{helper}{SWITCHINGTIME}{$d}{$st}; + $hash->{"PROFILE ".($d).": ".$longDays{$language}[$d]} .= sprintf("%s %s, ", substr ($st,0,5), $para); + } + } + + RemoveInternalTimer($hash); + my $now = time(); + InternalTimer ($now+30, "$hash->{TYPE}_Update", $hash, 0); + + if (defined($hash->{TIME_AS_PERL})) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now); + my $midnight = $now + 24*3600 -(3600*$hour + 60*$min + $sec) + 10*60; + InternalTimer ($midnight, "$hash->{TYPE}_UpdatePerlTime", $hash, 0); + } + + readingsBeginUpdate ($hash); + readingsBulkUpdate ($hash, "nextUpdate", strftime("Heute, %H:%M:%S",localtime($now+30))); + readingsBulkUpdate ($hash, "nextValue", "???"); + readingsBulkUpdate ($hash, "state", "waiting..."); + readingsEndUpdate ($hash, defined($hash->{LOCAL} ? 0 : 1)); + + return undef; +} +################################################################################ +sub Heating_Control_ParseSwitchingProfile($$$) { + my ($hash, $switchingtimes, $shortDays) = @_; + + my $name = $hash->{NAME}; + my $language = $hash->{LANGUAGE}; my %dayNumber=(); - my $idx = 0; - foreach my $day ("so","mo","di","mi","do","fr","sa") { - $dayNumber{$day} = $idx; $idx++; - } - $idx = 0; - foreach my $day ("su","mo","tu","we","th","fr","sa") { - $dayNumber{$day} = $idx; $idx++; - } - $idx = 0; - foreach my $day ("di","lu","ma","me","je","ve","sa") { - $dayNumber{$day} = $idx; $idx++; + my $daysRegExp = "("; + for(my $idx=0; $idx<7; $idx++) { + my $day = @{$$shortDays}[$idx]; + $dayNumber{$day} = $idx; + $daysRegExp .= $day . "|"; } + $daysRegExp =~ s/\|$//g; + $daysRegExp .= ")"; - my (@st, @days, $daylist, $time, $para, $englisch, $french); - for(my $i=0; $i<@switchingtimes; $i++) { - - @st = split(/\|/, $switchingtimes[$i]); + my (@st, @days, $daylist, $time, $para); + for(my $i=0; $i<@{$switchingtimes}; $i++) { + + @st = split(/\|/, @{$switchingtimes}[$i]); if ( @st == 2) { - $daylist = "1234567"; #jeden Tag/woche ist vordefiniert + $daylist = "1234567"; #jeden Tag/Woche ist vordefiniert $time = $st[0]; $para = $st[1]; } elsif ( @st == 3) { @@ -152,7 +201,8 @@ Heating_Control_Define($$) my %hdays=(); - #Aufzaehlung 1234 ... + # Angaben der Tage verarbeiten + # Aufzaehlung 1234 ... if ( $daylist =~ m/^(\d){0,7}$/g) { $daylist =~ s/7/0/g; @@ -164,19 +214,18 @@ Heating_Control_Define($$) my $oldDay = "", my $oldDel = ""; for (;length($daylist);) { - my $day = substr($daylist,0,2,""); - my $del = substr($daylist,0,1,""); - $englisch = ($day =~ m/^($daysRegExp_en)$/g); - $french = ($day =~ m/^($daysRegExp_fr)$/g); + my $day = substr($daylist,0,2,""); + my $del = substr($daylist,0,1,""); my @subDays; if ($oldDel eq "-" ){ # von bis Angabe: Mo-Di my $low = $dayNumber{$oldDay}; my $high = $dayNumber{$day}; if ($low <= $high) { - @subDays = ($low .. $high); - } else { - @subDays = ($dayNumber{so} .. $high, $low .. $dayNumber{sa}); + @subDays = ($low .. $high); + } else { + #@subDays = ($dayNumber{so} .. $high, $low .. $dayNumber{sa}); + @subDays = ( 00 .. $high, $low .. 06); } @hdays{@subDays}=1; } else { @@ -192,72 +241,129 @@ Heating_Control_Define($$) @days = sort(SortNumber keys %hdays); - return "invalid time in $name <$time> HH:MM" - if(!($time =~ m/^[0-2][0-9]:[0-5][0-9]$/g)); + # Zeitangabe verarbeiten. + if($time =~ m/^\{.*\}$/g) { # Perlausdruck {*} + $time = eval($time); # must deliver HH:MM[:SS] + $hash->{TIME_AS_PERL} = 1; + } + + if ($time =~ m/^[0-2][0-9]:[0-5][0-9]$/g) { # HH:MM + $time .= ":00"; # HH:MM:SS erzeugen + } elsif ($time =~ m/^[0-2][0-9](:[0-5][0-9]){2,2}$/g) { # HH:MM:SS + ; # ok. + } else { + Log3 $hash, 1, "[$name] invalid time in $name <$time> HH:MM[:SS]" + } for (my $d=0; $d<@days; $d++) { - #Log3 $hash, 3, "Switchingtime: $switchingtimes[$i] : $days[$d] -> $time -> $para "; + Log3 $hash, 5, "[$name] Switchingtime: @{$switchingtimes}[$i] : $days[$d] -> $time -> $para "; $hash->{helper}{SWITCHINGTIME}{$days[$d]}{$time} = $para; } } - - my $rWochentage; - if ($englisch) { - $rWochentage = \@Wochentage_en; - } elsif ($french) { - $rWochentage = \@Wochentage_fr; - } else { - $rWochentage = \@Wochentage_de; - } - - # Profile sortiert aufbauen - for (my $d=0; $d<=6; $d++) { - foreach my $st (sort (keys %{ $hash->{helper}{SWITCHINGTIME}{$d} })) { - my $para = $hash->{helper}{SWITCHINGTIME}{$d}{$st}; - $hash->{"PROFILE ".($d).": ".$$rWochentage[$d]} .= sprintf("%s %s, ", $st, $para); - } - } - - RemoveInternalTimer($hash); - my $now = time(); - InternalTimer ($now+30, "$hash->{TYPE}_Update", $hash, 0); - - readingsBeginUpdate ($hash); - readingsBulkUpdate ($hash, "nextUpdate", strftime("Heute, %H:%M:%S",localtime($now+30))); - readingsBulkUpdate ($hash, "nextValue", "???"); - readingsBulkUpdate ($hash, "state", "waiting..."); - readingsEndUpdate ($hash, defined($hash->{LOCAL} ? 0 : 1)); - - return undef; } - -sub -Heating_Control_Undef($$) -{ +################################################################################ +sub Heating_Control_Undef($$) { my ($hash, $arg) = @_; RemoveInternalTimer($hash); delete $modules{$hash->{TYPE}}{defptr}{$hash->{NAME}}; return undef; } - -sub -Heating_Control_Update($) +################################################################################ +sub Heating_Control_UpdatePerlTime($) +{ + my ($hash) = @_; + Heating_Control_Define($hash, $hash->{NAME} . " " . $hash->{TYPE} . " " . $hash->{DEF} ); +} +################################################################################ +sub Heating_Control_Update($) { my ($hash) = @_; + my $mod = "[".$hash->{NAME} ."] "; + my $name = $hash->{NAME}; + my $now = time() + 5; # garantiert > als die eingestellte Schlatzeit + + # Fenserkontakte abfragen - wenn einer im Status closed, dann Schaltung um 60 Sekunden verzögern + if (Heating_Control_FensterOffen($hash)) { + return; + } + # Schaltparameter ermitteln + my ($nowSwitch,$nextSwitch,$aktParam,$newParam,$nextParam) + = Heating_Control_akt_next_param($now, $hash); + # ggf. Device schalten + if ($nowSwitch gt "" && $aktParam ne $newParam ) { + Heating_Control_Device_Schalten($hash, $now, $nowSwitch, $newParam) + } + # Timer und Readings setzen. + InternalTimer ($nextSwitch, "$hash->{TYPE}_Update", $hash, 0); + + my $active = 1; + if (defined $hash->{helper}{CONDITION}) { + $active = eval ($hash->{helper}{CONDITION}); + } + readingsBeginUpdate($hash); + readingsBulkUpdate ($hash, "nextUpdate", strftime("%d.%m.%Y %H:%M:%S",localtime($nextSwitch))); + readingsBulkUpdate ($hash, "nextValue", $nextParam); + readingsBulkUpdate ($hash, "state", $active ? $newParam : "inactive" ); + readingsEndUpdate ($hash, defined($hash->{LOCAL} ? 0 : 1)); + + return 1; +} +################################################################################ +sub Heating_Control_FensterOffen ($) { + my ($hash) = @_; + my $mod = "[".$hash->{NAME} ."]"; + + my %contacts = ( "CUL_FHTTK" => { "READING" => "Window", "STATUS" => "Open" }, + "HM" => { "READING" => "hmw", "STATUS" => "hmo" }, + "MAX" => { "READING" => "maxw", "STATUS" => "maxs"}); + + my $fensterKontakte = AttrVal($hash->{NAME}, "windowSensor", "nF"); + Log3 $hash, 5, "$mod list of windowsenors found: '$fensterKontakte'"; + if ($fensterKontakte ne "nF" ) { + my @kontakte = split(/ /, $fensterKontakte); + foreach my $fk (@kontakte) { + if(!$defs{$fk}) { + Log3 $hash, 3, "$mod Window sensor <$fk> not found - check name."; + } else { + my $fk_hash = $defs{$fk}; + my $fk_typ = $fk_hash->{TYPE}; + if (!defined($contacts{$fk_typ})) { + Log3 $hash, 3, "$mod TYPE '$fk_typ' of $fk not yet supported, $fk ignored - inform maintainer"; + } else { + my $reading = $contacts{$fk_typ}{READING}; + my $status = $contacts{$fk_typ}{STATUS}; + my $windowStatus = ReadingsVal($fk,$reading,"nF"); + if ($windowStatus eq "nF") { + Log3 $hash, 3, "$mod READING '$reading' of $fk not found, $fk ignored - inform maintainer"; + } else { + Log3 $hash, 5, "$mod windowsensor '$fk' Reading '$reading' is '$windowStatus'"; + if ($windowStatus eq $status) { + Log3 $hash, 3, "$mod switch of $hash->{DEVICE} delayed - windowsensor '$fk' Reading '$reading' is '$windowStatus'"; + InternalTimer (time()+60, "$hash->{TYPE}_Update", $hash, 0); + return 1 + } + } + } + } + } + } + return 0; +} +################################################################################ +sub Heating_Control_akt_next_param($$) { + my ($now, $hash) = @_; + my $mod = "[".$hash->{NAME} ."] "; - my $now = time() + 5; # garantiert > als die eingestellte Schlatzeit my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now); my $aktParam = ReadingsVal($hash->{DEVICE}, $hash->{helper}{DESIRED_TEMP_READING}, 0); $aktParam = sprintf("%.1f", $aktParam) if ($aktParam =~ m/^[0-9]{1,3}$/i); my $newParam = $aktParam; #default# - my $nextParam = 0; - my $next = 0; - my $nextSwitch = 0; - my $nowSwitch = 0; + my ($nextParam, $next, $nextSwitch, $nowSwitch) = (0,0,0,0); + # aktuellen und nächsten Schaltzeitpunkt ermitteln. my $startIdx; for (my $d=-1; $d>=-7; $d--) { my $wd = ($d+$wday) % 7; @@ -273,7 +379,8 @@ Heating_Control_Update($) foreach my $st (sort (keys %{ $hash->{helper}{SWITCHINGTIME}{$wd} })) { # Tagediff + Sekunden des Tages addieren - my $secondsToSwitch = $d*24*3600 + 3600*(int(substr($st,0,2)) - $hour) + 60*(int(substr($st,3,2)) - $min ) - $sec; + my @t = split(/:/, $st); # HH MM SS + my $secondsToSwitch = $d*24*3600 + 3600*($t[0] - $hour) + 60*($t[1] - $min) + $t[2] - $sec; my $next = $now + $secondsToSwitch; if ($secondsToSwitch<=10 && $secondsToSwitch>=-20) { @@ -285,30 +392,31 @@ Heating_Control_Update($) $nowSwitch = $next; } else { $nextParam = $hash->{helper}{SWITCHINGTIME}{$wd}{$st}; - $nextParam = sprintf("%.1f", $nextParam) if ($nextParam =~ m/^[0-9]{1,3}$/i); + $nextParam = sprintf("%.1f", $nextParam) if ($nextParam =~ m/^[0-9]{1,3}$/i); $nextSwitch = $next; last; } } } - - my $name = $hash->{NAME}; - my $command; - #$nextSwitch += get_SummerTimeOffset($now, $nextSwitch); - Log3 $hash, 4, $mod .strftime('%d.%m.%Y %H:%M:%S',localtime($nowSwitch))." ; AktDesiredTemp: $aktParam ; newDesTemperature: $newParam"; + Log3 $hash, 4, $mod .strftime('%d.%m.%Y %H:%M:%S',localtime($nowSwitch))." ; aktParam: $aktParam ; newParam: $newParam"; Log3 $hash, 4, $mod .strftime('%d.%m.%Y %H:%M:%S',localtime($nextSwitch)); + return ($nowSwitch,$nextSwitch,$aktParam,$newParam,$nextParam); +} +################################################################################ +sub Heating_Control_Device_Schalten($$$$) { + my ($hash, $now, $nowSwitch, $newParam) = @_; + + my $command = ""; + my $mod = "[".$hash->{NAME} ."] "; #modifier des Zieldevices auswaehlen - my %modifier = ("MAX" => "desiredTemperature", - "FHT" => "desired-temp", - "FS20" => "", - "CUL_HM" => "desired-temp"); + my %modifier = ("MAX"=>"desiredTemperature","FHT"=>"desired-temp","CUL_HM"=>"desired-temp","FS20"=>""); $hash->{helper}{DESIRED_TEMP_READING} = ""; $hash->{helper}{DESIRED_TEMP_READING} = $modifier{$defs{$hash->{DEVICE}}{TYPE}}; - if ($nowSwitch gt "" && $aktParam ne $newParam ) { + #if ($nowSwitch gt "" && $aktParam ne $newParam ) { if (defined $hash->{helper}{CONDITION}) { $command = '{ fhem("set @ '.$hash->{helper}{DESIRED_TEMP_READING}.' %") if' . $hash->{helper}{CONDITION} . '}'; } elsif (defined $hash->{helper}{COMMAND}) { @@ -316,9 +424,11 @@ Heating_Control_Update($) } else { $command = '{ fhem("set @ '.$hash->{helper}{DESIRED_TEMP_READING}.' %") }'; } - } + #} + #Kommando ausführen my $secondsSinceSwitch = $nowSwitch - $now; + # toDo besser eine Positivliste mit Geraeten, die geschaltet werden sollen my %vergangenheitNichtSchalten = ("FS20" => 1); if ($vergangenheitNichtSchalten{$defs{$hash->{DEVICE}}{TYPE}} && $secondsSinceSwitch < -60) { ; @@ -333,24 +443,8 @@ Heating_Control_Update($) Log3 ($hash, 3, $ret) if($ret); } } - - my $active = 1; - if (defined $hash->{helper}{CONDITION}) { - $active = eval ($hash->{helper}{CONDITION}); - } - - RemoveInternalTimer($hash); - InternalTimer($nextSwitch, "$hash->{TYPE}_Update", $hash, 0); - - readingsBeginUpdate($hash); - readingsBulkUpdate ($hash, "nextUpdate", strftime("%d.%m.%Y %H:%M:%S",localtime($nextSwitch))); - readingsBulkUpdate ($hash, "nextValue", $nextParam); - readingsBulkUpdate ($hash, "state", $active ? $newParam : "inactive" ); - readingsEndUpdate ($hash, defined($hash->{LOCAL} ? 0 : 1)); - - return 1; } -# +################################################################################ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()} foreach my $hc ( sort keys %{$modules{Heating_Control}{defptr}} ) { @@ -367,7 +461,7 @@ sub Heating_Control_SetAllTemps() { # {Heating_Control_SetAllTemps()} } Log3 undef, 3, "Heating_Control_SetAllTemps() done!"; } - +################################################################################ sub SortNumber { if($a < $b) { return -1; } @@ -390,7 +484,7 @@ sub SortNumber { Define
    - define <name> Heating_Control <device> <profile> <command>|<condition> + define <name> Heating_Control <device> [<language>] <profile> <command>|<condition>

    to set a weekly profile for <device>, eg. a heating sink.
    @@ -410,14 +504,20 @@ sub SortNumber { The device to switch at the given time.

+

    language
    + Specifies the language used for definition and profiles. + de,en,fr are possible. The parameter is optional. +
+

    profile
    Define the weekly profile. All timings are separated by space. One switchingtime are defined by the following example:
      [<weekdays>|]<time>|<parameter>

    weekdays: optional, if not set every day is using.
    Otherwise you can define one day as number or as shortname.
    - time:define the time to switch, format: HH:MM(HH in 24 hour format)
    - parameter:the temperature to be set, using a float with mask 99.9 or a sybolic value like eco or comfort - whatever your thermostat understands
    + time:define the time to switch, format: HH:MM:[SS](HH in 24 hour format) or a Perlfunction like {sunrise_abs()}
    + parameter:the temperature to be set, using a float with mask 99.9 or a sybolic value like eco or comfort - whatever your thermostat understands. + The symbolic value can be added an additional parameter: dayTemp:16 night-temp:15. See examples

    command
    @@ -450,6 +550,12 @@ sub SortNumber { define HCW Heating_Control WZ_Heizung Sa-Su,We|08:00|21 (ReadingsVal("WeAreThere", "state", "no") eq "yes")
    The temperature is only set if the dummy variable WeAreThere is "yes".

    + + define HCW Heating_Control WZ_Heizung en Su-Fr|{sunrise_abs()}|21 Mo-Fr|{sunset_abs()}|16
    + The device is switched at sunrise/sunset. Language: english. + + define HCW Heating_Control WZ_Heizung en Mo-Fr|{myFunction}|night-temp:18 Mo-Fr|{myFunction()}|dayTemp:16
    + The is switched at time myFunction(). It is sent the Command "night-temp 18" and "dayTemp 16".

@@ -466,7 +572,7 @@ sub SortNumber {
  • event-on-update-reading
  • event-on-change-reading
  • stateFormat
  • -
    +
  • windowSensor
    Defines a list of window sensors. When one of its window state readings is open the aktual switch is delayed.

  • =end html @@ -480,7 +586,7 @@ sub SortNumber { Define
      - define <name> Heating_Control <device> <profile> <command>|<condition> + define <name> Heating_Control <device> [<language>] <profile> <command>|<condition>

      Bildet ein Wochenprofil für ein <device>, zb. Heizkörper, ab.
      @@ -496,7 +602,12 @@ sub SortNumber {

      Folgende Parameter sind im Define definiert:

        device
        - Das an den Schaltpunkten zu schaltende Device. + Name des zu schaltenden Device. +
      +

      +

        language
        + Spezifiziert die Sprache für die Definition und die Anzeige der Profile in der Weboberfläche. + Zurzeit sind de,en,fr definiert. Der Parameter ist optional.

        profile
        @@ -506,9 +617,10 @@ sub SortNumber { Wochentage: optionale Angabe, falls nicht gesetzt wird der Schaltpunkt jeden Tag ausgeführt. Für die Tage an denen dieser Schaltpunkt aktiv sein soll, ist jeder Tag mit seiner Tagesnummer (Mo=1, ..., So=7) oder Name des Tages (Mo, Di, ..., So) einzusetzen.
        - Uhrzeit:Angabe der Uhrzeit an dem geschaltet werden soll, Format: HH:MM(HH im 24 Stunden format)
        + Uhrzeit:Angabe der Uhrzeit zu der geschaltet werden soll, Format: HH:MM:[SS](HH im 24 Stunden Format) oder eine Perlfunction wie {sunrise_abs()}
        Parameter:Angabe der zu setzenden Temperatur als Zahl mit Format 99.9 oder als symbolische Konstante eco - or comfort - was immer das Heizkörperthermostat versteht.
        + or comfort - was immer das Heizkörperthermostat versteht. + Symbolischen Werten kann ein zusätzlicher Parameter angehängt werden: dayTemp:16 night-temp:15. Unten folgen Beispiele

        command
        @@ -532,7 +644,7 @@ sub SortNumber {

        Beispiel:

          - define HCB Heating_Control Bad_Heizung 12345|05:20|21 12345|05:25|comfort 17:20|21 17:25|eco
          + define HCW Heating_Control Bad_Heizung 12345|05:20|21 12345|05:25|comfort 17:20|21 17:25|eco
          Mo-Fr wird die Temperatur um 05:20Uhr auf 21°C, und um 05:25Uhr auf comfort gesetzt. Jeden Tag wird die Temperatur um 17:20Uhr auf 21°C und 17:25Uhr auf eco gesetzt.

          @@ -542,6 +654,13 @@ sub SortNumber { define HCW Heating_Control WZ_Heizung Sa-So,Mi|08:00|21 (ReadingsVal("WeAreThere", "state", "no") eq "yes")
          Die zu setzende Temperatur wird nur gesetzt, falls die Dummy Variable WeAreThere = "yes" ist.

          + + define HCW Heating_Control WZ_Heizung en Su-Fr|{sunrise_abs()}|21 Mo-Fr|{sunset_abs()}|16
          + Das Gerät wird bei Sonnenaufgang und Sonnenuntergang geschaltet. Sprache: Englisch. + + define HCW Heating_Control WZ_Heizung en Mo-Fr|{myFunction}|night-temp:18 Mo-Fr|{myFunction()}|dayTemp:16
          + Das Gerät wird bei myFunction() geschaltet. Es wird das Kommando "night-temp 18" bzw. "dayTemp 16" gesendet. +

      @@ -558,6 +677,7 @@ sub SortNumber {
    • event-on-update-reading
    • event-on-change-reading
    • stateFormat
    • +
    • windowSensor
      Definiert eine Liste mit Fensterkontakten. Wenn das Reading window state eines Fensterkontakts open ist, wird der aktuelle Schaltvorgang verzögert.

    diff --git a/fhem/FHEM/98_WeekdayTimer.pm b/fhem/FHEM/98_WeekdayTimer.pm index c800a82a0..ae13b2d2a 100644 --- a/fhem/FHEM/98_WeekdayTimer.pm +++ b/fhem/FHEM/98_WeekdayTimer.pm @@ -32,6 +32,11 @@ WeekdayTimer_Initialize($) { my ($hash) = @_; + if(!$modules{Heating_Control}{LOADED} && -f "$attr{global}{modpath}/FHEM/98_Heating_Control.pm") { + my $ret = CommandReload(undef, "98_Heating_Control"); + Log3 undef, 1, $ret if($ret); + } + # Consumer $hash->{DefFn} = "WeekdayTimer_Define"; $hash->{UndefFn} = "WeekdayTimer_Undef"; @@ -62,6 +67,14 @@ WeekdayTimer_Undef($$){ return Heating_Control_Undef($hash, $arg); } +sub +WeekdayTimer_UpdatePerlTime($) +{ + my ($hash) = @_; + + Heating_Control_Define($hash, $hash->{NAME} . " " . $hash->{TYPE} . " " . $hash->{DEF} ); +} + sub WeekdayTimer_Update($){ my ($hash) = @_; @@ -80,7 +93,9 @@ sub WeekdayTimer_SetAllTemps() { # {WeekdayTimer_SetAllTemps()} } } WeekdayTimer_Update($hash); + Log3 undef, 3, "WeekdayTimer_Update() for $hash->{NAME} done!"; } + Log3 undef, 3, "WeekdayTimer_SetAllTemps() done!"; } 1;