mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-09 14:47:00 +00:00
HMCCU: Version 4.1
git-svn-id: https://svn.fhem.de/fhem/trunk@14693 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
6b435af21c
commit
64139e7db0
@ -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: Version 4.1
|
||||
- feature: 93_DbRep: V5.5.0, new command restoreMySQL, use new Internal
|
||||
MODEL in DbLog since version 2.18.2
|
||||
- feature: 98_fheminfo: do not show complete uniqueid in frontend
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,14 @@
|
||||
################################################################
|
||||
######################################################################
|
||||
#
|
||||
# 88_HMCCUCHN.pm
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.0.002
|
||||
# Version 4.1
|
||||
#
|
||||
# (c) 2017 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
################################################################
|
||||
######################################################################
|
||||
#
|
||||
# define <name> HMCCUCHN <ccudev> [readonly] [defaults]
|
||||
# [iodev=<iodevname>]
|
||||
@ -44,15 +44,16 @@
|
||||
# attr <name> ccuverify { 0 | 1 | 2 }
|
||||
# attr <name> controldatapoint <datapoint>
|
||||
# attr <name> disable { 0 | 1 }
|
||||
# attr <name> peer datapoints:condition:{hmccu:object=value|ccu:object=value|fhem:command}
|
||||
# attr <name> hmstatevals <subst-rule>[;...]
|
||||
# attr <name> statedatapoint <datapoint>
|
||||
# attr <name> statevals <text1>:<subtext1>[,...]
|
||||
# attr <name> substexcl <reading-expr>
|
||||
# attr <name> substitute <subst-rule>[;...]
|
||||
#
|
||||
################################################################
|
||||
######################################################################
|
||||
# Requires modules 88_HMCCU.pm, HMCCUConf.pm
|
||||
################################################################
|
||||
######################################################################
|
||||
|
||||
package main;
|
||||
|
||||
@ -81,7 +82,12 @@ sub HMCCUCHN_Initialize ($)
|
||||
$hash->{AttrFn} = "HMCCUCHN_Attr";
|
||||
$hash->{parseParams} = 1;
|
||||
|
||||
$hash->{AttrList} = "IODev ccuackstate:0,1 ccucalculate ccuflags:multiple-strict,altread,nochn0,trace ccureadingfilter ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ccureadingname ccureadings:0,1 ccuscaleval ccuverify:0,1,2 ccuget:State,Value controldatapoint disable:0,1 hmstatevals:textField-long statedatapoint statevals substitute:textField-long substexcl stripnumber ". $readingFnAttributes;
|
||||
$hash->{AttrList} = "IODev ccuackstate:0,1 ccucalculate ".
|
||||
"ccuflags:multiple-strict,altread,nochn0,trace ccureadingfilter ".
|
||||
"ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ccureadingname ".
|
||||
"ccureadings:0,1 ccuscaleval ccuverify:0,1,2 ccuget:State,Value controldatapoint ".
|
||||
"disable:0,1 hmstatevals:textField-long statedatapoint statevals substitute:textField-long ".
|
||||
"substexcl stripnumber peer:textField-long ". $readingFnAttributes;
|
||||
}
|
||||
|
||||
##################################################
|
||||
@ -873,6 +879,40 @@ sub HMCCUCHN_Get ($@)
|
||||
Optionally the name of the HomeMatic state reading can be specified at the beginning of
|
||||
the attribute in format =<reading>;. The default reading name is 'hmstate'.
|
||||
</li><br/>
|
||||
<li><b>peer [<datapoints>:<condition>:
|
||||
{ccu:<object>=<value>|hmccu:<object>=<value>|
|
||||
fhem:<command>}</b><br/>
|
||||
Logically peer a datapoint of a HMCCUCHN or HMCCUDEV device with another device or any
|
||||
FHEM command.<br/>
|
||||
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
|
||||
the parameter <i>channelno</i> is obsolete.<br/>
|
||||
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 '%'.
|
||||
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
|
||||
(i.e. "true") is used. If the special character is doubled the previous values will
|
||||
be used.<br/>
|
||||
If the result of this operation is true, the action specified after the second colon
|
||||
is executed. Three types of actions are supported:<br/>
|
||||
<b>hmccu</b>: Parameter <i>object</i> refers to a FHEM device/datapoint in format
|
||||
<device>:<channelno>.<datapoint><br/>
|
||||
<b>ccu</b>: Parameter <i>object</i> refers to a CCU channel/datapoint in format
|
||||
<channel>.<datapoint>. <i>channel</i> can be a channel name or address.<br/>
|
||||
<b>fhem</b>: The specified <i>command</i> will be executed<br/>
|
||||
If action contains the string $value it is substituted by the current value of the
|
||||
datapoint which triggered the action. The attribute supports multiple peering rules
|
||||
separated by semicolons and optionally by newline characters.<br/><br/>
|
||||
Examples:<br/>
|
||||
# Set FHEM device mydummy to value if formatted value of 1.STATE is 'on'<br/>
|
||||
<code>attr mydev peer 1.STATE:'$1.STATE' eq 'on':fhem:set mydummy $value</code><br/>
|
||||
# Set 2.LEVEL of device myBlind to 100 if raw value of 1.STATE is 1<br/>
|
||||
<code>attr mydev peer 1.STATE:'%1.STATE' eq '1':hmccu:myBlind:2.LEVEL=100</code><br/>
|
||||
# Set 1.STATE of device LEQ1234567 to true if 1.LEVEL < 100<br/>
|
||||
<code>attr mydev peer 1.LEVEL:$1.LEVEL < 100:ccu:LEQ1234567:1.STATE=true</code><br/>
|
||||
# Set 1.STATE of device LEQ1234567 to true if current level is different from old level<br/>
|
||||
<code>attr mydev peer 1.LEVEL:$1.LEVEL != $$1.LEVEL:ccu:LEQ1234567:1.STATE=true</code><br/>
|
||||
</li><br/>
|
||||
<li><b>statedatapoint <datapoint></b><br/>
|
||||
Set state datapoint used by some commands like 'set devstate'.
|
||||
</li><br/>
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.0.002
|
||||
# Version 4.1
|
||||
#
|
||||
# (c) 2017 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
@ -37,7 +37,6 @@
|
||||
# attr <name> ccucalculate <value>:<reading>[:<dp-list>][...]
|
||||
# attr <name> ccuflags { altread, nochn0, trace }
|
||||
# attr <name> ccuget { State | Value }
|
||||
# attr <name> ccupeer [channel.]datapoint oper expr:{ hmccu:object=value | fhem:command }
|
||||
# attr <name> ccureadings { 0 | 1 }
|
||||
# attr <name> ccureadingformat { address[lc] | name[lc] | datapoint[lc] }
|
||||
# attr <name> ccureadingfilter <filter-rule>[,...]
|
||||
@ -46,6 +45,7 @@
|
||||
# attr <name> ccuverify { 0 | 1 | 2}
|
||||
# attr <name> controldatapoint <channel-number>.<datapoint>
|
||||
# attr <name> disable { 0 | 1 }
|
||||
# attr <name> peer datapoints:condition:{hmccu:object=value|ccu:object=value|fhem:command}
|
||||
# attr <name> hmstatevals <subst-rule>[;...]
|
||||
# attr <name> statechannel <channel>
|
||||
# attr <name> statedatapoint [<channel-number>.]<datapoint>
|
||||
@ -90,7 +90,7 @@ sub HMCCUDEV_Initialize ($)
|
||||
"ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ccureadingname ".
|
||||
"ccureadings:0,1 ccuget:State,Value ccuscaleval ccuverify:0,1,2 disable:0,1 ".
|
||||
"hmstatevals:textField-long statevals substexcl substitute:textField-long statechannel ".
|
||||
"statedatapoint controldatapoint stripnumber ccupeer:textField-long ".$readingFnAttributes;
|
||||
"statedatapoint controldatapoint stripnumber peer:textField-long ".$readingFnAttributes;
|
||||
}
|
||||
|
||||
#####################################
|
||||
@ -310,7 +310,7 @@ sub HMCCUDEV_Set ($@)
|
||||
}
|
||||
|
||||
return HMCCU_SetError ($hash, "Usage: set $name datapoint [{channel-number}.]{datapoint} {value}")
|
||||
if (!defined ($objname) || !defined ($objvalue) || $objvalue eq '');
|
||||
if (!defined ($objvalue) || $objvalue eq '');
|
||||
|
||||
if ($objname =~ /^([0-9]+)\..+$/) {
|
||||
my $chn = $1;
|
||||
@ -500,7 +500,8 @@ sub HMCCUDEV_Set ($@)
|
||||
}
|
||||
}
|
||||
elsif ($opt eq 'config') {
|
||||
return HMCCU_SetError ($hash, "Usage: set $name config [{channel-number}] {parameter}={value} [...]") if ((scalar keys %{$h}) < 1);
|
||||
return HMCCU_SetError ($hash, "Usage: set $name config [{channel-number}] {parameter}={value} [...]")
|
||||
if ((scalar keys %{$h}) < 1);
|
||||
my $objname = $ccuaddr;
|
||||
|
||||
# Channel number is optional because parameter can be related to device or channel
|
||||
@ -947,6 +948,10 @@ sub HMCCUDEV_Get ($@)
|
||||
<a href="#HMCCUCHNattr">see HMCCUCHN</a>
|
||||
</li><br/>
|
||||
<li><b>hmstatevals <subst-rule>[;...]</b><br/>
|
||||
<a href="#HMCCUCHNattr">see HMCCUCHN</a>
|
||||
</li><br/>
|
||||
<li><b>peer [<datapoints>:<condition>:
|
||||
{ccu:<object>=<value>|hmccu:<object>=<value>|fhem:<command>}</b><br/>
|
||||
<a href="#HMCCUCHNattr">see HMCCUCHN</a>
|
||||
</li><br/>
|
||||
<li><b>statechannel <channel-number></b><br/>
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 0.95 beta
|
||||
# Version 0.96 beta
|
||||
#
|
||||
# Thread based RPC Server module for HMCCU.
|
||||
#
|
||||
@ -40,7 +40,7 @@ use SetExtensions;
|
||||
######################################################################
|
||||
|
||||
# HMCCURPC version
|
||||
my $HMCCURPC_VERSION = '0.95 beta';
|
||||
my $HMCCURPC_VERSION = '0.96 beta';
|
||||
|
||||
# Maximum number of events processed per call of Read()
|
||||
my $HMCCURPC_MAX_EVENTS = 50;
|
||||
@ -66,6 +66,9 @@ my $HMCCURPC_TIMEOUT_WRITE = 0.001;
|
||||
# Timeout for accepting incoming connections
|
||||
my $HMCCURPC_TIMEOUT_ACCEPT = 1;
|
||||
|
||||
# Timeout for incoming CCU events
|
||||
my $HMCCURPC_TIMEOUT_EVENT = 600;
|
||||
|
||||
# Send statistic information after specified amount of events
|
||||
my $HMCCURPC_STATISTICS = 500;
|
||||
|
||||
@ -155,7 +158,7 @@ sub HMCCURPC_GetAttribute ($$$$);
|
||||
sub HMCCURPC_GetRPCPortList ($);
|
||||
sub HMCCURPC_ListDevices ($);
|
||||
sub HMCCURPC_RegisterCallback ($);
|
||||
sub HMCCURPC_RegisterSingleCallback ($$);
|
||||
sub HMCCURPC_RegisterSingleCallback ($$$);
|
||||
sub HMCCURPC_DeRegisterCallback ($);
|
||||
sub HMCCURPC_InitRPCServer ($$$);
|
||||
sub HMCCURPC_StartRPCServer ($);
|
||||
@ -234,9 +237,10 @@ sub HMCCURPC_Initialize ($)
|
||||
$hash->{parseParams} = 1;
|
||||
|
||||
$hash->{AttrList} = "rpcInterfaces:multiple-strict,".join(',',sort keys %HMCCURPC_RPC_PORT).
|
||||
" ccuflags:multiple-strict,expert,keepThreads rpcMaxEvents rpcQueueSize rpcTriggerTime".
|
||||
" ccuflags:multiple-strict,expert,keepThreads,reconnect".
|
||||
" rpcMaxEvents rpcQueueSize rpcTriggerTime".
|
||||
" rpcServer:on,off rpcServerAddr rpcServerPort rpcWriteTimeout rpcAcceptTimeout".
|
||||
" rpcConnTimeout rpcWaitTime rpcStatistics ".
|
||||
" rpcConnTimeout rpcWaitTime rpcStatistics rpcEventTimeout ".
|
||||
$readingFnAttributes;
|
||||
}
|
||||
|
||||
@ -483,7 +487,7 @@ sub HMCCURPC_Get ($@)
|
||||
my $rc;
|
||||
|
||||
if ($opt eq 'rpcevents') {
|
||||
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL");
|
||||
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL", "TO");
|
||||
$result = '';
|
||||
foreach my $clkey (keys %{$hash->{hmccu}{rpc}}) {
|
||||
next if ($clkey eq 'DATA');
|
||||
@ -598,6 +602,7 @@ sub HMCCURPC_Read ($)
|
||||
|
||||
# Get attributes
|
||||
my $rpcmaxevents = AttrVal ($name, 'rpcMaxEvents', $HMCCURPC_MAX_EVENTS);
|
||||
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
|
||||
|
||||
# Data read from child socket is only a trigger for reading data from event queue
|
||||
my $buffer = '';
|
||||
@ -643,10 +648,17 @@ sub HMCCURPC_Read ($)
|
||||
$devices{$par[0]}{newaddr} = $par[1];
|
||||
$devcount++;
|
||||
}
|
||||
elsif ($et eq 'TO') {
|
||||
if ($ccuflags =~ /reconnect/) {
|
||||
Log3 $name, 2, "HMCCURPC: Reconnecting to CCU interface ".
|
||||
HMCCURPC_RPC_NUMPORT{$par[0]};
|
||||
HMCCURPC_RegisterSingleCallback ($hash, $par[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
$eventcount++;
|
||||
if ($eventcount > $rpcmaxevents) {
|
||||
Log3 $name, 4, "Read stopped after $rpcmaxevents events";
|
||||
Log3 $name, 4, "HMCCURPC: Read stopped after $rpcmaxevents events";
|
||||
last;
|
||||
}
|
||||
}
|
||||
@ -807,7 +819,8 @@ sub HMCCURPC_ProcessEvent ($$)
|
||||
"IN", 2,
|
||||
"EX", 2,
|
||||
"SL", 1,
|
||||
"ST", 10
|
||||
"TO", 1,
|
||||
"ST", 11
|
||||
);
|
||||
|
||||
# Parse event
|
||||
@ -856,8 +869,9 @@ sub HMCCURPC_ProcessEvent ($$)
|
||||
my $delay = $rh->{$clkey}{evtime}-$t[0];
|
||||
$rh->{$clkey}{sumdelay} += $delay;
|
||||
$rh->{$clkey}{avgdelay} = $rh->{$clkey}{sumdelay}/$rh->{$clkey}{rec}{$et};
|
||||
Log3 $name, 2, "HMCCURPC: Received CENTRAL event. ".$t[2]."=".$t[3] if ($t[1] eq 'CENTRAL');
|
||||
my ($add, $chn) = split (/:/, $t[1]);
|
||||
return ($et, $clkey, $add, $chn, $t[2], $t[3]);
|
||||
return defined ($chn) ? ($et, $clkey, $add, $chn, $t[2], $t[3]) : undef;
|
||||
}
|
||||
elsif ($et eq 'SL') {
|
||||
#
|
||||
@ -998,12 +1012,22 @@ sub HMCCURPC_ProcessEvent ($$)
|
||||
my @res = ($et, $clkey);
|
||||
push (@res, @t);
|
||||
my $total = shift @t;
|
||||
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL");
|
||||
for (my $i=0; $i<9; $i++) {
|
||||
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL", "TO");
|
||||
for (my $i=0; $i<scalar(@eventtypes); $i++) {
|
||||
$hash->{hmccu}{rpc}{$clkey}{snd}{$eventtypes[$i]} += $t[$i];
|
||||
}
|
||||
return @res;
|
||||
}
|
||||
elsif ($et eq 'TO') {
|
||||
#
|
||||
# Event timeout
|
||||
# Input: TO|clkey|Time
|
||||
# Output: TO, clkey, Port, Time
|
||||
#
|
||||
Log3 $name, 2, "HMCCU: Received no events from interface $clkey for ".$t[0]." seconds";
|
||||
DoTrigger ($name, "No events from interface $clkey for ".$t[0]." seconds");
|
||||
return ($et, $clkey, $hash->{hmccu}{rpc}{$clkey}{port}, $t[0]);
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
@ -1084,19 +1108,22 @@ sub HMCCURPC_RegisterCallback ($)
|
||||
my $regcount = 0;
|
||||
|
||||
foreach my $port (@rpcports) {
|
||||
$regcount++ if (HMCCURPC_RegisterSingleCallback ($hash, $port));
|
||||
$regcount++ if (HMCCURPC_RegisterSingleCallback ($hash, $port, 0));
|
||||
}
|
||||
|
||||
return $regcount;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Register single callback
|
||||
# Register callback for specified CCU interface port.
|
||||
# If parameter 'force' is 1 callback will be registered even if state
|
||||
# is "running". State will not be modified.
|
||||
# Return 0 on error.
|
||||
######################################################################
|
||||
|
||||
sub HMCCURPC_RegisterSingleCallback ($$)
|
||||
sub HMCCURPC_RegisterSingleCallback ($$$)
|
||||
{
|
||||
my ($hash, $port) = @_;
|
||||
my ($hash, $port, $force) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $serveraddr = $hash->{host};
|
||||
@ -1104,8 +1131,8 @@ sub HMCCURPC_RegisterSingleCallback ($$)
|
||||
my $rpcserveraddr = AttrVal ($name, 'rpcServerAddr', $localaddr);
|
||||
my $clkey = 'CB'.$port;
|
||||
|
||||
return 0 if (!exists ($hash->{hmccu}{rpc}{$clkey}) ||
|
||||
$hash->{hmccu}{rpc}{$clkey}{state} ne 'working');
|
||||
return 0 if (!exists ($hash->{hmccu}{rpc}{$clkey}));
|
||||
return 0 if ($hash->{hmccu}{rpc}{$clkey}{state} ne 'working' && $force == 0);
|
||||
|
||||
my $cburl = '';
|
||||
if (HMCCURPC_IsAscRPCPort ($port)) {
|
||||
@ -1114,32 +1141,33 @@ sub HMCCURPC_RegisterSingleCallback ($$)
|
||||
else {
|
||||
$cburl = "xmlrpc_bin://$rpcserveraddr:".$hash->{hmccu}{rpc}{$clkey}{cbport};
|
||||
}
|
||||
|
||||
# The client URL is only relevant for ASCII RPC
|
||||
|
||||
my $clurl = "http://$serveraddr:$port/";
|
||||
$clurl .= $HMCCURPC_RPC_URL{$port} if (exists ($HMCCURPC_RPC_URL{$port}));
|
||||
|
||||
$hash->{hmccu}{rpc}{$clkey}{port} = $port;
|
||||
$hash->{hmccu}{rpc}{$clkey}{clurl} = $clurl;
|
||||
$hash->{hmccu}{rpc}{$clkey}{cburl} = $cburl;
|
||||
$hash->{hmccu}{rpc}{$clkey}{state} = 'registered';
|
||||
|
||||
Log3 $name, 1, "HMCCURPC: Registering callback $cburl with ID $clkey at $clurl";
|
||||
# if ($HMCCURPC_RPC_PROT{$port} eq 'A') {
|
||||
# my $rpcclient = RPC::XML::Client->new ($clurl);
|
||||
# $rpcclient->send_request ("init", $cburl, $clkey);
|
||||
# }
|
||||
$hash->{hmccu}{rpc}{$clkey}{state} = 'registered' if ($force == 0);
|
||||
|
||||
Log3 $name, 2, "HMCCURPC: Registering callback $cburl with ID $clkey at $clurl";
|
||||
my $rc;
|
||||
if (HMCCURPC_IsAscRPCPort ($port)) {
|
||||
HMCCURPC_SendRequest ($hash, $port, "init", $cburl, $clkey);
|
||||
$rc = HMCCURPC_SendRequest ($hash, $port, "init", $cburl, $clkey);
|
||||
}
|
||||
else {
|
||||
HMCCURPC_SendBinRequest ($hash, $port, "init",
|
||||
$rc = HMCCURPC_SendBinRequest ($hash, $port, "init",
|
||||
$BINRPC_STRING, $cburl, $BINRPC_STRING, $clkey);
|
||||
}
|
||||
Log3 $name, 1, "HMCCURPC: RPC callback with URL $cburl registered";
|
||||
|
||||
return 1;
|
||||
if (defined ($rc)) {
|
||||
Log3 $name, 1, "HMCCURPC: RPC callback with URL $cburl registered";
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
Log3 $name, 1, "HMCCURPC: Failed to register callback for ID $clkey";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
@ -1210,7 +1238,7 @@ sub HMCCURPC_InitRPCServer ($$$)
|
||||
Log3 $name, 2, "HMCCURPC: Callback server $clkey created. Listening on port $callbackport";
|
||||
|
||||
# Callback for events
|
||||
Log3 $name, 2, "HMCCURPC: Adding callback for events for server $clkey";
|
||||
Log3 $name, 4, "HMCCURPC: Adding callback for events for server $clkey";
|
||||
$server->add_method (
|
||||
{ name=>"event",
|
||||
signature=> ["string string string string int","string string string string double","string string string string boolean","string string string string i4"],
|
||||
@ -1219,7 +1247,7 @@ sub HMCCURPC_InitRPCServer ($$$)
|
||||
);
|
||||
|
||||
# Callback for new devices
|
||||
Log3 $name, 2, "HMCCURPC: Adding callback for new devices for server $clkey";
|
||||
Log3 $name, 4, "HMCCURPC: Adding callback for new devices for server $clkey";
|
||||
$server->add_method (
|
||||
{ name=>"newDevices",
|
||||
signature=>["string string array"],
|
||||
@ -1228,7 +1256,7 @@ sub HMCCURPC_InitRPCServer ($$$)
|
||||
);
|
||||
|
||||
# Callback for deleted devices
|
||||
Log3 $name, 2, "HMCCURPC: Adding callback for deleted devices for server $clkey";
|
||||
Log3 $name, 4, "HMCCURPC: Adding callback for deleted devices for server $clkey";
|
||||
$server->add_method (
|
||||
{ name=>"deleteDevices",
|
||||
signature=>["string string array"],
|
||||
@ -1237,7 +1265,7 @@ sub HMCCURPC_InitRPCServer ($$$)
|
||||
);
|
||||
|
||||
# Callback for modified devices
|
||||
Log3 $name, 2, "HMCCURPC: Adding callback for modified devices for server $clkey";
|
||||
Log3 $name, 4, "HMCCURPC: Adding callback for modified devices for server $clkey";
|
||||
$server->add_method (
|
||||
{ name=>"updateDevice",
|
||||
signature=>["string string string int"],
|
||||
@ -1246,7 +1274,7 @@ sub HMCCURPC_InitRPCServer ($$$)
|
||||
);
|
||||
|
||||
# Callback for replaced devices
|
||||
Log3 $name, 2, "HMCCURPC: Adding callback for replaced devices for server $clkey";
|
||||
Log3 $name, 4, "HMCCURPC: Adding callback for replaced devices for server $clkey";
|
||||
$server->add_method (
|
||||
{ name=>"replaceDevice",
|
||||
signature=>["string string string string"],
|
||||
@ -1255,7 +1283,7 @@ sub HMCCURPC_InitRPCServer ($$$)
|
||||
);
|
||||
|
||||
# Callback for readded devices
|
||||
Log3 $name, 2, "HMCCURPC: Adding callback for readded devices for server $clkey";
|
||||
Log3 $name, 4, "HMCCURPC: Adding callback for readded devices for server $clkey";
|
||||
$server->add_method (
|
||||
{ name=>"replaceDevice",
|
||||
signature=>["string string array"],
|
||||
@ -1264,7 +1292,7 @@ sub HMCCURPC_InitRPCServer ($$$)
|
||||
);
|
||||
|
||||
# Dummy implementation, always return an empty array
|
||||
Log3 $name, 2, "HMCCURPC: Adding callback for list devices for server $clkey";
|
||||
Log3 $name, 4, "HMCCURPC: Adding callback for list devices for server $clkey";
|
||||
$server->add_method (
|
||||
{ name=>"listDevices",
|
||||
signature=>["array string"],
|
||||
@ -1305,6 +1333,7 @@ sub HMCCURPC_StartRPCServer ($)
|
||||
$thrpar{socktimeout} = AttrVal ($name, 'rpcWriteTimeout', $HMCCURPC_TIMEOUT_WRITE);
|
||||
$thrpar{conntimeout} = AttrVal ($name, 'rpcConnTimeout', $HMCCURPC_TIMEOUT_CONNECTION);
|
||||
$thrpar{acctimeout} = AttrVal ($name, 'rpcAcceptTimeout', $HMCCURPC_TIMEOUT_ACCEPT);
|
||||
$thrpar{evttimeout} = AttrVal ($name, 'rpcEventTimeout', $HMCCURPC_TIMEOUT_EVENT);
|
||||
$thrpar{waittime} = AttrVal ($name, 'rpcWaitTime', $HMCCURPC_TIME_WAIT);
|
||||
$thrpar{queuesize} = AttrVal ($name, 'rpcQueueSize', $HMCCURPC_MAX_QUEUESIZE);
|
||||
$thrpar{triggertime} = AttrVal ($name, 'rpcTriggerTime', $HMCCURPC_TIME_TRIGGER);
|
||||
@ -1313,7 +1342,7 @@ sub HMCCURPC_StartRPCServer ($)
|
||||
|
||||
my $ccunum = $hash->{CCUNum};
|
||||
my $serveraddr = $hash->{host};
|
||||
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL");
|
||||
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL", "TO");
|
||||
|
||||
# Get or detect local IP address
|
||||
if ($localaddr eq '') {
|
||||
@ -1831,7 +1860,7 @@ sub HMCCURPC_HandleConnection ($$$$)
|
||||
my $tid = threads->tid ();
|
||||
my $clkey = 'CB'.$port;
|
||||
|
||||
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL");
|
||||
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL", "TO");
|
||||
|
||||
# Initialize RPC server
|
||||
my $iface = $HMCCURPC_RPC_NUMPORT{$port};
|
||||
@ -1854,9 +1883,9 @@ sub HMCCURPC_HandleConnection ($$$$)
|
||||
$rpcsrv->{hmccu}{queuesize} = $thrpar->{queuesize};
|
||||
$rpcsrv->{hmccu}{statistics} = $thrpar->{statistics};
|
||||
$rpcsrv->{hmccu}{running} = 0;
|
||||
$rpcsrv->{hmccu}{evttime} = time ();
|
||||
|
||||
# Initialize statistic counters
|
||||
$rpcsrv->{hmccu}{snd}{total} = 0;
|
||||
foreach my $et (@eventtypes) {
|
||||
$rpcsrv->{hmccu}{rec}{$et} = 0;
|
||||
$rpcsrv->{hmccu}{snd}{$et} = 0;
|
||||
@ -1872,6 +1901,9 @@ sub HMCCURPC_HandleConnection ($$$$)
|
||||
$rpcsrv->{__daemon}->timeout ($thrpar->{acctimeout});
|
||||
|
||||
while ($run) {
|
||||
my $difftime = time()-$rpcsrv->{hmccu}{evttime};
|
||||
HMCCURPC_Write ($rpcsrv, "TO", $clkey, $difftime) if ($difftime >= $thrpar->{evttimeout});
|
||||
|
||||
# Next statement blocks for timeout seconds
|
||||
my $connection = $rpcsrv->{__daemon}->accept ();
|
||||
next if (! $connection);
|
||||
@ -2034,6 +2066,8 @@ sub HMCCURPC_Write ($$$$)
|
||||
if (defined ($server->{hmccu}{eventqueue})) {
|
||||
my $queue = $server->{hmccu}{eventqueue};
|
||||
|
||||
$server->{hmccu}{evttime} = time ();
|
||||
|
||||
if (defined ($server->{hmccu}{queuesize}) &&
|
||||
$queue->pending () >= $server->{hmccu}{queuesize}) {
|
||||
Log3 $name, 1, "CCURPC: $cb maximum queue size reached";
|
||||
@ -2060,7 +2094,7 @@ sub HMCCURPC_WriteStats ($$)
|
||||
my ($server, $clkey) = @_;
|
||||
my $name = $server->{hmccu}{name};
|
||||
|
||||
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL");
|
||||
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL", "TO");
|
||||
|
||||
# Send statistic info
|
||||
my $st = $server->{hmccu}{snd}{total};
|
||||
@ -2746,6 +2780,7 @@ sub HMCCURPC_DecodeResponse ($)
|
||||
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/>
|
||||
reconnect - Try to re-register at CCU if no events received for rpcEventTimeout seconds<br/>
|
||||
</li><br/>
|
||||
<li><b>rpcAcceptTimeout <seconds></b><br/>
|
||||
Specify timeout for accepting incoming connections. Default is 1 second. Increase this
|
||||
@ -2754,6 +2789,10 @@ sub HMCCURPC_DecodeResponse ($)
|
||||
<li><b>rpcConnTimeout <seconds></b><br/>
|
||||
Specify timeout of CCU connection handling. Default is 10 second.
|
||||
</li><br/>
|
||||
<li><b>rpcEventTimeout <seconds></b><br/>
|
||||
Specify timeout for CCU events. Default is 600 seconds. If timeout occurs an event
|
||||
is triggered.
|
||||
</li><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
|
||||
(HMCCU device) is used. Default is BidCos-RF.
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.0.002
|
||||
# Version 4.1
|
||||
#
|
||||
# Configuration parameters for HomeMatic devices.
|
||||
#
|
||||
@ -113,7 +113,8 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
substitute => "ERROR_REDUCED,ERROR_OVERHEAT!(0|false):no,(1|true):yes;LEVEL!#0-0:off,#1-100:on;DIRECTION!0:none,1:up,2:down,3:undefined",
|
||||
webCmd => "control:on:off",
|
||||
widgetOverride => "control:slider,0,10,100"
|
||||
}, "HM-LC-Dim1T-Pl|HM-LC-Dim1T-CV|HM-LC-Dim1T-FM|HM-LC-Dim1T-CV-2|HM-LC-Dim2T-SM|HM-LC-Dim2T-SM-2|HM-LC-Dim1T-DR|HM-LC-Dim1T-FM-LF|HM-LC-Dim1T-FM-2|HM-LC-Dim1T-Pl-3|HM-LC-Dim1TPBU-FM|HM-LC-Dim1TPBU-FM-2" => {
|
||||
},
|
||||
"HM-LC-Dim1T-Pl|HM-LC-Dim1T-CV|HM-LC-Dim1T-FM|HM-LC-Dim1T-CV-2|HM-LC-Dim2T-SM|HM-LC-Dim2T-SM-2|HM-LC-Dim1T-DR|HM-LC-Dim1T-FM-LF|HM-LC-Dim1T-FM-2|HM-LC-Dim1T-Pl-3|HM-LC-Dim1TPBU-FM|HM-LC-Dim1TPBU-FM-2" => {
|
||||
_description => "Funk-Abschnitt-Dimmaktor",
|
||||
_channels => "1",
|
||||
ccureadingfilter => "(^LEVEL\$|DIRECTION)",
|
||||
@ -145,6 +146,22 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
statevals => "press:true",
|
||||
substitute => "PRESS!(1|true):pressed,(0|false):released"
|
||||
},
|
||||
"HM-PBI-4-FM" => {
|
||||
_description => "Funk-Tasterschnittstelle",
|
||||
_channels => "1,2,3,4",
|
||||
ccureadingfilter => "PRESS",
|
||||
statedatapoint => "PRESS_SHORT",
|
||||
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-RC-Key4-2|HM-RC-Key4-3" => {
|
||||
_description => "Funk-Handsender Key",
|
||||
_channels => "1,2,3,4",
|
||||
ccureadingfilter => "PRESS",
|
||||
"event-on-update-reading" => ".*",
|
||||
statedatapoint => "PRESS_SHORT",
|
||||
substitute => "PRESS_SHORT,PRESS_LONG!(1|true):pressed"
|
||||
},
|
||||
"HM-LC-Sw1PBU-FM" => {
|
||||
_description => "Unterputz Schaltaktor für Markenschalter",
|
||||
_channels => "1",
|
||||
@ -427,7 +444,8 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
substitute => "ERROR_REDUCED,ERROR_OVERHEAT!(0|false):no,(1|true):yes;LEVEL!#0-0:off,#1-100:on;DIRECTION!0:none,1:up,2:down,3:undefined",
|
||||
webCmd => "control:on:off",
|
||||
widgetOverride => "control:slider,0,10,100"
|
||||
}, "HM-LC-Dim1T-Pl|HM-LC-Dim1T-CV|HM-LC-Dim1T-FM|HM-LC-Dim1T-CV-2|HM-LC-Dim2T-SM|HM-LC-Dim2T-SM-2|HM-LC-Dim1T-DR|HM-LC-Dim1T-FM-LF|HM-LC-Dim1T-FM-2|HM-LC-Dim1T-Pl-3|HM-LC-Dim1TPBU-FM|HM-LC-Dim1TPBU-FM-2" => {
|
||||
},
|
||||
"HM-LC-Dim1T-Pl|HM-LC-Dim1T-CV|HM-LC-Dim1T-FM|HM-LC-Dim1T-CV-2|HM-LC-Dim2T-SM|HM-LC-Dim2T-SM-2|HM-LC-Dim1T-DR|HM-LC-Dim1T-FM-LF|HM-LC-Dim1T-FM-2|HM-LC-Dim1T-Pl-3|HM-LC-Dim1TPBU-FM|HM-LC-Dim1TPBU-FM-2" => {
|
||||
_description => "Funk-Abschnitt-Dimmaktor",
|
||||
ccureadingfilter => "(^LEVEL\$|DIRECTION)",
|
||||
ccuscaleval => "LEVEL:0:1:0:100",
|
||||
@ -453,6 +471,17 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
statevals => "press:true",
|
||||
substitute => "PRESS!(1|true):pressed,(0|false):released"
|
||||
},
|
||||
"HM-PBI-4-FM" => {
|
||||
_description => "Funk-Tasterschnittstelle",
|
||||
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-RC-Key4-2|HM-RC-Key4-3" => {
|
||||
_description => "Funk-Handsender Key",
|
||||
ccureadingfilter => "PRESS",
|
||||
"event-on-update-reading" => ".*",
|
||||
substitute => "PRESS_SHORT,PRESS_LONG!(1|true):pressed"
|
||||
},
|
||||
"HM-LC-Sw1PBU-FM" => {
|
||||
_description => "Unterputz Schaltaktor für Markenschalter",
|
||||
ccureadingfilter => "STATE",
|
||||
@ -546,6 +575,16 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
statedatapoint => "1.TEMPERATURE",
|
||||
stripnumber => 1
|
||||
},
|
||||
"HM-Sen-RD-O" => {
|
||||
_description => "Regensensor",
|
||||
ccureadingfilter => "(STATE|WORKING)",
|
||||
controldatapoint => "2.STATE",
|
||||
eventMap => "/datapoint 2.STATE 1:on/datapoint 2.STATE 0:off/",
|
||||
statedatapoint => "1.STATE",
|
||||
substitute => "1.STATE!(0|false):dry,(1|true):rain;2.STATE!(0|false):off,(1|true):on",
|
||||
webCmd => "control",
|
||||
widgetOverride => "control:uzsuToggle,off,on"
|
||||
},
|
||||
"HM-WDS100-C6-O-2" => {
|
||||
_description => "Funk-Kombisensor",
|
||||
ccureadingfilter => "(HUMIDITY|TEMPERATURE|WIND|RAIN|SUNSHINE|BRIGHTNESS)",
|
||||
@ -706,11 +745,11 @@ if (oPR) {
|
||||
},
|
||||
"CreateStringVariable" => {
|
||||
description => "Create CCU system variable of type STRING",
|
||||
syntax => "name, init, desc",
|
||||
parameters => 3,
|
||||
syntax => "name, unit, init, desc",
|
||||
parameters => 4,
|
||||
code => qq(
|
||||
object oSV = dom.GetObject("\$name");
|
||||
if (!oSV){
|
||||
if (!oSV){
|
||||
object oSysVars = dom.GetObject(ID_SYSTEM_VARIABLES);
|
||||
oSV = dom.CreateObject(OT_VARDP);
|
||||
oSysVars.Add(oSV.ID());
|
||||
@ -718,7 +757,7 @@ if (!oSV){
|
||||
oSV.ValueType(ivtString);
|
||||
oSV.ValueSubType(istChar8859);
|
||||
oSV.DPInfo("\$desc");
|
||||
oSV.ValueUnit("");
|
||||
oSV.ValueUnit("\$unit");
|
||||
oSV.State("\$init");
|
||||
oSV.Internal(false);
|
||||
oSV.Visible(true);
|
||||
@ -758,8 +797,8 @@ else {
|
||||
},
|
||||
"CreateBoolVariable" => {
|
||||
description => "Create CCU system variable of type BOOL",
|
||||
syntax => "name, init, desc, value1, value2",
|
||||
parameters => 5,
|
||||
syntax => "name, unit, init, desc, valtrue, valfalse",
|
||||
parameters => 6,
|
||||
code => qq(
|
||||
object oSV = dom.GetObject("\$name");
|
||||
if (!oSV){
|
||||
@ -772,6 +811,7 @@ if (!oSV){
|
||||
oSV.ValueName0("\$value1");
|
||||
oSV.ValueName1("\$value2");
|
||||
oSV.DPInfo("\$desc");
|
||||
oSV.ValueUnit("\$unit");
|
||||
oSV.State("\$init");
|
||||
dom.RTUpdate(false);
|
||||
}
|
||||
@ -785,7 +825,7 @@ else {
|
||||
syntax => "name, unit, init, desc, list",
|
||||
parameters => 5,
|
||||
code => qq(
|
||||
object oSV = dom.GetObject("p2");
|
||||
object oSV = dom.GetObject("\$name");
|
||||
if (!oSV){
|
||||
object oSysVars = dom.GetObject(ID_SYSTEM_VARIABLES);
|
||||
oSV = dom.CreateObject(OT_VARDP);
|
||||
@ -804,14 +844,16 @@ else {
|
||||
}
|
||||
)
|
||||
},
|
||||
"DeleteVariable" => {
|
||||
description => "Delete CCU system variable",
|
||||
syntax => "name",
|
||||
parameters => 1,
|
||||
"DeleteObject" => {
|
||||
description => "Delete CCU object",
|
||||
syntax => "name, type",
|
||||
parameters => 2,
|
||||
code => qq(
|
||||
object oSV = dom.GetObject("\$name");
|
||||
if (oSV) {
|
||||
dom.DeleteObject(oSV.ID());
|
||||
if (oSV.IsTypeOf(\$type)) {
|
||||
dom.DeleteObject(oSV.ID());
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
@ -874,7 +916,7 @@ foreach(devid, root.Devices().EnumUsedIDs()) {
|
||||
integer cc=0;
|
||||
foreach (chnid, odev.Channels()) {
|
||||
object ochn=dom.GetObject(chnid);
|
||||
WriteLine("C;" # ochn.Address() # ";" # ochn.Name());
|
||||
WriteLine("C;" # ochn.Address() # ";" # ochn.Name() # ";" # ochn.ChnDirection());
|
||||
cc=cc+1;
|
||||
}
|
||||
WriteLine("D;" # intna # ";" # odev.Address() # ";" # odev.Name() # ";" # odev.HssType() # ";" # cc);
|
||||
@ -938,6 +980,58 @@ foreach (sDevName, sDevList.Split(",")) {
|
||||
}
|
||||
WriteLine (c);
|
||||
)
|
||||
},
|
||||
"GetDatapointList" => {
|
||||
description => "Query datapoint information of device list",
|
||||
syntax => "list",
|
||||
parameters => 1,
|
||||
code => qq(
|
||||
string chnid;
|
||||
string sDPId;
|
||||
string sDevice;
|
||||
string sDevList = "\$list";
|
||||
foreach (sDevice, sDevList.Split(",")) {
|
||||
object odev = dom.GetObject (sDevice);
|
||||
if (odev) {
|
||||
string sType = odev.HssType();
|
||||
foreach (chnid, odev.Channels()) {
|
||||
object ochn = dom.GetObject(chnid);
|
||||
if (ochn) {
|
||||
string sAddr = ochn.Address();
|
||||
string sChnNo = sAddr.StrValueByIndex(":",1);
|
||||
foreach(sDPId, ochn.DPs()) {
|
||||
object oDP = dom.GetObject(sDPId);
|
||||
if (oDP) {
|
||||
string sDPName = oDP.Name().StrValueByIndex(".",2);
|
||||
WriteLine (sAddr # ";" # sType # ";" # sChnNo # ";" # sDPName # ";" # oDP.ValueType() # ";" # oDP.Operations());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
"GetChannel" => {
|
||||
description => "Get datapoints of channel list",
|
||||
syntax => "list, ccuget",
|
||||
parameters => 2,
|
||||
code => qq(
|
||||
string sDPId;
|
||||
string sChannel;
|
||||
string sChnList = "\$list";
|
||||
foreach (sChannel, sChnList.Split(",")) {
|
||||
object oChannel = dom.GetObject (sChannel);
|
||||
if (oChannel) {
|
||||
foreach(sDPId, oChannel.DPs()) {
|
||||
object oDP = dom.GetObject(sDPId);
|
||||
if (oDP) {
|
||||
WriteLine (sChannel # "=" # oDP.Name() # "=" # oDP.\$ccuget());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user