2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-29 11:27:08 +00:00

HMCCU: Support for multiple FHEM instances

git-svn-id: https://svn.fhem.de/fhem/trunk@16629 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2018-04-17 11:47:40 +00:00
parent 7c4473127b
commit 2ab1967bb3
3 changed files with 90 additions and 105 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it. # Do not insert empty lines here, update check depends on it.
- change: 88_HMCCU: minor changes
- feature: 93_DbRep: new function dbValue, DbReadingsVal (blocking) - feature: 93_DbRep: new function dbValue, DbReadingsVal (blocking)
- bugfix: 93_DbLog: 3.10.7, create addLog-event if reading was not found - bugfix: 93_DbLog: 3.10.7, create addLog-event if reading was not found
- bugfix: 73_GardenaSmartBridge: add error trigger for notify sub - bugfix: 73_GardenaSmartBridge: add error trigger for notify sub

View File

@ -4,7 +4,7 @@
# #
# $Id$ # $Id$
# #
# Version 4.2.004 # Version 4.2.005
# #
# Module for communication between FHEM and Homematic CCU2. # Module for communication between FHEM and Homematic CCU2.
# #
@ -105,7 +105,7 @@ my %HMCCU_CUST_CHN_DEFAULTS;
my %HMCCU_CUST_DEV_DEFAULTS; my %HMCCU_CUST_DEV_DEFAULTS;
# HMCCU version # HMCCU version
my $HMCCU_VERSION = '4.2.004'; my $HMCCU_VERSION = '4.2.005';
# Default RPC port (BidCos-RF) # Default RPC port (BidCos-RF)
my $HMCCU_RPC_PORT_DEFAULT = 2001; my $HMCCU_RPC_PORT_DEFAULT = 2001;
@ -267,7 +267,6 @@ sub HMCCU_GetAddress ($$$$);
sub HMCCU_IsDevAddr ($$); sub HMCCU_IsDevAddr ($$);
sub HMCCU_IsChnAddr ($$); sub HMCCU_IsChnAddr ($$);
sub HMCCU_SplitChnAddr ($); sub HMCCU_SplitChnAddr ($);
sub HMCCU_GetCCUObjectAttribute ($$$);
sub HMCCU_FindClientDevices ($$$$); sub HMCCU_FindClientDevices ($$$$);
sub HMCCU_GetRPCDevice ($$$); sub HMCCU_GetRPCDevice ($$$);
sub HMCCU_FindIODevice ($); sub HMCCU_FindIODevice ($);
@ -424,6 +423,7 @@ sub HMCCU_Define ($$)
$hash->{version} = $HMCCU_VERSION; $hash->{version} = $HMCCU_VERSION;
$hash->{ccutype} = 'CCU2'; $hash->{ccutype} = 'CCU2';
$hash->{RPCState} = "inactive"; $hash->{RPCState} = "inactive";
$hash->{NOTIFYDEV} = "global,TYPE=(HMCCU|HMCCUDEV|HMCCUCHN)";
Log3 $name, 1, "HMCCU: Device $name. Initialized version $HMCCU_VERSION"; Log3 $name, 1, "HMCCU: Device $name. Initialized version $HMCCU_VERSION";
my ($devcnt, $chncnt, $ifcount) = HMCCU_GetDeviceList ($hash); my ($devcnt, $chncnt, $ifcount) = HMCCU_GetDeviceList ($hash);
@ -497,6 +497,9 @@ sub HMCCU_Attr ($@)
if (HMCCU_IsRPCServerRunning ($hash, undef, undef)); if (HMCCU_IsRPCServerRunning ($hash, undef, undef));
} }
} }
if ($attrval =~ /(extrpc|intrpc)/) {
HMCCU_Log ($hash, 1, "RPC server mode $1 is deprecated. Please use procrpc instead", 0);
}
} }
elsif ($attrname eq 'rpcdevice') { elsif ($attrname eq 'rpcdevice') {
return "HMCCU: Can't find HMCCURPC device $attrval" return "HMCCU: Can't find HMCCURPC device $attrval"
@ -1211,12 +1214,10 @@ sub HMCCU_Set ($@)
return HMCCU_SetError ($hash, $usage) if (!defined ($program)); return HMCCU_SetError ($hash, $usage) if (!defined ($program));
my $url = qq(http://$host:8181/do.exe?r1=dom.GetObject("$program").ProgramExecute()); my $cmd = qq(dom.GetObject("$program").ProgramExecute());
$response = GetFileFromURL ($url, $ccureqtimeout); my $value = HMCCU_HMCommand ($hash, $cmd, 0);
$response =~ m/<r1>(.*)<\/r1>/;
my $value = $1;
return HMCCU_SetState ($hash, "OK") if (defined ($value) && $value ne '' && $value ne 'null'); return HMCCU_SetState ($hash, "OK") if (defined ($value));
return HMCCU_SetError ($hash, "Program execution error"); return HMCCU_SetError ($hash, "Program execution error");
} }
elsif ($opt eq 'hmscript') { elsif ($opt eq 'hmscript') {
@ -1674,7 +1675,7 @@ sub HMCCU_Get ($@)
my $ch = $defs{$dev}; my $ch = $defs{$dev};
my $ct = uc($ch->{ccutype}); my $ct = uc($ch->{ccutype});
my $fw = defined ($ch->{firmware}) ? $ch->{firmware} : 'N/A'; my $fw = defined ($ch->{firmware}) ? $ch->{firmware} : 'N/A';
next if (!exists ($hash->{hmccu}{type}{$ct})); next if (!exists ($hash->{hmccu}{type}{$ct}) || $ct !~ /$dtexp/);
$result .= sprintf "%-25s %-20s %-7s <a href=\"http://www.eq-3.de/%s\">%-9s</a> %-10s\n", $result .= sprintf "%-25s %-20s %-7s <a href=\"http://www.eq-3.de/%s\">%-9s</a> %-10s\n",
$ch->{NAME}, $ct, $fw, $hash->{hmccu}{type}{$ct}{download}, $ch->{NAME}, $ct, $fw, $hash->{hmccu}{type}{$ct}{download},
$hash->{hmccu}{type}{$ct}{firmware}, $hash->{hmccu}{type}{$ct}{date}; $hash->{hmccu}{type}{$ct}{firmware}, $hash->{hmccu}{type}{$ct}{date};
@ -4429,28 +4430,6 @@ sub HMCCU_SplitChnAddr ($)
return ($dev, $chn); return ($dev, $chn);
} }
######################################################################
# Query object attribute from CCU. Attribute must be a valid method
# for specified object, i.e. Address()
######################################################################
sub HMCCU_GetCCUObjectAttribute ($$$)
{
my ($hash, $object, $attr) = @_;
my $name = $hash->{NAME};
my $ccureqtimeout = AttrVal ($name, "ccuReqTimeout", $HMCCU_TIMEOUT_REQUEST);
my $url = 'http://'.$hash->{host}.':8181/do.exe?r1=dom.GetObject("'.$object.'").'.$attr;
my $response = GetFileFromURL ($url, $ccureqtimeout);
if (defined ($response) && $response !~ /<r1>null</) {
if ($response =~ /<r1>(.+)<\/r1>/) {
return $1;
}
}
return undef;
}
###################################################################### ######################################################################
# Get list of client devices matching the specified criteria. # Get list of client devices matching the specified criteria.
# If no criteria is specified all device names will be returned. # If no criteria is specified all device names will be returned.
@ -5235,6 +5214,11 @@ sub HMCCU_HMScriptExt ($$$)
my $code = $hmscript; my $code = $hmscript;
my $scrname = ''; my $scrname = '';
if (!exists ($hash->{host})) {
Log3 $name, 2, "HMCCU: CCU host name not defined. Name=$name Type=".$hash->{TYPE};
return "ERROR: CCU host name not defined";
}
# Check for internal script # Check for internal script
if ($hmscript =~ /^!(.*)$/) { if ($hmscript =~ /^!(.*)$/) {
$scrname = $1; $scrname = $1;
@ -5317,14 +5301,13 @@ sub HMCCU_GetDatapoint ($@)
{ {
my ($hash, $param) = @_; my ($hash, $param) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $type = $hash->{TYPE};
my $fnc = "GetDatapoint"; my $fnc = "GetDatapoint";
my $hmccu_hash; my $hmccu_hash;
my $value = ''; my $value = '';
$hmccu_hash = HMCCU_GetHash ($hash); $hmccu_hash = HMCCU_GetHash ($hash);
return (-3, $value) if (!defined ($hmccu_hash)); return (-3, $value) if (!defined ($hmccu_hash));
return (-4, $value) if ($type ne 'HMCCU' && $hash->{ccudevstate} eq 'deleted'); return (-4, $value) if ($hash->{TYPE} ne 'HMCCU' && $hash->{ccudevstate} eq 'deleted');
my $readingformat = HMCCU_GetAttrReadingFormat ($hash, $hmccu_hash); my $readingformat = HMCCU_GetAttrReadingFormat ($hash, $hmccu_hash);
my ($statechn, $statedpt, $controlchn, $controldpt) = HMCCU_GetSpecialDatapoints ( my ($statechn, $statedpt, $controlchn, $controldpt) = HMCCU_GetSpecialDatapoints (
@ -5332,28 +5315,22 @@ sub HMCCU_GetDatapoint ($@)
my $ccuget = HMCCU_GetAttribute ($hmccu_hash, $hash, 'ccuget', 'Value'); my $ccuget = HMCCU_GetAttribute ($hmccu_hash, $hash, 'ccuget', 'Value');
my $ccureqtimeout = AttrVal ($hmccu_hash->{NAME}, "ccuReqTimeout", $HMCCU_TIMEOUT_REQUEST); my $ccureqtimeout = AttrVal ($hmccu_hash->{NAME}, "ccuReqTimeout", $HMCCU_TIMEOUT_REQUEST);
my $url = 'http://'.$hmccu_hash->{host}.':8181/do.exe?r1=dom.GetObject("'; my $cmd = '';
my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($hmccu_hash, $param, my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($hmccu_hash, $param,
$HMCCU_FLAG_INTERFACE); $HMCCU_FLAG_INTERFACE);
return (-1, $value) if ($flags != $HMCCU_FLAGS_IACD && $flags != $HMCCU_FLAGS_NCD);
if ($flags == $HMCCU_FLAGS_IACD) { if ($flags == $HMCCU_FLAGS_IACD) {
$url .= $int.'.'.$add.':'.$chn.'.'.$dpt.'").'.$ccuget.'()'; $cmd = '(datapoints.Get("'.$int.'.'.$add.':'.$chn.'.'.$dpt.'")).'.$ccuget.'()';
} }
elsif ($flags == $HMCCU_FLAGS_NCD) { elsif ($flags == $HMCCU_FLAGS_NCD) {
$url .= $nam.'").DPByHssDP("'.$dpt.'").'.$ccuget.'()'; $cmd = '(dom.GetObject(ID_CHANNELS)).Get("'.$nam.'").DPByHssDP("'.$dpt.'").'.$ccuget.'()';
($add, $chn) = HMCCU_GetAddress ($hmccu_hash, $nam, '', ''); ($add, $chn) = HMCCU_GetAddress ($hmccu_hash, $nam, '', '');
} }
else {
return (-1, $value);
}
HMCCU_Trace ($hash, 2, $fnc, "URL=$url, param=$param, ccuget=$ccuget"); HMCCU_Trace ($hash, 2, $fnc, "CMD=$cmd, param=$param, ccuget=$ccuget");
my $rawresponse = GetFileFromURL ($url, $ccureqtimeout); $value = HMCCU_HMCommand ($hmccu_hash, $cmd, 1);
my $response = $rawresponse;
$response =~ m/<r1>(.*)<\/r1>/;
$value = $1;
HMCCU_Trace ($hash, 2, $fnc, "Response = ".$rawresponse);
if (defined ($value) && $value ne '' && $value ne 'null') { if (defined ($value) && $value ne '' && $value ne 'null') {
$value = HMCCU_UpdateSingleDatapoint ($hash, $chn, $dpt, $value); $value = HMCCU_UpdateSingleDatapoint ($hash, $chn, $dpt, $value);
@ -5361,7 +5338,7 @@ sub HMCCU_GetDatapoint ($@)
return (1, $value); return (1, $value);
} }
else { else {
Log3 $name, 1, "$type: Error URL = ".$url; HMCCU_Log ($hash, 1, "Error CMD = $cmd", 0);
return (-2, ''); return (-2, '');
} }
} }
@ -5407,7 +5384,7 @@ sub HMCCU_SetDatapoint ($$$)
$param = $1; $param = $1;
} }
my $cmd = 'dom.GetObject("'; my $cmd = '';
my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($hmccu_hash, $param, my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($hmccu_hash, $param,
$HMCCU_FLAG_INTERFACE); $HMCCU_FLAG_INTERFACE);
return -1 if ($flags != $HMCCU_FLAGS_IACD && $flags != $HMCCU_FLAGS_NCD); return -1 if ($flags != $HMCCU_FLAGS_IACD && $flags != $HMCCU_FLAGS_NCD);
@ -5425,11 +5402,11 @@ sub HMCCU_SetDatapoint ($$$)
} }
if ($flags == $HMCCU_FLAGS_IACD) { if ($flags == $HMCCU_FLAGS_IACD) {
$cmd .= $int.'.'.$add.':'.$chn.'.'.$dpt.'").State('.$value.')'; $cmd = '(datapoints.Get("'.$int.'.'.$add.':'.$chn.'.'.$dpt.'")).State('.$value.')';
$nam = HMCCU_GetChannelName ($hmccu_hash, $add.":".$chn, ''); $nam = HMCCU_GetChannelName ($hmccu_hash, $add.":".$chn, '');
} }
elsif ($flags == $HMCCU_FLAGS_NCD) { elsif ($flags == $HMCCU_FLAGS_NCD) {
$cmd .= $nam.'").DPByHssDP("'.$dpt.'").State('.$value.')'; $cmd = '(dom.GetObject(ID_CHANNELS)).Get("'.$nam.'").DPByHssDP("'.$dpt.'").State('.$value.')';
($add, $chn) = HMCCU_GetAddress ($hmccu_hash, $nam, '', ''); ($add, $chn) = HMCCU_GetAddress ($hmccu_hash, $nam, '', '');
} }
@ -5581,12 +5558,9 @@ sub HMCCU_SetVariable ($$$$$)
); );
if (!defined ($vartype)) { if (!defined ($vartype)) {
my $url = 'http://'.$hash->{host}.':8181/do.exe?r1=dom.GetObject("'.$varname. my $cmd = qq(dom.GetObject("$varname").State("$value"));
'").State("'.$value.'")'; my $response = HMCCU_HMCommand ($hash, $cmd, 1);
return HMCCU_Log ($hash, 1, "CMD=$cmd", -2) if (!defined ($response));
my $response = GetFileFromURL ($url, $ccureqtimeout);
return HMCCU_Log ($hash, 1, "URL=$url", -2)
if (!defined ($response) || $response =~ /<r1>null</);
} }
else { else {
return -18 if (!exists ($varfnc{$vartype})); return -18 if (!exists ($varfnc{$vartype}));

View File

@ -4,7 +4,7 @@
# #
# $Id$ # $Id$
# #
# Version 1.0.002 # Version 1.0.003
# #
# Subprocess based RPC Server module for HMCCU. # Subprocess based RPC Server module for HMCCU.
# #
@ -35,7 +35,7 @@ use SetExtensions;
###################################################################### ######################################################################
# HMCCURPC version # HMCCURPC version
my $HMCCURPCPROC_VERSION = '1.0.002'; my $HMCCURPCPROC_VERSION = '1.0.003';
# Maximum number of events processed per call of Read() # Maximum number of events processed per call of Read()
my $HMCCURPCPROC_MAX_EVENTS = 100; my $HMCCURPCPROC_MAX_EVENTS = 100;
@ -82,7 +82,7 @@ my $HMCCURPCPROC_INIT_INTERVAL2 = 30;
# Delay for RPC server functionality check after start # Delay for RPC server functionality check after start
my $HMCCURPCPROC_INIT_INTERVAL3 = 25; my $HMCCURPCPROC_INIT_INTERVAL3 = 25;
# Data types # BinRPC data types
my $BINRPC_INTEGER = 1; my $BINRPC_INTEGER = 1;
my $BINRPC_BOOL = 2; my $BINRPC_BOOL = 2;
my $BINRPC_STRING = 3; my $BINRPC_STRING = 3;
@ -91,7 +91,7 @@ my $BINRPC_BASE64 = 17;
my $BINRPC_ARRAY = 256; my $BINRPC_ARRAY = 256;
my $BINRPC_STRUCT = 257; my $BINRPC_STRUCT = 257;
# Message types # BinRPC message types
my $BINRPC_REQUEST = 0x42696E00; my $BINRPC_REQUEST = 0x42696E00;
my $BINRPC_RESPONSE = 0x42696E01; my $BINRPC_RESPONSE = 0x42696E01;
my $BINRPC_REQUEST_HEADER = 0x42696E40; my $BINRPC_REQUEST_HEADER = 0x42696E40;
@ -116,6 +116,7 @@ sub HMCCURPCPROC_SetState ($$);
sub HMCCURPCPROC_ProcessEvent ($$); sub HMCCURPCPROC_ProcessEvent ($$);
# RPC server functions # RPC server functions
sub HMCCURPCPROC_GetRPCServerID ($$);
sub HMCCURPCPROC_RegisterCallback ($$); sub HMCCURPCPROC_RegisterCallback ($$);
sub HMCCURPCPROC_DeRegisterCallback ($$); sub HMCCURPCPROC_DeRegisterCallback ($$);
sub HMCCURPCPROC_InitRPCServer ($$$$); sub HMCCURPCPROC_InitRPCServer ($$$$);
@ -220,7 +221,7 @@ sub HMCCURPCPROC_Define ($$)
my $ioname = $h->{iodev}; my $ioname = $h->{iodev};
return $usage if (scalar (@$a) < 3); return $usage if (scalar (@$a) < 3);
return "HMCCU I/O device $ioname not found" if (!exists ($defs{$ioname})); return "HMCCU I/O device $ioname not found" if (!exists ($defs{$ioname}));
return "Device $ioname is no HMCCU device" if ($defs{$ioname}->{TYPE} ne 'HMCCU'); return "Device $ioname is not a HMCCU device" if ($defs{$ioname}->{TYPE} ne 'HMCCU');
$hmccu_hash = $defs{$ioname}; $hmccu_hash = $defs{$ioname};
$hash->{host} = $hmccu_hash->{host}; $hash->{host} = $hmccu_hash->{host};
$iface = $$a[2]; $iface = $$a[2];
@ -229,18 +230,18 @@ sub HMCCURPCPROC_Define ($$)
return $usage if (scalar (@$a) < 4); return $usage if (scalar (@$a) < 4);
$hash->{host} = $$a[2]; $hash->{host} = $$a[2];
$iface = $$a[3]; $iface = $$a[3];
}
# Find IO device # Find IO device
for my $d (keys %defs) { for my $d (keys %defs) {
my $dh = $defs{$d}; my $dh = $defs{$d};
next if (!exists ($dh->{TYPE}) || !exists ($dh->{NAME})); next if (!exists ($dh->{TYPE}) || !exists ($dh->{NAME}));
if ($dh->{TYPE} eq 'HMCCU' && $dh->{host} eq $hash->{host}) { if ($dh->{TYPE} eq 'HMCCU' && $dh->{host} eq $hash->{host}) {
$hmccu_hash = $dh; $hmccu_hash = $dh;
last; last;
}
} }
return "Can't find HMCCU I/O device" if (!defined ($hmccu_hash));
} }
return "Can't find HMCCU I/O device" if (!defined ($hmccu_hash));
# Check if interface is valid # Check if interface is valid
my $ifname = HMCCU_GetRPCServerInfo ($hmccu_hash, $iface, 'name'); my $ifname = HMCCU_GetRPCServerInfo ($hmccu_hash, $iface, 'name');
@ -423,7 +424,8 @@ sub HMCCURPCPROC_Get ($@)
if ($opt eq 'rpcevents') { if ($opt eq 'rpcevents') {
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL", "TO"); my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL", "TO");
my $clkey = 'CB'.$hash->{rpcport}; my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid};
$result = "Event statistics for server $clkey\n"; $result = "Event statistics for server $clkey\n";
$result .= "Average event delay = ".$hash->{hmccu}{rpc}{avgdelay}."\n" $result .= "Average event delay = ".$hash->{hmccu}{rpc}{avgdelay}."\n"
if (defined ($hash->{hmccu}{rpc}{avgdelay})); if (defined ($hash->{hmccu}{rpc}{avgdelay}));
@ -440,11 +442,11 @@ sub HMCCURPCPROC_Get ($@)
return $result eq '' ? "No event statistics found" : $result; return $result eq '' ? "No event statistics found" : $result;
} }
elsif ($opt eq 'rpcstate') { elsif ($opt eq 'rpcstate') {
my $clkey = 'CB'.$hash->{rpcport}; my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid};
$result = "ID RPC-Process State \n"; $result = "PID RPC-Process State \n";
$result .= "-----------------------\n"; $result .= "--------------------------\n";
my $sid = defined ($hash->{hmccu}{rpc}{pid}) ? sprintf ("%2d", $hash->{hmccu}{rpc}{pid}) : "N/A"; my $sid = defined ($hash->{hmccu}{rpc}{pid}) ? sprintf ("%5d", $hash->{hmccu}{rpc}{pid}) : "N/A ";
my $sname = sprintf ("%-6s", $clkey); my $sname = sprintf ("%-10s", $clkey);
$result .= $sid." ".$sname." ".$hash->{hmccu}{rpc}{state}."\n"; $result .= $sid." ".$sname." ".$hash->{hmccu}{rpc}{state}."\n";
return $result; return $result;
} }
@ -623,6 +625,7 @@ sub HMCCURPCPROC_ResetRPCState ($)
$hash->{RPCPID} = "0"; $hash->{RPCPID} = "0";
$hash->{hmccu}{rpc}{pid} = undef; $hash->{hmccu}{rpc}{pid} = undef;
$hash->{hmccu}{rpc}{clkey} = undef;
$hash->{hmccu}{evtime} = 0; $hash->{hmccu}{evtime} = 0;
$hash->{hmccu}{rpcstarttime} = 0; $hash->{hmccu}{rpcstarttime} = 0;
@ -648,7 +651,7 @@ sub HMCCURPCPROC_ProcessEvent ($$)
{ {
my ($hash, $event) = @_; my ($hash, $event) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $rpcname = 'CB'.$hash->{rpcport}; my $rpcname = 'CB'.$hash->{rpcport}.$hash->{rpcid};
my $rh = \%{$hash->{hmccu}{rpc}}; # Just for code simplification my $rh = \%{$hash->{hmccu}{rpc}}; # Just for code simplification
my $hmccu_hash = $hash->{IODev}; my $hmccu_hash = $hash->{IODev};
@ -886,7 +889,7 @@ sub HMCCURPCPROC_RegisterCallback ($$)
my $port = $hash->{rpcport}; my $port = $hash->{rpcport};
my $serveraddr = $hash->{host}; my $serveraddr = $hash->{host};
my $localaddr = $hash->{hmccu}{localaddr}; my $localaddr = $hash->{hmccu}{localaddr};
my $clkey = 'CB'.$port; my $clkey = 'CB'.$port.$hash->{rpcid};
return (0, "RPC server $clkey not in state working") return (0, "RPC server $clkey not in state working")
if ($hash->{hmccu}{rpc}{state} ne 'working' && $force == 0); if ($hash->{hmccu}{rpc}{state} ne 'working' && $force == 0);
@ -932,7 +935,7 @@ sub HMCCURPCPROC_DeRegisterCallback ($$)
my $hmccu_hash = $hash->{IODev}; my $hmccu_hash = $hash->{IODev};
my $port = $hash->{rpcport}; my $port = $hash->{rpcport};
my $clkey = 'CB'.$port; my $clkey = 'CB'.$port.$hash->{rpcid};
my $localaddr = $hash->{hmccu}{localaddr}; my $localaddr = $hash->{hmccu}{localaddr};
my $cburl = ''; my $cburl = '';
my $clurl = ''; my $clurl = '';
@ -978,8 +981,7 @@ sub HMCCURPCPROC_DeRegisterCallback ($$)
sub HMCCURPCPROC_InitRPCServer ($$$$) sub HMCCURPCPROC_InitRPCServer ($$$$)
{ {
my ($name, $serverport, $callbackport, $prot) = @_; my ($name, $clkey, $callbackport, $prot) = @_;
my $clkey = 'CB'.$serverport;
my $server; my $server;
# Create binary RPC server # Create binary RPC server
@ -1095,6 +1097,22 @@ sub HMCCURPCPROC_StartRPCServer ($)
my $serveraddr = HMCCU_GetRPCServerInfo ($hmccu_hash, $rpcport, 'host'); my $serveraddr = HMCCU_GetRPCServerInfo ($hmccu_hash, $rpcport, 'host');
my $interface = HMCCU_GetRPCServerInfo ($hmccu_hash, $rpcport, 'name'); my $interface = HMCCU_GetRPCServerInfo ($hmccu_hash, $rpcport, 'name');
# Detect local IP address
if ($localaddr eq '') {
my $socket = IO::Socket::INET->new (PeerAddr => $serveraddr, PeerPort => $rpcport);
return (0, "Can't connect to CCU port $rpcport") if (!$socket);
$localaddr = $socket->sockhost ();
close ($socket);
}
$hash->{hmccu}{localaddr} = $localaddr;
# Get unique ID for RPC server: last segment of local IP address followed by 2 random digits
my @ipseg = split (/\./, $localaddr);
return (0, "Invalid local IP address $localaddr") if (scalar (@ipseg) != 4);
my $base = (time() % 10)+1;
$hash->{rpcid} = sprintf ("%03d", $ipseg[3]) . join '', map int rand ($base), 1..2;
my $clkey = 'CB'.$rpcport.$hash->{rpcid};
# Store parameters for child process # Store parameters for child process
$procpar{socktimeout} = AttrVal ($name, 'rpcWriteTimeout', $HMCCURPCPROC_TIMEOUT_WRITE); $procpar{socktimeout} = AttrVal ($name, 'rpcWriteTimeout', $HMCCURPCPROC_TIMEOUT_WRITE);
$procpar{conntimeout} = AttrVal ($name, 'rpcConnTimeout', $HMCCURPCPROC_TIMEOUT_CONNECTION); $procpar{conntimeout} = AttrVal ($name, 'rpcConnTimeout', $HMCCURPCPROC_TIMEOUT_CONNECTION);
@ -1110,18 +1128,10 @@ sub HMCCURPCPROC_StartRPCServer ($)
$procpar{flags} = HMCCU_GetRPCServerInfo ($hmccu_hash, $rpcport, 'flags'); $procpar{flags} = HMCCU_GetRPCServerInfo ($hmccu_hash, $rpcport, 'flags');
$procpar{type} = HMCCU_GetRPCServerInfo ($hmccu_hash, $rpcport, 'type'); $procpar{type} = HMCCU_GetRPCServerInfo ($hmccu_hash, $rpcport, 'type');
$procpar{name} = $name; $procpar{name} = $name;
$procpar{clkey} = $clkey;
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL", "TO"); my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL", "TO");
# Detect local IP address
if ($localaddr eq '') {
my $socket = IO::Socket::INET->new (PeerAddr => $serveraddr, PeerPort => $rpcport);
return (0, "Can't connect to CCU port $rpcport") if (!$socket);
$localaddr = $socket->sockhost ();
close ($socket);
}
$hash->{hmccu}{localaddr} = $localaddr;
# Reset state of server processes # Reset state of server processes
$hash->{hmccu}{rpc}{state} = 'inactive'; $hash->{hmccu}{rpc}{state} = 'inactive';
@ -1142,7 +1152,6 @@ sub HMCCURPCPROC_StartRPCServer ($)
# Initialize RPC server # Initialize RPC server
my $err = ''; my $err = '';
my %srvprocpar; my %srvprocpar;
my $clkey = 'CB'.$rpcport;
my $callbackport = $rpcserverport+$rpcport+($ccunum*10); my $callbackport = $rpcserverport+$rpcport+($ccunum*10);
# Start RPC server process # Start RPC server process
@ -1166,6 +1175,7 @@ sub HMCCURPCPROC_StartRPCServer ($)
Log3 $name, 2, "HMCCURPCPROC: [$name] RPC server process started for interface $interface with PID=$rpcpid"; Log3 $name, 2, "HMCCURPCPROC: [$name] RPC server process started for interface $interface with PID=$rpcpid";
# Store process parameters # Store process parameters
$hash->{hmccu}{rpc}{clkey} = $clkey;
$hash->{hmccu}{rpc}{cbport} = $callbackport; $hash->{hmccu}{rpc}{cbport} = $callbackport;
$hash->{hmccu}{rpc}{pid} = $rpcpid; $hash->{hmccu}{rpc}{pid} = $rpcpid;
$hash->{hmccu}{rpc}{state} = 'initialized'; $hash->{hmccu}{rpc}{state} = 'initialized';
@ -1180,12 +1190,11 @@ sub HMCCURPCPROC_StartRPCServer ($)
$hash->{RPCPID} = $rpcpid; $hash->{RPCPID} = $rpcpid;
# Trigger Timer function for checking successful RPC start # Trigger Timer function for checking successful RPC start
# Timer will be removed if event 'IN' is reveived # Timer will be removed before execution if event 'IN' is reveived
InternalTimer (gettimeofday()+$HMCCURPCPROC_INIT_INTERVAL3, "HMCCURPCPROC_IsRPCServerRunning", InternalTimer (gettimeofday()+$HMCCURPCPROC_INIT_INTERVAL3, "HMCCURPCPROC_IsRPCServerRunning",
$hash, 0); $hash, 0);
HMCCURPCPROC_SetRPCState ($hash, "starting", "RPC server starting", 1); HMCCURPCPROC_SetRPCState ($hash, "starting", "RPC server starting", 1);
DoTrigger ($name, "RPC server starting"); DoTrigger ($name, "RPC server starting");
return (1, undef); return (1, undef);
@ -1202,7 +1211,7 @@ sub HMCCURPCPROC_RPCServerStarted ($)
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $hmccu_hash = $hash->{IODev}; my $hmccu_hash = $hash->{IODev};
my $clkey = 'CB'.$hash->{rpcport}; my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid};
my $ifname = $hash->{rpcinterface}; my $ifname = $hash->{rpcinterface};
# Check if RPC servers are running. Set overall status # Check if RPC servers are running. Set overall status
@ -1231,7 +1240,7 @@ sub HMCCURPCPROC_RPCServerStopped ($)
{ {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $clkey = 'CB'.$hash->{rpcport}; my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid};
HMCCURPCPROC_CleanupProcess ($hash); HMCCURPCPROC_CleanupProcess ($hash);
HMCCURPCPROC_CleanupIO ($hash); HMCCURPCPROC_CleanupIO ($hash);
@ -1279,7 +1288,7 @@ sub HMCCURPCPROC_TerminateProcess ($)
{ {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $clkey = 'CB'.$hash->{rpcport}; my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid};
# return 0 if ($hash->{hmccu}{rpc}{state} eq 'inactive'); # return 0 if ($hash->{hmccu}{rpc}{state} eq 'inactive');
@ -1304,7 +1313,7 @@ sub HMCCURPCPROC_CleanupProcess ($)
{ {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $clkey = 'CB'.$hash->{rpcport}; my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid};
# return 1 if ($hash->{hmccu}{rpc}{state} eq 'inactive'); # return 1 if ($hash->{hmccu}{rpc}{state} eq 'inactive');
@ -1342,7 +1351,7 @@ sub HMCCURPCPROC_CleanupProcess ($)
sub HMCCURPCPROC_CheckProcessState ($$) sub HMCCURPCPROC_CheckProcessState ($$)
{ {
my ($hash, $state) = @_; my ($hash, $state) = @_;
my $prcname = 'CB'.$hash->{rpcport}; my $prcname = 'CB'.$hash->{rpcport}.$hash->{rpcid};
my $pstate = $hash->{hmccu}{rpc}{state}; my $pstate = $hash->{hmccu}{rpc}{state};
if ($state eq 'running' || $state eq '.*') { if ($state eq 'running' || $state eq '.*') {
@ -1404,7 +1413,7 @@ sub HMCCURPCPROC_StopRPCServer ($)
{ {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $clkey = 'CB'.$hash->{rpcport}; my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid};
if (HMCCURPCPROC_CheckProcessState ($hash, 'running')) { if (HMCCURPCPROC_CheckProcessState ($hash, 'running')) {
Log3 $name, 1, "HMCCURPCPROC: [$name] Stopping RPC server $clkey"; Log3 $name, 1, "HMCCURPCPROC: [$name] Stopping RPC server $clkey";
@ -1435,6 +1444,7 @@ sub HMCCURPCPROC_StopRPCServer ($)
###################################################################### ######################################################################
# Send RPC request to CCU. # Send RPC request to CCU.
# Supports XML and BINRPC requests.
# Return response or undef on error. # Return response or undef on error.
###################################################################### ######################################################################
@ -1572,18 +1582,18 @@ sub HMCCURPCPROC_HandleConnection ($$$$)
my $socktimeout = $procpar->{socktimeout}; my $socktimeout = $procpar->{socktimeout};
my $maxsnd = $procpar->{queuesend}; my $maxsnd = $procpar->{queuesend};
my $maxioerrors = $procpar->{maxioerrors}; my $maxioerrors = $procpar->{maxioerrors};
my $clkey = $procpar->{clkey};
my $ioerrors = 0; my $ioerrors = 0;
my $sioerrors = 0; my $sioerrors = 0;
my $run = 1; my $run = 1;
my $pid = $$; my $pid = $$;
my $clkey = 'CB'.$port;
my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL", "TO"); my @eventtypes = ("EV", "ND", "DD", "RD", "RA", "UD", "IN", "EX", "SL", "TO");
# Initialize RPC server # Initialize RPC server
Log3 $name, 2, "CCURPC: [$name] Initializing RPC server $clkey for interface $iface"; Log3 $name, 2, "CCURPC: [$name] Initializing RPC server $clkey for interface $iface";
my $rpcsrv = HMCCURPCPROC_InitRPCServer ($name, $port, $callbackport, $prot); my $rpcsrv = HMCCURPCPROC_InitRPCServer ($name, $clkey, $callbackport, $prot);
if (!defined ($rpcsrv)) { if (!defined ($rpcsrv)) {
Log3 $name, 1, "CCURPC: [$name] Can't initialize RPC server $clkey for interface $iface"; Log3 $name, 1, "CCURPC: [$name] Can't initialize RPC server $clkey for interface $iface";
return; return;