mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-04 22:19:38 +00:00
HMCCU: Firmware downloads, advanced scripting
git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@14103 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
ca9b3b3fdb
commit
5994d53ce9
1
CHANGED
1
CHANGED
@ -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.
|
||||
- update: 88_HMCCU: Homematic firmware download, advanced scripting
|
||||
- feature: 98_TRAFFIC: v1.3.2, stroke styles, warnings reduced, bugfix
|
||||
- update: 98_DOIFtools: more precise regexp for INITIALIZED event because
|
||||
there is more than one initialisation event now
|
||||
|
719
FHEM/88_HMCCU.pm
719
FHEM/88_HMCCU.pm
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.0
|
||||
# Version 4.0.001
|
||||
#
|
||||
# (c) 2017 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
@ -66,7 +66,6 @@ sub HMCCUCHN_Define ($@);
|
||||
sub HMCCUCHN_Set ($@);
|
||||
sub HMCCUCHN_Get ($@);
|
||||
sub HMCCUCHN_Attr ($@);
|
||||
sub HMCCUCHN_SetError ($$);
|
||||
|
||||
##################################################
|
||||
# Initialize module
|
||||
@ -286,7 +285,7 @@ sub HMCCUCHN_Set ($@)
|
||||
|
||||
my $objname = $ccuif.'.'.$ccuaddr.'.'.$sd;
|
||||
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname);
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
|
||||
|
||||
my $objvalue = '';
|
||||
my $st = 0;
|
||||
@ -487,7 +486,7 @@ sub HMCCUCHN_Get ($@)
|
||||
|
||||
my $objname = $ccuif.'.'.$ccuaddr.'.'.$sd;
|
||||
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname);
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
|
||||
return $ccureadings ? undef : $result;
|
||||
}
|
||||
elsif ($opt eq 'datapoint') {
|
||||
@ -500,7 +499,7 @@ sub HMCCUCHN_Get ($@)
|
||||
|
||||
$objname = $ccuif.'.'.$ccuaddr.'.'.$objname;
|
||||
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname);
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
|
||||
return $ccureadings ? undef : $result;
|
||||
}
|
||||
elsif ($opt eq 'update') {
|
||||
@ -536,7 +535,7 @@ sub HMCCUCHN_Get ($@)
|
||||
$par = '.*' if (!defined ($par));
|
||||
|
||||
my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "getParamset", $par);
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
|
||||
return $ccureadings ? undef : $res;
|
||||
}
|
||||
elsif ($opt eq 'configlist') {
|
||||
@ -551,7 +550,7 @@ sub HMCCUCHN_Get ($@)
|
||||
$par = '.*' if (!defined ($par));
|
||||
|
||||
my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "listParamset", $par);
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
|
||||
return $res;
|
||||
}
|
||||
elsif ($opt eq 'configdesc') {
|
||||
@ -562,7 +561,7 @@ sub HMCCUCHN_Get ($@)
|
||||
}
|
||||
|
||||
my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "getParamsetDescription", undef);
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
|
||||
return $res;
|
||||
}
|
||||
elsif ($opt eq 'defaults') {
|
||||
@ -582,36 +581,6 @@ sub HMCCUCHN_Get ($@)
|
||||
}
|
||||
}
|
||||
|
||||
#####################################
|
||||
# Set error status
|
||||
#####################################
|
||||
|
||||
sub HMCCUCHN_SetError ($$)
|
||||
{
|
||||
my ($hash, $text) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $msg;
|
||||
my %errlist = (
|
||||
-1 => 'Channel name or address invalid',
|
||||
-2 => 'Execution of CCU script failed',
|
||||
-3 => 'Cannot detect IO device',
|
||||
-4 => 'Device deleted in CCU',
|
||||
-5 => 'No response from CCU',
|
||||
-6 => 'Update of readings disabled. Set attribute ccureadings first'
|
||||
);
|
||||
|
||||
if (exists ($errlist{$text})) {
|
||||
$msg = $errlist{$text};
|
||||
}
|
||||
else {
|
||||
$msg = $text;
|
||||
}
|
||||
|
||||
$msg = "HMCCUCHN: ".$name." ". $msg;
|
||||
readingsSingleUpdate ($hash, "state", "Error", 1);
|
||||
Log3 $name, 1, $msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.0
|
||||
# Version 4.0.001
|
||||
#
|
||||
# (c) 2017 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
@ -383,7 +383,7 @@ sub HMCCUDEV_Set ($@)
|
||||
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname);
|
||||
Log3 $name, 2, "HMCCU: set toggle: GetDatapoint returned $rc, $result"
|
||||
if ($ccuflags =~ /trace/);
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
|
||||
|
||||
my $objvalue = '';
|
||||
my $st = 0;
|
||||
@ -588,7 +588,7 @@ sub HMCCUDEV_Get ($@)
|
||||
my $objname = $ccuif.'.'.$ccuaddr.':'.$sc.'.'.$sd;
|
||||
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname);
|
||||
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
|
||||
return $ccureadings ? undef : $result;
|
||||
}
|
||||
elsif ($opt eq 'datapoint') {
|
||||
@ -611,7 +611,7 @@ sub HMCCUDEV_Get ($@)
|
||||
$objname = $ccuif.'.'.$ccuaddr.':'.$objname;
|
||||
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname);
|
||||
|
||||
return HMCCU_SetError ($hash, $rc) 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 $ccureadings ? undef : $result;
|
||||
@ -663,7 +663,7 @@ sub HMCCUDEV_Get ($@)
|
||||
$par = '.*' if (!defined ($par));
|
||||
|
||||
my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "getParamset", $par);
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
|
||||
HMCCU_SetState ($hash, "OK") if (exists ($hash->{STATE}) && $hash->{STATE} eq "Error");
|
||||
return $ccureadings ? undef : $res;
|
||||
}
|
||||
@ -681,7 +681,7 @@ sub HMCCUDEV_Get ($@)
|
||||
$par = '.*' if (!defined ($par));
|
||||
|
||||
my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "listParamset", $par);
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
|
||||
HMCCU_SetState ($hash, "OK") if (exists ($hash->{STATE}) && $hash->{STATE} eq "Error");
|
||||
return $res;
|
||||
}
|
||||
@ -700,7 +700,7 @@ sub HMCCUDEV_Get ($@)
|
||||
}
|
||||
|
||||
my ($rc, $res) = HMCCU_RPCGetConfig ($hash, $ccuobj, "getParamsetDescription", undef);
|
||||
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
return HMCCU_SetError ($hash, $rc, $res) if ($rc < 0);
|
||||
HMCCU_SetState ($hash, "OK") if (exists ($hash->{STATE}) && $hash->{STATE} eq "Error");
|
||||
return $res;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 0.94 beta
|
||||
# Version 0.95 beta
|
||||
#
|
||||
# Thread based RPC Server module for HMCCU.
|
||||
#
|
||||
@ -40,7 +40,7 @@ use SetExtensions;
|
||||
######################################################################
|
||||
|
||||
# HMCCURPC version
|
||||
my $HMCCURPC_VERSION = '0.94 beta';
|
||||
my $HMCCURPC_VERSION = '0.95 beta';
|
||||
|
||||
# Maximum number of events processed per call of Read()
|
||||
my $HMCCURPC_MAX_EVENTS = 50;
|
||||
@ -162,7 +162,7 @@ sub HMCCURPC_StartRPCServer ($);
|
||||
sub HMCCURPC_CleanupThreads ($$$);
|
||||
sub HMCCURPC_CleanupThreadIO ($);
|
||||
sub HMCCURPC_TerminateThreads ($$);
|
||||
sub HMCCURPC_CheckThreadState ($$$);
|
||||
sub HMCCURPC_CheckThreadState ($$$$);
|
||||
sub HMCCURPC_IsRPCServerRunning ($);
|
||||
sub HMCCURPC_Housekeeping ($);
|
||||
sub HMCCURPC_StopRPCServer ($);
|
||||
@ -234,7 +234,7 @@ sub HMCCURPC_Initialize ($)
|
||||
$hash->{parseParams} = 1;
|
||||
|
||||
$hash->{AttrList} = "rpcInterfaces:multiple-strict,".join(',',sort keys %HMCCURPC_RPC_PORT).
|
||||
" ccuflags:multiple-strict,expert rpcMaxEvents rpcQueueSize rpcTriggerTime".
|
||||
" ccuflags:multiple-strict,expert,keepThreads rpcMaxEvents rpcQueueSize rpcTriggerTime".
|
||||
" rpcServer:on,off rpcServerAddr rpcServerPort rpcWriteTimeout rpcAcceptTimeout".
|
||||
" rpcConnTimeout rpcWaitTime rpcStatistics ".
|
||||
$readingFnAttributes;
|
||||
@ -352,7 +352,7 @@ sub HMCCURPC_Attr ($@)
|
||||
my $rc = 0;
|
||||
|
||||
if ($attrname eq 'rpcInterfaces') {
|
||||
my ($run, $all) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ALL, 'running');
|
||||
my ($run, $all) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ALL, 'running', undef);
|
||||
return 'Stop RPC server before modifying rpcInterfaces' if ($run > 0);
|
||||
}
|
||||
|
||||
@ -415,26 +415,26 @@ sub HMCCURPC_Set ($@)
|
||||
|
||||
return HMCCURPC_SetError ($hash, "RPC request failed") if (!defined ($response));
|
||||
|
||||
my $result = '';
|
||||
if (ref ($response) eq 'ARRAY') {
|
||||
$result = join "\n", @$response;
|
||||
}
|
||||
elsif (ref ($response) eq 'HASH') {
|
||||
foreach my $k (keys %$response) {
|
||||
$result .= "$k = ".$response->{$k}."\n";
|
||||
}
|
||||
}
|
||||
elsif (ref ($response) eq 'SCALAR') {
|
||||
$result = $$response;
|
||||
}
|
||||
else {
|
||||
if (ref ($response)) {
|
||||
$result = "Unknown response from CCU of type ".ref ($response);
|
||||
}
|
||||
else {
|
||||
$result = ($response eq '') ? 'Request returned void' : $response;
|
||||
}
|
||||
}
|
||||
my $result = HMCCU_RefToString ($response);
|
||||
# if (ref ($response) eq 'ARRAY') {
|
||||
# $result = join "\n", @$response;
|
||||
# }
|
||||
# elsif (ref ($response) eq 'HASH') {
|
||||
# foreach my $k (keys %$response) {
|
||||
# $result .= "$k = ".$response->{$k}."\n";
|
||||
# }
|
||||
# }
|
||||
# elsif (ref ($response) eq 'SCALAR') {
|
||||
# $result = $$response;
|
||||
# }
|
||||
# else {
|
||||
# if (ref ($response)) {
|
||||
# $result = "Unknown response from CCU of type ".ref ($response);
|
||||
# }
|
||||
# else {
|
||||
# $result = ($response eq '') ? 'Request returned void' : $response;
|
||||
# }
|
||||
# }
|
||||
|
||||
return $result;
|
||||
}
|
||||
@ -470,6 +470,8 @@ sub HMCCURPC_Get ($@)
|
||||
my ($hash, $a, $h) = @_;
|
||||
my $name = shift @$a;
|
||||
my $opt = shift @$a;
|
||||
|
||||
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
|
||||
my $options = "rpcevents:noArg rpcstate:noArg";
|
||||
|
||||
if ($opt ne 'rpcstate' && HMCCURPC_IsRPCStateBlocking ($hash)) {
|
||||
@ -866,8 +868,8 @@ sub HMCCURPC_ProcessEvent ($$)
|
||||
if ($t[0] == $rh->{$clkey}{tid}) {
|
||||
Log3 $name, 1, "HMCCURPC: Received SL event. RPC server $clkey enters server loop";
|
||||
$rh->{$clkey}{state} = $clkey eq 'DATA' ? 'running' : 'working';
|
||||
my ($run, $alld) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_DATA, "running");
|
||||
my ($work, $alls) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_SERVER, 'working');
|
||||
my ($run, $alld) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_DATA, 'running', undef);
|
||||
my ($work, $alls) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_SERVER, 'working', undef);
|
||||
if ($work == $alls && $run == $alld) {
|
||||
Log3 $name, 1, "HMCCURPC: All threads working";
|
||||
HMCCURPC_RegisterCallback ($hash);
|
||||
@ -893,7 +895,7 @@ sub HMCCURPC_ProcessEvent ($$)
|
||||
$rh->{$clkey}{state} = "running";
|
||||
|
||||
# Set binary RPC interfaces to 'running' if all ascii interfaces are in state 'running'
|
||||
my ($runa, $alla) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ASCII, 'running');
|
||||
my ($runa, $alla) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ASCII, 'running', undef);
|
||||
if ($runa == $alla) {
|
||||
foreach my $sn (keys %{$rh}) {
|
||||
$rh->{$sn}{state} = "running"
|
||||
@ -902,7 +904,7 @@ sub HMCCURPC_ProcessEvent ($$)
|
||||
}
|
||||
|
||||
# Check if all RPC servers were initialized. Set overall status
|
||||
my ($run, $all) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ALL, 'running');
|
||||
my ($run, $all) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ALL, 'running', undef);
|
||||
if ($run == $all) {
|
||||
$hash->{hmccu}{rpcstarttime} = 0;
|
||||
HMCCURPC_SetRPCState ($hash, "running", "All RPC servers running");
|
||||
@ -934,17 +936,16 @@ sub HMCCURPC_ProcessEvent ($$)
|
||||
if ($clkey ne 'DATA') {
|
||||
($stopped, $all) = HMCCURPC_CleanupThreads ($hash, $HMCCURPC_THREAD_SERVER, 'stopped');
|
||||
if ($stopped == $all) {
|
||||
# Terminate data processing thread
|
||||
# Terminate data processing thread if all server threads stopped
|
||||
Log3 $name, 2, "HMCCURPC: All RPC servers stopped. Terminating data processing thread";
|
||||
HMCCURPC_TerminateThreads ($hash, $HMCCURPC_THREAD_DATA);
|
||||
sleep (1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
# Vielleicht besser außerhalb von Read() löschen
|
||||
HMCCURPC_CleanupThreadIO ($hash);
|
||||
($stopped, $all) = HMCCURPC_CleanupThreads ($hash, $HMCCURPC_THREAD_DATA, '.*');
|
||||
if ($stopped == $all) {
|
||||
HMCCURPC_CleanupThreadIO ($hash);
|
||||
HMCCURPC_ResetRPCState ($hash, "OK");
|
||||
RemoveInternalTimer ($hash);
|
||||
Log3 $name, 1, "HMCCURPC: All threads stopped";
|
||||
@ -1159,8 +1160,6 @@ sub HMCCURPC_DeRegisterCallback ($)
|
||||
if (exists ($rpchash->{cburl}) && $rpchash->{cburl} ne '') {
|
||||
Log3 $name, 1, "HMCCURPC: Deregistering RPC server ".$rpchash->{cburl}.
|
||||
" with ID $clkey at ".$rpchash->{clurl};
|
||||
# my $rpcclient = RPC::XML::Client->new ($rpchash->{clurl});
|
||||
# $rpcclient->send_request ("init", $rpchash->{cburl});
|
||||
if (HMCCURPC_IsAscRPCPort ($rpchash->{port})) {
|
||||
HMCCURPC_SendRequest ($hash, $rpchash->{port}, "init", $rpchash->{cburl});
|
||||
}
|
||||
@ -1406,7 +1405,7 @@ sub HMCCURPC_StartRPCServer ($)
|
||||
sleep (1);
|
||||
|
||||
# Cleanup if one or more threads are not initialized (ignore thread state)
|
||||
my ($run, $all) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ALL, '.*');
|
||||
my ($run, $all) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ALL, '.*', undef);
|
||||
if ($run != $all) {
|
||||
Log3 $name, 0, "HMCCURPC: Only $run from $all threads are running. Cleaning up";
|
||||
HMCCURPC_Housekeeping ($hash);
|
||||
@ -1439,8 +1438,8 @@ sub HMCCURPC_CleanupThreadIO ($)
|
||||
my $pid = $$;
|
||||
if (exists ($selectlist{"RPC.$name.$pid"})) {
|
||||
Log3 $name, 2, "HMCCURPC: Stop I/O handling";
|
||||
delete $hash->{FD};
|
||||
delete $selectlist{"RPC.$name.$pid"};
|
||||
delete $hash->{FD} if (defined ($hash->{FD}));
|
||||
}
|
||||
if (defined ($hash->{hmccu}{sockchild})) {
|
||||
Log3 $name, 2, "HMCCURPC: Close child socket";
|
||||
@ -1498,6 +1497,8 @@ sub HMCCURPC_CleanupThreads ($$$)
|
||||
my ($hash, $mode, $state) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
|
||||
|
||||
my $count = 0;
|
||||
my $all = 0;
|
||||
|
||||
@ -1515,9 +1516,15 @@ sub HMCCURPC_CleanupThreads ($$$)
|
||||
" still running. Can't delete it";
|
||||
next;
|
||||
}
|
||||
if ($hash->{hmccu}{rpc}{$clkey}{state} eq 'stopped' && $ccuflags !~ /keepThreads/) {
|
||||
Log3 $name, 2, "HMCCURPC: Thread $clkey with TID=".$thr->tid ().
|
||||
" has been stopped. Deleting it";
|
||||
# undef $hash->{hmccu}{rpc}{$clkey}{child};
|
||||
undef $hash->{hmccu}{rpc}{$clkey}{child};
|
||||
}
|
||||
else {
|
||||
Log3 $name, 2, "HMCCURPC: Thread $clkey with TID=".$thr->tid ().
|
||||
" is in state ".$hash->{hmccu}{rpc}{$clkey}{state}.". Can't delete it";
|
||||
}
|
||||
# delete $hash->{hmccu}{rpc}{$clkey};
|
||||
}
|
||||
}
|
||||
@ -1531,21 +1538,22 @@ sub HMCCURPC_CleanupThreads ($$$)
|
||||
# Count threads in specified state.
|
||||
# Parameter state is a regular expression.
|
||||
# Parameter mode specifies which threads should be counted:
|
||||
# 1 - Count data processing thread
|
||||
# 2 - Count server threads
|
||||
# 3 - Count all threads
|
||||
# If state is empty thread state is ignored and only running threads
|
||||
# are counted by calling thread function is_running().
|
||||
# Return number of threads in specified state and total number of
|
||||
# threads.
|
||||
# threads. Also return IDs of running threads if parameter tids is
|
||||
# defined and parameter state is 'running' or '.*'.
|
||||
######################################################################
|
||||
|
||||
sub HMCCURPC_CheckThreadState ($$$)
|
||||
sub HMCCURPC_CheckThreadState ($$$$)
|
||||
{
|
||||
my ($hash, $mode, $state) = @_;
|
||||
my ($hash, $mode, $state, $tids) = @_;
|
||||
my $count = 0;
|
||||
my $all = 0;
|
||||
|
||||
$mode = $HMCCURPC_THREAD_ALL if (!defined ($mode));
|
||||
$state = '' if (!defined ($state));
|
||||
|
||||
foreach my $clkey (keys %{$hash->{hmccu}{rpc}}) {
|
||||
next if ($hash->{hmccu}{rpc}{$clkey}{state} eq 'inactive');
|
||||
next if (!($hash->{hmccu}{rpc}{$clkey}{type} & $mode));
|
||||
@ -1553,8 +1561,11 @@ sub HMCCURPC_CheckThreadState ($$$)
|
||||
if ($state eq 'running' || $state eq '.*') {
|
||||
next if (!exists ($hash->{hmccu}{rpc}{$clkey}{child}));
|
||||
my $thr = $hash->{hmccu}{rpc}{$clkey}{child};
|
||||
$count++ if (defined ($thr) && $thr->is_running () &&
|
||||
$hash->{hmccu}{rpc}{$clkey}{state} =~ /$state/);
|
||||
if (defined ($thr) && $thr->is_running () &&
|
||||
($state eq '' || $hash->{hmccu}{rpc}{$clkey}{state} =~ /$state/)) {
|
||||
$count++;
|
||||
push (@$tids, $thr->tid()) if (defined ($tids));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$count++ if ($hash->{hmccu}{rpc}{$clkey}{state} =~ /$state/);
|
||||
@ -1574,7 +1585,7 @@ sub HMCCURPC_IsRPCServerRunning ($)
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
Log3 $name, 2, "HMCCURPC: Checking if all threads are running";
|
||||
my ($run, $all) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ALL, 'running');
|
||||
my ($run, $all) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ALL, 'running', undef);
|
||||
if ($run != $all) {
|
||||
Log3 $name, 1, "HMCCURPC: Only $run of $all threads are running. Cleaning up";
|
||||
HMCCURPC_Housekeeping ($hash);
|
||||
@ -1597,7 +1608,10 @@ sub HMCCURPC_Housekeeping ($)
|
||||
|
||||
Log3 $name, 1, "HMCCURPC: Housekeeping called. Cleaning up RPC environment";
|
||||
|
||||
# I/O Handling beenden
|
||||
# Deregister callback URLs in CCU
|
||||
HMCCURPC_DeRegisterCallback ($hash);
|
||||
|
||||
# Stop I/O handling
|
||||
HMCCURPC_CleanupThreadIO ($hash);
|
||||
|
||||
my $count = HMCCURPC_TerminateThreads ($hash, $HMCCURPC_THREAD_ALL);
|
||||
@ -1623,7 +1637,7 @@ sub HMCCURPC_StopRPCServer ($)
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my ($run, $all) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ALL, 'running');
|
||||
my ($run, $all) = HMCCURPC_CheckThreadState ($hash, $HMCCURPC_THREAD_ALL, 'running', undef);
|
||||
if ($run > 0) {
|
||||
HMCCURPC_SetRPCState ($hash, "stopping", "Found $run threads. Stopping ...");
|
||||
|
||||
@ -1889,6 +1903,8 @@ sub HMCCURPC_HandleConnection ($$$$)
|
||||
foreach my $et (@eventtypes) {
|
||||
Log3 $name, 4, "CCURPC: $clkey event type = $et: ".$rpcsrv->{hmccu}{rec}{$et};
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
@ -2085,9 +2101,9 @@ sub HMCCURPC_HexDump ($$)
|
||||
# Callback functions
|
||||
######################################################################
|
||||
|
||||
##################################################
|
||||
######################################################################
|
||||
# Callback for new devices
|
||||
##################################################
|
||||
######################################################################
|
||||
|
||||
sub HMCCURPC_NewDevicesCB ($$$)
|
||||
{
|
||||
@ -2095,15 +2111,17 @@ sub HMCCURPC_NewDevicesCB ($$$)
|
||||
my $name = $server->{hmccu}{name};
|
||||
my $devcount = scalar (@$a);
|
||||
|
||||
Log3 $name, 2, "CCURPC: $cb NewDevice received $devcount device specifications";
|
||||
Log3 $name, 2, "CCURPC: $cb NewDevice received $devcount device and channel specifications";
|
||||
foreach my $dev (@$a) {
|
||||
my $msg = '';
|
||||
if ($dev->{ADDRESS} =~ /:[0-9]{1,2}$/) {
|
||||
$msg = "C|".$dev->{ADDRESS}."|".$dev->{TYPE}."|".$dev->{VERSION}."|null|null";
|
||||
}
|
||||
else {
|
||||
# Wired devices do not have a RX_MODE attribute
|
||||
my $rx = exists ($dev->{RX_MODE}) ? $dev->{RX_MODE} : 'null';
|
||||
$msg = "D|".$dev->{ADDRESS}."|".$dev->{TYPE}."|".$dev->{VERSION}."|".
|
||||
$dev->{FIRMWARE}."|".$dev->{RX_MODE};
|
||||
$dev->{FIRMWARE}."|".$rx;
|
||||
}
|
||||
HMCCURPC_Write ($server, "ND", $cb, $msg);
|
||||
}
|
||||
@ -2727,6 +2745,7 @@ sub HMCCURPC_DecodeResponse ($)
|
||||
<li><b>ccuflags { expert }</b><br/>
|
||||
Set flags for controlling device behaviour. Meaning of flags is:<br/>
|
||||
expert - Activate expert mode<br/>
|
||||
keepThreads - Do not delete thread objects after RPC server has been stopped<br/>
|
||||
</li><br/>
|
||||
<li><b>rpcAcceptTimeout <seconds></b><br/>
|
||||
Specify timeout for accepting incoming connections. Default is 1 second. Increase this
|
||||
|
@ -4,17 +4,19 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.0
|
||||
# Version 4.0.001
|
||||
#
|
||||
# Configuration parameters for Homematic devices.
|
||||
# Configuration parameters for HomeMatic devices.
|
||||
#
|
||||
# (c) 2016 zap (zap01 <at> t-online <dot> de)
|
||||
# (c) 2017 by zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
# Datapoints LOWBAT, LOW_BAT, UNREACH, ERROR.*, SABOTAGE and FAULT.* must
|
||||
# not be specified in ccureadingfilter. They are always stored as readings.
|
||||
# Datapoints LOWBAT, LOW_BAT, UNREACH, ERROR.*, SABOTAGE and FAULT.*
|
||||
# must not be specified in attribute ccureadingfilter. They are always
|
||||
# stored as readings.
|
||||
# Datapoints LOWBAT, LOW_BAT and UNREACH must not be specified in
|
||||
# substitute because they are substituted by default.
|
||||
# See attributes ccudef-readingname and ccudef-substitute in module HMCCU.
|
||||
# attribute substitute because they are substituted by default.
|
||||
# See also documentation of attributes ccudef-readingname and
|
||||
# ccudef-substitute in module HMCCU.
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
@ -135,6 +137,14 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
statevals => "press:true",
|
||||
substitute => "PRESS_SHORT,PRESS_LONG,PRESS_CONT!(1|true):pressed,(0|false):released;PRESS_LONG_RELEASE!(0|false):no,(1|true):yes"
|
||||
},
|
||||
"HM-SwI-3-FM" => {
|
||||
_description => "Funk-Schalterschnittstelle",
|
||||
_channels => "1,2,3",
|
||||
ccureadingfilter => "PRESS",
|
||||
statedatapoint => "PRESS",
|
||||
statevals => "press:true",
|
||||
substitute => "PRESS!(1|true):pressed,(0|false):released"
|
||||
},
|
||||
"HM-LC-Sw1PBU-FM" => {
|
||||
_description => "Unterputz Schaltaktor für Markenschalter",
|
||||
_channels => "1",
|
||||
@ -154,6 +164,14 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
statevals => "on:true,off:false",
|
||||
substitute => "STATE!(1|true):on,(0|false):off"
|
||||
},
|
||||
"HM-MOD-Re-8" => {
|
||||
_description => "8 Kanal Empfangsmodul",
|
||||
_channels => "1,2,3,4,5,6,7,8",
|
||||
ccureadingfilter => "(STATE|WORKING)",
|
||||
statedatapoint => "STATE",
|
||||
statevals => "on:true,off:false",
|
||||
substitute => "STATE!(1|true):on,(0|false):off;WORKING!(1|true):yes,(0|false):no"
|
||||
},
|
||||
"HM-LC-Sw1-Pl|HM-LC-Sw1-Pl-2|HM-LC-Sw1-SM|HM-LC-Sw1-FM|HM-LC-Sw1-PB-FM" => {
|
||||
_description => "1 Kanal Funk-Schaltaktor",
|
||||
_channels => "1",
|
||||
@ -200,6 +218,14 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
statedatapoint => "TEMPERATURE",
|
||||
stripnumber => 1
|
||||
},
|
||||
"HM-WDS100-C6-O-2" => {
|
||||
_description => "Funk-Kombisensor",
|
||||
_channels => "1",
|
||||
ccureadingfilter => "(HUMIDITY|TEMPERATURE|WIND|RAIN|SUNSHINE|BRIGHTNESS)",
|
||||
statedatapoint => "TEMPERATURE",
|
||||
stripnumber => 1,
|
||||
substitute => "RAINING!(1|true):yes,(0|false):no"
|
||||
},
|
||||
"HM-Sec-MD|HM-Sec-MDIR|HM-Sec-MDIR-2|HM-Sec-MDIR-3" => {
|
||||
_description => "Bewegungsmelder",
|
||||
_channels => "1",
|
||||
@ -421,6 +447,12 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
ccureadingfilter => "PRESS",
|
||||
substitute => "PRESS_SHORT,PRESS_LONG,PRESS_CONT!(1|true):pressed,(0|false):released;PRESS_LONG_RELEASE!(0|false):no,(1|true):yes"
|
||||
},
|
||||
"HM-SwI-3-FM" => {
|
||||
_description => "Funk-Schalterschnittstelle",
|
||||
ccureadingfilter => "PRESS",
|
||||
statevals => "press:true",
|
||||
substitute => "PRESS!(1|true):pressed,(0|false):released"
|
||||
},
|
||||
"HM-LC-Sw1PBU-FM" => {
|
||||
_description => "Unterputz Schaltaktor für Markenschalter",
|
||||
ccureadingfilter => "STATE",
|
||||
@ -437,6 +469,12 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
statevals => "on:true,off:false",
|
||||
substitute => "STATE!(1|true):on,(0|false):off"
|
||||
},
|
||||
"HM-MOD-Re-8" => {
|
||||
_description => "8 Kanal Empfangsmodul",
|
||||
ccureadingfilter => "(STATE|WORKING)",
|
||||
statevals => "on:true,off:false",
|
||||
substitute => "STATE!(1|true):on,(0|false):off;WORKING!(1|true):yes,(0|false):no"
|
||||
},
|
||||
"HM-LC-Bl1PBU-FM|HM-LC-Bl1-FM|HM-LC-Bl1-SM|HM-LC-BlX|HM-LC-Bl1-SM-2|HM-LC-Bl1-FM-2" => {
|
||||
_description => "Jalousienaktor",
|
||||
ccureadingfilter => "(LEVEL|INHIBIT|DIRECTION|WORKING)",
|
||||
@ -508,6 +546,13 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
statedatapoint => "1.TEMPERATURE",
|
||||
stripnumber => 1
|
||||
},
|
||||
"HM-WDS100-C6-O-2" => {
|
||||
_description => "Funk-Kombisensor",
|
||||
ccureadingfilter => "(HUMIDITY|TEMPERATURE|WIND|RAIN|SUNSHINE|BRIGHTNESS)",
|
||||
statedatapoint => "1.TEMPERATURE",
|
||||
stripnumber => 1,
|
||||
substitute => "RAINING!(1|true):yes,(0|false):no"
|
||||
},
|
||||
"HM-ES-TX-WM" => {
|
||||
_description => "Energiezaehler Sensor",
|
||||
ccureadingfilter => "(ENERGY_COUNTER|POWER)"
|
||||
@ -640,60 +685,259 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
);
|
||||
|
||||
######################################################################
|
||||
# Homematic scripts
|
||||
# Homematic scripts.
|
||||
# Scripts can be executed via HMCCU set command 'hmscript'. Script
|
||||
# name must be preceeded by a '!'.
|
||||
# Example:
|
||||
# set mydev hmscript !CreateStringVariable MyVar test "Test variable"
|
||||
######################################################################
|
||||
|
||||
%HMCCU_SCRIPTS = (
|
||||
"CreateVariable" => {
|
||||
_description => "Create CCU system variable of type STRING, NUMBER, BOOL or LIST",
|
||||
_pardesc => "Type, Name, Unit, Init, Desc [, { Min, Max | Val1, Val2 | ValList } ]",
|
||||
"ActivateProgram" => {
|
||||
description => "Activate or deactivate a CCU program",
|
||||
syntax => "name, mode",
|
||||
parameters => 2,
|
||||
code => qq(
|
||||
object oPR = dom.GetObject("\$name");
|
||||
if (oPR) {
|
||||
oPR.Active(\$mode);
|
||||
}
|
||||
)
|
||||
},
|
||||
"CreateStringVariable" => {
|
||||
description => "Create CCU system variable of type STRING",
|
||||
syntax => "name, init, desc",
|
||||
parameters => 3,
|
||||
code => qq(
|
||||
object oSV = dom.GetObject("\$name");
|
||||
if (!oSV){
|
||||
object oSysVars = dom.GetObject(ID_SYSTEM_VARIABLES);
|
||||
oSV = dom.CreateObject(OT_VARDP);
|
||||
oSysVars.Add(svObj.ID());
|
||||
oSV.Name("\$name");
|
||||
oSV.ValueType(ivtString);
|
||||
oSV.ValueSubType(istChar8859);
|
||||
oSV.DPInfo("\$desc");
|
||||
oSV.ValueUnit("");
|
||||
oSV.State("\$init");
|
||||
oSV.Internal(false);
|
||||
oSV.Visible(true);
|
||||
dom.RTUpdate(false);
|
||||
}
|
||||
else {
|
||||
oSV.State("\$init");
|
||||
}
|
||||
)
|
||||
},
|
||||
"CreateNumericVariable" => {
|
||||
description => "Create CCU system variable of type FLOAT",
|
||||
syntax => "name, unit, init, desc, min, max",
|
||||
parameters => 6,
|
||||
code => qq(
|
||||
object oSV = dom.GetObject("\$name");
|
||||
if (!oSV){
|
||||
object oSysVars = dom.GetObject(ID_SYSTEM_VARIABLES);
|
||||
oSV = dom.CreateObject(OT_VARDP);
|
||||
oSysVars.Add(svObj.ID());
|
||||
oSV.Name("\$name");
|
||||
oSV.ValueType(ivtFloat);
|
||||
oSV.ValueSubType(istGeneric);
|
||||
oSV.ValueMin(\$min);
|
||||
oSV.ValueMax(\$max);
|
||||
oSV.DPInfo("\$desc");
|
||||
oSV.ValueUnit("\$unit");
|
||||
oSV.State("\$init");
|
||||
oSV.Internal(false);
|
||||
oSV.Visible(true);
|
||||
dom.RTUpdate(false);
|
||||
}
|
||||
else {
|
||||
oSV.State("\$init");
|
||||
}
|
||||
)
|
||||
},
|
||||
"CreateBoolVariable" => {
|
||||
description => "Create CCU system variable of type BOOL",
|
||||
syntax => "name, init, desc, value1, value2",
|
||||
parameters => 5,
|
||||
code => qq(
|
||||
object oSV = dom.GetObject("\$name");
|
||||
if (!oSV){
|
||||
object oSysVars = dom.GetObject(ID_SYSTEM_VARIABLES);
|
||||
oSV = dom.CreateObject(OT_VARDP);
|
||||
oSysVars.Add(svObj.ID());
|
||||
oSV.Name("\$name");
|
||||
oSV.ValueType(ivtBinary);
|
||||
oSV.ValueSubType(istBool);
|
||||
oSV.ValueName0("\$value1");
|
||||
oSV.ValueName1("\$value2");
|
||||
oSV.DPInfo("\$desc");
|
||||
oSV.State("\$init");
|
||||
dom.RTUpdate(false);
|
||||
}
|
||||
else {
|
||||
oSV.State("\$init");
|
||||
}
|
||||
)
|
||||
},
|
||||
"CreateListVariable" => {
|
||||
description => "Create CCU system variable of type LIST",
|
||||
syntax => "name, unit, init, desc, list",
|
||||
parameters => 5,
|
||||
code => qq(
|
||||
object oSV = dom.GetObject("p2");
|
||||
if (!oSV){
|
||||
object oSysVars = dom.GetObject(ID_SYSTEM_VARIABLES);
|
||||
oSV = dom.CreateObject(OT_VARDP);
|
||||
oSysVars.Add(svObj.ID());
|
||||
oSV.Name("p2");
|
||||
if ("p1" = "STRING") {
|
||||
oSV.ValueType(ivtString);
|
||||
oSV.ValueSubType(istChar8859);
|
||||
}
|
||||
if ("p1" = "NUMBER") {
|
||||
oSV.ValueType(ivtFloat);
|
||||
oSV.ValueSubType(istGeneric);
|
||||
oSV.ValueMin(p6);
|
||||
oSV.ValueMax(p7);
|
||||
}
|
||||
if ("p1" = "BOOL") {
|
||||
oSV.ValueType(ivtBinary);
|
||||
oSV.ValueSubType(istBool);
|
||||
oSV.ValueName0("p6");
|
||||
oSV.ValueName1("p7");
|
||||
}
|
||||
if ("p1" = "LIST") {
|
||||
oSV.Name("\$name");
|
||||
oSV.ValueType(ivtInteger);
|
||||
oSV.ValueSubType(istEnum);
|
||||
oSV.ValueList("p6");
|
||||
}
|
||||
oSV.DPInfo("p5");
|
||||
oSV.ValueUnit("p3");
|
||||
oSV.State("p4");
|
||||
oSV.Internal(false);
|
||||
oSV.Visible(true);
|
||||
oSV.ValueList("\$list");
|
||||
oSV.DPInfo("\$desc");
|
||||
oSV.ValueUnit("\$unit");
|
||||
oSV.State("\$init");
|
||||
dom.RTUpdate(false);
|
||||
}
|
||||
else {
|
||||
oSV.State("\$init");
|
||||
}
|
||||
)
|
||||
},
|
||||
"DeleteVariable" => {
|
||||
_description => "Delete CCU system variable",
|
||||
description => "Delete CCU system variable",
|
||||
syntax => "name",
|
||||
parameters => 1,
|
||||
code => qq(
|
||||
object oSV = dom.GetObject("p1");
|
||||
object oSV = dom.GetObject("\$name");
|
||||
if (oSV) {
|
||||
dom.DeleteObject(oSV.ID());
|
||||
}
|
||||
)
|
||||
},
|
||||
"GetVariables" => {
|
||||
description => "Query system variables",
|
||||
syntax => "",
|
||||
parameters => 0,
|
||||
code => qq(
|
||||
object osysvar;
|
||||
string ssysvarid;
|
||||
foreach (ssysvarid, dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs())
|
||||
{
|
||||
osysvar = dom.GetObject(ssysvarid);
|
||||
WriteLine (osysvar.Name() # "=" # osysvar.Variable() # "=" # osysvar.Value());
|
||||
}
|
||||
)
|
||||
},
|
||||
"GetDeviceInfo" => {
|
||||
description => "Query device info",
|
||||
syntax => "devname, ccuget",
|
||||
parameters => 2,
|
||||
code => qq(
|
||||
string chnid;
|
||||
string sDPId;
|
||||
object odev = dom.GetObject ("\$devname");
|
||||
if (odev) {
|
||||
foreach (chnid, odev.Channels()) {
|
||||
object ochn = dom.GetObject(chnid);
|
||||
if (ochn) {
|
||||
foreach(sDPId, ochn.DPs()) {
|
||||
object oDP = dom.GetObject(sDPId);
|
||||
if (oDP) {
|
||||
integer op = oDP.Operations();
|
||||
string flags = "";
|
||||
if (OPERATION_READ & op) { flags = flags # "R"; }
|
||||
if (OPERATION_WRITE & op) { flags = flags # "W"; }
|
||||
if (OPERATION_EVENT & op) { flags = flags # "E"; }
|
||||
WriteLine ("C;" # ochn.Address() # ";" # ochn.Name() # ";" # oDP.Name() # ";" # oDP.ValueType() # ";" # oDP.\$ccuget() # ";" # flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
WriteLine ("ERROR: Device not found");
|
||||
}
|
||||
)
|
||||
},
|
||||
"GetDeviceList" => {
|
||||
description => "Query CCU devices and channels",
|
||||
syntax => "",
|
||||
parameters => 0,
|
||||
code => qq(
|
||||
string devid;
|
||||
string chnid;
|
||||
foreach(devid, root.Devices().EnumUsedIDs()) {
|
||||
object odev=dom.GetObject(devid);
|
||||
string intid=odev.Interface();
|
||||
string intna=dom.GetObject(intid).Name();
|
||||
integer cc=0;
|
||||
foreach (chnid, odev.Channels()) {
|
||||
object ochn=dom.GetObject(chnid);
|
||||
WriteLine("C;" # ochn.Address() # ";" # ochn.Name());
|
||||
cc=cc+1;
|
||||
}
|
||||
WriteLine("D;" # intna # ";" # odev.Address() # ";" # odev.Name() # ";" # odev.HssType() # ";" # cc);
|
||||
}
|
||||
)
|
||||
},
|
||||
"GetDatapointsByChannel" => {
|
||||
description => "Query datapoints of channel list",
|
||||
syntax => "list, ccuget",
|
||||
parameters => 2,
|
||||
code => qq(
|
||||
string sDPId;
|
||||
string sChnName;
|
||||
string sChnList = "\$list";
|
||||
integer c = 0;
|
||||
foreach (sChnName, sChnList.Split(",")) {
|
||||
object oChannel = dom.GetObject (sChnName);
|
||||
if (oChannel) {
|
||||
foreach(sDPId, oChannel.DPs()) {
|
||||
object oDP = dom.GetObject(sDPId);
|
||||
if (oDP) {
|
||||
if (OPERATION_READ & oDP.Operations()) {
|
||||
WriteLine (sChnName # "=" # oDP.Name() # "=" # oDP.\$ccuget());
|
||||
c = c+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
WriteLine (c);
|
||||
)
|
||||
},
|
||||
"GetDatapointsByDevice" => {
|
||||
description => "Query datapoints of device list",
|
||||
syntax => "list, ccuget",
|
||||
parameters => 2,
|
||||
code => qq(
|
||||
string chnid;
|
||||
string sDPId;
|
||||
string sDevName;
|
||||
string sDevList = "\$list";
|
||||
integer c = 0;
|
||||
foreach (sDevName, sDevList.Split(",")) {
|
||||
object odev = dom.GetObject (sDevName);
|
||||
if (odev) {
|
||||
foreach (chnid, odev.Channels()) {
|
||||
object ochn = dom.GetObject(chnid);
|
||||
if (ochn) {
|
||||
foreach(sDPId, ochn.DPs()) {
|
||||
object oDP = dom.GetObject(sDPId);
|
||||
if (oDP) {
|
||||
if (OPERATION_READ & oDP.Operations()) {
|
||||
WriteLine (ochn.Name() # "=" # oDP.Name() # "=" # oDP.\$ccuget());
|
||||
c = c+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
WriteLine (c);
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user