2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 04:36:36 +00:00

HMCCU: Bug fix

git-svn-id: https://svn.fhem.de/fhem/trunk@20414 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2019-10-27 16:49:53 +00:00
parent 381ebb1cc3
commit 02b8d986c4
5 changed files with 242 additions and 204 deletions

View File

@ -1,5 +1,6 @@
# 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.
- change: 88_HMCCU: Minor changes
- change: 71_ZM_Monitor: now writing internal 'model'
- feature: 74_AMADDevice: add class support for openApp,
fix bug then change attr remoteServer set Internal MODEL

View File

@ -4,7 +4,7 @@
#
# $Id$
#
# Version 4.3.018
# Version 4.3.019
#
# Module for communication between FHEM and Homematic CCU2/3.
#
@ -52,7 +52,7 @@ my %HMCCU_CUST_CHN_DEFAULTS;
my %HMCCU_CUST_DEV_DEFAULTS;
# HMCCU version
my $HMCCU_VERSION = '4.3.018';
my $HMCCU_VERSION = '4.3.019';
# Constants and default values
my $HMCCU_MAX_IOERRORS = 100;
@ -212,7 +212,7 @@ sub HMCCU_SetDefaults ($);
# Status and logging functions
sub HMCCU_Trace ($$$$);
sub HMCCU_Log ($$$$);
sub HMCCU_Log ($$$;$);
sub HMCCU_LogError ($$$);
sub HMCCU_SetError ($@);
sub HMCCU_SetState ($@);
@ -639,7 +639,8 @@ sub HMCCU_Attr ($@)
# Return empty string on success or error message on error.
######################################################################
sub HMCCU_AttrInterfacesPorts ($$$) {
sub HMCCU_AttrInterfacesPorts ($$$)
{
my ($hash, $attr, $attrval) = @_;
my $name = $hash->{NAME};
@ -1465,11 +1466,6 @@ sub HMCCU_Set ($@)
return HMCCU_SetError ($hash, $result) if ($result < 0);
return HMCCU_SetState ($hash, "OK");
}
# elsif ($opt eq 'test') {
# my $backend = shift @$a;
# my $url = defined ($backend) ? HMCCU_BuildURL ($hash, $backend) : '';
# return "URL=$url";
# }
elsif ($opt eq 'initialize') {
return HMCCU_SetError ($hash, "State of CCU must be unreachable")
if ($hash->{ccustate} ne 'unreachable');
@ -1508,51 +1504,60 @@ sub HMCCU_Set ($@)
return HMCCU_SetState ($hash, "OK");
}
elsif ($opt eq 'datapoint') {
$usage = "set $name $opt FHEM-Device[.Channel].Datapoint=Value [...]";
return HMCCU_SetError ($hash, $usage) if (scalar (keys %$h) < 1);
$usage = "set $name $opt DevSpec [Channel].Datapoint=Value [...]\n";
my $devSpec = shift @$a;
return HMCCU_SetError ($hash, $usage) if (scalar (keys %$h) < 1 || !defined($devSpec));
my $cmd = 1;
my %dpValues;
my @devList = devspec2array ($devSpec);
return HMCCU_SetError ($hash, "No FHEM device matching $devSpec in command set datapoint")
if (scalar (@devList) == 0);
foreach my $dptSpec (keys %$h) {
my $adr;
my $chn;
my $dpt;
my ($devName, $t1, $t2) = split (/\./, $dptSpec);
my ($t1, $t2) = split (/\./, $dptSpec);
return HMCCU_SetError ($hash, "FHEM device $devName not defined")
if (!exists ($defs{$devName}));
my $dh = $defs{$devName};
my $ccuif = $dh->{ccuif};
if ($dh->{TYPE} eq 'HMCCUCHN') {
return HMCCU_SetError ($hash, "Channel number not allowed for FHEM device $devName")
if (defined ($t2));
($adr, $chn) = HMCCU_SplitChnAddr ($dh->{ccuaddr});
$dpt = $t1;
}
elsif ($dh->{TYPE} eq 'HMCCUDEV') {
return HMCCU_SetError ($hash, "Missing channel number for device $devName")
if (!defined ($t2));
return HMCCU_SetError ($hash, "Invalid channel number specified for device $devName")
if ($t1 !~ /^[0-9]+$/ || $t1 > $dh->{channels});
$adr = $dh->{ccuaddr};
$chn = $t1;
$dpt = $t2;
}
else {
return HMCCU_SetError ($hash, "FHEM device $devName has illegal type");
}
foreach my $devName (@devList) {
my $dh = $defs{$devName};
my $ccuif = $dh->{ccuif};
return HMCCU_SetError ($hash, "Invalid datapoint $dpt specified for device $devName")
if (!HMCCU_IsValidDatapoint ($dh, $dh->{ccutype}, $chn, $dpt, 2));
my $statevals = AttrVal ($dh->{NAME}, 'statevals', '');
if ($dh->{TYPE} eq 'HMCCUCHN') {
if (defined ($t2)) {
HMCCU_Log ($hash, 3, "Ignored channel in set datapoint for device $devName");
$dpt = $t2;
}
else {
$dpt = $t1;
}
($adr, $chn) = HMCCU_SplitChnAddr ($dh->{ccuaddr});
}
elsif ($dh->{TYPE} eq 'HMCCUDEV') {
return HMCCU_SetError ($hash, "Missing channel number for device $devName")
if (!defined ($t2));
return HMCCU_SetError ($hash, "Invalid channel number specified for device $devName")
if ($t1 !~ /^[0-9]+$/ || $t1 > $dh->{channels});
$adr = $dh->{ccuaddr};
$chn = $t1;
$dpt = $t2;
}
else {
return HMCCU_SetError ($hash, "FHEM device $devName has illegal type");
}
my $no = sprintf ("%03d", $cmd);
$dpValues{"$no.$ccuif.$devName:$chn.$dpt"} = HMCCU_Substitute ($h->{$dptSpec}, $statevals, 1, undef, '');
$cmd++;
return HMCCU_SetError ($hash, "Invalid datapoint $dpt specified for device $devName")
if (!HMCCU_IsValidDatapoint ($dh, $dh->{ccutype}, $chn, $dpt, 2));
my $statevals = AttrVal ($dh->{NAME}, 'statevals', '');
my $no = sprintf ("%03d", $cmd);
$dpValues{"$no.$ccuif.$devName:$chn.$dpt"} = HMCCU_Substitute ($h->{$dptSpec}, $statevals, 1, undef, '');
$cmd++;
}
}
my $rc = HMCCU_SetMultipleDatapoints ($hash, \%dpValues);
@ -2590,9 +2595,10 @@ sub HMCCU_Trace ($$$$)
# Log message and return parameter rc.
######################################################################
sub HMCCU_Log ($$$$)
sub HMCCU_Log ($$$;$)
{
my ($hash, $level, $msg, $rc) = @_;
$rc = 0 if (!defined($rc));
my $name = "n/a";
my $type = "n/a";
$name = $hash->{NAME} if (exists ($hash->{NAME}));
@ -2618,9 +2624,10 @@ sub HMCCU_LogError ($$$)
######################################################################
# Set error state and write log file message
# Parameter text can be an error code (integer < 0) or an error text.
# Parameter text can be an error code (integer <= 0) or an error text.
# If text is 0 or 'OK' call HMCCU_SetState which returns undef.
# Otherwise error message is returned.
# Parameter addinfo is optional.
# Return error message.
######################################################################
sub HMCCU_SetError ($@)
@ -2653,19 +2660,23 @@ sub HMCCU_SetError ($@)
-21 => 'Device disabled'
);
$msg = exists ($errlist{$text}) ? $errlist{$text} : $text;
$msg = $type.": ".$name." ". $msg;
if (defined ($addinfo) && $addinfo ne '') {
$msg .= ". $addinfo";
if ($text ne 'OK' && $text ne '0') {
$msg = exists ($errlist{$text}) ? $errlist{$text} : $text;
$msg = $type.": ".$name." ". $msg;
if (defined ($addinfo) && $addinfo ne '') {
$msg .= ". $addinfo";
}
HMCCU_Log ($hash, 1, $msg, undef);
return HMCCU_SetState ($hash, "Error", $msg);
}
else {
return HMCCU_SetState ($hash, "OK");
}
HMCCU_Log ($hash, 1, $msg, undef);
return HMCCU_SetState ($hash, "Error", $msg);
}
######################################################################
# Set state of device if attribute ccuflags = ackState
# Return undef or $retval
######################################################################
sub HMCCU_SetState ($@)
@ -2932,19 +2943,18 @@ sub HMCCU_UpdateClients ($$$$$$)
my ($hash, $devexp, $ccuget, $fromccu, $ifname, $nonBlock) = @_;
my $fhname = $hash->{NAME};
my $c = 0;
my $dc = 0;
my $filter = "ccudevstate=active";
$filter .= ",ccuif=$ifname" if (defined ($ifname));
$ccuget = AttrVal ($fhname, 'ccuget', 'Value') if ($ccuget eq 'Attr');
my $list = '';
HMCCU_Log ($hash, 2, "Updating devices for filter $filter", 0);
if ($fromccu) {
foreach my $name (sort keys %{$hash->{hmccu}{adr}}) {
next if ($name !~ /$devexp/ || !($hash->{hmccu}{adr}{$name}{valid}));
my @devlist = HMCCU_FindClientDevices ($hash, "(HMCCUDEV|HMCCUCHN)", undef, $filter);
my @devlist = HMCCU_FindClientDevices ($hash, "(HMCCUDEV|HMCCUCHN)", undef, $filter);
$dc += scalar(@devlist);
foreach my $d (@devlist) {
my $ch = $defs{$d};
next if (!defined ($ch->{IODev}) || !defined ($ch->{ccuaddr}));
@ -2958,8 +2968,7 @@ sub HMCCU_UpdateClients ($$$$$$)
}
else {
my @devlist = HMCCU_FindClientDevices ($hash, "(HMCCUDEV|HMCCUCHN)", $devexp, $filter);
Log3 $fhname, 2, "HMCCU: Found ".scalar(@devlist)." client devices matching $devexp";
$dc = scalar(@devlist);
foreach my $d (@devlist) {
my $ch = $defs{$d};
next if (!defined ($ch->{IODev}) || !defined ($ch->{ccuaddr}) || $ch->{ccuif} eq 'fhem');
@ -2970,6 +2979,9 @@ sub HMCCU_UpdateClients ($$$$$$)
$c++;
}
}
return HMCCU_Log ($hash, 2, "HMCCU: Found no devices to update", 0) if ($c == 0);
HMCCU_Log ($hash, 2, "Updating $c of $dc client devices matching devexp=$devexp filter=$filter");
if (HMCCU_IsFlag ($fhname, 'nonBlocking') || $nonBlock) {
HMCCU_HMScriptExt ($hash, '!GetDatapointsByDevice', { list => $list, ccuget => $ccuget },
@ -6140,7 +6152,7 @@ sub HMCCU_ReadRPCQueue ($)
}
######################################################################
# Execute Homematic command on CCU.
# Execute Homematic command on CCU (blocking).
# If parameter mode is 1 an empty string is a valid result.
# Return undef on error.
######################################################################
@ -6162,7 +6174,6 @@ sub HMCCU_HMCommand ($$$)
$param->{sslargs} = { SSL_verify_mode => 0 };
my ($err, $response) = HttpUtils_BlockingGet ($param);
# my $response = GetFileFromURL ($url, $ccureqtimeout, $cmd);
if ($err eq '') {
$value = $response;
$value =~ s/<xml>(.*)<\/xml>//;
@ -6184,7 +6195,7 @@ sub HMCCU_HMCommand ($$$)
}
######################################################################
# Execute Homematic command on CCU without waiting for response.
# Execute Homematic command on CCU (non blocking).
######################################################################
sub HMCCU_HMCommandNB ($$$)
@ -6251,9 +6262,6 @@ sub HMCCU_HMScriptExt ($$$$$)
my $host = $hash->{host};
my $ccureqtimeout = AttrVal ($hash->{NAME}, "ccuReqTimeout", $HMCCU_TIMEOUT_REQUEST);
# if (!defined ($nonBlocking)) {
# $nonBlocking = HMCCU_IsFlag ($name, 'nonBlocking') ? 1 : 0;
# }
if ($hmscript =~ /^!(.*)$/) {
# Internal script
@ -6301,6 +6309,8 @@ sub HMCCU_HMScriptExt ($$$$$)
}
}
HMCCU_Trace ($hash, 2, "HMScriptEx", $code);
# Execute script on CCU
my $url = HMCCU_BuildURL ($hash, 'rega');
if (defined ($cbFunc)) {
@ -6535,19 +6545,17 @@ sub HMCCU_SetMultipleDatapoints ($$) {
}
}
# Execute command (non blocking)
if ($ccuFlags =~ /nonBlocking/) {
# Execute command (non blocking)
HMCCU_HMCommandNB ($clHash, $cmd, undef);
return 0;
}
# Execute command (blocking)
my $response = HMCCU_HMCommand ($clHash, $cmd, 1);
return -2 if (!defined ($response));
# Datapoint verification ???
return 0;
else {
# Execute command (blocking)
my $response = HMCCU_HMCommand ($clHash, $cmd, 1);
return defined ($response) ? 0 : -2;
# Datapoint verification ???
}
}
######################################################################
@ -8520,9 +8528,10 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
<li><b>set &lt;name&gt; cleardefaults</b><br/>
Clear default attributes imported from file.
</li><br/>
<li><b>set &lt;name&gt; datapoint &lt;FHEM-Device&gt;[.&lt;channel-number&gt;].&lt;datapoint&gt;=&ltvalue&gt;</b><br/>
<li><b>set &lt;name&gt; datapoint &lt;FHEM-DevSpec&gt; [&lt;channel-number&gt;].&lt;datapoint&gt;=&ltvalue&gt;</b><br/>
Set datapoint values on multiple devices. If <i>FHEM-Device</i> is of type HMCCUDEV
a <i>channel-number</i> must be specified.
a <i>channel-number</i> must be specified. The channel number is ignored for devices of
type HMCCUCHN.
</li><br/>
<li><b>set &lt;name&gt; defaults</b><br/>
Set default attributes for I/O device.

View File

@ -4,7 +4,7 @@
#
# $Id$
#
# Version 4.3.008
# Version 4.3.009
#
# (c) 2019 zap (zap01 <at> t-online <dot> de)
#
@ -41,7 +41,7 @@ sub HMCCUCHN_Initialize ($)
$hash->{parseParams} = 1;
$hash->{AttrList} = "IODev ccucalculate ".
"ccuflags:multiple-strict,ackState,nochn0,trace ccureadingfilter ".
"ccuflags:multiple-strict,ackState,logCommand,nochn0,trace ccureadingfilter ".
"ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ".
"ccureadingname:textField-long ccuSetOnChange ".
"ccureadings:0,1 ccuscaleval ccuverify:0,1,2 ccuget:State,Value controldatapoint ".
@ -228,12 +228,16 @@ sub HMCCUCHN_Set ($@)
my $ccutype = $hash->{ccutype};
my $ccuaddr = $hash->{ccuaddr};
my $ccuif = $hash->{ccuif};
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my $statevals = AttrVal ($name, 'statevals', '');
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', 'STATE', '', '');
my $result = '';
my $rc;
# Log commands
HMCCU_Log ($hash, 3, "set $name $opt ".join (' ', @$a)) if ($ccuflags =~ /logCommand/);
if ($opt eq 'datapoint') {
my $usage = "Usage: set $name datapoint {datapoint} {value} [...]";
my %dpval;
@ -255,9 +259,7 @@ sub HMCCUCHN_Set ($@)
return HMCCU_SetError ($hash, $usage) if (scalar (keys %dpval) < 1);
$rc = HMCCU_SetMultipleDatapoints ($hash, \%dpval);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'control') {
return HMCCU_SetError ($hash, -14) if ($cd eq '');
@ -270,9 +272,7 @@ sub HMCCUCHN_Set ($@)
$rc = HMCCU_SetMultipleDatapoints ($hash,
{ "001.$ccuif.$ccuaddr.$cd" => HMCCU_Substitute ($objvalue, $statevals, 1, undef, '') }
);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt =~ /^($hash->{statevals})$/) {
my $cmd = $1;
@ -287,9 +287,7 @@ sub HMCCUCHN_Set ($@)
$rc = HMCCU_SetMultipleDatapoints ($hash,
{ "001.$ccuif.$ccuaddr.$sd" => HMCCU_Substitute ($objvalue, $statevals, 1, undef, '') }
);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'toggle') {
return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals}));
@ -324,9 +322,7 @@ sub HMCCUCHN_Set ($@)
$rc = HMCCU_SetMultipleDatapoints ($hash,
{ "001.$objname" => HMCCU_Substitute ($objvalue, $statevals, 1, undef, '') }
);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'pct' || $opt eq 'up' || $opt eq 'down') {
return HMCCU_SetError ($hash, "Can't find LEVEL datapoint for device type $ccutype")
@ -374,8 +370,7 @@ sub HMCCUCHN_Set ($@)
$rc = HMCCU_SetMultipleDatapoints ($hash, { "001.$objname" => $objvalue });
}
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'on-for-timer' || $opt eq 'on-till') {
return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals}));
@ -400,9 +395,7 @@ sub HMCCUCHN_Set ($@)
"001.$ccuif.$ccuaddr.ON_TIME" => $timespec,
"002.$ccuif.$ccuaddr.$sd" => HMCCU_Substitute ("on", $statevals, 1, undef, '')
});
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'clear') {
my $rnexp = shift @$a;
@ -418,10 +411,8 @@ sub HMCCUCHN_Set ($@)
if (defined ($par) && $par eq 'device') {
($ccuobj, undef) = HMCCU_SplitChnAddr ($ccuaddr);
}
my ($rc, $res) = HMCCU_RPCRequest ($hash, "putParamset", $ccuobj, "MASTER", $h);
# my $rc = HMCCU_RPCSetConfig ($hash, $ccuobj, $h);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
($rc, $result) = HMCCU_RPCRequest ($hash, "putParamset", $ccuobj, "MASTER", $h);
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'rpcparameter') {
return HMCCU_SetError ($hash, "Usage: set $name rpcparameter [MASTER|VALUES] {parameter}={value} [...]")
@ -429,46 +420,42 @@ sub HMCCUCHN_Set ($@)
my $key = shift @$a;
$key = 'VALUES' if (!defined ($key));
my $rc;
my $res;
if ($key eq 'VALUES') {
($rc, $res) = HMCCU_SetMultipleParameters ($hash, $ccuaddr, $h);
($rc, $result) = HMCCU_SetMultipleParameters ($hash, $ccuaddr, $h);
}
elsif ($key eq 'MASTER') {
($rc, $res) = HMCCU_RPCRequest ($hash, "putParamset", $ccuaddr, $key, $h);
($rc, $result) = HMCCU_RPCRequest ($hash, "putParamset", $ccuaddr, $key, $h);
}
else {
return HMCCU_SetError ($hash, "Key must be MASTER or VALUES");
}
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'defaults') {
my $rc = HMCCU_SetDefaults ($hash);
return HMCCU_SetError ($hash, "HMCCU: No default attributes found") if ($rc == 0);
return HMCCU_SetState ($hash, "OK");
$rc = HMCCU_SetDefaults ($hash);
return HMCCU_SetError ($hash, $rc == 0 ? "No default attributes found" : "OK");
}
else {
return "HMCCUCHN: Unknown argument $opt, choose one of $rocmds"
if ($hash->{statevals} eq 'readonly');
my $retmsg = "HMCCUCHN: Unknown argument $opt, choose one of $rwcmds";
if ($hash->{statevals} ne '') {
my @cmdlist = split /\|/,$hash->{statevals};
shift @cmdlist;
$retmsg .= ':'.join(',',@cmdlist) if (scalar(@cmdlist) > 0);
foreach my $sv (@cmdlist) {
$retmsg .= ' '.$sv.':noArg';
}
$retmsg .= " toggle:noArg";
$retmsg .= " on-for-timer on-till"
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $ccuaddr, "ON_TIME", 2));
$retmsg .= " pct up down"
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $ccuaddr, "LEVEL", 2));
}
my $retmsg = "clear defaults:noArg";
if ($hash->{statevals} ne 'readonly') {
$retmsg .= " config control datapoint rpcparameter devstate";
return $retmsg;
if ($hash->{statevals} ne '') {
my @cmdlist = split /\|/,$hash->{statevals};
shift @cmdlist;
$retmsg .= ':'.join(',',@cmdlist) if (scalar(@cmdlist) > 0);
foreach my $sv (@cmdlist) {
$retmsg .= ' '.$sv.':noArg';
}
$retmsg .= " toggle:noArg";
$retmsg .= " on-for-timer on-till"
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $ccuaddr, "ON_TIME", 2));
$retmsg .= " pct up down"
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $ccuaddr, "LEVEL", 2));
}
}
return AttrTemplate_Set ($hash, $retmsg, $name, $opt, @$a);
}
}
@ -500,11 +487,15 @@ sub HMCCUCHN_Get ($@)
my $ccuaddr = $hash->{ccuaddr};
my $ccuif = $hash->{ccuif};
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', 'STATE', '', '');
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my $ccureadings = AttrVal ($name, "ccureadings", 1);
my $result = '';
my $rc;
# Log commands
HMCCU_Log ($hash, 3, "set $name $opt ".join (' ', @$a)) if ($ccuflags =~ /logCommand/);
if ($opt eq 'devstate') {
return HMCCU_SetError ($hash, -13) if ($sd eq '');
return HMCCU_SetError ($hash, -8)
@ -560,10 +551,9 @@ sub HMCCUCHN_Get ($@)
}
$par = '.*' if (!defined ($par));
my ($rc, $res) = HMCCU_RPCRequest ($hash, "getParamset", $ccuobj, "MASTER", undef, $par);
# my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "getParamset", $par);
return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
return $ccureadings ? undef : $res;
($rc, $result) = HMCCU_RPCRequest ($hash, "getParamset", $ccuobj, "MASTER", undef, $par);
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
return $ccureadings ? undef : $result;
}
elsif ($opt eq 'configlist') {
my $ccuobj = $ccuaddr;
@ -576,10 +566,9 @@ sub HMCCUCHN_Get ($@)
}
$par = '.*' if (!defined ($par));
my ($rc, $res) = HMCCU_RPCRequest ($hash, "listParamset", $ccuobj, "MASTER", undef, $par);
# my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "listParamset", $par);
return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
return $res;
($rc, $result) = HMCCU_RPCRequest ($hash, "listParamset", $ccuobj, "MASTER", undef, $par);
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
return $result;
}
elsif ($opt eq 'configdesc') {
my $ccuobj = $ccuaddr;
@ -588,14 +577,12 @@ sub HMCCUCHN_Get ($@)
($ccuobj, undef) = HMCCU_SplitChnAddr ($ccuaddr);
}
my ($rc, $res) = HMCCU_RPCRequest ($hash, "getParamsetDescription", $ccuobj, "MASTER", undef);
# my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "getParamsetDescription", undef);
return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
return $res;
($rc, $result) = HMCCU_RPCRequest ($hash, "getParamsetDescription", $ccuobj, "MASTER", undef);
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
return $result;
}
elsif ($opt eq 'defaults') {
$result = HMCCU_GetDefaults ($hash, 0);
return $result;
return HMCCU_GetDefaults ($hash, 0);
}
else {
my $retmsg = "HMCCUCHN: Unknown argument $opt, choose one of devstate:noArg defaults:noArg datapoint";
@ -812,9 +799,10 @@ sub HMCCUCHN_Get ($@)
Example:<br/>
<code>dewpoint:taupunkt:1.TEMPERATURE,1.HUMIDITY</code>
</li><br/>
<li><b>ccuflags {nochn0, trace}</b><br/>
<li><b>ccuflags {ackState, logCommand, nochn0, trace}</b><br/>
Control behaviour of device:<br/>
ackState: Acknowledge command execution by setting STATE to error or success.<br/>
logCommand: Write get and set commands to FHEM log with verbose level 3.<br/>
nochn0: Prevent update of status channel 0 datapoints / readings.<br/>
trace: Write log file information for operations related to this device.
</li><br/>

View File

@ -4,7 +4,7 @@
#
# $Id$
#
# Version 4.3.010
# Version 4.3.011
#
# (c) 2019 zap (zap01 <at> t-online <dot> de)
#
@ -43,7 +43,7 @@ sub HMCCUDEV_Initialize ($)
$hash->{parseParams} = 1;
$hash->{AttrList} = "IODev ccuaggregate:textField-long ccucalculate:textField-long ".
"ccuflags:multiple-strict,ackState,nochn0,trace ccureadingfilter:textField-long ".
"ccuflags:multiple-strict,ackState,logCommand,nochn0,trace ccureadingfilter:textField-long ".
"ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ".
"ccureadingname:textField-long ".
"ccureadings:0,1 ccuget:State,Value ccuscaleval ccuSetOnChange ccuverify:0,1,2 disable:0,1 ".
@ -281,9 +281,9 @@ sub HMCCUDEV_InitDevice ($$)
return 0;
}
#####################################
######################################################################
# Delete device
#####################################
######################################################################
sub HMCCUDEV_Delete ($$)
{
@ -296,9 +296,9 @@ sub HMCCUDEV_Delete ($$)
return undef;
}
#####################################
######################################################################
# Set attribute
#####################################
######################################################################
sub HMCCUDEV_Attr ($@)
{
@ -330,9 +330,9 @@ sub HMCCUDEV_Attr ($@)
return;
}
#####################################
######################################################################
# Set commands
#####################################
######################################################################
sub HMCCUDEV_Set ($@)
{
@ -342,9 +342,6 @@ sub HMCCUDEV_Set ($@)
return "No set command specified" if (!defined ($opt));
# Valid commands for read only devices
my $rocmds = "clear config defaults:noArg";
# Get I/O device, check device state
return undef if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' ||
!defined ($hash->{IODev}));
@ -374,6 +371,9 @@ sub HMCCUDEV_Set ($@)
my $result = '';
my $rc;
# Log commands
HMCCU_Log ($hash, 3, "set $name $opt ".join (' ', @$a)) if ($ccuflags =~ /logCommand/);
if ($opt eq 'datapoint') {
my $usage = "Usage: set $name datapoint [{channel-number}.]{datapoint} {value} [...]";
my %dpval;
@ -414,9 +414,7 @@ sub HMCCUDEV_Set ($@)
return HMCCU_SetError ($hash, $usage) if (scalar (keys %dpval) < 1);
$rc = HMCCU_SetMultipleDatapoints ($hash, \%dpval);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'control') {
return HMCCU_SetError ($hash, -12) if ($cc eq '');
@ -431,9 +429,7 @@ sub HMCCUDEV_Set ($@)
$rc = HMCCU_SetMultipleDatapoints ($hash,
{ "001.$ccuif.$ccuaddr:$cc.$cd" => HMCCU_Substitute ($objvalue, $statevals, 1, undef, '') }
);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt =~ /^($hash->{statevals})$/) {
my $cmd = $1;
@ -447,9 +443,7 @@ sub HMCCUDEV_Set ($@)
$rc = HMCCU_SetMultipleDatapoints ($hash,
{ "001.$ccuif.$ccuaddr:$sc.$sd" => HMCCU_Substitute ($objvalue, $statevals, 1, undef, '') }
);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'toggle') {
return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals}));
@ -488,9 +482,7 @@ sub HMCCUDEV_Set ($@)
$rc = HMCCU_SetMultipleDatapoints ($hash,
{ "001.$objname" => HMCCU_Substitute ($objvalue, $statevals, 1, undef, '') }
);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'pct' || $opt eq 'up' || $opt eq 'down') {
return HMCCU_SetError ($hash, -11) if ($sc eq '' && $cc eq '');
@ -550,8 +542,7 @@ sub HMCCUDEV_Set ($@)
$rc = HMCCU_SetMultipleDatapoints ($hash, { "001.$objname" => $objvalue });
}
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'on-for-timer' || $opt eq 'on-till') {
return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals}));
@ -575,9 +566,7 @@ sub HMCCUDEV_Set ($@)
"001.$ccuif.$ccuaddr:$sc.ON_TIME" => $timespec,
"002.$ccuif.$ccuaddr:$sc.$sd" => HMCCU_Substitute ("on", $statevals, 1, undef, '')
});
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'clear') {
my $rnexp = shift @$a;
@ -596,10 +585,7 @@ sub HMCCUDEV_Set ($@)
}
my ($rc, $res) = HMCCU_RPCRequest ($hash, "putParamset", $objname, "MASTER", $h);
# my $rc = HMCCU_RPCSetConfig ($hash, $objname, $h);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'rpcparameter') {
return HMCCU_SetError ($hash, "Usage: set $name rpcparameter { channel VALUES | [channel] MASTER } {parameter}={value} [...]")
@ -607,8 +593,6 @@ sub HMCCUDEV_Set ($@)
my $key;
my $chn;
my $rc;
my $res;
while (my $p = shift @$a) {
if (uc($p) =~ /^(MASTER|VALUES)$/ && !defined ($key)) {
@ -624,53 +608,51 @@ sub HMCCUDEV_Set ($@)
my $addr = defined ($chn) ? "$ccuaddr:$chn" : $ccuaddr;
if ($key eq 'VALUES') {
($rc, $res) = HMCCU_SetMultipleParameters ($hash, $addr, $h);
($rc, $result) = HMCCU_SetMultipleParameters ($hash, $addr, $h);
}
elsif ($key eq 'MASTER') {
($rc, $res) = HMCCU_RPCRequest ($hash, "putParamset", $addr, $key, $h);
($rc, $result) = HMCCU_RPCRequest ($hash, "putParamset", $addr, $key, $h);
}
else {
return HMCCU_SetError ($hash, "Key must be MASTER or VALUES");
}
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'defaults') {
my $rc = HMCCU_SetDefaults ($hash);
return HMCCU_SetError ($hash, "HMCCU: No default attributes found") if ($rc == 0);
return HMCCU_SetState ($hash, "OK");
return HMCCU_SetError ($hash, $rc == 0 ? "No default attributes found" : "OK");
}
else {
return "HMCCUCHN: Unknown argument $opt, choose one of ".$rocmds
if ($hash->{statevals} eq 'readonly');
my $retmsg = "HMCCUDEV: Unknown argument $opt, choose one of clear config control datapoint rpcparameter defaults:noArg";
if ($sc ne '') {
$retmsg .= " devstate";
if ($hash->{statevals} ne '') {
my @cmdlist = split /\|/,$hash->{statevals};
shift @cmdlist;
$retmsg .= ':'.join(',',@cmdlist) if (@cmdlist > 0);
foreach my $sv (@cmdlist) {
$retmsg .= ' '.$sv.':noArg';
my $retmsg = "clear config defaults:noArg";
if ($hash->{statevals} ne 'readonly') {
$retmsg .= " control datapoint rpcparameter";
if ($sc ne '') {
$retmsg .= " devstate";
if ($hash->{statevals} ne '') {
my @cmdlist = split /\|/,$hash->{statevals};
shift @cmdlist;
$retmsg .= ':'.join(',',@cmdlist) if (@cmdlist > 0);
foreach my $sv (@cmdlist) {
$retmsg .= ' '.$sv.':noArg';
}
$retmsg .= " toggle:noArg";
$retmsg .= " on-for-timer on-till"
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $sc, "ON_TIME", 2));
$retmsg .= " pct up down"
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $sc, "LEVEL", 2) ||
HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $cc, "LEVEL", 2));
}
$retmsg .= " toggle:noArg";
$retmsg .= " on-for-timer on-till"
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $sc, "ON_TIME", 2));
$retmsg .= " pct up down"
if (HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $sc, "LEVEL", 2) ||
HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $cc, "LEVEL", 2));
}
}
return $retmsg;
return AttrTemplate_Set ($hash, $retmsg, $name, $opt, @$a);
}
}
#####################################
######################################################################
# Get commands
#####################################
######################################################################
sub HMCCUDEV_Get ($@)
{
@ -700,6 +682,7 @@ sub HMCCUDEV_Get ($@)
my $ccutype = $hash->{ccutype};
my $ccuaddr = $hash->{ccuaddr};
my $ccuif = $hash->{ccuif};
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my $ccureadings = AttrVal ($name, 'ccureadings', 1);
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', 'STATE', '', '');
@ -711,6 +694,9 @@ sub HMCCUDEV_Get ($@)
return "HMCCUDEV: Unknown argument $opt, choose one of update:noArg";
}
# Log commands
HMCCU_Log ($hash, 3, "set $name $opt ".join (' ', @$a)) if ($ccuflags =~ /logCommand/);
if ($opt eq 'devstate') {
return HMCCU_SetError ($hash, -11) if ($sc eq '');
return HMCCU_SetError ($hash, -13) if ($sd eq '');

View File

@ -0,0 +1,54 @@
######################################################################
# $Id: hmccu.template 18592 2019-02-14 06:27:39Z Beta-User $
#
# Comments start with #. Empty lines are ignored.
# Syntax of one entry:
# name: line,
# one optional filter: line
# zero or more par: lines
# FHEM-Commands
# filter:INTERNAL=VALUE (optional)
# par: name of the parameter; comment; perl_code (optional)
# perl_code returns a value for the parameter, or undef.
# If undef, the user has to specify them (the comment is shown to the user)
######################################################################
######################################################################
# Door or window sensor
name:DoorWindowSensor
filter:TYPE=HMCCUCHN|HMCCUDEV:FILTER=ccutype=HM-Sec-SCo|HM-Sec-SC|HM-Sec-SC-2|HMIP-SWDO|HmIP-SWDO-I
par:channelNo;Channel number;{ InternalVal("DEVICE","TYPE","") eq "HMCCUDEV" ? "1." : "" }
desc: Door/window sensor
attr DEVICE ccureadingfilter STATE
attr DEVICE devStateIcon closed:10px-kreis-gruen open:10px-kreis-rot
attr DEVICE event-on-change-reading .*
attr DEVICE genericDeviceType ContactSensor
attr DEVICE hmstatevals ERROR!7:sabotage;SABOTAGE!1:sabotage
attr DEVICE statedatapoint channelNoSTATE
attr DEVICE substitute STATE!(0|false):closed,(1|true):open
######################################################################
# Window handle sensor
name WindowHandleSensor
filter:TYPE=HMCCUCHN|HMCCUDEV:FILTER=ccutype=HM-Sec-RHS|HM-Sec-RHS-2
attr DEVICE ccureadingfilter STATE
attr DEVICE hmstatevals ERROR!1:sabotage
attr DEVICE statedatapoint channelNoSTATE
attr DEVICE substitute STATE!0:closed,1:tilted,2:open;ERROR!0:no,1:sabotage
######################################################################
# Power socket
name PowerSocket
filter:TYPE=HMCCUCHN|HMCCUDEV:FILTER=ccutype=HM-LC-Sw1-Pl-2|HM-LC-Sw1-Pl-DN-R1|HmIP-PS
par:channelNo;Channel number;{ InternalVal("DEVICE","TYPE","") eq "HMCCUDEV" ? (InternalVal("DEVICE","ccuif","") eq "BidCos-RF" ? "1." : "3.") : "" }
desc: Power socket BidCos
attr DEVICE ccureadingfilter STATE
attr DEVICE statedatapoint channelNoSTATE
attr DEVICE controldatapoint channelNoSTATE
attr DEVICE statevals on:true,off:false
attr DEVICE substitute STATE!(1|true):on,(0|false):off
attr DEVICE webCmd devstate
attr DEVICE widgetOverride devstate:uzsuToggle,off,on