From c6bec808eaa41fa7da715db5b580ac84c415db13 Mon Sep 17 00:00:00 2001 From: zap <> Date: Sun, 10 Feb 2019 11:52:28 +0000 Subject: [PATCH] HMCCU: New commands and bug fixes git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@18552 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- CHANGED | 1 + FHEM/88_HMCCU.pm | 408 ++++++++++++++++++++++++++++++++++------ FHEM/88_HMCCUCHN.pm | 47 +++-- FHEM/88_HMCCUDEV.pm | 19 +- FHEM/88_HMCCURPCPROC.pm | 126 ++++++++++--- FHEM/HMCCUConf.pm | 30 +-- 6 files changed, 493 insertions(+), 138 deletions(-) diff --git a/CHANGED b/CHANGED index a46b77c22..5ab49343a 100644 --- a/CHANGED +++ b/CHANGED @@ -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. + - feature: 88_HMCCU: New commands and bug fixes - changed: 93_DbLog: CommandRef revised - feature: 98_HTTPMOD: starting with featurelevel >5.9 enableCookies, enableControlSet, handleRedirects and diff --git a/FHEM/88_HMCCU.pm b/FHEM/88_HMCCU.pm index 174ae2ce8..71f1fae4f 100755 --- a/FHEM/88_HMCCU.pm +++ b/FHEM/88_HMCCU.pm @@ -4,7 +4,7 @@ # # $Id$ # -# Version 4.3.010 +# Version 4.3.011 # # Module for communication between FHEM and Homematic CCU2/3. # @@ -51,7 +51,7 @@ my %HMCCU_CUST_CHN_DEFAULTS; my %HMCCU_CUST_DEV_DEFAULTS; # HMCCU version -my $HMCCU_VERSION = '4.3.010'; +my $HMCCU_VERSION = '4.3.011'; # Default RPC interface and port (BidCos-RF) my $HMCCU_RPC_PORT_DEFAULT = 2001; @@ -73,6 +73,11 @@ my $HMCCU_TIMEOUT_EVENT = 600; my $HMCCU_STATISTICS = 500; my $HMCCU_TIMEOUT_REQUEST = 4; +# ReGa Ports +my %HMCCU_REGA_PORT = ( + 'http' => 8181, 'https' => '48181' +); + # RPC port name by port number my %HMCCU_RPC_NUMPORT = ( 2000 => 'BidCos-Wired', 2001 => 'BidCos-RF', 2010 => 'HmIP-RF', 9292 => 'VirtualDevices', @@ -87,10 +92,15 @@ my %HMCCU_RPC_PORT = ( # RPC flags my %HMCCU_RPC_FLAG = ( - 2000 => 'forceASCII', 2001 => 'forceASCII', 2003 => '_', 2010 => '_', + 2000 => 'forceASCII', 2001 => 'forceASCII', 2003 => '_', 2010 => 'forceASCII', 7000 => 'forceInit', 8701 => 'forceInit', 9292 => '_' ); +my %HMCCU_RPC_SSL = ( + 2000 => 1, 2001 => 1, 2010 => 1, 9292 => 1, + 'BidCos-Wired' => 1, 'BidCos-RF' => 1, 'HmIP-RF' => 1, 'VirtualDevices' => 1 +); + # Initial intervals for registration of RPC callbacks and reading RPC queue # # X = Start RPC server @@ -323,14 +333,19 @@ sub HMCCU_QueueEnq ($$); sub HMCCU_QueueDeq ($); # Helper functions +sub HMCCU_BuildURL ($$); sub HMCCU_CalculateReading ($$); +sub HMCCU_CorrectName ($); +sub HMCCU_Encrypt ($); +sub HMCCU_Decrypt ($); +sub HMCCU_DeleteReadings ($$); sub HMCCU_EncodeEPDisplay ($); sub HMCCU_ExprMatch ($$$); sub HMCCU_ExprNotMatch ($$$); sub HMCCU_GetDutyCycle ($); sub HMCCU_GetHMState ($$$); +sub HMCCU_GetIdFromIP ($$); sub HMCCU_GetTimeSpec ($); -sub HMCCU_CorrectName ($); sub HMCCU_RefToString ($); sub HMCCU_ResolveName ($$); sub HMCCU_TCPConnect ($$); @@ -392,8 +407,17 @@ sub HMCCU_Define ($$) my $name = $hash->{NAME}; return "Specify CCU hostname or IP address as a parameter" if (scalar (@$a) < 3); - - $hash->{host} = $$a[2]; + + # Setup http or ssl connection + if ($$a[2] =~ /^(https?):\/\/(.+)/) { + $hash->{prot} = $1; + $hash->{host} = $2; + } + else { + $hash->{prot} = 'http'; + $hash->{host} = $$a[2]; + } + $hash->{Clients} = ':HMCCUDEV:HMCCUCHN:HMCCURPC:HMCCURPCPROC:'; $hash->{hmccu}{ccu}{delay} = exists ($h->{ccudelay}) ? $h->{ccudelay} : $HMCCU_CCU_BOOT_DELAY; $hash->{hmccu}{ccu}{timeout} = exists ($h->{waitforccu}) ? $h->{waitforccu} : $HMCCU_CCU_PING_TIMEOUT; @@ -408,12 +432,12 @@ sub HMCCU_Define ($$) HMCCU_Log ($hash, 1, "Forced delayed initialization", 0); } else { - if (HMCCU_TCPPing ($hash->{host}, 8181, $hash->{hmccu}{ccu}{timeout})) { + if (HMCCU_TCPPing ($hash->{host}, $HMCCU_REGA_PORT{$hash->{prot}}, $hash->{hmccu}{ccu}{timeout})) { $hash->{ccustate} = 'active'; } else { $hash->{ccustate} = 'unreachable'; - HMCCU_Log ($hash, 1, "CCU port 8181 is not reachable", 0); + HMCCU_Log ($hash, 1, "CCU port ".$HMCCU_REGA_PORT{$hash->{prot}}." is not reachable", 0); } } @@ -481,7 +505,7 @@ sub HMCCU_Define ($$) # Initialization of FHEM device. # Called during Define() or by HMCCU after CCU ready. # Return 0 on successful initialization or >0 on error: -# 1 = CCU port 8181 is not reachable. +# 1 = CCU port 8181 or 48181 is not reachable. # 2 = Error while reading device list from CCU. ###################################################################### @@ -492,9 +516,9 @@ sub HMCCU_InitDevice ($) if ($hash->{hmccu}{ccu}{delayed} == 1) { HMCCU_Log ($hash, 1, "HMCCU: Initializing devices", 0); - if (!HMCCU_TCPPing ($hash->{host}, 8181, $hash->{hmccu}{ccu}{timeout})) { + if (!HMCCU_TCPPing ($hash->{host}, $HMCCU_REGA_PORT{$hash->{prot}}, $hash->{hmccu}{ccu}{timeout})) { $hash->{ccustate} = 'unreachable'; - HMCCU_Log ($hash, 1, "HMCCU: CCU port 8181 is not reachable", 0); + HMCCU_Log ($hash, 1, "HMCCU: CCU port ".$HMCCU_REGA_PORT{$hash->{prot}}." is not reachable", 0); return 1; } } @@ -1169,12 +1193,12 @@ sub HMCCU_Detail ($$$$)
- > CUxD Config
+ > CUxD Config
|
define <name> HMCCU <HostOrIP> [<ccu-number>] [waitforccu=<timeout>]
+ define <name> HMCCU [<Protocol>://]<HostOrIP> [<ccu-number>] [waitforccu=<timeout>]
[ccudelay=<delay>] [delayedinit=<delay>]
Example:
- define myccu HMCCU 192.168.1.10 ccudelay=180
+ define myccu HMCCU https://192.168.1.10 ccudelay=180
- The parameter HostOrIP is the hostname or IP address of a Homematic CCU2 or CCU3. If you have
- more than one CCU you can specifiy a unique CCU number with parameter ccu-number. With
- option waitforccu HMCCU will wait for the specified time if CCU is not reachable.
+ The parameter HostOrIP is the hostname or IP address of a Homematic CCU2 or CCU3. Optionally
+ the protocol 'http' or 'https' can be specified. Default protocol is 'http'.
+ If you have more than one CCU you can specifiy a unique CCU number with parameter ccu-number.
+ With option waitforccu HMCCU will wait for the specified time if CCU is not reachable.
Parameter timeout should be a multiple of 20 in seconds. Warning: This option will
block the start of FHEM for timeout seconds.
The option ccudelay specifies the time for delayed initialization of CCU environment if
@@ -7846,6 +8119,15 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
- set <name> ackmessages
Acknowledge device was unreachable messages in CCU.
+
+ - set <name> authentication [<username> <password>]
+ Set credentials for CCU authentication. Authentication must be activated by setting
+ attribute ccuflags to 'authenticate'.
+ When executing this command without arguments credentials are deleted.
+
+ - set <name> clear [<reading-exp>]
+ Delete readings matching specified reading name expression. Default expression is '.*'.
+ Readings 'state' and 'control' are not deleted.
- set <name> cleardefaults
Clear default attributes imported from file.
@@ -7877,6 +8159,9 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
- set <name> importdefaults <filename>
Import default attributes from file.
+ - set <name> initialize
+ Initialize I/O device if state of CCU is unreachable.
+
- set <name> rpcregister [{all | <interface>}]
Register RPC servers at CCU.
@@ -7899,6 +8184,9 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
- get <name> aggregation {<rule>|all}
Process aggregation rule defined with attribute ccuaggregate.
+ - get <name> ccumsg {service|alarm}
+ Query active service or alarm messages from CCU. Generate FHEM event for each message.
+
- get <name> configdesc {<device>|<channel>}
Get configuration parameter description of CCU device or channel (similar
to device settings in CCU). Not every CCU device or channel provides a configuration
diff --git a/FHEM/88_HMCCUCHN.pm b/FHEM/88_HMCCUCHN.pm
index 70ad2572e..a7ee42942 100644
--- a/FHEM/88_HMCCUCHN.pm
+++ b/FHEM/88_HMCCUCHN.pm
@@ -4,9 +4,9 @@
#
# $Id$
#
-# Version 4.3.005
+# Version 4.3.006
#
-# (c) 2018 zap (zap01 t-online de)
+# (c) 2019 zap (zap01 t-online de)
#
######################################################################
# Client device for Homematic channels.
@@ -208,8 +208,8 @@ sub HMCCUCHN_Set ($@)
my $rocmds = "clear config defaults:noArg";
# Get I/O device, check device state
- return HMCCU_SetError ($hash, -19) if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending');
- return HMCCU_SetError ($hash, -3) if (!defined ($hash->{IODev}));
+ return undef if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' ||
+ !defined ($hash->{IODev}));
return undef if ($hash->{statevals} eq 'readonly' && $opt ne '?' &&
$opt !~ /^(clear|config|defaults)$/);
@@ -403,11 +403,8 @@ sub HMCCUCHN_Set ($@)
}
elsif ($opt eq 'clear') {
my $rnexp = shift @$a;
- $rnexp = '.*' if (!defined ($rnexp));
- my @readlist = keys %{$hash->{READINGS}};
- foreach my $rd (@readlist) {
- delete ($hash->{READINGS}{$rd}) if ($rd ne 'state' && $rd ne 'control' && $rd =~ /$rnexp/);
- }
+ HMCCU_DeleteReadings ($hash, $rnexp);
+ return HMCCU_SetState ($hash, "OK");
}
elsif ($opt eq 'config') {
return HMCCU_SetError ($hash, "Usage: set $name config [device] {parameter}={value} [...]")
@@ -460,7 +457,8 @@ sub HMCCUCHN_Get ($@)
my $name = shift @$a;
my $opt = shift @$a;
- return HMCCU_SetError ($hash, -3) if (!defined ($hash->{IODev}));
+ return undef if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' ||
+ !defined ($hash->{IODev}));
my $disable = AttrVal ($name, "disable", 0);
return undef if ($disable == 1);
@@ -794,16 +792,33 @@ sub HMCCUCHN_Get ($@)
If set to 1 values read from CCU will be stored as readings. Default is 1.
- ccureadingfilter <filter-rule[;...]>
- Only datapoints matching specified expression are stored as readings.
+ Only datapoints matching specified expression RegExp are stored as readings.
Syntax for filter-rule is either:
- [N:]{<channel-name>|<channel-number>}!<RegExp> or:
+ [N:]{<channel-name>}!RegExp> or:
[N:][<channel-number>.]<RegExp>
If channel-name or channel-number is specified the following rule
- applies only to this channel.
- By default all datapoints will be stored as readings. Attribute ccudef-readingfilter
- of I/O device will be checked before this attribute.
+ applies only to this channel.
If a rule starts with 'N:' the filter is negated which means that a reading is
- stored if rule doesn't match.
+ stored if rule doesn't match.
+ The following table describes the dependencies between this attribute and attribute
+ ccudef-readingfilter in I/O device. The filtering of readings depends on which attribute
+ is set.
+
+ ccureadingfilter
Device ccudef-readingfilter
I/O Device Update Readings/Datapoints
+ not set not set all readings
+ not set set only readings from ccudef-readingfilter
+ set not set only readings from ccureadingfilter
+ set set both readings from ccureadingfilter and ccudef-readingfilter
+
+ So if ccudef-readingfilter is set in I/O device one must also set ccureadingfilter to
+ get updates for additional, device specific readings. Please keep in mind, that readings updates
+ are also affected by attributes event-on-change-reading and event-on-update-reading.
+ Examples:
+
+ attr mydev ccureadingfilter .*
+ attr mydev ccureadingfilter 1.(^ACTUAL|CONTROL|^SET_TEMP);(^WINDOW_OPEN|^VALVE)
+ attr mydev ccureadingfilter MyBlindChannel!^LEVEL$
+
- ccureadingformat {address[lc] | name[lc] | datapoint[lc]}
Set format of reading names. Default for virtual device groups is 'name'. The default for all
diff --git a/FHEM/88_HMCCUDEV.pm b/FHEM/88_HMCCUDEV.pm
index 49926897a..7352d208c 100644
--- a/FHEM/88_HMCCUDEV.pm
+++ b/FHEM/88_HMCCUDEV.pm
@@ -4,9 +4,9 @@
#
# $Id$
#
-# Version 4.3.006
+# Version 4.3.008
#
-# (c) 2018 zap (zap01 t-online de)
+# (c) 2019 zap (zap01 t-online de)
#
######################################################################
# Client device for Homematic devices.
@@ -239,7 +239,6 @@ sub HMCCUDEV_InitDevice ($$)
# Group specified by CCU virtual group name
@devlist = HMCCU_GetGroupMembers ($hmccu_hash, $gdname);
$gdcount = scalar (@devlist);
- return 5 if ($gdcount == 0);
}
return 3 if ($gdcount == 0);
@@ -345,8 +344,8 @@ sub HMCCUDEV_Set ($@)
my $rocmds = "clear config defaults:noArg";
# Get I/O device, check device state
- return HMCCU_SetError ($hash, -19) if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending');
- return HMCCU_SetError ($hash, -3) if (!defined ($hash->{IODev}));
+ return undef if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' ||
+ !defined ($hash->{IODev}));
my $hmccu_hash = $hash->{IODev};
my $hmccu_name = $hmccu_hash->{NAME};
@@ -580,11 +579,8 @@ sub HMCCUDEV_Set ($@)
}
elsif ($opt eq 'clear') {
my $rnexp = shift @$a;
- $rnexp = '.*' if (!defined ($rnexp));
- my @readlist = keys %{$hash->{READINGS}};
- foreach my $rd (@readlist) {
- delete ($hash->{READINGS}{$rd}) if ($rd ne 'state' && $rd ne 'control' && $rd =~ /$rnexp/);
- }
+ HMCCU_DeleteReadings ($hash, $rnexp);
+ return HMCCU_SetState ($hash, "OK");
}
elsif ($opt eq 'config') {
return HMCCU_SetError ($hash, "Usage: set $name config [{channel-number}] {parameter}={value} [...]")
@@ -645,7 +641,8 @@ sub HMCCUDEV_Get ($@)
my $opt = shift @$a;
# Get I/O device
- return HMCCU_SetError ($hash, -3) if (!defined ($hash->{IODev}));
+ return undef if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' ||
+ !defined ($hash->{IODev}));
my $hmccu_hash = $hash->{IODev};
my $hmccu_name = $hmccu_hash->{NAME};
diff --git a/FHEM/88_HMCCURPCPROC.pm b/FHEM/88_HMCCURPCPROC.pm
index 16aabcba6..63f1bdd3f 100755
--- a/FHEM/88_HMCCURPCPROC.pm
+++ b/FHEM/88_HMCCURPCPROC.pm
@@ -4,7 +4,7 @@
#
# $Id$
#
-# Version 1.5
+# Version 1.6
#
# Subprocess based RPC Server module for HMCCU.
#
@@ -35,7 +35,7 @@ use SetExtensions;
######################################################################
# HMCCURPC version
-my $HMCCURPCPROC_VERSION = '1.5';
+my $HMCCURPCPROC_VERSION = '1.6';
# Maximum number of events processed per call of Read()
my $HMCCURPCPROC_MAX_EVENTS = 100;
@@ -107,6 +107,7 @@ sub HMCCURPCPROC_Initialize ($);
sub HMCCURPCPROC_Define ($$);
sub HMCCURPCPROC_InitDevice ($$);
sub HMCCURPCPROC_Undef ($$);
+sub HMCCURPCPROC_DelayedShutdown ($);
sub HMCCURPCPROC_Shutdown ($);
sub HMCCURPCPROC_Attr ($@);
sub HMCCURPCPROC_Set ($@);
@@ -134,7 +135,7 @@ sub HMCCURPCPROC_RPCServerStopped ($);
sub HMCCURPCPROC_SendRequest ($@);
sub HMCCURPCPROC_SetRPCState ($$$$);
sub HMCCURPCPROC_StartRPCServer ($);
-sub HMCCURPCPROC_StopRPCServer ($);
+sub HMCCURPCPROC_StopRPCServer ($$);
sub HMCCURPCPROC_TerminateProcess ($);
# Helper functions
@@ -197,6 +198,7 @@ sub HMCCURPCPROC_Initialize ($)
$hash->{ReadFn} = "HMCCURPCPROC_Read";
$hash->{AttrFn} = "HMCCURPCPROC_Attr";
$hash->{ShutdownFn} = "HMCCURPCPROC_Shutdown";
+ $hash->{DelayedShutdownFn} = "HMCCURPCPROC_DelayedShutdown";
$hash->{parseParams} = 1;
@@ -231,17 +233,32 @@ sub HMCCURPCPROC_Define ($$)
$hmccu_hash = $defs{$ioname};
if (scalar (@$a) < 4) {
$hash->{host} = $hmccu_hash->{host};
+ $hash->{prot} = $hmccu_hash->{prot};
$iface = $$a[2];
}
else {
- $hash->{host} = $$a[2];
+ if ($$a[2] =~ /^(https?):\/\/(.+)/) {
+ $hash->{prot} = $1;
+ $hash->{host} = $2;
+ }
+ else {
+ $hash->{prot} = 'http';
+ $hash->{host} = $$a[2];
+ }
$iface = $$a[3];
}
$rpcip = HMCCU_ResolveName ($hash->{host}, 'N/A');
}
else {
return $usage if (scalar (@$a) < 4);
- $hash->{host} = $$a[2];
+ if ($$a[2] =~ /^(https?):\/\/(.+)/) {
+ $hash->{prot} = $1;
+ $hash->{host} = $2;
+ }
+ else {
+ $hash->{prot} = 'http';
+ $hash->{host} = $$a[2];
+ }
$iface = $$a[3];
$rpcip = HMCCU_ResolveName ($hash->{host}, 'N/A');
@@ -250,12 +267,8 @@ sub HMCCURPCPROC_Define ($$)
my $dh = $defs{$d};
next if (!exists ($dh->{TYPE}) || !exists ($dh->{NAME}));
next if ($dh->{TYPE} ne 'HMCCU');
-
- # The following call will fail during FHEM start if CCU is not ready
- my $ifhost = HMCCU_GetRPCServerInfo ($dh, $iface, 'host');
- next if (!defined ($ifhost));
- if ($dh->{host} eq $hash->{host} || $ifhost eq $hash->{host} || $ifhost eq $rpcip) {
- $hmccu_hash = $dh;
+ if ($dh->{ccuip} eq $rpcip) {
+ $hmccu_hash = $dh;
last;
}
}
@@ -338,10 +351,11 @@ sub HMCCURPCPROC_InitDevice ($$) {
# Get unique ID for RPC server: last 2 segments of local IP address
# Do not append random digits because of https://forum.fhem.de/index.php/topic,83544.msg797146.html#msg797146
- my @ipseg = split (/\./, $dev_hash->{hmccu}{localaddr});
- return 3 if (scalar (@ipseg) != 4);
- $dev_hash->{rpcid} = sprintf ("%03d%03d", $ipseg[2], $ipseg[3]);
-
+ my $id1 = HMCCU_GetIdFromIP ($dev_hash->{hmccu}{localaddr}, '');
+ my $id2 = HMCCU_GetIdFromIP ($hmccu_hash->{ccuip}, '');
+ return 3 if ($id1 eq '' || $id2 eq '');
+ $dev_hash->{rpcid} = $id1.$id2;
+
# Set I/O device and store reference for RPC device in I/O device
my $ioname = $hmccu_hash->{NAME};
return 2 if (!HMCCU_AssignIODevice ($dev_hash, $ioname, $ifname));
@@ -380,10 +394,11 @@ sub HMCCURPCPROC_Undef ($$)
my $ifname = $hash->{rpcinterface};
# Shutdown RPC server
- HMCCURPCPROC_Shutdown ($hash);
+ HMCCURPCPROC_StopRPCServer ($hash, $HMCCURPCPROC_INIT_INTERVAL2);
# Delete RPC device name in I/O device
- if (exists ($hmccu_hash->{hmccu}{interfaces}{$ifname}{device}) &&
+ if (exists ($hmccu_hash->{hmccu}{interfaces}{$ifname}) &&
+ exists ($hmccu_hash->{hmccu}{interfaces}{$ifname}{device}) &&
$hmccu_hash->{hmccu}{interfaces}{$ifname}{device} eq $name) {
delete $hmccu_hash->{hmccu}{interfaces}{$ifname}{device};
}
@@ -391,6 +406,30 @@ sub HMCCURPCPROC_Undef ($$)
return undef;
}
+######################################################################
+# Delayed shutdown FHEM
+######################################################################
+
+sub HMCCURPCPROC_DelayedShutdown ($)
+{
+ my ($hash) = @_;
+ my $name = $hash->{NAME};
+
+ my $delay = max (AttrVal ("global", "maxShutdownDelay", 10)-2, 0);
+
+ # Shutdown RPC server
+ if (!exists ($hash->{hmccu}{delayedShutdown})) {
+ $hash->{hmccu}{delayedShutdown} = 1;
+ Log3 $name, 1, "HMCCURPCPROC: [$name] Graceful shutdown";
+ HMCCURPCPROC_StopRPCServer ($hash, $delay);
+ }
+ else {
+ Log3 $name, 1, "HMCCURPCPROC: [$name] Shutdown already in progress";
+ }
+
+ return 1;
+}
+
######################################################################
# Shutdown FHEM
######################################################################
@@ -398,9 +437,15 @@ sub HMCCURPCPROC_Undef ($$)
sub HMCCURPCPROC_Shutdown ($)
{
my ($hash) = @_;
+ my $name = $hash->{NAME};
# Shutdown RPC server
- HMCCURPCPROC_StopRPCServer ($hash);
+ if (!exists ($hash->{hmccu}{delayedShutdown})) {
+ Log3 $name, 1, "HMCCURPCPROC: [$name] Immediate shutdown";
+ HMCCURPCPROC_StopRPCServer ($hash, 0);
+ }
+
+ # Remove all internal timers
RemoveInternalTimer ($hash);
return undef;
@@ -511,7 +556,7 @@ sub HMCCURPCPROC_Set ($@)
}
elsif ($action eq 'off') {
$hmccu_hash->{hmccu}{interfaces}{$hash->{rpcinterface}}{manager} = 'HMCCURPCPROC';
- HMCCURPCPROC_StopRPCServer ($hash);
+ HMCCURPCPROC_StopRPCServer ($hash, $HMCCURPCPROC_INIT_INTERVAL2);
}
return undef;
@@ -565,7 +610,11 @@ sub HMCCURPCPROC_Get ($@)
$result .= "--------------------------\n";
my $sid = defined ($hash->{hmccu}{rpc}{pid}) ? sprintf ("%5d", $hash->{hmccu}{rpc}{pid}) : "N/A ";
my $sname = sprintf ("%-10s", $clkey);
- $result .= $sid." ".$sname." ".$hash->{hmccu}{rpc}{state}."\n";
+ my $cbport = defined ($hash->{hmccu}{rpc}{cbport}) ? $hash->{hmccu}{rpc}{cbport} : "N/A";
+ my $addr = defined ($hash->{hmccu}{localaddr}) ? $hash->{hmccu}{localaddr} : "N/A";
+ $result .= $sid." ".$sname." ".$hash->{hmccu}{rpc}{state}."\n\n";
+ $result .= "Local address = $addr\n";
+ $result .= "Callback port = $cbport\n";
return $result;
}
else {
@@ -760,7 +809,8 @@ sub HMCCURPCPROC_IsRPCStateBlocking ($)
{
my ($hash) = @_;
- return ($hash->{RPCState} eq "running" || $hash->{RPCState} eq "inactive") ? 0 : 1;
+ return (exists ($hash->{RPCState}) &&
+ ($hash->{RPCState} eq "running" || $hash->{RPCState} eq "inactive")) ? 0 : 1;
}
######################################################################
@@ -950,7 +1000,7 @@ sub HMCCURPCPROC_ProcessEvent ($$)
# Input: TO|clkey|DiffTime
# Output: TO, clkey, Port, DiffTime
#
- if ($evttimeout > 0 && $t[0] > $evttimeout) {
+ if ($evttimeout > 0) {
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} == $defPort) {
@@ -1021,7 +1071,8 @@ sub HMCCURPCPROC_RegisterCallback ($$)
}
my $cburl = HMCCU_GetRPCCallbackURL ($hmccu_hash, $localaddr, $hash->{hmccu}{rpc}{cbport}, $clkey, $port);
- my $clurl = HMCCU_GetRPCServerInfo ($hmccu_hash, $port, 'url');
+# my $clurl = HMCCU_GetRPCServerInfo ($hmccu_hash, $port, 'url');
+ my $clurl = HMCCU_BuildURL ($hmccu_hash, $port);
my $rpctype = HMCCU_GetRPCServerInfo ($hmccu_hash, $port, 'type');
return (0, "Can't get RPC parameters for ID $clkey") if (!defined ($cburl) || !defined ($clurl) || !defined ($rpctype));
@@ -1069,7 +1120,8 @@ sub HMCCURPCPROC_DeRegisterCallback ($$)
$cburl = $rpchash->{cburl} if (exists ($rpchash->{cburl}));
$clurl = $rpchash->{clurl} if (exists ($rpchash->{clurl}));
$cburl = HMCCU_GetRPCCallbackURL ($hmccu_hash, $localaddr, $rpchash->{cbport}, $clkey, $port) if ($cburl eq '');
- $clurl = HMCCU_GetRPCServerInfo ($hmccu_hash, $port, 'url') if ($clurl eq '');
+# $clurl = HMCCU_GetRPCServerInfo ($hmccu_hash, $port, 'url') if ($clurl eq '');
+ $clurl = HMCCU_BuildURL ($hmccu_hash, $port) if ($clurl eq '');
return (0, "Can't get RPC parameters for ID $clkey") if ($cburl eq '' || $clurl eq '');
Log3 $name, 1, "HMCCURPCPROC: [$name] Deregistering RPC server $cburl with ID $clkey at $clurl";
@@ -1378,6 +1430,9 @@ sub HMCCURPCPROC_RPCServerStopped ($)
RemoveInternalTimer ($hash);
DoTrigger ($name, "RPC server $clkey stopped");
+
+ # Inform FHEM that instance can be shut down
+ CancelDelayedShutdown ($name) if (exists ($hash->{hmccu}{delayedShutdown}));
}
######################################################################
@@ -1535,13 +1590,16 @@ sub HMCCURPCPROC_Housekeeping ($)
######################################################################
# Stop RPC server processes.
+# If function is called by Shutdown, parameter wait must be 0
######################################################################
-sub HMCCURPCPROC_StopRPCServer ($)
+sub HMCCURPCPROC_StopRPCServer ($$)
{
- my ($hash) = @_;
+ my ($hash, $wait) = @_;
my $name = $hash->{NAME};
my $clkey = 'CB'.$hash->{rpcport}.$hash->{rpcid};
+
+ $wait = $HMCCURPCPROC_INIT_INTERVAL2 if (!defined ($wait));
if (HMCCURPCPROC_CheckProcessState ($hash, 'running')) {
Log3 $name, 1, "HMCCURPCPROC: [$name] Stopping RPC server $clkey";
@@ -1556,8 +1614,14 @@ sub HMCCURPCPROC_StopRPCServer ($)
# Trigger timer function for checking successful RPC stop
# Timer will be removed wenn receiving EX event from RPC server process
- InternalTimer (gettimeofday()+$HMCCURPCPROC_INIT_INTERVAL2, "HMCCURPCPROC_Housekeeping",
- $hash, 0);
+ if ($wait > 0) {
+ Log3 $name, 2, "HMCCURPCPROC: [$name] Scheduling cleanup in $wait seconds";
+ InternalTimer (gettimeofday()+$wait, "HMCCURPCPROC_Housekeeping", $hash, 0);
+ }
+ else {
+ Log3 $name, 2, "HMCCURPCPROC: [$name] Cleaning up immediately";
+ HMCCURPCPROC_Housekeeping ($hash);
+ }
# Give process the chance to terminate
sleep (1);
@@ -1587,12 +1651,14 @@ sub HMCCURPCPROC_SendRequest ($@)
if (HMCCU_IsRPCType ($hmccu_hash, $port, 'A')) {
# Use XMLRPC
- my $clurl = HMCCU_GetRPCServerInfo ($hmccu_hash, $port, 'url');
+# my $clurl = HMCCU_GetRPCServerInfo ($hmccu_hash, $port, 'url');
+ my $clurl = HMCCU_BuildURL ($hmccu_hash, $port);
return HMCCU_Log ($hash, 2, "Can't get client URL for port $port", undef)
if (!defined ($clurl));
Log3 $name, 4, "HMCCURPCPROC: [$name] Send ASCII RPC request $request to $clurl";
- my $rpcclient = RPC::XML::Client->new ($clurl);
+ my $rpcclient = RPC::XML::Client->new ($clurl, useragent => [
+ ssl_opts => { verify_hostname => 0, SSL_verify_mode => 0 } ]);
$rc = $rpcclient->simple_request ($request, @param);
Log3 $name, 2, "HMCCURPCPROC: [$name] RPC request error ".$RPC::XML::ERROR if (!defined ($rc));
}
diff --git a/FHEM/HMCCUConf.pm b/FHEM/HMCCUConf.pm
index ec6ae1fe6..fac305cfb 100644
--- a/FHEM/HMCCUConf.pm
+++ b/FHEM/HMCCUConf.pm
@@ -4,19 +4,11 @@
#
# $Id$
#
-# Version 4.5
+# Version 4.6
#
# Configuration parameters for HomeMatic devices.
#
-# (c) 2018 by zap (zap01 t-online de)
-#
-# Datapoints LOWBAT, LOW_BAT, UNREACH, ERROR.*, SABOTAGE and FAULT.*
-# must not be specified in attribute ccureadingfilter. They are always
-# stored as readings.
-# Datapoints LOWBAT, LOW_BAT and UNREACH must not be specified in
-# attribute substitute because they are substituted by default.
-# See also documentation of attributes ccudef-readingname and
-# ccudef-substitute in module HMCCU.
+# (c) 2019 by zap (zap01 t-online de)
#
#########################################################################
@@ -554,7 +546,7 @@ use vars qw(%HMCCU_SCRIPTS);
},
"HMIP-PSM" => {
_description => "Steckdose mit Energiemessung IP",
- ccureadingfilter => "(STATE|CURRENT|^ENERGY_COUNTER\$|POWER)",
+ ccureadingfilter => "3.STATE;6.(CURRENT|^ENERGY_COUNTER\$|POWER)",
controldatapoint => "3.STATE",
statedatapoint => "3.STATE",
statevals => "on:true,off:false",
@@ -1473,25 +1465,21 @@ if(oTmpArray) {
object oTmp = dom.GetObject(sTmp);
if (oTmp) {
if(oTmp.IsTypeOf(OT_ALARMDP) && (oTmp.AlState() == asOncoming)) {
- boolean collect = true;
object trigDP = dom.GetObject(oTmp.AlTriggerDP());
object och = dom.GetObject((trigDP.Channel()));
object odev = dom.GetObject((och.Device()));
var ival = trigDP.Value();
- time sftime = oTmp.AlOccurrenceTime();
- time sltime = oTmp.LastTriggerTime();
- var sdesc = trigDP.HSSID();
+ time sftime = oTmp.AlOccurrenceTime(); ! erste Meldezeit
+ time sltime = oTmp.LastTriggerTime();!letze Meldezeit
+ var sdesc = trigDP.HssType();
var sserial = odev.Address();
- string sAlarmMessage = web.webKeyFromStringTable(sdesc.Name());
- if(!sAlarmMessage.Length()) {
- sAlarmMessage = sdesc;
- }
+ var sname = odev.Name();
+ WriteLine(sftime.Format("%d.%m.%y %H:%M") # ";" # sltime.Format("%d.%m.%y %H:%M") # ";" # sserial # ";" # sname # ";" # sdesc);
c = c+1;
- WriteLine(sftime # ";" # sltime # ";" # sAlarmMessage # ";" # sserial);
}
}
}
-}
+}
Write(c);
)
},