diff --git a/fhem/FHEM/98_THRESHOLD.pm b/fhem/FHEM/98_THRESHOLD.pm index e1a36e521..eac0ae397 100644 --- a/fhem/FHEM/98_THRESHOLD.pm +++ b/fhem/FHEM/98_THRESHOLD.pm @@ -33,7 +33,7 @@ THRESHOLD_Initialize($) $hash->{DefFn} = "THRESHOLD_Define"; $hash->{SetFn} = "THRESHOLD_Set"; $hash->{NotifyFn} = "THRESHOLD_Notify"; - $hash->{AttrList} = "disable:0,1 loglevel:0,1,2,3,4,5,6"; + $hash->{AttrList} = "disable:0,1 loglevel:0,1,2,3,4,5,6 state_format state_cmd1_gt state_cmd2_lt"; } @@ -44,34 +44,36 @@ THRESHOLD_Define($$$) my ($hash, $def) = @_; my @b =split (/\|/,$def); my @a = split("[ \t][ \t]*", $b[0]); - my $cmd1=""; - my $cmd2=""; - my $state_cmd1=""; - my $state_cmd2=""; + my $cmd1_gt=""; + my $cmd2_lt=""; my $cmd_default=0; my $actor; - - if (@b > 5 || @a < 3 || @a > 6) { + my $init_desired_value; + my $target_sensor; + my $target_reading; + my $offset=0; + my $pn = $a[0]; + + if (@b > 6 || @a < 3 || @a > 6) { my $msg = "wrong syntax: define THRESHOLD " . - "[:[][:[][:]]] [AND|OR [:[][:]]] ". - "[][|[][|[][|[][|[[][:]]]]]]"; - Log 2, $msg; + ":::: AND|OR :: ". + "||||:|state_format"; + Log3 $pn,2, $msg; return $msg; } - my $pn = $a[0]; + # Sensor - my ($sensor, $reading, $hysteresis,$init_desired_value) = split(":", $a[2], 4); + my ($sensor, $reading, $hysteresis,$s4,$s5,$s6) = split(":", $a[2], 6); if(!$defs{$sensor}) { my $msg = "$pn: Unknown sensor device $sensor specified"; - Log 2, $msg; + Log3 $pn,2, $msg; return $msg; } - $hash->{sensor} = $sensor; $reading = "temperature" if (!defined($reading)); - if (!defined($hysteresis)) { + if (!defined($hysteresis) or ($hysteresis eq "")) { if ($reading eq "temperature" or $reading eq "temp") { $hysteresis=1; } elsif ($reading eq "humidity") { @@ -81,20 +83,61 @@ THRESHOLD_Define($$$) } } elsif ($hysteresis !~ m/^[\d\.]*$/ ) { my $msg = "$pn: value:$hysteresis, hysteresis needs a numeric parameter"; - Log 2, $msg; + Log3 $pn,2, $msg; return $msg; } - if (defined($init_desired_value)) { - if ($init_desired_value !~ m/^[-\d\.]*$/) { - my $msg = "$pn: value:$init_desired_value, init_desired_value needs a numeric parameter"; - Log 2, $msg; - return $msg; - } + if (defined($s6)) { # target_sensor:target_reading:offset + $target_sensor=$s4; + $target_reading=$s5; + $offset=$s6; + } elsif (defined($s5)) { # init_desired_value:offset or target_sensor:offset or target_sensor:target_reading + if ($s5 =~ m/^[-\d\.]*$/) { # offset + $offset=$s5; + } else { # target_reading + $target_reading=$s5; + } + if ($s4 =~ m/^[-\d\.]*$/) { # init_desired_value + $init_desired_value=$s4; + } else { # target_sensor + $target_sensor=$s4; + } + } elsif (defined($s4)) { # target_sensor or init_desired_value + if ($s4 =~ m/^[-\d\.]*$/) { # init_desired_value + $init_desired_value=$s4; + } else { # target_sensor + $target_sensor=$s4; + $target_reading="temperature"; + } + } + if (defined($target_sensor)) { + if (!$defs{$target_sensor}) { + my $msg = "$pn: Unknown sensor device $target_sensor specified"; + Log3 $pn,2, $msg; + return $msg; + } } - $hash->{sensor_reading} = $reading; - $hash->{hysteresis} = $hysteresis; - - # Sensor2 + +# Modify DEF + if ($hash->{sensor}) + { + delete $hash->{sensor}; + delete $hash->{sensor_reading}; + delete $hash->{hysteresis}; + delete $hash->{target_sensor}; + delete $hash->{target_reading}; + delete $hash->{init_desired_value}; + delete $hash->{offset}; + delete $hash->{cmd1_gt}; + delete $hash->{cmd2_lt}; + delete $hash->{cmd_default}; + delete $hash->{STATE}; + delete $hash->{operator}; + delete $hash->{sensor2}; + delete $hash->{sensor2_reading}; + delete $hash->{sensor2_state}; + } + + # Sensor2 if (defined($a[3])) { my $operator=$a[3]; @@ -103,7 +146,7 @@ THRESHOLD_Define($$$) if (defined ($sensor2)) { if(!$defs{$sensor2}) { my $msg = "$pn: Unknown sensor2 device $sensor2 specified"; - Log 2, $msg; + Log3 $pn,2, $msg; return $msg; } } @@ -121,56 +164,87 @@ THRESHOLD_Define($$$) if (defined ($actor)) { if (!$defs{$actor}) { my $msg = "$pn: Unknown actor device $actor specified"; - Log 2, $msg; + Log3 $pn,2, $msg; return $msg; } } if (@b == 1) { # no actor parameters if (!defined($actor)) { - my $msg = "$pn: no actor device specified"; - Log 2, $msg; - return $msg; + $attr{$pn}{state_cmd1_gt}="off"; + $attr{$pn}{state_cmd2_lt}="on"; + $attr{$pn}{state_format} = "_sc"; + $hysteresis = 0; + $cmd_default = 0; + } else { + $cmd1_gt = "set $actor off"; + $cmd2_lt = "set $actor on"; + $attr{$pn}{state_cmd1_gt}="off"; + $attr{$pn}{state_cmd2_lt} = "on"; + $cmd_default = 2; + $attr{$pn}{state_format} = "_m _dv _sc"; } - $cmd1 = "set $actor off"; - $cmd2 = "set $actor on"; - $cmd_default = 2; } else { # actor parameters - $cmd1 = $b[1] if (defined($b[1])); - $cmd2 = $b[2] if (defined($b[2])); + $cmd1_gt = $b[1] if (defined($b[1])); + $cmd2_lt = $b[2] if (defined($b[2])); $cmd_default = (!($b[3])) ? 0 : $b[3]; if ($cmd_default !~ m/^[0-2]$/ ) { my $msg = "$pn: value:$cmd_default, cmd_default_index needs 0,1,2"; - Log 2, $msg; + Log3 $pn,2, $msg; return $msg; } if (defined($b[4])) { - my ($st_cmd1, $st_cmd2) = split(":", $b[4], 2); - $state_cmd1 = $st_cmd1 if (defined($st_cmd1)); - $state_cmd2 = $st_cmd2 if (defined($st_cmd2)); - } + my ($st_cmd1_gt, $st_cmd2_lt) = split(":", $b[4], 2); + $attr{$pn}{state_cmd1_gt} = $st_cmd1_gt if (defined($st_cmd1_gt)); + $attr{$pn}{state_cmd2_lt} = $st_cmd2_lt if (defined($st_cmd2_lt)); + $attr{$pn}{state_format} = "_sc"; + } + + if (defined($b[5])) { + $attr{$pn}{state_format} = $b[5]; + } elsif (defined($b[4])){ + $attr{$pn}{state_format} = "_sc"; + } else { + $attr{$pn}{state_format} = "_m _dv"; + } + } if (defined($actor)) { - $cmd1 =~ s/@/$actor/g; - $cmd2 =~ s/@/$actor/g; + $cmd1_gt =~ s/@/$actor/g; + $cmd2_lt =~ s/@/$actor/g; } + + $hash->{sensor} = $sensor; + $hash->{sensor_reading} = $reading; + $hash->{hysteresis} = $hysteresis; + $hash->{target_sensor} = $target_sensor if (defined ($target_sensor)); + $hash->{target_reading} = $target_reading if (defined ($target_reading)); + $hash->{init_desired_value} = $init_desired_value if (defined ($init_desired_value)); + $hash->{offset} = $offset; + $hash->{cmd1_gt} = SemicolonEscape($cmd1_gt); + $hash->{cmd2_lt} = SemicolonEscape($cmd2_lt); + $hash->{cmd_default} = $cmd_default; + $hash->{STATE} = 'initialized'; - $hash->{helper}{state_cmd1} = $state_cmd1; - $hash->{helper}{state_cmd2} = $state_cmd2; - $hash->{helper}{actor_cmd1} = SemicolonEscape($cmd1); - $hash->{helper}{actor_cmd2} = SemicolonEscape($cmd2); - $hash->{helper}{actor_cmd_default} = $cmd_default; - $hash->{STATE} = 'initialized' if (!ReadingsVal($pn,"desired_value","")); + readingsBeginUpdate ($hash); if (defined ($init_desired_value)) { - my $set_state =($state_cmd1 eq "" and $state_cmd2 eq "") ? 1 : 0; - readingsBeginUpdate ($hash); - readingsBulkUpdate ($hash, "state", "active $init_desired_value") if ($set_state); - readingsBulkUpdate ($hash, "threshold_min", $init_desired_value-$hysteresis); + my $mode="active"; + readingsBulkUpdate ($hash, "threshold_min", $init_desired_value-$hysteresis+$offset); + readingsBulkUpdate ($hash, "threshold_max", $init_desired_value+$offset); readingsBulkUpdate ($hash, "cmd","wait for next cmd"); readingsBulkUpdate ($hash, "desired_value", $init_desired_value); - readingsEndUpdate ($hash, 1); + readingsBulkUpdate ($hash, "mode", $mode); } + + if (defined ($target_sensor)) + { + my $mode="external"; + readingsBulkUpdate ($hash, "cmd", "wait for next cmd"); + readingsBulkUpdate ($hash, "mode", "external"); + } + readingsEndUpdate ($hash, 1); + return undef; } @@ -184,16 +258,28 @@ THRESHOLD_Set($@) return "$pn, need a parameter for set" if(@a < 2); my $arg = $a[1]; my $value = (defined $a[2]) ? $a[2] : ""; - my $set_state = ($hash->{helper}{state_cmd1} eq "" and $hash->{helper}{state_cmd2} eq "") ? 1 : 0; my $desired_value = ReadingsVal($pn,"desired_value",""); + my $target_sensor = + my $offset = $hash->{offset}; + my $mode; + my $state_format = AttrVal($pn, "state_format", "_m _dv"); if ($arg eq "desired" ) { return "$pn: set desired value:$value, desired value needs a numeric parameter" if(@a != 3 || $value !~ m/^[-\d\.]*$/); return $ret if ($desired_value == $value); - Log GetLogLevel($pn,3), "set $pn $arg $value"; + Log3 $pn,2, "set $pn $arg $value"; + $mode = "active"; + $state_format =~ s/\_m/$mode/g; + $state_format =~ s/\_dv/$value/g; + $state_format =~ s/\_s1v//g; + $state_format =~ s/\_s2s//g; + $state_format =~ s/\_sc//g; + readingsBeginUpdate ($hash); - readingsBulkUpdate ($hash, "state", "active $value") if ($set_state); - readingsBulkUpdate ($hash, "threshold_min",$value-$hash->{hysteresis}); + readingsBulkUpdate ($hash, "mode", $mode); + readingsBulkUpdate ($hash, "state", $state_format) if ($state_format); + readingsBulkUpdate ($hash, "threshold_min",$value-$hash->{hysteresis}+$offset); + readingsBulkUpdate ($hash, "threshold_max", $value+$offset); readingsBulkUpdate ($hash, "cmd","wait for next cmd"); readingsBulkUpdate ($hash, "desired_value", $value); readingsEndUpdate ($hash, 1); @@ -201,29 +287,83 @@ THRESHOLD_Set($@) return "$pn: set deactivated, set desired value first" if (!$desired_value); $ret=CommandAttr(undef, "$pn disable 1"); if (!$ret) { - readingsSingleUpdate ($hash, "state", "deactivated $desired_value",1) if ($set_state); + readingsBeginUpdate ($hash); + $mode = "deactivated"; + $state_format =~ s/\_m/$mode/g; + $state_format =~ s/\_dv//g; + $state_format =~ s/\_s1v//g; + $state_format =~ s/\_s2s//g; + $state_format =~ s/\_sc//g; + readingsBulkUpdate ($hash, "state", $state_format) if ($state_format); + readingsBulkUpdate ($hash, "mode", "deactiveted"); + readingsEndUpdate ($hash, 1); } } elsif ($arg eq "active" ) { return "$pn: set active, set desired value first" if (!$desired_value); $ret=CommandDeleteAttr(undef, "$pn disable"); if (!$ret) { + $mode="active"; readingsBeginUpdate ($hash); - readingsBulkUpdate ($hash, "state", "active $desired_value") if ($set_state); + $state_format =~ s/\_m/$mode/g; + $state_format =~ s/\_dv//g; + $state_format =~ s/\_s1v//g; + $state_format =~ s/\_s2s//g; + $state_format =~ s/\_sc//g; + readingsBulkUpdate ($hash, "mode", $mode); + readingsBulkUpdate ($hash, "state", $state_format) if ($state_format); readingsBulkUpdate ($hash, "cmd","wait for next cmd"); readingsEndUpdate ($hash, 1); } - } elsif ($arg eq "hysteresis" ) { + } elsif ($arg eq "external" ) { + $ret=CommandDeleteAttr(undef, "$pn disable"); + if (!$ret) { + return "$pn: no target_sensor defined" if (!$hash->{target_sensor}); + $mode="external"; + readingsBeginUpdate ($hash); + $state_format =~ s/\_m/$mode/g; + $state_format =~ s/\_dv//g; + $state_format =~ s/\_s1v//g; + $state_format =~ s/\_s2s//g; + $state_format =~ s/\_sc//g; + readingsBulkUpdate ($hash, "mode", $mode); + readingsBulkUpdate ($hash, "state", $state_format) if ($state_format); + readingsBulkUpdate ($hash, "cmd","wait for next cmd"); + readingsEndUpdate ($hash, 1); + } + } elsif ($arg eq "hysteresis" ) { return "$pn: set hysteresis value:$value, hysteresis needs a numeric parameter" if (@a != 3 || $value !~ m/^[\d\.]*$/ ); $hash->{hysteresis} = $value; if ($desired_value) { readingsBeginUpdate ($hash); - readingsBulkUpdate ($hash, "threshold_min",$desired_value-$hash->{hysteresis}); + readingsBulkUpdate ($hash, "threshold_min",$desired_value-$hash->{hysteresis}+$offset); + readingsBulkUpdate ($hash, "threshold_max", $desired_value+$offset); readingsBulkUpdate ($hash, "cmd","wait for next cmd"); readingsEndUpdate ($hash, 1); } - } else { - return "$pn: unknown argument $a[1], choose one of desired active deactivated hysteresis" - } + } elsif ($arg eq "offset" ) { + return "$pn: set offset value:$value, offset needs a numeric parameter" if (@a != 3 || $value !~ m/^[-\d\.]*$/ ); + $offset = $value; + $hash->{offset} = $offset; + if ($desired_value) { + readingsBeginUpdate ($hash); + readingsBulkUpdate ($hash, "threshold_min",$desired_value-$hash->{hysteresis}+$offset); + readingsBulkUpdate ($hash, "threshold_max", $desired_value+$offset); + readingsBulkUpdate ($hash, "cmd","wait for next cmd"); + readingsEndUpdate ($hash, 1); + } + } elsif ($arg eq "cmd1_gt" ) { + readingsBeginUpdate ($hash); + THRESHOLD_setValue ($hash,1); + THRESHOLD_set_state ($hash); + readingsEndUpdate ($hash, 1); + } elsif ($arg eq "cmd2_lt" ) { + readingsBeginUpdate ($hash); + THRESHOLD_setValue ($hash,2); + THRESHOLD_set_state ($hash); + readingsEndUpdate ($hash, 1); + } else { + return "$pn: unknown argument $a[1], choose one of desired active external deactivated hysteresis offset cmd1_gt cmd2_lt" + } return $ret; } @@ -233,109 +373,185 @@ THRESHOLD_Notify($$) { my ($hash, $dev) = @_; my $pn = $hash->{NAME}; - - return "" if(($attr{$pn} && $attr{$pn}{disable}) || !ReadingsVal($pn,"desired_value","")); + return "" if($attr{$pn} && $attr{$pn}{disable}); my $sensor = $hash->{sensor}; my $reading = $hash->{sensor_reading}; + my $target_sensor = $hash->{target_sensor}; + my $target_reading = $hash->{target_reading}; my $sensor2 = $hash->{sensor2}; my $reading2 = $hash->{sensor2_reading}; - - if ($dev->{NAME} ne $sensor) { - if ($sensor2) { - if ($dev->{NAME} ne $sensor2) { - return ""; - } - } else { - return ""; - } - } + my $s_value; + my $t_value; + my $sensor_max; + my $sensor_min; + my $name = $dev->{NAME}; - if(!($defs{$sensor}{READINGS}{$reading})) { - my $msg = "$pn: no reading yet for $sensor $reading"; - Log 2, $msg; - return ""; - } - - my $instr = $defs{$sensor}{READINGS}{$reading}{VAL}; - - $instr =~ /[^\d^\-^.]*([-\d.]*)/; - - my $s_value = $1; - - - my $sensor_max = ReadingsVal($pn,"desired_value",""); - my $sensor_min = ReadingsVal($pn,"threshold_min",""); - my $cmd_default = $hash->{helper}{actor_cmd_default}; - - readingsSingleUpdate ($hash, "sensor_value",$s_value, 1); - - if (!$hash->{operator}) { - if ($s_value > $sensor_max) { - THRESHOLD_setValue($hash,1); - } elsif ($s_value < $sensor_min) { - THRESHOLD_setValue($hash,2); - } else { - THRESHOLD_setValue($hash,$cmd_default) if (ReadingsVal($pn,"cmd","") eq "wait for next cmd" && $cmd_default != 0); + SELECT:{ + if (($name eq $sensor) and ReadingsVal($pn,"desired_value","")) {last SELECT;} + if ($sensor2) { + if (($name eq $sensor2) and ReadingsVal($pn,"desired_value","")) {last SELECT;} } - } else { - if (!($defs{$sensor2}{READINGS}{$reading2})) { - my $msg = "$pn: no reading yet for $sensor2 $reading2"; - Log 2, $msg; - return ""; - } - - my $s2_state = $defs{$sensor2}{READINGS}{$reading2}{VAL}; - my $sensor2_state = $hash->{sensor2_state}; - - readingsSingleUpdate ($hash, "sensor2_state",$s2_state, 1); - - if ($hash->{operator} eq "AND") { - if (($s_value > $sensor_max) && ($s2_state eq $sensor2_state)) { - THRESHOLD_setValue($hash,1); - } elsif (($s_value < $sensor_min) || ($s2_state ne $sensor2_state)){ - THRESHOLD_setValue($hash,2); - } else { - THRESHOLD_setValue($hash,$cmd_default) if (ReadingsVal($pn,"cmd","") eq "wait for next cmd" && $cmd_default != 0); + if ($target_sensor) { + if (ReadingsVal($pn,"mode","") eq "external") { + if ($name eq $target_sensor) {last SELECT;} } - } elsif ($hash->{operator} eq "OR") { - if (($s_value > $sensor_max) || ($s2_state eq $sensor2_state)) { - THRESHOLD_setValue($hash,1); - } elsif (($s_value < $sensor_min) && ($s2_state ne $sensor2_state)){ - THRESHOLD_setValue($hash,2); - } else { - THRESHOLD_setValue($hash,$cmd_default) if (ReadingsVal($pn,"cmd","") eq "wait for next cmd" && $cmd_default != 0); - } - } + } + return ""; } + + if (!($defs{$sensor}{READINGS}{$reading})) { + my $msg = "$pn: no reading yet for $sensor $reading"; + Log3 $pn,2, $msg; + return""; + } else { + my $instr = $defs{$sensor}{READINGS}{$reading}{VAL}; + $instr =~ /[^\d^\-^.]*([-\d.]*)/; + $s_value = $1; + } + if ($sensor2) { + if (!($defs{$sensor2}{READINGS}{$reading2})) { + my $msg = "$pn: no reading yet for $sensor2 $reading2"; + Log3 $pn,2, $msg; + return""; + } + } + my $mode = ReadingsVal($pn,"mode",""); + + #compatibility hack + if (!$mode) { + my $desired_value = ReadingsVal($pn,"desired_value",""); + $mode="active"; + my $state_format = AttrVal($pn, "state_format", "_m _dv"); + $state_format =~ s/\_m/$mode/g; + $state_format =~ s/\_dv/$desired_value/g; + $state_format =~ s/\_s1v//g; + $state_format =~ s/\_s2s//g; + $state_format =~ s/\_sc//g; + readingsBeginUpdate ($hash); + readingsBulkUpdate ($hash, "state", $state_format) if ($state_format); + readingsBulkUpdate ($hash, "threshold_min", $desired_value-$hash->{hysteresis}+$hash->{offset}); + readingsBulkUpdate ($hash, "threshold_max", $desired_value+$hash->{offset}); + readingsBulkUpdate ($hash, "mode", $mode); + readingsEndUpdate ($hash, 1); + } + + if (($target_reading) && $mode eq "external") + { + if (!($defs{$target_sensor}{READINGS}{$target_reading})) { + my $msg = "$pn: no reading yet for $target_sensor $target_reading"; + Log3 $pn,2, $msg; + return""; + } else { + my $instr = $defs{$target_sensor}{READINGS}{$target_reading}{VAL}; + $instr =~ /[^\d^\-^.]*([-\d.]*)/; + $t_value = $1; + $sensor_max = $t_value+$hash->{offset}; + $sensor_min = $t_value-$hash->{hysteresis}+$hash->{offset}; + } + } + + readingsBeginUpdate ($hash); + readingsBulkUpdate ($hash, "sensor_value",$s_value) if (defined($s_value) and ($s_value ne ReadingsVal($pn,"sensor_value",""))); + readingsBulkUpdate ($hash, "desired_value",$t_value) if (defined($t_value) and ($t_value ne ReadingsVal($pn,"desired_value",""))); + + if (defined ($sensor_max)) { + readingsBulkUpdate ($hash, "threshold_max",$sensor_max) if ($sensor_max ne ReadingsVal($pn,"threshold_max","")); + } else { + $sensor_max = ReadingsVal($pn,"threshold_max",""); + } + if (defined ($sensor_min)) { + readingsBulkUpdate ($hash, "threshold_min",$sensor_min) if ($sensor_min ne ReadingsVal($pn,"threshold_min","")); + } else { + $sensor_min = ReadingsVal($pn,"threshold_min",""); + } + + my $cmd_now=""; + if (($sensor_min ne "") and ($sensor_max ne "")) + { + my $cmd_default = $hash->{cmd_default}; + if (!$hash->{operator}) { + if ($s_value > $sensor_max) { + THRESHOLD_setValue($hash,1); + } elsif ($s_value < $sensor_min) { + THRESHOLD_setValue($hash,2); + } else { + THRESHOLD_setValue($hash,$cmd_default) if (ReadingsVal($pn,"cmd","") eq "wait for next cmd" && $cmd_default != 0); + } + } else { + my $s2_state = $defs{$sensor2}{READINGS}{$reading2}{VAL}; + my $sensor2_state = $hash->{sensor2_state}; + readingsBulkUpdate ($hash, "sensor2_state",$s2_state) if ($s2_state ne ReadingsVal($pn,"sensor2_state","")); + + if ($hash->{operator} eq "AND") { + if (($s_value > $sensor_max) && ($s2_state eq $sensor2_state)) { + THRESHOLD_setValue($hash,1); + } elsif (($s_value < $sensor_min) || ($s2_state ne $sensor2_state)){ + THRESHOLD_setValue($hash,2); + } else { + THRESHOLD_setValue($hash,$cmd_default) if (ReadingsVal($pn,"cmd","") eq "wait for next cmd" && $cmd_default != 0); + } + } elsif ($hash->{operator} eq "OR") { + if (($s_value > $sensor_max) || ($s2_state eq $sensor2_state)) { + THRESHOLD_setValue($hash,1); + } elsif (($s_value < $sensor_min) && ($s2_state ne $sensor2_state)){ + THRESHOLD_setValue($hash,2); + } else { + THRESHOLD_setValue($hash,$cmd_default) if (ReadingsVal($pn,"cmd","") eq "wait for next cmd" && $cmd_default != 0); + } + } + } + } + THRESHOLD_set_state ($hash); + readingsEndUpdate ($hash, 1); return ""; } +sub +THRESHOLD_set_state($) +{ + my ($hash) = @_; + my $pn=$hash->{NAME}; + my $state_old = ReadingsVal($pn, "state",""); + my $mode = ReadingsVal($pn,"mode",""); + my $desired_value = ReadingsVal($pn,"desired_value",""); + my $sensor_value = ReadingsVal($pn,"sensor_value",""); + my $sensor2_state = ReadingsVal($pn,"sensor2_state",""); + my $cmd = ReadingsVal($pn,"cmd",""); +# my %h_state_cmd = (cmd1_gt=>state_cmd1_gt, cmd2_lt=>state_cmd2_lt); + my $state_cmd = AttrVal ($pn, "state_".$cmd,""); + my $state_format = AttrVal($pn, "state_format", "_m _dv"); + $state_format =~ s/\_m/$mode/g; + $state_format =~ s/\_dv/$desired_value/g; + $state_format =~ s/\_s1v/$sensor_value/g; + $state_format =~ s/\_s2s/$sensor2_state/g; + $state_format =~ s/\_sc/$state_cmd/g; + if (($state_format) and ($state_old ne $state_format)) { + readingsBulkUpdate ($hash, "state", $state_format); + } +} + sub THRESHOLD_setValue($$) { my ($hash, $cmd_nr) = @_; my $pn = $hash->{NAME}; - my @cmd_sym = ("cmd1","cmd2"); + my @cmd_sym = ("cmd1_gt","cmd2_lt"); my $cmd_sym_now = $cmd_sym[$cmd_nr-1]; if (ReadingsVal($pn,"cmd","") ne $cmd_sym_now) { my $ret=0; - my @cmd =($hash->{helper}{actor_cmd1},$hash->{helper}{actor_cmd2}); - my @state_cmd = ($hash->{helper}{state_cmd1},$hash->{helper}{state_cmd2}); + my @cmd =($hash->{cmd1_gt},$hash->{cmd2_lt}); + my @state_cmd = (AttrVal($pn,"state_cmd1_gt",""),AttrVal($pn,"state_cmd2_lt","")); my $cmd_now = $cmd[$cmd_nr-1]; my $state_cmd_now = $state_cmd[$cmd_nr-1]; if ($cmd_now ne "") { if ($ret = AnalyzeCommandChain(undef, $cmd_now)) { - Log GetLogLevel($pn,3), "output of $pn $cmd_now: $ret"; - return ""; + Log3 $pn,2 , "output of $pn $cmd_now: $ret"; } } - readingsBeginUpdate ($hash); - readingsBulkUpdate ($hash, "state",$state_cmd_now) if (($state_cmd_now) ne ""); - readingsBulkUpdate ($hash, "cmd",$cmd_sym_now); - readingsEndUpdate ($hash, 1); - } + readingsBulkUpdate ($hash, "cmd",$cmd_sym_now); + } } 1; @@ -346,102 +562,147 @@ THRESHOLD_setValue($$)

THRESHOLD

    - This module reads any sensor that provides values in decimal and execute FHEM/Perl commands, if the value of the sensor is higher or lower than the threshold value. - So can be easily implemented a software thermostat, hygrostat and much more.
    + Diverse controls can be realized by means of the module by evaluation of sensor data. + In the simplest case, this module reads any sensor that provides values in decimal and execute FHEM/Perl commands, if the value of the sensor is higher or lower than the threshold value. + A typical application is the simulation of a thermostat or humidistat.
    +
    + With one or more such modules, complex systems can be implemented for heating, cooling, ventilation, dehumidification or shading. + But even simple notification when crossing or falling below a specific value can be easily realized. It no if-statements in Perl or notify definitions need to be made. + This leads to quickly create and clear controls, without having to necessarily go into the Perl matter.
    + Some application examples are at the end of the module description.
    +
    + According to the definition of a module type THRESHOLD eg:
    +
    + define <name> THRESHOLD <sensor> <actor>

    It is controlled by setting a desired value with:

    set <name> desired <value>

    + The module begins with the control system only when a desired value is set!
    +
    + The specification of the desired value may also come from another sensor. This control may take place by the comparison of two sensors.
    +
    + Likewise, any wall thermostats can be used (eg, HM, MAX, FHT) for the definition of the reference temperature.
    +
    The switching behavior can also be influenced by another sensor or sensor group.

    + The combination of multiple THRESHOLD modules together is possible, see examples below.
    +
Define

    - define <name> THRESHOLD <sensor>[:[<reading>][:[<hysteresis>][:<init_desired_value>]]] [AND|OR <sensor2>[:[<reading2>][:<state>]]] [<actor>][|[<cmd1>][|[<cmd2>][|[<cmd_default_index>][|[[<state_cmd1>][:<state_cmd2>]]]]]]
    + define <name> THRESHOLD <sensor>:<reading>:<hysteresis>:<target_value>:<offset> AND|OR <sensor2>:<reading2>:<state> <actor>|<cmd1_gt>|<cmd2_lt>|<cmd_default_index>|<state_cmd1_gt>:<state_cmd2_lt>|<state_format>


    -
  • sensor
    +
  • sensor
    a defined sensor in FHEM
  • -
  • reading
    +
    +
  • reading (optional)
    reading of the sensor, which includes a value in decimal
    default value: temperature
  • -
  • hysteresis
    +
    +
  • hysteresis (optional)
    Hysteresis, this provides the threshold_min = desired_value - hysteresis
    default value: 1 at temperature, 10 at huminity
  • -
  • init_desired_value
    - Initial value, if no value is specified, it must be set with "set desired value".
    +
    +
  • target_value (optional)
    + number: Initial value, if no value is specified, it must be set with "set desired value".
    + else::, an additional sensor can be specified, which sets the target value dynamically Defaultwert: no value

  • +
  • offset (optional)
    + Offset zum Sollwert
    + Damit errechnet sich die Sollwertobergrenze = Sollwert+offset und die Sollwertuntergrenze = Sollwert-Hysterese+offset.
    + Defaultwert: 0
    +

  • -
  • AND|OR
    +
    +
  • AND|OR (optional)
    logical operator with an optional second sensor
  • -
  • sensor2
    +
  • sensor2 (optional, nur in Verbindung mit AND oder OR)
    the second sensor
  • -
  • reading2
    +
    +
  • reading2 (optional)
    reading of the second sensor
    default value: state
  • -
  • state
    +
    +
  • state (optional)
    state of the second sensor
    default value: open

  • -
  • actor
    +
    +
  • actor (optional)
    actor device defined in FHEM
  • -
  • cmd1
    +
    +
  • cmd1_gt (optional)
    FHEM/Perl command that is executed, if the value of the sensor is higher than desired value and/or the value of sensor 2 is matchted. @ is a placeholder for the specified actor.
    default value: set actor off, if actor defined
  • -
  • cmd2
    +
    +
  • cmd2_lt (optional)
    FHEM/Perl command that is executed, if the value of the sensor is lower than threshold_min or the value of sensor 2 is not matchted. @ is a placeholder for the specified actor.
    default value: set actor on, if actor defined
  • -
  • cmd_default_index
    +
    +
  • cmd_default_index (optional)
    Index of command that is executed after setting the desired value until the desired value or threshold_min value is reached.
    0 - no command
    - 1 - cmd1
    - 2 - cmd2
    + 1 - cmd1_gt
    + 2 - cmd2_lt
    default value: 2, if actor defined, else 0

  • -
  • state_cmd1
    - state, which is displayed, if FHEM/Perl-command cmd1 was executed. If state_cmd1 state ist set, other states, such as active or deactivated are suppressed. -
    - default value: none -
  • -
  • state_cmd2
    - state, which is displayed, if FHEM/Perl-command cmd1 was executed. If state_cmd1 state ist set, other states, such as active or deactivated are suppressed. +
  • state_cmd1_gt (optional, is defined as an attribute at the same time and can be changed there)
    + state, which is displayed, if FHEM/Perl-command cmd1_gt was executed. If state_cmd1_gt state ist set, other states, such as active or deactivated are suppressed.
    default value: none

  • +
  • state_cmd2_lt (optional, is defined as an attribute at the same time and can be changed there)
    + state, which is displayed, if FHEM/Perl-command cmd1_gt was executed. If state_cmd1_gt state ist set, other states, such as active or deactivated are suppressed.
    - Examples:
    + default value: none +
  • +
    +
  • state_format (optional, is defined as an attribute at the same time and can be changed there)
    + Format of the state output: arbitrary text with placeholders.
    + Possible placeholders:
    + _m: mode
    + _dv: desired_value
    + _s1v: sensor_value
    + _s2s: sensor2_state
    + _sc: state_cmd
    + Default value: _m _dv _sc, _sc when state_cmd1_gt and state_cmd2_lt set without actor.

    +
  • +
    + Examples:

    Example for heating:

    + It is heated up to the desired value of 20. If the value below the threshold_min value of 19 (20-1) + the heating is switched on again.
    +
    define thermostat THRESHOLD temp_sens heating

    set thermostat desired 20

    - Description:
    -
    - It is heated up to the desired value of 20. If the value below the threshold_min value of 19 (20-1) - the heating is switched on again.

    Example for heating with window contact:

    define thermostat THRESHOLD temp_sens OR win_sens heating

    +
    Example for heating with multiple window contacts:

    define W_ALL structure W1 W2 W3 ...
    @@ -452,6 +713,7 @@ THRESHOLD_setValue($$)
    define thermostat THRESHOLD S1 OR W_ALL heating

    +
    More examples for dehumidification, air conditioning, watering:

    define hygrostat THRESHOLD hym_sens:humidity dehydrator|set @ on|set @ off|1
    @@ -460,21 +722,70 @@ THRESHOLD_setValue($$) define thermostat THRESHOLD temp_sens AND Sensor2:state:close aircon|set @ on|set @ off|1
    define hygrostat THRESHOLD hym_sens:humidity:20 watering|set @ off|set @ on|2

    +
    It can also FHEM/perl command chains are specified:

    Examples:

    - define thermostat THRESHOLD sensor |set Switch1 on;set Switch2 on|set Switch1 off;set Switch2 off|1
    - define thermostat THRESHOLD sensor alarm|{Log 2,"value is exceeded"}|set @ on;set Switch2 on
    + define thermostat THRESHOLD sensor |set Switch1 on;;set Switch2 on|set Switch1 off;;set Switch2 off|1
    + define thermostat THRESHOLD sensor alarm|{Log 2,"value is exceeded"}|set @ on;;set Switch2 on
    define thermostat THRESHOLD sensor ||{Log 2,"value is reached"}|

    - Example for status display on/off:

    - define thermostat THRESHOLD sensor heating|set @ off|set @ on|2|off:on
    + Examples of the reference input by another sensor:

    - Example for status display (eg for state evaluation in other modules), if temperature drops below 30 degrees or above:
    + Hot water circulation: The return temperature is 5 degrees (offset) below the hot water tank temperature and can vary by up to 4 degrees (hysteresis).

    - define thermostat THRESHOLD sensor:temperature:0:30 ||||on:off
    + define TH_water_circulation THRESHOLD return_w:temperature:4:water_storage:temperature:-5 circualtion_pump
    +
    + Control of heating by a wall thermostat with acquisition the desired and actual temperature from the wall thermostat:
    +
    + define TH_heating THRESHOLD WT:measured-temp:1:WT:desired-temp heating
    +
    + set TH_heating desired 17 overrides the desired-values from the wall thermostat until called set TH_heating external
    +
    +
    + Examples of customized state output:
    +
    + define thermostat THRESHOLD sensor aircon|set @ on|set @ off|2|on:off
    +
    +
    + Example of state output (eg for state evaluation in other modules) without executing code:
    +
    + define thermostat THRESHOLD sensor:temperature:0:30
    +
    + by reason of default values​​:
    +
    + define thermostat THRESHOLD sensor:temperature:0:30||||off:on|_sc
    +
    +
    + Example of combining several THRESHOLD modules together:
    +
    + It should be heated when the room temperature drops below 21 degrees and the outside temperature is below 15 degrees:
    +
    + define TH_outdoor THRESHOLD outdoor:temperature:0:15
    + define TH_room THRESHOLD indoor AND TH_outdoor:state:on heating
    + set TH_room desired 21
    +
    +
    + An example of time-dependent heating in combination with Heating_Control module:
    +
    + define TH_living_room THRESHOLD T_living_room heating
    + define HC_living_room Heating_Control TH_living_room 06:00|22 22:00|18 set @ desired %
    +
    +
    + Examples of customized state output:
    +
    + State output: <mode> <state_cmd> <desired_value> <sensor_value>
    +
    + define TH_living_room THRESHOLD T_living_room heating|set @ off|set @ on|2|off:on|_m _sc _dv _s1v
    +
    + or
    +
    + define TH_living_room THRESHOLD T_living_room heating
    + attr TH_living_room state_cmd1_gt off
    + attr TH_living_room state_cmd2_lt on
    + attr TH_living_room state_format _m _sc _dv _s1v

@@ -489,12 +800,29 @@ THRESHOLD_setValue($$)
  • set <name> active <value>
    - Module is activated again. + Module is activated. If under target_value a sensor for reference input has been defined, the current setpoint will be inhibited until set "set external". +
  • +
    +
  • set <name> externel
    + Module is activated, reference input comes from the target sensor, if a sensor has been defined under target_value.

  • set <name> hysteresis <value>
    Set hysteresis value.
  • +
    +
  • set <name> offset <value>
    + Set offset value.
    + Defaultwert: 0 +
  • +
    +
  • set <name> cmd1_gt
    + Executes the command defined in cmd1_gt.
    +
  • +
    +
  • set <name> cmd2_lt
    + Executes the command defined in cmd2_lt.
    +

  • @@ -510,6 +838,9 @@ THRESHOLD_setValue($$)
    @@ -519,119 +850,161 @@ THRESHOLD_setValue($$)

    THRESHOLD

      - Dieses Modul liest einen beliebigen Sensor aus, der Werte als Dezimalzahlen liefert und führt beim Überschreiten der Schwellen-Obergrenze (Sollwert) bzw. beim Unterschreiten der Schwellen-Untergrenze beliebige FHEM/Perl-Befehle aus. Damit lässt sich leicht z. B. ein Software-Thermostat oder -Hygrostat realisieren.
      + Vielfältige Steuerungen, bei denen durch die Auswertung von Sensordaten eine Steuerung erfolgen soll, können mit Hilfe dieses Moduls realisiert werden. + Nach der Definition eines THRESHOLD-Moduls und der Vorgabe eines Sollwertes beginnt bereits das definierte Modul mit der Steuerung. Im einfachsten Fall liest das Modul einen Sensor aus, der Werte als Dezimalzahlen liefert + und schaltet beim Überschreiten einer definierten Schwellen-Obergrenze (Sollwert) + bzw. beim Unterschreiten einer Schwellen-Untergrenze einen Aktor oder führt beliebige FHEM/Perl-Befehle aus. + Typisches Anwendungsgebiet ist z. B. die Nachbildung eines Thermostats oder Hygrostats.

      - Nach der Definition eines Moduls vom Typ THRESHOLD erfolgt die eigentliche Steuerung über die Vorgabe eines Sollwertes.
      + Mit Hilfe des Moduls, bzw. vieler solcher Module, lassen sich einfache oder auch komplexe Steuerungen für Heizung, Kühlung, Lüftung, Entfeuchtung, Beschattung oder z. B. einfache Benachrichtung + beim Über- oder Unterschreiten eines bestimmten Wertes realisieren. Dabei müssen keine If-Abfragen in Perl oder Notify-Definitionen vorgenommen werden. + Das führt, nicht nur bei FHEM-Anfängern, zu schnell erstellten und übersichtlichen Steuerungen, ohne zwingend in die Perl-Materie einsteigen zu müssen. + Am Ende der Beschreibung befinden sich einige Anwendungsbeipiele des Moduls.

      - Das geschieht über:
      + Nach der Definition eines Moduls vom Typ THRESHOLD z. B. mit:
      +
      + define <name> THRESHOLD <sensor> <actor>
      +
      + erfolgt die eigentliche Steuerung über die Vorgabe eines Sollwertes. Das geschieht über:

      set <name> desired <value>

      - Das Modul beginnt mit der Steuerung erst dann, wenn ein Sollwert gesetzt wird.
      + Das Modul beginnt mit der Steuerung erst dann, wenn ein Sollwert gesetzt wird!
      +
      + Alternativ kann die Vorgabe des Sollwertes von einem weiteren Sensor kommen. Damit kann eine Steuerung durch den Vergleich zweier Sensoren stattfinden. + Typisches Anwendungsbeispiel ist z. B. die Steuerung von Umwelz- oder Zirkulationspumpen.
      +
      + Ebenso können beliebige Wandthermostate (z. B. HM, MAX, FHT) für die Vorgabe der Solltemperatur genutzt werden.

      Optional kann das Schaltverhalten zusätzlich durch einen weiteren Sensor oder eine Sensorgruppe, - definiert über structure (z. B. Fensterkontakte), beeinflusst werden.
      + definiert über structure (z. B. Fensterkontakte), über eine AND- bzw. OR-Verknüpfung beeinflusst werden.
      +
      + Auch die Kombination mehrerer THRESHOLD-Module miteinander ist möglich, siehe Beispiele unten.

    Define
      -
      - define <name> THRESHOLD <sensor>[:[<reading>][:[<hysteresis>][:<init_desired_value>]]] [AND|OR <sensor2>[:[<reading2>][:<state>]]] [<actor>][|[<cmd1>][|[<cmd2>][|[<cmd_default_index>][|[[<state_cmd1>][:<state_cmd2>]]]]]]
      +
      + define <name> THRESHOLD <sensor>:<reading>:<hysteresis>:<target_value>:<offset> AND|OR <sensor2>:<reading2>:<state> <actor>|<cmd1_gt>|<cmd2_lt>|<cmd_default_index>|<state_cmd1_gt>:<state_cmd2_lt>|<state_format>


      -
    • sensor
      - ein in FHEM definierter Sensor +
    • sensor
      + ein in FHEM definierter Sensor
    • -
    • reading
      +
      +
    • reading (optional)
      Reading des Sensors, der einen Wert als Dezimalzahl beinhaltet
      - Defaultwert: temperature + Defaultwert: temperature
    • -
    • hysteresis
      - Hysterese, daraus errechnet sich die Untergrenze = Sollwert - hysteresis
      - Defaultwert: 1 bei Temperaturen, 10 bei Feuchtigkeit +
      +
    • hysteresis (optional)
      + Hysterese, daraus errechnet sich die Untergrenze = Sollwert - hysteresis + offset
      + Defaultwert: 1 bei Temperaturen, 10 bei Feuchtigkeit
    • -
    • init_desired_value
      - Initial-Sollwert, wenn kein Wert vorgegeben wird, muss er mit "set desired value" gesetzt werden
      - Defaultwert: kein +
      +
    • target_value (optional)
      + bei Zahl: Initial-Sollwert , wenn kein Wert vorgegeben wird, muss er mit "set desired value" gesetzt werden, daraus berechnet sich die Obergrenze = Sollwert + offset
      + sonst: :, hier kann ein weiterer Sensor angegeben werden, der den Sollwert dynamisch vorgibt
      + Defaultwert: kein
      +
    • +
      +
    • offset (optional)
      + Offset zum Sollwert
      + Damit errechnet sich die Sollwertobergrenze = Sollwert+offset und die Sollwertuntergrenze = Sollwert-Hysterese+offset.
      + Defaultwert: 0


    • -
    • AND|OR
      - Verknüpfung mit einem optionalen zweiten Sensor +
    • AND|OR (optional)
      + Verknüpfung mit einem optionalen zweiten Sensor
    • -
    • sensor2
      - ein definierter Sensor, dessen Status abgefragt wird +
      +
    • sensor2 (optional, nur in Verbindung mit AND oder OR)
      + ein definierter Sensor, dessen Status abgefragt wird
    • -
    • reading2
      +
      +
    • reading2 (optional)
      Reading, der den Status des Sensors beinhaltet
      - Defaultwert: state + Defaultwert: state
    • -
    • state
      +
      +
    • state (optional)
      Status des Sensors, der zu einer Aktion führt
      - Defaultwert: open -

    • -
    • actor
      - ein in FHEM definierter Aktor + Defaultwert: open
    • -
    • cmd1
      +
      +
    • actor (optional)
      + ein in FHEM definierter Aktor
      +
    • +
      +
    • cmd1_gt (optional)
      FHEM/Perl Befehl, der beim Überschreiten des Sollwertes ausgeführt wird bzw. - wenn status des sensor2 übereinstimmt. @ ist ein Platzhalter für den angegebenen Aktor. -
      - Defaultwert: set actor off, wenn Aktor angegeben ist + wenn status des sensor2 übereinstimmt. @ ist ein Platzhalter für den angegebenen Aktor.
      + Defaultwert: set actor off, wenn Aktor angegeben ist
    • -
    • cmd2
      +
      +
    • cmd2_lt (optional)
      FHEM/Perl Befehl, der beim Unterschreiten der Untergrenze (Sollwert-Hysterese) ausgeführt wird bzw. - wenn status des sensor2 nicht übereinstimmt. @ ist ein Platzhalter für den angegebenen Aktor. -
      - Defaultwert: set actor on, wenn Aktor angegeben ist + wenn status des sensor2 nicht übereinstimmt. @ ist ein Platzhalter für den angegebenen Aktor.
      + Defaultwert: set actor on, wenn Aktor angegeben ist
    • -
    • cmd_default_index
      +
      +
    • cmd_default_index (optional)
      FHEM/Perl Befehl, der nach dem Setzen des Sollwertes ausgeführt wird, bis Sollwert oder die Untergrenze erreicht wird.
      0 - kein Befehl
      - 1 - cmd1
      - 2 - cmd2
      + 1 - cmd1_gt
      + 2 - cmd2_lt
      Defaultwert: 2, wenn Aktor angegeben ist, sonst 0

    • -
    • state_cmd1
      - Status, der angezeigt wird, wenn FHEM/Perl-Befehl cmd1 ausgeführt wurde. Wenn state_cmd1 gesetzt ist, werden andere Stati, wie active oder deactivated unterdrückt. -
      - Defaultwert: keiner +
    • state_cmd1_gt (optional, wird gleichzeitig als Attribut definiert)
      + Status, der angezeigt wird, wenn FHEM/Perl-Befehl cmd1_gt ausgeführt wurde.
      + Defaultwert: kein
    • -
    • state_cmd2
      - Status, der angezeigt wird, wenn FHEM/Perl-Befehl cmd2 ausgeführt wurde. Wenn state_cmd2 gesetzt ist, werden andere Stati, wie active oder deactivated unterdrückt.
      - Defaultwert: keiner +
    • state_cmd2_lt (optional, wird gleichzeitig als Attribut definiert)
      + Status, der angezeigt wird, wenn FHEM/Perl-Befehl cmd2_lt ausgeführt wurde.
      + Defaultwert: kein
      +
    • +
      +
    • state_format (optional, wird gleichzeitig als Attribut definiert und kann dort verändert werden)
      + Format der Statusanzeige: beliebiger Text mit Platzhaltern
      + Mögliche Platzhalter:
      + _m: mode
      + _dv: desired_value
      + _s1v: sensor_value
      + _s2s: sensor2_state
      + _sc: state_cmd
      + Defaultwert: _m _dv _sc, _sc, wenn state_cmd1_gt und state_cmd2_lt ohne Aktor gesetzt wird.


    • - Beispiele:
      + Beispiele:

      - Beispiel für Heizung:
      + Beispiel für ein einfaches Heizungsthermostat:

      - define thermostat THRESHOLD temp_sens heating
      + Es soll bis 20 Grad geheizt werden. Beim Unterschreiten der Untergrenze von 19 Grad (Sollwert-Hysterese) wird die Heizung wieder eingeschaltet.

      - set thermostat desired 20
      + define TH_room THRESHOLD temp_room heating

      - Beschreibung:
      + set TH_room desired 20

      - Es wird geheizt bis zum Maximalwert 20. Beim Unterschreiten des Untergrenze von 19 (20-1) wird die Heizung wieder eingeschaltet.

      Beispiel für Heizung mit Fensterkontakt:

      - define thermostat THRESHOLD temp_sens OR win_sens heating
      + define TH_room THRESHOLD temp_room OR win_sens heating
      +

      Beispiel für Heizung mit mehreren Fensterkontakten:

      define W_ALL structure W1 W2 W3 ....
      attr W_ALL clientstate_behavior relative
      attr W_ALL clientstate_priority closed open
      -
      - danach:

      define thermostat THRESHOLD S1 OR W_ALL heating

      +
      Einige weitere Bespiele für Entfeuchtung, Klimatisierung, Bewässerung:

      define hygrostat THRESHOLD hym_sens:humidity dehydrator|set @ on|set @ off|1
      @@ -640,41 +1013,107 @@ THRESHOLD_setValue($$) define thermostat THRESHOLD temp_sens AND Sensor2:state:close aircon|set @ on|set @ off|1
      define hygrostat THRESHOLD hym_sens:humidity:20 watering|set @ off|set @ on|2

      - Es können ebenso FHEM/Perl-Befehlsketten angegeben werden:

      - Beispiele:
      + Beispiele für die Ausführung beliebiger FHEM/Perl-Befehlsketten:

      - define thermostat THRESHOLD sensor |set Switch1 on;set Switch2 on|set Switch1 off;set Switch2 off|1
      - define thermostat THRESHOLD sensor alarm|{Log 2,"Wert überschritten"}|set @ on;set Switch2 on
      + define thermostat THRESHOLD sensor |set Switch1 on;;set Switch2 on|set Switch1 off;;set Switch2 off|1
      + define thermostat THRESHOLD sensor alarm|{Log 2,"Wert überschritten"}|set @ on;;set Switch2 on
      define thermostat THRESHOLD sensor ||{Log 2,"Wert unterschritten"}|

      - Beispiele mit Statusanzeige:

      - define thermostat THRESHOLD sensor heating|set @ off|set @ on|2|aus:an
      + Beispiele für die Sollwert-Vorgabe durch einen weiteren Sensor:

      - Beispiel für reine Zustandanzeige (z. B. für Zustandsauswertung in anderen Modulen), wenn Temperatur von 30 Grad über- oder unterschritten wird:
      + Warmwasserzirkulation: Die Rücklauftemperatur soll 5 Grad (offset) unter der Warmwasserspeichertemperatur liegen und bis zu 4 Grad (Hysterese) schwanken können.

      - define thermostat THRESHOLD sensor:temperature:0:30 ||||on:off
      + define TH_water_circulation THRESHOLD return_w:temperature:4:water_storage:temperature:-5 circualtion_pump

      -
    +
    + Steuerung einer Heizung durch ein Wandthermostat mit Übernahme der Soll- und Ist-Temperatur vom Wandthermostat:
    +
    + define TH_Heizung THRESHOLD WT:measured-temp:1:WT:desired-temp Heizung
    +
    + Mit set TH_Heizung desired 17 wird die Vorgabe vom Wandthermostat übersteuert bis set TH_Heizung external aufgerufen wird.
    +
    +
    + Beispiele mit angepasster Statusanzeige:
    +
    + define thermostat THRESHOLD sensor aircon|set @ on|set @ off|2|on:off
    +
    +
    + Beispiel für reine Zustandanzeige (z. B. für Zustandsauswertung in anderen Modulen) ohne Ausführung von Code:
    +
    + define thermostat THRESHOLD sensor:temperature:0:30
    +
    + entspricht wegen Defaultwerte:
    +
    + define thermostat THRESHOLD sensor:temperature:0:30||||off:on|_sc
    +
    +
    + Beispiel für Kombination mehrerer THRESHOLD-Module miteinander:
    +
    + Es soll geheizt werden, wenn die Zimmertemperatur unter 21 Grad fällt und die Außentemperatur unter 15 Grad ist:
    +
    + define TH_outdoor THRESHOLD outdoor:temperature:0:15
    + define TH_room THRESHOLD indoor AND TH_outdoor:state:on heating
    + set TH_room desired 21
    +
    +
    + Beispiel für zeitabhängiges Heizen in Kombination mit Heating_Control-Modul:
    +
    + define TH_living_room THRESHOLD T_living_room heating
    + define HC_living_room Heating_Control TH_living_room 06:00|22 22:00|18 set @ desired %
    +
    +
    + Beispiele für Anpassung der Statusanzeige des Moduls:
    +
    + Anzeige von <mode> <state_cmd> <desired_value> <sensor_value>
    +
    + define TH_living_room THRESHOLD T_living_room heating|set @ off|set @ on|2|off:on|_m _sc _dv _s1v
    +
    + oder
    +
    + define TH_living_room THRESHOLD T_living_room heating
    + attr TH_living_room state_cmd1_gt off
    + attr TH_living_room state_cmd2_lt on
    + attr TH_living_room state_format _m _sc _dv _s1v
    +
    + Set
    • set <name> desired <value>
      Setzt den Sollwert. Wenn kein Sollwert gesetzt ist, ist das Modul nicht aktiv. + Sollwert-Vorgabe durch einen Sensor wird hiermit übersteuert, solange bis "set external" gesetzt wird.

    • set <name> deactivated <value>
      Modul wird deaktiviert.

    • -
    • set <name> active <value>
      - Modul wird wieder aktiviert. +
    • set <name> active
      + Modul wird aktiviert, falls unter target_value ein Sensor für die Sollwert-Vorgabe definiert wurde, wird der aktuelle Sollwert solange eingefroren bis "set external" gesetzt wird.
      +
    • +
      +
    • set <name> externel
      + Modul wird aktiviert, Sollwert-Vorgabe kommt vom Sensor, falls ein Sensor unter target_value definierte wurde.

    • set <name> hysteresis <value>
      Setzt Hysterese-Wert.
    • +
      +
    • set <name> offset <value>
      + Setzt Offset-Wert.
      + Defaultwert: 0 +
    • +
      +
    • set <name> cmd1_gt
      + Führt das unter cmd1_gt definierte Kommando aus.
      +
    • +
      +
    • set <name> cmd2_lt
      + Führt das unter cmd2_lt definierte Kommando aus.
      +

    @@ -689,6 +1128,9 @@ THRESHOLD_setValue($$)