From b15e7d948c0ae3302fb466b1044a0c3c3cb512b9 Mon Sep 17 00:00:00 2001 From: tobiasfaust Date: Tue, 29 Jan 2013 18:41:04 +0000 Subject: [PATCH] =?UTF-8?q?Codepage=20von=2098=5FHeating=5FControl.pm=20ko?= =?UTF-8?q?rrigiert.=20Doku=20nun=20per=20commandref=20verf=C3=BCgbar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 98_structure.pm: unbalanced
  • gefixt git-svn-id: https://fhem.svn.sourceforge.net/svnroot/fhem/trunk/fhem@2593 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- FHEM/98_Heating_Control.pm | 918 ++++++++++++++++++------------------- FHEM/98_structure.pm | 7 +- 2 files changed, 463 insertions(+), 462 deletions(-) diff --git a/FHEM/98_Heating_Control.pm b/FHEM/98_Heating_Control.pm index c0fea7f9c..056f01e8e 100644 --- a/FHEM/98_Heating_Control.pm +++ b/FHEM/98_Heating_Control.pm @@ -1,459 +1,459 @@ -# $Id$ -############################################################################## -# -# 98_Heating_Control.pm -# written by Dietmar Ortmann -# modified by Tobias Faust -# -# This file is part of fhem. -# -# Fhem is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# Fhem is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with fhem. If not, see . -# -############################################################################## - -package main; -use strict; -use warnings; -use POSIX; - -sub Heating_Control_Update($); - -##################################### -sub -Heating_Control_Initialize($) -{ - my ($hash) = @_; - -# Consumer - $hash->{DefFn} = "Heating_Control_Define"; - $hash->{UndefFn} = "Heating_Control_Undef"; - $hash->{GetFn} = "Heating_Control_Get"; - $hash->{AttrList}= "loglevel:0,1,2,3,4,5 disable:0,1 ". - $readingFnAttributes; -} - -sub -Heating_Control_Get($@) -{ - my ($hash, @a) = @_; - return "argument is missing" if(int(@a) != 2); - - $hash->{LOCAL} = 1; - #Heating_Control_GetUpdate($hash); - delete $hash->{LOCAL}; - my $reading= $a[1]; - my $value; - - if(defined($hash->{READINGS}{$reading})) { - $value= $hash->{READINGS}{$reading}{VAL}; - } else { - return "no such reading: $reading"; - } - return "$a[0] $reading => $value"; -} - - -sub -Heating_Control_Define($$) -{ - my ($hash, $def) = @_; - my @a = split("[ \t]+", $def); - - return "Usage: define Heating_Control " - if(@a < 4); - - my $name = shift @a; - my $type = shift @a; - my $device = shift @a; - my @switchingtimes; - my $conditionOrCommand = ""; - my @Wochentage = ("Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag"); - - return "invalid Device, given Device <$device> not found" if(!$defs{$device}); - - #Altlasten bereinigen - 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; $w++) { - delete($hash->{"PROFILE ".($w+1).": ".$Wochentage[$w]}) if($hash->{"PROFILE ".($w+1).": ".$Wochentage[$w]}); - } - - for(my $i=0; $i<@a; $i++) { - #prüfen auf Angabe eines Schaltpunktes - my @t = split(/\|/, $a[$i]); - my $anzahl = @t; - if ( $anzahl ~~ [2,3]) { - push(@switchingtimes, $a[$i]); - } else { - #der Rest ist das auzuführende Kommando/condition - $conditionOrCommand = trim(join(" ", @a[$i..@a-1])); - last; - } - } - - $hash->{NAME} = $name; - $hash->{helper}{SWITCHINGTIMES} = join(" ", @switchingtimes); - $hash->{DEVICE} = $device; - - if($conditionOrCommand =~ m/^\(.*\)$/g) { #condition (*) - $hash->{helper}{CONDITION} = $conditionOrCommand; - } elsif(length($conditionOrCommand) > 0 ) { - $hash->{helper}{COMMAND} = $conditionOrCommand; - } - - my (@st, @days, $daylist, $time, $temp); - for(my $i=0; $i<@switchingtimes; $i++) { - - @st = split(/\|/, $switchingtimes[$i]); - if ( @st == 2) { - $daylist = "1234567"; #jeden Tag/woche ist vordefiniert - $time = $st[0]; - $temp = $st[1]; - } elsif ( @st == 3) { - $daylist = lc($st[0]); - $time = $st[1]; - $temp = $st[2]; - } - - # nur noch die Einzelteile per regExp testen - return "invalid daylist in $name <$daylist> 123... | Sa,So,..." - if(!($daylist =~ m/^(\d){0,7}$/g || $daylist =~ m/^((Sa|So|Mo|Di|Mi|Do|Fr)(,|$)){0,7}$/g )); - - # Sa, So ... in den Index übersetzen - my $idx = 1; - foreach my $day ("mo","di","mi","do","fr","sa","so") { - $daylist =~ s/$day/$idx/g; - $idx++; - } - - # Kommas entfernen - $daylist =~ s/,//g; - @days = split("", $daylist); - - # doppelte Tage entfernen - my %hdays=(); - @hdays{@days}=1; - #korrekt die Tage sortieren - @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)); - return "invalid temperature in $name <$temp> 99.9" - if(!($temp =~ m/^\d{1,2}(\.\d){0,1}$/g)); - - for (my $d=0; $d<@days; $d++) { - #Log 3, "Switchingtime: $switchingtimes[$i] : $days[$d] -> $time -> $temp "; - $hash->{helper}{SWITCHINGTIME}{$days[$d]}{$time} = $temp; - $hash->{"PROFILE ".($days[$d]).": ".$Wochentage[$days[$d]-1]} .= sprintf("%s: %.1f°C, ", $time, $temp); - } - } - - #desired-temp des Zieldevices auswählen - if($defs{$device}{TYPE} eq "MAX") { - $hash->{helper}{DESIRED_TEMP_READING} = "desiredTemperature" - } else { - $hash->{helper}{DESIRED_TEMP_READING} = "desired-temp"; - } - - my $now = time(); - InternalTimer ($now+30, "Heating_Control_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($$) -{ - my ($hash, $arg) = @_; - - RemoveInternalTimer($hash); - return undef; -} - -sub -Heating_Control_Update($) -{ - my ($hash) = @_; - my $now = time(); - my $next = 0; - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now); - - my $AktDesiredTemp = ReadingsVal($hash->{DEVICE}, $hash->{helper}{DESIRED_TEMP_READING}, 0); - my $newDesTemperature = $AktDesiredTemp; #default# - my $nextDesTemperature = 0; - my $nextSwitch = 0; - my $nowSwitch = 0; - my @days = ($wday..7, 1..$wday-1); - - for (my $d=0; $d<@days; $d++) { - #über jeden Tag - last if ($nextSwitch > 0); - foreach my $st (sort (keys %{ $hash->{helper}{SWITCHINGTIME}{$days[$d]} })) { - #berechnen, des Schaltpunktes - my $secondsToSwitch = 3600*(int(substr($st,0,2)) - $hour) + - 60*(int(substr($st,3,2)) - $min ) - $sec; - # Tagesdiff dazurechnen - if($wday <= int($days[$d])) { - $secondsToSwitch += 3600*24*(int($days[$d])-$wday) - } else { - $secondsToSwitch += 3600*24*(7-$wday+int($days[$d])) - } - - $next = time()+$secondsToSwitch; - #Log 3, "Jetzt:".strftime('%d.%m.%Y %H:%M:%S',localtime($now))." -> Next: ".strftime('%d.%m.%Y %H:%M:%S',localtime($next))." -> Temp: $hash->{helper}{SWITCHINGTIME}{$days[$d]}{$st}"; - - if ($now > $next) { - $newDesTemperature = $hash->{helper}{SWITCHINGTIME}{$days[$d]}{$st}; - #Log 3, "temperature------------>$newDesTemperature"; - $nowSwitch = $now; - } else { - $nextSwitch = $next; - $nextDesTemperature = $hash->{helper}{SWITCHINGTIME}{$days[$d]}{$st}; - last; - } - } - } - - if ($nextSwitch eq "") { - $nextSwitch = $now + 3600; - } - - my $name = $hash->{NAME}; - my $command; - - #Log 3, "NowSwitch: ".strftime('%d.%m.%Y %H:%M:%S',localtime($nowSwitch))." ; AktDesiredTemp: $AktDesiredTemp ; newDesTemperature: $newDesTemperature"; - if ($nowSwitch gt "" && $AktDesiredTemp != $newDesTemperature) { - if (defined $hash->{helper}{CONDITION}) { - $command = '{ fhem("set @ '.$hash->{helper}{DESIRED_TEMP_READING}.' %") if' . $hash->{helper}{CONDITION} . '}'; - } elsif (defined $hash->{helper}{COMMAND}) { - $command = $hash->{helper}{COMMAND}; - } else { - $command = '{ fhem("set @ '.$hash->{helper}{DESIRED_TEMP_READING}.' %") }'; - } - } - - if ($command && AttrVal($hash->{NAME}, "disable", 0) == 0) { - $command =~ s/@/$hash->{DEVICE}/g; - $command =~ s/%/$newDesTemperature/g; - $command = SemicolonEscape($command); - my $ret = AnalyzeCommandChain(undef, $command); - Log GetLogLevel($name,3), $ret if($ret); - } - - #Log 3, "nextSwitch=".strftime('%d.%m.%Y %H:%M:%S',localtime($nextSwitch)); - - InternalTimer($nextSwitch, "Heating_Control_Update", $hash, 0); - readingsBeginUpdate($hash); - readingsBulkUpdate($hash, "nextUpdate", strftime("%d.%m.%Y %H:%M:%S",localtime($nextSwitch))); - readingsBulkUpdate($hash, "nextValue", $nextDesTemperature . "°C"); - readingsBulkUpdate($hash, "state", strftime("%d.%m.%Y %H:%M:%S",localtime($nextSwitch)). ": " . $newDesTemperature."°C"); - readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1)); - - return 1; -} - -sub SortNumber { - if($a < $b) - { return -1; } - elsif($a == $b) - { return 0; } - else - { return 1; } -} - -1; - - - -=pod -=begin html - - -

    Heating Control

    -
      -
      - - Define -
        - define <name> Heating_Control <device> <profile> <command>|<condition> -

        - - to set a weekly profile for <device>, eg. a heating sink. You can define different switchingtimes for every day. - The new temperature is send to the <device> automaticly with set <device> desired-temp <temp> - if the device is a heating thermostat (FHT8b, MAX). Have you defined a <condition> - and this condition is false if the switchingtime has reached, no command will executed.
        - A other case is to define an own perl command with <command>. -

        - The following parameter are defined: -

          device
          - The device to switch at the given time. -
        -

        -

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

          - 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: HH24:MI
          - temperature:the temperature to set, using a Integer
          -
        -

        -

          command
          - If no condition is set, all others is interpreted as command. Perl-code is setting up - by well-known Block with {}.
          - Note: if a command is defined only this command are executed. In case of executing - a "set desired-temp" command, you must define it explicit.
          - The following parameter are replaced:
          -
            -
          1. @ => the device to switch
          2. -
          3. % => the new temperature
          4. -
          -
        -

        -

          condition
          - if a condition is defined you must declared this with () and a valid perl-code.
          - The returnvalue must be boolean.
          - The parameter @ and % will be interpreted. -
        -

        - Example: -

          - define HCB Heating_Control Bad_Heizung 12345|05:20|21 12345|05:25|12 17:20|21 17:25|12
          - Mo-Fr are setting the temperature at 05:20 to 21°C, and at 05:25 to 12°C. - Every day will be set the temperature at 17:20 to 21°C and 17:25 to 12°C.

          - - define HCW Heating_Control WZ_Heizung 07:00|16 Mo,Die,Mi|16:00|18.5 20:00|12 - {fhem(“set dummy on”); fhem("set @ desired-temp %");}
          - At the given times and weekdays only(!) the command will be executed.

          - - define HCK Heating_Control KZ_Heizung 07:00|16 16:00|18.5 20:00|12 ($sunshine=0))
          - The temperature is only set if the variable is $sunhine=0.

          -

        -
      - - - Set
        N/A

      - - - Get
        N/A

      - - - Attributes -
      -
    - -=end html -=begin html_DE - - -

    Heating Control

    -
      -
      - - Define -
        - define <name> Heating_Control <device> <profile> <command>|<condition> -

        - - Bildet ein Wochenprofil für ein <device>, zb. Heizkörper, ab. Es können für jeden Tag unterschiedliche - Schaltzeiten angegeben werden. Ist das <device> ein Heizkörperthermostat (zb. FHT8b, MAX) so wird die - zu setzende Temperatur im <profile> automatisch mittels set <device> desired-temp <temp> - dem Device mitgeteilt. Ist eine <condition> angegeben und ist zum Schaltpunkt der Ausdruck unwahr, - so wird dieser Schaltpunkt nicht ausgeführt.
        - Alternativ zur Automatik kann stattdessen eigener Perl-Code im <command> ausgeführt werden. -

        - Folgende Parameter sind im Define definiert: -

          device
          - Das an den Schaltpunkten zu schaltende Device. -
        -

        -

          profile
          - Angabe des Wochenprofils. Die einzelnen Schaltzeiten sind durch Leerzeichen getrennt - Die Angabe der Schaltzeiten ist nach folgendem Muster definiert:
          -
            [<Wochentage>|]<Uhrzeit>|<Temperatur>

          - 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, Die, ..., So) einzusetzen.
          - Uhrzeit:Angabe der Uhrzeit an dem geschaltet werden soll, Format: HH24:MI
          - Temperatur:Angabe der zu setzenden Temperatur als Zahl
          -
        -

        -

          command
          - Falls keine Condition in () angegeben wurde, so wird alles weitere als Command - interpretiert. Perl-Code ist in {} zu setzen.
          - Wichtig: Falls ein Command definiert ist, so wird zu den definierten Schaltzeiten - nur(!) das Command ausgeführt. Falls ein desired-temp Befehl abgesetzt werde soll, - so muss dies explizit angegeben werden.
          - Folgende Parameter werden ersetzt:
          -
            -
          1. @ => das zu schaltende Device
          2. -
          3. % => die zu setzende Temperatur
          4. -
          -
        -

        -

          condition
          - Bei Angabe einer Condition ist diese in () zu setzen und mit validem Perl-Code zu versehen.
          - Der Rückgabedatentyp der condition muss boolean sein.
          - Die Parameter @ und % werden interpretiert. -
        -

        - Beispiel: -

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

          - - define HCW Heating_Control WZ_Heizung 07:00|16 Mo,Die,Mi|16:00|18.5 20:00|12 - {fhem(“set dummy on”); fhem("set @ desired-temp %");}
          - Zu den definierten Schaltzeiten wird nur(!) der in {} angegebene Perl-Code ausgeführt.

          - - define HCK Heating_Control KZ_Heizung 07:00|16 16:00|18.5 20:00|12 ($sunshine=0))
          - Die zu setzendeTemperatur wird nur gesetzt, falls die globale Variable $sunhine=0 ist.

          -

        -
      - - - Set
        N/A

      - - - Get
        N/A

      - - - Attributes -
      -
    - -=end html_DE -=cut +# $Id$ +############################################################################## +# +# 98_Heating_Control.pm +# written by Dietmar Ortmann +# modified by Tobias Faust +# +# This file is part of fhem. +# +# Fhem is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# Fhem is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with fhem. If not, see . +# +############################################################################## + +package main; +use strict; +use warnings; +use POSIX; + +sub Heating_Control_Update($); + +##################################### +sub +Heating_Control_Initialize($) +{ + my ($hash) = @_; + +# Consumer + $hash->{DefFn} = "Heating_Control_Define"; + $hash->{UndefFn} = "Heating_Control_Undef"; + $hash->{GetFn} = "Heating_Control_Get"; + $hash->{AttrList}= "loglevel:0,1,2,3,4,5 disable:0,1 ". + $readingFnAttributes; +} + +sub +Heating_Control_Get($@) +{ + my ($hash, @a) = @_; + return "argument is missing" if(int(@a) != 2); + + $hash->{LOCAL} = 1; + #Heating_Control_GetUpdate($hash); + delete $hash->{LOCAL}; + my $reading= $a[1]; + my $value; + + if(defined($hash->{READINGS}{$reading})) { + $value= $hash->{READINGS}{$reading}{VAL}; + } else { + return "no such reading: $reading"; + } + return "$a[0] $reading => $value"; +} + + +sub +Heating_Control_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t]+", $def); + + return "Usage: define Heating_Control " + if(@a < 4); + + my $name = shift @a; + my $type = shift @a; + my $device = shift @a; + my @switchingtimes; + my $conditionOrCommand = ""; + my @Wochentage = ("Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag"); + + return "invalid Device, given Device <$device> not found" if(!$defs{$device}); + + #Altlasten bereinigen + 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; $w++) { + delete($hash->{"PROFILE ".($w+1).": ".$Wochentage[$w]}) if($hash->{"PROFILE ".($w+1).": ".$Wochentage[$w]}); + } + + for(my $i=0; $i<@a; $i++) { + #prüfen auf Angabe eines Schaltpunktes + my @t = split(/\|/, $a[$i]); + my $anzahl = @t; + if ( $anzahl ~~ [2,3]) { + push(@switchingtimes, $a[$i]); + } else { + #der Rest ist das auzuführende Kommando/condition + $conditionOrCommand = trim(join(" ", @a[$i..@a-1])); + last; + } + } + + $hash->{NAME} = $name; + $hash->{helper}{SWITCHINGTIMES} = join(" ", @switchingtimes); + $hash->{DEVICE} = $device; + + if($conditionOrCommand =~ m/^\(.*\)$/g) { #condition (*) + $hash->{helper}{CONDITION} = $conditionOrCommand; + } elsif(length($conditionOrCommand) > 0 ) { + $hash->{helper}{COMMAND} = $conditionOrCommand; + } + + my (@st, @days, $daylist, $time, $temp); + for(my $i=0; $i<@switchingtimes; $i++) { + + @st = split(/\|/, $switchingtimes[$i]); + if ( @st == 2) { + $daylist = "1234567"; #jeden Tag/woche ist vordefiniert + $time = $st[0]; + $temp = $st[1]; + } elsif ( @st == 3) { + $daylist = lc($st[0]); + $time = $st[1]; + $temp = $st[2]; + } + + # nur noch die Einzelteile per regExp testen + return "invalid daylist in $name <$daylist> 123... | Sa,So,..." + if(!($daylist =~ m/^(\d){0,7}$/g || $daylist =~ m/^((Sa|So|Mo|Di|Mi|Do|Fr)(,|$)){0,7}$/g )); + + # Sa, So ... in den Index übersetzen + my $idx = 1; + foreach my $day ("mo","di","mi","do","fr","sa","so") { + $daylist =~ s/$day/$idx/g; + $idx++; + } + + # Kommas entfernen + $daylist =~ s/,//g; + @days = split("", $daylist); + + # doppelte Tage entfernen + my %hdays=(); + @hdays{@days}=1; + #korrekt die Tage sortieren + @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)); + return "invalid temperature in $name <$temp> 99.9" + if(!($temp =~ m/^\d{1,2}(\.\d){0,1}$/g)); + + for (my $d=0; $d<@days; $d++) { + #Log 3, "Switchingtime: $switchingtimes[$i] : $days[$d] -> $time -> $temp "; + $hash->{helper}{SWITCHINGTIME}{$days[$d]}{$time} = $temp; + $hash->{"PROFILE ".($days[$d]).": ".$Wochentage[$days[$d]-1]} .= sprintf("%s: %.1f°C, ", $time, $temp); + } + } + + #desired-temp des Zieldevices auswählen + if($defs{$device}{TYPE} eq "MAX") { + $hash->{helper}{DESIRED_TEMP_READING} = "desiredTemperature" + } else { + $hash->{helper}{DESIRED_TEMP_READING} = "desired-temp"; + } + + my $now = time(); + InternalTimer ($now+30, "Heating_Control_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($$) +{ + my ($hash, $arg) = @_; + + RemoveInternalTimer($hash); + return undef; +} + +sub +Heating_Control_Update($) +{ + my ($hash) = @_; + my $now = time(); + my $next = 0; + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now); + + my $AktDesiredTemp = ReadingsVal($hash->{DEVICE}, $hash->{helper}{DESIRED_TEMP_READING}, 0); + my $newDesTemperature = $AktDesiredTemp; #default# + my $nextDesTemperature = 0; + my $nextSwitch = 0; + my $nowSwitch = 0; + + $wday=7 if($wday==0); + my @days = ($wday..7, 1..$wday-1); + + for (my $d=0; $d<@days; $d++) { + #über jeden Tag + last if ($nextSwitch > 0); + foreach my $st (sort (keys %{ $hash->{helper}{SWITCHINGTIME}{$days[$d]} })) { + #berechnen, des Schaltpunktes + my $secondsToSwitch = 3600*(int(substr($st,0,2)) - $hour) + + 60*(int(substr($st,3,2)) - $min ) - $sec; + # Tagesdiff dazurechnen + if($wday <= int($days[$d])) { + $secondsToSwitch += 3600*24*(int($days[$d])-$wday) + } else { + $secondsToSwitch += 3600*24*(7-$wday+int($days[$d])) + } + + $next = time()+$secondsToSwitch; + #Log 3, "Jetzt:".strftime('%d.%m.%Y %H:%M:%S',localtime($now))." -> Next: ".strftime('%d.%m.%Y %H:%M:%S',localtime($next))." -> Temp: $hash->{helper}{SWITCHINGTIME}{$days[$d]}{$st}"; + + if ($now > $next) { + $newDesTemperature = $hash->{helper}{SWITCHINGTIME}{$days[$d]}{$st}; + #Log 3, "temperature------------>$newDesTemperature"; + $nowSwitch = $now; + } else { + $nextSwitch = $next; + $nextDesTemperature = $hash->{helper}{SWITCHINGTIME}{$days[$d]}{$st}; + last; + } + } + } + + if ($nextSwitch eq "") { + $nextSwitch = $now + 3600; + } + + my $name = $hash->{NAME}; + my $command; + + #Log 3, "NowSwitch: ".strftime('%d.%m.%Y %H:%M:%S',localtime($nowSwitch))." ; AktDesiredTemp: $AktDesiredTemp ; newDesTemperature: $newDesTemperature"; + if ($nowSwitch gt "" && $AktDesiredTemp != $newDesTemperature) { + if (defined $hash->{helper}{CONDITION}) { + $command = '{ fhem("set @ '.$hash->{helper}{DESIRED_TEMP_READING}.' %") if' . $hash->{helper}{CONDITION} . '}'; + } elsif (defined $hash->{helper}{COMMAND}) { + $command = $hash->{helper}{COMMAND}; + } else { + $command = '{ fhem("set @ '.$hash->{helper}{DESIRED_TEMP_READING}.' %") }'; + } + } + + if ($command && AttrVal($hash->{NAME}, "disable", 0) == 0) { + $command =~ s/@/$hash->{DEVICE}/g; + $command =~ s/%/$newDesTemperature/g; + $command = SemicolonEscape($command); + my $ret = AnalyzeCommandChain(undef, $command); + Log GetLogLevel($name,3), $ret if($ret); + } + + #Log 3, "nextSwitch=".strftime('%d.%m.%Y %H:%M:%S',localtime($nextSwitch)); + + InternalTimer($nextSwitch, "Heating_Control_Update", $hash, 0); + readingsBeginUpdate($hash); + readingsBulkUpdate($hash, "nextUpdate", strftime("%d.%m.%Y %H:%M:%S",localtime($nextSwitch))); + readingsBulkUpdate($hash, "nextValue", $nextDesTemperature . "°C"); + readingsBulkUpdate($hash, "state", strftime("%d.%m.%Y %H:%M:%S",localtime($nextSwitch)). ": " . $newDesTemperature."°C"); + readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1)); + + return 1; +} + +sub SortNumber { + if($a < $b) + { return -1; } + elsif($a == $b) + { return 0; } + else + { return 1; } +} + +1; + +=pod +=begin html + + +

    Heating Control

    +
      +
      + + Define +
        + define <name> Heating_Control <device> <profile> <command>|<condition> +

        + + to set a weekly profile for <device>, eg. a heating sink. You can define different switchingtimes for every day. + The new temperature is send to the <device> automaticly with set <device> desired-temp <temp> + if the device is a heating thermostat (FHT8b, MAX). Have you defined a <condition> + and this condition is false if the switchingtime has reached, no command will executed.
        + A other case is to define an own perl command with <command>. +

        + The following parameter are defined: +

          device
          + The device to switch at the given time. +
        +

        +

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

          + 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: HH24:MI
          + temperature:the temperature to set, using a Integer
          +
        +

        +

          command
          + If no condition is set, all others is interpreted as command. Perl-code is setting up + by well-known Block with {}.
          + Note: if a command is defined only this command are executed. In case of executing + a "set desired-temp" command, you must define it explicit.
          + The following parameter are replaced:
          +
            +
          1. @ => the device to switch
          2. +
          3. % => the new temperature
          4. +
          +
        +

        +

          condition
          + if a condition is defined you must declared this with () and a valid perl-code.
          + The returnvalue must be boolean.
          + The parameter @ and % will be interpreted. +
        +

        + Example: +

          + define HCB Heating_Control Bad_Heizung 12345|05:20|21 12345|05:25|12 17:20|21 17:25|12
          + Mo-Fr are setting the temperature at 05:20 to 21°C, and at 05:25 to 12°C. + Every day will be set the temperature at 17:20 to 21°C and 17:25 to 12°C.

          + + define HCW Heating_Control WZ_Heizung 07:00|16 Mo,Die,Mi|16:00|18.5 20:00|12 + {fhem(“set dummy on”); fhem("set @ desired-temp %");}
          + At the given times and weekdays only(!) the command will be executed.

          + + define HCK Heating_Control KZ_Heizung 07:00|16 16:00|18.5 20:00|12 ($sunshine=0))
          + The temperature is only set if the variable is $sunhine=0.

          +

        +
      + + + Set
        N/A

      + + + Get
        N/A

      + + + Attributes +
      +
    + +=end html +=begin html_DE + + +

    Heating Control

    +
      +
      + + Define +
        + define <name> Heating_Control <device> <profile> <command>|<condition> +

        + + Bildet ein Wochenprofil für ein <device>, zb. Heizkörper, ab. Es können für jeden Tag unterschiedliche + Schaltzeiten angegeben werden. Ist das <device> ein Heizkörperthermostat (zb. FHT8b, MAX) so wird die + zu setzende Temperatur im <profile> automatisch mittels set <device> desired-temp <temp> + dem Device mitgeteilt. Ist eine <condition> angegeben und ist zum Schaltpunkt der Ausdruck unwahr, + so wird dieser Schaltpunkt nicht ausgeführt.
        + Alternativ zur Automatik kann stattdessen eigener Perl-Code im <command> ausgeführt werden. +

        + Folgende Parameter sind im Define definiert: +

          device
          + Das an den Schaltpunkten zu schaltende Device. +
        +

        +

          profile
          + Angabe des Wochenprofils. Die einzelnen Schaltzeiten sind durch Leerzeichen getrennt + Die Angabe der Schaltzeiten ist nach folgendem Muster definiert:
          +
            [<Wochentage>|]<Uhrzeit>|<Temperatur>

          + 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, Die, ..., So) einzusetzen.
          + Uhrzeit:Angabe der Uhrzeit an dem geschaltet werden soll, Format: HH24:MI
          + Temperatur:Angabe der zu setzenden Temperatur als Zahl
          +
        +

        +

          command
          + Falls keine Condition in () angegeben wurde, so wird alles weitere als Command + interpretiert. Perl-Code ist in {} zu setzen.
          + Wichtig: Falls ein Command definiert ist, so wird zu den definierten Schaltzeiten + nur(!) das Command ausgeführt. Falls ein desired-temp Befehl abgesetzt werde soll, + so muss dies explizit angegeben werden.
          + Folgende Parameter werden ersetzt:
          +
            +
          1. @ => das zu schaltende Device
          2. +
          3. % => die zu setzende Temperatur
          4. +
          +
        +

        +

          condition
          + Bei Angabe einer Condition ist diese in () zu setzen und mit validem Perl-Code zu versehen.
          + Der Rückgabedatentyp der condition muss boolean sein.
          + Die Parameter @ und % werden interpretiert. +
        +

        + Beispiel: +

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

          + + define HCW Heating_Control WZ_Heizung 07:00|16 Mo,Die,Mi|16:00|18.5 20:00|12 + {fhem(“set dummy on”); fhem("set @ desired-temp %");}
          + Zu den definierten Schaltzeiten wird nur(!) der in {} angegebene Perl-Code ausgeführt.

          + + define HCK Heating_Control KZ_Heizung 07:00|16 16:00|18.5 20:00|12 ($sunshine=0))
          + Die zu setzendeTemperatur wird nur gesetzt, falls die globale Variable $sunhine=0 ist.

          +

        +
      + + + Set
        N/A

      + + + Get
        N/A

      + + + Attributes +
      +
    + +=end html_DE +=cut diff --git a/FHEM/98_structure.pm b/FHEM/98_structure.pm index db2eb55e8..d0e3f92be 100755 --- a/FHEM/98_structure.pm +++ b/FHEM/98_structure.pm @@ -612,7 +612,8 @@ structure_Attr($@)
      Die Struktur übernimmt den Status des zuletzt geänderten Gerätes.
    - +
  • +
  • clientstate_priority
    @@ -623,7 +624,7 @@ structure_Attr($@) unterschiedliche Devicetypen zusammenfassen zu können. Jede Gruppe wird durch Leerzeichen, jeder Eintrag pro Gruppe durch Pipe getrennt. Der Status der Struktur ist der erste Eintrag in der entsprechenden Gruppe. - +

  • Beispiel:
    - +
  • readingFnAttributes