mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-27 20:34:52 +00:00
HMCCU: Features and bugfixes
git-svn-id: https://svn.fhem.de/fhem/trunk@28502 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
61ab9d1e23
commit
104b705e03
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@
|
||||
#
|
||||
# Version 5.0
|
||||
#
|
||||
# (c) 2022 zap (zap01 <at> t-online <dot> de)
|
||||
# (c) 2024 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
######################################################################
|
||||
# Client device for Homematic channels.
|
||||
@ -30,7 +30,7 @@ sub HMCCUCHN_Set ($@);
|
||||
sub HMCCUCHN_Get ($@);
|
||||
sub HMCCUCHN_Attr ($@);
|
||||
|
||||
my $HMCCUCHN_VERSION = '5.0 240121821';
|
||||
my $HMCCUCHN_VERSION = '5.0 2024-02';
|
||||
|
||||
######################################################################
|
||||
# Initialize module
|
||||
@ -51,7 +51,7 @@ sub HMCCUCHN_Initialize ($)
|
||||
$hash->{parseParams} = 1;
|
||||
|
||||
$hash->{AttrList} = 'IODev ccucalculate '.
|
||||
'ccuflags:multiple-strict,hideStdReadings,replaceStdReadings,noBoundsChecking,ackState,logCommand,noAutoSubstitute,noReadings,trace,simulate,showMasterReadings,showLinkReadings,showDeviceReadings,showServiceReadings '.
|
||||
'ccuflags:multiple-strict,hideStdReadings,replaceStdReadings,noBoundsChecking,ackState,logCommand,noAutoSubstitute,noReadings,trace,simulate,showMasterReadings,showLinkReadings,showDeviceReadings '.
|
||||
'ccureadingfilter:textField-long statedatapoint controldatapoint '.
|
||||
'ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc '.
|
||||
'ccureadingname:textField-long ccuSetOnChange ccuReadingPrefix '.
|
||||
@ -212,7 +212,7 @@ sub HMCCUCHN_InitDevice ($$)
|
||||
$rc = -2;
|
||||
}
|
||||
|
||||
HMCCU_GetUpdate ($devHash, $da);
|
||||
HMCCU_ExecuteGetExtValuesCommand ($devHash, $da);
|
||||
}
|
||||
|
||||
return $rc;
|
||||
@ -352,9 +352,6 @@ sub HMCCUCHN_Set ($@)
|
||||
elsif ($lcopt eq 'datapoint') {
|
||||
return HMCCU_ExecuteSetDatapointCommand ($hash, $a, $h);
|
||||
}
|
||||
# elsif ($lcopt eq 'toggle') {
|
||||
# return HMCCU_ExecuteToggleCommand ($hash);
|
||||
# }
|
||||
elsif (exists($hash->{hmccu}{roleCmds}{set}{$opt})) {
|
||||
return HMCCU_ExecuteRoleCommand ($ioHash, $hash, 'set', $opt, $a, $h);
|
||||
}
|
||||
@ -455,7 +452,7 @@ sub HMCCUCHN_Get ($@)
|
||||
}
|
||||
elsif ($lcopt eq 'extvalues') {
|
||||
my $filter = shift @$a;
|
||||
my $rc = HMCCU_GetUpdate ($hash, $ccuaddr, $filter);
|
||||
my $rc = HMCCU_ExecuteGetExtValuesCommand ($hash, $ccuaddr, $filter);
|
||||
return $rc < 0 ? HMCCU_SetError ($hash, $rc) : 'OK';
|
||||
}
|
||||
elsif ($lcopt eq 'paramsetdesc') {
|
||||
@ -526,6 +523,9 @@ sub HMCCUCHN_Get ($@)
|
||||
<li><b>set <name> armState {DISARMED|EXTSENS_ARMED|ALLSENS_ARMED|ALARM_BLOCKED}</b><br/>
|
||||
[alarm siren] Set arm state.
|
||||
</li><br/>
|
||||
<li><b>set <name> calibrate {START|STOP}</b><br/>
|
||||
[blind] Run calibration.
|
||||
</li><br/>
|
||||
<li><b>set <name> clear [<reading-exp>|reset]</b><br/>
|
||||
Delete readings matching specified reading name expression. Default expression is '.*'.
|
||||
Readings 'state' and 'control' are not deleted. With option 'reset' all readings
|
||||
@ -687,7 +687,6 @@ sub HMCCUCHN_Get ($@)
|
||||
<li>showMasterReadings: Store configuration readings of parameter set 'MASTER' of current channel.</li>
|
||||
<li>showDeviceReadings: Store configuration readings of device and value readings of channel 0.</li>
|
||||
<li>showLinkReadings: Store readings of links.</li>
|
||||
<li>showServiceReadings: Store readings of parameter set 'SERVICE'</li>
|
||||
</ul>
|
||||
If non of the flags is set, only readings belonging to parameter set VALUES (datapoints)
|
||||
are stored.
|
||||
@ -776,7 +775,6 @@ sub HMCCUCHN_Get ($@)
|
||||
showDeviceReadings: Show readings of device and channel 0.<br/>
|
||||
showLinkReadings: Show link readings.<br/>
|
||||
showMasterReadings: Show configuration readings.<br/>
|
||||
showServiceReadings: Show service readings (HmIP only)<br/>
|
||||
trace: Write log file information for operations related to this device.
|
||||
</li><br/>
|
||||
<a name="ccuget"></a>
|
||||
@ -855,7 +853,6 @@ sub HMCCUCHN_Get ($@)
|
||||
MASTER (configuration parameters): 'R-'<br/>
|
||||
LINK (links parameters): 'L-'<br/>
|
||||
PEER (peering parameters): 'P-'<br/>
|
||||
SERVICE (service parameters): S-<br/>
|
||||
To hide prefix do not specify <i>prefix</i>.
|
||||
</li><br/>
|
||||
<a name="ccuscaleval"></a>
|
||||
|
@ -6,7 +6,7 @@
|
||||
#
|
||||
# Version 5.0
|
||||
#
|
||||
# (c) 2022 zap (zap01 <at> t-online <dot> de)
|
||||
# (c) 2024 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
######################################################################
|
||||
# Client device for Homematic devices.
|
||||
@ -31,7 +31,7 @@ sub HMCCUDEV_Set ($@);
|
||||
sub HMCCUDEV_Get ($@);
|
||||
sub HMCCUDEV_Attr ($@);
|
||||
|
||||
my $HMCCUDEV_VERSION = '5.0 240121821';
|
||||
my $HMCCUDEV_VERSION = '5.0 2024-02';
|
||||
|
||||
######################################################################
|
||||
# Initialize module
|
||||
@ -52,7 +52,7 @@ sub HMCCUDEV_Initialize ($)
|
||||
$hash->{parseParams} = 1;
|
||||
|
||||
$hash->{AttrList} = 'IODev ccuaggregate:textField-long ccucalculate:textField-long '.
|
||||
'ccuflags:multiple-strict,ackState,hideStdReadings,replaceStdReadings,noAutoSubstitute,noBoundsChecking,logCommand,noReadings,trace,simulate,showMasterReadings,showLinkReadings,showDeviceReadings,showServiceReadings '.
|
||||
'ccuflags:multiple-strict,ackState,hideStdReadings,replaceStdReadings,noAutoSubstitute,noBoundsChecking,logCommand,noReadings,trace,simulate,showMasterReadings,showLinkReadings,showDeviceReadings '.
|
||||
'ccureadingfilter:textField-long '.
|
||||
'ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc '.
|
||||
'ccureadingname:textField-long ccuSetOnChange ccuReadingPrefix devStateFlags '.
|
||||
@ -259,7 +259,7 @@ sub HMCCUDEV_InitDevice ($$)
|
||||
}
|
||||
|
||||
# Update readings
|
||||
HMCCU_GetUpdate ($devHash, $da);
|
||||
HMCCU_ExecuteGetExtValuesCommand ($devHash, $da);
|
||||
}
|
||||
|
||||
# Parse group options
|
||||
@ -437,9 +437,6 @@ sub HMCCUDEV_Set ($@)
|
||||
elsif ($lcopt eq 'datapoint') {
|
||||
return HMCCU_ExecuteSetDatapointCommand ($hash, $a, $h);
|
||||
}
|
||||
# elsif ($lcopt eq 'toggle') {
|
||||
# return HMCCU_ExecuteToggleCommand ($hash);
|
||||
# }
|
||||
elsif (exists($hash->{hmccu}{roleCmds}{set}{$opt})) {
|
||||
return HMCCU_ExecuteRoleCommand ($ioHash, $hash, 'set', $opt, $a, $h);
|
||||
}
|
||||
@ -541,7 +538,7 @@ sub HMCCUDEV_Get ($@)
|
||||
}
|
||||
elsif ($lcopt eq 'extvalues') {
|
||||
my $filter = shift @$a;
|
||||
my $rc = HMCCU_GetUpdate ($hash, $ccuaddr, $filter);
|
||||
my $rc = HMCCU_ExecuteGetExtValuesCommand ($hash, $ccuaddr, $filter);
|
||||
return $rc < 0 ? HMCCU_SetError ($hash, $rc) : 'OK';
|
||||
}
|
||||
elsif ($lcopt eq 'paramsetdesc') {
|
||||
|
@ -8,7 +8,7 @@
|
||||
#
|
||||
# Subprocess based RPC Server module for HMCCU.
|
||||
#
|
||||
# (c) 2023 by zap (zap01 <at> t-online <dot> de)
|
||||
# (c) 2024 by zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
##############################################################################
|
||||
#
|
||||
@ -31,15 +31,12 @@ use RPC::XML::Client;
|
||||
use RPC::XML::Server;
|
||||
use SetExtensions;
|
||||
|
||||
# require "$attr{global}{modpath}/FHEM/88_HMCCU.pm";
|
||||
|
||||
|
||||
######################################################################
|
||||
# Constants
|
||||
######################################################################
|
||||
|
||||
# HMCCURPC version
|
||||
my $HMCCURPCPROC_VERSION = '5.0 240121821';
|
||||
my $HMCCURPCPROC_VERSION = '5.0 2024-02';
|
||||
|
||||
# Maximum number of events processed per call of Read()
|
||||
my $HMCCURPCPROC_MAX_EVENTS = 100;
|
||||
@ -89,6 +86,9 @@ my $HMCCURPCPROC_INIT_INTERVAL2 = 30;
|
||||
# Delay for RPC server functionality check after start in seconds
|
||||
my $HMCCURPCPROC_INIT_INTERVAL3 = 25;
|
||||
|
||||
# Interval for checking status of parent (FHEM) process in seconds
|
||||
my $HMCCURPCPROC_PARENT_CHECK_INTERVAL = 5;
|
||||
|
||||
my %HMCCURPCPROC_RPC_FLAGS = (
|
||||
'BidCos-Wired' => '_', 'BidCos-RF' => 'multicalls', 'HmIP-RF' => '_',
|
||||
'VirtualDevices' => '_', 'Homegear' => '_', 'CUxD' => '_',
|
||||
@ -133,7 +133,8 @@ my %RPC_METHODS = (
|
||||
'getValue' => [ 'STRING', 'STRING' ]
|
||||
);
|
||||
|
||||
# RPC event types
|
||||
# RPC event types:
|
||||
#
|
||||
# EV = Event
|
||||
# ND = New device
|
||||
# DD = Delete device
|
||||
@ -142,7 +143,7 @@ my %RPC_METHODS = (
|
||||
# UD = Update device
|
||||
# IN = Init RPC connection
|
||||
# EX = Exit RPC process
|
||||
# SL = Server loop
|
||||
# SL = Server loop (server is accepting connections)
|
||||
# ST = Statistics (not in list of event types)
|
||||
# TO = Timeout
|
||||
my @RPC_EVENT_TYPES = ('EV', 'ND', 'DD', 'RD', 'RA', 'UD', 'IN', 'EX', 'SL', 'TO');
|
||||
@ -211,7 +212,7 @@ sub HMCCURPCPROC_HandleConnection ($$$$);
|
||||
sub HMCCURPCPROC_SendQueue ($$$$);
|
||||
sub HMCCURPCPROC_SendData ($$);
|
||||
sub HMCCURPCPROC_ReceiveData ($$);
|
||||
sub HMCCURPCPROC_ReadFromSocket ($$$);
|
||||
sub HMCCURPCPROC_ReadFromSocket ($$);
|
||||
sub HMCCURPCPROC_DataAvailableOnSocket ($$);
|
||||
sub HMCCURPCPROC_WriteToSocket ($$$);
|
||||
sub HMCCURPCPROC_Write ($$$$);
|
||||
@ -569,7 +570,7 @@ sub HMCCURPCPROC_Shutdown ($)
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Set attribute
|
||||
# Set/delete attribute
|
||||
######################################################################
|
||||
|
||||
sub HMCCURPCPROC_Attr ($@)
|
||||
@ -577,12 +578,15 @@ sub HMCCURPCPROC_Attr ($@)
|
||||
my ($cmd, $name, $attrname, $attrval) = @_;
|
||||
my $hash = $defs{$name};
|
||||
my $ioHash = $hash->{IODev};
|
||||
my $restartRPC = 0;
|
||||
|
||||
if ($cmd eq 'set') {
|
||||
if ($attrname =~ /^(rpcAcceptTimeout|rpcReadTimeout|rpcWriteTimeout)$/ && $attrval == 0) {
|
||||
$restartRPC = 1;
|
||||
return "HMCCURPCPROC: [$name] Value for attribute $attrname must be greater than 0";
|
||||
}
|
||||
elsif ($attrname eq 'rpcServerAddr') {
|
||||
$restartRPC = 1;
|
||||
$hash->{hmccu}{localaddr} = $attrval;
|
||||
}
|
||||
elsif ($attrname eq 'rpcPingCCU') {
|
||||
@ -594,12 +598,13 @@ sub HMCCURPCPROC_Attr ($@)
|
||||
}
|
||||
elsif ($cmd eq 'del') {
|
||||
if ($attrname eq 'rpcServerAddr') {
|
||||
$restartRPC = 1;
|
||||
$hash->{hmccu}{localaddr} = $hash->{hmccu}{defaultaddr};
|
||||
}
|
||||
}
|
||||
|
||||
HMCCU_LogDisplay ($hash, 2, 'Please restart RPC server to apply attribute changes')
|
||||
if ($init_done && (!defined($ioHash) || $ioHash->{hmccu}{postInit} == 0) &&
|
||||
if ($restartRPC && $init_done && (!defined($ioHash) || $ioHash->{hmccu}{postInit} == 0) &&
|
||||
HMCCURPCPROC_CheckProcessState ($hash, 'running'));
|
||||
|
||||
return undef;
|
||||
@ -764,7 +769,6 @@ sub HMCCURPCPROC_Get ($@)
|
||||
$result .= "$eh->{$i}{k} / $dn : $eh->{$i}{v}\n";
|
||||
}
|
||||
}
|
||||
$result .= ('=' x 40)."\nRPC requests: ".$hash->{hmccu}{rpc}{requests};
|
||||
return $result eq '' ? 'No event statistics found' : $result;
|
||||
}
|
||||
elsif ($opt eq 'rpcstate') {
|
||||
@ -1406,6 +1410,9 @@ sub HMCCURPCPROC_RegisterCallback ($$)
|
||||
|
||||
######################################################################
|
||||
# Deregister RPC callbacks at CCU
|
||||
# force:
|
||||
# >0 - Ignore state of RPC server. Deregister in any case.
|
||||
# >1 - Do not update RPC server state.
|
||||
######################################################################
|
||||
|
||||
sub HMCCURPCPROC_DeRegisterCallback ($$)
|
||||
@ -1417,18 +1424,14 @@ sub HMCCURPCPROC_DeRegisterCallback ($$)
|
||||
my $port = $hash->{rpcport};
|
||||
my $clkey = HMCCURPCPROC_GetKey ($hash);
|
||||
my $localaddr = $hash->{hmccu}{localaddr};
|
||||
my $cburl = '';
|
||||
my $clurl = '';
|
||||
my $auth = '';
|
||||
my $rpchash = \%{$hash->{hmccu}{rpc}};
|
||||
|
||||
return (0, "RPC server $clkey not in state registered or running")
|
||||
if ($rpchash->{state} ne 'registered' && $rpchash->{state} ne 'running' && $force == 0);
|
||||
|
||||
$cburl = $rpchash->{cburl} if (exists($rpchash->{cburl}));
|
||||
$clurl = $rpchash->{clurl} if (exists($rpchash->{clurl}));
|
||||
$auth = $rpchash->{auth} if (exists($rpchash->{auth}));
|
||||
$cburl = HMCCU_GetRPCCallbackURL ($ioHash, $localaddr, $rpchash->{cbport}, $clkey, $port) if ($cburl eq '');
|
||||
my $cburl = $rpchash->{cburl} // HMCCU_GetRPCCallbackURL ($ioHash, $localaddr, $rpchash->{cbport}, $clkey, $port);
|
||||
my $clurl = $rpchash->{clurl} // '';
|
||||
my $auth = $rpchash->{auth} // '';
|
||||
($clurl, $auth) = HMCCU_BuildURL ($ioHash, $port) if ($clurl eq '');
|
||||
return (0, "Can't get RPC parameters for ID $clkey") if ($cburl eq '' || $clurl eq '');
|
||||
|
||||
@ -1439,7 +1442,7 @@ sub HMCCURPCPROC_DeRegisterCallback ($$)
|
||||
my $err;
|
||||
for (my $i=0; $i<2; $i++) {
|
||||
($resp, $err) = HMCCURPCPROC_SendRequest ($hash, "init", "$cburl:STRING", '');
|
||||
if (defined ($resp)) {
|
||||
if (defined ($resp) && $force < 2) {
|
||||
HMCCURPCPROC_SetRPCState ($hash, $force == 0 ? 'deregistered' : $rpchash->{state},
|
||||
"Callback for RPC server $clkey deregistered", 1);
|
||||
|
||||
@ -1576,23 +1579,31 @@ sub HMCCURPCPROC_StartRPCServer ($)
|
||||
my $rpcport = $hash->{rpcport};
|
||||
my ($serveraddr, $interface) = HMCCU_GetRPCServerInfo ($ioHash, $rpcport, 'host,name');
|
||||
my $clkey = 'CB'.$rpcport.$hash->{rpcid};
|
||||
my $callbackport = $rpcserverport+$rpcport+($ccunum*10);
|
||||
$hash->{hmccu}{localaddr} = $localaddr;
|
||||
|
||||
my ($clurl, $auth) = HMCCU_BuildURL ($ioHash, $hash->{rpcport});
|
||||
my ($flags, $type) = HMCCU_GetRPCServerInfo ($ioHash, $rpcport, 'flags,type');
|
||||
|
||||
# Store parameters for child process
|
||||
my %procpar;
|
||||
$procpar{socktimeout} = AttrVal ($name, 'rpcWriteTimeout', $HMCCURPCPROC_TIMEOUT_WRITE);
|
||||
$procpar{conntimeout} = AttrVal ($name, 'rpcConnTimeout', $HMCCURPCPROC_TIMEOUT_CONNECTION);
|
||||
$procpar{acctimeout} = AttrVal ($name, 'rpcAcceptTimeout', $HMCCURPCPROC_TIMEOUT_ACCEPT);
|
||||
$procpar{queuesize} = AttrVal ($name, 'rpcQueueSize', $HMCCURPCPROC_MAX_QUEUESIZE);
|
||||
$procpar{queuesend} = AttrVal ($name, 'rpcQueueSend', $HMCCURPCPROC_MAX_QUEUESEND);
|
||||
$procpar{statistics} = AttrVal ($name, 'rpcStatistics', $HMCCURPCPROC_STATISTICS);
|
||||
$procpar{maxioerrors} = AttrVal ($name, 'rpcMaxIOErrors', $HMCCURPCPROC_MAX_IOERRORS);
|
||||
$procpar{ccuflags} = AttrVal ($name, 'ccuflags', 'null');
|
||||
$procpar{evttimeout} = $evttimeout;
|
||||
$procpar{interface} = $interface;
|
||||
($procpar{flags}, $procpar{type}) = HMCCU_GetRPCServerInfo ($ioHash, $rpcport, 'flags,type');
|
||||
$procpar{name} = $name;
|
||||
$procpar{clkey} = $clkey;
|
||||
my %procpar = (
|
||||
socktimeout => AttrVal ($name, 'rpcWriteTimeout', $HMCCURPCPROC_TIMEOUT_WRITE),
|
||||
conntimeout => AttrVal ($name, 'rpcConnTimeout', $HMCCURPCPROC_TIMEOUT_CONNECTION),
|
||||
acctimeout => AttrVal ($name, 'rpcAcceptTimeout', $HMCCURPCPROC_TIMEOUT_ACCEPT),
|
||||
queuesize => AttrVal ($name, 'rpcQueueSize', $HMCCURPCPROC_MAX_QUEUESIZE),
|
||||
queuesend => AttrVal ($name, 'rpcQueueSend', $HMCCURPCPROC_MAX_QUEUESEND),
|
||||
statistics => AttrVal ($name, 'rpcStatistics', $HMCCURPCPROC_STATISTICS),
|
||||
maxioerrors => AttrVal ($name, 'rpcMaxIOErrors', $HMCCURPCPROC_MAX_IOERRORS),
|
||||
ccuflags => AttrVal ($name, 'ccuflags', 'null'),
|
||||
name => $name,
|
||||
evttimeout => $evttimeout,
|
||||
serveraddr => $serveraddr,
|
||||
interface => $interface,
|
||||
clkey => $clkey,
|
||||
flags => $flags,
|
||||
type => $type,
|
||||
parentPID => $$
|
||||
);
|
||||
|
||||
# Reset state of server processes
|
||||
$hash->{hmccu}{rpc}{state} = 'inactive';
|
||||
@ -1603,18 +1614,16 @@ sub HMCCURPCPROC_StartRPCServer ($)
|
||||
if (!socketpair ($sockchild, $sockparent, AF_UNIX, SOCK_STREAM, PF_UNSPEC));
|
||||
$sockchild->autoflush (1);
|
||||
$sockparent->autoflush (1);
|
||||
$hash->{hmccu}{sockparent} = $sockparent;
|
||||
$hash->{hmccu}{sockchild} = $sockchild;
|
||||
$hash->{hmccu}{sockparent} = $sockparent;
|
||||
$hash->{hmccu}{sockchild} = $sockchild;
|
||||
|
||||
# Enable FHEM I/O, calculate RPC server port
|
||||
my $pid = $$;
|
||||
$hash->{FD} = fileno $sockchild;
|
||||
$selectlist{"RPC.$name.$pid"} = $hash;
|
||||
my $callbackport = $rpcserverport+$rpcport+($ccunum*10);
|
||||
|
||||
# Initialize RPC server
|
||||
# my $err = '';
|
||||
# my %srvprocpar;
|
||||
|
||||
$hash->{hmccu}{rpc}{clkey} = $clkey;
|
||||
$hash->{hmccu}{rpc}{cbport} = $callbackport;
|
||||
|
||||
# Start RPC server process
|
||||
my $rpcpid = fhemFork ();
|
||||
@ -1623,7 +1632,7 @@ sub HMCCURPCPROC_StartRPCServer ($)
|
||||
close ($sockchild);
|
||||
return (0, "Can't create RPC server process for interface $interface");
|
||||
}
|
||||
|
||||
|
||||
if (!$rpcpid) {
|
||||
# Child process, only needs parent socket
|
||||
HMCCURPCPROC_HandleConnection ($rpcport, $callbackport, $sockparent, \%procpar);
|
||||
@ -1631,15 +1640,13 @@ sub HMCCURPCPROC_StartRPCServer ($)
|
||||
# Connection loop ended. Close sockets and exit child process
|
||||
close ($sockparent);
|
||||
close ($sockchild);
|
||||
exit (0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
# Parent process
|
||||
HMCCU_Log ($hash, 2, "RPC server process started for interface $interface with PID=$rpcpid");
|
||||
|
||||
# Store process parameters
|
||||
$hash->{hmccu}{rpc}{clkey} = $clkey;
|
||||
$hash->{hmccu}{rpc}{cbport} = $callbackport;
|
||||
$hash->{hmccu}{rpc}{pid} = $rpcpid;
|
||||
$hash->{hmccu}{rpc}{state} = 'initialized';
|
||||
|
||||
@ -1687,7 +1694,7 @@ sub HMCCURPCPROC_RPCServerStarted ($)
|
||||
# Update client devices if interface is managed by HMCCURPCPROC device.
|
||||
# Normally interfaces are managed by HMCCU device.
|
||||
if ($ioHash->{hmccu}{interfaces}{$ifname}{manager} eq 'HMCCURPCPROC') {
|
||||
HMCCU_UpdateClients ($ioHash, '.*', 'Attr', 0, $ifname, 1);
|
||||
HMCCU_UpdateClients ($ioHash, '.*', 'Attr', $ifname, 1);
|
||||
}
|
||||
|
||||
RemoveInternalTimer ($hash, "HMCCURPCPROC_IsRPCServerRunning");
|
||||
@ -2081,6 +2088,12 @@ sub HMCCURPCPROC_ProcessMulticallResponse ($$$$$)
|
||||
######################################################################
|
||||
# Send RPC request to CCU.
|
||||
# Supports XML and BINRPC requests.
|
||||
# Parameters:
|
||||
# hash - FHEM hash reference or parameter hash reference
|
||||
# Parameter hash used by sub processes:
|
||||
# NAME - HMCCURPCPROC device name
|
||||
# rpcport - CCU RPC port
|
||||
# methods - list of RPC methods
|
||||
# Return value:
|
||||
# (response, undef) - Request successful
|
||||
# (undef, error) - Request failed with error
|
||||
@ -2089,22 +2102,29 @@ sub HMCCURPCPROC_ProcessMulticallResponse ($$$$$)
|
||||
sub HMCCURPCPROC_SendRequest ($@)
|
||||
{
|
||||
my ($hash, $request, @param) = @_;
|
||||
my $port = $hash->{rpcport};
|
||||
|
||||
my $ph = exists($hash->{TYPE}) ? 0 : 1;
|
||||
|
||||
my $ioHash = $hash->{IODev};
|
||||
if (!defined($ioHash)) {
|
||||
if (!$ph && !defined($ioHash)) {
|
||||
HMCCU_Log ($hash, 2, 'I/O device not found');
|
||||
return (undef, 'I/O device not found');
|
||||
}
|
||||
|
||||
my $port = $hash->{rpcport};
|
||||
my $multicalls = 0;
|
||||
if (!$ph) {
|
||||
$multicalls = 1 if (
|
||||
!HMCCU_IsFlag ($hash, 'noMulticalls') && defined($hash->{hmccu}{rpc}{multicall}) &&
|
||||
HMCCU_IsRPCType ($ioHash, $port, 'A')
|
||||
);
|
||||
}
|
||||
|
||||
my $retry = AttrVal ($hash->{NAME}, 'rpcRetryRequest', 1);
|
||||
$retry = 2 if ($retry > 2);
|
||||
$hash->{hmccu}{rpc}{requests} //= 0; # Count RPC requests
|
||||
|
||||
# Multicall request
|
||||
if ($request eq 'system.multicall' && (
|
||||
HMCCU_IsFlag ($hash, 'noMulticalls') || !defined($hash->{hmccu}{rpc}{multicall}) || HMCCU_IsRPCType ($ioHash, $port, 'B')
|
||||
)) {
|
||||
if ($request eq 'system.multicall' && !$multicalls) {
|
||||
# If multicalls are not supported or disabled, execute multiple requests
|
||||
my @respList = ();
|
||||
my $reqList = shift @param; # Reference to request array
|
||||
@ -2143,13 +2163,11 @@ sub HMCCURPCPROC_SendRequest ($@)
|
||||
for (my $reqNo=0; $reqNo<=$retry; $reqNo++) {
|
||||
if (HMCCU_IsRPCType ($ioHash, $port, 'A')) {
|
||||
# XML RPC request
|
||||
$hash->{hmccu}{rpc}{requests}++;
|
||||
($resp, $err) = HMCCURPCPROC_SendXMLRequest ($hash, $ioHash, $request, @param);
|
||||
last if (defined($resp));
|
||||
}
|
||||
elsif (HMCCU_IsRPCType ($ioHash, $port, 'B')) {
|
||||
# Binary RPC request
|
||||
$hash->{hmccu}{rpc}{requests}++;
|
||||
($resp, $err) = HMCCURPCPROC_SendBINRequest ($hash, $ioHash, $request, @param);
|
||||
last if (defined($resp));
|
||||
}
|
||||
@ -2258,7 +2276,7 @@ sub HMCCURPCPROC_SendBINRequest ($@)
|
||||
|
||||
my ($bytesWritten, $errmsg) = HMCCURPCPROC_WriteToSocket ($hash->{hmccu}{rpc}{connection}, $encreq, $timeoutWrite);
|
||||
if ($bytesWritten > 0) {
|
||||
my ($bytesRead, $encresp) = HMCCURPCPROC_ReadFromSocket ($hash, $hash->{hmccu}{rpc}{connection}, $timeoutRead);
|
||||
my ($bytesRead, $encresp) = HMCCURPCPROC_ReadFromSocket ($hash->{hmccu}{rpc}{connection}, $timeoutRead);
|
||||
# $socket->close ();
|
||||
|
||||
if ($bytesRead > 0) {
|
||||
@ -2374,6 +2392,7 @@ sub HMCCURPCPROC_HandleConnection ($$$$)
|
||||
my $maxsnd = $procpar->{queuesend};
|
||||
my $maxioerrors = $procpar->{maxioerrors};
|
||||
my $clkey = $procpar->{clkey};
|
||||
my $parentPID = $procpar->{parentPID};
|
||||
|
||||
my $ioerrors = 0;
|
||||
my $sioerrors = 0;
|
||||
@ -2408,20 +2427,34 @@ sub HMCCURPCPROC_HandleConnection ($$$$)
|
||||
$rpcsrv->{hmccu}{snd}{$et} = 0;
|
||||
}
|
||||
|
||||
# Recover device hash
|
||||
my $rpcDeviceHash = $defs{$name};
|
||||
|
||||
# Signal handler
|
||||
$SIG{INT} = sub { $run = 0; HMCCU_Log ($name, 2, "$clkey received signal INT"); };
|
||||
|
||||
my $checkTime = time(); # At this point in time we checked the state of the parent process
|
||||
|
||||
HMCCURPCPROC_Write ($rpcsrv, 'SL', $clkey, $pid);
|
||||
HMCCU_Log ($name, 2, "$clkey accepting connections. PID=$pid");
|
||||
|
||||
$rpcsrv->{__daemon}->timeout ($acctimeout) if ($acctimeout > 0.0);
|
||||
|
||||
while ($run) {
|
||||
while ($run > 0) {
|
||||
my $currentTime = time();
|
||||
|
||||
# Check for event timeout
|
||||
if ($evttimeout > 0) {
|
||||
my $difftime = time()-$rpcsrv->{hmccu}{evttime};
|
||||
my $difftime = $currentTime-$rpcsrv->{hmccu}{evttime};
|
||||
HMCCURPCPROC_Write ($rpcsrv, 'TO', $clkey, $difftime) if ($difftime >= $evttimeout);
|
||||
}
|
||||
|
||||
|
||||
# Check if parent process is still running
|
||||
if ($currentTime-$checkTime > $HMCCURPCPROC_PARENT_CHECK_INTERVAL) {
|
||||
$run = kill(0, $parentPID) ? 1 : -1;
|
||||
$checkTime = $currentTime;
|
||||
}
|
||||
|
||||
# Send queue entries to parent process
|
||||
if (scalar (@queue) > 0) {
|
||||
HMCCU_Log ($name, 4, "RPC server $clkey sending data to FHEM");
|
||||
@ -2440,7 +2473,7 @@ sub HMCCURPCPROC_HandleConnection ($$$$)
|
||||
HMCCU_Log ($name, 4, "RPC server $clkey accepting connections");
|
||||
my $connection = $rpcsrv->{__daemon}->accept ();
|
||||
next if (! $connection);
|
||||
last if (! $run);
|
||||
last if ($run < 1);
|
||||
$connection->timeout ($conntimeout) if ($conntimeout > 0.0);
|
||||
|
||||
HMCCU_Log ($name, 4, "RPC server $clkey processing request");
|
||||
@ -2456,10 +2489,18 @@ sub HMCCURPCPROC_HandleConnection ($$$$)
|
||||
undef $connection;
|
||||
}
|
||||
|
||||
HMCCU_Log ($name, 1, "RPC server $clkey stopped handling connections. PID=$pid");
|
||||
HMCCU_Log ($name, 1, "RPC server $clkey stopped handling connections. PID=$pid run=$run");
|
||||
|
||||
close ($rpcsrv->{__daemon}) if ($prot eq 'B');
|
||||
|
||||
|
||||
if ($run < 0) {
|
||||
# Parent process not running: try to deregister callback URL and terminate RPC server process
|
||||
HMCCU_Log ($name, 1, "Parent process (FHEM,PID=$parentPID) not running. Shutting down RPC server process $clkey.");
|
||||
HMCCURPCPROC_DeRegisterCallback ($rpcDeviceHash, 1);
|
||||
HMCCU_Log ($name, 1, "FHEM will be restarted automatically if restart is enabled in system.d configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
# Send statistic info
|
||||
HMCCURPCPROC_WriteStats ($rpcsrv, $clkey);
|
||||
|
||||
@ -2593,9 +2634,9 @@ sub HMCCURPCPROC_ReceiveData ($$)
|
||||
# Return (BytesRead, Data) on success.
|
||||
######################################################################
|
||||
|
||||
sub HMCCURPCPROC_ReadFromSocket ($$$)
|
||||
sub HMCCURPCPROC_ReadFromSocket ($$)
|
||||
{
|
||||
my ($hash, $socket, $timeout) = @_;
|
||||
my ($socket, $timeout) = @_;
|
||||
|
||||
my $data = '';
|
||||
my $totalBytes = 0;
|
||||
|
@ -46,7 +46,8 @@ $HMCCU_CONFIG_VERSION = '5.0';
|
||||
######################################################################
|
||||
# Channel roles with state and control datapoints
|
||||
# F: 1=Channel/HMCCUCHN, 2=Device/HMCCUDEV, 3=Both
|
||||
# S: State datapoint, C: Control datapoint, V: Control values
|
||||
# S: State datapoint, C: Control datapoint,
|
||||
# V: Control values, #=Enum or const:value[,...]
|
||||
# P: Priority (used by HMCCUDEV if more than 1 channel role fits)
|
||||
# 1=lowest priority
|
||||
######################################################################
|
||||
@ -327,7 +328,7 @@ $HMCCU_CONFIG_VERSION = '5.0';
|
||||
# Set/Get commands related to channel role
|
||||
# Role => { Command-Definition, ... }
|
||||
# Command-Defintion:
|
||||
# [Mode ]Command[:InterfaceExpr] => [No:]Datapoint-Def[:Function] [...]'
|
||||
# '[Mode ]Command[:InterfaceExpr]' => '[CombDatapoint ][No:]Datapoint-Def[:Function] [...]'
|
||||
# Mode:
|
||||
# Either 'set' or 'get'. Default is 'set'.
|
||||
# Command:
|
||||
@ -335,6 +336,9 @@ $HMCCU_CONFIG_VERSION = '5.0';
|
||||
# InterfaceExpr:
|
||||
# Command is only available, if interface of device is matching the regular
|
||||
# expression.
|
||||
# CombDatapoint:
|
||||
# Either 'COMBINED_PARAMETER' or 'SUBMIT'
|
||||
# Datapoint names are combined datapoint shortcuts.
|
||||
# No:
|
||||
# Execution order of subcommands. By default subcommands are executed from left to
|
||||
# right.
|
||||
@ -375,7 +379,7 @@ $HMCCU_CONFIG_VERSION = '5.0';
|
||||
%HMCCU_ROLECMDS = (
|
||||
'ACOUSTIC_SIGNAL_TRANSMITTER' => {
|
||||
'level' => 'V:LEVEL:?level',
|
||||
'on' => 'V:LEVEL:1',
|
||||
'on' => 'V:LEVEL:100',
|
||||
'off' => 'V:LEVEL:0'
|
||||
},
|
||||
'ALARM_SWITCH_VIRTUAL_RECEIVER' => {
|
||||
@ -388,7 +392,7 @@ $HMCCU_CONFIG_VERSION = '5.0';
|
||||
},
|
||||
'BLIND' => {
|
||||
'pct' => 'V:LEVEL:?level',
|
||||
'open' => 'V:LEVEL:1',
|
||||
'open' => 'V:LEVEL:100',
|
||||
'close' => 'V:LEVEL:0',
|
||||
'up' => 'V:LEVEL:?delta=+20',
|
||||
'down' => 'V:LEVEL:?delta=-20',
|
||||
@ -397,7 +401,7 @@ $HMCCU_CONFIG_VERSION = '5.0';
|
||||
},
|
||||
'BLIND_VIRTUAL_RECEIVER' => {
|
||||
'pct' => 'V:LEVEL:?level',
|
||||
'open' => 'V:LEVEL:1',
|
||||
'open' => 'V:LEVEL:100',
|
||||
'close' => 'V:LEVEL:0',
|
||||
'oldLevel' => 'V:LEVEL:1.005',
|
||||
'up' => 'V:LEVEL:?delta=+20',
|
||||
@ -425,27 +429,27 @@ $HMCCU_CONFIG_VERSION = '5.0';
|
||||
'DIMMER' => {
|
||||
'pct' => '3:V:LEVEL:?level 1:V:ON_TIME:?time=0.0 2:V:RAMP_TIME:?ramp=0.5',
|
||||
'level' => 'V:LEVEL:?level',
|
||||
'on' => 'V:LEVEL:1',
|
||||
'on' => 'V:LEVEL:100',
|
||||
'off' => 'V:LEVEL:0',
|
||||
'on-for-timer' => 'V:ON_TIME:?duration V:LEVEL:1',
|
||||
'on-till' => 'V:ON_TIME:?time V:LEVEL:1',
|
||||
'on-for-timer' => 'V:ON_TIME:?duration V:LEVEL:100',
|
||||
'on-till' => 'V:ON_TIME:?time V:LEVEL:100',
|
||||
'up' => 'V:LEVEL:?delta=+10',
|
||||
'down' => 'V:LEVEL:?delta=-10',
|
||||
'stop' => 'V:RAMP_STOP:1',
|
||||
'toggle' => 'V:LEVEL:0,1'
|
||||
'toggle' => 'V:LEVEL:0,100'
|
||||
},
|
||||
'DIMMER_VIRTUAL_RECEIVER' => {
|
||||
'pct' => '5:V:LEVEL:?level 1:V:DURATION_UNIT:0 2:V:ON_TIME,DURATION_VALUE:?time=0.0 3:V:RAMP_TIME_UNIT:0 4:V:RAMP_TIME,RAMP_TIME_VALUE:?ramp=0.5',
|
||||
'level' => 'V:LEVEL:?level',
|
||||
'on' => 'V:LEVEL:1',
|
||||
'on' => 'V:LEVEL:100',
|
||||
'off' => 'V:LEVEL:0',
|
||||
'oldLevel' => 'V:LEVEL:1.005',
|
||||
'on-for-timer' => '1:V:DURATION_UNIT:0 2:V:ON_TIME,DURATION_VALUE:?duration 3:V:LEVEL:1',
|
||||
'on-till' => '1:V:DURATION_UNIT:0 2:V:ON_TIME,DURATION_VALUE:?time 3:V:LEVEL:1',
|
||||
'on-for-timer' => '1:V:DURATION_UNIT:0 2:V:ON_TIME,DURATION_VALUE:?duration 3:V:LEVEL:100',
|
||||
'on-till' => '1:V:DURATION_UNIT:0 2:V:ON_TIME,DURATION_VALUE:?time 3:V:LEVEL:100',
|
||||
'up' => 'V:LEVEL:?delta=+10',
|
||||
'down' => 'V:LEVEL:?delta=-10',
|
||||
'color' => 'V:COLOR:#color',
|
||||
'toggle' => 'V:LEVEL:0,1'
|
||||
'toggle' => 'V:LEVEL:0,100'
|
||||
},
|
||||
'DIMMER_WEEK_PROFILE' => {
|
||||
'progMode' => 'V:WEEK_PROGRAM_TARGET_CHANNEL_LOCK:#progMode'
|
||||
@ -472,13 +476,13 @@ $HMCCU_CONFIG_VERSION = '5.0';
|
||||
},
|
||||
'JALOUSIE' => {
|
||||
'pct' => 'V:LEVEL:?level',
|
||||
'open' => 'V:LEVEL:1',
|
||||
'open' => 'V:LEVEL:100',
|
||||
'close' => 'V:LEVEL:0',
|
||||
'up' => 'V:LEVEL:?delta=+20',
|
||||
'down' => 'V:LEVEL:?delta=-20',
|
||||
'stop' => 'V:STOP:1',
|
||||
'pctSlats' => 'V:LEVEL_SLATS:?level',
|
||||
'openSlats' => 'V:LEVEL_SLATS:1',
|
||||
'openSlats' => 'V:LEVEL_SLATS:100',
|
||||
'closeSlats' => 'V:LEVEL_SLATS:0',
|
||||
},
|
||||
'KEY' => {
|
||||
@ -513,9 +517,12 @@ $HMCCU_CONFIG_VERSION = '5.0';
|
||||
'color' => 'V:COLOR:?color V:ACT_HSV_COLOR_VALUE:?hsvColor',
|
||||
'brightness' => 'V:ACT_BRIGHTNESS:?brightness'
|
||||
},
|
||||
'SHUTTER_TRANSMITTER' => {
|
||||
'calibrate' => 'V:SELF_CALIBRATION:#Mode'
|
||||
},
|
||||
'SHUTTER_VIRTUAL_RECEIVER' => {
|
||||
'pct' => 'V:LEVEL:?level',
|
||||
'open' => 'V:LEVEL:1',
|
||||
'open' => 'V:LEVEL:100',
|
||||
'oldLevel' => 'V:LEVEL:1.005',
|
||||
'close' => 'V:LEVEL:0',
|
||||
'up' => 'V:LEVEL:?delta=+20',
|
||||
@ -543,9 +550,13 @@ $HMCCU_CONFIG_VERSION = '5.0';
|
||||
'sensor-on-till' => 'V:ON_TIME:?time V:STATE:1'
|
||||
},
|
||||
'SWITCH_VIRTUAL_RECEIVER' => {
|
||||
'COMBINED_PARAMETER' => {
|
||||
'OT' => 'ON_TIME',
|
||||
'S' => 'STATE'
|
||||
},
|
||||
'on' => 'V:STATE:1',
|
||||
'off' => 'V:STATE:0',
|
||||
'on-for-timer' => 'V:ON_TIME:?duration V:STATE:1',
|
||||
'on-for-timer' => 'COMBINED_PARAMETER V:OT:?duration V:S:1',
|
||||
'on-till' => 'V:ON_TIME:?time V:STATE:1',
|
||||
'toggle' => 'V:STATE:0,1'
|
||||
},
|
||||
@ -560,15 +571,22 @@ $HMCCU_CONFIG_VERSION = '5.0';
|
||||
'get week-program' => 'D:WEEK_PROGRAM_POINTER:#program:HMCCU_DisplayWeekProgram'
|
||||
},
|
||||
'UNIVERSAL_LIGHT_RECEIVER' => {
|
||||
'COMBINED_PARAMETER' => {
|
||||
'L' => 'LEVEL',
|
||||
'OT' => 'ON_TIME',
|
||||
'H' => 'HUE',
|
||||
'SAT' => 'SATURATION'
|
||||
},
|
||||
'pct' => '5:V:LEVEL:?level 1:V:DURATION_UNIT:0 2:V:DURATION_VALUE:?time=0.0 3:V:RAMP_TIME_UNIT:0 4:V:RAMP_TIME_VALUE:?ramp=0.5',
|
||||
'level' => 'V:LEVEL:?level',
|
||||
'on' => 'V:LEVEL:1',
|
||||
'on' => 'V:LEVEL:100',
|
||||
'off' => 'V:LEVEL:0',
|
||||
'on-for-timer' => '1:V:DURATION_UNIT:0 2:V:DURATION_VALUE:?duration 3:V:LEVEL:1',
|
||||
'on-till' => '1:V:DURATION_UNIT:0 2:V:DURATION_VALUE:?time 3:V:LEVEL:1',
|
||||
'on-for-timer' => '1:V:DURATION_UNIT:0 2:V:DURATION_VALUE:?duration 3:V:LEVEL:100',
|
||||
'on-till' => '1:V:DURATION_UNIT:0 2:V:DURATION_VALUE:?time 3:V:LEVEL:100',
|
||||
'up' => 'V:LEVEL:?delta=+10',
|
||||
'down' => 'V:LEVEL:?delta=-10',
|
||||
'toggle' => 'V:LEVEL:0,1'
|
||||
'toggle' => 'V:LEVEL:0,100',
|
||||
'color' => 'COMBINED_PARAMETER V:L:?level V:H:?hue V:SAT:?saturation'
|
||||
},
|
||||
'VIRTUAL_KEY' => {
|
||||
'on' => 'V:PRESS_SHORT:1',
|
||||
|
Loading…
x
Reference in New Issue
Block a user