From 3309062efe330e2aeac9ff612e28ea5e065c2107 Mon Sep 17 00:00:00 2001 From: fhemzap Date: Tue, 5 Jan 2016 18:09:55 +0000 Subject: [PATCH] HMCCU: Update all client devices git-svn-id: https://svn.fhem.de/fhem/trunk@10369 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/contrib/HMCCU/88_HMCCU.pm | 179 +++++++++++++++++++++++++++++++-- 1 file changed, 169 insertions(+), 10 deletions(-) diff --git a/fhem/contrib/HMCCU/88_HMCCU.pm b/fhem/contrib/HMCCU/88_HMCCU.pm index b3d92dfac..92a31d810 100644 --- a/fhem/contrib/HMCCU/88_HMCCU.pm +++ b/fhem/contrib/HMCCU/88_HMCCU.pm @@ -1,14 +1,14 @@ -################################################################ +#################################################################### # # 88_HMCCU.pm # # $Id$ # -# Version 2.3 +# Version 2.4 # # (c) 2015 zap (zap01 t-online de) # -################################################################ +#################################################################### # # define HMCCU [] # @@ -27,6 +27,9 @@ # get parfile [] # get config {|} # get configdesc {|} +# get deviceinfo +# get rpcstate +# get update [] # # attr ccureadingfilter # attr ccureadingformat { name | address } @@ -44,14 +47,13 @@ # attr updatemode { client | both | hmccu } # # subst_rule := [datapoint[,...]]!:[,...][;...] -################################################################ +#################################################################### package main; use strict; use warnings; use SetExtensions; -# use XML::Simple qw(:strict); use RPC::XML::Client; # use File::Queue; # use Data::Dumper; @@ -103,6 +105,7 @@ sub HMCCU_SetError ($$); sub HMCCU_SetState ($$); sub HMCCU_Substitute ($$$$); sub HMCCU_SubstRule ($$$); +sub HMCCU_UpdateClients ($$); sub HMCCU_UpdateClientReading ($@); sub HMCCU_StartRPCServer ($); sub HMCCU_StopRPCServer ($); @@ -125,6 +128,7 @@ sub HMCCU_GetDatapoint ($@); sub HMCCU_SetDatapoint ($$$); sub HMCCU_GetVariables ($$); sub HMCCU_SetVariable ($$$); +sub HMCCU_GetUpdate ($$); sub HMCCU_GetChannel ($$); sub HMCCU_RPCGetConfig ($$$); sub HMCCU_RPCSetConfig ($$$); @@ -359,7 +363,7 @@ sub HMCCU_Get ($@) my ($hash, @a) = @_; my $name = shift @a; my $opt = shift @a; - my $options = "devicelist:noArg devstate datapoint vars channel parfile config configdesc deviceinfo"; + my $options = "devicelist:noArg devstate datapoint vars channel update parfile config configdesc rpcstate:noArg deviceinfo"; my $host = $hash->{host}; my $ccureadingformat = AttrVal ($name, "ccureadingformat", 'name'); @@ -432,6 +436,14 @@ sub HMCCU_Get ($@) HMCCU_SetState ($hash, "OK"); return $ccureadings ? undef : $result; } + elsif ($opt eq 'update') { + my $devexp = shift @a; + $devexp = '.*' if (!defined ($devexp)); + + my ($c_ok, $c_err) = HMCCU_UpdateClients ($hash, $devexp); + + return "$c_ok client devices successfully updated. Update for $c_err client devices failed"; + } elsif ($opt eq 'parfile') { my $par_parfile = shift @a; my @parameters; @@ -471,6 +483,15 @@ sub HMCCU_Get ($@) return HMCCU_SetError ($hash, -2) if ($result eq ''); return $result; } + elsif ($opt eq 'rpcstate') { + my $pid = HMCCU_CheckProcess ($hash); + if ($pid > 0) { + return "RPC process running with pid $pid"; + } + else { + return "RPC process not running"; + } + } elsif ($opt eq 'devicelist') { my $dumplist = shift @a; @@ -806,6 +827,35 @@ sub HMCCU_SubstRule ($$$) return ($rc, $value); } +################################################################## +# Update all datapoint/readings of all client devices +################################################################## + +sub HMCCU_UpdateClients ($$) +{ + my ($hash, $devexp) = @_; + my $c_ok = 0; + my $c_err = 0; + + foreach my $d (keys %defs) { + # Get hash of client device + my $ch = $defs{$d}; + next if ($ch->{TYPE} ne 'HMCCUDEV' && $ch->{TYPE} ne 'HMCCUCHN'); + next if ($ch->{NAME} !~ /$devexp/); + next if (!defined ($ch->{IODev}) || !defined ($ch->{ccuaddr})); + + my $rc = HMCCU_GetUpdate ($ch, $ch->{ccuaddr}); + if ($rc <= 0) { + $c_err++; + } + else { + $c_ok++; + } + } + + return ($c_ok, $c_err); +} + ################################################################## # Update HMCCU readings and client readings. # @@ -868,6 +918,7 @@ sub HMCCU_UpdateClientReading ($@) my $crf = AttrVal ($cn, 'ccureadingformat', 'name'); my $flt = AttrVal ($cn, 'ccureadingfilter', '.*'); my $st = AttrVal ($cn, 'statedatapoint', 'STATE'); + my $sc = AttrVal ($cn, 'statechannel', ''); my $substitute = AttrVal ($cn, 'substitute', ''); last if ($upd == 0); next if ($dpt eq '' || $dpt !~ /$flt/); @@ -886,7 +937,7 @@ sub HMCCU_UpdateClientReading ($@) $cl_value = HMCCU_FormatReadingValue ($ch, $cl_value); readingsSingleUpdate ($ch, $clreading, $cl_value, 1); - if ($clreading =~ /\.$st$/) { + if ($clreading =~ /\.$st$/ && ($sc eq '' || $sc eq $channel)) { HMCCU_SetState ($ch, $cl_value); } } @@ -1015,6 +1066,8 @@ sub HMCCU_CheckProcess ($) my @plist = split "\n", $pdump; foreach my $proc (@plist) { + # Remove leading blanks, fix for MacOS. Thanks to mcdeck + $proc =~ s/^\s+//; my @procattr = split /\s+/, $proc; return $procattr[1] if ($procattr[1] != $$ && $procattr[7] =~ /perl$/ && $procattr[8] eq $hash->{RPCPRC}); } @@ -1457,6 +1510,7 @@ sub HMCCU_GetDatapoint ($@) my $readingformat = AttrVal ($name, 'ccureadingformat', 'name'); my $substitute = AttrVal ($name, 'substitute', ''); my $statedpt = AttrVal ($name, 'statedatapoint', 'STATE'); + my $statechn = AttrVal ($name, 'statechannel', ''); if ($hash->{TYPE} ne 'HMCCU') { # Get hash of HMCCU IO device @@ -1500,7 +1554,9 @@ sub HMCCU_GetDatapoint ($@) $value = HMCCU_FormatReadingValue ($hash, $value); readingsSingleUpdate ($hash, $reading, $value, 1) if ($ccureadings); if (($reading =~ /\.$statedpt$/ || $reading eq $statedpt) && $ccureadings) { - HMCCU_SetState ($hash, $value); + if ($statechn eq '' || $statechn eq $chn) { + HMCCU_SetState ($hash, $value); + } } } @@ -1610,6 +1666,99 @@ sub HMCCU_SetVariable ($$$) return 0; } +#################################################### +# Update all datapoints / readings of device or +# channel considering attribute ccureadingfilter. +#################################################### + +sub HMCCU_GetUpdate ($$) +{ + my ($cl_hash, $addr) = @_; + + return -3 if (!exists ($cl_hash->{IODev})); + my $hmccu_hash = $cl_hash->{IODev}; + my $nam = ''; + my $script; + + my $cn = $cl_hash->{NAME}; + my $ccureadings = AttrVal ($cn, 'ccureadings', 1); + my $ccureadingfilter = AttrVal ($cn, 'ccureadingfilter', '.*'); + my $readingformat = AttrVal ($cn, 'ccureadingformat', 'name'); + my $substitute = AttrVal ($cn, 'substitute', ''); + my $statedpt = AttrVal ($cn, 'statedatapoint', 'STATE'); + my $statechn = AttrVal ($cn, 'statechannel', ''); + + if ($addr =~ /^[A-Z]{3,3}[0-9]{7,7}:[0-9]{1,2}$/) { + $nam = HMCCU_GetChannelName ($addr, ''); + return -1 if ($nam eq ''); + + $script = qq( +string sDPId; +string sChnName = "$nam"; +object oChannel = dom.GetObject (sChnName); +foreach(sDPId, oChannel.DPs().EnumUsedIDs()) +{ + object oDP = dom.GetObject(sDPId); + WriteLine (sChnName # "=" # oDP.Name() # "=" # oDP.Value()); +} + ); + } + elsif ($addr =~ /^[A-Z]{3,3}[0-9]{7,7}$/) { + $nam = HMCCU_GetDeviceName ($addr, ''); + return -1 if ($nam eq ''); + + $script = qq( +string chnid; +string sDPId; +object odev = dom.GetObject ("$nam"); +foreach (chnid, odev.Channels()) +{ + object ochn = dom.GetObject(chnid); + foreach(sDPId, ochn.DPs().EnumUsedIDs()) + { + object oDP = dom.GetObject(sDPId); + WriteLine (ochn.Name() # "=" # oDP.Name() # "=" # oDP.Value()); + } +} + ); + } + else { + return -1; + } + + my $response = HMCCU_HMScript ($hmccu_hash->{host}, $script); + return -2 if ($response eq ''); + + readingsBeginUpdate ($cl_hash) if ($ccureadings); + + foreach my $dpdef (split /\n/, $response) { + my @dpdata = split /=/, $dpdef; + next if (@dpdata < 2); + my @adrtoks = split /\./, $dpdata[1]; + next if (@adrtoks != 3); + next if ($adrtoks[2] !~ /$ccureadingfilter/); + + my ($add, $chn) = split /:/, $adrtoks[1]; + my $reading = HMCCU_GetReadingName ($adrtoks[0], $add, $chn, $adrtoks[2], + $dpdata[0], $readingformat); + next if ($reading eq ''); + + my $value = (defined ($dpdata[2]) && $dpdata[2] ne '') ? $dpdata[2] : 'N/A'; + my $value = HMCCU_Substitute ($value, $substitute, 0, $reading); + $value = HMCCU_FormatReadingValue ($cl_hash, $value); + if ($ccureadings) { + readingsBulkUpdate ($cl_hash, $reading, $value); + if ($reading =~ /\.$statedpt$/ && ($statechn eq '' || $statechn eq $chn)) { + readingsBulkUpdate ($cl_hash, "state", $value); + } + } + } + + readingsEndUpdate ($cl_hash, 1) if ($ccureadings); + + return 1; +} + #################################################### # Get multiple datapoints of channels and update # readings. @@ -1635,6 +1784,7 @@ sub HMCCU_GetChannel ($$) my $readingformat = AttrVal ($name, 'ccureadingformat', 'name'); my $defsubstitute = AttrVal ($name, 'substitute', ''); my $statedpt = AttrVal ($name, 'statedatapoint', 'STATE'); + my $statechn = AttrVal ($name, 'statechannel', ''); if ($hash->{TYPE} ne 'HMCCU') { # Get hash of HMCCU IO device @@ -1701,7 +1851,6 @@ foreach (sChannel, sChnList.Split(",")) my $reading = HMCCU_GetReadingName ($adrtoks[0], $add, $chn, $adrtoks[2], $dpdata[0], $readingformat); next if ($reading eq ''); - Log 1, "HMCCU: Readingname = $reading"; my $value = HMCCU_Substitute ($dpdata[2], $chnpars{$dpdata[0]}{sub}, 0, $reading); if ($hash->{TYPE} eq 'HMCCU') { @@ -1711,7 +1860,9 @@ foreach (sChannel, sChnList.Split(",")) $value = HMCCU_FormatReadingValue ($hash, $value); if ($ccureadings) { readingsBulkUpdate ($hash, $reading, $value); - readingsBulkUpdate ($hash, "state", $value) if ($reading =~ /\.$statedpt$/); + if ($reading =~ /\.$statedpt$/ && ($statechn eq '' || $statechn eq $chn)) { + readingsBulkUpdate ($hash, "state", $value); + } } } @@ -2020,6 +2171,14 @@ sub HMCCU_Dewpoint ($$$$)

Empty lines or lines starting with a # are ignored.
+
  • get <name> rpcstate +
    + Check if RPC server process is running. +

  • +
  • get <name> update [<devexp>] +
    + Update all datapoint / readings of client devices with device name matching <devexp> +