From a726ddf72663de2fe6439f1f33d3f2e5207f0321 Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Thu, 19 Jul 2018 16:11:09 +0000 Subject: [PATCH] 10_ZWave.pm: dim* Patches from Andreas/2016-11-13 (Forum #60468) git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@17004 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- FHEM/10_ZWave.pm | 230 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 198 insertions(+), 32 deletions(-) diff --git a/FHEM/10_ZWave.pm b/FHEM/10_ZWave.pm index eadc478ac..04ce89065 100644 --- a/FHEM/10_ZWave.pm +++ b/FHEM/10_ZWave.pm @@ -48,7 +48,7 @@ my %zwave_class = ( parse => { "..2001(.*)"=> '"basicSet:".hex($1)', # Forum #36980 "..2002" => "basicGet:request", # sent by the remote "032003(..)"=> '"basicReport:".hex($1)', # V1 - "052003(..)(..)(..)" => 'ZWave_BASIC_03_report($1,$2,$3)', + "052003(..)(..)(..)" => 'ZWave_basicReport($1,$2,$3)', }}, CONTROLLER_REPLICATION => { id => '21' }, APPLICATION_STATUS => { id => '22', # V1 @@ -60,30 +60,43 @@ my %zwave_class = ( ZIP_SERVER => { id => '24' }, SWITCH_BINARY => { id => '25', set => { off => "0100", - on => "01FF" }, + on => "01FF", + "off-for-timer" => 'ZWave_switchBinary_timer($hash,"00","%s")', + "on-for-timer" => 'ZWave_switchBinary_timer($hash,"FF","%s")' }, get => { swbStatus => "02", }, parse => { "..250300" => "state:off", "..2503ff" => "state:on", "052503(..)(..)(..)" => 'sprintf("swbStatus:%s target %s '. - 'duration %s", hex($1), hex($2), ZWave_duration($3))', + 'duration %s", hex($1), hex($2),ZWave_byte2time($3))', "03250100" => "state:setOff", "032501ff" => "state:setOn" } } , SWITCH_MULTILEVEL => { id => '26', set => { off => "0100", on => "01FF", dim => "01%02x", - dimWithDuration => "01%02x%02x", + dimWithDuration => 'ZWave_switchMultilevel_Set($hash, 0, "%s")', + dimUpDown => 'ZWave_switchMultilevel_Set($hash, 1, "%s")', + dimUpDownWithDuration => + 'ZWave_switchMultilevel_Set($hash, 2, "%s")', + dimUpDownIncDecWithDuration => + 'ZWave_switchMultilevel_Set($hash, 3, "%s")', stop => "05" }, - get => { swmStatus => "02", }, - parse => { "032603(.*)"=> '($1 eq "00" ? "state:off" : + get => { swmStatus => "02", + swmSupported=> "06" }, + parse => { "..2603(.*)"=> '($1 eq "00" ? "state:off" : ($1 eq "ff" ? "state:on" : "state:dim ".hex($1)))', + "052603(..)(..)(..)" => 'sprintf("swmStatus:%s target %s '. + 'duration %s", hex($1), hex($2), ZWave_duration($3))', # V4 "..260100.."=> "state:setOff", "..2601ff.."=> "state:setOn", "..260420" => "state:swmBeginUp", "..260460" => "state:swmBeginDown", "..2604(..)(..)(..)(..)" => 'ZWave_swmParse($1,$2,$3,$4)', - "..2605" => "state:swmEnd" } }, + "..2605" => "state:swmEnd", + "..2607(..)(..)" => + 'sprintf("swmSwitchType:primary %s secondary %s", + Zwave_switchType($1), Zwave_switchType($2))', }}, #V3 SWITCH_ALL => { id => '27', set => { swaIncludeNone => "0100", swaIncludeOff => "0101", @@ -581,18 +594,24 @@ my %zwave_class = ( ); my %zwave_classVersion = ( - dimWithDuration => { min => 2 }, - meterReset => { min => 2 }, - meterSupported => { min => 2 }, - wakeupIntervalCapabilities => { min => 2 }, + alarmEventSupported => { min => 3 }, alarmTypeSupported => { min => 2 }, - alarmnotification => { min => 2 }, alarmWithType => { min => 2 }, alarmWithTypeEvent => { min => 3 }, - alarmEventSupported => { min => 3 }, + alarmnotification => { min => 2 }, + dimWithDuration => { min => 2 }, + dimUpDownWithDuration => { min => 2 }, + dimUpDownIncDecWithDuration => { min => 3 }, + meterReset => { min => 2 }, + meterSupported => { min => 2 }, + "on-for-timer" => { min => 2 }, + "off-for-timer" => { min => 2 }, + swmSupported => { min => 3 }, tmEnergySaveHeating => { min => 2 }, tmFullPower => { min => 3 }, tmManual => { min => 3 }, + wakeupIntervalCapabilities => { min => 2 }, + ); my %zwave_cmdArgs = ( @@ -2773,11 +2792,9 @@ ZWave_configCheckParam($$$$@) return ("", sprintf("04%02x%02x%0*x", $h->{index}, $len/2, $len, $arg[0])); } -############################################## -### START: 0x20 BASIC sub -ZWave_BASIC_03_report ($$$) -{ # 0x2003 BASIC_REPORT V2 +ZWave_basicReport ($$$) +{ my ($value, $target, $duration) = @_;; my $time = hex($duration); @@ -2795,8 +2812,6 @@ ZWave_BASIC_03_report ($$$) return $rt; } -############################################## -### START: 0x21 APPLICATION_STATUS sub ZWave_APPLICATION_STATUS_01_Report($$$) { # 0x2101 ApplicationStatus ApplicationBusyReport >= V1 @@ -2811,6 +2826,7 @@ ZWave_APPLICATION_STATUS_01_Report($$$) return ("applicationBusy:$rt"); } + ############################################## ### START: 0x71 ALARM (NOTIFICATION) ### Renamed from ALARM to NOTIFICATION in V3 specification, @@ -5087,12 +5103,99 @@ ZWave_Attr(@) } sub -ZWave_duration($) +ZWave_switchBinary_timer($$$) +{ + my ($hash, $on, $time) = @_; + return (undef, "01$on".ZWave_time2byte($hash, $time)); +} + +sub +ZWave_switchMultilevel_Set($$$) +{ + my ($hash, $cmdType, $arg) = @_; + my $n = $hash->{NAME}; + $arg = uc($arg); + my ($regexp, $duration); + + if($cmdType == 0) { # dimWithDuration + return "$n dimWithDuration: wrong format for $arg" + if($arg !~ m/$p1_b (\d+)/); + return ("", sprintf("01%02x%02x", $1, ZWave_time2byte($hash,$2))); + + } elsif ($cmdType == 1) { # dimUpDown + $regexp = "(UP|DOWN) (IGNORE|USE) $p1_b"; + + } elsif ($cmdType == 2) { # dimUpDownWithDuration + $regexp = "(UP|DOWN) (IGNORE|USE) $p1_b $p1_b"; + + } elsif ($cmdType == 3) { # dimUpDownIncDecWithDuration + $regexp = "(UP|DOWN|NOMOTION) (IGNORE|USE) $p1_b " + ."$p1_b (INC|DEC|NOINCDEC) $p1_b"; + } + + return "$n: wrong format, see commandref" if($arg !~ m/$regexp/); + + my $bitfield = 0; + $bitfield |= ($2 eq "IGNORE") ? 0x01<<5 : 0x00; + $bitfield |= ($1 eq "DOWN") ? 0x01<<6 : + ($1 eq "NOMOTION") ? 0x03<<6 : 0x00; + if ($cmdType == 3) { + $bitfield |= ($5 eq "DEC") ? 0x01<<3 : + ($5 eq "NOINCDEC") ? 0x03<<3 : 0x00; + } + + $duration = ZWave_time2byte($hash,$4) if ($cmdType >=2); + + my $rt = sprintf("04%02x%02x", $bitfield, $3); + $rt .= sprintf("%02x", $duration) if ($cmdType == 2); + $rt .= sprintf("%02x%02x", $duration, $6) if ($cmdType == 3); + + return ("", $rt); + +} + +my %zwave_switchType = ( + "00"=>"Undefined", + "01"=>"On/Off", + "02"=>"Up/Down", + "03"=>"Open/Close", + "04"=>"Clockwise/Counter-Clockwise", + "05"=>"Right/Left", + "06"=>"Forward/Reverse", + "07"=>"Push/Pull", +); + +sub +Zwave_switchType($) +{ + my ($t) = @_; + $t = sprintf("%02x", hex($t)&0x1f); # clear reserved bits + return (($zwave_switchType{$t}) ? $zwave_switchType{$t} : "Unknown"); +} + +sub +ZWave_time2byte($$) +{ + my ($hash, $txt) = @_; + if($txt !~ m/^[0-9]+$/) { + Log 1, "ZWave_time2byte: wrong duration $txt, replacing it with 0"; + return "00"; + } + my $b = ($txt <= 0x7f ? $txt : int($txt/60)+0x7f); + $b = 0xfe if($b > 0xfe); + my $b2 = $b > 0x7f ? ($b - 0x7f) * 60 : $b; + my $n = ($hash ? $hash->{NAME} : "unknown"); + Log3 $n, 2, "$n: changing *for-timeout to $b2 from $txt" if($b2 != $txt); + return sprintf("%02x", $b); +} + +sub +ZWave_byte2time($) { my ($duration) = @_; my $time = hex($duration); - $time = ($time - 0x7f) * 60 if($time>0x7f && $time<=0xfd); - return (lc($duration) eq "fe" ? "unknown" : "$time seconds"); + $time = ($time - 0x7f) * 60 if($time>0x7f && $time<0xff); + return (lc($duration) eq "ff" ? "factoryDefault" : "$time seconds"); } ##################################### @@ -5648,18 +5751,76 @@ s2Hex($) switch the device on