diff --git a/contrib/HMCCU/FHEM/88_HMCCU.pm b/contrib/HMCCU/FHEM/88_HMCCU.pm index cfd0584e9..bfad73913 100644 --- a/contrib/HMCCU/FHEM/88_HMCCU.pm +++ b/contrib/HMCCU/FHEM/88_HMCCU.pm @@ -4,7 +4,7 @@ # # $Id: 88_HMCCU.pm 18745 2019-02-26 17:33:23Z zap $ # -# Version 4.4.013 +# Version 4.4.014 # # Module for communication between FHEM and Homematic CCU2/3. # @@ -56,7 +56,7 @@ my %HMCCU_CUST_CHN_DEFAULTS; my %HMCCU_CUST_DEV_DEFAULTS; # HMCCU version -my $HMCCU_VERSION = '4.4.013'; +my $HMCCU_VERSION = '4.4.014'; # Constants and default values my $HMCCU_MAX_IOERRORS = 100; @@ -8748,6 +8748,7 @@ sub HMCCU_GetDeviceStates ($) '0.STICKY_UNREACH' => 'stickyUnreach', '0.UPDATE_PENDING' => 'updPending' ); + my @stValKeys = ('0.LOWBAT', '0.UNREACH'); my %stVal = ( '0.LOWBAT' => '1|true:low,0|false:ok', '0.UNREACH' => '1|true:dead,0|false:alive' ); @@ -8763,7 +8764,7 @@ sub HMCCU_GetDeviceStates ($) $clHash->{hmccu}{dp}{$dp}{VALUES}{VAL} =~ /^(1|true)$/); } push @values, scalar(@state) > 0 ? join(',', @state) : 'ok'; - foreach my $dp (keys %stVal) { + foreach my $dp (@stValKeys) { if (exists($clHash->{hmccu}{dp}{$dp}) && exists($clHash->{hmccu}{dp}{$dp}{VALUES})&& defined($clHash->{hmccu}{dp}{$dp}{VALUES}{SVAL})) { push @values, $clHash->{hmccu}{dp}{$dp}{VALUES}{SVAL}; diff --git a/contrib/HMCCU/FHEM/88_HMCCUCHN.pm b/contrib/HMCCU/FHEM/88_HMCCUCHN.pm index 9bcca4049..5aaa24a62 100644 --- a/contrib/HMCCU/FHEM/88_HMCCUCHN.pm +++ b/contrib/HMCCU/FHEM/88_HMCCUCHN.pm @@ -4,7 +4,7 @@ # # $Id: 88_HMCCUCHN.pm 18552 2019-02-10 11:52:28Z zap $ # -# Version 4.4.012 +# Version 4.4.014 # # (c) 2020 zap (zap01 t-online de) # @@ -248,9 +248,6 @@ sub HMCCUCHN_Set ($@) return "No set command specified" if (!defined ($opt)); $opt = lc($opt); - my $rocmds = "clear defaults:noArg"; - my $rwcmds = "clear config control datapoint defaults:noArg values"; - # Get I/O device, check device state return undef if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' || !defined ($hash->{IODev})); @@ -278,16 +275,32 @@ sub HMCCUCHN_Set ($@) # Get additional commands (including state commands) my $roleCmds = HMCCU_GetSpecialCommands ($hash, $cc); + my %pset = ('V' => 'VALUES', 'M' => 'MASTER', 'D' => 'MASTER'); my $cmdList = ''; + my %valLookup; foreach my $cmd (keys %$roleCmds) { $cmdList .= " $cmd"; my @setList = split (/\s+/, $roleCmds->{$cmd}); foreach my $set (@setList) { my ($ps, $dpt, $par) = split(/:/, $set); - if ($par !~ /^\?/) { - my @argList = split (',', $par); - $cmdList .= scalar(@argList) > 1 ? ":$par" : ":noArg"; + my @argList = (); + if ($par =~ /^#/) { + my $adr = $ccuaddr; + $adr =~ s/:[0-9]{1,2}$//; + my $paramDef = HMCCU_GetParamDef ($ioHash, $adr, $pset{$ps}, $dpt); + if (defined($paramDef)) { + if ($paramDef->{TYPE} eq 'ENUM' && defined($paramDef->{VALUE_LIST})) { + $par = $paramDef->{VALUE_LIST}; + $par =~ s/[ ]+/-/g; + @argList = split (',', $par); + while (my ($i, $e) = each(@argList)) { $valLookup{$pset{$ps}}{$dpt}{$e} = $i; } + } + } } + elsif ($par !~ /^\?/) { + @argList = split (',', $par); + } + $cmdList .= scalar(@argList) > 1 ? ":$par" : ":noArg"; } } @@ -343,23 +356,6 @@ sub HMCCUCHN_Set ($@) $rc = HMCCU_SetMultipleDatapoints ($hash, \%dpval); return HMCCU_SetError ($hash, min(0, $rc)); } - elsif ($opt eq 'control') { - return HMCCU_SetError ($hash, -14) if ($cd eq ''); - if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $cc, $cd, 2)) { - HMCCU_Trace ($hash, 2, "Set", "Invalid datapoint $cc $cd"); - return HMCCU_SetError ($hash, -8); - } - my $objvalue = shift @$a; - return HMCCU_SetError ($hash, "Usage: set $name control {value}") if (!defined ($objvalue)); - - $objvalue =~ s/\\_/%20/g; - $objvalue =~ HMCCU_Substitute ($objvalue, $stateVals, 1, undef, ''); - - $rc = HMCCU_SetMultipleDatapoints ($hash, - { "001.$ccuif.$ccuaddr.$cd" => $objvalue } - ); - return HMCCU_SetError ($hash, min(0, $rc)); - } elsif ($opt eq 'toggle') { return HMCCU_SetError ($hash, -15) if ($stateVals eq ''); return HMCCU_SetError ($hash, -12) if ($cc eq ''); @@ -400,11 +396,10 @@ sub HMCCUCHN_Set ($@) my $i = 0; foreach my $set (@setList) { my ($ps, $dpt, $par) = split(/:/, $set); - $ps = $ps eq 'V' ? 'VALUES' : 'MASTER'; return HMCCU_SetError ($hash, "Syntax error in definition of command $opt") if (!defined($par)); - if (!HMCCU_IsValidParameter ($hash, $ccuaddr, $ps, $dpt)) { + if (!HMCCU_IsValidParameter ($hash, $ccuaddr, $pset{$ps}, $dpt)) { HMCCU_Trace ($hash, 2, "Set", "Invalid parameter $ps $dpt"); return HMCCU_SetError ($hash, -8); } @@ -416,8 +411,8 @@ sub HMCCUCHN_Set ($@) if (!defined($value) && defined($parDef)) { if ($parDef =~ /^[+-][0-9]+$/) { return HMCCU_SetError ($hash, "Current value of $cc.$dpt not available") - if (!defined($hash->{hmccu}{dp}{"$cc.$dpt"}{$ps}{SVAL})); - $value = $hash->{hmccu}{dp}{"$cc.$dpt"}{$ps}{SVAL}+int($parDef); + if (!defined($hash->{hmccu}{dp}{"$cc.$dpt"}{$pset{$ps}}{SVAL})); + $value = $hash->{hmccu}{dp}{"$cc.$dpt"}{$pset{$ps}}{SVAL}+int($parDef); } else { $value = $parDef; @@ -428,7 +423,14 @@ sub HMCCUCHN_Set ($@) if (!defined($value)); } else { - $value = $par; + if (exists($valLookup{$ps}{$dpt})) { + return HMCCU_SetError ($hash, "Illegal value $par. Use one of ".join(',', keys %{$valLookup{$ps}{$dpt}})) + if (!exists($valLookup{$ps}{$dpt}{$par})); + $value = $valLookup{$ps}{$dpt}{$par}; + } + else { + $value = $par; + } } if ($opt eq 'pct' || $opt eq 'level') { @@ -457,7 +459,7 @@ sub HMCCUCHN_Set ($@) last; } else { - if ($ps eq 'VALUES') { + if ($ps eq 'V') { my $no = sprintf ("%03d", $i); $dpval{"$i.$ccuif.$ccuaddr.$dpt"} = $value; $i++; @@ -579,7 +581,7 @@ sub HMCCUCHN_Set ($@) else { my $retmsg = "clear defaults:noArg"; if ($hash->{readonly} ne 'yes') { - $retmsg .= " config control"; + $retmsg .= " config"; $retmsg .= ':'.join(',', @states) if (scalar(@states) > 0); $retmsg .= " datapoint".$cmdList; $retmsg .= ' toggle:noArg' if (scalar(@states) > 0); diff --git a/contrib/HMCCU/FHEM/88_HMCCURPCPROC.pm b/contrib/HMCCU/FHEM/88_HMCCURPCPROC.pm index 420ff11ef..fcc4d214e 100755 --- a/contrib/HMCCU/FHEM/88_HMCCURPCPROC.pm +++ b/contrib/HMCCU/FHEM/88_HMCCURPCPROC.pm @@ -4,7 +4,7 @@ # # $Id: 88_HMCCURPCPROC.pm 18745 2019-02-26 17:33:23Z zap $ # -# Version 4.4.002 +# Version 4.4.003 # # Subprocess based RPC Server module for HMCCU. # @@ -38,7 +38,7 @@ require "$attr{global}{modpath}/FHEM/88_HMCCU.pm"; ###################################################################### # HMCCURPC version -my $HMCCURPCPROC_VERSION = '4.4.001'; +my $HMCCURPCPROC_VERSION = '4.4.003'; # Maximum number of events processed per call of Read() my $HMCCURPCPROC_MAX_EVENTS = 100; @@ -2342,7 +2342,8 @@ sub HMCCURPCPROC_Write ($$$$) # Try to send events immediately. Put them in queue if send fails my $rc = 0; my $err = ''; - if ($et ne 'ND' && $server->{hmccu}{ccuflags} !~ /queueEvents/) { +# if ($et ne 'ND' && $server->{hmccu}{ccuflags} !~ /queueEvents/) { + if ($server->{hmccu}{ccuflags} !~ /queueEvents/) { ($rc, $err) = HMCCURPCPROC_SendData ($server->{hmccu}{sockparent}, $ev); HMCCU_Log ($name, 3, "SendData $ev $err") if ($rc == 0); } @@ -2429,23 +2430,30 @@ sub HMCCURPCPROC_NewDevicesCB ($$$) my $devcount = scalar (@$a); HMCCU_Log ($name, 2, "$cb NewDevice received $devcount device and channel specifications"); - + + # Format: + # C/D|Address|Type|Version|Firmware|RxMode|Paramsets| + # LinkSourceRoles|LinkTargetRoles|Direction|Children|Parent|AESActive + foreach my $dev (@$a) { my $msg = ''; + my $ps = ref($dev->{PARAMSETS}) eq 'ARRAY' ? + join(',', @{$dev->{PARAMSETS}}) : $dev->{PARAMSETS}; if (defined($dev->{PARENT}) && $dev->{PARENT} ne '') { + my $lsr = ref($dev->{LINK_SOURCE_ROLES}) eq 'ARRAY' ? + join(',', @{$dev->{LINK_SOURCE_ROLES}}) : $dev->{LINK_SOURCE_ROLES}; + my $ltr = ref($dev->{LINK_TARGET_ROLES}) eq 'ARRAY' ? + join(',', @{$dev->{LINK_TARGET_ROLES}}) : $dev->{LINK_TARGET_ROLES}; $msg = "C|".$dev->{ADDRESS}."|".$dev->{TYPE}."|".$dev->{VERSION}. - "|null|null|".join(',',@{$dev->{PARAMSETS}}). - "|".join(',',@{$dev->{LINK_SOURCE_ROLES}}). - "|".join(',',@{$dev->{LINK_TARGET_ROLES}})."|".$dev->{DIRECTION}. + "|null|null|".$ps."|".$lsr."|".$ltr."|".$dev->{DIRECTION}. "|null|".$dev->{PARENT}."|".$dev->{AES_ACTIVE}; } else { # Wired devices do not have a RX_MODE attribute my $rx = exists ($dev->{RX_MODE}) ? $dev->{RX_MODE} : 'null'; $msg = "D|".$dev->{ADDRESS}."|".$dev->{TYPE}."|".$dev->{VERSION}."|". - $dev->{FIRMWARE}."|".$rx."|".join(',',@{$dev->{PARAMSETS}}). - "|null|null|null". - "|".join(',',@{$dev->{CHILDREN}})."|null|null"; + $dev->{FIRMWARE}."|".$rx."|".$ps."|null|null|null|". + join(',',@{$dev->{CHILDREN}})."|null|null"; } HMCCURPCPROC_Write ($server, "ND", $cb, $msg); } diff --git a/contrib/HMCCU/FHEM/HMCCUConf.pm b/contrib/HMCCU/FHEM/HMCCUConf.pm index d68a639bb..c68c84b43 100644 --- a/contrib/HMCCU/FHEM/HMCCUConf.pm +++ b/contrib/HMCCU/FHEM/HMCCUConf.pm @@ -35,12 +35,36 @@ use vars qw(%HMCCU_SCRIPTS); 'SHUTTER_CONTACT' => { F => 3, S => 'STATE', C => '', V => '' }, + 'SHUTTER_CONTACT_TRANSCEIVER' => { + F => 3, S => 'STATE', C => '', V => '' + }, + 'ROTARY_HANDLE_TRANSCEIVER' => { + F => 3, S => 'STATE', C => '', V => '' + }, + 'ALARM_SWITCH_VIRTUAL_RECEIVER' => { + F => 3, S => 'STATE', C => '', V => '' + }, + 'SMOKE_DETECTOR' => { + F => 3, S => 'SMOKE_DETECTOR_ALARM_STATUS', C => '', V => '' + }, + 'LUXMETER' => { + F => 3, S => 'LUX', C => '', V => '' + }, + 'MOTIONDETECTOR_TRANSCEIVER' => { + F => 3, S => 'MOTION', C => 'MOTION_DETECTION_ACTIVE', V => 'on:true,off:false' + }, 'KEY' => { F => 3, S => 'PRESS_SHORT', C => 'PRESS_SHORT', V => 'pressed:true' }, + 'KEY_TRANSCEIVER' => { + F => 3, S => 'PRESS_SHORT', C => 'PRESS_SHORT', V => 'pressed:true' + }, 'BLIND' => { F => 3, S => 'LEVEL', C => 'LEVEL', V => 'open:100,close:0' }, + 'BLIND_VIRTUAL_RECEIVER' => { + F => 3, S => 'LEVEL', C => 'LEVEL', V => 'open:100,close:0' + }, 'SWITCH' => { F => 3, S => 'STATE', C => 'STATE', V => 'on:true,off:false' }, @@ -50,6 +74,9 @@ use vars qw(%HMCCU_SCRIPTS); 'DIMMER' => { F => 3, S => 'LEVEL', C => 'LEVEL', V => 'on:100,off:0' }, + 'DIMMER_VIRTUAL_RECEIVER' => { + F => 3, S => 'LEVEL', C => 'LEVEL', V => 'on:100,off:0' + }, 'WEATHER_TRANSMIT' => { F => 1, S => 'TEMPERATURE', C => 'TEMPERATURE', V => '' }, @@ -73,16 +100,33 @@ use vars qw(%HMCCU_SCRIPTS); # Paramset:Datapoint:FixedValue[,FixedValue] # Paramset:Datapoint:?Parameter # Paramset:Datapoint:?Parameter=Default-Value +# Paramset:Datapoint:#Parameter # Paramset: -# V=VALUES or M=MASTER +# V=VALUES, M=MASTER (channel), D=MASTER (device) +# If Parameter is preceded by ? any value is accepted. +# If Parameter is preceded by # Datapoint must have type ENUM and +# valid values are taken from parameter set description. # If Default-Value is preceeded by + or -, value is added to or # subtracted from current datapoint value ###################################################################### %HMCCU_ROLECMDS = ( + 'MOTIONDETECTOR_TRANSCEIVER' => { + 'on' => 'V:MOTION_DETECTION_ACTIVE:true', + 'off' => 'V:MOTION_DETECTION_ACTIVE:false' + }, + 'SMOKE_DETECTOR' => { + 'command' => 'V:SMOKE_DETECTOR_COMMAND:#command' + }, 'KEY' => { 'on' => 'V:PRESS_SHORT:true', - 'off' => 'V:PRESS_SHORT:true' + 'off' => 'V:PRESS_SHORT:true', + 'press' => 'V:PRESS_SHORT:true' + }, + 'KEY_TRANSCEIVER' => { + 'on' => 'V:PRESS_SHORT:true', + 'off' => 'V:PRESS_SHORT:true', + 'press' => 'V:PRESS_SHORT:true' }, 'BLIND' => { 'pct' => 'V:LEVEL:?level', @@ -92,6 +136,22 @@ use vars qw(%HMCCU_SCRIPTS); 'down' => 'V:LEVEL:?delta=-10', 'stop' => 'V:STOP:true' }, + 'BLIND_VIRTUAL_RECEIVER' => { + 'pct' => 'V:LEVEL:?level', + 'open' => 'V:LEVEL:100', + 'close' => 'V:LEVEL:0', + 'up' => 'V:LEVEL:?delta=+10', + 'down' => 'V:LEVEL:?delta=-10', + 'stop' => 'V:STOP:true' + }, + 'SHUTTER_VIRTUAL_RECEIVER' => { + 'pct' => 'V:LEVEL:?level', + 'open' => 'V:LEVEL:100', + 'close' => 'V:LEVEL:0', + 'up' => 'V:LEVEL:?delta=+10', + 'down' => 'V:LEVEL:?delta=-10', + 'stop' => 'V:STOP:true' + }, 'SWITCH' => { 'on' => 'V:STATE:true', 'off' => 'V:STATE:false' @@ -106,13 +166,19 @@ use vars qw(%HMCCU_SCRIPTS); 'off' => 'V:LEVEL:0', 'stop' => 'V:RAMP_STOP:true' }, + 'DIMMER_VIRTUAL_RECEIVER' => { + 'pct' => 'V:LEVEL:?level', + 'on' => 'V:LEVEL:100', + 'off' => 'V:LEVEL:0' + }, 'THERMALCONTROL_TRANSMIT' => { 'desired-temp' => 'V:SET_TEMPERATURE:?temperature', 'manu' => 'V:MANU_MODE:?temperature', 'on' => 'V:MANU_MODE:30.5', 'off' => 'V:MANU_MODE:4.5', 'auto' => 'V:AUTO_MODE:true', - 'boost' => 'V:BOOST_MODE:true' + 'boost' => 'V:BOOST_MODE:true', + 'week-program' => 'D:WEEK_PROGRAM_POINTER:#program' }, 'CLIMATECONTROL_RT_TRANSCEIVER' => { 'desired-temp' => 'V:SET_TEMPERATURE:?temperature', @@ -140,39 +206,54 @@ use vars qw(%HMCCU_SCRIPTS); %HMCCU_ATTR = ( 'BLIND' => { 'ccureadingname' => 'LEVEL$:pct', - 'webCmd' => 'up:down:stop:control', - 'widgetOverride' => 'control:slider,0,10,100 pct:slider,0,10,100' + 'webCmd' => 'up:down:stop:pct', + 'widgetOverride' => 'pct:slider,0,10,100' + }, + 'BLIND_VIRTUAL_RECEIVER' => { + 'ccureadingname' => 'LEVEL$:pct', + 'webCmd' => 'up:down:stop:pct', + 'widgetOverride' => 'pct:slider,0,10,100' + }, + 'SHUTTER_VIRTUAL_RECEIVER' => { + 'ccureadingname' => 'LEVEL$:pct', + 'webCmd' => 'up:down:stop:pct', + 'widgetOverride' => 'pct:slider,0,10,100' }, 'SWITCH' => { - 'webCmd' => 'control', - 'widgetOverride' => 'control:uzsuToggle,off,on' + 'webCmd' => 'toggle', + 'widgetOverride' => 'toggle:uzsuToggle,off,on' }, 'SWITCH_VIRTUAL_RECEIVER' => { - 'webCmd' => 'control', - 'widgetOverride' => 'control:uzsuToggle,off,on' + 'webCmd' => 'toggle', + 'widgetOverride' => 'toggle:uzsuToggle,off,on' }, 'DIMMER' => { 'ccureadingname' => 'LEVEL$:pct', - 'webCmd' => 'control', - 'widgetOverride' => 'pct:slider,0,10,100 level:slider,0,10,100 control:slider,0,10,100' + 'webCmd' => 'pct', + 'widgetOverride' => 'pct:slider,0,10,100' + }, + 'DIMMER_VIRTUAL_RECEIVER' => { + 'ccureadingname' => 'LEVEL$:pct', + 'webCmd' => 'pct', + 'widgetOverride' => 'pct:slider,0,10,100' }, 'THERMALCONTROL_TRANSMIT' => { 'ccureadingname' => 'SET_TEMPERATURE$:desired-temp;ACTUAL_TEMPERATURE$:measured-temp', 'cmdIcon' => 'auto:sani_heating_automatic manu:sani_heating_manual boost:sani_heating_boost on:general_an off:general_aus', 'webCmd' => 'desired-temp:auto:manu:boost:on:off', - 'widgetOverride' => 'control:slider,4.5,0.5,30.5,1 desired-temp:slider,4.5,0.5,30.5,1' + 'widgetOverride' => 'desired-temp:slider,4.5,0.5,30.5,1' }, 'CLIMATECONTROL_RT_TRANSCEIVER' => { 'ccureadingname' => 'SET_TEMPERATURE$:desired-temp;ACTUAL_TEMPERATURE$:measured-temp', 'cmdIcon' => 'auto:sani_heating_automatic manu:sani_heating_manual boost:sani_heating_boost on:general_an off:general_aus', 'webCmd' => 'desired-temp', - 'widgetOverride' => 'control:slider,4.5,0.5,30.5,1 desired-temp:slider,4.5,0.5,30.5,1' + 'widgetOverride' => 'desired-temp:slider,4.5,0.5,30.5,1' }, 'HEATING_CLIMATECONTROL_TRANSCEIVER' => { 'ccureadingname' => 'SET_POINT_TEMPERATURE$:desired-temp;ACTUAL_TEMPERATURE$:measured-temp', 'cmdIcon' => 'auto:sani_heating_automatic manu:sani_heating_manual boost:sani_heating_boost on:general_an off:general_aus', 'webCmd' => 'desired-temp:auto:manu:boost', - 'widgetOverride' => 'control:slider,4.5,0.5,30.5,1 desired-temp:slider,4.5,0.5,30.5,1' + 'widgetOverride' => 'desired-temp:slider,4.5,0.5,30.5,1' } ); @@ -181,9 +262,29 @@ use vars qw(%HMCCU_SCRIPTS); ###################################################################### %HMCCU_CONVERSIONS = ( + 'MOTIONDETECTOR_TRANSCEIVER' => { + 'MOTION' => { '0' => 'noMotion', 'false' => 'noMotion', '1' => 'motion', 'true' => 'motion' }, + }, + 'KEY' => { + 'PRESS_SHORT' => { '1' => 'pressed', 'true' => 'pressed' }, + 'PRESS_LONG' => { '1' => 'pressed', 'true' => 'pressed' } + }, + 'KEY_TRANSCEIVER' => { + 'PRESS_SHORT' => { '1' => 'pressed', 'true' => 'pressed' }, + 'PRESS_LONG' => { '1' => 'pressed', 'true' => 'pressed' } + }, 'SHUTTER_CONTACT' => { 'STATE' => { '0' => 'closed', '1' => 'open', 'false' => 'closed', 'true' => 'open' } }, + 'SHUTTER_CONTACT_TRANSCEIVER' => { + 'STATE' => { '0' => 'closed', '1' => 'open', 'false' => 'closed', 'true' => 'open' } + }, + 'ROTARY_HANDLE_TRANSCEIVER' => { + 'STATE' => { '0' => 'closed', '1' => 'open', 'false' => 'closed', 'true' => 'open' } + }, + 'ALARM_SWITCH_VIRTUAL_RECEIVER' => { + 'STATE' => { '0' => 'ok', '1' => 'alarm', 'false' => 'ok', 'true' => 'alarm' } + }, 'SWITCH' => { 'STATE' => { '0' => 'off', 'false' => 'off', '1' => 'on', 'true' => 'on', 'off' => '0', 'on' => '1' }, }, @@ -193,11 +294,21 @@ use vars qw(%HMCCU_SCRIPTS); 'BLIND' => { 'LEVEL' => { '0' => 'closed', '100' => 'open', 'close' => '0', 'open' => '100' } }, + 'BLIND_VIRTUAL_RECEIVER' => { + 'LEVEL' => { '0' => 'closed', '100' => 'open', 'close' => '0', 'open' => '100' } + }, + 'SHUTTER_VIRTUAL_RECEIVER' => { + 'LEVEL' => { '0' => 'closed', '100' => 'open', 'close' => '0', 'open' => '100' } + }, 'DIMMER' => { 'LEVEL' => { '0' => 'off', '100' => 'on', 'off' => '0', 'on' => '100' } }, + 'DIMMER_VIRTUAL_RECEIVER' => { + 'LEVEL' => { '0' => 'off', '100' => 'on', 'off' => '0', 'on' => '100' } + }, 'THERMALCONTROL_TRANSMIT' => { - 'SET_TEMPERATURE' => { '4.5' => 'off', '30.5' => 'on' } + 'SET_TEMPERATURE' => { '4.5' => 'off', '30.5' => 'on' }, + 'WINDOW_OPEN_REPORTING' => { '0' => 'closed', '1' => 'open', 'false' => 'closed', 'true' => 'open' } }, 'CLIMATECONTROL_RT_TRANSCEIVER' => { 'SET_TEMPERATURE' => { '4.5' => 'off', '30.5' => 'on' }