2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-13 05:06:35 +00:00

HMCCU: Updated 4.4 Beta in contrib

git-svn-id: https://svn.fhem.de/fhem/trunk@23439 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2020-12-31 10:21:16 +00:00
parent 92e0ee22bf
commit c22732e3fd
5 changed files with 1043 additions and 486 deletions

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
# #
# $Id: 88_HMCCUCHN.pm 18552 2019-02-10 11:52:28Z zap $ # $Id: 88_HMCCUCHN.pm 18552 2019-02-10 11:52:28Z zap $
# #
# Version 4.4.029 # Version 4.4.031
# #
# (c) 2020 zap (zap01 <at> t-online <dot> de) # (c) 2020 zap (zap01 <at> t-online <dot> de)
# #
@ -47,12 +47,12 @@ sub HMCCUCHN_Initialize ($)
$hash->{parseParams} = 1; $hash->{parseParams} = 1;
$hash->{AttrList} = 'IODev ccucalculate '. $hash->{AttrList} = 'IODev ccucalculate '.
'ccuflags:multiple-strict,ackState,logCommand,noReadings,trace,showMasterReadings,showLinkReadings,showDeviceReadings '. 'ccuflags:multiple-strict,ackState,logCommand,noReadings,trace,showMasterReadings,showLinkReadings,showDeviceReadings,showServiceReadings '.
'ccureadingfilter:textField-long '. 'ccureadingfilter:textField-long '.
'ccureadingformat:name,namelc,address,addresslc '. 'ccureadingformat:name,namelc,address,addresslc '.
'ccureadingname:textField-long ccuSetOnChange ccuReadingPrefix '. 'ccureadingname:textField-long ccuSetOnChange ccuReadingPrefix '.
'ccuscaleval ccuverify:0,1,2 ccuget:State,Value controldatapoint '. 'ccuscaleval ccuverify:0,1,2 ccuget:State,Value '.
'disable:0,1 hmstatevals:textField-long statedatapoint statevals substitute:textField-long '. 'disable:0,1 hmstatevals:textField-long statevals substitute:textField-long '.
'substexcl stripnumber peer:textField-long traceFilter '. $readingFnAttributes; 'substexcl stripnumber peer:textField-long traceFilter '. $readingFnAttributes;
} }
@ -158,13 +158,16 @@ sub HMCCUCHN_InitDevice ($$)
$devHash->{ccutype} = $dt; $devHash->{ccutype} = $dt;
$devHash->{ccudevstate} = 'active'; $devHash->{ccudevstate} = 'active';
# Initialize user attributes
HMCCU_SetSCAttributes ($ioHash, $devHash);
if ($init_done) { if ($init_done) {
# Interactive device definition # Interactive device definition
HMCCU_AddDevice ($ioHash, $di, $da, $devHash->{NAME}); HMCCU_AddDevice ($ioHash, $di, $da, $devHash->{NAME});
HMCCU_UpdateDevice ($ioHash, $devHash); HMCCU_UpdateDevice ($ioHash, $devHash);
HMCCU_UpdateDeviceRoles ($ioHash, $devHash); HMCCU_UpdateDeviceRoles ($ioHash, $devHash);
my ($sc, $sd, $cc, $cd, $sdCnt, $cdCnt) = HMCCU_GetSpecialDatapoints ($devHash); my ($sc, $sd, $cc, $cd, $sdCnt, $cdCnt) = HMCCU_GetSCDatapoints ($devHash);
HMCCU_UpdateRoleCommands ($ioHash, $devHash, $cc); HMCCU_UpdateRoleCommands ($ioHash, $devHash, $cc);
HMCCU_UpdateAdditionalCommands ($ioHash, $devHash, $cc, $cd); HMCCU_UpdateAdditionalCommands ($ioHash, $devHash, $cc, $cd);
@ -252,13 +255,13 @@ sub HMCCUCHN_Set ($@)
my ($hash, $a, $h) = @_; my ($hash, $a, $h) = @_;
my $name = shift @$a; my $name = shift @$a;
my $opt = shift @$a // return 'No set command specified'; my $opt = shift @$a // return 'No set command specified';
$opt = lc($opt); my $lcopt = lc($opt);
# Check device state # Check device state
return "Device state doesn't allow set commands" return "Device state doesn't allow set commands"
if (!defined($hash->{ccudevstate}) || if (!defined($hash->{ccudevstate}) ||
$hash->{ccudevstate} eq 'pending' || !defined($hash->{IODev}) || $hash->{ccudevstate} eq 'pending' || !defined($hash->{IODev}) ||
($hash->{readonly} eq 'yes' && $opt !~ /^(\?|clear|config|defaults)$/) || ($hash->{readonly} eq 'yes' && $lcopt !~ /^(\?|clear|config|defaults)$/) ||
AttrVal ($name, 'disable', 0) == 1); AttrVal ($name, 'disable', 0) == 1);
my $ioHash = $hash->{IODev}; my $ioHash = $hash->{IODev};
@ -267,7 +270,7 @@ sub HMCCUCHN_Set ($@)
if (HMCCU_IsRPCStateBlocking ($ioHash)); if (HMCCU_IsRPCStateBlocking ($ioHash));
# Get state and control datapoints # Get state and control datapoints
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash); my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($hash);
# Additional commands, including state commands # Additional commands, including state commands
my $cmdList = $hash->{hmccu}{cmdlist}{set} // ''; my $cmdList = $hash->{hmccu}{cmdlist}{set} // '';
@ -275,7 +278,7 @@ sub HMCCUCHN_Set ($@)
# Some commands require a control datapoint # Some commands require a control datapoint
if ($opt =~ /^(control|toggle)$/) { if ($opt =~ /^(control|toggle)$/) {
return HMCCU_SetError ($hash, -14) if ($cd eq ''); return HMCCU_SetError ($hash, -14) if ($cd eq '');
return HMCCU_SetError ($hash, -8) return HMCCU_SetError ($hash, -8, $cd)
if (!HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $hash->{ccuaddr}, $cd, 2)); if (!HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $hash->{ccuaddr}, $cd, 2));
} }
@ -286,7 +289,7 @@ sub HMCCUCHN_Set ($@)
HMCCU_Log ($hash, 3, "set $name $opt ".join (' ', @$a)) HMCCU_Log ($hash, 3, "set $name $opt ".join (' ', @$a))
if ($opt ne '?' && (HMCCU_IsFlag ($name, 'logCommand') || HMCCU_IsFlag ($ioName, 'logCommand'))); if ($opt ne '?' && (HMCCU_IsFlag ($name, 'logCommand') || HMCCU_IsFlag ($ioName, 'logCommand')));
if ($opt eq 'control') { if ($lcopt eq 'control') {
my $value = shift @$a // return HMCCU_SetError ($hash, "Usage: set $name control {value}"); my $value = shift @$a // return HMCCU_SetError ($hash, "Usage: set $name control {value}");
my $stateVals = HMCCU_GetStateValues ($hash, $cd, $cc); my $stateVals = HMCCU_GetStateValues ($hash, $cd, $cc);
$rc = HMCCU_SetMultipleDatapoints ($hash, $rc = HMCCU_SetMultipleDatapoints ($hash,
@ -294,10 +297,10 @@ sub HMCCUCHN_Set ($@)
); );
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc)); return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
} }
elsif ($opt eq 'datapoint') { elsif ($lcopt eq 'datapoint') {
return HMCCU_ExecuteSetDatapointCommand ($hash, $a, $h, $cc, $cd); return HMCCU_ExecuteSetDatapointCommand ($hash, $a, $h, $cc, $cd);
} }
elsif ($opt eq 'toggle') { elsif ($lcopt eq 'toggle') {
return HMCCU_ExecuteToggleCommand ($hash, $cc, $cd); return HMCCU_ExecuteToggleCommand ($hash, $cc, $cd);
} }
elsif (exists($hash->{hmccu}{roleCmds}{set}{$opt})) { elsif (exists($hash->{hmccu}{roleCmds}{set}{$opt})) {
@ -306,10 +309,10 @@ sub HMCCUCHN_Set ($@)
elsif ($opt eq 'clear') { elsif ($opt eq 'clear') {
return HMCCU_ExecuteSetClearCommand ($hash, $a); return HMCCU_ExecuteSetClearCommand ($hash, $a);
} }
elsif ($opt =~ /^(config|values)$/) { elsif ($lcopt =~ /^(config|values)$/) {
return HMCCU_ExecuteSetParameterCommand ($ioHash, $hash, $opt, $a, $h); return HMCCU_ExecuteSetParameterCommand ($ioHash, $hash, $lcopt, $a, $h);
} }
elsif ($opt eq 'defaults') { elsif ($lcopt eq 'defaults') {
my $mode = shift @$a // 'update'; my $mode = shift @$a // 'update';
$rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, ctrlChn => $cc }); $rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, ctrlChn => $cc });
$rc = HMCCU_SetDefaults ($hash) if (!$rc); $rc = HMCCU_SetDefaults ($hash) if (!$rc);
@ -319,10 +322,14 @@ sub HMCCUCHN_Set ($@)
else { else {
my $retmsg = "clear defaults:reset,update"; my $retmsg = "clear defaults:reset,update";
if ($hash->{readonly} ne 'yes') { if ($hash->{readonly} ne 'yes') {
$retmsg .= ' config datapoint'; $retmsg .= ' config';
my ($a, $c) = split(":", $hash->{ccuaddr});
my $dpCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, $c, 2);
$retmsg .= ' datapoint' if ($dpCount > 0);
$retmsg .= " $cmdList" if ($cmdList ne ''); $retmsg .= " $cmdList" if ($cmdList ne '');
} }
return AttrTemplate_Set ($hash, $retmsg, $name, $opt, @$a); # return AttrTemplate_Set ($hash, $retmsg, $name, $opt, @$a);
return $retmsg;
} }
} }
@ -335,7 +342,7 @@ sub HMCCUCHN_Get ($@)
my ($hash, $a, $h) = @_; my ($hash, $a, $h) = @_;
my $name = shift @$a; my $name = shift @$a;
my $opt = shift @$a // return 'No get command specified'; my $opt = shift @$a // return 'No get command specified';
$opt = lc($opt); my $lcopt = lc($opt);
return undef if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' || return undef if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' ||
!defined ($hash->{IODev})); !defined ($hash->{IODev}));
@ -353,7 +360,7 @@ sub HMCCUCHN_Get ($@)
my $ccuaddr = $hash->{ccuaddr}; my $ccuaddr = $hash->{ccuaddr};
my $ccuif = $hash->{ccuif}; my $ccuif = $hash->{ccuif};
my $ccuflags = AttrVal ($name, 'ccuflags', 'null'); my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash); my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($hash);
# Additional commands, including state commands # Additional commands, including state commands
my $cmdList = $hash->{hmccu}{cmdlist}{get} // ''; my $cmdList = $hash->{hmccu}{cmdlist}{get} // '';
@ -365,45 +372,40 @@ sub HMCCUCHN_Get ($@)
HMCCU_Log ($hash, 3, "get $name $opt ".join (' ', @$a)) HMCCU_Log ($hash, 3, "get $name $opt ".join (' ', @$a))
if ($opt ne '?' && $ccuflags =~ /logCommand/ || HMCCU_IsFlag ($ioName, 'logCommand')); if ($opt ne '?' && $ccuflags =~ /logCommand/ || HMCCU_IsFlag ($ioName, 'logCommand'));
if ($opt eq 'datapoint') { if ($lcopt eq 'datapoint') {
my $objname = shift @$a // return HMCCU_SetError ($hash, "Usage: get $name datapoint {datapoint}"); my $objname = shift @$a // return HMCCU_SetError ($hash, "Usage: get $name datapoint {datapoint}");
return HMCCU_SetError ($hash, -8) return HMCCU_SetError ($hash, -8, $objname)
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $objname, 1)); if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $objname, 1));
$objname = $ccuif.'.'.$ccuaddr.'.'.$objname; $objname = $ccuif.'.'.$ccuaddr.'.'.$objname;
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname, 0); ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname, 0);
return $rc < 0 ? HMCCU_SetError ($hash, $rc, $result) : $result; return $rc < 0 ? HMCCU_SetError ($hash, $rc, $result) : $result;
} }
elsif ($opt eq 'deviceinfo') { elsif ($lcopt eq 'deviceinfo') {
my ($devAddr, undef) = HMCCU_SplitChnAddr ($ccuaddr); my ($devAddr, undef) = HMCCU_SplitChnAddr ($ccuaddr);
return HMCCU_ExecuteGetDeviceInfoCommand ($ioHash, $hash, $devAddr, $sc, $sd, $cc, $cd); return HMCCU_ExecuteGetDeviceInfoCommand ($ioHash, $hash, $devAddr, $sc, $sd, $cc, $cd);
} }
elsif ($opt =~ /^(config|values|update)$/) { elsif ($lcopt =~ /^(config|values|update)$/) {
my ($devAddr, undef) = HMCCU_SplitChnAddr ($ccuaddr); my ($devAddr, undef) = HMCCU_SplitChnAddr ($ccuaddr);
my @addList = ($devAddr, "$devAddr:0", $ccuaddr); my @addList = ($devAddr, "$devAddr:0", $ccuaddr);
my $resp = HMCCU_ExecuteGetParameterCommand ($ioHash, $hash, $opt, \@addList); my $resp = HMCCU_ExecuteGetParameterCommand ($ioHash, $hash, $lcopt, \@addList);
return HMCCU_SetError ($hash, "Can't get device description") if (!defined($resp)); return HMCCU_SetError ($hash, "Can't get device description") if (!defined($resp));
return HMCCU_DisplayGetParameterResult ($ioHash, $hash, $resp); return HMCCU_DisplayGetParameterResult ($ioHash, $hash, $resp);
} }
elsif ($opt eq 'paramsetdesc') { elsif ($lcopt eq 'paramsetdesc') {
$result = HMCCU_ParamsetDescToStr ($ioHash, $hash); $result = HMCCU_ParamsetDescToStr ($ioHash, $hash);
return defined($result) ? $result : HMCCU_SetError ($hash, "Can't get device model"); return defined($result) ? $result : HMCCU_SetError ($hash, "Can't get device model");
} }
elsif (exists($hash->{hmccu}{roleCmds}{get}{$opt})) { elsif (exists($hash->{hmccu}{roleCmds}{get}{$opt})) {
return HMCCU_ExecuteRoleCommand ($ioHash, $hash, 'get', $opt, $cc, $a, $h); return HMCCU_ExecuteRoleCommand ($ioHash, $hash, 'get', $opt, $cc, $a, $h);
} }
elsif ($opt eq 'defaults') {
return HMCCU_GetDefaults ($hash, 0);
}
else { else {
my $retmsg = "HMCCUCHN: Unknown argument $opt, choose one of defaults:noArg datapoint"; my $retmsg = "HMCCUCHN: Unknown argument $opt, choose one of";
$retmsg .= ' update:noArg deviceInfo:noArg config:noArg paramsetDesc:noArg values:noArg';
my ($a, $c) = split(":", $hash->{ccuaddr}); my ($a, $c) = split(":", $hash->{ccuaddr});
my @valuelist; my @dpList;
my $valuecount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, $c, 1, \@valuelist); my $dpCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, $c, 1, \@dpList);
$retmsg .= ":".join(",",@valuelist) if ($valuecount > 0); $retmsg .= ' datapoint:'.join(",",@dpList) if ($dpCount > 0);
$retmsg .= " update:noArg deviceInfo:noArg config:noArg".
" paramsetDesc:noArg values:noArg";
$retmsg .= " $cmdList" if ($cmdList ne ''); $retmsg .= " $cmdList" if ($cmdList ne '');
return $retmsg; return $retmsg;
@ -422,8 +424,8 @@ sub HMCCUCHN_Get ($@)
<h3>HMCCUCHN</h3> <h3>HMCCUCHN</h3>
<ul> <ul>
The module implements Homematic CCU channels as client devices for HMCCU. A HMCCU I/O device must The module implements Homematic CCU channels as client devices for HMCCU. A HMCCU I/O device must
exist before a client device can be defined. If a CCU channel is not found execute command exist before a client device can be defined. If a CCU channel is not found, execute command
'get devicelist' in I/O device. This will synchronize devices and channels between CCU 'get ccuConfig' in I/O device. This will synchronize devices and channels between CCU
and HMCCU. and HMCCU.
</br></br> </br></br>
<a name="HMCCUCHNdefine"></a> <a name="HMCCUCHNdefine"></a>
@ -440,9 +442,23 @@ sub HMCCUCHN_Get ($@)
<code>define window_living HMCCUCHN WIN-LIV-1 readonly</code><br/> <code>define window_living HMCCUCHN WIN-LIV-1 readonly</code><br/>
<code>define temp_control HMCCUCHN BidCos-RF.LEQ1234567:1</code> <code>define temp_control HMCCUCHN BidCos-RF.LEQ1234567:1</code>
<br/><br/> <br/><br/>
The interface part of a channel address is optional. The interface part of a channel address is optional. Channel addresses can be found with command
Channel addresses can be found with command 'get deviceinfo &lt;CCU-DeviceName&gt;' executed 'get deviceinfo &lt;CCU-DeviceName&gt;' executed in I/O device.<br/><br/>
in I/O device. Internals:<br/>
<ul>
<li>ccuaddr: Address of channel in CCU</li>
<li>ccudevstate: State of device in CCU (active/inactive/dead)</li>
<li>ccuif: Interface of device</li>
<li>ccuname: Name of channel in CCU</li>
<li>ccurole: Role of channel</li>
<li>ccusubtype: Homematic subtype of device (different from ccutype for HmIP devices)</li>
<li>ccutype: Homematic type of device</li>
<li>readonly: Indicates whether FHEM device is writeable</li>
<li>receiver: List of peered devices with role 'receiver'. If no FHEM device exists for a receiver, the
name of the CCU device is displayed preceeded by 'ccu:'</li>
<li>sender: List of peered devices with role 'sender'. If no FHEM device exists for a sender, the
name of the CCU device is displayed preceeded by 'ccu:'</li>
</ul>
</ul> </ul>
<br/> <br/>
@ -480,7 +496,7 @@ sub HMCCUCHN_Get ($@)
</li><br/> </li><br/>
<li><b>set &lt;name&gt; datapoint &lt;datapoint&gt; &lt;value&gt; | &lt;datapoint&gt=&lt;value&gt; [...]</b><br/> <li><b>set &lt;name&gt; datapoint &lt;datapoint&gt; &lt;value&gt; | &lt;datapoint&gt=&lt;value&gt; [...]</b><br/>
Set datapoint values of a CCU channel. If value contains blank characters it must be Set datapoint values of a CCU channel. If value contains blank characters it must be
enclosed in double quotes.<br/><br/> enclosed in double quotes. This command is only available, if channel contains a writeable datapoint.<br/><br/>
Examples:<br/> Examples:<br/>
<code>set temp_control datapoint SET_TEMPERATURE 21</code><br/> <code>set temp_control datapoint SET_TEMPERATURE 21</code><br/>
<code>set temp_control datapoint AUTO_MODE 1 SET_TEMPERATURE=21</code> <code>set temp_control datapoint AUTO_MODE 1 SET_TEMPERATURE=21</code>
@ -523,14 +539,14 @@ sub HMCCUCHN_Get ($@)
channel contains a datapoint STOP. channel contains a datapoint STOP.
</li><br/> </li><br/>
<li><b>set &lt;name&gt; toggle</b><br/> <li><b>set &lt;name&gt; toggle</b><br/>
Toggle state datapoint between values defined by attribute 'statevals'. This command is Toggle state datapoint between values defined by attribute 'statevals'. This command is
only available if state values can be detected or are defined by using attribute only available if state values can be detected or are defined by using attribute
'statevals'. Toggling supports more than two state values.<br/><br/> 'statevals'. Toggling supports more than two state values.<br/><br/>
Example: Toggle blind actor<br/> Example: Toggle blind actor<br/>
<code> <code>
attr myswitch statevals up:100,down:0<br/> attr myswitch statevals up:100,down:0<br/>
set myswitch toggle set myswitch toggle
</code> </code>
</li><br/> </li><br/>
<li><b>set &lt;name&gt; up [&lt;value&gt;]</b><br/> <li><b>set &lt;name&gt; up [&lt;value&gt;]</b><br/>
[blind,dimmer] Increment value of datapoint LEVEL. This command is only available [blind,dimmer] Increment value of datapoint LEVEL. This command is only available
@ -549,38 +565,51 @@ sub HMCCUCHN_Get ($@)
<b>Get</b><br/><br/> <b>Get</b><br/><br/>
<ul> <ul>
<li><b>get &lt;name&gt; config</b><br/> <li><b>get &lt;name&gt; config</b><br/>
Get configuration parameters of device and channel. Get configuration parameters of device and channel.
Values related to configuration or link parameters are stored as readings beginning Values related to configuration or link parameters are stored as readings beginning
with "R-" for MASTER parameter set and "L-" for LINK parameter set. with "R-" for MASTER parameter set and "L-" for LINK parameter set.
Prefixes can be modified with attribute 'ccuReadingPrefix'. Whether parameters are Prefixes "R-" and "L-" can be modified with attribute 'ccuReadingPrefix'. Whether parameters are
stored as readings or not, can be controlled by setting the following flags in stored as readings or not, can be controlled by setting the following flags in
attribute ccuflags:<br/> attribute ccuflags:<br/>
noReadings: Do not store any reading.<br/> <ul>
showMasterReadings: Store configuration readings of current channel.<br/> <li>noReadings: Do not store any reading.</li>
showDeviceReadings: Store readings of device and channel 0.<br/> <li>showMasterReadings: Store configuration readings of parameter set 'MASTER' of current channel.</li>
showLinkReadings: Store readings of links.<br/> <li>showDeviceReadings: Store configuration readings of device and value readings of channel 0.</li>
If non of the flags is set, only readings belonging to parameter set VALUES (datapoints) <li>showLinkReadings: Store readings of links.</li>
are stored. <li>showServiceReadings: Store readings of parameter set 'SERVICE'</li>
</ul>
If non of the flags is set, only readings belonging to parameter set VALUES (datapoints)
are stored.
</li><br/> </li><br/>
<li><b>get &lt;name&gt; datapoint &lt;datapoint&gt;</b><br/> <li><b>get &lt;name&gt; datapoint &lt;datapoint&gt;</b><br/>
Get value of a CCU channel datapoint. Get value of a CCU channel datapoint. Format of <i>datapoint</i> is ChannelNo.DatapointName.
For HMCCUCHN devices the ChannelNo is not needed. This command is only available if a
readable datapoint exists.
</li><br/> </li><br/>
<li><b>get &lt;name&gt; defaults</b><br/> <li><b>get &lt;name&gt; defaults</b><br/>
Display default attributes for CCU device type. This command has been removed in version 4.4. The default attributes are included in the
output of command 'get deviceInfo'.
</li><br/> </li><br/>
<li><b>get &lt;name&gt; deviceInfo</b><br/> <li><b>get &lt;name&gt; deviceInfo</b><br/>
Display information about device and channels:<br/> Display information about device type and channels:<br/>
<ul> <ul>
<li>all channels and datapoints of device with datapoint values and types</li> <li>all channels and datapoints of device with datapoint values and types</li>
<li>statedatapoint and controldatapoint</li> <li>statedatapoint and controldatapoint</li>
<li>device and channel description</li> <li>device and channel description</li>
</ul> <li>default attributes (if device is not supported by built in functionality)</li>
</ul>
The output of this command is helpful to gather information about new / not yet supported devices.
Please add this information to your post in the FHEM forum, if you have a question about
the integration of a new device. See also command 'get paramsetDesc'.
</li><br/> </li><br/>
<li><b>get &lt;name&gt; paramsetDesc</b><br/> <li><b>get &lt;name&gt; paramsetDesc</b><br/>
Display description of parameter sets of channel and device. Display description of parameter sets of channel and device. The output of this command
is helpful to gather information about new / not yet supported devices. Please add this
information to your post in the FHEM forum, if you have a question about
the integration of a new device. See also command 'get deviceInfo'.
</li><br/> </li><br/>
<li><b>get &lt;name&gt; update</b><br/> <li><b>get &lt;name&gt; update</b><br/>
Update all readings for all parameters of all parameter sets (MASTER, LINK, VALUES). Update all readings for all parameters of all parameter sets (MASTER, LINK, VALUES).
</li><br/> </li><br/>
<li><b>get &lt;name&gt; values</b><br/> <li><b>get &lt;name&gt; values</b><br/>
Update all readings for all parameters of parameter set VALUES (datapoints). Update all readings for all parameters of parameter set VALUES (datapoints).
@ -624,6 +653,7 @@ sub HMCCUCHN_Get ($@)
showDeviceReadings: Show readings of device and channel 0.<br/> showDeviceReadings: Show readings of device and channel 0.<br/>
showLinkReadings: Show link readings.<br/> showLinkReadings: Show link readings.<br/>
showMasterReadings: Show configuration readings.<br/> showMasterReadings: Show configuration readings.<br/>
showServiceReadings: Show service readings (HmIP only)<br/>
trace: Write log file information for operations related to this device. trace: Write log file information for operations related to this device.
</li><br/> </li><br/>
<a name="ccuget"></a> <a name="ccuget"></a>
@ -686,8 +716,12 @@ sub HMCCUCHN_Get ($@)
</li><br/> </li><br/>
<a name="ccuReadingPrefix"></a> <a name="ccuReadingPrefix"></a>
<li><b>ccuReadingPrefix &lt;paramset&gt;:&lt;prefix&gt;[,...]</b><br/> <li><b>ccuReadingPrefix &lt;paramset&gt;:&lt;prefix&gt;[,...]</b><br/>
Set reading name prefix for parameter sets. The special parameter set 'peer' can Set reading name prefix for parameter sets. Default values for parameter sets are:<br/>
be used for link readings. VALUES (state values): No prefix<br/>
MASTER (configuration parameters): 'R-'<br/>
LINK (links parameters): 'L-'<br/>
PEER (peering parameters): 'P-'<br/>
SERVICE (service parameters): S-<br/>
</li><br/> </li><br/>
<a name="ccuscaleval"></a> <a name="ccuscaleval"></a>
<li><b>ccuscaleval &lt;[channelno.]datapoint&gt;:&lt;factor&gt;[,...]</b><br/> <li><b>ccuscaleval &lt;[channelno.]datapoint&gt;:&lt;factor&gt;[,...]</b><br/>

View File

@ -4,7 +4,7 @@
# #
# $Id: 88_HMCCUDEV.pm 18552 2019-02-10 11:52:28Z zap $ # $Id: 88_HMCCUDEV.pm 18552 2019-02-10 11:52:28Z zap $
# #
# Version 4.4.034 # Version 4.4.037
# #
# (c) 2020 zap (zap01 <at> t-online <dot> de) # (c) 2020 zap (zap01 <at> t-online <dot> de)
# #
@ -47,13 +47,13 @@ sub HMCCUDEV_Initialize ($)
$hash->{parseParams} = 1; $hash->{parseParams} = 1;
$hash->{AttrList} = 'IODev ccuaggregate:textField-long ccucalculate:textField-long '. $hash->{AttrList} = 'IODev ccuaggregate:textField-long ccucalculate:textField-long '.
'ccuflags:multiple-strict,ackState,logCommand,noReadings,trace,showMasterReadings,showLinkReadings,showDeviceReadings '. 'ccuflags:multiple-strict,ackState,logCommand,noReadings,trace,showMasterReadings,showLinkReadings,showDeviceReadings,showServiceReadings '.
'ccureadingfilter:textField-long '. 'ccureadingfilter:textField-long '.
'ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc '. 'ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc '.
'ccureadingname:textField-long ccuSetOnChange ccuReadingPrefix '. 'ccureadingname:textField-long ccuSetOnChange ccuReadingPrefix '.
'ccuget:State,Value ccuscaleval ccuverify:0,1,2 disable:0,1 '. 'ccuget:State,Value ccuscaleval ccuverify:0,1,2 disable:0,1 '.
'hmstatevals:textField-long statevals substexcl substitute:textField-long statechannel '. 'hmstatevals:textField-long statevals substexcl substitute:textField-long statechannel '.
'controlchannel statedatapoint controldatapoint stripnumber peer:textField-long traceFilter '. 'controlchannel stripnumber peer:textField-long traceFilter '.
$readingFnAttributes; $readingFnAttributes;
} }
@ -67,7 +67,7 @@ sub HMCCUDEV_Define ($@)
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $usage = "Usage: define $name HMCCUDEV {device|'virtual'} [control-channel] ". my $usage = "Usage: define $name HMCCUDEV {device|'virtual'} [control-channel] ".
"['readonly'] ['noDefaults'|'defaults'] [iodev={iodev-name}] [address={virtual-device-no}]". "['readonly'] ['noDefaults'|'defaults'] [force] [iodev={iodev-name}] [address={virtual-device-no}]".
"[{groupexp=regexp|group={device|channel}[,...]]"; "[{groupexp=regexp|group={device|channel}[,...]]";
return $usage if (scalar(@$a) < 3); return $usage if (scalar(@$a) < 3);
@ -80,7 +80,7 @@ sub HMCCUDEV_Define ($@)
"Type of virtual device not defined", "Type of virtual device not defined",
"Device type not found", "Device type not found",
"Too many virtual devices", "Too many virtual devices",
"Control channel ambiguous. Please specify control channel in device definition" "Use HMCCUCHN instead"
); );
my @warnmsg = ( my @warnmsg = (
@ -112,6 +112,7 @@ sub HMCCUDEV_Define ($@)
if ($arg eq 'readonly') { $hash->{readonly} = 'yes'; } if ($arg eq 'readonly') { $hash->{readonly} = 'yes'; }
elsif (lc($arg) eq 'nodefaults' && $init_done) { $hash->{hmccu}{nodefaults} = 1; } elsif (lc($arg) eq 'nodefaults' && $init_done) { $hash->{hmccu}{nodefaults} = 1; }
elsif ($arg eq 'defaults' && $init_done) { $hash->{hmccu}{nodefaults} = 0; } elsif ($arg eq 'defaults' && $init_done) { $hash->{hmccu}{nodefaults} = 0; }
elsif ($arg eq 'force') { $hash->{hmccu}{forcedev} = 1; }
elsif ($arg =~ /^[0-9]+$/) { $attr{$name}{controlchannel} = $arg; } elsif ($arg =~ /^[0-9]+$/) { $attr{$name}{controlchannel} = $arg; }
else { return $usage; } else { return $usage; }
} }
@ -146,9 +147,14 @@ sub HMCCUDEV_Define ($@)
# Initialize FHEM device, set IO device # Initialize FHEM device, set IO device
my $rc = HMCCUDEV_InitDevice ($ioHash, $hash); my $rc = HMCCUDEV_InitDevice ($ioHash, $hash);
return $errmsg[$rc] if ($rc > 0 && $rc < scalar(@errmsg)); if (HMCCU_IsIntNum ($rc)) {
HMCCU_LogDisplay ($hash, 2, $warnmsg[-$rc]) if ($init_done && $rc < 0 && -$rc < scalar(@warnmsg)); return $errmsg[$rc] if ($rc > 0 && $rc < scalar(@errmsg));
return undef; HMCCU_LogDisplay ($hash, 2, $warnmsg[-$rc]) if ($init_done && $rc < 0 && -$rc < scalar(@warnmsg));
return undef;
}
else {
return $rc;
}
} }
###################################################################### ######################################################################
@ -205,33 +211,42 @@ sub HMCCUDEV_InitDevice ($$)
my ($di, $da, $dn, $dt, $dc) = HMCCU_GetCCUDeviceParam ($ioHash, $devspec); my ($di, $da, $dn, $dt, $dc) = HMCCU_GetCCUDeviceParam ($ioHash, $devspec);
return 1 if (!defined($da)); return 1 if (!defined($da));
$gdname = $dn; $gdname = $dn;
# Inform HMCCU device about client device
return 2 if (!HMCCU_AssignIODevice ($devHash, $ioHash->{NAME}));
$devHash->{ccuif} = $di; $devHash->{ccuif} = $di;
$devHash->{ccuaddr} = $da; $devHash->{ccuaddr} = $da;
$devHash->{ccuname} = $dn; $devHash->{ccuname} = $dn;
$devHash->{ccutype} = $dt; $devHash->{ccutype} = $dt;
$devHash->{ccudevstate} = 'active';
$devHash->{hmccu}{channels} = $dc; $devHash->{hmccu}{channels} = $dc;
# Initialize user attributes
my $detect = HMCCU_DetectDevice ($ioHash, $da, $di);
HMCCU_SetSCAttributes ($ioHash, $devHash, $detect);
# Inform HMCCU device about client device
return 2 if (!HMCCU_AssignIODevice ($devHash, $ioHash->{NAME}));
$devHash->{ccudevstate} = 'active';
if ($init_done) { if ($init_done) {
return "Specify option 'force' for HMCCUDEV or use HMCCUCHN instead (recommended). Command: define $name HMCCUCHN $detect->{defAdd}"
if (defined($detect) && $detect->{defMod} eq 'HMCCUCHN' && $devHash->{hmccu}{forcedev} == 0);
# Interactive device definition # Interactive device definition
HMCCU_AddDevice ($ioHash, $di, $da, $devHash->{NAME}); HMCCU_AddDevice ($ioHash, $di, $da, $devHash->{NAME});
HMCCU_UpdateDevice ($ioHash, $devHash); HMCCU_UpdateDevice ($ioHash, $devHash);
HMCCU_UpdateDeviceRoles ($ioHash, $devHash); HMCCU_UpdateDeviceRoles ($ioHash, $devHash);
my ($sc, $sd, $cc, $cd, $sdCnt, $cdCnt) = HMCCU_GetSpecialDatapoints ($devHash); my ($sc, $sd, $cc, $cd, $sdCnt, $cdCnt) = HMCCU_GetSCDatapoints ($devHash);
return -1 if ($cdCnt > 2); return -1 if ($cdCnt >= 2);
HMCCU_UpdateRoleCommands ($ioHash, $devHash, $cc); HMCCU_UpdateRoleCommands ($ioHash, $devHash, $cc);
HMCCU_UpdateAdditionalCommands ($ioHash, $devHash, $cc, $cd); HMCCU_UpdateAdditionalCommands ($ioHash, $devHash, $cc, $cd);
if (!exists($devHash->{hmccu}{nodefaults}) || $devHash->{hmccu}{nodefaults} == 0) { if (!exists($devHash->{hmccu}{nodefaults}) || $devHash->{hmccu}{nodefaults} == 0) {
my $chn = $cc eq '' ? ($sc eq '' ? undef : $sc) : $cc;
if (!HMCCU_SetDefaultAttributes ($devHash, { if (!HMCCU_SetDefaultAttributes ($devHash, {
mode => 'update', role => undef, ctrlChn => $cc eq '' ? undef : $cc mode => 'update', role => undef, roleChn => $chn,
})) { })) {
HMCCU_Log ($devHash, 2, "No role attributes found"); HMCCU_Log ($devHash, 2, "No role attributes found");
HMCCU_SetDefaults ($devHash); HMCCU_SetDefaults ($devHash);
@ -387,7 +402,7 @@ sub HMCCUDEV_Set ($@)
my ($hash, $a, $h) = @_; my ($hash, $a, $h) = @_;
my $name = shift @$a; my $name = shift @$a;
my $opt = shift @$a // return 'No set command specified'; my $opt = shift @$a // return 'No set command specified';
$opt = lc($opt); my $lcopt = lc($opt);
# Check device state # Check device state
return "Device state doesn't allow set commands" return "Device state doesn't allow set commands"
@ -401,16 +416,16 @@ sub HMCCUDEV_Set ($@)
if (HMCCU_IsRPCStateBlocking ($ioHash)); if (HMCCU_IsRPCStateBlocking ($ioHash));
# Get state and control datapoints # Get state and control datapoints
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash); my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($hash);
# Get additional commands # Get additional commands
my $cmdList = $hash->{hmccu}{cmdlist}{set} // ''; my $cmdList = $hash->{hmccu}{cmdlist}{set} // '';
# Some commands require a control channel and datapoint # Some commands require a control channel and datapoint
if ($opt =~ /^(control|toggle)$/) { if ($lcopt =~ /^(control|toggle)$/) {
return HMCCU_SetError ($hash, -14) if ($cd eq ''); return HMCCU_SetError ($hash, -14) if ($cd eq '');
return HMCCU_SetError ($hash, -12) if ($cc eq ''); return HMCCU_SetError ($hash, -12) if ($cc eq '');
return HMCCU_SetError ($hash, -8) return HMCCU_SetError ($hash, -8, $cd)
if (!HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $cc, $cd, 2)); if (!HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $cc, $cd, 2));
return HMCCU_SetError ($hash, -7) if ($cc >= $hash->{hmccu}{channels}); return HMCCU_SetError ($hash, -7) if ($cc >= $hash->{hmccu}{channels});
} }
@ -422,7 +437,7 @@ sub HMCCUDEV_Set ($@)
HMCCU_Log ($hash, 3, "set $name $opt ".join (' ', @$a)) HMCCU_Log ($hash, 3, "set $name $opt ".join (' ', @$a))
if ($opt ne '?' && (HMCCU_IsFlag ($name, 'logCommand') || HMCCU_IsFlag ($ioName, 'logCommand'))); if ($opt ne '?' && (HMCCU_IsFlag ($name, 'logCommand') || HMCCU_IsFlag ($ioName, 'logCommand')));
if ($opt eq 'control') { if ($lcopt eq 'control') {
my $value = shift @$a // return HMCCU_SetError ($hash, "Usage: set $name control {value}"); my $value = shift @$a // return HMCCU_SetError ($hash, "Usage: set $name control {value}");
my $stateVals = HMCCU_GetStateValues ($hash, $cd, $cc); my $stateVals = HMCCU_GetStateValues ($hash, $cd, $cc);
$rc = HMCCU_SetMultipleDatapoints ($hash, $rc = HMCCU_SetMultipleDatapoints ($hash,
@ -430,22 +445,22 @@ sub HMCCUDEV_Set ($@)
); );
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc)); return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
} }
elsif ($opt eq 'datapoint') { elsif ($lcopt eq 'datapoint') {
return HMCCU_ExecuteSetDatapointCommand ($hash, $a, $h, $cc, $cd); return HMCCU_ExecuteSetDatapointCommand ($hash, $a, $h, $cc, $cd);
} }
elsif ($opt eq 'toggle') { elsif ($lcopt eq 'toggle') {
return HMCCU_ExecuteToggleCommand ($hash, $cc, $cd); return HMCCU_ExecuteToggleCommand ($hash, $cc, $cd);
} }
elsif (exists($hash->{hmccu}{roleCmds}{set}{$opt})) { elsif (exists($hash->{hmccu}{roleCmds}{set}{$opt})) {
return HMCCU_ExecuteRoleCommand ($ioHash, $hash, 'set', $opt, $cc, $a, $h); return HMCCU_ExecuteRoleCommand ($ioHash, $hash, 'set', $opt, $cc, $a, $h);
} }
elsif ($opt eq 'clear') { elsif ($lcopt eq 'clear') {
return HMCCU_ExecuteSetClearCommand ($hash, $a); return HMCCU_ExecuteSetClearCommand ($hash, $a);
} }
elsif ($opt =~ /^(config|values)$/) { elsif ($lcopt =~ /^(config|values)$/) {
return HMCCU_ExecuteSetParameterCommand ($ioHash, $hash, $opt, $a, $h); return HMCCU_ExecuteSetParameterCommand ($ioHash, $hash, $opt, $a, $h);
} }
elsif ($opt eq 'defaults') { elsif ($lcopt eq 'defaults') {
my $mode = shift @$a // 'update'; my $mode = shift @$a // 'update';
$rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, ctrlChn => $cc }); $rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, ctrlChn => $cc });
$rc = HMCCU_SetDefaults ($hash) if (!$rc); $rc = HMCCU_SetDefaults ($hash) if (!$rc);
@ -456,10 +471,13 @@ sub HMCCUDEV_Set ($@)
my $retmsg = 'clear defaults:reset,update'; my $retmsg = 'clear defaults:reset,update';
if ($hash->{readonly} ne 'yes') { if ($hash->{readonly} ne 'yes') {
$retmsg .= ' config datapoint'; $retmsg .= ' config';
my $dpCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, -1, 2);
$retmsg .= ' datapoint' if ($dpCount > 0);
$retmsg .= " $cmdList" if ($cmdList ne ''); $retmsg .= " $cmdList" if ($cmdList ne '');
} }
return AttrTemplate_Set ($hash, $retmsg, $name, $opt, @$a); # return AttrTemplate_Set ($hash, $retmsg, $name, $opt, @$a);
return $retmsg;
} }
} }
@ -472,7 +490,7 @@ sub HMCCUDEV_Get ($@)
my ($hash, $a, $h) = @_; my ($hash, $a, $h) = @_;
my $name = shift @$a; my $name = shift @$a;
my $opt = shift @$a // return 'No get command specified'; my $opt = shift @$a // return 'No get command specified';
$opt = lc($opt); my $lcopt = lc($opt);
# Get I/O device # Get I/O device
return "Device state doesn't allow set commands" return "Device state doesn't allow set commands"
@ -490,7 +508,7 @@ sub HMCCUDEV_Get ($@)
my $ccuaddr = $hash->{ccuaddr}; my $ccuaddr = $hash->{ccuaddr};
my $ccuif = $hash->{ccuif}; my $ccuif = $hash->{ccuif};
my $ccuflags = AttrVal ($name, 'ccuflags', 'null'); my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash); my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($hash);
# Get additional commands # Get additional commands
my $cmdList = $hash->{hmccu}{cmdlist}{get} // ''; my $cmdList = $hash->{hmccu}{cmdlist}{get} // '';
@ -506,7 +524,7 @@ sub HMCCUDEV_Get ($@)
HMCCU_Log ($hash, 3, "get $name $opt ".join (' ', @$a)) HMCCU_Log ($hash, 3, "get $name $opt ".join (' ', @$a))
if ($opt ne '?' && $ccuflags =~ /logCommand/ || HMCCU_IsFlag ($ioName, 'logCommand')); if ($opt ne '?' && $ccuflags =~ /logCommand/ || HMCCU_IsFlag ($ioName, 'logCommand'));
if ($opt eq 'datapoint') { if ($lcopt eq 'datapoint') {
my $objname = shift @$a // return HMCCU_SetError ($hash, "Usage: get $name datapoint [{channel-number}.]{datapoint}"); my $objname = shift @$a // return HMCCU_SetError ($hash, "Usage: get $name datapoint [{channel-number}.]{datapoint}");
if ($objname =~ /^([0-9]+)\..+$/) { if ($objname =~ /^([0-9]+)\..+$/) {
@ -518,7 +536,7 @@ sub HMCCUDEV_Get ($@)
$objname = $sc.'.'.$objname; $objname = $sc.'.'.$objname;
} }
return HMCCU_SetError ($hash, -8) return HMCCU_SetError ($hash, -8, $objname)
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, undef, $objname, 1)); if (!HMCCU_IsValidDatapoint ($hash, $ccutype, undef, $objname, 1));
$objname = $ccuif.'.'.$ccuaddr.':'.$objname; $objname = $ccuif.'.'.$ccuaddr.':'.$objname;
@ -528,39 +546,33 @@ sub HMCCUDEV_Get ($@)
HMCCU_SetState ($hash, "OK") if (exists ($hash->{STATE}) && $hash->{STATE} eq "Error"); HMCCU_SetState ($hash, "OK") if (exists ($hash->{STATE}) && $hash->{STATE} eq "Error");
return $result; return $result;
} }
elsif ($opt eq 'deviceinfo') { elsif ($lcopt eq 'deviceinfo') {
return HMCCU_ExecuteGetDeviceInfoCommand ($ioHash, $hash, $ccuaddr, $sc, $sd, $cc, $cd); return HMCCU_ExecuteGetDeviceInfoCommand ($ioHash, $hash, $ccuaddr, $sc, $sd, $cc, $cd);
} }
elsif ($opt =~ /^(config|values|update)$/) { elsif ($lcopt =~ /^(config|values|update)$/) {
my @addList = ($ccuaddr); my @addList = ($ccuaddr);
my $devDesc = HMCCU_GetDeviceDesc ($ioHash, $ccuaddr, $ccuif); my $devDesc = HMCCU_GetDeviceDesc ($ioHash, $ccuaddr, $ccuif);
return HMCCU_SetError ($hash, "Can't get device description") if (!defined($devDesc)); return HMCCU_SetError ($hash, "Can't get device description") if (!defined($devDesc));
push @addList, split (',', $devDesc->{CHILDREN}); push @addList, split (',', $devDesc->{CHILDREN});
my $resp = HMCCU_ExecuteGetParameterCommand ($ioHash, $hash, $opt, \@addList); my $resp = HMCCU_ExecuteGetParameterCommand ($ioHash, $hash, $lcopt, \@addList);
return HMCCU_SetError ($hash, "Can't get device description") if (!defined($resp)); return HMCCU_SetError ($hash, "Can't get device description") if (!defined($resp));
return HMCCU_DisplayGetParameterResult ($ioHash, $hash, $resp); return HMCCU_DisplayGetParameterResult ($ioHash, $hash, $resp);
} }
elsif ($opt eq 'paramsetdesc') { elsif ($lcopt eq 'paramsetdesc') {
$result = HMCCU_ParamsetDescToStr ($ioHash, $hash); $result = HMCCU_ParamsetDescToStr ($ioHash, $hash);
return defined($result) ? $result : HMCCU_SetError ($hash, "Can't get device model"); return defined($result) ? $result : HMCCU_SetError ($hash, "Can't get device model");
} }
elsif (exists($hash->{hmccu}{roleCmds}{get}{$opt})) { elsif (exists($hash->{hmccu}{roleCmds}{get}{$opt})) {
return HMCCU_ExecuteRoleCommand ($ioHash, $hash, 'get', $opt, $cc, $a, $h); return HMCCU_ExecuteRoleCommand ($ioHash, $hash, 'get', $opt, $cc, $a, $h);
} }
elsif ($opt eq 'defaults') {
$result = HMCCU_GetDefaults ($hash, 0);
return $result;
}
else { else {
my $retmsg = "HMCCUDEV: Unknown argument $opt, choose one of datapoint"; my $retmsg = "HMCCUDEV: Unknown argument $opt, choose one of";
$retmsg .= ' update:noArg config:noArg paramsetDesc:noArg deviceInfo:noArg values:noArg';
my @valuelist; my @dpList;
my $valuecount = HMCCU_GetValidDatapoints ($hash, $ccutype, -1, 1, \@valuelist); my $dpCount = HMCCU_GetValidDatapoints ($hash, $ccutype, -1, 1, \@dpList);
$retmsg .= ':'.join(",", @valuelist) if ($valuecount > 0); $retmsg .= ' datapoint:'.join(",", @dpList) if ($dpCount > 0);
$retmsg .= ' defaults:noArg update:noArg config:noArg'.
' paramsetDesc:noArg deviceInfo:noArg values:noArg';
$retmsg .= " $cmdList" if ($cmdList ne ''); $retmsg .= " $cmdList" if ($cmdList ne '');
return $retmsg; return $retmsg;
@ -587,12 +599,14 @@ sub HMCCUDEV_Get ($@)
<b>Define</b><br/><br/> <b>Define</b><br/><br/>
<ul> <ul>
<code>define &lt;name&gt; HMCCUDEV {&lt;device&gt; | 'virtual'} [&lt;controlchannel&gt;] <code>define &lt;name&gt; HMCCUDEV {&lt;device&gt; | 'virtual'} [&lt;controlchannel&gt;]
[readonly] [<u>defaults</u>|noDefaults] [{group={device|channel}[,...]|groupexp=regexp] [readonly] [<u>defaults</u>|noDefaults] [force] {group={device|channel}[,...]|groupexp=regexp]
[iodev=&lt;iodev-name&gt;]</code> [iodev=&lt;iodev-name&gt;]</code>
<br/><br/> <br/><br/>
If option 'readonly' is specified no set command will be available. With option 'defaults' If option 'readonly' is specified no set command will be available. With option 'defaults'
some default attributes depending on CCU device type will be set. Default attributes are only some default attributes depending on CCU device type will be set. Default attributes are only
available for some device types. The option is ignored during FHEM start. available for some device types. The option is ignored during FHEM start.
Option 'force' must be specified to define a HMCCUDEV device even if the preferred and
recommended type is HMCCUCHN.<br/>
Parameter <i>controlchannel</i> corresponds to attribute 'controlchannel'. If a device Parameter <i>controlchannel</i> corresponds to attribute 'controlchannel'. If a device
has several identical channels, some commands need to know the channel number for has several identical channels, some commands need to know the channel number for
controlling the device.<br/> controlling the device.<br/>
@ -616,8 +630,23 @@ sub HMCCUDEV_Get ($@)
# Group device by using CCU group device and 3 group members<br/> # Group device by using CCU group device and 3 group members<br/>
define heating_living HMCCUDEV GRP-LIV group=WIN-LIV,HEAT-LIV,THERM-LIV define heating_living HMCCUDEV GRP-LIV group=WIN-LIV,HEAT-LIV,THERM-LIV
</code> </code>
<br/> <br/><br/>
</ul> Internals:<br/>
<ul>
<li>ccuaddr: Address of device in CCU</li>
<li>ccudevstate: State of device in CCU (active/inactive/dead)</li>
<li>ccuif: Interface of device</li>
<li>ccuname: Name of device in CCU</li>
<li>ccurole: Role of device</li>
<li>ccusubtype: Homematic subtype of device (different from ccutype for HmIP devices)</li>
<li>ccutype: Homematic type of device</li>
<li>readonly: Indicates whether FHEM device is writeable</li>
<li>receiver: List of peered devices with role 'receiver'. If no FHEM device exists for a receiver, the
name of the CCU device is displayed preceeded by 'ccu:'</li>
<li>sender: List of peered devices with role 'sender'. If no FHEM device exists for a sender, the
name of the CCU device is displayed preceeded by 'ccu:'</li>
</ul>
</ul>
<br/> <br/>
<a name="HMCCUDEVset"></a> <a name="HMCCUDEVset"></a>

View File

@ -4,7 +4,7 @@
# #
# $Id: HMCCUConf.pm 18552 2019-02-10 11:52:28Z zap $ # $Id: HMCCUConf.pm 18552 2019-02-10 11:52:28Z zap $
# #
# Version 4.8.010 # Version 4.8.015
# #
# Configuration parameters for HomeMatic devices. # Configuration parameters for HomeMatic devices.
# #
@ -18,6 +18,7 @@ use strict;
use warnings; use warnings;
use vars qw($HMCCU_CONFIG_VERSION); use vars qw($HMCCU_CONFIG_VERSION);
use vars qw(%HMCCU_DEF_ROLE);
use vars qw(%HMCCU_STATECONTROL); use vars qw(%HMCCU_STATECONTROL);
use vars qw(%HMCCU_READINGS); use vars qw(%HMCCU_READINGS);
use vars qw(%HMCCU_ROLECMDS); use vars qw(%HMCCU_ROLECMDS);
@ -27,83 +28,97 @@ use vars qw(%HMCCU_CHN_DEFAULTS);
use vars qw(%HMCCU_DEV_DEFAULTS); use vars qw(%HMCCU_DEV_DEFAULTS);
use vars qw(%HMCCU_SCRIPTS); use vars qw(%HMCCU_SCRIPTS);
$HMCCU_CONFIG_VERSION = '4.8.010'; $HMCCU_CONFIG_VERSION = '4.8.015';
######################################################################
# Map subtype to default role. Subtype is only available for HMIP
# devices.
# Used by HMCCU to detect control channel of HMCCUDEV devices.
######################################################################
%HMCCU_DEF_ROLE = (
'ASIR' => 'ALARM_SWITCH_VIRTUAL_RECEIVER',
'PSM' => 'SWITCH_VIRTUAL_RECEIVER',
'SD' => 'SMOKE_DETECTOR'
);
###################################################################### ######################################################################
# Channel roles with state and control datapoints # Channel roles with state and control datapoints
# F: 1=Channel/HMCCUCHN, 2=Device/HMCCUDEV, 3=Both # F: 1=Channel/HMCCUCHN, 2=Device/HMCCUDEV, 3=Both
# S: State datapoint, C: Control datapoint, V: Control values # S: State datapoint, C: Control datapoint, V: Control values
# P: Priority (used by HMCCUDEV if more than 1 channel role fits)
# 1=lowest priority
###################################################################### ######################################################################
%HMCCU_STATECONTROL = ( %HMCCU_STATECONTROL = (
'SHUTTER_CONTACT' => { 'SHUTTER_CONTACT' => {
F => 3, S => 'STATE', C => '', V => '' F => 3, S => 'STATE', C => '', V => '', P => 2
}, },
'SHUTTER_CONTACT_TRANSCEIVER' => { 'SHUTTER_CONTACT_TRANSCEIVER' => {
F => 3, S => 'STATE', C => '', V => '' F => 3, S => 'STATE', C => '', V => '', P => 2
}, },
'ROTARY_HANDLE_SENSOR' => { 'ROTARY_HANDLE_SENSOR' => {
F => 3, S => 'STATE', C => '', V => '' F => 3, S => 'STATE', C => '', V => '', P => 2
}, },
'ROTARY_HANDLE_TRANSCEIVER' => { 'ROTARY_HANDLE_TRANSCEIVER' => {
F => 3, S => 'STATE', C => '', V => '' F => 3, S => 'STATE', C => '', V => '', P => 2
}, },
'ALARM_SWITCH_VIRTUAL_RECEIVER' => { 'ALARM_SWITCH_VIRTUAL_RECEIVER' => {
F => 3, S => 'STATE', C => '', V => '' F => 3, S => 'ACOUSTIC_ALARM_ACTIVE', C => 'ACOUSTIC_ALARM_SELECTION', V => '', P => 2
}, },
'SMOKE_DETECTOR' => { 'SMOKE_DETECTOR' => {
F => 3, S => 'SMOKE_DETECTOR_ALARM_STATUS', C => '', V => '' F => 3, S => 'SMOKE_DETECTOR_ALARM_STATUS', C => '', V => '', P => 2
}, },
'LUXMETER' => { 'LUXMETER' => {
F => 3, S => 'LUX', C => '', V => '' F => 3, S => 'LUX', C => '', V => '', P => 2
}, },
'MOTIONDETECTOR_TRANSCEIVER' => { 'MOTIONDETECTOR_TRANSCEIVER' => {
F => 3, S => 'MOTION', C => 'MOTION_DETECTION_ACTIVE', V => 'on:true,off:false' F => 3, S => 'MOTION', C => 'MOTION_DETECTION_ACTIVE', V => 'on:true,off:false', P => 2
}, },
'KEY' => { 'KEY' => {
F => 3, S => 'PRESS_SHORT', C => 'PRESS_SHORT', V => 'pressed:true' F => 3, S => 'PRESS_SHORT', C => 'PRESS_SHORT', V => 'pressed:true', P => 1
}, },
'KEY_TRANSCEIVER' => { 'KEY_TRANSCEIVER' => {
F => 3, S => 'PRESS_SHORT', C => 'PRESS_SHORT', V => 'pressed:true' F => 3, S => 'PRESS_SHORT', C => 'PRESS_SHORT', V => 'pressed:true', P => 1
}, },
'VIRTUAL_KEY' => { 'VIRTUAL_KEY' => {
F => 3, S => 'PRESS_SHORT', C => 'PRESS_SHORT', V => 'pressed:true' F => 3, S => 'PRESS_SHORT', C => 'PRESS_SHORT', V => 'pressed:true', P => 1
}, },
'BLIND' => { 'BLIND' => {
F => 3, S => 'LEVEL', C => 'LEVEL', V => 'open:100,close:0' F => 3, S => 'LEVEL', C => 'LEVEL', V => 'open:100,close:0', P => 2
}, },
'BLIND_VIRTUAL_RECEIVER' => { 'BLIND_VIRTUAL_RECEIVER' => {
F => 3, S => 'LEVEL', C => 'LEVEL', V => 'open:100,close:0' F => 3, S => 'LEVEL', C => 'LEVEL', V => 'open:100,close:0', P => 2
}, },
'SWITCH' => { 'SWITCH' => {
F => 3, S => 'STATE', C => 'STATE', V => 'on:true,off:false' F => 3, S => 'STATE', C => 'STATE', V => 'on:true,off:false', P => 2
}, },
'SWITCH_VIRTUAL_RECEIVER' => { 'SWITCH_VIRTUAL_RECEIVER' => {
F => 3, S => 'STATE', C => 'STATE', V => 'on:true,off:false' F => 3, S => 'STATE', C => 'STATE', V => 'on:true,off:false', P => 2
}, },
'DIMMER' => { 'DIMMER' => {
F => 3, S => 'LEVEL', C => 'LEVEL', V => 'on:100,off:0' F => 3, S => 'LEVEL', C => 'LEVEL', V => 'on:100,off:0', P => 2
}, },
'DIMMER_VIRTUAL_RECEIVER' => { 'DIMMER_VIRTUAL_RECEIVER' => {
F => 3, S => 'LEVEL', C => 'LEVEL', V => 'on:100,off:0' F => 3, S => 'LEVEL', C => 'LEVEL', V => 'on:100,off:0', P => 2
}, },
'WEATHER' => { 'WEATHER' => {
F => 3, S => 'TEMPERATURE', C => 'TEMPERATURE', V => '' F => 3, S => 'TEMPERATURE', C => '', V => '', P => 1
}, },
'WEATHER_TRANSMIT' => { 'WEATHER_TRANSMIT' => {
F => 3, S => 'TEMPERATURE', C => 'TEMPERATURE', V => '' F => 3, S => 'TEMPERATURE', C => '', V => '', P => 1
}, },
'CLIMATE_TRANSCEIVER' => { 'CLIMATE_TRANSCEIVER' => {
F => 3, S => 'ACTUAL_TEMPERATURE', C => 'ACTUAL_TEMPERATURE', V => '' F => 3, S => 'ACTUAL_TEMPERATURE', C => '', V => '', P => 1
}, },
'THERMALCONTROL_TRANSMIT' => { 'THERMALCONTROL_TRANSMIT' => {
F => 3, S => 'ACTUAL_TEMPERATURE', C => 'SET_TEMPERATURE', V => 'on:30.5,off:4.5' F => 3, S => 'ACTUAL_TEMPERATURE', C => 'SET_TEMPERATURE', V => 'on:30.5,off:4.5', P => 2
}, },
'CLIMATECONTROL_RT_TRANSCEIVER' => { 'CLIMATECONTROL_RT_TRANSCEIVER' => {
F => 3, S => 'ACTUAL_TEMPERATURE', C => 'SET_TEMPERATURE', V => 'on:30.5,off:4.5' F => 3, S => 'ACTUAL_TEMPERATURE', C => 'SET_TEMPERATURE', V => 'on:30.5,off:4.5', P => 2
}, },
'HEATING_CLIMATECONTROL_TRANSCEIVER' => { 'HEATING_CLIMATECONTROL_TRANSCEIVER' => {
F => 3, S => 'ACTUAL_TEMPERATURE', C => 'SET_POINT_TEMPERATURE', V => 'on:30.5,off:4.5' F => 3, S => 'ACTUAL_TEMPERATURE', C => 'SET_POINT_TEMPERATURE', V => 'on:30.5,off:4.5', P => 2
} }
); );
@ -157,17 +172,22 @@ $HMCCU_CONFIG_VERSION = '4.8.010';
# Set commands related to channel role # Set commands related to channel role
# Role => { Command-Definition, ... } # Role => { Command-Definition, ... }
# Command-Defintion: # Command-Defintion:
# Command => 'Datapoint-Definition [...]' # Command => 'Datapoint-Definition[:Function] [...]'
# Function:
# A Perl function name
# Datapoint-Definition: # Datapoint-Definition:
# Paramset:Datapoint:[Parameter=]FixedValue[,FixedValue] # Paramset:Datapoint:[Parameter=]FixedValue[,FixedValue]
# Paramset:Datapoint:?Parameter # Paramset:Datapoint:?Parameter
# Paramset:Datapoint:?Parameter=Default-Value # Paramset:Datapoint:?Parameter=Default-Value
# Paramset:Datapoint:#Parameter # Paramset:Datapoint:#Parameter
# Paramset:Datapoint:*Parameter=Default-Value
# Paramset: # Paramset:
# V=VALUES, M=MASTER (channel), D=MASTER (device) # V=VALUES, M=MASTER (channel), D=MASTER (device), I=INTERNAL
# If Parameter is preceded by ? any value is accepted. # Parameter characters:
# If Parameter is preceded by # Datapoint must have type ENUM and # ? = any value is accepted
# valid values are taken from parameter set description. # # = datapoint must have type ENUM. Valid values are taken from
# parameter set description.
# * = internal value $hash->{hmccu}{values}{parameterName}
# If Default-Value is preceeded by + or -, value is added to or # If Default-Value is preceeded by + or -, value is added to or
# subtracted from current datapoint value # subtracted from current datapoint value
###################################################################### ######################################################################
@ -180,6 +200,11 @@ $HMCCU_CONFIG_VERSION = '4.8.010';
'SMOKE_DETECTOR' => { 'SMOKE_DETECTOR' => {
'command' => 'V:SMOKE_DETECTOR_COMMAND:#command' 'command' => 'V:SMOKE_DETECTOR_COMMAND:#command'
}, },
'ALARM_SWITCH_VIRTUAL_RECEIVER' => {
'opticalAlarm' => 'V:OPTICAL_ALARM_SELECTION:#alarmMode V:ACOUSTIC_ALARM_SELECTION:0 V:DURATION_UNIT:*unit=0 V:DURATION_VALUE:*duration=10',
'acousticAlarm' => 'V:ACOUSTIC_ALARM_SELECTION:#alarmMode V:OPTICAL_ALARM_SELECTION:0 V:DURATION_UNIT:0 V:DURATION_VALUE:10',
'duration' => 'I:DURATION_VALUE:?duration I:DURATION_UNIT:#unit'
},
'KEY' => { 'KEY' => {
'on' => 'V:PRESS_SHORT:1', 'on' => 'V:PRESS_SHORT:1',
'off' => 'V:PRESS_SHORT:1', 'off' => 'V:PRESS_SHORT:1',
@ -199,44 +224,44 @@ $HMCCU_CONFIG_VERSION = '4.8.010';
'pct' => 'V:LEVEL:?level', 'pct' => 'V:LEVEL:?level',
'open' => 'V:LEVEL:100', 'open' => 'V:LEVEL:100',
'close' => 'V:LEVEL:0', 'close' => 'V:LEVEL:0',
'up' => 'V:LEVEL:?delta=+10', 'up' => 'V:LEVEL:?delta=+20',
'down' => 'V:LEVEL:?delta=-10', 'down' => 'V:LEVEL:?delta=-20',
'stop' => 'V:STOP:1' 'stop' => 'V:STOP:1'
}, },
'BLIND_VIRTUAL_RECEIVER' => { 'BLIND_VIRTUAL_RECEIVER' => {
'pct' => 'V:LEVEL:?level', 'pct' => 'V:LEVEL:?level',
'open' => 'V:LEVEL:100', 'open' => 'V:LEVEL:100',
'close' => 'V:LEVEL:0', 'close' => 'V:LEVEL:0',
'up' => 'V:LEVEL:?delta=+10', 'up' => 'V:LEVEL:?delta=+20',
'down' => 'V:LEVEL:?delta=-10', 'down' => 'V:LEVEL:?delta=-20',
'stop' => 'V:STOP:1' 'stop' => 'V:STOP:1'
}, },
'SHUTTER_VIRTUAL_RECEIVER' => { 'SHUTTER_VIRTUAL_RECEIVER' => {
'pct' => 'V:LEVEL:?level', 'pct' => 'V:LEVEL:?level',
'open' => 'V:LEVEL:100', 'open' => 'V:LEVEL:100',
'close' => 'V:LEVEL:0', 'close' => 'V:LEVEL:0',
'up' => 'V:LEVEL:?delta=+10', 'up' => 'V:LEVEL:?delta=+20',
'down' => 'V:LEVEL:?delta=-10', 'down' => 'V:LEVEL:?delta=-20',
'stop' => 'V:STOP:1' 'stop' => 'V:STOP:1'
}, },
'SWITCH' => { 'SWITCH' => {
'on' => 'V:STATE:1', 'on' => 'V:STATE:1',
'off' => 'V:STATE:0', 'off' => 'V:STATE:0',
'on-for-timer' => 'V:ON_TIME:?duration V:STATE:1', 'on-for-timer' => 'V:ON_TIME:?duration V:STATE:1',
'on-till' => 'V:ON_TIME:?duration V:STATE:1' 'on-till' => 'V:ON_TIME:?time V:STATE:1'
}, },
'SWITCH_VIRTUAL_RECEIVER' => { 'SWITCH_VIRTUAL_RECEIVER' => {
'on' => 'V:STATE:1', 'on' => 'V:STATE:1',
'off' => 'V:STATE:0', 'off' => 'V:STATE:0',
'on-for-timer' => 'V:ON_TIME:?duration V:STATE:1', 'on-for-timer' => 'V:ON_TIME:?duration V:STATE:1',
'on-till' => 'V:ON_TIME:?duration V:STATE:1' 'on-till' => 'V:ON_TIME:?time V:STATE:1'
}, },
'DIMMER' => { 'DIMMER' => {
'pct' => 'V:LEVEL:?level V:ON_TIME:?time=0.0 V:RAMP_TIME:?ramp=0.5', 'pct' => 'V:LEVEL:?level V:ON_TIME:?time=0.0 V:RAMP_TIME:?ramp=0.5',
'on' => 'V:LEVEL:100', 'on' => 'V:LEVEL:100',
'off' => 'V:LEVEL:0', 'off' => 'V:LEVEL:0',
'on-for-timer' => 'V:ON_TIME:?duration V:STATE:1', 'on-for-timer' => 'V:ON_TIME:?duration V:STATE:1',
'on-till' => 'V:ON_TIME:?duration V:STATE:1', 'on-till' => 'V:ON_TIME:?time V:STATE:1',
'stop' => 'V:RAMP_STOP:1' 'stop' => 'V:RAMP_STOP:1'
}, },
'DIMMER_VIRTUAL_RECEIVER' => { 'DIMMER_VIRTUAL_RECEIVER' => {
@ -244,7 +269,7 @@ $HMCCU_CONFIG_VERSION = '4.8.010';
'on' => 'V:LEVEL:100', 'on' => 'V:LEVEL:100',
'off' => 'V:LEVEL:0', 'off' => 'V:LEVEL:0',
'on-for-timer' => 'V:ON_TIME:?duration V:STATE:1', 'on-for-timer' => 'V:ON_TIME:?duration V:STATE:1',
'on-till' => 'V:ON_TIME:?duration V:STATE:1' 'on-till' => 'V:ON_TIME:?time V:STATE:1'
}, },
'THERMALCONTROL_TRANSMIT' => { 'THERMALCONTROL_TRANSMIT' => {
'desired-temp' => 'V:SET_TEMPERATURE:?temperature', 'desired-temp' => 'V:SET_TEMPERATURE:?temperature',
@ -279,41 +304,58 @@ $HMCCU_CONFIG_VERSION = '4.8.010';
###################################################################### ######################################################################
# Channel roles with attributes # Channel roles with attributes
# If key '_none_' exists, role doesn't have default attributes
###################################################################### ######################################################################
%HMCCU_ATTR = ( %HMCCU_ATTR = (
'SHUTTER_CONTACT' => {
'_none_' => ''
},
'SHUTTER_CONTACT_TRANSCEIVER' => {
'_none_' => ''
},
'KEY' => {
'event-on-update-reading' => '.*',
'cmdIcon' => 'press:taster',
'webCmd' => 'press'
},
'KEY_TRANSCEIVER' => {
'event-on-update-reading' => '.*',
'cmdIcon' => 'press:taster',
'webCmd' => 'press'
},
'BLIND' => { 'BLIND' => {
'substexcl' => 'pct', 'substexcl' => 'pct',
'cmdIcon' => 'open:fts_shutter_up stop:fts_shutter_manual close:fts_shutter_down', 'cmdIcon' => 'open:fts_shutter_up stop:fts_shutter_manual close:fts_shutter_down',
'webCmd' => 'open:close:stop:pct', 'webCmd' => 'pct:open:close:stop',
'widgetOverride' => 'pct:slider,0,10,100' 'widgetOverride' => 'pct:slider,0,10,100'
}, },
'BLIND_VIRTUAL_RECEIVER' => { 'BLIND_VIRTUAL_RECEIVER' => {
'substexcl' => 'pct', 'substexcl' => 'pct',
'cmdIcon' => 'open:fts_shutter_up stop:fts_shutter_manual close:fts_shutter_down', 'cmdIcon' => 'open:fts_shutter_up stop:fts_shutter_manual close:fts_shutter_down',
'webCmd' => 'open:close:stop:pct', 'webCmd' => 'pct:open:close:stop',
'widgetOverride' => 'pct:slider,0,10,100' 'widgetOverride' => 'pct:slider,0,10,100'
}, },
'SHUTTER_VIRTUAL_RECEIVER' => { 'SHUTTER_VIRTUAL_RECEIVER' => {
'substexcl' => 'pct', 'substexcl' => 'pct',
'cmdIcon' => 'open:fts_shutter_up stop:fts_shutter_manual close:fts_shutter_down', 'cmdIcon' => 'open:fts_shutter_up stop:fts_shutter_manual close:fts_shutter_down',
'webCmd' => 'open:close:stop:pct', 'webCmd' => 'pct:open:close:stop',
'widgetOverride' => 'pct:slider,0,10,100' 'widgetOverride' => 'pct:slider,0,10,100'
}, },
'SWITCH' => { 'SWITCH' => {
'webCmd' => 'toggle', 'cmdIcon' => 'on:general_an off:general_aus'
'widgetOverride' => 'toggle:uzsuToggle,off,on'
}, },
'SWITCH_VIRTUAL_RECEIVER' => { 'SWITCH_VIRTUAL_RECEIVER' => {
'webCmd' => 'toggle', 'cmdIcon' => 'on:general_an off:general_aus'
'widgetOverride' => 'toggle:uzsuToggle,off,on'
}, },
'DIMMER' => { 'DIMMER' => {
'cmdIcon' => 'on:general_an off:general_aus',
'substexcl' => 'pct', 'substexcl' => 'pct',
'webCmd' => 'pct', 'webCmd' => 'pct',
'widgetOverride' => 'pct:slider,0,10,100' 'widgetOverride' => 'pct:slider,0,10,100'
}, },
'DIMMER_VIRTUAL_RECEIVER' => { 'DIMMER_VIRTUAL_RECEIVER' => {
'cmdIcon' => 'on:general_an off:general_aus',
'substexcl' => 'pct', 'substexcl' => 'pct',
'webCmd' => 'pct', 'webCmd' => 'pct',
'widgetOverride' => 'pct:slider,0,10,100' 'widgetOverride' => 'pct:slider,0,10,100'

View File

@ -1,5 +1,5 @@
UPD 2020-11-12_19:39:34 102657 FHEM/88_HMCCURPCPROC.pm UPD 2020-12-31_11:18:05 102657 FHEM/88_HMCCURPCPROC.pm
UPD 2020-11-12_19:40:01 76540 FHEM/HMCCUConf.pm UPD 2020-12-31_11:18:05 78208 FHEM/HMCCUConf.pm
UPD 2020-11-12_19:39:14 39378 FHEM/88_HMCCUCHN.pm UPD 2020-12-31_11:18:05 41583 FHEM/88_HMCCUCHN.pm
UPD 2020-11-12_19:39:06 302472 FHEM/88_HMCCU.pm UPD 2020-12-31_11:18:05 320619 FHEM/88_HMCCU.pm
UPD 2020-11-12_19:39:22 30769 FHEM/88_HMCCUDEV.pm UPD 2020-12-31_11:18:05 32244 FHEM/88_HMCCUDEV.pm