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:
zap 2017-04-25 15:40:51 +00:00
parent ca9b3b3fdb
commit 5994d53ce9
6 changed files with 904 additions and 366 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.
- 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

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
Log3 $name, 2, "HMCCURPC: Thread $clkey with TID=".$thr->tid ().
" has been stopped. Deleting it";
# undef $hash->{hmccu}{rpc}{$clkey}{child};
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};
}
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 &lt;seconds&gt;</b><br/>
Specify timeout for accepting incoming connections. Default is 1 second. Increase this

View File

@ -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 } ]",
parameters => 6,
code => qq(
"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.ValueType(ivtInteger);
oSV.ValueSubType(istEnum);
oSV.ValueList("p6");
}
oSV.DPInfo("p5");
oSV.ValueUnit("p3");
oSV.State("p4");
oSV.Internal(false);
oSV.Visible(true);
oSV.Name("\$name");
oSV.ValueType(ivtInteger);
oSV.ValueSubType(istEnum);
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",
parameters => 1,
code => qq(
object oSV = dom.GetObject("p1");
description => "Delete CCU system variable",
syntax => "name",
parameters => 1,
code => qq(
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);
)
}
);