2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 10:46:53 +00:00

HMCCU: Version 4.1.001

git-svn-id: https://svn.fhem.de/fhem/trunk@14948 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2017-08-23 13:47:34 +00:00
parent a45b09be19
commit bb2ce4cea3
6 changed files with 260 additions and 205 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.
- changed: 88_HMCCU Version 4.1.001
- feature: HttpUtils/IPv6 with the useInet6 global attribute (Forum #75557) - feature: HttpUtils/IPv6 with the useInet6 global attribute (Forum #75557)
- bugfix: 74_AMADautomagicFlowset_4.0.5.xml: add openTask Check with - bugfix: 74_AMADautomagicFlowset_4.0.5.xml: add openTask Check with
timer trigger timer trigger

View File

@ -4,7 +4,7 @@
# #
# $Id$ # $Id$
# #
# Version 4.1 # Version 4.1.001
# #
# Module for communication between FHEM and Homematic CCU2. # Module for communication between FHEM and Homematic CCU2.
# #
@ -31,9 +31,8 @@
# get <name> defaults # get <name> defaults
# get <name> deviceinfo <device> # get <name> deviceinfo <device>
# get <name> devicelist [dump] # get <name> devicelist [dump]
# get <name> devicelist create <devexp> [t={chn|dev|all}] [s=<suffix>] # get <name> devicelist create <devexp> [t={chn|dev|all}] [s=<suffix>] [p=<prefix>] [f=<format>]
# [p=<prefix>] [f=<format>] # [defattr] [duplicates] [save] [<attr>=<val> [...]]}]
# [defattr] [<attr>=<val> [...]]}]
# get <name> dump {devtypes|datapoints} [<filter>] # get <name> dump {devtypes|datapoints} [<filter>]
# get <name> dutycycle # get <name> dutycycle
# get <name> exportdefaults {filename} # get <name> exportdefaults {filename}
@ -106,7 +105,7 @@ my %HMCCU_CUST_CHN_DEFAULTS;
my %HMCCU_CUST_DEV_DEFAULTS; my %HMCCU_CUST_DEV_DEFAULTS;
# HMCCU version # HMCCU version
my $HMCCU_VERSION = '4.1'; my $HMCCU_VERSION = '4.1.001';
# Default RPC port (BidCos-RF) # Default RPC port (BidCos-RF)
my $HMCCU_RPC_PORT_DEFAULT = 2001; my $HMCCU_RPC_PORT_DEFAULT = 2001;
@ -221,10 +220,10 @@ sub HMCCU_FormatReadingValue ($$);
sub HMCCU_Trace ($$$$); sub HMCCU_Trace ($$$$);
sub HMCCU_Log ($$$$); sub HMCCU_Log ($$$$);
sub HMCCU_SetError ($@); sub HMCCU_SetError ($@);
sub HMCCU_SetState ($$); sub HMCCU_SetState ($@);
sub HMCCU_Substitute ($$$$$); sub HMCCU_Substitute ($$$$$);
sub HMCCU_SubstRule ($$$); sub HMCCU_SubstRule ($$$);
sub HMCCU_SubstVariables ($$); sub HMCCU_SubstVariables ($$$);
sub HMCCU_UpdateClients ($$$$); sub HMCCU_UpdateClients ($$$$);
sub HMCCU_UpdateDeviceTable ($$); sub HMCCU_UpdateDeviceTable ($$);
sub HMCCU_UpdateSingleDatapoint ($$$$); sub HMCCU_UpdateSingleDatapoint ($$$$);
@ -1021,11 +1020,11 @@ sub HMCCU_Set ($@)
my $opt = shift @$a; my $opt = shift @$a;
my $options = "var delete execute hmscript cleardefaults:noArg defaults:noArg ". my $options = "var delete execute hmscript cleardefaults:noArg defaults:noArg ".
"importdefaults rpcserver:on,off datapoint"; "importdefaults rpcserver:on,off datapoint";
my $usage = "HMCCU: Unknown argument $opt, choose one of $options";
my $host = $hash->{host}; my $host = $hash->{host};
if ($opt ne 'rpcserver' && HMCCU_IsRPCStateBlocking ($hash)) { if ($opt ne 'rpcserver' && HMCCU_IsRPCStateBlocking ($hash)) {
HMCCU_SetState ($hash, "busy"); return HMCCU_SetState ($hash, "busy", "HMCCU: CCU busy, choose one of rpcserver:off");
return "HMCCU: CCU busy, choose one of rpcserver:off";
} }
my $ccuflags = AttrVal ($name, 'ccuflags', 'null'); my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
@ -1040,11 +1039,10 @@ sub HMCCU_Set ($@)
$vartype = shift @$a if (scalar (@$a) == 3); $vartype = shift @$a if (scalar (@$a) == 3);
my $objname = shift @$a; my $objname = shift @$a;
my $objvalue = shift @$a; my $objvalue = shift @$a;
$usage = "set $name $opt [{'bool'|'list'|'number'|'test'}] variable value [param=value [...]]";
my $result; my $result;
return HMCCU_SetError ($hash, return HMCCU_SetError ($hash, $usage) if (!defined ($objvalue));
"Usage: set $name $opt [type] {variable} {value} [parameter=value [...]]")
if (!defined ($objvalue));
$objname =~ s/$stripchar$// if ($stripchar ne ''); $objname =~ s/$stripchar$// if ($stripchar ne '');
$objvalue =~ s/\\_/%20/g; $objvalue =~ s/\\_/%20/g;
@ -1058,45 +1056,43 @@ sub HMCCU_Set ($@)
elsif ($opt eq 'datapoint') { elsif ($opt eq 'datapoint') {
my $objname = shift @$a; my $objname = shift @$a;
my $objvalue = shift @$a; my $objvalue = shift @$a;
$usage = "Usage: set $name $opt {ccuobject|'hmccu':fhemobject} value";
return HMCCU_SetError ($hash, "Usage: set $name $opt {ccuobject|hmccu:fhemobject} {value}") return HMCCU_SetError ($hash, $usage) if (!defined ($objvalue));
if (!defined ($objvalue));
my $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); my $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
return HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
} }
elsif ($opt eq 'delete') { elsif ($opt eq 'delete') {
my $objname = shift @$a; my $objname = shift @$a;
my $objtype = shift @$a; my $objtype = shift @$a;
$objtype = "OT_VARDP" if (!defined ($objtype)); $objtype = "OT_VARDP" if (!defined ($objtype));
$usage = "Usage: set $name $opt ccuobject ['OT_VARDP'|'OT_DEVICE']";
return HMCCU_SetError ($hash, "Usage: set $name $opt {ccuobject} [OT_VARDP | OT_DEVICE]") return HMCCU_SetError ($hash, $usage)
if (!defined ($objname) || ($objtype ne 'OT_VARDP' && $objtype ne 'OT_DEVICE')); if (!defined ($objname) || $objtype !~ /^(OT_VARDP|OT_DEVICE)$/);
my $result = HMCCU_HMScriptExt ($hash, "!DeleteObject", { name => $objname, type => $objtype }); my $result = HMCCU_HMScriptExt ($hash, "!DeleteObject", { name => $objname, type => $objtype });
return HMCCU_SetError ($hash, -2) if ($result =~ /^ERROR:.*/); return HMCCU_SetError ($hash, -2) if ($result =~ /^ERROR:.*/);
return HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
} }
elsif ($opt eq 'execute') { elsif ($opt eq 'execute') {
my $program = shift @$a; my $program = shift @$a;
my $response; my $response;
$usage = "Usage: set $name $opt program-name";
return HMCCU_SetError ($hash, "Usage: set $name execute {program-name}") return HMCCU_SetError ($hash, $usage) if (!defined ($program));
if (!defined ($program));
my $url = qq(http://$host:8181/do.exe?r1=dom.GetObject("$program").ProgramExecute()); my $url = qq(http://$host:8181/do.exe?r1=dom.GetObject("$program").ProgramExecute());
$response = GetFileFromURL ($url); $response = GetFileFromURL ($url);
$response =~ m/<r1>(.*)<\/r1>/; $response =~ m/<r1>(.*)<\/r1>/;
my $value = $1; my $value = $1;
if (defined ($value) && $value ne '' && $value ne 'null') {
return HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK") if (defined ($value) && $value ne '' && $value ne 'null');
} return HMCCU_SetError ($hash, "Program execution error");
else {
return HMCCU_SetError ($hash, "Program execution error");
}
} }
elsif ($opt eq 'hmscript') { elsif ($opt eq 'hmscript') {
my $script = shift @$a; my $script = shift @$a;
@ -1104,6 +1100,7 @@ sub HMCCU_Set ($@)
my $response = ''; my $response = '';
my %objects = (); my %objects = ();
my $objcount = 0; my $objcount = 0;
$usage = "Usage: set $name $opt {file|!function|'['code']'} ['dump'] [parname=value [...]]";
# If no parameter is specified list available script functions # If no parameter is specified list available script functions
if (!defined ($script)) { if (!defined ($script)) {
@ -1115,7 +1112,7 @@ sub HMCCU_Set ($@)
} }
} }
$response .= "Usage: set $name hmscript {file|!function|'['code']'} [dump] [parname=value [...]]"; $response .= $usage;
return HMCCU_SetError ($hash, $response) return HMCCU_SetError ($hash, $response)
if (!defined ($script) || (defined ($dump) && $dump ne 'dump')); if (!defined ($script) || (defined ($dump) && $dump ne 'dump'));
@ -1154,9 +1151,10 @@ sub HMCCU_Set ($@)
} }
elsif ($opt eq 'rpcserver') { elsif ($opt eq 'rpcserver') {
my $action = shift @$a; my $action = shift @$a;
$usage = "Usage: set $name $opt {'on'|'off'|'restart'}";
return HMCCU_SetError ($hash, "Usage: set $name rpcserver {on|off|restart}") return HMCCU_SetError ($hash, $usage)
if (!defined ($action) || $action !~ /^(on|off|restart)$/); if (!defined ($action) || $action !~ /^(on|off|restart)$/);
if ($action eq 'on') { if ($action eq 'on') {
if ($ccuflags =~ /extrpc/) { if ($ccuflags =~ /extrpc/) {
@ -1203,13 +1201,13 @@ sub HMCCU_Set ($@)
%HMCCU_CUST_CHN_DEFAULTS = (); %HMCCU_CUST_CHN_DEFAULTS = ();
%HMCCU_CUST_DEV_DEFAULTS = (); %HMCCU_CUST_DEV_DEFAULTS = ();
return "Default attributes deleted"; return HMCCU_SetState ($hash, "OK", "Default attributes deleted");
} }
elsif ($opt eq 'importdefaults') { elsif ($opt eq 'importdefaults') {
my $filename = shift @$a; my $filename = shift @$a;
$usage = "Usage: set $name $opt filename";
return HMCCU_SetError ($hash, "Usage: set $name importdefaults {filename}") return HMCCU_SetError ($hash, $usage) if (!defined ($filename));
if (!defined ($filename));
my $rc = HMCCU_ImportDefaults ($filename); my $rc = HMCCU_ImportDefaults ($filename);
return HMCCU_SetError ($hash, -16) if ($rc == 0); return HMCCU_SetError ($hash, -16) if ($rc == 0);
@ -1218,11 +1216,10 @@ sub HMCCU_Set ($@)
return HMCCU_SetError ($hash, "Syntax error in default attribute file $filename line $rc"); return HMCCU_SetError ($hash, "Syntax error in default attribute file $filename line $rc");
} }
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK", "Default attributes read from file $filename");
return "Default attributes read from file $filename";
} }
else { else {
return "HMCCU: Unknown argument $opt, choose one of ".$options; return $usage;
} }
} }
@ -1235,13 +1232,14 @@ sub HMCCU_Get ($@)
my ($hash, $a, $h) = @_; my ($hash, $a, $h) = @_;
my $name = shift @$a; my $name = shift @$a;
my $opt = shift @$a; my $opt = shift @$a;
my $options = "defaults:noArg exportdefaults devicelist dump dutycycle:noArg vars update". my $options = "defaults:noArg exportdefaults devicelist dump dutycycle:noArg vars update".
" updateccu parfile configdesc firmware:noArg rpcevents:noArg rpcstate:noArg deviceinfo"; " updateccu parfile configdesc firmware:noArg rpcevents:noArg rpcstate:noArg deviceinfo";
my $usage = "HMCCU: Unknown argument $opt, choose one of $options";
my $host = $hash->{host}; my $host = $hash->{host};
if ($opt ne 'rpcstate' && HMCCU_IsRPCStateBlocking ($hash)) { if ($opt ne 'rpcstate' && HMCCU_IsRPCStateBlocking ($hash)) {
HMCCU_SetState ($hash, "busy"); return HMCCU_SetState ($hash, "busy", "HMCCU: CCU busy, choose one of rpcstate:noArg");
return "HMCCU: CCU busy, choose one of rpcstate:noArg";
} }
my $ccuflags = AttrVal ($name, "ccuflags", "null"); my $ccuflags = AttrVal ($name, "ccuflags", "null");
@ -1257,12 +1255,12 @@ sub HMCCU_Get ($@)
my $content = shift @$a; my $content = shift @$a;
my $filter = shift @$a; my $filter = shift @$a;
$filter = '.*' if (!defined ($filter)); $filter = '.*' if (!defined ($filter));
$usage = "Usage: get $name dump {'datapoints'|'devtypes'} [filter]";
my %foper = (1, "R", 2, "W", 4, "E", 3, "RW", 5, "RE", 6, "WE", 7, "RWE"); my %foper = (1, "R", 2, "W", 4, "E", 3, "RW", 5, "RE", 6, "WE", 7, "RWE");
my %ftype = (2, "B", 4, "F", 16, "I", 20, "S"); my %ftype = (2, "B", 4, "F", 16, "I", 20, "S");
return HMCCU_SetError ($hash, "Usage: get $name dump {datapoints|devtypes} [filter]") return HMCCU_SetError ($hash, $usage) if (!defined ($content));
if (!defined ($content));
if ($content eq 'devtypes') { if ($content eq 'devtypes') {
foreach my $devtype (sort keys %{$hash->{hmccu}{dp}}) { foreach my $devtype (sort keys %{$hash->{hmccu}{dp}}) {
@ -1284,37 +1282,34 @@ sub HMCCU_Get ($@)
} }
} }
else { else {
return HMCCU_SetError ($hash, "Usage: get $name dump {datapoints|devtypes} [{filter}]"); return HMCCU_SetError ($hash, $usage);
} }
return "No data found" if ($result eq ''); return HMCCU_SetState ($hash, "OK", ($result eq '') ? "No data found" : $result);
return $result;
} }
elsif ($opt eq 'vars') { elsif ($opt eq 'vars') {
my $varname = shift @$a; my $varname = shift @$a;
$usage = "Usage: get $name vars {regexp}[,...]";
return HMCCU_SetError ($hash, "Usage: get $name vars {regexp}[,...]") return HMCCU_SetError ($hash, $usage) if (!defined ($varname));
if (!defined ($varname));
($rc, $result) = HMCCU_GetVariables ($hash, $varname); ($rc, $result) = HMCCU_GetVariables ($hash, $varname);
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0); return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK", $ccureadings ? undef : $result);
return $ccureadings ? undef : $result;
} }
elsif ($opt eq 'update' || $opt eq 'updateccu') { elsif ($opt eq 'update' || $opt eq 'updateccu') {
my $devexp = shift @$a; my $devexp = shift @$a;
$devexp = '.*' if (!defined ($devexp)); $devexp = '.*' if (!defined ($devexp));
$usage = "Usage: get $name $opt [device-expr [{'State'|'Value'}]]";
my $ccuget = shift @$a; my $ccuget = shift @$a;
$ccuget = 'Attr' if (!defined ($ccuget)); $ccuget = 'Attr' if (!defined ($ccuget));
return HMCCU_SetError ($hash, "Usage: get $name $opt [device-expr [{'State'|'Value'}]]") return HMCCU_SetError ($hash, $usage) if ($ccuget !~ /^(Attr|State|Value)$/);
if ($ccuget !~ /^(Attr|State|Value)$/);
my ($c_ok, $c_err) = HMCCU_UpdateClients ($hash, $devexp, $ccuget, my ($co, $ce) = HMCCU_UpdateClients ($hash, $devexp, $ccuget, ($opt eq 'updateccu') ? 1 : 0);
($opt eq 'updateccu') ? 1 : 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK",
return "$c_ok client devices successfully updated. Update for $c_err client devices failed"; "$co client devices successfully updated. Update for $ce client devices failed");
} }
elsif ($opt eq 'parfile') { elsif ($opt eq 'parfile') {
my $par_parfile = shift @$a; my $par_parfile = shift @$a;
@ -1343,23 +1338,22 @@ sub HMCCU_Get ($@)
($rc, $result) = HMCCU_GetChannel ($hash, \@parameters); ($rc, $result) = HMCCU_GetChannel ($hash, \@parameters);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK", $ccureadings ? undef : $result);
return $ccureadings ? undef : $result;
} }
elsif ($opt eq 'deviceinfo') { elsif ($opt eq 'deviceinfo') {
my $device = shift @$a; my $device = shift @$a;
$usage = "Usage: get $name $opt device [{'State'|'Value'}]";
return HMCCU_SetError ($hash, "Usage: get $name deviceinfo {device} [{'State'|'Value'}]") return HMCCU_SetError ($hash, $usage) if (!defined ($device));
if (!defined ($device));
my $ccuget = shift @$a; my $ccuget = shift @$a;
$ccuget = 'Attr' if (!defined ($ccuget)); $ccuget = 'Attr' if (!defined ($ccuget));
return HMCCU_SetError ($hash, "Usage: get $name deviceinfo {device} [{'State'|'Value'}]") return HMCCU_SetError ($hash, $usage) if ($ccuget !~ /^(Attr|State|Value)$/);
if ($ccuget !~ /^(Attr|State|Value)$/);
return HMCCU_SetError ($hash, -1) if (!HMCCU_IsValidDeviceOrChannel ($hash, $device)); return HMCCU_SetError ($hash, -1) if (!HMCCU_IsValidDeviceOrChannel ($hash, $device));
$result = HMCCU_GetDeviceInfo ($hash, $device, $ccuget); $result = HMCCU_GetDeviceInfo ($hash, $device, $ccuget);
return HMCCU_SetError ($hash, -2) if ($result eq '' || $result =~ /^ERROR:.*/); return HMCCU_SetError ($hash, -2) if ($result eq '' || $result =~ /^ERROR:.*/);
HMCCU_SetState ($hash, "OK");
return HMCCU_FormatDeviceInfo ($result); return HMCCU_FormatDeviceInfo ($result);
} }
elsif ($opt eq 'rpcevents') { elsif ($opt eq 'rpcevents') {
@ -1370,20 +1364,29 @@ sub HMCCU_Get ($@)
$result .= "S: ".$stkey." = ".$hash->{hmccu}{evs}{$stkey}."\n"; $result .= "S: ".$stkey." = ".$hash->{hmccu}{evs}{$stkey}."\n";
$result .= "R: ".$stkey." = ".$hash->{hmccu}{evr}{$stkey}."\n"; $result .= "R: ".$stkey." = ".$hash->{hmccu}{evr}{$stkey}."\n";
} }
return $result; return HMCCU_SetState ($hash, "OK", $result);
}
else {
my $rpcdev = HMCCU_GetRPCDevice ($hash, 0);
return HMCCU_SetError ($hash, "HMCCU: External RPC server not found") if ($rpcdev eq '');
$result = AnalyzeCommandChain (undef, "get $rpcdev rpcevents");
return HMCCU_SetState ($hash, "OK", $result) if (defined ($result));
return HMCCU_SetError ($hash, "No event statistics available");
} }
return HMCCU_SetError ($hash, "HMCCU: command not supported for external RPC server");
} }
elsif ($opt eq 'rpcstate') { elsif ($opt eq 'rpcstate') {
my @hm_pids = (); my @hm_pids = ();
my @hm_tids = (); my @hm_tids = ();
$result = "No RPC processes or threads are running";
if (HMCCU_IsRPCServerRunning ($hash, \@hm_pids, \@hm_tids)) { if (HMCCU_IsRPCServerRunning ($hash, \@hm_pids, \@hm_tids)) {
return "RPC process(es) running with pid(s) ". $result = "RPC process(es) running with pid(s) ".
join (',', @hm_pids) if (scalar (@hm_pids) > 0); join (',', @hm_pids) if (scalar (@hm_pids) > 0);
return "RPC thread(s) running with tid(s) ". $result = "RPC thread(s) running with tid(s) ".
join (',', @hm_tids) if (scalar (@hm_tids) > 0); join (',', @hm_tids) if (scalar (@hm_tids) > 0);
} }
return "No RPC processes or threads are running";
return HMCCU_SetState ($hash, "OK", $result);
} }
elsif ($opt eq 'devicelist') { elsif ($opt eq 'devicelist') {
my ($devcount, $chncount) = HMCCU_GetDeviceList ($hash); my ($devcount, $chncount) = HMCCU_GetDeviceList ($hash);
@ -1411,65 +1414,93 @@ sub HMCCU_Get ($@)
return $result; return $result;
} }
elsif ($optcmd eq 'create') { elsif ($optcmd eq 'create') {
$usage = "Usage: get $name create {devexp|chnexp} [t={'chn'|'dev'|'all'}] [s=suffix] ".
"[p=prefix] [f=format] ['defattr'] ['duplicates'] [save] [attr=val [...]]";
my $devdefaults = 0;
my $duplicates = 0;
my $savedef = 0;
my $newcount = 0;
# Process command line parameters
my $devspec = shift @$a;
my $devprefix = exists ($h->{p}) ? $h->{p} : ''; my $devprefix = exists ($h->{p}) ? $h->{p} : '';
my $devsuffix = exists ($h->{'s'}) ? $h->{'s'} : ''; my $devsuffix = exists ($h->{'s'}) ? $h->{'s'} : '';
my $devtype = exists ($h->{t}) ? $h->{t} : 'dev'; my $devtype = exists ($h->{t}) ? $h->{t} : 'dev';
my $devformat = exists ($h->{f}) ? $h->{f} : '%n'; my $devformat = exists ($h->{f}) ? $h->{f} : '%n';
my $devdefaults = 0; return HMCCU_SetError ($hash, $usage)
my $newcount = 0; if ($devtype !~ /^(dev|chn|all)$/ || !defined ($devspec));
my @devattr;
my $devspec = shift @$a;
return "Please specify expression for CCU device or channel names"
if (!defined ($devspec));
foreach my $defopt (@$a) { foreach my $defopt (@$a) {
if ($defopt eq 'defattr') { if ($defopt eq 'defattr') { $devdefaults = 1; }
$devdefaults = 1; elsif ($defopt eq 'duplicates') { $duplicates = 1; }
} elsif ($defopt eq 'save') { $savedef = 1; }
else { else { return HMCCU_SetError ($hash, $usage); }
push (@devattr, $defopt);
}
} }
# Get list of existing client devices
my @devlist = HMCCU_FindClientDevices ($hash, "(HMCCUDEV|HMCCUCHN)", undef, undef);
foreach my $add (sort keys %{$hash->{hmccu}{dev}}) { foreach my $add (sort keys %{$hash->{hmccu}{dev}}) {
my $defmod = $hash->{hmccu}{dev}{$add}{addtype} eq 'dev' ? 'HMCCUDEV' : 'HMCCUCHN'; my $defmod = $hash->{hmccu}{dev}{$add}{addtype} eq 'dev' ? 'HMCCUDEV' : 'HMCCUCHN';
my $ccuname = $hash->{hmccu}{dev}{$add}{name}; my $ccuname = $hash->{hmccu}{dev}{$add}{name};
my $ccudevname = HMCCU_GetDeviceName ($hash, $add, $ccuname); my $ccudevname = HMCCU_GetDeviceName ($hash, $add, $ccuname);
next if ($devtype ne 'all' && $devtype ne $hash->{hmccu}{dev}{$add}{addtype}); next if ($devtype ne 'all' && $devtype ne $hash->{hmccu}{dev}{$add}{addtype});
next if (HMCCU_ExprNotMatch ($ccuname, $devspec, 1)); next if (HMCCU_ExprNotMatch ($ccuname, $devspec, 1));
# Build FHEM device name
my $devname = $devformat; my $devname = $devformat;
$devname = $devprefix.$devname.$devsuffix; $devname = $devprefix.$devname.$devsuffix;
$devname =~ s/%n/$ccuname/g; $devname =~ s/%n/$ccuname/g;
$devname =~ s/%d/$ccudevname/g; $devname =~ s/%d/$ccudevname/g;
$devname =~ s/%a/$add/g; $devname =~ s/%a/$add/g;
$devname =~ s/[^A-Za-z\d_\.]+/_/g; $devname =~ s/[^A-Za-z\d_\.]+/_/g;
# Check for duplicate device definitions
if (!$duplicates) {
next if (exists ($defs{$devname}));
my $devexists = 0;
foreach my $exdev (@devlist) {
if ($defs{$exdev}->{ccuaddr} eq $add) {
$devexists = 1;
last;
}
}
next if ($devexists);
}
# Define new client device
my $ret = CommandDefine (undef, $devname." $defmod ".$add); my $ret = CommandDefine (undef, $devname." $defmod ".$add);
if ($ret) { if ($ret) {
Log3 $name, 2, "HMCCU: Define command failed $devname $defmod $ccuname"; Log3 $name, 2, "HMCCU: Define command failed $devname $defmod $ccuname";
Log3 $name, 2, "$defmod: $ret"; Log3 $name, 2, "$defmod: $ret";
$result .= "\nCan't create device $devname. $ret";
next; next;
} }
# Set device attributes
HMCCU_SetDefaults ($defs{$devname}) if ($devdefaults); HMCCU_SetDefaults ($defs{$devname}) if ($devdefaults);
foreach my $da (@devattr) { foreach my $da (keys %$h) {
my ($at, $vl) = split ('=', $da); next if ($da =~ /^[pstf]$/);
CommandAttr (undef, "$devname $at $vl") if (defined ($vl)); $ret = CommandAttr (undef, "$devname $da ".$h->{$da});
if ($ret) {
Log3 $name, 2, "HMCCU: Attr command failed $devname $da ".$h->{$da};
Log3 $name, 2, "$defmod: $ret";
}
} }
Log3 $name, 2, "$defmod: Created device $devname"; Log3 $name, 2, "$defmod: Created device $devname";
$result .= "\nCreated device $devname";
$newcount++; $newcount++;
} }
CommandSave (undef, undef) if ($newcount > 0); CommandSave (undef, undef) if ($newcount > 0 && $savedef);
$result .= ", created $newcount client devices"; $result .= "\nCreated $newcount client devices";
} }
} }
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK", $result);
return $result;
} }
elsif ($opt eq 'dutycycle') { elsif ($opt eq 'dutycycle') {
my $dc = HMCCU_GetDutyCycle ($hash); my $dc = HMCCU_GetDutyCycle ($hash);
return "Read $dc duty cycle values"; return HMCCU_SetState ($hash, "OK", "Read $dc duty cycle values");
} }
elsif ($opt eq 'firmware') { elsif ($opt eq 'firmware') {
my $dc = HMCCU_GetFirmwareVersions ($hash); my $dc = HMCCU_GetFirmwareVersions ($hash);
@ -1491,29 +1522,27 @@ sub HMCCU_Get ($@)
$hash->{hmccu}{type}{$ct}{firmware}, $hash->{hmccu}{type}{$ct}{date}; $hash->{hmccu}{type}{$ct}{firmware}, $hash->{hmccu}{type}{$ct}{date};
} }
return $result; return HMCCU_SetState ($hash, "OK", $result);
} }
elsif ($opt eq 'defaults') { elsif ($opt eq 'defaults') {
$result = HMCCU_GetDefaults ($hash, 1); $result = HMCCU_GetDefaults ($hash, 1);
return $result; return HMCCU_SetState ($hash, "OK", $result);
} }
elsif ($opt eq 'exportdefaults') { elsif ($opt eq 'exportdefaults') {
my $filename = shift @$a; my $filename = shift @$a;
$usage = "Usage: get $name $opt filename";
return HMCCU_SetError ($hash, "Usage: get $name exportdefaults {filename}") return HMCCU_SetError ($hash, $usage) if (!defined ($filename));
if (!defined ($filename));
my $rc = HMCCU_ExportDefaults ($filename); my $rc = HMCCU_ExportDefaults ($filename);
return HMCCU_SetError ($hash, -16) if ($rc == 0); return HMCCU_SetError ($hash, -16) if ($rc == 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK", "Default attributes written to $filename");
return "Default attributes written to $filename";
} }
elsif ($opt eq 'aggregation') { elsif ($opt eq 'aggregation') {
my $rule = shift @$a; my $rule = shift @$a;
$usage = "Usage: get $name $opt {'all'|'rule'}";
return HMCCU_SetError ($hash, "Usage: get $name aggregagtion {all|rule}") return HMCCU_SetError ($hash, $usage) if (!defined ($rule));
if (!defined ($rule));
if ($rule eq 'all') { if ($rule eq 'all') {
foreach my $r (keys %{$hash->{hmccu}{agg}}) { foreach my $r (keys %{$hash->{hmccu}{agg}}) {
@ -1528,27 +1557,24 @@ sub HMCCU_Get ($@)
$result = "$rule = $result"; $result = "$rule = $result";
} }
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK", $ccureadings ? undef : $result);
return $ccureadings ? undef : $result;
} }
elsif ($opt eq 'configdesc') { elsif ($opt eq 'configdesc') {
my $ccuobj = shift @$a; my $ccuobj = shift @$a;
$usage = "Usage: get $name $opt {device|channel}";
return HMCCU_SetError ($hash, "Usage: get $name configdesc {device|channel}") return HMCCU_SetError ($hash, $usage) if (!defined ($ccuobj));
if (!defined ($ccuobj));
my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "getParamsetDescription", undef); my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "getParamsetDescription", undef);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK", $res);
return $res;
} }
else { else {
if (exists ($hash->{hmccu}{agg})) { if (exists ($hash->{hmccu}{agg})) {
my @rules = keys %{$hash->{hmccu}{agg}}; my @rules = keys %{$hash->{hmccu}{agg}};
$options .= " aggregation:all,".join (',', @rules) if (scalar (@rules) > 0); $options .= " aggregation:all,".join (',', @rules) if (scalar (@rules) > 0);
} }
return "HMCCU: Unknown argument $opt, choose one of ".$options; return $usage;
} }
} }
@ -1933,18 +1959,17 @@ sub HMCCU_SetError ($@)
$msg .= ". $addinfo"; $msg .= ". $addinfo";
} }
HMCCU_SetState ($hash, "Error");
Log3 $name, 1, $msg; Log3 $name, 1, $msg;
return $msg; return HMCCU_SetState ($hash, "Error", $msg);
} }
################################################################## ##################################################################
# Set state of device if attribute ccuackstate = 1 # Set state of device if attribute ccuackstate = 1
################################################################## ##################################################################
sub HMCCU_SetState ($$) sub HMCCU_SetState ($@)
{ {
my ($hash, $text) = @_; my ($hash, $text, $retval) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $defackstate = $hash->{TYPE} eq 'HMCCU' ? 1 : 0; my $defackstate = $hash->{TYPE} eq 'HMCCU' ? 1 : 0;
@ -1955,7 +1980,7 @@ sub HMCCU_SetState ($$)
readingsSingleUpdate ($hash, "state", $text, 1); readingsSingleUpdate ($hash, "state", $text, 1);
} }
return ($text eq "busy") ? "HMCCU: CCU busy" : undef; return ($text eq "busy") ? "HMCCU: CCU busy" : $retval;
} }
###################################################################### ######################################################################
@ -2050,20 +2075,51 @@ sub HMCCU_SubstRule ($$$)
} }
###################################################################### ######################################################################
# Substitute datapoint variables in string by datapoint value. # Substitute datapoint variables in string by datapoint value. The
# value depends on the character preceding the variable name. Syntax
# of variable names is:
# {$|$$|%|%%}{[cn.]Name}
# {$|$$|%|%%}[cn.]Name
# % = Original / raw value
# %% = Previous original / raw value
# $ = Converted / formatted value
# $$ = Previous converted / formatted value
###################################################################### ######################################################################
sub HMCCU_SubstVariables ($$) sub HMCCU_SubstVariables ($$$)
{ {
my ($clhash, $text) = @_; my ($clhash, $text, $dplist) = @_;
my @varlist;
if (defined ($dplist)) {
@varlist = split (',', $dplist);
}
else {
@varlist = keys %{$clhash->{hmccu}{dp}};
}
# Substitute datapoint variables by value # Substitute datapoint variables by value
foreach my $dp (keys %{$clhash->{hmccu}{dp}}) { # foreach my $dp (keys %{$clhash->{hmccu}{dp}}) {
my ($chn,$dpt) = split (/\./, $dp); foreach my $dp (@varlist) {
my ($chn, $dpt) = split (/\./, $dp);
if (defined ($clhash->{hmccu}{dp}{$dp}{VAL})) { if (defined ($clhash->{hmccu}{dp}{$dp}{VAL})) {
my $value = HMCCU_FormatReadingValue ($clhash, $clhash->{hmccu}{dp}{$dp}{VAL}); # my $value = HMCCU_FormatReadingValue ($clhash, $clhash->{hmccu}{dp}{$dp}{VAL});
$text =~ s/\$\{$dp\}/$value/g; # $text =~ s/\$\{$dp\}/$value/g;
$text =~ s/\$\{$dpt\}/$value/g; # $text =~ s/\$\{$dpt\}/$value/g;
$text =~ s/\$\{?$dp\}?/$clhash->{hmccu}{dp}{$dp}{VAL}/g;
$text =~ s/\$\{?$dpt\}?/$clhash->{hmccu}{dp}{$dp}{VAL}/g;
}
if (defined ($clhash->{hmccu}{dp}{$dp}{OVAL})) {
$text =~ s/\$\$\{?$dp\}?/$clhash->{hmccu}{dp}{$dp}{OVAL}/g;
$text =~ s/\$\$\{?$dpt\}?/$clhash->{hmccu}{dp}{$dp}{OVAL}/g;
}
if (defined ($clhash->{hmccu}{dp}{$dp}{SVAL})) {
$text =~ s/\%\{?$dp\}?/$clhash->{hmccu}{dp}{$dp}{SVAL}/g;
$text =~ s/\%\{?$dpt\}?/$clhash->{hmccu}{dp}{$dp}{SVAL}/g;
}
if (defined ($clhash->{hmccu}{dp}{$dp}{OSVAL})) {
$text =~ s/\%\%\{?$dp\}?/$clhash->{hmccu}{dp}{$dp}{OSVAL}/g;
$text =~ s/\%\%\{?$dpt\}?/$clhash->{hmccu}{dp}{$dp}{OSVAL}/g;
} }
} }
@ -2524,42 +2580,37 @@ sub HMCCU_UpdatePeers ($$$$)
HMCCU_Trace ($clt_hash, 2, $fnc, "vars=$vars, cond=$cond, type=$type, act=$act"); HMCCU_Trace ($clt_hash, 2, $fnc, "vars=$vars, cond=$cond, type=$type, act=$act");
next if ($cond !~ /$chndpt/); next if ($cond !~ /$chndpt/);
HMCCU_Trace ($clt_hash, 2, $fnc, "eval $cond"); HMCCU_Trace ($clt_hash, 2, $fnc, "eval $cond");
# Check if rule is affected by datapoint update
my $ex = 0; my $ex = 0;
foreach my $dpt (split (",", $vars)) { foreach my $dpt (split (",", $vars)) {
HMCCU_Trace ($clt_hash, 2, $fnc, "dpt=$dpt"); HMCCU_Trace ($clt_hash, 2, $fnc, "dpt=$dpt");
$ex = 1 if ($ex == 0 && $dpt eq $chndpt); $ex = 1 if ($ex == 0 && $dpt eq $chndpt);
if (exists ($clt_hash->{hmccu}{dp}{$dpt})) { if (!exists ($clt_hash->{hmccu}{dp}{$dpt})) {
if (exists ($clt_hash->{hmccu}{dp}{$dpt}{OVAL})) {
$cond =~ s/\%\%$dpt/$clt_hash->{hmccu}{dp}{$dpt}{OVAL}/g;
}
if (exists ($clt_hash->{hmccu}{dp}{$dpt}{VAL})) {
$cond =~ s/\%$dpt/$clt_hash->{hmccu}{dp}{$dpt}{VAL}/g;
}
if (exists ($clt_hash->{hmccu}{dp}{$dpt}{OSVAL})) {
$cond =~ s/\$\$$dpt/$clt_hash->{hmccu}{dp}{$dpt}{OSVAL}/g;
}
if (exists ($clt_hash->{hmccu}{dp}{$dpt}{SVAL})) {
$cond =~ s/\$$dpt/$clt_hash->{hmccu}{dp}{$dpt}{SVAL}/g;
}
}
else {
HMCCU_Trace ($clt_hash, 2, $fnc, "Datapoint $dpt does not exist on hash"); HMCCU_Trace ($clt_hash, 2, $fnc, "Datapoint $dpt does not exist on hash");
} }
last if ($ex == 1);
} }
next if (! $ex); next if (! $ex);
# Substitute variables and evaluate condition
$cond = HMCCU_SubstVariables ($clt_hash, $cond, $vars);
my $e = eval "$cond"; my $e = eval "$cond";
HMCCU_Trace ($clt_hash, 2, $fnc, "Error in eval $cond") if (!defined ($e)); HMCCU_Trace ($clt_hash, 2, $fnc, "Error in eval $cond") if (!defined ($e));
HMCCU_Trace ($clt_hash, 2, $fnc, "NoMatch in eval $cond") if (defined ($e) && $e eq ''); HMCCU_Trace ($clt_hash, 2, $fnc, "NoMatch in eval $cond") if (defined ($e) && $e eq '');
next if (!defined ($e) || $e eq ''); next if (!defined ($e) || $e eq '');
# Substitute variables and execute action
if ($type eq 'ccu' || $type eq 'hmccu') { if ($type eq 'ccu' || $type eq 'hmccu') {
my ($aobj, $aexp) = split (/=/, $act); my ($aobj, $aexp) = split (/=/, $act);
$aexp =~ s/\$value/$val/g; $aexp =~ s/\$value/$val/g;
$aexp = HMCCU_SubstVariables ($clt_hash, $aexp, $vars);
HMCCU_Trace ($clt_hash, 2, $fnc, "set $aobj to $aexp"); HMCCU_Trace ($clt_hash, 2, $fnc, "set $aobj to $aexp");
HMCCU_SetDatapoint ($clt_hash, "$type:$aobj", $aexp); HMCCU_SetDatapoint ($clt_hash, "$type:$aobj", $aexp);
} }
elsif ($type eq 'fhem') { elsif ($type eq 'fhem') {
$act =~ s/\$value/$val/g; $act =~ s/\$value/$val/g;
$act = HMCCU_SubstVariables ($clt_hash, $act, $vars);
HMCCU_Trace ($clt_hash, 2, $fnc, "Execute command $act"); HMCCU_Trace ($clt_hash, 2, $fnc, "Execute command $act");
AnalyzeCommandChain (undef, $act); AnalyzeCommandChain (undef, $act);
} }
@ -4022,7 +4073,7 @@ sub HMCCU_GetAttrSubstitute ($$)
return $subst if ($subst !~ /\$\{.+\}/); return $subst if ($subst !~ /\$\{.+\}/);
$subst = HMCCU_SubstVariables ($clhash, $subst); $subst = HMCCU_SubstVariables ($clhash, $subst, undef);
HMCCU_Trace ($clhash, 2, $fnc, "subst_vars = $subst"); HMCCU_Trace ($clhash, 2, $fnc, "subst_vars = $subst");
@ -4661,7 +4712,8 @@ sub HMCCU_ScaleValue ($$$$)
# Do not scale if value out of range or interval wrong # Do not scale if value out of range or interval wrong
return $value if ($a[1] > $a[2] || $a[3] > $a[4]); return $value if ($a[1] > $a[2] || $a[3] > $a[4]);
return $value if ($mode == 0 && ($value < $a[1] || $value > $a[2])); return $value if ($mode == 0 && ($value < $a[1] || $value > $a[2]));
return $value if ($mode == 1 && ($value >= $a[1] && $value <= $a[2])); # return $value if ($mode == 1 && ($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) {
@ -5260,7 +5312,7 @@ sub HMCCU_GetHMState ($$$)
$hmstate[3] = ReadingsVal ($name, 'state', undef) if (!defined ($defval)); $hmstate[3] = ReadingsVal ($name, 'state', undef) if (!defined ($defval));
# Substitute variables # Substitute variables
$hmstatevals = HMCCU_SubstVariables ($clhash, $hmstatevals); $hmstatevals = HMCCU_SubstVariables ($clhash, $hmstatevals, undef);
my @rulelist = split (";", $hmstatevals); my @rulelist = split (";", $hmstatevals);
foreach my $rule (@rulelist) { foreach my $rule (@rulelist) {
@ -6074,8 +6126,8 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
which reacts with execution of command 'get devicelist' on these events. which reacts with execution of command 'get devicelist' on these events.
</li><br/> </li><br/>
<li><b>get &lt;name&gt; devicelist create &lt;devexp&gt; [t={chn|<u>dev</u>|all}] <li><b>get &lt;name&gt; devicelist create &lt;devexp&gt; [t={chn|<u>dev</u>|all}]
[p=&lt;prefix&gt;] [s=&lt;suffix&gt;] [f=&lt;format&gt;] [defattr] [p=&lt;prefix&gt;] [s=&lt;suffix&gt;] [f=&lt;format&gt;] [defattr] [duplicates]
[&lt;attr&gt;=&lt;value&gt; [...]]</b><br/> [save] [&lt;attr&gt;=&lt;value&gt; [...]]</b><br/>
With option 'create' HMCCU will automatically create client devices for all CCU devices With option 'create' HMCCU will automatically create client devices for all CCU devices
and channels matching specified regular expression. With option t=chn or t=dev (default) and channels matching specified regular expression. With option t=chn or t=dev (default)
the creation of devices is limited to CCU channels or devices.<br/> the creation of devices is limited to CCU channels or devices.<br/>
@ -6085,7 +6137,9 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
format identifiers which are substituted by corresponding values of the CCU device or format identifiers which are substituted by corresponding values of the CCU device or
channel: %n = CCU object name (channel or device), %d = CCU device name, %a = CCU address. channel: %n = CCU object name (channel or device), %d = CCU device name, %a = CCU address.
In addition a list of default attributes for the created client devices can be specified. In addition a list of default attributes for the created client devices can be specified.
If option 'defattr' is specified HMCCU tries to set default attributes for device. If option 'defattr' is specified HMCCU tries to set default attributes for device.
With option 'duplicates' HMCCU will overwrite existing devices and/or create devices
for existing device addresses. Option 'save' will save FHEM config after device definition.
</li><br/> </li><br/>
<li><b>get &lt;name&gt; dump {datapoints|devtypes} [&lt;filter&gt;]</b><br/> <li><b>get &lt;name&gt; dump {datapoints|devtypes} [&lt;filter&gt;]</b><br/>
Dump all Homematic devicetypes or all devices including datapoints currently Dump all Homematic devicetypes or all devices including datapoints currently

View File

@ -4,7 +4,7 @@
# #
# $Id$ # $Id$
# #
# Version 4.1 # Version 4.1.001
# #
# (c) 2017 zap (zap01 <at> t-online <dot> de) # (c) 2017 zap (zap01 <at> t-online <dot> de)
# #
@ -133,15 +133,9 @@ sub HMCCUCHN_Define ($@)
my $arg = shift @$a; my $arg = shift @$a;
while (defined ($arg)) { while (defined ($arg)) {
return $usage if ($n == 3); return $usage if ($n == 3);
if ($arg eq 'readonly') { if ($arg eq 'readonly') { $hash->{statevals} = $arg; }
$hash->{statevals} = $arg; elsif ($arg eq 'defaults') { HMCCU_SetDefaults ($hash); }
} else { return $usage; }
elsif ($arg eq 'defaults') {
HMCCU_SetDefaults ($hash);
}
else {
return $usage;
}
$n++; $n++;
$arg = shift @$a; $arg = shift @$a;
} }
@ -239,8 +233,7 @@ sub HMCCUCHN_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'control') { elsif ($opt eq 'control') {
return HMCCU_SetError ($hash, -14) if ($cd eq ''); return HMCCU_SetError ($hash, -14) if ($cd eq '');
@ -255,8 +248,7 @@ sub HMCCUCHN_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt =~ /^($hash->{statevals})$/) { elsif ($opt =~ /^($hash->{statevals})$/) {
my $cmd = $1; my $cmd = $1;
@ -275,8 +267,7 @@ sub HMCCUCHN_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'toggle') { elsif ($opt eq 'toggle') {
return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals})); return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals}));
@ -312,8 +303,7 @@ sub HMCCUCHN_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'pct') { elsif ($opt eq 'pct') {
return HMCCU_SetError ($hash, "Can't find LEVEL datapoint for device type $ccutype") return HMCCU_SetError ($hash, "Can't find LEVEL datapoint for device type $ccutype")
@ -362,8 +352,7 @@ sub HMCCUCHN_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'on-for-timer' || $opt eq 'on-till') { elsif ($opt eq 'on-for-timer' || $opt eq 'on-till') {
return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals})); return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals}));
@ -401,8 +390,7 @@ sub HMCCUCHN_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'clear') { elsif ($opt eq 'clear') {
my $rnexp = shift @$a; my $rnexp = shift @$a;
@ -423,14 +411,12 @@ sub HMCCUCHN_Set ($@)
} }
my $rc = HMCCU_RPCSetConfig ($hash, $ccuobj, $h); my $rc = HMCCU_RPCSetConfig ($hash, $ccuobj, $h);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'defaults') { elsif ($opt eq 'defaults') {
my $rc = HMCCU_SetDefaults ($hash); my $rc = HMCCU_SetDefaults ($hash);
return HMCCU_SetError ($hash, "HMCCU: No default attributes found") if ($rc == 0); return HMCCU_SetError ($hash, "HMCCU: No default attributes found") if ($rc == 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
else { else {
return "HMCCUCHN: Unknown argument $opt, choose one of ".$rocmds return "HMCCUCHN: Unknown argument $opt, choose one of ".$rocmds
@ -819,7 +805,7 @@ sub HMCCUCHN_Get ($@)
attr mydev ccureadingname 0.(LOWBAT|LOW_BAT):battery<br/> attr mydev ccureadingname 0.(LOWBAT|LOW_BAT):battery<br/>
# Add reading battery as a copy of readings LOWBAT and LOW_BAT.<br/> # Add reading battery as a copy of readings LOWBAT and LOW_BAT.<br/>
# Rename reading 4.SET_TEMPERATURE as desired-temp<br/> # Rename reading 4.SET_TEMPERATURE as desired-temp<br/>
attr mydev ccureadingname 0.(LOWBAT|LOW_BAT):+battery,1.SET_TEMPERATURE:desired-temp<br/> attr mydev ccureadingname 0.(LOWBAT|LOW_BAT):+battery;1.SET_TEMPERATURE:desired-temp<br/>
# Store values of readings n.PRESS_SHORT in new reading pressed.<br/> # Store values of readings n.PRESS_SHORT in new reading pressed.<br/>
# Value of pressed is 1/true if any button is pressed<br/> # Value of pressed is 1/true if any button is pressed<br/>
attr mydev ccureadingname [1-4].PRESSED_SHORT:+pressed attr mydev ccureadingname [1-4].PRESSED_SHORT:+pressed
@ -879,20 +865,18 @@ sub HMCCUCHN_Get ($@)
Optionally the name of the HomeMatic state reading can be specified at the beginning of Optionally the name of the HomeMatic state reading can be specified at the beginning of
the attribute in format =&lt;reading&gt;;. The default reading name is 'hmstate'. the attribute in format =&lt;reading&gt;;. The default reading name is 'hmstate'.
</li><br/> </li><br/>
<li><b>peer [&lt;datapoints&gt;:&lt;condition&gt;: <li><b>peer &lt;datapoints&gt;:&lt;condition&gt;:
{ccu:&lt;object&gt;=&lt;value&gt;|hmccu:&lt;object&gt;=&lt;value&gt;| {ccu:&lt;object&gt;=&lt;value&gt;|hmccu:&lt;object&gt;=&lt;value&gt;|
fhem:&lt;command&gt;}</b><br/> fhem:&lt;command&gt;}</b><br/>
Logically peer a datapoint of a HMCCUCHN or HMCCUDEV device with another device or any Logically peer datapoints of a HMCCUCHN or HMCCUDEV device with another device or any
FHEM command.<br/> FHEM command.<br/>
Parameter <i>datapoints</i> is a comma separated list of datapoints in format Parameter <i>datapoints</i> is a comma separated list of datapoints in format
<i>channelno.datapoint</i> which can trigger the action. If source device is of type HMCCUCHN <i>channelno.datapoint</i> which can trigger the action.<br/>
the parameter <i>channelno</i> is obsolete.<br/>
Parameter <i>condition</i> is a valid Perl expression which can contain Parameter <i>condition</i> is a valid Perl expression which can contain
<i>channelno.datapoint</i> names as variables. Variables must start with a '$' or a '%'. <i>channelno.datapoint</i> names as variables. Variables must start with a '$' or a '%'.
If a variable is preceded by a '$' the variable is substituted by the converted datapoint If a variable is preceded by a '$' the variable is substituted by the converted datapoint
value (i.e. "on" instead of "true"). If variable is preceded by a '%' the raw value value (i.e. "on" instead of "true"). If variable is preceded by a '%' the raw value
(i.e. "true") is used. If the special character is doubled the previous values will (i.e. "true") is used. If '$' or '%' is doubled the previous values will be used.<br/>
be used.<br/>
If the result of this operation is true, the action specified after the second colon If the result of this operation is true, the action specified after the second colon
is executed. Three types of actions are supported:<br/> is executed. Three types of actions are supported:<br/>
<b>hmccu</b>: Parameter <i>object</i> refers to a FHEM device/datapoint in format <b>hmccu</b>: Parameter <i>object</i> refers to a FHEM device/datapoint in format

View File

@ -4,7 +4,7 @@
# #
# $Id$ # $Id$
# #
# Version 4.1 # Version 4.1.001
# #
# (c) 2017 zap (zap01 <at> t-online <dot> de) # (c) 2017 zap (zap01 <at> t-online <dot> de)
# #
@ -157,18 +157,10 @@ sub HMCCUDEV_Define ($@)
# Parse optional command line parameters # Parse optional command line parameters
foreach my $arg (@$a) { foreach my $arg (@$a) {
if ($arg eq 'readonly') { if ($arg eq 'readonly') { $hash->{statevals} = $arg; }
$hash->{statevals} = $arg; elsif ($arg eq 'defaults') { HMCCU_SetDefaults ($hash); }
} elsif ($arg =~ /^[0-9]+$/) { $attr{$name}{statechannel} = $arg; }
elsif ($arg eq 'defaults') { else { return $usage; }
HMCCU_SetDefaults ($hash);
}
elsif ($arg =~ /^[0-9]+$/) {
$attr{$name}{statechannel} = $arg;
}
else {
return $usage;
}
} }
# Parse group options # Parse group options
@ -331,8 +323,7 @@ sub HMCCUDEV_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'control') { elsif ($opt eq 'control') {
return HMCCU_SetError ($hash, -12) if ($cc eq ''); return HMCCU_SetError ($hash, -12) if ($cc eq '');
@ -350,8 +341,7 @@ sub HMCCUDEV_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt =~ /^($hash->{statevals})$/) { elsif ($opt =~ /^($hash->{statevals})$/) {
my $cmd = $1; my $cmd = $1;
@ -369,8 +359,7 @@ sub HMCCUDEV_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'toggle') { elsif ($opt eq 'toggle') {
return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals})); return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals}));
@ -410,8 +399,7 @@ sub HMCCUDEV_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'pct') { elsif ($opt eq 'pct') {
return HMCCU_SetError ($hash, -11) if ($sc eq ''); return HMCCU_SetError ($hash, -11) if ($sc eq '');
@ -455,8 +443,7 @@ sub HMCCUDEV_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'on-for-timer' || $opt eq 'on-till') { elsif ($opt eq 'on-for-timer' || $opt eq 'on-till') {
return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals})); return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{statevals}));
@ -488,8 +475,7 @@ sub HMCCUDEV_Set ($@)
$rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue); $rc = HMCCU_SetDatapoint ($hash, $objname, $objvalue);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'clear') { elsif ($opt eq 'clear') {
my $rnexp = shift @$a; my $rnexp = shift @$a;
@ -513,14 +499,12 @@ sub HMCCUDEV_Set ($@)
my $rc = HMCCU_RPCSetConfig ($hash, $objname, $h); my $rc = HMCCU_RPCSetConfig ($hash, $objname, $h);
return HMCCU_SetError ($hash, $rc) if ($rc < 0); return HMCCU_SetError ($hash, $rc) if ($rc < 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
elsif ($opt eq 'defaults') { elsif ($opt eq 'defaults') {
my $rc = HMCCU_SetDefaults ($hash); my $rc = HMCCU_SetDefaults ($hash);
return HMCCU_SetError ($hash, "HMCCU: No default attributes found") if ($rc == 0); return HMCCU_SetError ($hash, "HMCCU: No default attributes found") if ($rc == 0);
HMCCU_SetState ($hash, "OK"); return HMCCU_SetState ($hash, "OK");
return undef;
} }
else { else {
return "HMCCUCHN: Unknown argument $opt, choose one of ".$rocmds return "HMCCUCHN: Unknown argument $opt, choose one of ".$rocmds
@ -619,7 +603,6 @@ sub HMCCUDEV_Get ($@)
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname); ($rc, $result) = HMCCU_GetDatapoint ($hash, $objname);
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"); HMCCU_SetState ($hash, "OK") if (exists ($hash->{STATE}) && $hash->{STATE} eq "Error");
return $ccureadings ? undef : $result; return $ccureadings ? undef : $result;
} }

View File

@ -4,7 +4,7 @@
# #
# $Id$ # $Id$
# #
# Version 0.96 beta # Version 0.96.001 beta
# #
# Thread based RPC Server module for HMCCU. # Thread based RPC Server module for HMCCU.
# #
@ -1901,8 +1901,10 @@ sub HMCCURPC_HandleConnection ($$$$)
$rpcsrv->{__daemon}->timeout ($thrpar->{acctimeout}); $rpcsrv->{__daemon}->timeout ($thrpar->{acctimeout});
while ($run) { while ($run) {
my $difftime = time()-$rpcsrv->{hmccu}{evttime}; if ($thrpar->{evttimeout} > 0) {
HMCCURPC_Write ($rpcsrv, "TO", $clkey, $difftime) if ($difftime >= $thrpar->{evttimeout}); my $difftime = time()-$rpcsrv->{hmccu}{evttime};
HMCCURPC_Write ($rpcsrv, "TO", $clkey, $difftime) if ($difftime >= $thrpar->{evttimeout});
}
# Next statement blocks for timeout seconds # Next statement blocks for timeout seconds
my $connection = $rpcsrv->{__daemon}->accept (); my $connection = $rpcsrv->{__daemon}->accept ();
@ -2757,6 +2759,10 @@ sub HMCCURPC_DecodeResponse ($)
<a name="HMCCURPCset"></a> <a name="HMCCURPCset"></a>
<b>Set</b><br/><br/> <b>Set</b><br/><br/>
<ul> <ul>
<li><b> set &lt;name&gt; rpcrequest &lt;port&gt; &lt;method&gt; [&lt;parameters&gt;]</b><br/>
Send RPC request to CCU. The result is displayed in FHEM browser window. Parameter
&lt;port&gt; is a valid RPC port (i.e. 2001 for BidCos).
</li><br/>
<li><b>set &lt;name&gt; rpcserver { on | off }</b><br/> <li><b>set &lt;name&gt; rpcserver { on | off }</b><br/>
Start or stop RPC server(s). This command is only available if expert mode is activated. Start or stop RPC server(s). This command is only available if expert mode is activated.
</li><br/> </li><br/>
@ -2791,7 +2797,7 @@ sub HMCCURPC_DecodeResponse ($)
</li><br/> </li><br/>
<li><b>rpcEventTimeout &lt;seconds&gt;</b><br/> <li><b>rpcEventTimeout &lt;seconds&gt;</b><br/>
Specify timeout for CCU events. Default is 600 seconds. If timeout occurs an event Specify timeout for CCU events. Default is 600 seconds. If timeout occurs an event
is triggered. is triggered. If set to 0 the timeout is ignored.
</li><br/> </li><br/>
<li><b>rpcInterfaces { BidCos-Wired, BidCos-RF, HmIP-RF, VirtualDevices, CUxD, Homegear }</b><br/> <li><b>rpcInterfaces { BidCos-Wired, BidCos-RF, HmIP-RF, VirtualDevices, CUxD, Homegear }</b><br/>
Select RPC interfaces. If attribute is missing the corresponding attribute of I/O device Select RPC interfaces. If attribute is missing the corresponding attribute of I/O device

View File

@ -4,7 +4,7 @@
# #
# $Id$ # $Id$
# #
# Version 4.1 # Version 4.1.001
# #
# Configuration parameters for HomeMatic devices. # Configuration parameters for HomeMatic devices.
# #
@ -255,9 +255,23 @@ use vars qw(%HMCCU_SCRIPTS);
_description => "Bewegungsmelder", _description => "Bewegungsmelder",
_channels => "1", _channels => "1",
ccureadingfilter => "(ILLUMINATION|MOTION)", ccureadingfilter => "(ILLUMINATION|MOTION)",
eventMap => "/datapoint MOTION_DETECTION_ACTIVE 1:detection-on/datapoint MOTION_DETECTION_ACTIVE 0:detection-off/",
statedatapoint => "MOTION", statedatapoint => "MOTION",
substitute => "MOTION!(0|false):no,(1|true):yes" substitute => "MOTION!(0|false):no,(1|true):yes"
}, },
"HmIP-SPI" => {
_description => "Anwesenheitssensor",
_channels => "1",
ccureadingfilter => "(ILLUMINATION|PRESENCE)",
controldatapoint => "PRESENCE_DETECTION_ACTIVE",
eventMap => "/datapoint RESET_PRESENCE 1:reset/datapoint PRESENCE_DETECTION_ACTIVE 1:detection-on/datapoint PRESENCE_DETECTION_ACTIVE 0:detection-off/",
hmstatevals => "SABOTAGE!(1|true):sabotage",
statedatapoint => "PRESENCE_DETECTION_STATE",
stripnumber => 1,
substitute => "PRESENCE_DETECTION_STATE!(0|false):no,(1|true):yes;PRESENCE_DETECTION_ACTIVE!(0|false):off,(1|true):on",
webCmd => "control",
widgetOverride => "control:uzsuToggle,off,on"
},
"HM-Sen-LI-O" => { "HM-Sen-LI-O" => {
_description => "Lichtsensor", _description => "Lichtsensor",
_channels => "1", _channels => "1",
@ -619,9 +633,22 @@ use vars qw(%HMCCU_SCRIPTS);
"HmIP-SMI" => { "HmIP-SMI" => {
_description => "Bewegungsmelder", _description => "Bewegungsmelder",
ccureadingfilter => "(ILLUMINATION|MOTION)", ccureadingfilter => "(ILLUMINATION|MOTION)",
eventMap => "/datapoint 1.MOTION_DETECTION_ACTIVE 1:detection-on/datapoint 1.MOTION_DETECTION_ACTIVE 0:detection-off/",
statedatapoint => "1.MOTION", statedatapoint => "1.MOTION",
substitute => "MOTION!(0|false):no,(1|true):yes" substitute => "MOTION!(0|false):no,(1|true):yes"
}, },
"HmIP-SPI" => {
_description => "Anwesenheitssensor",
ccureadingfilter => "(ILLUMINATION|PRESENCE)",
controldatapoint => "1.PRESENCE_DETECTION_ACTIVE",
eventMap => "/datapoint 1.RESET_PRESENCE 1:reset/datapoint 1.PRESENCE_DETECTION_ACTIVE 1:detection-on/datapoint 1.PRESENCE_DETECTION_ACTIVE 0:detection-off/",
hmstatevals => "SABOTAGE!(1|true):sabotage",
statedatapoint => "1.PRESENCE_DETECTION_STATE",
stripnumber => 1,
substitute => "PRESENCE_DETECTION_STATE!(0|false):no,(1|true):yes;PRESENCE_DETECTION_ACTIVE!(0|false):off,(1|true):on",
webCmd => "control",
widgetOverride => "control:uzsuToggle,off,on"
},
"HM-Sen-LI-O" => { "HM-Sen-LI-O" => {
_description => "Lichtsensor", _description => "Lichtsensor",
ccureadingfilter => "LUX", ccureadingfilter => "LUX",