1
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-05-07 22:29:19 +00:00

HMCCU: Update 4.4 Beta

git-svn-id: https://svn.fhem.de/fhem/trunk@24463 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2021-05-17 16:06:08 +00:00
parent a8a48134e2
commit e67bb25dec
7 changed files with 288 additions and 237 deletions

View File

@ -1,6 +1,8 @@
- bugfix: 88_HMCCU.pm: Release candidate 5
- bugfix: 88_HMCCU.pm: Release candidate 4
- bugfix: 88_HMCCU.pm: Release candidate 3 - bugfix: 88_HMCCU.pm: Release candidate 3
- bugfix: 88_HMCCU.pm: Release candidate 2 - bugfix: 88_HMCCU.pm: Release candidate 2
- bugfix: 88_HMCCU.pm: Fixed bug in set defaults command - bugfix: 88_HMCCU.pm: Fixed bug in set defaults command
- bugfix: 88_HMCCU.pm: Fixed state-/controldatapoint bug during start - bugfix: 88_HMCCU.pm: Fixed state/controldatapoint bug during FHEM start
- bugfix: 88_HMCCU.pm: Fixed some bugs. New command set readingFilter - bugfix: 88_HMCCU.pm: Fixed some bugs. New command set readingFilter
- bugfix: 88_HMCCU.pm: Fixed device detection bugs - bugfix: 88_HMCCU.pm: Fixed device detection bugs

View File

@ -4,7 +4,7 @@
# #
# $Id: 88_HMCCU.pm 18745 2019-02-26 17:33:23Z zap $ # $Id: 88_HMCCU.pm 18745 2019-02-26 17:33:23Z zap $
# #
# Version 4.4.066 # Version 4.4.068
# #
# Module for communication between FHEM and Homematic CCU2/3. # Module for communication between FHEM and Homematic CCU2/3.
# #
@ -58,7 +58,7 @@ my %HMCCU_CUST_CHN_DEFAULTS;
my %HMCCU_CUST_DEV_DEFAULTS; my %HMCCU_CUST_DEV_DEFAULTS;
# HMCCU version # HMCCU version
my $HMCCU_VERSION = '4.4.066'; my $HMCCU_VERSION = '4.4.068';
# Timeout for CCU requests (seconds) # Timeout for CCU requests (seconds)
my $HMCCU_TIMEOUT_REQUEST = 4; my $HMCCU_TIMEOUT_REQUEST = 4;
@ -97,6 +97,7 @@ my %HMCCU_RPC_SSL = (
# Default values for delayed initialization during FHEM startup # Default values for delayed initialization during FHEM startup
my $HMCCU_INIT_INTERVAL0 = 12; my $HMCCU_INIT_INTERVAL0 = 12;
my $HMCCU_CCU_PING_TIMEOUT = 1; my $HMCCU_CCU_PING_TIMEOUT = 1;
my $HMCCU_CCU_PING_SLEEP = 1;
my $HMCCU_CCU_BOOT_DELAY = 180; my $HMCCU_CCU_BOOT_DELAY = 180;
my $HMCCU_CCU_DELAYED_INIT = 59; my $HMCCU_CCU_DELAYED_INIT = 59;
my $HMCCU_CCU_RPC_OFFSET = 20; my $HMCCU_CCU_RPC_OFFSET = 20;
@ -148,7 +149,7 @@ my $HMCCU_EXT_ADDR = 'ZZZ0000000';
# FHEM standard functions # FHEM standard functions
sub HMCCU_Initialize ($); sub HMCCU_Initialize ($);
sub HMCCU_Define ($$); sub HMCCU_Define ($$$);
sub HMCCU_InitDevice ($); sub HMCCU_InitDevice ($);
sub HMCCU_Undef ($$); sub HMCCU_Undef ($$);
sub HMCCU_DelayedShutdown ($); sub HMCCU_DelayedShutdown ($);
@ -184,7 +185,7 @@ sub HMCCU_SetRPCState ($@);
sub HMCCU_FilterReading ($$$;$); sub HMCCU_FilterReading ($$$;$);
sub HMCCU_FormatReadingValue ($$$); sub HMCCU_FormatReadingValue ($$$);
sub HMCCU_GetReadingName ($$$$$$$;$); sub HMCCU_GetReadingName ($$$$$$$;$);
sub HMCCU_ScaleValue ($$$$$); sub HMCCU_ScaleValue ($$$$$;$);
sub HMCCU_StripNumber ($$;$); sub HMCCU_StripNumber ($$;$);
sub HMCCU_Substitute ($$$$$;$$); sub HMCCU_Substitute ($$$$$;$$);
sub HMCCU_SubstRule ($$$); sub HMCCU_SubstRule ($$$);
@ -251,6 +252,7 @@ sub HMCCU_ExecuteRoleCommand ($@);
sub HMCCU_ExecuteGetDeviceInfoCommand ($@); sub HMCCU_ExecuteGetDeviceInfoCommand ($@);
sub HMCCU_ExecuteGetParameterCommand ($@); sub HMCCU_ExecuteGetParameterCommand ($@);
sub HMCCU_ExecuteSetClearCommand ($@); sub HMCCU_ExecuteSetClearCommand ($@);
sub HMCCU_ExecuteSetControlCommand ($@);
sub HMCCU_ExecuteSetDatapointCommand ($@); sub HMCCU_ExecuteSetDatapointCommand ($@);
sub HMCCU_ExecuteSetParameterCommand ($@); sub HMCCU_ExecuteSetParameterCommand ($@);
sub HMCCU_DisplayGetParameterResult ($$$); sub HMCCU_DisplayGetParameterResult ($$$);
@ -347,9 +349,10 @@ sub HMCCU_ISO2UTF ($);
sub HMCCU_Max ($$); sub HMCCU_Max ($$);
sub HMCCU_MaxHashEntries ($$); sub HMCCU_MaxHashEntries ($$);
sub HMCCU_Min ($$); sub HMCCU_Min ($$);
sub HMCCU_MinMax ($$$);
sub HMCCU_RefToString ($); sub HMCCU_RefToString ($);
sub HMCCU_ResolveName ($$); sub HMCCU_ResolveName ($$);
sub HMCCU_TCPConnect ($$); sub HMCCU_TCPConnect ($$;$);
sub HMCCU_TCPPing ($$$); sub HMCCU_TCPPing ($$$);
sub HMCCU_UpdateReadings ($$;$); sub HMCCU_UpdateReadings ($$;$);
@ -390,7 +393,7 @@ sub HMCCU_Initialize ($)
# Define device # Define device
###################################################################### ######################################################################
sub HMCCU_Define ($$) sub HMCCU_Define ($$$)
{ {
my ($hash, $a, $h) = @_; my ($hash, $a, $h) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -1700,11 +1703,12 @@ sub HMCCU_Get ($@)
return $devTable; return $devTable;
} }
elsif ($opt eq 'deviceinfo') { elsif ($opt eq 'deviceinfo') {
my $device = shift @$a // return HMCCU_SetError ($hash, "Usage: get $name $opt {device}"); my $device = shift @$a // return HMCCU_SetError ($hash, "Usage: get $name $opt {device} [extended]");
my $extended = shift @$a;
my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($hash, $device, my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($hash, $device,
$HMCCU_FLAG_FULLADDR); $HMCCU_FLAG_FULLADDR);
return HMCCU_SetError ($hash, -1, $device) if (!($flags & $HMCCU_FLAG_ADDRESS)); return HMCCU_SetError ($hash, -1, $device) if (!($flags & $HMCCU_FLAG_ADDRESS));
return HMCCU_ExecuteGetDeviceInfoCommand ($hash, $hash, $add); return HMCCU_ExecuteGetDeviceInfoCommand ($hash, $hash, $add, defined($extended) ? 1 : 0);
} }
elsif ($opt eq 'rpcevents') { elsif ($opt eq 'rpcevents') {
$result = ''; $result = '';
@ -3296,6 +3300,11 @@ sub HMCCU_UpdateDevice ($$)
my $iface = $clHash->{ccuif}; my $iface = $clHash->{ccuif};
my ($da, $dc) = HMCCU_SplitChnAddr ($address); my ($da, $dc) = HMCCU_SplitChnAddr ($address);
# Update device information
if (exists($ioHash->{hmccu}{device}{$iface}{$da})) {
$clHash->{firmware} = $ioHash->{hmccu}{device}{$iface}{$da}{FIRMWARE} // '?';
}
# Update link receivers # Update link receivers
if (exists($ioHash->{hmccu}{snd}{$iface}{$da})) { if (exists($ioHash->{hmccu}{snd}{$iface}{$da})) {
delete $clHash->{receiver} if (exists($clHash->{receiver})); delete $clHash->{receiver} if (exists($clHash->{receiver}));
@ -3561,7 +3570,6 @@ sub HMCCU_GetDeviceRoles ($$$;$)
###################################################################### ######################################################################
# Get device configuration for all interfaces from CCU # Get device configuration for all interfaces from CCU
# Currently binary interfaces like CUxD are not supported
###################################################################### ######################################################################
sub HMCCU_GetDeviceConfig ($) sub HMCCU_GetDeviceConfig ($)
@ -4419,6 +4427,8 @@ sub HMCCU_UpdateParamsetReadings ($$$;$)
# Modify value: scale, format, substitute # Modify value: scale, format, substitute
$sv = HMCCU_ScaleValue ($clHash, $c, $p, $v, 0); $sv = HMCCU_ScaleValue ($clHash, $c, $p, $v, 0);
HMCCU_UpdateInternalValues ($clHash, $chKey, $ps, 'NVAL', $sv);
HMCCU_Trace ($clHash, 2, "$p: sv = $sv");
$fv = HMCCU_FormatReadingValue ($clHash, $sv, $p); $fv = HMCCU_FormatReadingValue ($clHash, $sv, $p);
$cv = HMCCU_Substitute ($fv, $clHash, 0, $c, $p, $chnType, $devDesc); $cv = HMCCU_Substitute ($fv, $clHash, 0, $c, $p, $chnType, $devDesc);
$cv = HMCCU_GetParamValueConversion ($ioHash, $devDesc, $ps, $p, $fv) $cv = HMCCU_GetParamValueConversion ($ioHash, $devDesc, $ps, $p, $fv)
@ -4944,10 +4954,11 @@ sub HMCCU_IsRPCStateBlocking ($)
{ {
my ($hash) = @_; my ($hash) = @_;
return ($hash->{RPCState} eq 'starting' || return (exists($hash->{RPCState}) && (
$hash->{RPCState} eq 'starting' ||
$hash->{RPCState} eq 'restarting' || $hash->{RPCState} eq 'restarting' ||
$hash->{RPCState} eq 'stopping' $hash->{RPCState} eq 'stopping'
) ? 1 : 0; )) ? 1 : 0;
} }
###################################################################### ######################################################################
@ -6348,7 +6359,7 @@ sub HMCCU_SetInitialAttributes ($$)
my ($ioHash, $clName) = @_; my ($ioHash, $clName) = @_;
my $ccudefAttributes = AttrVal ($ioHash->{NAME}, 'ccudef-attributes', 'room=Homematic'); my $ccudefAttributes = AttrVal ($ioHash->{NAME}, 'ccudef-attributes', 'room=Homematic');
foreach my $a (split(',', $ccudefAttributes)) { foreach my $a (split(';', $ccudefAttributes)) {
my ($an, $av) = split('=', $a); my ($an, $av) = split('=', $a);
CommandAttr (undef, "$clName $an $av") if (defined($av)); CommandAttr (undef, "$clName $an $av") if (defined($av));
} }
@ -6365,8 +6376,9 @@ sub HMCCU_SetDefaultAttributes ($;$)
my $ioHash = HMCCU_GetHash ($clHash); my $ioHash = HMCCU_GetHash ($clHash);
my $clName = $clHash->{NAME}; my $clName = $clHash->{NAME};
my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($clHash);
$parRef //= { mode => 'update', role => undef, roleChn => undef }; $parRef //= { mode => 'update', role => undef, roleChn => undef };
my $role = $parRef->{role} // HMCCU_GetChannelRole ($clHash, $parRef->{roleChn}); my $role = $parRef->{role} // HMCCU_GetChannelRole ($clHash, $parRef->{roleChn} // $cc);
if ($role ne '') { if ($role ne '') {
$clHash->{hmccu}{semDefaults} = 1; $clHash->{hmccu}{semDefaults} = 1;
@ -6674,11 +6686,12 @@ sub HMCCU_UpdateAdditionalCommands ($$;$$)
# Execute command related to role # Execute command related to role
# Parameters: # Parameters:
# $mode: 'set' or 'get' # $mode: 'set' or 'get'
# $command: The command
###################################################################### ######################################################################
sub HMCCU_ExecuteRoleCommand ($@) sub HMCCU_ExecuteRoleCommand ($@)
{ {
my ($ioHash, $clHash, $mode, $command, $cc, $a, $h) = @_; my ($ioHash, $clHash, $mode, $command, $a, $h) = @_;
my $name = $clHash->{NAME}; my $name = $clHash->{NAME};
my $rc; my $rc;
@ -6692,6 +6705,7 @@ sub HMCCU_ExecuteRoleCommand ($@)
my $channel = $clHash->{hmccu}{roleCmds}{$mode}{$command}{channel}; my $channel = $clHash->{hmccu}{roleCmds}{$mode}{$command}{channel};
if ("$channel" eq '?') { if ("$channel" eq '?') {
my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($clHash);
return HMCCU_SetError ($clHash, -12) if ($cc eq ''); return HMCCU_SetError ($clHash, -12) if ($cc eq '');
$channel = $cc; $channel = $cc;
} }
@ -6732,8 +6746,8 @@ sub HMCCU_ExecuteRoleCommand ($@)
# Delta value. Sign depends on sign of default value. Sign of specified value is ignored # Delta value. Sign depends on sign of default value. Sign of specified value is ignored
my $sign = $1 eq '+' ? 1 : -1; my $sign = $1 eq '+' ? 1 : -1;
return HMCCU_SetError ($clHash, "Current value of $channel.$cmd->{dpt} not available") return HMCCU_SetError ($clHash, "Current value of $channel.$cmd->{dpt} not available")
if (!defined($clHash->{hmccu}{dp}{"$channel.$cmd->{dpt}"}{$cmd->{ps}}{SVAL})); if (!defined($clHash->{hmccu}{dp}{"$channel.$cmd->{dpt}"}{$cmd->{ps}}{NVAL}));
$value = $clHash->{hmccu}{dp}{"$channel.$cmd->{dpt}"}{$cmd->{ps}}{SVAL}+abs(int($value))*$sign; $value = $clHash->{hmccu}{dp}{"$channel.$cmd->{dpt}"}{$cmd->{ps}}{NVAL}+abs(int($value))*$sign;
} }
if ($cmd->{unit} eq 's') { if ($cmd->{unit} eq 's') {
$value = HMCCU_GetTimeSpec ($value); $value = HMCCU_GetTimeSpec ($value);
@ -6750,10 +6764,13 @@ sub HMCCU_ExecuteRoleCommand ($@)
push @par, $vl; push @par, $vl;
} }
$value = HMCCU_Min ($value, HMCCU_ScaleValue ($clHash, $channel, $cmd->{dpt}, $cmd->{max}, 0)) # Align new value with min/max boundaries
if (defined($cmd->{max}) && $cmd->{max} ne ''); if (exists($cmd->{min}) && exists($cmd->{max})) {
$value = HMCCU_Max ($value, HMCCU_ScaleValue ($clHash, $channel, $cmd->{dpt}, $cmd->{min}, 0)) $value = HMCCU_MinMax ($value,
if (defined($cmd->{min}) && $cmd->{min} ne ''); HMCCU_ScaleValue ($clHash, $channel, $cmd->{dpt}, $cmd->{min}, 0),
HMCCU_ScaleValue ($clHash, $channel, $cmd->{dpt}, $cmd->{max}, 0)
);
}
if ($cmd->{ps} eq 'VALUES') { if ($cmd->{ps} eq 'VALUES') {
my $dno = sprintf ("%03d", $c); my $dno = sprintf ("%03d", $c);
@ -6847,18 +6864,36 @@ sub HMCCU_ExecuteSetClearCommand ($@)
return HMCCU_SetState ($clHash, "OK"); return HMCCU_SetState ($clHash, "OK");
} }
######################################################################
# Execute set control command
######################################################################
sub HMCCU_ExecuteSetControlCommand ($@)
{
my ($clHash, $a, $h) = @_;
my $value = shift @$a // return HMCCU_SetError ($clHash, "Usage: set $clHash->{NAME} control {value}");
my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($clHash);
my $stateVals = HMCCU_GetStateValues ($clHash, $cd, $cc);
my $rc = HMCCU_SetMultipleDatapoints ($clHash,
{ "001.$clHash->{ccuif}.$clHash->{ccuaddr}:$cc.$cd" => HMCCU_Substitute ($value, $stateVals, 1, undef, '') }
);
return HMCCU_SetError ($clHash, HMCCU_Min(0, $rc));
}
###################################################################### ######################################################################
# Execute set datapoint command # Execute set datapoint command
###################################################################### ######################################################################
sub HMCCU_ExecuteSetDatapointCommand ($@) sub HMCCU_ExecuteSetDatapointCommand ($@)
{ {
my ($clHash, $a, $h, $cc, $cd) = @_; my ($clHash, $a, $h) = @_;
my $usage = "Usage: set $clHash->{NAME} datapoint [{channel-number}.]{datapoint} {value} [...]"; my $usage = "Usage: set $clHash->{NAME} datapoint [{channel-number}.]{datapoint} {value} [...]";
my %dpval; my %dpval;
my $i = 0; my $i = 0;
my ($devAddr, $chnNo) = HMCCU_SplitChnAddr ($clHash->{ccuaddr}); my ($devAddr, $chnNo) = HMCCU_SplitChnAddr ($clHash->{ccuaddr});
my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($clHash);
my $stVals = HMCCU_GetStateValues ($clHash, $cd, $cc); my $stVals = HMCCU_GetStateValues ($clHash, $cd, $cc);
push (@$a, %${h}) if (defined($h)); push (@$a, %${h}) if (defined($h));
@ -6994,9 +7029,10 @@ sub HMCCU_ExecuteSetParameterCommand ($@)
sub HMCCU_ExecuteToggleCommand ($@) sub HMCCU_ExecuteToggleCommand ($@)
{ {
my ($clHash, $cc, $cd) = @_; my ($clHash) = @_;
# Get state values related to control channel and datapoint # Get state values related to control channel and datapoint
my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($clHash);
my $stateVals = HMCCU_GetStateValues ($clHash, $cd, $cc); my $stateVals = HMCCU_GetStateValues ($clHash, $cd, $cc);
my %stateCmds = split (/[:,]/, $stateVals); my %stateCmds = split (/[:,]/, $stateVals);
my @states = keys %stateCmds; my @states = keys %stateCmds;
@ -7034,16 +7070,17 @@ sub HMCCU_ExecuteToggleCommand ($@)
sub HMCCU_ExecuteGetDeviceInfoCommand ($@) sub HMCCU_ExecuteGetDeviceInfoCommand ($@)
{ {
my ($ioHash, $clHash, $address, $sc, $sd, $cc, $cd) = @_; my ($ioHash, $clHash, $address, $extended) = @_;
$sc = '?' if (!defined($sc) || $sc eq ''); $extended //= 0;
$sd = '?' if (!defined($sd) || $sd eq '');
$cc = '?' if (!defined($cc) || $cc eq '');
$cd = '?' if (!defined($cd) || $cd eq '');
my $iface = HMCCU_GetDeviceInterface ($ioHash, $address); my $iface = HMCCU_GetDeviceInterface ($ioHash, $address);
my $result = HMCCU_GetDeviceInfo ($clHash, $address); my $result = HMCCU_GetDeviceInfo ($clHash, $address);
return HMCCU_SetError ($clHash, -2) if ($result eq ''); return HMCCU_SetError ($clHash, -2) if ($result eq '');
my $devInfo = '<html><b>Device channels and datapoints</b><br/><br/>';
my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($clHash);
my $devInfo = '<html><b>Device channels and datapoints</b><br/><br/><pre>';
$devInfo .= '</pre>';
$devInfo .= HMCCU_FormatDeviceInfo ($result); $devInfo .= HMCCU_FormatDeviceInfo ($result);
my $detect = HMCCU_DetectDevice ($ioHash, $address, $iface); my $detect = HMCCU_DetectDevice ($ioHash, $address, $iface);
if (defined($detect)) { if (defined($detect)) {
@ -7069,17 +7106,24 @@ sub HMCCU_ExecuteGetDeviceInfoCommand ($@)
$devInfo .= $detect->{defMod} ne '' ? $devInfo .= $detect->{defMod} ne '' ?
"<br/>Recommended module for device definition: $detect->{defMod}<br/>" : "<br/>Recommended module for device definition: $detect->{defMod}<br/>" :
"<br/>Failed to detect device settings. Device must be configured manually.<br/>"; "<br/>Failed to detect device settings. Device must be configured manually.<br/>";
if ($extended) {
$devInfo .= "<br/>Detection level: $detect->{level}<br/>".
"<br/>Detected default state datapoint: $detect->{defSCh}.$detect->{defSDP}<br/>".
"<br/>Detected default control datapoint: $detect->{defCCh}.$detect->{defCDP}<br/>".
"<br/>Unique state roles: $detect->{uniqueStateRoleCount}<br/>".
"<br/>Unique state roles: $detect->{uniqueControlRoleCount}<br/>";
} }
$devInfo .= "<br/>Current state datapoint = $sc.$sd<br/>" if ($sc ne '?'); }
$devInfo .= "<br/>Current control datapoint = $cc.$cd<br/>" if ($cc ne '?'); $devInfo .= "<br/>Current state datapoint = $sc.$sd<br/>";
$devInfo .= '<br/><b>Device description</b><br/><br/>'; $devInfo .= "<br/>Current control datapoint = $cc.$cd<br/>";
$devInfo .= '<br/><b>Device description</b><br/><br/><pre>';
$result = HMCCU_DeviceDescToStr ($ioHash, $clHash->{TYPE} eq 'HMCCU' ? $address : $clHash); $result = HMCCU_DeviceDescToStr ($ioHash, $clHash->{TYPE} eq 'HMCCU' ? $address : $clHash);
$devInfo .= '</pre>';
$devInfo .= defined($result) ? $result : "Can't get device description<br/>"; $devInfo .= defined($result) ? $result : "Can't get device description<br/>";
if ($clHash->{TYPE} ne 'HMCCU') { if ($clHash->{TYPE} ne 'HMCCU') {
$devInfo .= '<br/>Defaults<br/><br/>'; $devInfo .= '<br/>Defaults<br/><br/>';
$devInfo .= HMCCU_GetDefaults ($clHash); $devInfo .= HMCCU_GetDefaults ($clHash);
} }
$devInfo .= '</html>';
return $devInfo; return $devInfo;
} }
@ -7671,6 +7715,7 @@ sub HMCCU_DetectDevice ($$$)
# Build device information to be returned # Build device information to be returned
my %di = ( my %di = (
stateRoleCount => $stateRoleCnt, controlRoleCount => $ctrlRoleCnt, stateRoleCount => $stateRoleCnt, controlRoleCount => $ctrlRoleCnt,
uniqueStateRoleCount => $cntUniqStateRoles, uniqueControlRoleCount => $cntUniqCtrlRoles,
defSCh => -1, defCCh => -1, defSDP => '', defCDP => '', defSCh => -1, defCCh => -1, defSDP => '', defCDP => '',
level => 0 level => 0
); );
@ -8311,12 +8356,31 @@ sub HMCCU_SetMultipleDatapoints ($$) {
# an error original value is returned. # an error original value is returned.
###################################################################### ######################################################################
sub HMCCU_ScaleValue ($$$$$) sub HMCCU_ScaleValue ($$$$$;$)
{ {
my ($hash, $chnno, $dpt, $value, $mode) = @_; my ($hash, $chnno, $dpt, $value, $mode, $paramSet) = @_;
$chnno //= '';
$paramSet //= 'VALUES';
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $ioHash = HMCCU_GetHash ($hash); my $ioHash = HMCCU_GetHash ($hash);
# Get parameter definition and min/max values
my $min;
my $max;
my $unit;
my $ccuaddr = $hash->{ccuaddr};
$ccuaddr .= ':'.$chnno if ($hash->{TYPE} eq 'HMCCUDEV' && $chnno ne '');
my $paramDef = HMCCU_GetParamDef ($ioHash, $ccuaddr, 'VALUES', $dpt);
if (defined($paramDef)) {
$min = $paramDef->{MIN} if (defined($paramDef->{MIN}) && $paramDef->{MIN} ne '');
$max = $paramDef->{MAX} if (defined($paramDef->{MAX}) && $paramDef->{MAX} ne '');
$unit = $paramDef->{UNIT};
}
else {
HMCCU_Trace ($hash, 2, "Can't get parameter definion for addr=$hash->{ccuaddr} chn=$chnno");
}
# Default values can be overriden by attribute
my $ccuscaleval = AttrVal ($name, 'ccuscaleval', ''); my $ccuscaleval = AttrVal ($name, 'ccuscaleval', '');
HMCCU_Trace ($hash, 2, "chnno=$chnno, dpt=$dpt, value=$value, mode=$mode"); HMCCU_Trace ($hash, 2, "chnno=$chnno, dpt=$dpt, value=$value, mode=$mode");
@ -8347,14 +8411,12 @@ sub HMCCU_ScaleValue ($$$$$)
if ($n == 2) { if ($n == 2) {
$f = ($a[1] == 0.0) ? 1.0 : $a[1]; $f = ($a[1] == 0.0) ? 1.0 : $a[1];
return ($mode == 0) ? $value/$f : $value*$f; $value = ($mode == 0) ? $value/$f : $value*$f;
} }
else { elsif ($a[1] <= $a[2] && $a[3] <= $a[4] && (
# Do not scale if value out of range or interval wrong ($mode == 0 && $value >= $a[1] && $value <= $a[2]) ||
return $value if ($a[1] > $a[2] || $a[3] > $a[4]); ($mode == 1 && $value >= $a[3] && $value <= $a[4])
return $value if ($mode == 0 && ($value < $a[1] || $value > $a[2])); )) {
return $value if ($mode == 1 && ($value < $a[3] || $value > $a[4]));
# Reverse value # Reverse value
if ($rev) { if ($rev) {
my $dr = ($mode == 0) ? $a[1]+$a[2] : $a[3]+$a[4]; my $dr = ($mode == 0) ? $a[1]+$a[2] : $a[3]+$a[4];
@ -8363,46 +8425,54 @@ sub HMCCU_ScaleValue ($$$$$)
my $d1 = $a[2]-$a[1]; my $d1 = $a[2]-$a[1];
my $d2 = $a[4]-$a[3]; my $d2 = $a[4]-$a[3];
return $value if ($d1 == 0.0 || $d2 == 0.0); if ($d1 != 0.0 && $d2 != 0.0) {
$f = $d1/$d2; $f = $d1/$d2;
return ($mode == 0) ? $value/$f+$a[3] : ($value-$a[3])*$f; $value = ($mode == 0) ? $value/$f+$a[3] : ($value-$a[3])*$f;
} }
} }
} }
if ($dpt eq 'LEVEL') { # Align value with min/max boundaries for set mode
my $rv = ($mode == 0) ? HMCCU_Min($value,1.0)*100.0 : HMCCU_Min($value,100.0)/100.0; if ($mode == 1 && defined($min) && defined($max)) {
HMCCU_Trace ($hash, 2, "LEVEL: $rv"); $value = HMCCU_MinMax ($value, $min, $max);
return $rv;
# return ($mode == 0) ? HMCCU_Min($value,1.0)*100.0 : HMCCU_Min($value,100.0)/100.0;
} }
elsif ($dpt =~ /^RSSI_/) {
return abs ($value) == 65535 || $value == 1 ? 'N/A' : ($value > 0 ? $value-256 : $value); HMCCU_Trace ($hash, 2, "Attribute scaled value of $dpt = $value");
return $value;
}
# if ($dpt eq 'LEVEL') {
# my $rv = ($mode == 0) ? HMCCU_Min($value,1.0)*100.0 : HMCCU_Min($value,100.0)/100.0;
# HMCCU_Trace ($hash, 2, "LEVEL: $rv");
# return $rv;
## return ($mode == 0) ? HMCCU_Min($value,1.0)*100.0 : HMCCU_Min($value,100.0)/100.0;
# }
if ($dpt =~ /^RSSI_/) {
# Subtract 256 from Rega value (Rega bug)
$value = abs ($value) == 65535 || $value == 0 ? 'N/A' : ($value > 0 ? $value-256 : $value);
} }
elsif ($dpt =~ /^(P[0-9]_)?ENDTIME/) { elsif ($dpt =~ /^(P[0-9]_)?ENDTIME/) {
if ($mode == 0) { if ($mode == 0) {
my $hh = sprintf ("%02d", int($value/60)); my $hh = sprintf ("%02d", int($value/60));
my $mm = sprintf ("%02d", $value%60); my $mm = sprintf ("%02d", $value%60);
return "$hh:$mm"; $value = "$hh:$mm";
} }
else { else {
my ($hh, $mm) = split (':', $value); my ($hh, $mm) = split (':', $value);
$mm = 0 if (!defined($mm)); $mm //= 0;
return $hh*60+$mm; $value = $hh*60+$mm;
} }
} }
# my $address = $hash->{TYPE} eq 'HMCCUDEV' ? $hash->{ccuaddr}.":$chnno" : $hash->{ccuaddr}; elsif (defined($unit) && $unit =~ /^([0-9]+)%$/) {
# my $devDesc = HMCCU_GetDeviceDesc ($ioHash, $address, $hash->{ccuif}); my $f = $1;
# if (defined($devDesc)) { $min //= 0;
# my $devModel = HMCCU_GetDeviceModel ($ioHash, $devDesc->{_model}, $devDesc->{_fw_ver}, $chnno); $max //= 1.0;
# if (defined($devModel)) { $value = ($mode == 0) ? HMCCU_MinMax ($value, $min, $max)*$f :
# if ($devDesc->{TYPE} eq 'BLIND' || $devDesc->{TYPE} eq 'DIMMER' && $dpt eq 'LEVEL') { HMCCU_MinMax($value, $min*$f, $max*$f)/$f;
# my $f = $devModel->{VALUES}{LEVEL}{MAX}-$devModel->{VALUES}{LEVEL}{MIN}; }
# $f = 1.0 if (!defined($f) || $f == 0.0);
# return ($mode == 0) ? $value/$f : $value*$f; HMCCU_Trace ($hash, 2, "Auto scaled value of $dpt = $value");
# }
# }
# }
return $value; return $value;
} }
@ -8951,7 +9021,8 @@ sub HMCCU_GetTimeSpec ($)
} }
###################################################################### ######################################################################
# Get minimum of 2 values # Get minimum or maximum of 2 values
# Align value with boundaries
###################################################################### ######################################################################
sub HMCCU_Min ($$) sub HMCCU_Min ($$)
@ -8961,10 +9032,6 @@ sub HMCCU_Min ($$)
return $a < $b ? $a : $b; return $a < $b ? $a : $b;
} }
######################################################################
# Get maximum of 2 values
######################################################################
sub HMCCU_Max ($$) sub HMCCU_Max ($$)
{ {
my ($a, $b) = @_; my ($a, $b) = @_;
@ -8972,6 +9039,15 @@ sub HMCCU_Max ($$)
return $a > $b ? $a : $b; return $a > $b ? $a : $b;
} }
sub HMCCU_MinMax ($$$)
{
my ($v, $min, $max) = @_;
$min = $v if (!defined($min) || $min eq '');
$max = $min if (!defined($max) || $max eq '');
return HMCCU_Max (HMCCU_Min ($v, $max), $min);
}
###################################################################### ######################################################################
# Build ReGa or RPC client URL # Build ReGa or RPC client URL
# Parameter backend specifies type of URL, 'rega' or name or port of # Parameter backend specifies type of URL, 'rega' or name or port of
@ -9482,8 +9558,8 @@ sub HMCCU_TCPPing ($$$)
my $t = time (); my $t = time ();
while (time() < $t+$timeout) { while (time() < $t+$timeout) {
return 1 if (HMCCU_TCPConnect ($addr, $port) ne ''); return 1 if (HMCCU_TCPConnect ($addr, $port, 1) ne '');
sleep (20); sleep ($HMCCU_CCU_PING_SLEEP);
} }
return 0; return 0;
@ -9498,11 +9574,11 @@ sub HMCCU_TCPPing ($$$)
# Return empty string on error or local IP address on success. # Return empty string on error or local IP address on success.
###################################################################### ######################################################################
sub HMCCU_TCPConnect ($$) sub HMCCU_TCPConnect ($$;$)
{ {
my ($addr, $port) = @_; my ($addr, $port, $timeout) = @_;
my $socket = IO::Socket::INET->new (PeerAddr => $addr, PeerPort => $port); my $socket = IO::Socket::INET->new (PeerAddr => $addr, PeerPort => $port, Timeout => $timeout);
if ($socket) { if ($socket) {
my $ipaddr = $socket->sockhost (); my $ipaddr = $socket->sockhost ();
close ($socket); close ($socket);
@ -9750,7 +9826,7 @@ sub HMCCU_MaxHashEntries ($$)
<li><b>get &lt;name&gt; defaults</b><br/> <li><b>get &lt;name&gt; defaults</b><br/>
List device types and channels with default attributes available. List device types and channels with default attributes available.
</li><br/> </li><br/>
<li><b>get &lt;name&gt; deviceinfo &lt;device-name-or-address&gt;</b><br/> <li><b>get &lt;name&gt; deviceinfo &lt;device-name-or-address&gt; [extended]</b><br/>
List device channels, datapoints and the device description. List device channels, datapoints and the device description.
</li><br/> </li><br/>
<li><b>get &lt;name&gt; dutycycle</b><br/> <li><b>get &lt;name&gt; dutycycle</b><br/>

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.038 # Version 4.4.039
# #
# (c) 2021 zap (zap01 <at> t-online <dot> de) # (c) 2021 zap (zap01 <at> t-online <dot> de)
# #
@ -281,42 +281,39 @@ sub HMCCUCHN_Set ($@)
return ($opt eq '?' ? undef : 'Cannot perform set commands. CCU busy') return ($opt eq '?' ? undef : 'Cannot perform set commands. CCU busy')
if (HMCCU_IsRPCStateBlocking ($ioHash)); if (HMCCU_IsRPCStateBlocking ($ioHash));
# Get state and control datapoints # Build set command syntax
my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($hash); my $syntax = 'clear defaults:reset,update';
# Additional commands, including state commands # Command readingFilter depends on readable datapoints
my $cmdList = $hash->{hmccu}{cmdlist}{set} // ''; my ($add, $chn) = split(":", $hash->{ccuaddr});
my @dpRList = ();
my $dpRCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, $chn, 5, \@dpRList);
$syntax .= ' readingFilter:multiple-strict,'.join(',', @dpRList) if ($dpRCount > 0);
# Some commands require a control datapoint # Commands only available in read/write mode
if ($opt =~ /^(control|toggle)$/) { if ($hash->{readonly} ne 'yes') {
return HMCCU_SetError ($hash, -14) if ($cd eq ''); $syntax .= ' config';
return HMCCU_SetError ($hash, -8, $cd) my $dpWCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, $chn, 2);
if (!HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $hash->{ccuaddr}, $cd, 2)); $syntax .= ' datapoint' if ($dpWCount > 0);
my $addCmds = $hash->{hmccu}{cmdlist}{set} // '';
$syntax .= " $addCmds" if ($addCmds ne '');
} }
my $result = '';
my $rc;
# Log commands # Log commands
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 ($lcopt eq 'control') { if ($lcopt eq 'control') {
my $value = shift @$a // return HMCCU_SetError ($hash, "Usage: set $name control {value}"); return HMCCU_ExecuteSetControlCommand ($hash, $a, $h);
my $stateVals = HMCCU_GetStateValues ($hash, $cd, $cc);
$rc = HMCCU_SetMultipleDatapoints ($hash,
{ "001.$hash->{ccuif}.$hash->{ccuaddr}.$cd" => HMCCU_Substitute ($value, $stateVals, 1, undef, '') }
);
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
} }
elsif ($lcopt eq 'datapoint') { elsif ($lcopt eq 'datapoint') {
return HMCCU_ExecuteSetDatapointCommand ($hash, $a, $h, $cc, $cd); return HMCCU_ExecuteSetDatapointCommand ($hash, $a, $h);
} }
elsif ($lcopt eq 'toggle') { elsif ($lcopt eq 'toggle') {
return HMCCU_ExecuteToggleCommand ($hash, $cc, $cd); return HMCCU_ExecuteToggleCommand ($hash);
} }
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, $a, $h);
} }
elsif ($opt eq 'clear') { elsif ($opt eq 'clear') {
return HMCCU_ExecuteSetClearCommand ($hash, $a); return HMCCU_ExecuteSetClearCommand ($hash, $a);
@ -332,27 +329,13 @@ sub HMCCUCHN_Set ($@)
} }
elsif ($lcopt eq 'defaults') { elsif ($lcopt eq 'defaults') {
my $mode = shift @$a // 'update'; my $mode = shift @$a // 'update';
$rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, roleChn => $cc }); my $rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, roleChn => undef });
$rc = HMCCU_SetDefaults ($hash) if (!$rc); $rc = HMCCU_SetDefaults ($hash) if (!$rc);
HMCCU_RefreshReadings ($hash) if ($rc); HMCCU_RefreshReadings ($hash) if ($rc);
return HMCCU_SetError ($hash, $rc == 0 ? "No default attributes found" : "OK"); return HMCCU_SetError ($hash, $rc == 0 ? "No default attributes found" : "OK");
} }
else { else {
my $retmsg = "clear defaults:reset,update"; return "Unknown argument $opt choose one of $syntax";
my ($a, $c) = split(":", $hash->{ccuaddr});
my @dpRList = ();
my $dpRCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, $c, 5, \@dpRList);
$retmsg .= ' readingFilter:multiple-strict,'.join(',', @dpRList) if ($dpRCount > 0);
if ($hash->{readonly} ne 'yes') {
$retmsg .= ' config';
my $dpWCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, $c, 2);
$retmsg .= ' datapoint' if ($dpWCount > 0);
$retmsg .= " $cmdList" if ($cmdList ne '');
}
# return AttrTemplate_Set ($hash, $retmsg, $name, $opt, @$a);
return $retmsg;
} }
} }
@ -368,10 +351,7 @@ sub HMCCUCHN_Get ($@)
my $lcopt = 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}) || AttrVal ($name, "disable", 0) == 1);
my $disable = AttrVal ($name, "disable", 0);
return undef if ($disable == 1);
my $ioHash = $hash->{IODev}; my $ioHash = $hash->{IODev};
my $ioName = $ioHash->{NAME}; my $ioName = $ioHash->{NAME};
@ -383,13 +363,19 @@ 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_GetSCDatapoints ($hash);
# Additional commands, including state commands # Build set command syntax
my $cmdList = $hash->{hmccu}{cmdlist}{get} // ''; my $syntax = 'update:noArg config:noArg paramsetDesc:noArg deviceInfo:noArg values:noArg';
my $result = ''; # Command datapoint depends on readable datapoints
my $rc; my ($add, $chn) = split(":", $hash->{ccuaddr});
my @dpRList;
my $dpRCount = HMCCU_GetValidDatapoints ($hash, $ccutype, $chn, 1, \@dpRList);
$syntax .= ' datapoint:'.join(",", @dpRList) if ($dpRCount > 0);
# Additional device specific commands
my $addCmds = $hash->{hmccu}{cmdlist}{get} // '';
$syntax .= " $addCmds" if ($addCmds ne '');
# Log commands # Log commands
HMCCU_Log ($hash, 3, "get $name $opt ".join (' ', @$a)) HMCCU_Log ($hash, 3, "get $name $opt ".join (' ', @$a))
@ -401,37 +387,30 @@ sub HMCCUCHN_Get ($@)
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); 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;
} }
elsif ($lcopt eq 'deviceinfo') { elsif ($lcopt eq 'deviceinfo') {
my $extended = shift @$a;
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, defined($extended) ? 1 : 0);
} }
elsif ($lcopt =~ /^(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, $lcopt, \@addList); my $result = 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($result));
return HMCCU_DisplayGetParameterResult ($ioHash, $hash, $resp); return HMCCU_DisplayGetParameterResult ($ioHash, $hash, $result);
} }
elsif ($lcopt eq 'paramsetdesc') { elsif ($lcopt eq 'paramsetdesc') {
$result = HMCCU_ParamsetDescToStr ($ioHash, $hash); my $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, $a, $h);
} }
else { else {
my $retmsg = "HMCCUCHN: Unknown argument $opt, choose one of"; return "Unknown argument $opt choose one of $syntax";
$retmsg .= ' update:noArg deviceInfo:noArg config:noArg paramsetDesc:noArg values:noArg';
my ($a, $c) = split(":", $hash->{ccuaddr});
my @dpList;
my $dpCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, $c, 1, \@dpList);
$retmsg .= ' datapoint:'.join(",",@dpList) if ($dpCount > 0);
$retmsg .= " $cmdList" if ($cmdList ne '');
return $retmsg;
} }
} }
@ -450,7 +429,7 @@ sub HMCCUCHN_Get ($@)
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 ccuConfig' 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>
<b>Define</b><br/><br/> <b>Define</b><br/><br/>
<ul> <ul>
@ -569,9 +548,9 @@ sub HMCCUCHN_Get ($@)
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 between states 'open', 'half' and 'close'<br/>
<code> <code>
attr myswitch statevals up:100,down:0<br/> attr myswitch statevals open:100,half:50,close:0<br/>
set myswitch toggle set myswitch toggle
</code> </code>
</li><br/> </li><br/>
@ -617,7 +596,7 @@ sub HMCCUCHN_Get ($@)
This command has been removed in version 4.4. The default attributes are included in the This command has been removed in version 4.4. The default attributes are included in the
output of command 'get deviceInfo'. 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 ['extended']</b><br/>
Display information about device type 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>

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.046 # Version 4.4.047
# #
# (c) 2021 zap (zap01 <at> t-online <dot> de) # (c) 2021 zap (zap01 <at> t-online <dot> de)
# #
@ -376,44 +376,38 @@ sub HMCCUDEV_Set ($@)
return ($opt eq '?' ? undef : 'Cannot perform set commands. CCU busy') return ($opt eq '?' ? undef : 'Cannot perform set commands. CCU busy')
if (HMCCU_IsRPCStateBlocking ($ioHash)); if (HMCCU_IsRPCStateBlocking ($ioHash));
# Get state and control datapoints # Build set command syntax
my ($sc, $sd, $cc, $cd) = HMCCU_GetSCDatapoints ($hash); my $syntax = 'clear defaults:reset,update';
# Get additional commands # Command readingFilter depends on readable datapoints
my $cmdList = $hash->{hmccu}{cmdlist}{set} // ''; my @dpRList = ();
my $dpRCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, -1, 5, \@dpRList);
$syntax .= ' readingFilter:multiple-strict,'.join(',', @dpRList) if ($dpRCount > 0);
# Some commands require a control channel and datapoint # Commands only available in read/write mode
if ($lcopt =~ /^(control|toggle)$/) { if ($hash->{readonly} ne 'yes') {
return HMCCU_SetError ($hash, -14) if ($cd eq ''); $syntax .= ' config';
return HMCCU_SetError ($hash, -12) if ($cc eq ''); my $dpWCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, -1, 2);
return HMCCU_SetError ($hash, -8, $cd) $syntax .= ' datapoint' if ($dpWCount > 0);
if (!HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $cc, $cd, 2)); my $addCmds = $hash->{hmccu}{cmdlist}{set} // '';
return HMCCU_SetError ($hash, -7) if ($cc >= $hash->{hmccu}{channels}); $syntax .= " $addCmds" if ($addCmds ne '');
} }
my $result = '';
my $rc;
# Log commands # Log commands
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 ($lcopt eq 'control') { if ($lcopt eq 'control') {
my $value = shift @$a // return HMCCU_SetError ($hash, "Usage: set $name control {value}"); return HMCCU_ExecuteSetControlCommand ($hash, $a, $h);
my $stateVals = HMCCU_GetStateValues ($hash, $cd, $cc);
$rc = HMCCU_SetMultipleDatapoints ($hash,
{ "001.$hash->{ccuif}.$hash->{ccuaddr}:$cc.$cd" => HMCCU_Substitute ($value, $stateVals, 1, undef, '') }
);
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
} }
elsif ($lcopt eq 'datapoint') { elsif ($lcopt eq 'datapoint') {
return HMCCU_ExecuteSetDatapointCommand ($hash, $a, $h, $cc, $cd); return HMCCU_ExecuteSetDatapointCommand ($hash, $a, $h);
} }
elsif ($lcopt eq 'toggle') { elsif ($lcopt eq 'toggle') {
return HMCCU_ExecuteToggleCommand ($hash, $cc, $cd); return HMCCU_ExecuteToggleCommand ($hash);
} }
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, $a, $h);
} }
elsif ($lcopt eq 'clear') { elsif ($lcopt eq 'clear') {
return HMCCU_ExecuteSetClearCommand ($hash, $a); return HMCCU_ExecuteSetClearCommand ($hash, $a);
@ -428,26 +422,13 @@ sub HMCCUDEV_Set ($@)
} }
elsif ($lcopt eq 'defaults') { elsif ($lcopt eq 'defaults') {
my $mode = shift @$a // 'update'; my $mode = shift @$a // 'update';
$rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, roleChn => $cc }); my $rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, roleChn => undef });
$rc = HMCCU_SetDefaults ($hash) if (!$rc); $rc = HMCCU_SetDefaults ($hash) if (!$rc);
HMCCU_RefreshReadings ($hash) if ($rc); HMCCU_RefreshReadings ($hash) if ($rc);
return HMCCU_SetError ($hash, $rc == 0 ? 'No default attributes found' : 'OK'); return HMCCU_SetError ($hash, $rc == 0 ? 'No default attributes found' : 'OK');
} }
else { else {
my $retmsg = 'clear defaults:reset,update'; return "Unknown argument $opt choose one of $syntax";
my @dpRList = ();
my $dpRCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, -1, 5, \@dpRList);
$retmsg .= ' readingFilter:multiple-strict,'.join(',', @dpRList) if ($dpRCount > 0);
if ($hash->{readonly} ne 'yes') {
$retmsg .= ' config';
my $dpWCount = HMCCU_GetValidDatapoints ($hash, $hash->{ccutype}, -1, 2);
$retmsg .= ' datapoint' if ($dpWCount > 0);
$retmsg .= " $cmdList" if ($cmdList ne '');
}
# return AttrTemplate_Set ($hash, $retmsg, $name, $opt, @$a);
return $retmsg;
} }
} }
@ -478,13 +459,18 @@ 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_GetSCDatapoints ($hash);
# Get additional commands # Build set command syntax
my $cmdList = $hash->{hmccu}{cmdlist}{get} // ''; my $syntax = 'update:noArg config:noArg paramsetDesc:noArg deviceInfo:noArg values:noArg';
my $result = ''; # Command datapoint depends on readable datapoints
my $rc; my @dpRList;
my $dpRCount = HMCCU_GetValidDatapoints ($hash, $ccutype, -1, 1, \@dpRList);
$syntax .= ' datapoint:'.join(",", @dpRList) if ($dpRCount > 0);
# Additional device specific commands
my $addCmds = $hash->{hmccu}{cmdlist}{get} // '';
$syntax .= " $addCmds" if ($addCmds ne '');
# Log commands # Log commands
HMCCU_Log ($hash, 3, "get $name $opt ".join (' ', @$a)) HMCCU_Log ($hash, 3, "get $name $opt ".join (' ', @$a))
@ -498,6 +484,7 @@ sub HMCCUDEV_Get ($@)
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);
return HMCCU_SetError ($hash, -11) if ($sc eq ''); return HMCCU_SetError ($hash, -11) if ($sc eq '');
$objname = $sc.'.'.$objname; $objname = $sc.'.'.$objname;
} }
@ -506,14 +493,14 @@ sub HMCCUDEV_Get ($@)
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, undef, $objname, 1)); if (!HMCCU_IsValidDatapoint ($hash, $ccutype, undef, $objname, 1));
$objname = $ccuif.'.'.$ccuaddr.':'.$objname; $objname = $ccuif.'.'.$ccuaddr.':'.$objname;
($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);
HMCCU_SetState ($hash, "OK") if (exists ($hash->{STATE}) && $hash->{STATE} eq "Error");
return $result; return $result;
} }
elsif ($lcopt eq 'deviceinfo') { elsif ($lcopt eq 'deviceinfo') {
return HMCCU_ExecuteGetDeviceInfoCommand ($ioHash, $hash, $ccuaddr, $sc, $sd, $cc, $cd); my $extended = shift @$a;
return HMCCU_ExecuteGetDeviceInfoCommand ($ioHash, $hash, $ccuaddr, defined($extended) ? 1 : 0);
} }
elsif ($lcopt =~ /^(config|values|update)$/) { elsif ($lcopt =~ /^(config|values|update)$/) {
my @addList = ($ccuaddr); my @addList = ($ccuaddr);
@ -522,26 +509,19 @@ sub HMCCUDEV_Get ($@)
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, $lcopt, \@addList); my $result = 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($result));
return HMCCU_DisplayGetParameterResult ($ioHash, $hash, $resp); return HMCCU_DisplayGetParameterResult ($ioHash, $hash, $result);
} }
elsif ($lcopt eq 'paramsetdesc') { elsif ($lcopt eq 'paramsetdesc') {
$result = HMCCU_ParamsetDescToStr ($ioHash, $hash); my $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, $a, $h);
} }
else { else {
my $retmsg = "HMCCUDEV: Unknown argument $opt, choose one of"; return "Unknown argument $opt choose one of $syntax";
$retmsg .= ' update:noArg config:noArg paramsetDesc:noArg deviceInfo:noArg values:noArg';
my @dpList;
my $dpCount = HMCCU_GetValidDatapoints ($hash, $ccutype, -1, 1, \@dpList);
$retmsg .= ' datapoint:'.join(",", @dpList) if ($dpCount > 0);
$retmsg .= " $cmdList" if ($cmdList ne '');
return $retmsg;
} }
} }
@ -723,7 +703,7 @@ sub HMCCUDEV_Get ($@)
<li><b>get &lt;name&gt; defaults</b><br/> <li><b>get &lt;name&gt; defaults</b><br/>
<a href="#HMCCUCHNget">see HMCCUCHN</a> <a href="#HMCCUCHNget">see HMCCUCHN</a>
</li><br/> </li><br/>
<li><b>get &lt;name&gt; deviceinfo</b><br/> <li><b>get &lt;name&gt; deviceinfo ['extended']</b><br/>
Display information about device and channels:<br/> Display information about device 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>

View File

@ -4,11 +4,11 @@
# #
# $Id: 88_HMCCURPCPROC.pm 18745 2019-02-26 17:33:23Z zap $ # $Id: 88_HMCCURPCPROC.pm 18745 2019-02-26 17:33:23Z zap $
# #
# Version 4.4.013 # Version 4.4.014
# #
# Subprocess based RPC Server module for HMCCU. # Subprocess based RPC Server module for HMCCU.
# #
# (c) 2020 by zap (zap01 <at> t-online <dot> de) # (c) 2021 by zap (zap01 <at> t-online <dot> de)
# #
############################################################################## ##############################################################################
# #
@ -39,7 +39,7 @@ require "$attr{global}{modpath}/FHEM/88_HMCCU.pm";
###################################################################### ######################################################################
# HMCCURPC version # HMCCURPC version
my $HMCCURPCPROC_VERSION = '4.4.013'; my $HMCCURPCPROC_VERSION = '4.4.014';
# 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;
@ -266,14 +266,15 @@ sub HMCCURPCPROC_Define ($$)
my $rpcip = ''; my $rpcip = '';
my $iface; my $iface;
my $usage = 'Usage: define $name HMCCURPCPROC { CCUHost | iodev={device} } { RPCPort | RPCInterface }'; my $usage = 'Usage: define $name HMCCURPCPROC { CCUHost | iodev={device} } { RPCPort | RPCInterface }';
my $errSource = "HMCCURPCPROC [$name]";
$hash->{version} = $HMCCURPCPROC_VERSION; $hash->{version} = $HMCCURPCPROC_VERSION;
if (exists($h->{iodev})) { if (exists($h->{iodev})) {
$ioname = $h->{iodev}; $ioname = $h->{iodev};
return $usage if (scalar(@$a) < 3); return $usage if (scalar(@$a) < 3);
return "HMCCU I/O device $ioname not found" if (!exists($defs{$ioname})); return "$errSource HMCCU I/O device $ioname not found" if (!exists($defs{$ioname}));
return "Device $ioname is not a HMCCU device" if ($defs{$ioname}->{TYPE} ne 'HMCCU'); return "$errSource Device $ioname is not a HMCCU device" if ($defs{$ioname}->{TYPE} ne 'HMCCU');
$ioHash = $defs{$ioname}; $ioHash = $defs{$ioname};
if (scalar(@$a) < 4) { if (scalar(@$a) < 4) {
$hash->{host} = $ioHash->{host}; $hash->{host} = $ioHash->{host};
@ -312,6 +313,8 @@ sub HMCCURPCPROC_Define ($$)
next if (!exists ($dh->{TYPE}) || !exists ($dh->{NAME}) || $dh->{TYPE} ne 'HMCCU'); next if (!exists ($dh->{TYPE}) || !exists ($dh->{NAME}) || $dh->{TYPE} ne 'HMCCU');
if ($dh->{ccuip} eq $rpcip) { $ioHash = $dh; last; } if ($dh->{ccuip} eq $rpcip) { $ioHash = $dh; last; }
} }
return $errSource."HMCCU I/O device not found" if (!defined($ioHash));
} }
# Store some definitions for delayed initialization # Store some definitions for delayed initialization
@ -322,15 +325,15 @@ sub HMCCURPCPROC_Define ($$)
# Interactive define command while CCU not ready or no IO device defined # Interactive define command while CCU not ready or no IO device defined
if (!defined($ioHash)) { if (!defined($ioHash)) {
my ($ccuactive, $ccuinactive) = HMCCU_IODeviceStates (); my ($ccuactive, $ccuinactive) = HMCCU_IODeviceStates ();
return $ccuinactive > 0 ? return $errSource.($ccuinactive > 0 ?
'CCU and/or IO device not ready. Please try again later' : ' CCU and/or IO device not ready. Please try again later' :
'Cannot detect IO device'; ' Cannot detect IO device');
} }
} }
else { else {
# CCU not ready during FHEM start # CCU not ready during FHEM start
if (!defined ($ioHash) || $ioHash->{ccustate} ne 'active') { if ($ioHash->{ccustate} ne 'active') {
HMCCU_Log ($hash, 2, 'Cannot detect IO device, maybe CCU not ready. Trying later ...'); HMCCU_Log ($hash, 2, 'CCU not ready. Trying later ...');
readingsSingleUpdate ($hash, 'state', 'Pending', 1); readingsSingleUpdate ($hash, 'state', 'Pending', 1);
$hash->{ccudevstate} = 'pending'; $hash->{ccudevstate} = 'pending';
return undef; return undef;
@ -339,11 +342,11 @@ sub HMCCURPCPROC_Define ($$)
# Initialize FHEM device, set IO device # Initialize FHEM device, set IO device
my $rc = HMCCURPCPROC_InitDevice ($ioHash, $hash); my $rc = HMCCURPCPROC_InitDevice ($ioHash, $hash);
return "Invalid port or interface $iface" if ($rc == 1); return "$errSource Invalid port or interface $iface" if ($rc == 1);
return "Can't assign I/O device $ioname" if ($rc == 2); return "$errSource Can't assign I/O device $ioname" if ($rc == 2);
return "Invalid local IP address ".$hash->{hmccu}{localaddr} if ($rc == 3); return "$errSource Invalid local IP address ".$hash->{hmccu}{localaddr} if ($rc == 3);
return "RPC device for CCU/port already exists" if ($rc == 4); return "$errSource RPC device for CCU/port already exists" if ($rc == 4);
return "Cannot connect to CCU ".$hash->{host}." interface $iface" if ($rc == 5); return "$errSource Cannot connect to CCU ".$hash->{host}." interface $iface" if ($rc == 5);
return undef; return undef;
} }

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.027 # Version 4.8.028
# #
# Configuration parameters for HomeMatic devices. # Configuration parameters for HomeMatic devices.
# #
@ -28,7 +28,7 @@ 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.027'; $HMCCU_CONFIG_VERSION = '4.8.028';
###################################################################### ######################################################################
# Map subtype to default role. Subtype is only available for HMIP # Map subtype to default role. Subtype is only available for HMIP
@ -103,6 +103,9 @@ $HMCCU_CONFIG_VERSION = '4.8.027';
'BLIND' => { 'BLIND' => {
F => 3, S => 'LEVEL', C => 'LEVEL', V => 'open:100,close:0', P => 2 F => 3, S => 'LEVEL', C => 'LEVEL', V => 'open:100,close:0', P => 2
}, },
'BLIND_TRANSMITTER' => {
F => 3, S => 'LEVEL', C => '', V => '', P => 1
},
'BLIND_VIRTUAL_RECEIVER' => { 'BLIND_VIRTUAL_RECEIVER' => {
F => 3, S => 'LEVEL', C => 'LEVEL', V => 'open:100,close:0', P => 2 F => 3, S => 'LEVEL', C => 'LEVEL', V => 'open:100,close:0', P => 2
}, },
@ -160,6 +163,8 @@ $HMCCU_CONFIG_VERSION = '4.8.027';
%HMCCU_READINGS = ( %HMCCU_READINGS = (
'BLIND' => 'BLIND' =>
'(C#\.)?LEVEL$:+pct', '(C#\.)?LEVEL$:+pct',
'BLIND_TRANSMITTER' =>
'(C#\.)?LEVEL$:+pct',
'BLIND_VIRTUAL_RECEIVER' => 'BLIND_VIRTUAL_RECEIVER' =>
'(C#\.)?LEVEL$:+pct', '(C#\.)?LEVEL$:+pct',
'SHUTTER_VIRTUAL_RECEIVER' => 'SHUTTER_VIRTUAL_RECEIVER' =>
@ -388,6 +393,9 @@ $HMCCU_CONFIG_VERSION = '4.8.027';
'webCmd' => 'pct:open:close:stop', 'webCmd' => 'pct:open:close:stop',
'widgetOverride' => 'pct:slider,0,10,100' 'widgetOverride' => 'pct:slider,0,10,100'
}, },
'BLIND_TRANSMITTER' => {
'substexcl' => 'pct',
},
'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',
@ -508,6 +516,9 @@ $HMCCU_CONFIG_VERSION = '4.8.027';
'DIRECTION' => { '0' => 'none', '1' => 'up', '2' => 'down' }, 'DIRECTION' => { '0' => 'none', '1' => 'up', '2' => 'down' },
'WORKING' => { '0' => 'no', 'false' => 'no', '1' => 'yes', 'true' => 'yes' } 'WORKING' => { '0' => 'no', 'false' => 'no', '1' => 'yes', 'true' => 'yes' }
}, },
'BLIND_TRANSMITTER' => {
'LEVEL' => { '0' => 'closed', '100' => 'open', 'close' => '0', 'open' => '100' }
},
'BLIND_VIRTUAL_RECEIVER' => { 'BLIND_VIRTUAL_RECEIVER' => {
'LEVEL' => { '0' => 'closed', '100' => 'open', 'close' => '0', 'open' => '100' }, 'LEVEL' => { '0' => 'closed', '100' => 'open', 'close' => '0', 'open' => '100' },
'DIRECTION' => { '0' => 'none', '1' => 'up', '2' => 'down' }, 'DIRECTION' => { '0' => 'none', '1' => 'up', '2' => 'down' },

View File

@ -1,5 +1,5 @@
UPD 2021-04-16_11:55:59 102657 FHEM/88_HMCCURPCPROC.pm UPD 2021-05-17_18:01:13 102813 FHEM/88_HMCCURPCPROC.pm
UPD 2021-04-16_11:55:50 81576 FHEM/HMCCUConf.pm UPD 2021-05-17_18:01:13 81874 FHEM/HMCCUConf.pm
UPD 2021-04-16_11:55:30 42683 FHEM/88_HMCCUCHN.pm UPD 2021-05-17_18:01:13 42050 FHEM/88_HMCCUCHN.pm
UPD 2021-04-16_11:55:22 335317 FHEM/88_HMCCU.pm UPD 2021-05-17_18:01:13 337736 FHEM/88_HMCCU.pm
UPD 2021-04-16_11:55:38 31630 FHEM/88_HMCCUDEV.pm UPD 2021-05-17_18:01:13 30869 FHEM/88_HMCCUDEV.pm