2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-08 13:24:56 +00:00

HMCCU: Reading updates and HmIP only

git-svn-id: https://svn.fhem.de/fhem/trunk@18253 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2019-01-14 15:10:14 +00:00
parent ddb4e23e06
commit 39cbcf2692
2 changed files with 76 additions and 40 deletions

View File

@ -4,7 +4,7 @@
#
# $Id$
#
# Version 4.3.009
# Version 4.3.010
#
# Module for communication between FHEM and Homematic CCU2/3.
#
@ -51,9 +51,9 @@ my %HMCCU_CUST_CHN_DEFAULTS;
my %HMCCU_CUST_DEV_DEFAULTS;
# HMCCU version
my $HMCCU_VERSION = '4.3.009';
my $HMCCU_VERSION = '4.3.010';
# Default RPC port (BidCos-RF)
# Default RPC interface and port (BidCos-RF)
my $HMCCU_RPC_PORT_DEFAULT = 2001;
my $HMCCU_RPC_INTERFACE_DEFAULT = 'BidCos-RF';
@ -63,7 +63,7 @@ my $HMCCU_MAX_QUEUESIZE = 500;
my $HMCCU_TIME_WAIT = 100000;
my $HMCCU_TIME_TRIGGER = 10;
# RPC ping interval for interface BidCos-RF, should be smaller than HMCCU_TIMEOUT_EVENT
# RPC ping interval for default interface, should be smaller than HMCCU_TIMEOUT_EVENT
my $HMCCU_TIME_PING = 300;
my $HMCCU_TIMEOUT_CONNECTION = 10;
@ -272,6 +272,7 @@ sub HMCCU_GetAddress ($$$$);
sub HMCCU_GetAffectedAddresses ($);
sub HMCCU_GetCCUDeviceParam ($$);
sub HMCCU_GetChannelName ($$$);
sub HMCCU_GetDefaultInterface ($);
sub HMCCU_GetDeviceChannels ($$$);
sub HMCCU_GetDeviceInfo ($$$);
sub HMCCU_GetDeviceInterface ($$$);
@ -463,6 +464,8 @@ sub HMCCU_Define ($$)
$hash->{hmccu}{updatetime} = 0;
$hash->{hmccu}{rpccount} = 0;
$hash->{hmccu}{rpcports} = $HMCCU_RPC_PORT_DEFAULT;
$hash->{hmccu}{defInterface} = $HMCCU_RPC_INTERFACE_DEFAULT;
$hash->{hmccu}{defPort} = $HMCCU_RPC_PORT_DEFAULT;
readingsBeginUpdate ($hash);
readingsBulkUpdate ($hash, "state", "Initialized");
@ -622,7 +625,8 @@ sub HMCCU_Attr ($@)
delete $hash->{RPCDEV} if (exists ($hash->{RPCDEV}));
}
elsif ($attrname eq 'rpcport' || $attrname eq 'rpcinterfaces') {
$hash->{hmccu}{rpcports} = $HMCCU_RPC_PORT_DEFAULT;
my ($defInterface, $defPort) = HMCCU_GetDefaultInterface ($hash);
$hash->{hmccu}{rpcports} = $defPort;
}
}
@ -1504,9 +1508,7 @@ sub HMCCU_Set ($@)
else {
# If output is not related to a channel store reading in I/O device
my $Value = HMCCU_Substitute ($tokens[1], $substitute, 0, undef, $tokens[0]);
my $rn = $tokens[0];
$rn =~ s/\:/\./g;
$rn =~ s/[^A-Za-z\d_\.-]+/_/g;
my $rn = HMCCU_CorrectName ($tokens[0]);
readingsSingleUpdate ($hash, $rn, $Value, 1);
}
}
@ -2039,6 +2041,8 @@ sub HMCCU_ParseObject ($$$)
my ($i, $a, $c, $d, $n, $f) = ('', '', '', '', '', '', 0);
my $extaddr;
my ($defInterface, $defPort) = HMCCU_GetDefaultInterface ($hash);
# "ccu:" is default. Remove it.
$object =~ s/^ccu://g;
@ -2145,7 +2149,7 @@ sub HMCCU_ParseObject ($$$)
$f = $f | $HMCCU_FLAG_CHANNEL;
}
if ($flags & $HMCCU_FLAG_FULLADDR) {
($i, $a, $c) = (HMCCU_GetDeviceInterface ($hash, $add, 'BidCos-RF'), $add, $chn);
($i, $a, $c) = (HMCCU_GetDeviceInterface ($hash, $add, $defInterface), $add, $chn);
$f |= $HMCCU_FLAG_INTERFACE;
$f |= $HMCCU_FLAG_ADDRESS if ($add ne '');
$f |= $HMCCU_FLAG_CHANNEL if ($chn ne '');
@ -2153,7 +2157,7 @@ sub HMCCU_ParseObject ($$$)
}
elsif ($f & $HMCCU_FLAG_ADDRESS && $i eq '' &&
($flags & $HMCCU_FLAG_FULLADDR || $flags & $HMCCU_FLAG_INTERFACE)) {
$i = HMCCU_GetDeviceInterface ($hash, $a, 'BidCos-RF');
$i = HMCCU_GetDeviceInterface ($hash, $a, $defInterface);
$f |= $HMCCU_FLAG_INTERFACE;
}
@ -2270,7 +2274,8 @@ sub HMCCU_FilterReading ($$$)
# Address,Datapoint
# Address,ChannelNo,Datapoint
#
# Reading names can be modified by setting attribut ccureadingname.
# Reading names can be modified or new readings can be added by
# setting attribut ccureadingname.
# Returns list of readings names.
######################################################################
@ -2305,9 +2310,6 @@ sub HMCCU_GetReadingName ($$$$$$$)
else { return ''; }
}
# Substitue unsupported characters in reading name
$n = HMCCU_CorrectName ($n);
return '' if ($n eq '');
$rn = $n.'.'.$d;
}
@ -2350,7 +2352,8 @@ sub HMCCU_GetReadingName ($$$$$$$)
# Convert to lowercase
$rnlist[0] = lc($rnlist[0]) if ($rf =~ /lc$/);
return @rnlist;
# Return array of corrected reading names
return map { HMCCU_CorrectName ($_) } @rnlist;
}
######################################################################
@ -3405,14 +3408,15 @@ sub HMCCU_UpdatePeers ($$$$)
######################################################################
# Get list of valid RPC interfaces.
# Binary interfaces are ignored if internal RPC server is used.
# Default interface is BidCos-RF.
# Default interface is BidCos-RF or HmIP-RF.
######################################################################
sub HMCCU_GetRPCInterfaceList ($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my @interfaces = ($HMCCU_RPC_INTERFACE_DEFAULT);
my ($defInterface, $defPort) = HMCCU_GetDefaultInterface ($hash);
my @interfaces = ($defInterface);
my $ccuflags = HMCCU_GetFlags ($name);
@ -3421,7 +3425,7 @@ sub HMCCU_GetRPCInterfaceList ($)
my $ifname = HMCCU_GetRPCServerInfo ($hash, $p, 'name');
next if (!defined ($ifname));
my $iftype = HMCCU_GetRPCServerInfo ($hash, $ifname, 'type');
next if ($ifname eq $HMCCU_RPC_INTERFACE_DEFAULT ||
next if ($ifname eq $defInterface ||
($iftype eq 'B' && $ccuflags !~ /(extrpc|procrpc)/) ||
!exists ($hash->{hmccu}{interfaces}{$ifname}));
push (@interfaces, $ifname);
@ -3441,7 +3445,8 @@ sub HMCCU_GetRPCPortList ($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my @ports = ($HMCCU_RPC_PORT_DEFAULT);
my ($defInterface, $defPort) = HMCCU_GetDefaultInterface ($hash);
my @ports = ($defPort);
my $ccuflags = HMCCU_GetFlags ($name);
@ -3450,7 +3455,7 @@ sub HMCCU_GetRPCPortList ($)
my $ifname = HMCCU_GetRPCServerInfo ($hash, $p, 'name');
next if (!defined ($ifname));
my $iftype = HMCCU_GetRPCServerInfo ($hash, $ifname, 'type');
next if ($p == $HMCCU_RPC_PORT_DEFAULT ||
next if ($p == $defPort ||
($iftype eq 'B' && $ccuflags !~ /(extrpc|procrpc)/) ||
!exists ($hash->{hmccu}{interfaces}{$ifname}));
push (@ports, $p);
@ -3461,8 +3466,8 @@ sub HMCCU_GetRPCPortList ($)
}
######################################################################
# Called by HMCCURPCPROC device of interface BidCos-RF when no events
# from CCU were received for a specified time span.
# Called by HMCCURPCPROC device of default interface
# when no events from CCU were received for a specified time span.
# Return 1 if all RPC servers have been registered successfully.
# Return 0 if at least one RPC server failed to register or the
# corresponding HMCCURPCPROC device was not found.
@ -4353,9 +4358,25 @@ sub HMCCU_GetDeviceList ($)
}
if (scalar (keys %objects) > 0) {
# Update some CCU I/O device information
$hash->{ccuinterfaces} = join (',', keys %{$hash->{hmccu}{interfaces}});
if ($ifcount > 0) {
$hash->{ccuinterfaces} = join (',', keys %{$hash->{hmccu}{interfaces}});
if (!exists ($hash->{hmccu}{interfaces}{'BidCos-RF'})) {
if (exists ($hash->{hmccu}{interfaces}{'HmIP-RF'})) {
$hash->{hmccu}{defInterface} = 'HmIP-RF';
$hash->{hmccu}{defPort} = 2010;
HMCCU_Log ($hash, 1, "Changed default interface from BidCos-RF to HmIP-RF", 0);
}
else {
HMCCU_Log ($hash, 1, "Neither interface BidCos-RF nor HmIP-RF does exist on CCU", 0);
return (-1, -1, -1, -1, -1);
}
}
}
else {
HMCCU_Log ($hash, 1, "Found no interfaces on CCU", 0);
return (-1, -1, -1, -1, -1);
}
# Update HMCCU device tables
($devcount, $chncount) = HMCCU_UpdateDeviceTable ($hash, \%objects);
@ -4872,6 +4893,20 @@ sub HMCCU_GetDeviceChannels ($$$)
return 0;
}
######################################################################
# Get default RPC interface and port
######################################################################
sub HMCCU_GetDefaultInterface ($)
{
my ($hash) = @_;
my $ifname = exists ($hash->{hmccu}{defInterface}) ? $hash->{hmccu}{defInterface} : $HMCCU_RPC_INTERFACE_DEFAULT;
my $ifport = exists ($hash->{hmccu}{defPort}) ? $hash->{hmccu}{defPort} : $HMCCU_RPC_PORT_DEFAULT;
return ($ifname, $ifport);
}
######################################################################
# Get interface of a CCU device by address.
# Channel number will be removed if specified.
@ -8072,7 +8107,7 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
</li><br/>
<li><b>rpcinterfaces &lt;interface&gt;[,...]</b><br/>
Specify list of CCU RPC interfaces. HMCCU will register a RPC server for each interface.
Interface BidCos-RF is default and always active. Valid interfaces are:<br/><br/>
Either interface BidCos-RF or HmIP-RF (HmIP only) is default. Valid interfaces are:<br/><br/>
<ul>
<li>BidCos-Wired (Port 2000)</li>
<li>BidCos-RF (Port 2001)</li>
@ -8094,7 +8129,7 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
</li><br/>
<li><b>rpcport &lt;value[,...]&gt;</b><br/>
Deprecated, use attribute 'rpcinterfaces' instead. Specify list of RPC ports on CCU.
Default is 2001. Valid RPC ports are:<br/><br/>
Either port 2001 or 2010 (HmIP only) is default. Valid RPC ports are:<br/><br/>
<ul>
<li>2000 = Wired components</li>
<li>2001 = BidCos-RF (wireless 868 MHz components with BidCos protocol)</li>

View File

@ -4,7 +4,7 @@
#
# $Id$
#
# Version 1.4
# Version 1.5
#
# Subprocess based RPC Server module for HMCCU.
#
@ -35,7 +35,7 @@ use SetExtensions;
######################################################################
# HMCCURPC version
my $HMCCURPCPROC_VERSION = '1.4';
my $HMCCURPCPROC_VERSION = '1.5';
# Maximum number of events processed per call of Read()
my $HMCCURPCPROC_MAX_EVENTS = 100;
@ -52,7 +52,7 @@ my $HMCCURPCPROC_MAX_QUEUESEND = 70;
# Time to wait after data processing loop in microseconds
my $HMCCURPCPROC_TIME_WAIT = 100000;
# RPC ping interval for interface BidCos-RF, should be smaller than HMCCURPCPROC_TIMEOUT_EVENT
# RPC ping interval for default interface, should be smaller than HMCCURPCPROC_TIMEOUT_EVENT
my $HMCCURPCPROC_TIME_PING = 300;
# Timeout for established CCU connection in seconds
@ -70,9 +70,6 @@ my $HMCCURPCPROC_TIMEOUT_EVENT = 0;
# Send statistic information after specified amount of events
my $HMCCURPCPROC_STATISTICS = 500;
# Default RPC Port = BidCos-RF
my $HMCCURPCPROC_RPC_PORT_DEFAULT = 2001;
# Default RPC server base port
my $HMCCURPCPROC_SERVER_PORT = 5400;
@ -777,6 +774,7 @@ sub HMCCURPCPROC_ProcessEvent ($$)
my $rpcname = 'CB'.$hash->{rpcport}.$hash->{rpcid};
my $rh = \%{$hash->{hmccu}{rpc}}; # Just for code simplification
my $hmccu_hash = $hash->{IODev};
my ($defInterface, $defPort) = HMCCU_GetDefaultInterface ($hmccu_hash);
# Number of arguments in RPC events (without event type and clkey)
my %rpceventargs = (
@ -795,7 +793,7 @@ sub HMCCURPCPROC_ProcessEvent ($$)
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my $ping = AttrVal ($hmccu_hash->{NAME}, 'rpcPingCCU', $HMCCURPCPROC_TIME_PING);
my $evttimeout = ($ping > 0 && $hash->{rpcinterface} eq 'BidCos-RF') ? $ping*2 :
my $evttimeout = ($ping > 0 && $hash->{rpcinterface} eq $defInterface) ? $ping*2 :
HMCCURPCPROC_GetAttribute ($hash, 'rpcEventTimeout', 'rpcevtimeout', $HMCCURPCPROC_TIMEOUT_EVENT);
return undef if (!defined ($event) || $event eq '');
@ -955,8 +953,8 @@ sub HMCCURPCPROC_ProcessEvent ($$)
if ($evttimeout > 0 && $t[0] > $evttimeout) {
Log3 $name, 2, "HMCCURPCPROC: [$name] Received no events from interface $clkey for ".$t[0]." seconds";
$hash->{ccustate} = 'timeout';
if ($hash->{RPCState} eq 'running' && $hash->{rpcport} == 2001) {
# If interface is BidCos-RF inform IO device about timeout
if ($hash->{RPCState} eq 'running' && $hash->{rpcport} == $defPort) {
# If interface is default interface inform IO device about timeout
HMCCU_EventsTimedOut ($hmccu_hash)
}
DoTrigger ($name, "No events from interface $clkey for ".$t[0]." seconds");
@ -1208,6 +1206,7 @@ sub HMCCURPCPROC_StartRPCServer ($)
my ($hash) = @_;
my $name = $hash->{NAME};
my $hmccu_hash = $hash->{IODev};
my ($defInterface, $defPort) = HMCCU_GetDefaultInterface ($hmccu_hash);
# Local IP address and callback ID should be set during device definition
return (0, "Local address and/or callback ID not defined")
@ -1220,7 +1219,7 @@ sub HMCCURPCPROC_StartRPCServer ($)
my $ping = AttrVal ($hmccu_hash->{NAME}, 'rpcPingCCU', $HMCCURPCPROC_TIME_PING);
my $localaddr = HMCCURPCPROC_GetAttribute ($hash, undef, 'rpcserveraddr', $hash->{hmccu}{localaddr});
my $rpcserverport = HMCCURPCPROC_GetAttribute ($hash, 'rpcServerPort', 'rpcserverport', $HMCCURPCPROC_SERVER_PORT);
my $evttimeout = ($ping > 0 && $hash->{rpcinterface} eq 'BidCos-RF') ?
my $evttimeout = ($ping > 0 && $hash->{rpcinterface} eq $defInterface) ?
$ping*2 :
HMCCURPCPROC_GetAttribute ($hash, 'rpcEventTimeout', 'rpcevtimeout', $HMCCURPCPROC_TIMEOUT_EVENT);
my $ccunum = $hash->{CCUNum};
@ -1332,6 +1331,7 @@ sub HMCCURPCPROC_RPCServerStarted ($)
my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid};
my $ifname = $hash->{rpcinterface};
my $ping = AttrVal ($hmccu_hash->{NAME}, 'rpcPingCCU', $HMCCURPCPROC_TIME_PING);
my ($defInterface, $defPort) = HMCCU_GetDefaultInterface ($hmccu_hash);
# Check if RPC servers are running. Set overall status
if (HMCCURPCPROC_CheckProcessState ($hash, 'running')) {
@ -1347,8 +1347,8 @@ sub HMCCURPCPROC_RPCServerStarted ($)
RemoveInternalTimer ($hash, "HMCCURPCPROC_IsRPCServerRunning");
# Activate heartbeat if interface is BidCos-RF and rpcPingCCU > 0
if ($ping > 0 && $ifname eq "BidCos-RF") {
# Activate heartbeat if interface is default interface and rpcPingCCU > 0
if ($ping > 0 && $ifname eq $defInterface) {
Log3 $name, 1, "HMCCURPCPROC: [$name] Scheduled CCU ping every $ping seconds";
InternalTimer (gettimeofday()+$ping, "HMCCURPCPROC_RPCPing", $hash, 0);
}
@ -1654,8 +1654,9 @@ sub HMCCURPCPROC_RPCPing ($)
my $name = $hash->{NAME};
my $hmccu_hash = $hash->{IODev};
my $ping = AttrVal ($hmccu_hash->{NAME}, 'rpcPingCCU', $HMCCURPCPROC_TIME_PING);
my ($defInterface, $defPort) = HMCCU_GetDefaultInterface ($hmccu_hash);
if ($hash->{rpcinterface} eq 'BidCos-RF') {
if ($hash->{rpcinterface} eq $defInterface) {
if ($ping > 0) {
if ($init_done && HMCCURPCPROC_CheckProcessState ($hash, 'running')) {
my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid};