HMCCU: Fixed some bugs

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@25212 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2021-11-10 17:51:58 +00:00
parent fb92081745
commit 21e0d6ca76
6 changed files with 233 additions and 122 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it. # Do not insert empty lines here, update check depends on it.
- bugfix: 88_HMCCU: Fixed some bugs
- bugfix: 73_km200: Allowing port behind IP address - bugfix: 73_km200: Allowing port behind IP address
- feature: 6.1 released - feature: 6.1 released

View File

@ -57,7 +57,7 @@ my %HMCCU_CUST_CHN_DEFAULTS;
my %HMCCU_CUST_DEV_DEFAULTS; my %HMCCU_CUST_DEV_DEFAULTS;
# HMCCU version # HMCCU version
my $HMCCU_VERSION = '5.0 213011850'; my $HMCCU_VERSION = '5.0 213141800';
# Timeout for CCU requests (seconds) # Timeout for CCU requests (seconds)
my $HMCCU_TIMEOUT_REQUEST = 4; my $HMCCU_TIMEOUT_REQUEST = 4;
@ -168,7 +168,7 @@ sub HMCCU_AggregationRules ($$);
# Handling of default attributes # Handling of default attributes
sub HMCCU_ExportDefaults ($$); sub HMCCU_ExportDefaults ($$);
sub HMCCU_ImportDefaults ($); sub HMCCU_ImportDefaults ($);
sub HMCCU_FindDefaults ($$); sub HMCCU_FindDefaults ($);
sub HMCCU_GetDefaults ($;$); sub HMCCU_GetDefaults ($;$);
sub HMCCU_SetDefaults ($); sub HMCCU_SetDefaults ($);
@ -310,7 +310,7 @@ sub HMCCU_GetDatapoint ($@);
sub HMCCU_GetDatapointAttr ($$$$$); sub HMCCU_GetDatapointAttr ($$$$$);
sub HMCCU_GetDatapointList ($;$$); sub HMCCU_GetDatapointList ($;$$);
sub HMCCU_GetSCDatapoints ($); sub HMCCU_GetSCDatapoints ($);
sub HMCCU_SetSCDatapoints ($$;$$); sub HMCCU_SetSCDatapoints ($$;$$$);
sub HMCCU_GetStateValues ($;$$); sub HMCCU_GetStateValues ($;$$);
sub HMCCU_GetValidDatapoints ($$$$;$); sub HMCCU_GetValidDatapoints ($$$$;$);
sub HMCCU_IsValidDatapoint ($$$$$); sub HMCCU_IsValidDatapoint ($$$$$);
@ -576,7 +576,9 @@ sub HMCCU_PostInit ($)
my $rpcServer = AttrVal ($hash->{NAME}, 'rpcserver', 'off'); my $rpcServer = AttrVal ($hash->{NAME}, 'rpcserver', 'off');
HMCCU_Log ($hash, 1, 'Reading device config from CCU. This may take a couple of seconds ...'); HMCCU_Log ($hash, 1, 'Reading device config from CCU. This may take a couple of seconds ...');
$hash->{postInit} = 1;
my ($cDev, $cPar, $cLnk) = HMCCU_GetDeviceConfig ($hash); my ($cDev, $cPar, $cLnk) = HMCCU_GetDeviceConfig ($hash);
$hash->{postInit} = 0;
HMCCU_Log ($hash, 2, "Read device configuration: devices/channels=$cDev parametersets=$cPar links=$cLnk"); HMCCU_Log ($hash, 2, "Read device configuration: devices/channels=$cDev parametersets=$cPar links=$cLnk");
HMCCU_StartExtRPCServer ($hash) if ($rpcServer eq 'on'); HMCCU_StartExtRPCServer ($hash) if ($rpcServer eq 'on');
@ -870,12 +872,12 @@ sub HMCCU_ImportDefaults ($)
###################################################################### ######################################################################
# Find default attributes # Find default attributes
# Return template reference. # Return template reference or undef if no defaults were found.
###################################################################### ######################################################################
sub HMCCU_FindDefaults ($$) sub HMCCU_FindDefaults ($)
{ {
my ($hash, $common) = @_; my ($hash) = @_;
my $type = $hash->{TYPE}; my $type = $hash->{TYPE};
my $ccutype = $hash->{ccutype}; my $ccutype = $hash->{ccutype};
@ -916,13 +918,11 @@ sub HMCCU_SetDefaultsTemplate ($$)
my ($hash, $template) = @_; my ($hash, $template) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
$hash->{hmccu}{semDefaults} = 1;
foreach my $a (keys %{$template}) { foreach my $a (keys %{$template}) {
next if ($a =~ /^_/); next if ($a =~ /^_/);
my $v = $template->{$a}; my $v = $template->{$a};
CommandAttr (undef, "$name $a $v"); CommandAttr (undef, "$name $a $v");
} }
$hash->{hmccu}{semDefaults} = 0;
} }
###################################################################### ######################################################################
@ -934,7 +934,7 @@ sub HMCCU_SetDefaults ($)
my ($hash) = @_; my ($hash) = @_;
# Set type specific attributes # Set type specific attributes
my $template = HMCCU_FindDefaults ($hash, 0) // return 0; my $template = HMCCU_FindDefaults ($hash) // return 0;
HMCCU_SetDefaultsTemplate ($hash, $template); HMCCU_SetDefaultsTemplate ($hash, $template);
return 1; return 1;
@ -972,7 +972,7 @@ sub HMCCU_GetDefaults ($;$)
if (scalar(@roleList) > 0); if (scalar(@roleList) > 0);
} }
else { else {
my $template = HMCCU_FindDefaults ($hash, 0); my $template = HMCCU_FindDefaults ($hash);
return ($result eq '' ? 'No default attributes defined' : $result) if (!defined($template)); return ($result eq '' ? 'No default attributes defined' : $result) if (!defined($template));
foreach my $a (keys %{$template}) { foreach my $a (keys %{$template}) {
@ -1025,7 +1025,7 @@ sub HMCCU_Notify ($$)
my $devname = $devhash->{NAME}; my $devname = $devhash->{NAME};
my $devtype = $devhash->{TYPE}; my $devtype = $devhash->{TYPE};
return if (AttrVal ($name, 'disable', 0) == 1); return if (!HMCCU_IsDeviceActive ($hash));
my $events = deviceEvents ($devhash, 1); my $events = deviceEvents ($devhash, 1);
return if (!$events); return if (!$events);
@ -1046,27 +1046,15 @@ sub HMCCU_Notify ($$)
my $refreshAttrList = 'ccucalculate|ccuflags|ccureadingfilter|ccureadingformat|'. my $refreshAttrList = 'ccucalculate|ccuflags|ccureadingfilter|ccureadingformat|'.
'ccureadingname|ccuReadingPrefix|ccuscaleval|controldatapoint|hmstatevals|'. 'ccureadingname|ccuReadingPrefix|ccuscaleval|controldatapoint|hmstatevals|'.
'statedatapoint|statevals|substitute|substexcl|stripnumber'; 'statedatapoint|statevals|substitute|substexcl|stripnumber';
my $cmdAttrList = 'statechannel|statedatapoint|controlchannel|controldatapoint|statevals';
my ($aCmd, $aDev, $aAtt, $aVal) = split (/\s+/, $event); my ($aCmd, $aDev, $aAtt, $aVal) = split (/\s+/, $event);
$aAtt = $aVal if ($aCmd eq 'DELETEATTR'); $aAtt = $aVal if ($aCmd eq 'DELETEATTR');
if (defined($aAtt)) { if (defined($aAtt)) {
my $clHash = $defs{$aDev}; my $clHash = $defs{$aDev};
# Consider attr event only for HMCCUCHN or HMCCUDEV devices assigned to current IO device # Consider attr event only for HMCCUCHN or HMCCUDEV devices assigned to current IO device
if (defined($clHash->{TYPE}) && ($clHash->{TYPE} eq 'HMCCUCHN' || $clHash->{TYPE} eq 'HMCCUDEV') && HMCCU_RefreshReadings ($clHash)
defined($clHash->{IODev}) && $clHash->{IODev} == $hash && if (defined($clHash->{TYPE}) && ($clHash->{TYPE} eq 'HMCCUCHN' || $clHash->{TYPE} eq 'HMCCUDEV') &&
(!defined($clHash->{hmccu}{semDefaults}) || $clHash->{hmccu}{semDefaults} == 0)) { defined($clHash->{IODev}) && $clHash->{IODev} == $hash && $aAtt =~ /^($refreshAttrList)$/i);
if ($aAtt =~ /^($cmdAttrList)$/) {
my ($cc, $cd) = HMCCU_ControlDatapoint ($clHash);
# if ($cc ne '' && $cd ne '') {
HMCCU_UpdateRoleCommands ($hash, $clHash, $cc);
HMCCU_UpdateAdditionalCommands ($hash, $clHash, $cc, $cd);
# }
}
if ($aAtt =~ /^($refreshAttrList)$/i) {
HMCCU_RefreshReadings ($clHash);
}
}
} }
} }
} }
@ -1510,7 +1498,7 @@ sub HMCCU_Set ($@)
return HMCCU_SetError ($hash, "Missing channel number for device $devName") return HMCCU_SetError ($hash, "Missing channel number for device $devName")
if (!defined ($t2)); if (!defined ($t2));
return HMCCU_SetError ($hash, "Invalid channel number specified for device $devName") return HMCCU_SetError ($hash, "Invalid channel number specified for device $devName")
if ($t1 !~ /^[0-9]+$/ || $t1 > $dh->{channels}); if ($t1 !~ /^[0-9]+$/ || $t1 > $dh->{hmccu}{channels});
$adr = $dh->{ccuaddr}; $adr = $dh->{ccuaddr};
$chn = $t1; $chn = $t1;
$dpt = $t2; $dpt = $t2;
@ -1520,7 +1508,7 @@ sub HMCCU_Set ($@)
} }
return HMCCU_SetError ($hash, "Invalid datapoint $dpt specified for device $devName") return HMCCU_SetError ($hash, "Invalid datapoint $dpt specified for device $devName")
if (!HMCCU_IsValidDatapoint ($dh, $dh->{ccutype}, $chn, $dpt, 2)); if (!HMCCU_IsValidParameter ($dh, HMCCU_GetChannelAddr ($dh, $chn), 'VALUES', $dpt, 2));
$value = HMCCU_Substitute ($value, $stateVals, 1, undef, '') $value = HMCCU_Substitute ($value, $stateVals, 1, undef, '')
if ($stateVals ne '' && "$chn" eq "$cc" && $dpt eq $cd); if ($stateVals ne '' && "$chn" eq "$cc" && $dpt eq $cd);
@ -3840,6 +3828,7 @@ sub HMCCU_GetDeviceConfig ($)
if (!exists($clHash->{ccuaddr})) { if (!exists($clHash->{ccuaddr})) {
HMCCU_Log ($ioHash, 2, "Disabling client device $name because CCU address is missing. Does the device exist on CCU?"); HMCCU_Log ($ioHash, 2, "Disabling client device $name because CCU address is missing. Does the device exist on CCU?");
CommandAttr (undef, "$name disable 1"); CommandAttr (undef, "$name disable 1");
$clHash->{ccudevstate} = 'inactive';
next; next;
} }
HMCCU_SetSCAttributes ($ioHash, $clHash); HMCCU_SetSCAttributes ($ioHash, $clHash);
@ -4342,7 +4331,7 @@ sub HMCCU_FindParamDef ($$$)
# reference. # reference.
# $ps - Parameter set name. # $ps - Parameter set name.
# $parameter - Parameter name. # $parameter - Parameter name.
# $oper - Access mode: # $oper - Access mode (default = 7):
# 1 = parameter readable # 1 = parameter readable
# 2 = parameter writeable # 2 = parameter writeable
# 4 = parameter events # 4 = parameter events
@ -4701,8 +4690,6 @@ sub HMCCU_RefreshReadings ($)
{ {
my ($clHash) = @_; my ($clHash) = @_;
return if ($clHash->{hmccu}{semDefaults} == 1);
my $ioHash = HMCCU_GetHash ($clHash) // return; my $ioHash = HMCCU_GetHash ($clHash) // return;
HMCCU_DeleteReadings ($clHash, '.*'); HMCCU_DeleteReadings ($clHash, '.*');
@ -5752,6 +5739,24 @@ sub HMCCU_GetDatapointList ($;$$)
return $c; return $c;
} }
######################################################################
# Check if device has an address, is not disabled and state is
# not inactive
######################################################################
sub HMCCU_IsDeviceActive ($)
{
my ($clHash) = @_;
if (defined($clHash)) {
my $disabled = AttrVal ($clHash->{NAME}, 'disable', 0);
my $devstate = $clHash->{ccudevstate} // 'pending';
return $disabled == 0 && exists($clHash->{ccuaddr}) && $devstate ne 'inactive' ? 1 : 0;
}
return 0;
}
###################################################################### ######################################################################
# Check if device/channel name or address is valid and refers to an # Check if device/channel name or address is valid and refers to an
# existing device or channel. # existing device or channel.
@ -6320,6 +6325,10 @@ sub HMCCU_SplitChnAddr ($;$)
return ($dev, $chn); return ($dev, $chn);
} }
######################################################################
# Split datapoint specification into channel number and datapoint name
######################################################################
sub HMCCU_SplitDatapoint ($;$) sub HMCCU_SplitDatapoint ($;$)
{ {
my ($dpt, $defchn) = @_; my ($dpt, $defchn) = @_;
@ -6332,6 +6341,24 @@ sub HMCCU_SplitDatapoint ($;$)
return (scalar(@t) > 1) ? @t : ($defchn, $t[0]); return (scalar(@t) > 1) ? @t : ($defchn, $t[0]);
} }
######################################################################
# Get channel address of FHEM device
######################################################################
sub HMCCU_GetChannelAddr ($;$)
{
my ($clHash, $chn) = @_;
if (exists($clHash->{ccuaddr})) {
my ($d, $c) = HMCCU_SplitChnAddr ($clHash->{ccuaddr});
$c = '0' if ($clHash->{TYPE} eq 'HMCCUDEV');
$chn = $c if (!defined($chn) || $chn eq '');
return "$d:$chn";
}
return '';
}
###################################################################### ######################################################################
# Get list of client devices matching the specified criteria. # Get list of client devices matching the specified criteria.
# If no criteria is specified all device names will be returned. # If no criteria is specified all device names will be returned.
@ -6630,6 +6657,9 @@ sub HMCCU_SetInitialAttributes ($$;$)
###################################################################### ######################################################################
# Set default attributes for client device. # Set default attributes for client device.
# Optionally delete obsolete attributes. # Optionally delete obsolete attributes.
# Return (rc, messages).
# rc: 0=error, 1=success
# messages can be an empty string.
###################################################################### ######################################################################
sub HMCCU_SetDefaultAttributes ($;$) sub HMCCU_SetDefaultAttributes ($;$)
@ -6641,46 +6671,72 @@ sub HMCCU_SetDefaultAttributes ($;$)
$parRef //= { mode => 'update', role => undef, roleChn => undef }; $parRef //= { mode => 'update', role => undef, roleChn => undef };
my $role; my $role;
my @toast = ();
my $rc = 1;
if ($parRef->{mode} eq 'reset') { if ($parRef->{mode} eq 'reset' || $parRef->{mode} eq 'forceReset') {
# List of attributes to be removed
my @removeAttr = ('ccureadingname', 'ccuscaleval', 'cmdIcon',
'substitute', 'webCmd', 'widgetOverride'
);
my $detect = HMCCU_DetectDevice ($ioHash, $clHash->{ccuaddr}, $clHash->{ccuif}); my $detect = HMCCU_DetectDevice ($ioHash, $clHash->{ccuaddr}, $clHash->{ccuif});
if (defined($detect) && $detect->{level} > 0) { if (defined($detect) && $detect->{level} > 0) {
my ($sc, $sd, $cc, $cd, $rsd, $rcd) = HMCCU_SetDefaultSCDatapoints ($ioHash, $clHash, $detect, 1); # List of attributes which can be removed for devices known by HMCCU
HMCCU_Log ($clHash, 2, "Cannot set default state- and/or control datapoints") my @attrList = (
if ($rsd == 0 && $rcd == 0); 'ccureadingname', 'ccuscaleval', 'cmdIcon', 'eventMap',
'substitute', 'webCmd', 'widgetOverride'
);
# List of attributes to be removed
my @removeAttr = ();
# List of attributes to keep
my @keepAttr = ();
# Wrong module used for client device
push @toast, "Device is of type HMCCUDEV, but HMCCUCHN is recommended. Please consider recreating the device with 'get createDev'."
if (exists($detect->{defMod}) && $detect->{defMod} eq 'HMCCUCHN' && $clType eq 'HMCCUDEV');
$role = HMCCU_GetChannelRole ($clHash, $detect->{defCCh}); $role = HMCCU_GetChannelRole ($clHash, $detect->{defCCh});
# Set attributes defined in IO device attribute ccudef-attributes # Set attributes defined in IO device attribute ccudef-attributes
HMCCU_SetInitialAttributes ($ioHash, $clName); HMCCU_SetInitialAttributes ($ioHash, $clName);
# Remove additional attributes if device type is supported by HMCCU # Remove additional attributes if device type is supported by HMCCU and attributes are not modified by user
if (($detect->{level} == 5 && $detect->{rolePatternCount} > 1 && $clType eq 'HMCCUDEV' && if (($detect->{level} == 5 && $detect->{rolePatternCount} > 1 && $clType eq 'HMCCUDEV' &&
AttrVal ($clName, 'statedatapoint', '') eq '' && AttrVal ($clName, 'controldatapoint', '') eq '') || AttrVal ($clName, 'statedatapoint', '') eq '' && AttrVal ($clName, 'controldatapoint', '') eq '') ||
($detect->{defSCh} == -1 && $detect->{defCCh} == -1)) { ($detect->{defSCh} == -1 && $detect->{defCCh} == -1))
HMCCU_LogDisplay ($clHash, 2, "Please select a state and/or control datapoint by using attributes statedatapoint and controldatapoint"); {
push @toast, 'Please select a state and/or control datapoint by using attributes statedatapoint and controldatapoint.';
} }
else { else {
push @removeAttr, 'statechannel', 'statedatapoint' if ($detect->{defSCh} != -1); push @removeAttr, 'statechannel', 'statedatapoint' if ($detect->{defSCh} != -1);
push @removeAttr, 'controlchannel', 'controldatapoint', 'statevals' if ($detect->{defCCh} != -1); push @removeAttr, 'controlchannel', 'controldatapoint', 'statevals' if ($detect->{defCCh} != -1);
} }
# Remove attributes # Keep attribute if it differs from old defaults
my $template = HMCCU_FindDefaults ($clHash);
if (defined($template)) {
foreach my $a (@attrList) {
my $av = AttrVal ($clName, $a, '');
if ($parRef->{mode} eq 'forceReset' || (exists($template->{$a}) && $av eq $template->{$a})) {
push @removeAttr, $a;
next;
}
push @keepAttr, $a if ($av ne '');
}
}
push @toast, 'Attributes '.join(',',@keepAttr).' are no longer needed in 5.0 but differ from old 4.3 defaults. Please remove all HMCCU values from them or delete the attributes manually'
if (scalar(@keepAttr) > 0);
push @toast, 'Removed attributes '.join(',', @removeAttr) if (scalar(@removeAttr) > 0);
# Remove attributes. Set flag 'setDefaults' to prevent calling HMCCU_SetDefaultSCDatapoints in Attr function
# of client devices
HMCCU_DeleteAttributes ($clHash, \@removeAttr, 1); HMCCU_DeleteAttributes ($clHash, \@removeAttr, 1);
# Update command tables my ($sc, $sd, $cc, $cd, $rsd, $rcd) = HMCCU_SetDefaultSCDatapoints ($ioHash, $clHash, $detect, 1);
HMCCU_UpdateRoleCommands ($ioHash, $clHash, $cc); push @toast, 'Cannot set default state and control datapoint.'
HMCCU_UpdateAdditionalCommands ($ioHash, $clHash, $cc, $cd); if ($rsd == 0 && $rcd == 0);
} }
else { else {
HMCCU_LogDisplay ($clHash, 2, "Device type $clHash->{ccutype} not known by HMCCU"); push @toast, "Device type $clHash->{ccutype} not known by HMCCU";
# Remove attributes $rc = 0;
HMCCU_DeleteAttributes ($clHash, \@removeAttr, 1);
} }
} }
else { else {
@ -6689,22 +6745,18 @@ sub HMCCU_SetDefaultAttributes ($;$)
} }
if (defined($role) && $role ne '') { if (defined($role) && $role ne '') {
$clHash->{hmccu}{semDefaults} = 1;
# Set additional attributes # Set additional attributes
if (exists($HMCCU_ATTR->{$role}) && !exists($HMCCU_ATTR->{$role}{_none_})) { if (exists($HMCCU_ATTR->{$role}) && !exists($HMCCU_ATTR->{$role}{_none_})) {
foreach my $a (keys %{$HMCCU_ATTR->{$role}}) { foreach my $a (keys %{$HMCCU_ATTR->{$role}}) {
CommandAttr (undef, "$clName $a ".$HMCCU_ATTR->{$role}{$a}); CommandAttr (undef, "$clName $a ".$HMCCU_ATTR->{$role}{$a});
} }
} }
$clHash->{hmccu}{semDefaults} = 0;
return 1;
} }
else { else {
HMCCU_Log ($clHash, 2, "Cannot detect role of $clName"); push @toast, "Cannot detect role of $clName";
return 0;
} }
return ($rc, join("\n", @toast));
} }
###################################################################### ######################################################################
@ -6717,11 +6769,11 @@ sub HMCCU_DeleteAttributes ($$;$)
$sem //= 0; $sem //= 0;
my $clName = $clHash->{NAME}; my $clName = $clHash->{NAME};
$clHash->{hmccu}{semDefaults} = $sem; $clHash->{hmccu}{setDefaults} = $sem;
foreach my $a (@$attrList) { foreach my $a (@$attrList) {
CommandDeleteAttr (undef, "$clName $a") if (exists($attr{$clName}{$a})); CommandDeleteAttr (undef, "$clName $a") if (exists($attr{$clName}{$a}));
} }
$clHash->{hmccu}{semDefaults} = 0; $clHash->{hmccu}{setDefaults} = 0;
} }
###################################################################### ######################################################################
@ -7571,7 +7623,10 @@ sub HMCCU_ExecuteGetParameterCommand ($@)
my %objects; my %objects;
foreach my $a (@$addList) { foreach my $a (@$addList) {
my $devDesc = HMCCU_GetDeviceDesc ($ioHash, $a, $clHash->{ccuif}); my $devDesc = HMCCU_GetDeviceDesc ($ioHash, $a, $clHash->{ccuif});
return HMCCU_SetError ($clHash, "Can't get device description") if (!defined($devDesc)); if (!defined($devDesc)) {
HMCCU_Log ($clHash, 2, "Can't get device description");
return undef;
}
my $paramset = $defParamset eq '' ? $devDesc->{PARAMSETS} : $defParamset; my $paramset = $defParamset eq '' ? $devDesc->{PARAMSETS} : $defParamset;
my ($da, $dc) = HMCCU_SplitChnAddr ($a); my ($da, $dc) = HMCCU_SplitChnAddr ($a);
@ -7739,16 +7794,19 @@ sub HMCCU_CheckParameter ($$;$$$)
# the channel number. # the channel number.
# If parameter v is missing, the attribute is deleted # If parameter v is missing, the attribute is deleted
# Parameter r contains the role. # Parameter r contains the role.
# If $cmd == 1 update role commands.
# Return: # Return:
# 0=Error, 1=Success # 0=Error, 1=Success
###################################################################### ######################################################################
sub HMCCU_SetSCDatapoints ($$;$$) sub HMCCU_SetSCDatapoints ($$;$$$)
{ {
my ($clHash, $d, $v, $r) = @_; my ($clHash, $d, $v, $r, $cmd) = @_;
my $ioHash = HMCCU_GetHash ($clHash); my $ioHash = HMCCU_GetHash ($clHash);
my $addr = $clHash->{ccuaddr};
$r //= ''; $r //= '';
$cmd //= 0;
# Flags: 1=statechannel, 2=statedatapoint, 4=controlchannel, 8=controldatapoint # Flags: 1=statechannel, 2=statedatapoint, 4=controlchannel, 8=controldatapoint
my %flags = ( my %flags = (
@ -7767,18 +7825,31 @@ sub HMCCU_SetSCDatapoints ($$;$$)
if (defined($v)) { if (defined($v)) {
# Set value # Set value
return 0 if ($v eq ''); return 0 if (!HMCCU_IsDeviceActive ($clHash) || $v eq '' || $v eq '.' || $v =~ /^[0-9]+\.$/ || $v =~ /^\..+$/);
if ($f & 10) { if ($f & 10) {
($chn, $dpt) = $v =~ /^([0-9]{1,2})\.(.+)/ ? ($1, $2) : ($clHash->{hmccu}{$d}{chn}, $v); # statedatapoint / controldatapoint
if ($v =~ /^([0-9]{1,2})\.(.+)$/) {
($chn, $dpt) = ($1, $2);
}
else {
($chn, $dpt) = ($clHash->{hmccu}{$d}{chn}, $v);
if ((!defined($chn) || $chn eq '') && $clHash->{TYPE} eq 'HMCCUCHN') {
my ($da, $cn) = HMCCU_SplitChnAddr ($addr);
$chn = $cn;
}
}
} }
elsif ($f & 5) { elsif ($f & 5) {
# statechannel / controlchannel
return 0 if ($v !~ /^[0-9]{1,2}$/); return 0 if ($v !~ /^[0-9]{1,2}$/);
($chn, $dpt) = ($v, $clHash->{hmccu}{$d}{dpt}); ($chn, $dpt) = ($v, $clHash->{hmccu}{$d}{dpt});
} }
HMCCU_Log ($clHash, 2, "f=$f chn not defined in $d $v".stacktraceAsString(undef)) if (!defined($chn));
HMCCU_Log ($clHash, 2, "f=$f dpt not defined in $d $v".stacktraceAsString(undef)) if (!defined($dpt) && !($f & 5));
return 0 if ($init_done && defined($chn) && $chn ne '' && defined($dpt) && $dpt ne '' && return 0 if ($init_done && defined($chn) && $chn ne '' && defined($dpt) && $dpt ne '' &&
!HMCCU_IsValidDatapoint ($clHash, $clHash->{ccutype}, $chn, $dpt, $f & 3 ? 5 : 2)); !HMCCU_IsValidParameter ($clHash, HMCCU_GetChannelAddr ($clHash, $chn), 'VALUES', $dpt, $f & 3 ? 5 : 2));
$clHash->{ccurolestate} = $r if ($r ne '' && $f & 3); $clHash->{ccurolestate} = $r if ($r ne '' && $f & 3);
$clHash->{ccurolectrl} = $r if ($r ne '' && $f & 12); $clHash->{ccurolectrl} = $r if ($r ne '' && $f & 12);
@ -7811,6 +7882,15 @@ sub HMCCU_SetSCDatapoints ($$;$$)
} }
} }
# Optionally update internal command tables
if ($cmd) {
my ($cc, $cd) = HMCCU_ControlDatapoint ($clHash);
if ($cc ne '' && $cd ne '') {
HMCCU_UpdateRoleCommands ($ioHash, $clHash, $cc);
HMCCU_UpdateAdditionalCommands ($ioHash, $clHash, $cc, $cd);
}
}
return 1; return 1;
} }
@ -7836,6 +7916,7 @@ sub HMCCU_SetDefaultSCDatapoints ($$;$$)
$cc = $detect->{defCCh} if ($detect->{defCCh} != -1); $cc = $detect->{defCCh} if ($detect->{defCCh} != -1);
$sd = $detect->{stateRole}{$sc}{datapoint} if ($sc ne '' && exists($detect->{stateRole}{$sc})); $sd = $detect->{stateRole}{$sc}{datapoint} if ($sc ne '' && exists($detect->{stateRole}{$sc}));
$cd = $detect->{controlRole}{$cc}{datapoint} if ($cc ne '' && exists($detect->{controlRole}{$cc})); $cd = $detect->{controlRole}{$cc}{datapoint} if ($cc ne '' && exists($detect->{controlRole}{$cc}));
# HMCCU_Log ($clHash, 2, "Prio 4: s=$sc.$sd c=$cc.$sd");
} }
# Prio 3: Use information stored in device hash (HMCCUDEV only) # Prio 3: Use information stored in device hash (HMCCUDEV only)
@ -7843,6 +7924,7 @@ sub HMCCU_SetDefaultSCDatapoints ($$;$$)
# Support for level 5 devices # Support for level 5 devices
($sc, $sd) = HMCCU_SplitDatapoint ($clHash->{hmccu}{defSDP}) if (defined($clHash->{hmccu}{defSDP})); ($sc, $sd) = HMCCU_SplitDatapoint ($clHash->{hmccu}{defSDP}) if (defined($clHash->{hmccu}{defSDP}));
($cc, $cd) = HMCCU_SplitDatapoint ($clHash->{hmccu}{defCDP}) if (defined($clHash->{hmccu}{defCDP})); ($cc, $cd) = HMCCU_SplitDatapoint ($clHash->{hmccu}{defCDP}) if (defined($clHash->{hmccu}{defCDP}));
# HMCCU_Log ($clHash, 2, "Prio 3: s=$sc.$sd c=$cc.$sd");
} }
# Prio 2: Use attribute statechannel and controlchannel for HMCCUDEV and channel address for HMCCUCHN # Prio 2: Use attribute statechannel and controlchannel for HMCCUDEV and channel address for HMCCUCHN
@ -7857,6 +7939,7 @@ sub HMCCU_SetDefaultSCDatapoints ($$;$$)
$sc = AttrVal ($clName, 'statechannel', $sc); $sc = AttrVal ($clName, 'statechannel', $sc);
$cc = AttrVal ($clName, 'controlchannel', $cc); $cc = AttrVal ($clName, 'controlchannel', $cc);
} }
# HMCCU_Log ($clHash, 2, "Prio 2: s=$sc.$sd c=$cc.$sd");
# Prio 1: Use attributes statedatapoint and controldatapoint # Prio 1: Use attributes statedatapoint and controldatapoint
# Attributes are overriding attributes statechannel and controlchannel for HMCCUDEV # Attributes are overriding attributes statechannel and controlchannel for HMCCUDEV
@ -7878,11 +7961,13 @@ sub HMCCU_SetDefaultSCDatapoints ($$;$$)
} }
$cd = $ca[0]; $cd = $ca[0];
} }
# HMCCU_Log ($clHash, 2, "Prio 1: s=$sc.$sd c=$cc.$sd");
my $sr = $sc ne '' && defined($detect) && exists($detect->{stateRole}{$sc}) ? $detect->{stateRole}{$sc}{role} : ''; my $sr = $sc ne '' && defined($detect) && exists($detect->{stateRole}{$sc}) ? $detect->{stateRole}{$sc}{role} : '';
my $cr = $cc ne '' && defined($detect) && exists($detect->{controlRole}{$cc}) ? $detect->{controlRole}{$cc}{role} : ''; my $cr = $cc ne '' && defined($detect) && exists($detect->{controlRole}{$cc}) ? $detect->{controlRole}{$cc}{role} : '';
($sc, $sd) = ('', '') if (!HMCCU_SetSCDatapoints ($clHash, 'statedatapoint', "$sc.$sd", $sr)); ($sc, $sd) = ('', '') if (!HMCCU_SetSCDatapoints ($clHash, 'statedatapoint', "$sc.$sd", $sr));
($cc, $cd) = ('', '') if (!HMCCU_SetSCDatapoints ($clHash, 'controldatapoint', "$cc.$cd", $cr)); ($cc, $cd) = ('', '') if (!HMCCU_SetSCDatapoints ($clHash, 'controldatapoint', "$cc.$cd", $cr));
# HMCCU_Log ($clHash, 2, "SetDC: s=$sc.$sd c=$cc.$sd sr=$sr cr=$cr");
if ($cmd) { if ($cmd) {
my $chn = $cc ne '' ? $cc : $sc; my $chn = $cc ne '' ? $cc : $sc;
@ -8887,8 +8972,8 @@ sub HMCCU_SetMultipleParameters ($$$;$)
foreach my $p (sort keys %$params) { foreach my $p (sort keys %$params) {
HMCCU_Trace ($clHash, 2, "Parameter=$address.$paramSet.$p Value=$params->{$p}"); HMCCU_Trace ($clHash, 2, "Parameter=$address.$paramSet.$p Value=$params->{$p}");
return (-8, undef) if ( return (-8, undef) if (
($paramSet eq 'VALUES' && !HMCCU_IsValidDatapoint ($clHash, $clHash->{ccutype}, $chn, $p, 2)) || ($paramSet eq 'VALUES' && !HMCCU_IsValidParameter ($clHash, $address, 'VALUES', $p, 2)) ||
($paramSet eq 'MASTER' && !HMCCU_IsValidParameter ($clHash, $address, $paramSet, $p)) ($paramSet eq 'MASTER' && !HMCCU_IsValidParameter ($clHash, $address, 'MASTER', $p))
); );
$params->{$p} = HMCCU_ScaleValue ($clHash, $chn, $p, $params->{$p}, 1); $params->{$p} = HMCCU_ScaleValue ($clHash, $chn, $p, $params->{$p}, 1);
} }
@ -8949,7 +9034,7 @@ sub HMCCU_SetMultipleDatapoints ($$) {
my $clType = $clHash->{TYPE}; my $clType = $clHash->{TYPE};
my $ccuType = $clHash->{ccutype}; my $ccuType = $clHash->{ccutype};
return -1 if ($clType ne 'HMCCUCHN' && $clType ne 'HMCCUDEV'); return -1 if ($clType ne 'HMCCUCHN' && $clType ne 'HMCCUDEV');
if (!HMCCU_IsValidDatapoint ($clHash, $ccuType, $chn, $dpt, 2)) { if (!HMCCU_IsValidParameter ($clHash, HMCCU_GetChannelAddr ($clHash, $chn), 'VALUES', $dpt, 2)) {
HMCCU_Trace ($clHash, 2, "Invalid datapoint $chn $dpt"); HMCCU_Trace ($clHash, 2, "Invalid datapoint $chn $dpt");
return -8; return -8;
} }
@ -9230,7 +9315,7 @@ sub HMCCU_GetUpdate ($$;$$)
my $name = $clHash->{NAME}; my $name = $clHash->{NAME};
my $type = $clHash->{TYPE}; my $type = $clHash->{TYPE};
return 1 if (AttrVal ($name, 'disable', 0) == 1); return 1 if (!HMCCU_IsDeviceActive ($clHash));
my $ioHash = HMCCU_GetHash ($clHash) // return -3; my $ioHash = HMCCU_GetHash ($clHash) // return -3;
return -4 if ($type ne 'HMCCU' && $clHash->{ccudevstate} eq 'deleted'); return -4 if ($type ne 'HMCCU' && $clHash->{ccudevstate} eq 'deleted');

View File

@ -30,7 +30,7 @@ sub HMCCUCHN_Set ($@);
sub HMCCUCHN_Get ($@); sub HMCCUCHN_Get ($@);
sub HMCCUCHN_Attr ($@); sub HMCCUCHN_Attr ($@);
my $HMCCUCHN_VERSION = '5.0 213011850'; my $HMCCUCHN_VERSION = '5.0 213141800';
###################################################################### ######################################################################
# Initialize module # Initialize module
@ -97,8 +97,8 @@ sub HMCCUCHN_Define ($@)
$hash->{readonly} = 'no'; $hash->{readonly} = 'no';
$hash->{hmccu}{channels} = 1; $hash->{hmccu}{channels} = 1;
$hash->{hmccu}{nodefaults} = $init_done ? 0 : 1; $hash->{hmccu}{nodefaults} = $init_done ? 0 : 1;
$hash->{hmccu}{semDefaults} = 0;
$hash->{hmccu}{detect} = 0; $hash->{hmccu}{detect} = 0;
$hash->{hmccu}{setDefaults} = 0;
# Parse optional command line parameters # Parse optional command line parameters
my $n = 0; my $n = 0;
@ -184,6 +184,7 @@ sub HMCCUCHN_InitDevice ($$)
my $rc = 0; my $rc = 0;
if ($init_done) { if ($init_done) {
HMCCU_Log ($devHash, 2, "InitDevice called when init done");
my $detect = HMCCU_DetectDevice ($ioHash, $da, $di); my $detect = HMCCU_DetectDevice ($ioHash, $da, $di);
# Interactive device definition # Interactive device definition
@ -199,8 +200,12 @@ sub HMCCUCHN_InitDevice ($$)
if ($rsd == 0 && $rcd == 0); if ($rsd == 0 && $rcd == 0);
if (!exists($devHash->{hmccu}{nodefaults}) || $devHash->{hmccu}{nodefaults} == 0) { if (!exists($devHash->{hmccu}{nodefaults}) || $devHash->{hmccu}{nodefaults} == 0) {
if (!HMCCU_SetDefaultAttributes ($devHash)) { # Don't let device definition fail if default attributes cannot be set
HMCCU_SetDefaults ($devHash); my ($rc, $retMsg) = HMCCU_SetDefaultAttributes ($devHash);
if (!$rc) {
HMCCU_Log ($devHash, 2, $retMsg);
HMCCU_Log ($devHash, 2, 'No HMCCU 4.3 default attributes found during device definition')
if (!HMCCU_SetDefaults ($devHash));
} }
} }
} }
@ -252,6 +257,7 @@ sub HMCCUCHN_Attr ($@)
my ($cmd, $name, $attrname, $attrval) = @_; my ($cmd, $name, $attrname, $attrval) = @_;
my $clHash = $defs{$name}; my $clHash = $defs{$name};
my $ioHash = HMCCU_GetHash ($clHash); my $ioHash = HMCCU_GetHash ($clHash);
my $clType = $clHash->{TYPE};
if ($cmd eq 'set') { if ($cmd eq 'set') {
return 'Missing attribute value' if (!defined($attrval)); return 'Missing attribute value' if (!defined($attrval));
@ -259,15 +265,16 @@ sub HMCCUCHN_Attr ($@)
$clHash->{IODev} = $defs{$attrval}; $clHash->{IODev} = $defs{$attrval};
} }
elsif ($attrname eq 'statevals') { elsif ($attrname eq 'statevals') {
return 'Attribute statevals ignored. Device is read only' if ($clHash->{readonly} eq 'yes'); return "$clType [$name] Attribute statevals ignored. Device is read only" if ($clHash->{readonly} eq 'yes');
return 'Attribute statevals ignored. Device type is known by HMCCU' if ($clHash->{hmccu}{detect} > 0); return "$clType [$name] Attribute statevals ignored. Device type is known by HMCCU" if ($clHash->{hmccu}{detect} > 0);
if ($init_done && !HMCCU_IsValidControlDatapoint ($clHash)) { if ($init_done && !HMCCU_IsValidControlDatapoint ($clHash)) {
HMCCU_LogDisplay ($clHash, 2, 'Warning: Attribute controldatapoint not set or set to invalid datapoint'); HMCCU_LogDisplay ($clHash, 2, 'Warning: Attribute controldatapoint not set or set to invalid datapoint');
} }
} }
elsif ($attrname =~ /^(state|control)datapoint$/) { elsif ($attrname =~ /^(state|control)datapoint$/) {
my $role = HMCCU_GetChannelRole ($clHash); my $role = HMCCU_GetChannelRole ($clHash);
return "Invalid value $attrval" if (!HMCCU_SetSCDatapoints ($clHash, $attrname, $attrval, $role)); return "$clType [$name] Invalid value $attrval for attribute $attrname"
if (!HMCCU_SetSCDatapoints ($clHash, $attrname, $attrval, $role, 1));
} }
} }
elsif ($cmd eq 'del') { elsif ($cmd eq 'del') {
@ -277,7 +284,7 @@ sub HMCCUCHN_Attr ($@)
delete $clHash->{hmccu}{roleCmds} delete $clHash->{hmccu}{roleCmds}
if (exists($clHash->{hmccu}{roleCmds}) && if (exists($clHash->{hmccu}{roleCmds}) &&
(!exists($clHash->{hmccu}{control}{chn}) || $clHash->{hmccu}{control}{chn} eq '')); (!exists($clHash->{hmccu}{control}{chn}) || $clHash->{hmccu}{control}{chn} eq ''));
if ($init_done) { if ($init_done && $clHash->{hmccu}{setDefaults} == 0) {
my ($sc, $sd, $cc, $cd, $rsd, $rcd) = HMCCU_SetDefaultSCDatapoints ($ioHash, $clHash, undef, 1); my ($sc, $sd, $cc, $cd, $rsd, $rcd) = HMCCU_SetDefaultSCDatapoints ($ioHash, $clHash, undef, 1);
HMCCU_Log ($clHash, 2, "Cannot set default state- and/or control datapoints") HMCCU_Log ($clHash, 2, "Cannot set default state- and/or control datapoints")
if ($rsd == 0 && $rcd == 0); if ($rsd == 0 && $rcd == 0);
@ -312,7 +319,7 @@ sub HMCCUCHN_Set ($@)
if (HMCCU_IsRPCStateBlocking ($ioHash)); if (HMCCU_IsRPCStateBlocking ($ioHash));
# Build set command syntax # Build set command syntax
my $syntax = 'clear defaults:reset,update,old'; my $syntax = 'clear defaults:reset,update,old,forceReset';
# Command readingFilter depends on readable datapoints # Command readingFilter depends on readable datapoints
my ($add, $chn) = split(":", $hash->{ccuaddr}); my ($add, $chn) = split(":", $hash->{ccuaddr});
@ -359,15 +366,18 @@ sub HMCCUCHN_Set ($@)
} }
elsif ($lcopt eq 'defaults') { elsif ($lcopt eq 'defaults') {
my $mode = shift @$a // 'update'; my $mode = shift @$a // 'update';
return HMCCU_SetError ($hash, "Usage: get $name defaults [forceReset|old|reset|update]")
if ($mode !~ /^(forceReset|reset|old|update)$/);
my $rc = 0; my $rc = 0;
my $retMsg = 'OK'; my $retMsg = '';
if ($mode ne 'old') { ($rc, $retMsg) = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, roleChn => undef }) if ($mode ne 'old');
$rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, roleChn => undef }); if (!$rc) {
$retMsg = 'Please remove HMCCU 4.3 entries from attribute eventMap' if ($rc && $mode eq 'reset' && exists($attr{$name}{eventMap})); $rc = HMCCU_SetDefaults ($hash);
$retMsg .= $rc ? "\nSet version 4.3 attributes" : "\nNo version 4.3 default attributes found";
} }
$rc = HMCCU_SetDefaults ($hash) if (!$rc); $retMsg = 'OK' if ($retMsg eq '');
HMCCU_RefreshReadings ($hash) if ($rc); HMCCU_RefreshReadings ($hash) if ($rc);
return HMCCU_SetError ($hash, $rc == 0 ? 'No default attributes found' : $retMsg); return HMCCU_SetError ($hash, $retMsg);
} }
else { else {
return "Unknown argument $opt choose one of $syntax"; return "Unknown argument $opt choose one of $syntax";
@ -419,9 +429,9 @@ sub HMCCUCHN_Get ($@)
if ($lcopt 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, $objname) return HMCCU_SetError ($hash, -8, $objname)
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $objname, 1)); if (!HMCCU_IsValidParameter ($hash, $ccuaddr, 'VALUES', $objname, 1));
$objname = $ccuif.'.'.$ccuaddr.'.'.$objname; $objname = "$ccuif.$ccuaddr.$objname";
my ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname, 0); my ($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;
} }
@ -544,12 +554,16 @@ sub HMCCUCHN_Get ($@)
<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>
</li><br/> </li><br/>
<li><b>set &lt;name&gt; defaults ['reset'|'old'|'<u>update</u>']</b><br/> <li><b>set &lt;name&gt; defaults ['reset'|'forceReset'|'old'|'<u>update</u>']</b><br/>
Set default attributes for CCU device type. Default attributes are only available for Set default attributes for CCU device type. Default attributes are only available for
some device types and for some channels of a device type. If option 'reset' is specified, some device types and for some channels of a device type. With option 'reset' obsolete attributes
the following attributes are deleted before the new attributes are set: are deleted if they are matching the default attributes of HMCCU 4.3. Attributes modified
'ccureadingname', 'ccuscaleval', 'eventMap', 'substexcl', 'webCmd', 'widgetOverride'. by the user will be kept.<br/>
During update to version 4.4 it's recommended to use option 'reset'. With option 'old' With option 'forceReset' all obsolete attributes will be deleted. The following attributes are
obsolete in HMCCU 5.x: 'ccureadingname', 'ccuscaleval', 'eventMap', 'substexcl', 'webCmd', 'widgetOverride'.
In addition 'statedatapoint', 'statechannel', 'controldatapoint' and 'controlchannel' are removed if HMCCU
is able to detect these values automatically.<br/>
During update to version 5.x it's recommended to use option 'reset' or 'forceReset'. With option 'old'
the attributes are set according to HMCCU 4.3 defaults mechanism. the attributes are set according to HMCCU 4.3 defaults mechanism.
</li><br/> </li><br/>
<li><b>set &lt;name&gt; down [&lt;value&gt;]</b><br/> <li><b>set &lt;name&gt; down [&lt;value&gt;]</b><br/>

View File

@ -31,7 +31,7 @@ sub HMCCUDEV_Set ($@);
sub HMCCUDEV_Get ($@); sub HMCCUDEV_Get ($@);
sub HMCCUDEV_Attr ($@); sub HMCCUDEV_Attr ($@);
my $HMCCUDEV_VERSION = '5.0 213011850'; my $HMCCUDEV_VERSION = '5.0 213141800';
###################################################################### ######################################################################
# Initialize module # Initialize module
@ -109,11 +109,11 @@ sub HMCCUDEV_Define ($@)
$hash->{hmccu}{groupexp} = $h->{groupexp} if (exists($h->{groupexp})); $hash->{hmccu}{groupexp} = $h->{groupexp} if (exists($h->{groupexp}));
$hash->{hmccu}{group} = $h->{group} if (exists($h->{group})); $hash->{hmccu}{group} = $h->{group} if (exists($h->{group}));
$hash->{hmccu}{nodefaults} = $init_done ? 0 : 1; $hash->{hmccu}{nodefaults} = $init_done ? 0 : 1;
$hash->{hmccu}{semDefaults} = 0;
$hash->{hmccu}{forcedev} = 0; $hash->{hmccu}{forcedev} = 0;
$hash->{hmccu}{detect} = 0; $hash->{hmccu}{detect} = 0;
$hash->{hmccu}{defSDP} = $h->{sd} if (exists($h->{sd})); $hash->{hmccu}{defSDP} = $h->{sd} if (exists($h->{sd}));
$hash->{hmccu}{defCDP} = $h->{cd} if (exists($h->{cd})); $hash->{hmccu}{defCDP} = $h->{cd} if (exists($h->{cd}));
$hash->{hmccu}{setDefaults} = 0;
# Parse optional command line parameters # Parse optional command line parameters
foreach my $arg (@$a) { foreach my $arg (@$a) {
@ -209,6 +209,7 @@ sub HMCCUDEV_InitDevice ($$)
my $rc = 0; my $rc = 0;
if ($init_done) { if ($init_done) {
HMCCU_Log ($devHash, 2, "InitDevice called when init done");
my $detect = HMCCU_DetectDevice ($ioHash, $da, $di); my $detect = HMCCU_DetectDevice ($ioHash, $da, $di);
return "Specify option 'forceDev' for HMCCUDEV or use HMCCUCHN instead (recommended). Command: define $name HMCCUCHN $detect->{defAdd}" return "Specify option 'forceDev' for HMCCUDEV or use HMCCUCHN instead (recommended). Command: define $name HMCCUCHN $detect->{defAdd}"
if (defined($detect) && $detect->{defMod} eq 'HMCCUCHN' && $devHash->{hmccu}{forcedev} == 0); if (defined($detect) && $detect->{defMod} eq 'HMCCUCHN' && $devHash->{hmccu}{forcedev} == 0);
@ -243,11 +244,14 @@ sub HMCCUDEV_InitDevice ($$)
if (!exists($devHash->{hmccu}{nodefaults}) || $devHash->{hmccu}{nodefaults} == 0) { if (!exists($devHash->{hmccu}{nodefaults}) || $devHash->{hmccu}{nodefaults} == 0) {
my $chn = $detect->{defCCh} != -1 ? $detect->{defCCh} : $detect->{defSCh}; my $chn = $detect->{defCCh} != -1 ? $detect->{defCCh} : $detect->{defSCh};
if (!HMCCU_SetDefaultAttributes ($devHash, { # Don't let device definition fail if default attributes cannot be set
my ($rc, $retMsg) = HMCCU_SetDefaultAttributes ($devHash, {
mode => 'update', role => undef, roleChn => $chn, mode => 'update', role => undef, roleChn => $chn,
})) { });
HMCCU_Log ($devHash, 2, "No role attributes found for channel $chn"); if (!$rc) {
HMCCU_SetDefaults ($devHash); HMCCU_Log ($devHash, 2, $retMsg);
HMCCU_Log ($devHash, 2, 'No HMCCU 4.3 default attributes found during device definition')
if (!HMCCU_SetDefaults ($devHash));
} }
} }
} }
@ -328,15 +332,16 @@ sub HMCCUDEV_Attr ($@)
my ($cmd, $name, $attrname, $attrval) = @_; my ($cmd, $name, $attrname, $attrval) = @_;
my $clHash = $defs{$name}; my $clHash = $defs{$name};
my $ioHash = HMCCU_GetHash ($clHash); my $ioHash = HMCCU_GetHash ($clHash);
my $clType = $clHash->{TYPE};
if ($cmd eq 'set') { if ($cmd eq 'set') {
return "Missing value of attribute $attrname" if (!defined($attrval)); return "$clType [$name] Missing value of attribute $attrname" if (!defined($attrval));
if ($attrname eq 'IODev') { if ($attrname eq 'IODev') {
$clHash->{IODev} = $defs{$attrval}; $clHash->{IODev} = $defs{$attrval};
} }
elsif ($attrname eq 'statevals') { elsif ($attrname eq 'statevals') {
return 'Attribute statevals ignored. Device is read only' if ($clHash->{readonly} eq 'yes'); return "$clType [$name] Attribute statevals ignored. Device is read only" if ($clHash->{readonly} eq 'yes');
return 'Attribute statevals ignored. Device type is known by HMCCU' if ($clHash->{hmccu}{detect} > 0); return "$clType [$name] Attribute statevals ignored. Device type is known by HMCCU" if ($clHash->{hmccu}{detect} > 0);
if ($init_done && !HMCCU_IsValidControlDatapoint ($clHash)) { if ($init_done && !HMCCU_IsValidControlDatapoint ($clHash)) {
HMCCU_LogDisplay ($clHash, 2, 'Warning: Attribute controldatapoint not set or set to invalid datapoint'); HMCCU_LogDisplay ($clHash, 2, 'Warning: Attribute controldatapoint not set or set to invalid datapoint');
} }
@ -348,16 +353,17 @@ sub HMCCUDEV_Attr ($@)
$chn = $1; $chn = $1;
} }
else { else {
return "Attribute value must be in format channel.datapoint"; return "$clType [$name] Value of attribute $attrname must be in format channel.datapoint";
} }
} }
else { else {
return "Attribute value must be a valid channel number" if (!HMCCU_IsIntNum ($attrval)); return "$clType [$name] Value of attribute $attrname must be a valid channel number" if (!HMCCU_IsIntNum ($attrval));
$chn = $attrval; $chn = $attrval;
} }
my $role = HMCCU_GetChannelRole ($clHash, $chn); my $role = HMCCU_GetChannelRole ($clHash, $chn);
return "Invalid value $attrval" if (!HMCCU_SetSCDatapoints ($clHash, $attrname, $attrval, $role)); return "$clType [$name] Invalid value $attrval for attribute $attrname"
if (!HMCCU_SetSCDatapoints ($clHash, $attrname, $attrval, $role, 1));
} }
} }
elsif ($cmd eq 'del') { elsif ($cmd eq 'del') {
@ -367,10 +373,10 @@ sub HMCCUDEV_Attr ($@)
delete $clHash->{hmccu}{roleCmds} delete $clHash->{hmccu}{roleCmds}
if (exists($clHash->{hmccu}{roleCmds}) && if (exists($clHash->{hmccu}{roleCmds}) &&
(!exists($clHash->{hmccu}{control}{chn}) || $clHash->{hmccu}{control}{chn} eq '')); (!exists($clHash->{hmccu}{control}{chn}) || $clHash->{hmccu}{control}{chn} eq ''));
if ($init_done) { if ($init_done && $clHash->{hmccu}{setDefaults} == 0) {
# Try to set default state and control datapoint and update command list # Try to set default state and control datapoint and update command list
my ($sc, $sd, $cc, $cd, $rsd, $rcd) = HMCCU_SetDefaultSCDatapoints ($ioHash, $clHash, undef, 1); my ($sc, $sd, $cc, $cd, $rsd, $rcd) = HMCCU_SetDefaultSCDatapoints ($ioHash, $clHash, undef, 1);
HMCCU_Log ($clHash, 2, "Cannot set default state- and/or control datapoints") HMCCU_Log ($clHash, 2, "Deleted attribute $attrname but cannot set default state- and/or control datapoints")
if ($rsd == 0 && $rcd == 0); if ($rsd == 0 && $rcd == 0);
} }
} }
@ -402,7 +408,7 @@ sub HMCCUDEV_Set ($@)
if (HMCCU_IsRPCStateBlocking ($ioHash)); if (HMCCU_IsRPCStateBlocking ($ioHash));
# Build set command syntax # Build set command syntax
my $syntax = 'clear defaults:reset,update,old'; my $syntax = 'clear defaults:reset,update,old,forceReset';
# Command readingFilter depends on readable datapoints # Command readingFilter depends on readable datapoints
my @dpRList = (); my @dpRList = ();
@ -447,15 +453,18 @@ sub HMCCUDEV_Set ($@)
} }
elsif ($lcopt eq 'defaults') { elsif ($lcopt eq 'defaults') {
my $mode = shift @$a // 'update'; my $mode = shift @$a // 'update';
return HMCCU_SetError ($hash, "Usage: get $name defaults [forceReset|old|reset|update]")
if ($mode !~ /^(forceReset|reset|old|update)$/);
my $rc = 0; my $rc = 0;
my $retMsg = 'OK'; my $retMsg = '';
if ($mode ne 'old') { ($rc, $retMsg) = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, roleChn => undef }) if ($mode ne 'old');
$rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, roleChn => undef }); if (!$rc) {
$retMsg = 'Please remove HMCCU 4.3 entries from attribute eventMap' if ($rc && $mode eq 'reset' && exists($attr{$name}{eventMap})); $rc = HMCCU_SetDefaults ($hash);
$retMsg .= $rc ? "\nSet version 4.3 attributes" : "\nNo version 4.3 default attributes found";
} }
$rc = HMCCU_SetDefaults ($hash) if (!$rc); $retMsg = 'OK' if ($retMsg eq '');
HMCCU_RefreshReadings ($hash) if ($rc); HMCCU_RefreshReadings ($hash) if ($rc);
return HMCCU_SetError ($hash, $rc == 0 ? 'No default attributes found' : $retMsg); return HMCCU_SetError ($hash, $retMsg);
} }
else { else {
return "Unknown argument $opt choose one of $syntax"; return "Unknown argument $opt choose one of $syntax";
@ -508,21 +517,22 @@ sub HMCCUDEV_Get ($@)
if ($lcopt 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}");
my $chn;
if ($objname =~ /^([0-9]+)\..+$/) { my $dpt;
my $chn = $1; if ($objname =~ /^([0-9]+)\.(.+)$/) {
($chn, $dpt) = ($1, $2);
return HMCCU_SetError ($hash, -7) if ($chn >= $hash->{hmccu}{channels}); return HMCCU_SetError ($hash, -7) if ($chn >= $hash->{hmccu}{channels});
} }
else { else {
my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($hash); my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($hash);
return HMCCU_SetError ($hash, -11) if ($sc eq ''); return HMCCU_SetError ($hash, -11) if ($sc eq '');
$objname = $sc.'.'.$objname; ($chn, $dpt) = ($sc, $objname);
} }
return HMCCU_SetError ($hash, -8, $objname) return HMCCU_SetError ($hash, -8, $objname)
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, undef, $objname, 1)); if (!HMCCU_IsValidParameter ($hash, HMCCU_GetChannelAddr ($hash, $chn), 'VALUES', $dpt, 1));
$objname = $ccuif.'.'.$ccuaddr.':'.$objname; $objname = "$ccuif.$ccuaddr:$chn.$dpt";
my ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname, 0); my ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname, 0);
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0); return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);

View File

@ -39,7 +39,7 @@ require "$attr{global}{modpath}/FHEM/88_HMCCU.pm";
###################################################################### ######################################################################
# HMCCURPC version # HMCCURPC version
my $HMCCURPCPROC_VERSION = '5.0 212981850'; my $HMCCURPCPROC_VERSION = '5.0 213141800';
# Maximum number of events processed per call of Read() # Maximum number of events processed per call of Read()
my $HMCCURPCPROC_MAX_EVENTS = 100; my $HMCCURPCPROC_MAX_EVENTS = 100;

View File

@ -239,6 +239,7 @@ $HMCCU_CONFIG_VERSION = '5.0';
'(C#\.)?SET_TEMPERATURE$:+desired-temp', '(C#\.)?SET_TEMPERATURE$:+desired-temp',
'HEATING_CLIMATECONTROL_TRANSCEIVER' => 'HEATING_CLIMATECONTROL_TRANSCEIVER' =>
'(C#\.)?ACTUAL_TEMPERATURE$:+measured-temp;'. '(C#\.)?ACTUAL_TEMPERATURE$:+measured-temp;'.
'(C#\.)?HUMIDITY$:+humidity;'.
'(C#\.)?ACTUAL_HUMIDITY$:+humidity;'. '(C#\.)?ACTUAL_HUMIDITY$:+humidity;'.
'(C#\.)?SET_POINT_TEMPERATURE$:+desired-temp', '(C#\.)?SET_POINT_TEMPERATURE$:+desired-temp',
'CLIMATECONTROL_REGULATOR' => 'CLIMATECONTROL_REGULATOR' =>