HMCCU: Fixed Windows process ID bug

git-svn-id: https://svn.fhem.de/fhem/trunk@13680 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2017-03-12 10:45:56 +00:00
parent ea946b630e
commit c34ddc9776
5 changed files with 274 additions and 97 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it.
- update: 88_HMCCU: Code optimized. Fixed Windows process ID bug.
- bugfix: 71_YAMAHA_NP: Fixed tuner readings in standby.
- bugfix: 42_Nextion: mult. fixes - page10 / disconnect / init
- bugfix: 71_YAMAHA_NP: Fixed volume slider

View File

@ -4,7 +4,7 @@
#
# $Id$
#
# Version 3.9.006
# Version 3.9.007
#
# Module for communication between FHEM and Homematic CCU2.
# Supports BidCos-RF, BidCos-Wired, HmIP-RF, virtual CCU channels,
@ -50,10 +50,7 @@
# attr <name> ccudefaults <filename>
# attr <name> ccuflags { intrpc,extrpc,dptnocheck,noagg }
# attr <name> ccuget { State | Value }
# attr <name> ccureadingfilter <filter_rule>
# attr <name> ccureadingformat { name[lc] | address[lc] | datapoint[lc] }
# attr <name> ccureadings { 0 | 1 }
# attr <name> ccutrace {<ccudevname_exp>|<ccudevaddr_exp>}
# attr <name> parfile <parfile>
# attr <name> rpcevtimeout <seconds>
# attr <name> rpcinterfaces { BidCos-Wired, BidCos-RF, HmIP-RF, VirtualDevices, Homegear }
@ -65,7 +62,7 @@
# attr <name> rpcserverport <base_port>
# attr <name> rpctimeout <read>[,<write>]
# attr <name> stripchar <character>
# attr <name> stripnumber { 0 | 1 | 2 }
# attr <name> stripnumber { -<digits> | 0 | 1 | 2 }
# attr <name> substitute <subst_rule>
#
# filter_rule := [channel-regexp!]datapoint-regexp[,...]
@ -104,7 +101,7 @@ my %HMCCU_CUST_CHN_DEFAULTS;
my %HMCCU_CUST_DEV_DEFAULTS;
# HMCCU version
my $HMCCU_VERSION = '3.9.006';
my $HMCCU_VERSION = '3.9.007';
# RPC Ports and URL extensions
my %HMCCU_RPC_NUMPORT = (
@ -132,7 +129,7 @@ my $HMCCU_INIT_INTERVAL2 = 5;
# Number of arguments in RPC events
my %rpceventargs = (
"EV", 3,
"ND", 2,
"ND", 6,
"DD", 1,
"RD", 2,
"RA", 1,
@ -201,6 +198,7 @@ sub HMCCU_Substitute ($$$$$);
sub HMCCU_SubstRule ($$$);
sub HMCCU_SubstVariables ($$);
sub HMCCU_UpdateClients ($$$$);
sub HMCCU_UpdateDeviceTable ($$);
sub HMCCU_UpdateDevices ($$$);
sub HMCCU_UpdateSingleDatapoint ($$$$);
sub HMCCU_UpdateSingleDevice ($$$);
@ -225,6 +223,7 @@ sub HMCCU_IsDevAddr ($$);
sub HMCCU_IsChnAddr ($$);
sub HMCCU_SplitChnAddr ($);
sub HMCCU_GetCCUObjectAttribute ($$$);
sub HMCCU_FindClientDevices ($$$$);
sub HMCCU_FindIODevice ($);
sub HMCCU_GetHash ($@);
sub HMCCU_GetAttribute ($$$$);
@ -307,7 +306,7 @@ sub HMCCU_Initialize ($)
$hash->{ShutdownFn} = "HMCCU_Shutdown";
$hash->{parseParams} = 1;
$hash->{AttrList} = "stripchar stripnumber ccuackstate:0,1 ccuaggregate:textField-long ccudefaults rpcinterfaces:multiple-strict,".join(',',sort keys %HMCCU_RPC_PORT)." ccudef-hmstatevals:textField-long ccudef-substitute:textField-long ccudef-readingname:textField-long ccudef-readingfilter:textField-long ccudef-readingformat:name,namelc,address,addresslc,datapoint,datapointlc ccuflags:multiple-strict,intrpc,dptnocheck,noagg,nohmstate ccureadings:0,1 ccureadingfilter ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc rpcinterval:2,3,5,7,10 rpcqueue rpcport:multiple-strict,".join(',',sort keys %HMCCU_RPC_NUMPORT)." rpcserver:on,off rpcserveraddr rpcserverport rpctimeout rpcevtimeout parfile substitute ccutrace ccuget:Value,State ". $readingFnAttributes;
$hash->{AttrList} = "stripchar stripnumber ccuackstate:0,1 ccuaggregate:textField-long ccudefaults rpcinterfaces:multiple-strict,".join(',',sort keys %HMCCU_RPC_PORT)." ccudef-hmstatevals:textField-long ccudef-substitute:textField-long ccudef-readingname:textField-long ccudef-readingfilter:textField-long ccudef-readingformat:name,namelc,address,addresslc,datapoint,datapointlc ccuflags:multiple-strict,intrpc,dptnocheck,noagg,nohmstate ccureadings:0,1 rpcinterval:2,3,5,7,10 rpcqueue rpcport:multiple-strict,".join(',',sort keys %HMCCU_RPC_NUMPORT)." rpcserver:on,off rpcserveraddr rpcserverport rpctimeout rpcevtimeout parfile substitute ccuget:Value,State ". $readingFnAttributes;
}
##################################################
@ -831,13 +830,11 @@ sub HMCCU_AggregateReadings ($$)
my $resval;
$resval = $ftrue if ($fcond =~ /^(max|min|sum|avg)$/);
foreach my $d (keys %defs) {
# Get device parameters and check device type
my @devlist = HMCCU_FindClientDevices ($hash, "(HMCCUDEV|HMCCUCHN)", undef, undef);
foreach my $d (@devlist) {
my $ch = $defs{$d};
next if (!exists ($ch->{NAME}) || !exists ($ch->{TYPE}));
my $cn = $ch->{NAME};
my $ct = $ch->{TYPE};
next if ($ct ne 'HMCCUCHN' && $ct ne 'HMCCUDEV');
my $fmatch = '';
$fmatch = $cn if ($ftype eq 'name');
@ -930,7 +927,7 @@ sub HMCCU_Undef ($$)
HMCCU_Shutdown ($hash);
# Delete reference to IO module in client devices
my @keylist = sort keys %defs;
my @keylist = keys %defs;
foreach my $d (@keylist) {
if (exists ($defs{$d}) && exists($defs{$d}{IODev}) &&
$defs{$d}{IODev} == $hash) {
@ -1151,7 +1148,6 @@ sub HMCCU_Get ($@)
return "HMCCU: CCU busy, choose one of rpcstate:noArg";
}
my $ccureadingformat = HMCCU_GetAttrReadingFormat ($hash, $hash);
my $ccureadings = AttrVal ($name, "ccureadings", 1);
my $parfile = AttrVal ($name, "parfile", '');
my $rpcport = $hash->{hmccu}{rpcports};
@ -1924,21 +1920,20 @@ sub HMCCU_UpdateClients ($$$$)
foreach my $name (sort keys %{$hash->{hmccu}{adr}}) {
next if ($name !~ /$devexp/ || !($hash->{hmccu}{adr}{$name}{valid}));
foreach my $d (keys %defs) {
my @devlist = HMCCU_FindClientDevices ($hash, "(HMCCUDEV|HMCCUCHN)", undef, "ccudevstate=active");
foreach my $d (@devlist) {
my $ch = $defs{$d};
next if (!exists ($ch->{NAME}) || !exists ($ch->{TYPE}));
next if ($ch->{TYPE} ne 'HMCCUDEV' && $ch->{TYPE} ne 'HMCCUCHN');
next if ($ch->{ccudevstate} ne 'Active');
next if (!defined ($ch->{IODev}) || !defined ($ch->{ccuaddr}));
next if ($ch->{ccuaddr} ne $hash->{hmccu}{adr}{$name}{address});
my $rc = HMCCU_GetUpdate ($ch, $hash->{hmccu}{adr}{$name}{address}, $ccuget);
if ($rc <= 0) {
if ($rc == -10) {
Log3 $fhname, 1, "HMCCU: Device $name has no readable datapoints";
Log3 $fhname, 3, "HMCCU: Device $name has no readable datapoints";
}
else {
Log3 $fhname, 1, "HMCCU: Update of device $name failed" if ($rc != -10);
Log3 $fhname, 2, "HMCCU: Update of device $name failed" if ($rc != -10);
}
$c_err++;
}
@ -1949,13 +1944,11 @@ sub HMCCU_UpdateClients ($$$$)
}
}
else {
foreach my $d (keys %defs) {
# Get hash of client device
my @devlist = HMCCU_FindClientDevices ($hash, "(HMCCUDEV|HMCCUCHN)", $devexp, "ccudevstate=active");
Log3 $fhname, 2, "HMCCU: No client devices matching $devexp" if (scalar (@devlist) == 0);
foreach my $d (@devlist) {
my $ch = $defs{$d};
next if (!exists ($ch->{NAME}) || !exists ($ch->{TYPE}));
next if ($ch->{TYPE} ne 'HMCCUDEV' && $ch->{TYPE} ne 'HMCCUCHN');
next if ($ch->{ccudevstate} ne 'Active');
next if ($ch->{NAME} !~ /$devexp/);
next if (!defined ($ch->{IODev}) || !defined ($ch->{ccuaddr}));
my $rc = HMCCU_GetUpdate ($ch, $ch->{ccuaddr}, $ccuget);
@ -1978,6 +1971,127 @@ sub HMCCU_UpdateClients ($$$$)
return ($c_ok, $c_err);
}
##########################################################################
# Update parameters in internal device tables and client devices.
# Parameter devices is a hash reference with keys:
# {address}
# {address}{flag} := [N, D, R]
# {address}{addtype} := [chn, dev]
# {address}{channels} := Number of channels
# {address}{name} := Device or channel name
# {address}{type} := Homematic device type
# {address}{usetype} := Usage type
# {address}{interface} := Device interface ID
# {address}{firmware} := Firmware version of device
# {address}{version} := Version of RPC device description
# {address}{rxmode} := Transmit mode
# If flag is 'D' the hash must contain an entry for the device address
# and for each channel address.
##########################################################################
sub HMCCU_UpdateDeviceTable ($$)
{
my ($hash, $devices) = @_;
my $devcount = 0;
my $chncount = 0;
# Update internal device table
foreach my $da (keys %{$devices}) {
my $nm = $hash->{hmccu}{dev}{$da}{name} if (defined ($hash->{hmccu}{dev}{$da}{name}));
$nm = $devices->{$da}{name} if (defined ($devices->{$da}{name}));
if ($devices->{$da}{flag} eq 'N' && defined ($nm)) {
# Updated or new device/channel
$hash->{hmccu}{dev}{$da}{addtype} = HMCCU_IsChnAddr ($da, 0) ? 'chn' : 'dev';
$hash->{hmccu}{dev}{$da}{name} = $nm if (defined ($nm));
$hash->{hmccu}{dev}{$da}{valid} = 1;
$hash->{hmccu}{dev}{$da}{channels} = $devices->{$da}{channels}
if (defined ($devices->{$da}{channels}));
$hash->{hmccu}{dev}{$da}{type} = $devices->{$da}{type}
if (defined ($devices->{$da}{type}));
$hash->{hmccu}{dev}{$da}{usetype} = $devices->{$da}{usetype}
if (defined ($devices->{$da}{usetype}));
$hash->{hmccu}{dev}{$da}{interface} = $devices->{$da}{interface}
if (defined ($devices->{$da}{interface}));
$hash->{hmccu}{dev}{$da}{version} = $devices->{$da}{version}
if (defined ($devices->{$da}{version}));
$hash->{hmccu}{dev}{$da}{firmware} = $devices->{$da}{firmware}
if (defined ($devices->{$da}{firmware}));
$hash->{hmccu}{dev}{$da}{rxmode} = $devices->{$da}{rxmode}
if (defined ($devices->{$da}{rxmode}));
$hash->{hmccu}{adr}{$nm}{address} = $da;
$hash->{hmccu}{adr}{$nm}{addtype} = $hash->{hmccu}{dev}{$da}{addtype};
$hash->{hmccu}{adr}{$nm}{valid} = 1 if (defined ($nm));
}
elsif ($devices->{$da}{flag} eq 'D' && exists ($hash->{hmccu}{dev}{$da})) {
# Device deleted, mark as invalid
$hash->{hmccu}{dev}{$da}{valid} = 0;
$hash->{hmccu}{adr}{$nm}{valid} = 0 if (defined ($nm));
}
elsif ($devices->{$da}{flag} eq 'R' && exists ($hash->{hmccu}{dev}{$da})) {
# Device replaced, change address
my $na = $devices->{hmccu}{newaddr};
# Copy device entries and delete old device entries
foreach my $k (keys %{$hash->{hmccu}{dev}{$da}}) {
$hash->{hmccu}{dev}{$na}{$k} = $hash->{hmccu}{dev}{$da}{$k};
}
$hash->{hmccu}{adr}{$nm}{address} = $na;
delete $hash->{hmccu}{dev}{$da};
}
}
# Update client devices
my @devlist = HMCCU_FindClientDevices ($hash, "(HMCCUDEV|HMCCUCHN)", undef, undef);
foreach my $d (@devlist) {
my $ch = $defs{$d};
my $ct = $ch->{TYPE};
my $ca = $ch->{ccuaddr};
next if (!exists ($devices->{$ca}));
if ($devices->{$ca}{flag} eq 'N') {
# New device or new device information
$ch->{ccudevstate} = 'active';
if ($ct eq 'HMCCUDEV') {
$ch->{ccutype} = $hash->{hmccu}{dev}{$ca}{type}
if (defined ($hash->{hmccu}{dev}{$ca}{type}));
$ch->{firmware} = $devices->{$ca}{firmware}
if (defined ($devices->{$ca}{firmware}));
}
else {
$ch->{chntype} = $devices->{$ca}{usetype}
if (defined ($devices->{$ca}{usetype}));
my ($add, $chn) = HMCCU_SplitChnAddr ($ca);
$ch->{ccutype} = $devices->{$add}{type}
if (defined ($devices->{$add}{type}));
$ch->{firmware} = $devices->{$add}{firmware}
if (defined ($devices->{$add}{firmware}));
}
$ch->{ccuname} = $hash->{hmccu}{dev}{$ca}{name}
if (defined ($hash->{hmccu}{dev}{$ca}{name}));
$ch->{ccuif} = $hash->{hmccu}{dev}{$ca}{interface}
if (defined ($devices->{$ca}{interface}));
$ch->{channels} = $hash->{hmccu}{dev}{$ca}{channels}
if (defined ($hash->{hmccu}{dev}{$ca}{channels}));
}
elsif ($devices->{$ca}{flag} eq 'D') {
# Deleted device
$ch->{ccudevstate} = 'deleted';
}
elsif ($devices->{$ca}{flag} eq 'R') {
# Replaced device
$ch->{ccuaddr} = $devices->{$ca}{newaddr};
}
}
# Update internals of I/O device
foreach my $adr (keys %{$hash->{hmccu}{dev}}) {
$devcount++ if ($hash->{hmccu}{dev}{$adr}{addtype} eq 'dev');
$chncount++ if ($hash->{hmccu}{dev}{$adr}{addtype} eq 'chn');
}
$hash->{ccudevices} = $devcount;
$hash->{ccuchannels} = $chncount;
}
####################################################
# Mark devices and channels as deleted or active.
# mode: 0=delete, 1=reactivate
@ -2007,7 +2121,7 @@ sub HMCCU_UpdateDevices ($$$)
my $ch = $defs{$d};
next if (!exists ($ch->{NAME}) || !exists ($ch->{TYPE}));
if ($ch->{TYPE} eq 'HMCCUDEV' && $ch->{ccuaddr} eq $a) {
$ch->{ccudevstate} = $mode ? 'Active' : 'Deleted';
$ch->{ccudevstate} = $mode ? 'active' : 'deleted';
readingsSingleUpdate ($ch, 'state', $mode ? 'Activated' : 'Deleted', 1);
}
elsif ($ch->{TYPE} eq 'HMCCUCHN' && $ch->{ccuaddr} =~ /^$a:[0-9]+/) {
@ -2015,7 +2129,7 @@ sub HMCCU_UpdateDevices ($$$)
$ch->{chntype} = defined ($hash->{hmccu}{dev}{$a}{chntype}) ?
$hash->{hmccu}{dev}{$a}{chntype} : "unknown";
}
$ch->{ccudevstate} = $mode ? 'Active' : 'Deleted';
$ch->{ccudevstate} = $mode ? 'active' : 'deleted';
readingsSingleUpdate ($ch, 'state', $mode ? 'Activated' : 'Deleted', 1);
}
}
@ -2072,11 +2186,10 @@ sub HMCCU_UpdateSingleDevice ($$$)
# Check for updated data
my ($devaddr, $cnum) = HMCCU_SplitChnAddr ($clthash->{ccuaddr});
return 0 if (!exists ($objects->{$devaddr}));
return 0 if ($clttype eq 'HMCUCCHN' && !exists ($objects->{$devaddr}{$cnum}) &&
!exists ($objects->{$devaddr}{0}));
return 0 if ($clttype eq 'HMCCUDEV' && $clthash->{ccuif} eq 'VirtualDevices' &&
!exists ($objects->{$devaddr}));
# Get attributes of IO device
my $ccuflags = AttrVal ($ccuname, 'ccuflags', 'null');
@ -2099,6 +2212,11 @@ sub HMCCU_UpdateSingleDevice ($$$)
}
}
if ($cltflags =~ /trace/) {
Log3 $ccuname, 2, "HMCCU: $cltname Devlist = ".join(',', @devlist);
Log3 $ccuname, 2, "HMCCU: $cltname Objects = ".join(',', keys %{$objects});
}
# Store the resulting readings
my %results;
@ -2138,7 +2256,7 @@ sub HMCCU_UpdateSingleDevice ($$$)
", orgvalue=$value value=$cvalue" if ($cltflags =~ /trace/);
foreach my $rn (@readings) {
HMCCU_BulkUpdate ($clthash, $rn, $value, $cvalue) if ($rn ne '');
HMCCU_BulkUpdate ($clthash, $rn, $fvalue, $cvalue) if ($rn ne '');
}
foreach my $clcr (keys %calcs) {
HMCCU_BulkUpdate ($clthash, $clcr, $calcs{$clcr}, $calcs{$clcr});
@ -2168,8 +2286,7 @@ sub HMCCU_UpdateSingleDevice ($$$)
# Parameter objects is a hash reference:
# {devaddr}
# {devaddr}{channelno}
# {devaddr}{channelno}{datapoint}
# {devaddr}{channelno}{datapoint}{value}
# {devaddr}{channelno}{datapoint} = value
# Return number of updated devices.
######################################################################
@ -2184,16 +2301,9 @@ sub HMCCU_UpdateMultipleDevices ($$)
return 0 if (!defined ($hash) || !defined ($objects));
# Update reading in matching client devices
foreach my $d (keys %defs) {
# Get hash and name of client device
my @devlist = HMCCU_FindClientDevices ($hash, "(HMCCUDEV|HMCCUCHN)", undef, "ccudevstate=active");
foreach my $d (@devlist) {
my $ch = $defs{$d};
next if (!exists ($ch->{NAME}) || !exists ($ch->{TYPE}));
my $ct = $ch->{TYPE};
my $cn = $ch->{NAME};
# Filter devices
next if ($ct ne 'HMCCUDEV' && $ct ne 'HMCCUCHN');
my $rc = HMCCU_UpdateSingleDevice ($hash, $ch, $objects);
$c++ if (ref ($rc));
}
@ -2561,7 +2671,7 @@ sub HMCCU_StopRPCServer ($)
# Send signal SIGINT to RPC server processes
foreach my $clkey (keys %{$hash->{hmccu}{rpc}}) {
my $rpchash = \%{$hash->{hmccu}{rpc}{$clkey}};
if (exists ($rpchash->{pid}) && $rpchash->{pid} > 0) {
if (exists ($rpchash->{pid}) && $rpchash->{pid} != 0) {
Log3 $name, 0, "HMCCU: Stopping RPC server $clkey with PID ".$rpchash->{pid};
kill ('INT', $rpchash->{pid});
$rpchash->{state} = "stopping";
@ -2682,7 +2792,7 @@ sub HMCCU_IsRPCServerRunning ($$$)
foreach my $clkey (keys %{$hash->{hmccu}{rpc}}) {
if (exists ($hash->{hmccu}{rpc}{$clkey}{pid}) &&
defined ($hash->{hmccu}{rpc}{$clkey}{pid}) &&
$hash->{hmccu}{rpc}{$clkey}{pid} > 0) {
$hash->{hmccu}{rpc}{$clkey}{pid} != 0) {
my $pid = $hash->{hmccu}{rpc}{$clkey}{pid};
push (@$hm_pids, $pid) if (kill (0, $pid));
}
@ -2733,7 +2843,6 @@ sub HMCCU_GetDeviceInfo ($$$)
return '' if (!defined ($hmccu_hash));
$ccuget = HMCCU_GetAttribute ($hmccu_hash, $hash, 'ccuget', 'Value') if ($ccuget eq 'Attr');
my $ccutrace = AttrVal ($hmccu_hash->{NAME}, 'ccutrace', '');
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($hmccu_hash, $device, 0);
@ -2770,7 +2879,7 @@ if (odev) {
);
my $response = HMCCU_HMScript ($hmccu_hash, $script);
if (($ccutrace ne '' && ($device =~ /$ccutrace/ || $devname =~ /$ccutrace/)) || $ccuflags =~ /trace/) {
if ($ccuflags =~ /trace/) {
Log3 $name, 2, "HMCCU: Device=$device Devname=$devname";
Log3 $name, 2, "HMCCU: Script response = \n".$response;
Log3 $name, 2, "HMCCU: Script = ".$script;
@ -3491,6 +3600,35 @@ sub HMCCU_GetCCUObjectAttribute ($$$)
return undef;
}
######################################################################
# Get list of client devices matching the specified criteria.
# If no criteria is specified all device names will be returned.
# Parameters modexp and namexp are regular expressions for module
# name and device name. Parameter internal contains an expression
# like internal=valueexp. All parameters can be undefined.
######################################################################
sub HMCCU_FindClientDevices ($$$$)
{
my ($hash, $modexp, $namexp, $internal) = @_;
my @devlist = ();
foreach my $d (keys %defs) {
my $ch = $defs{$d};
next if (!defined ($ch->{TYPE}) || !defined ($ch->{NAME}));
next if (defined ($modexp) && $ch->{TYPE} !~ /$modexp/);
next if (defined ($namexp) && $ch->{NAME} !~ /$namexp/);
next if (defined ($hash) && exists ($ch->{IODev}) && $ch->{IODev} != $hash);
if (defined ($internal)) {
my ($i, $v) = split ('=', $internal);
next if (defined ($v) && exists ($ch->{$i}) && $ch->{$i} !~ /$v/);
}
push @devlist, $ch->{NAME};
}
return @devlist;
}
####################################################
# Get hash of HMCCU IO device which is responsible
# for device or channel specified by parameter
@ -3784,11 +3922,11 @@ sub HMCCU_ProcessEvent ($$)
return undef;
}
Log3 $name, 0, "HMCCU: Received IN event. RPC server $clkey initialized.";
$rh->{$clkey}{state} = $rh->{$clkey}{pid} > 0 ? "running" : "initialized";
$rh->{$clkey}{state} = $rh->{$clkey}{pid} != 0 ? "running" : "initialized";
# Check if all RPC servers were initialized. Set overall status
foreach my $ser (keys %{$rh}) {
$norun++ if ($rh->{$ser}{state} ne "running" && $rh->{$ser}{pid} > 0);
$norun++ if ($rh->{$ser}{state} ne "running" && $rh->{$ser}{pid} != 0);
$norun++ if ($rh->{$ser}{state} ne "initialized" && $rh->{$ser}{pid} == 0);
$run++ if ($rh->{$ser}{state} eq "running");
}
@ -3836,13 +3974,22 @@ sub HMCCU_ProcessEvent ($$)
$hash->{hmccu}{rpcinit} = $run;
return ($t[0], $clkey, $t[2], $f, $run);
}
elsif ($t[0] eq 'ND' || $t[0] eq 'DD' || $t[0] eq 'RA') {
elsif ($t[0] eq 'ND') {
#
# CCU device added
# Input: ND|C/D|Address|Type|Version|Firmware|RxMode
# Output: ND, DevAdd, C/D, Type, Version, Firmware, RxMode
#
# Log3 $name, 2, "HMCCU: ND ".join (',', @t);
return ($t[0], $t[2], $t[1], $t[3], $t[4], $t[5], $t[6]);
}
elsif ($t[0] eq 'DD' || $t[0] eq 'RA') {
#
# CCU device added, deleted or readded
# Input: {ND,DD,RA}|Address
# Output: {ND,DD,RA}, DevAdd, [ChnType]
# Input: {DD,RA}|Address
# Output: {DD,RA}, DevAdd
#
return ($t[0], $t[1], $t[2]);
return ($t[0], $t[1]);
}
elsif ($t[0] eq 'UD') {
#
@ -3892,17 +4039,18 @@ sub HMCCU_ReadRPCQueue ($)
my $name = $hash->{NAME};
my $eventno = 0;
my $f = 0;
my @newdevices;
my @deldevices;
my @newdevices;
my @deldevices;
my @termpids;
my $newcount = 0;
my $delcount = 0;
# my $delcount = 0;
my $devcount = 0;
my %events = ();
my %devices = ();
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my $rpcinterval = AttrVal ($name, 'rpcinterval', 5);
my $rpcqueue = AttrVal ($name, 'rpcqueue', '/tmp/ccuqueue');
# my $rpcport = AttrVal ($name, 'rpcport', 2001);
my $rpcport = $hash->{hmccu}{rpcports};
my $rpctimeout = AttrVal ($name, 'rpcevtimeout', 300);
my $maxevents = $rpcinterval*10;
@ -3930,18 +4078,37 @@ sub HMCCU_ReadRPCQueue ($)
last if ($eventno == $maxevents);
}
elsif ($et eq 'ND') {
push (@newdevices, $par[0]);
# push (@newdevices, $par[1]);
$newcount++ if (!exists ($hash->{hmccu}{dev}{$par[0]}));
$hash->{hmccu}{dev}{$par[0]}{chntype} = $par[1];
# $hash->{hmccu}{dev}{$par[1]}{chntype} = $par[3];
$devices{$par[0]}{flag} = 'N';
$devices{$par[0]}{version} = $par[3];
if ($par[1] eq 'D') {
$devices{$par[0]}{type} = $par[2];
$devices{$par[0]}{firmware} = $par[4];
$devices{$par[0]}{rxmode} = $par[5];
}
else {
$devices{$par[0]}{usetype} = $par[2];
}
$devcount++;
}
elsif ($et eq 'DD') {
push (@deldevices, $par[0]);
$delcount++;
# push (@deldevices, $par[0]);
$devices{$par[0]}{flag} = 'D';
$devcount++;
# $delcount++;
}
elsif ($et eq 'RD') {
$devices{$par[0]}{flag} = 'R';
$devices{$par[0]}{newaddr} = $par[1];
$devcount++;
}
elsif ($et eq 'SL') {
InternalTimer (gettimeofday()+$HMCCU_INIT_INTERVAL1,
'HMCCU_RPCRegisterCallback', $hash, 0);
return;
$f = -1;
last;
}
elsif ($et eq 'EX') {
push (@termpids, $par[1]);
@ -3950,6 +4117,8 @@ sub HMCCU_ReadRPCQueue ($)
}
}
last if ($f == -1);
# Read next element from queue
$element = HMCCU_QueueDeq ($hash);
}
@ -3957,7 +4126,13 @@ sub HMCCU_ReadRPCQueue ($)
HMCCU_QueueClose ($hash);
}
# Update readings
HMCCU_UpdateMultipleDevices ($hash, \%events) if ($eventno > 0);
# Update device table and client device parameter
HMCCU_UpdateDeviceTable ($hash, \%devices) if ($devcount > 0);
return if ($f == -1);
# Check if events from CCU timed out
if ($hash->{hmccu}{evtime} > 0 && time()-$hash->{hmccu}{evtime} > $rpctimeout &&
@ -3968,19 +4143,19 @@ sub HMCCU_ReadRPCQueue ($)
}
# CCU devices deleted
$delcount = scalar @deldevices;
if ($delcount > 0) {
HMCCU_UpdateDevices ($hash, \@deldevices, 0);
$hash->{DelDevices} = $delcount;
DoTrigger ($name, "$delcount devices deleted in CCU");
}
# $delcount = scalar @deldevices;
# if ($delcount > 0) {
# HMCCU_UpdateDevices ($hash, \@deldevices, 0);
# $hash->{DelDevices} = $delcount;
# DoTrigger ($name, "$delcount devices deleted in CCU");
# }
# CCU devices added
HMCCU_UpdateDevices ($hash, \@newdevices, 1) if (scalar @newdevices > 0);
if ($newcount > 0) {
$hash->{NewDevices} += $newcount;
DoTrigger ($name, "$newcount devices added in CCU");
}
# HMCCU_UpdateDevices ($hash, \@newdevices, 1) if (scalar @newdevices > 0);
# if ($newcount > 0) {
# $hash->{NewDevices} += $newcount;
# DoTrigger ($name, "$newcount devices added in CCU");
# }
my @hm_pids;
my @ex_pids;
@ -4097,7 +4272,7 @@ sub HMCCU_GetDatapoint ($@)
$hmccu_hash = HMCCU_GetHash ($hash);
return (-3, $value) if (!defined ($hmccu_hash));
return (-4, $value) if ($type ne 'HMCCU' && $hash->{ccudevstate} eq 'Deleted');
return (-4, $value) if ($type ne 'HMCCU' && $hash->{ccudevstate} eq 'deleted');
my $ccureadings = AttrVal ($name, 'ccureadings', 1);
my $readingformat = HMCCU_GetAttrReadingFormat ($hash, $hmccu_hash);
@ -4156,7 +4331,7 @@ sub HMCCU_SetDatapoint ($$$)
my $hmccu_hash = HMCCU_GetHash ($hash);
return -3 if (!defined ($hmccu_hash));
return -4 if ($hash->{ccudevstate} eq 'Deleted');
return -4 if ($hash->{ccudevstate} eq 'deleted');
my $name = $hmccu_hash->{NAME};
my $cdname = $hash->{NAME};
@ -4351,13 +4526,12 @@ sub HMCCU_GetUpdate ($$$)
my $hmccu_hash = HMCCU_GetHash ($cl_hash);
return -3 if (!defined ($hmccu_hash));
return -4 if ($type ne 'HMCCU' && $cl_hash->{ccudevstate} eq 'Deleted');
return -4 if ($type ne 'HMCCU' && $cl_hash->{ccudevstate} eq 'deleted');
my $nam = '';
my $script;
$ccuget = HMCCU_GetAttribute ($hmccu_hash, $cl_hash, 'ccuget', 'Value') if ($ccuget eq 'Attr');
my $ccutrace = AttrVal ($hmccu_hash->{NAME}, 'ccutrace', '');
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
if (HMCCU_IsChnAddr ($addr, 0)) {
@ -4436,7 +4610,7 @@ WriteLine (c);
}
my $response = HMCCU_HMScript ($hmccu_hash, $script);
if (($ccutrace ne '' && ($addr =~ /$ccutrace/ || $nam =~ /$ccutrace/)) || $ccuflags =~ /trace/) {
if ($ccuflags =~ /trace/) {
Log3 $name, 2, "HMCCU: Addr=$addr Name=$nam";
Log3 $name, 2, "HMCCU: Script response = \n".$response;
Log3 $name, 2, "HMCCU: Script = \n".$script;
@ -4566,7 +4740,7 @@ sub HMCCU_RPCGetConfig ($$$$)
my $hmccu_hash = HMCCU_GetHash ($hash);
return (-3, $result) if (!defined ($hmccu_hash));
return (-4, $result) if ($type ne 'HMCCU' && $hash->{ccudevstate} eq 'Deleted');
return (-4, $result) if ($type ne 'HMCCU' && $hash->{ccudevstate} eq 'deleted');
my $ccureadings = AttrVal ($name, 'ccureadings', 1);
my $readingformat = HMCCU_GetAttrReadingFormat ($hash, $hmccu_hash);
@ -4658,7 +4832,7 @@ sub HMCCU_RPCSetConfig ($$$)
my $hmccu_hash = HMCCU_GetHash ($hash);
return -3 if (!defined ($hmccu_hash));
return -4 if ($type ne 'HMCCU' && $hash->{ccudevstate} eq 'Deleted');
return -4 if ($type ne 'HMCCU' && $hash->{ccudevstate} eq 'deleted');
my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($hmccu_hash, $param,
$HMCCU_FLAG_FULLADDR);
@ -5349,7 +5523,16 @@ sub HMCCU_CCURPC_NewDevicesCB ($$$)
Log3 $name, 2, "CCURPC: $cb NewDevice received $devcount device specifications";
for my $dev (@$a) {
HMCCU_CCURPC_Write ("ND", $dev->{ADDRESS}."|".$dev->{TYPE});
my $msg = '';
if ($dev->{ADDRESS} =~ /:[0-9]{1,2}$/) {
$msg = "C|".$dev->{ADDRESS}."|".$dev->{TYPE}."|".$dev->{VERSION}."|null|null";
}
else {
$msg = "D|".$dev->{ADDRESS}."|".$dev->{TYPE}."|".$dev->{VERSION}."|".
$dev->{FIRMWARE}."|".$dev->{RX_MODE};
}
HMCCU_CCURPC_Write ("ND", $msg);
# HMCCU_CCURPC_Write ("ND", $dev->{ADDRESS}."|".$dev->{TYPE});
}
return;
@ -5721,20 +5904,10 @@ sub HMCCU_CCURPC_GetEventsCB ($$)
'Value' because each request is sent to the device. With method 'Value' only CCU
is queried. Default is 'Value'.
</li><br/>
<li><b>ccureadingformat {<u>name</u> | address | datapoint | namelc | addresslc |
datapointlc}</b><br/>
Format of reading names (channel name, channel address or channel number combined with
datapoint). With suffix 'lc' reading names are lowercase. Default is 'name'.
</li><br/>
<li><b>ccureadings {0 | <u>1</u>}</b><br/>
If set to 1 values read from CCU will be stored as readings. Otherwise output
is displayed in browser window.
</li><br/>
<li><b>ccutrace {&lt;ccu-devname-exp&gt; | &lt;ccu-address-exp&gt;}</b><br/>
Turn on trace mode for devices matching specified expression. Will write extended
information into FHEM log (level 1). Deprecated. Use attribute 'ccuflags' in
client devices instead.
</li><br/>
<li><b>parfile &lt;filename&gt;</b><br/>
Define parameter file for command 'get parfile'.
</li><br/>

View File

@ -145,7 +145,7 @@ sub HMCCUCHN_Define ($@)
AssignIoPort ($hash, $hmccu_hash->{NAME});
readingsSingleUpdate ($hash, "state", "Initialized", 1);
$hash->{ccudevstate} = 'Active';
$hash->{ccudevstate} = 'active';
return undef;
}

View File

@ -207,7 +207,7 @@ sub HMCCUDEV_Define ($@)
AssignIoPort ($hash, $hmccu_hash->{NAME});
readingsSingleUpdate ($hash, "state", "Initialized", 1);
$hash->{ccudevstate} = 'Active';
$hash->{ccudevstate} = 'active';
return undef;
}
@ -280,6 +280,7 @@ sub HMCCUDEV_Set ($@)
my $ccutype = $hash->{ccutype};
my $ccuaddr = $hash->{ccuaddr};
my $ccuif = $hash->{ccuif};
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my $statevals = AttrVal ($name, "statevals", '');
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', 'STATE', '', '');
@ -380,6 +381,8 @@ sub HMCCUDEV_Set ($@)
# Read current value of datapoint
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname);
Log3 $name, 2, "HMCCU: set toggle: GetDatapoint returned $rc, $result"
if ($ccuflags =~ /trace/);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
my $objvalue = '';

View File

@ -4,7 +4,7 @@
#
# $Id$
#
# Version 3.9.001
# Version 3.9.002
#
# Configuration parameters for Homematic devices.
#
@ -126,7 +126,7 @@ use vars qw(%HMCCU_DEV_DEFAULTS);
webCmd => "control:on:off",
widgetOverride => "control:slider,0,10,100"
},
"HM-PB-2-FM" => {
"HM-PB-2-FM|HM-PB-2-WM55|HM-PB-2-WM55-2" => {
_description => "Funk-Wandtaster 2-fach",
_channels => "1,2",
ccureadingfilter => "PRESS",
@ -414,7 +414,7 @@ use vars qw(%HMCCU_DEV_DEFAULTS);
webCmd => "control:on:off",
widgetOverride => "control:slider,0,10,100"
},
"HM-PB-2-FM" => {
"HM-PB-2-FM|HM-PB-2-WM55|HM-PB-2-WM55-2" => {
_description => "Funk-Wandtaster 2-fach",
ccureadingfilter => "PRESS",
substitute => "PRESS_SHORT,PRESS_LONG,PRESS_CONT!(1|true):pressed,(0|false):released;PRESS_LONG_RELEASE!(0|false):no,(1|true):yes"