2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-07 16:59:18 +00:00

HMCCU: Fixed multiple datapoints query

git-svn-id: https://svn.fhem.de/fhem/trunk@10526 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
fhemzap 2016-01-16 17:29:44 +00:00
parent 1c1a4dc0bb
commit 86b64c66b3

View File

@ -4,7 +4,7 @@
#
# $Id$
#
# Version 2.5
# Version 2.6
#
# (c) 2015 zap (zap01 <at> t-online <dot> de)
#
@ -29,11 +29,13 @@
# get <name> configdesc {<device>|<channel>}
# get <name> deviceinfo <device>
# get <name> rpcstate
# get <name> update [<devexp>]
# get <name> update [<devexp> [{ State | Value }]]
#
# attr <name> ccuget { State | Value }
# attr <name> ccureadingfilter <datapoint_exp>
# attr <name> ccureadingformat { name | address }
# attr <name> ccureadings { 0 | 1 }
# attr <name> ccutrace {<ccudevname_exp>|<ccudevaddr_exp>}
# attr <name> parfile <parfile>
# attr <name> rpcinterval { 3 | 5 | 10 }
# attr <name> rpcport <ccu_rpc_port>
@ -107,6 +109,7 @@ sub HMCCU_Substitute ($$$$);
sub HMCCU_SubstRule ($$$);
sub HMCCU_UpdateClients ($$$);
sub HMCCU_UpdateClientReading ($@);
sub HMCCU_DeleteDevices ($);
sub HMCCU_StartRPCServer ($);
sub HMCCU_StopRPCServer ($);
sub HMCCU_IsRPCServerRunning ($$$);
@ -117,13 +120,13 @@ sub HMCCU_GetAddress ($$$);
sub HMCCU_GetCCUObjectAttribute ($$);
sub HMCCU_GetHash ($@);
sub HMCCU_GetAttribute ($$$$);
sub HMCCU_IsValidDevice ($);
sub HMCCU_GetDeviceName ($$);
sub HMCCU_GetChannelName ($$);
sub HMCCU_GetDeviceType ($$);
sub HMCCU_GetDeviceChannels ($);
sub HMCCU_GetDeviceInterface ($$);
sub HMCCU_ReadRPCQueue ($);
sub HMCCU_HTTPRequest ($@);
sub HMCCU_HMScript ($$);
sub HMCCU_GetDatapoint ($@);
sub HMCCU_SetDatapoint ($$$);
@ -171,6 +174,7 @@ sub HMCCU_Define ($$)
$hash->{Clients} = ':HMCCUDEV:HMCCUCHN:';
$hash->{DevCount} = HMCCU_GetDeviceList ($hash);
$hash->{NewDevices} = 0;
return undef;
}
@ -751,7 +755,8 @@ sub HMCCU_SetError ($$)
my %errlist = (
-1 => 'Channel name or address invalid',
-2 => 'Execution of CCU script or command failed',
-3 => 'Cannot detect IO device'
-3 => 'Cannot detect IO device',
-4 => 'Device deleted in CCU'
);
$msg = exists ($errlist{$text}) ? $errlist{$text} : $text;
@ -962,6 +967,36 @@ sub HMCCU_UpdateClientReading ($@)
return $hmccu_value;
}
####################################################
# Mark client devices deleted in CCU as invalid
####################################################
sub HMCCU_DeleteDevices ($)
{
my ($devlist) = @_;
foreach my $a (@$devlist) {
my $cc = $HMCCU_Devices{$a}{channels};
$HMCCU_Devices{$a}{valid} = 0;
$HMCCU_Addresses{$HMCCU_Devices{$a}{name}}{valid} = 0;
for (my $i=0; $i<$cc; $i++) {
$HMCCU_Devices{$a.':'.$i}{valid} = 0;
$HMCCU_Addresses{$HMCCU_Devices{$a.':'.$i}{name}}{valid} = 0;
}
foreach my $d (keys %defs) {
my $ch = $defs{$d};
if ($ch->{TYPE} eq 'HMCCUDEV' && $ch->{ccuaddr} eq $a) {
$ch->{ccudevstate} = 'Deleted';
readingsSingleUpdate ($ch, 'state', 'Deleted', 1);
}
elsif ($ch->{TYPE} eq 'HMCCUCHN' && $ch->{ccuaddr} =~ /^$a:[0-9]+/) {
$ch->{ccudevstate} = 'Deleted';
readingsSingleUpdate ($ch, 'state', 'Deleted', 1);
}
}
}
}
####################################################
# Start RPC server
####################################################
@ -1149,15 +1184,17 @@ sub HMCCU_GetDeviceInfo ($$$)
string chnid;
string sDPId;
object odev = dom.GetObject ("$devname");
foreach (chnid, odev.Channels())
{
object ochn = dom.GetObject(chnid);
WriteLine("Channel " # ochn.Address() # " " # ochn.Name());
foreach(sDPId, ochn.DPs().EnumUsedIDs())
{
if (odev) {
foreach (chnid, odev.Channels()) {
object ochn = dom.GetObject(chnid);
WriteLine("Channel " # ochn.Address() # " " # ochn.Name());
foreach(sDPId, ochn.DPs()) {
object oDP = dom.GetObject(sDPId);
WriteLine (" DP " # oDP.Name() # " = " # oDP.$ccuget());
}
if (oDP) {
WriteLine (" DP " # oDP.Name() # " = " # oDP.$ccuget());
}
}
}
}
);
@ -1183,14 +1220,12 @@ sub HMCCU_GetDeviceList ($)
my $script = qq(
string devid;
string chnid;
foreach(devid, root.Devices().EnumUsedIDs())
{
foreach(devid, root.Devices().EnumUsedIDs()) {
object odev=dom.GetObject(devid);
string intid=odev.Interface();
string intna=dom.GetObject(intid).Name();
integer cc=0;
foreach (chnid, odev.Channels())
{
foreach (chnid, odev.Channels()) {
object ochn=dom.GetObject(chnid);
WriteLine("C;" # ochn.Address() # ";" # ochn.Name());
cc=cc+1;
@ -1215,8 +1250,10 @@ foreach(devid, root.Devices().EnumUsedIDs())
$HMCCU_Devices{$hmdata[2]}{interface} = $hmdata[1];
$HMCCU_Devices{$hmdata[2]}{channels} = $hmdata[5];
$HMCCU_Devices{$hmdata[2]}{addtype} = 'dev';
$HMCCU_Devices{$hmdata[2]}{valid} = 1;
$HMCCU_Addresses{$hmdata[3]}{address} = $hmdata[2];
$HMCCU_Addresses{$hmdata[3]}{addtype} = 'dev';
$HMCCU_Addresses{$hmdata[3]}{valid} = 1;
$count++;
}
elsif ($hmdata[0] eq 'C') {
@ -1224,8 +1261,10 @@ foreach(devid, root.Devices().EnumUsedIDs())
$HMCCU_Devices{$hmdata[1]}{name} = $hmdata[2];
$HMCCU_Devices{$hmdata[1]}{channels} = 1;
$HMCCU_Devices{$hmdata[1]}{addtype} = 'chn';
$HMCCU_Devices{$hmdata[1]}{valid} = 1;
$HMCCU_Addresses{$hmdata[2]}{address} = $hmdata[1];
$HMCCU_Addresses{$hmdata[2]}{addtype} = 'chn';
$HMCCU_Addresses{$hmdata[2]}{valid} = 1;
$count++;
}
}
@ -1250,9 +1289,29 @@ foreach(devid, root.Devices().EnumUsedIDs())
if (!defined ($ch->{channels}) || $ch->{channels} != $HMCCU_Devices{$add}{channels});
}
$hash->{NewDevices} = 0;
return $count;
}
####################################################
# Check if device/channel name or address is valid
####################################################
sub HMCCU_IsValidDevice ($)
{
my ($param) = @_;
if ($param =~ /^[A-Z]{3,3}[0-9]{7,7}$/ || $param =~ /^[A-Z]{3,3}[0-9]{7,7}:[0-9]+$/) {
return 0 if (! exists ($HMCCU_Devices{$param}));
return $HMCCU_Devices{$param}{valid};
}
else {
return 0 if (! exists ($HMCCU_Addresses{$param}));
return $HMCCU_Addresses{$param}{valid};
}
}
####################################################
# Get name of a CCU device by address.
# Channel number will be removed if specified.
@ -1443,39 +1502,6 @@ sub HMCCU_GetAttribute ($$$$)
return $value;
}
####################################################
# Submit HTTP request to CCU.
# If parameter $val is specified datapoint wil be
# set to value.
####################################################
sub HMCCU_HTTPRequest ($@)
{
my ($hash, $int, $add, $chn, $dpt, $val) = @_;
my $ccuget = AttrVal ($hash->{NAME}, 'ccuget', 'Value');
my $host = $hash->{host};
my $addr = $int.'.'.$add.':'.$chn.'.'.$dpt;
my $url = 'http://'.$host.':8181/do.exe?r1=dom.GetObject("'.$addr.'")';
if (defined ($val)) {
$url .= '.State("'.$val.'")';
}
else {
$url .= '.$ccuget()';
}
my $response = GetFileFromURL ($url);
if (defined ($response) && $response =~ /<r1>(.+)<\/r1>/) {
my $retval = $1;
if ($retval ne 'null') {
return defined ($val) ? 1 : $retval;
}
}
return 0;
}
####################################################
# Timer function for reading RPC queue
####################################################
@ -1504,7 +1530,6 @@ sub HMCCU_ReadRPCQueue ($)
$HMCCU_EventTime = time () if ($eventno == 0);
my @Tokens = split (/\|/, $element);
if ($Tokens[0] eq 'EV') {
# Log 2, "HMCCU: Event from ".$Tokens[1]." dp=".$Tokens[2]." val=".$Tokens[3];
my ($add, $chn) = split (/:/, $Tokens[1]);
my $reading = HMCCU_GetReadingName ('', $add, $chn, $Tokens[2], '',
$ccureadingformat);
@ -1513,10 +1538,13 @@ sub HMCCU_ReadRPCQueue ($)
last if ($eventno == $maxevents);
}
elsif ($Tokens[0] eq 'ND') {
# push (@newdevices, $Tokens[1]);
if (! exists ($HMCCU_Devices{$Tokens[1]})) {
$hash->{NewDevices} = 0 if (!exists ($hash->{NewDevices}));
$hash->{NewDevices}++;
}
}
elsif ($Tokens[0] eq 'DD') {
# push (@deldevices, $Tokens[1]);
push (@deldevices, $Tokens[1]);
}
elsif ($Tokens[0] eq 'EX') {
Log 1, "HMCCU: Received EX event. RPC server terminated.";
@ -1535,8 +1563,7 @@ sub HMCCU_ReadRPCQueue ($)
Log 1, "HMCCU: Received no events from CCU since 300 seconds";
}
# HMCCU_DeleteDevices (\@deldevices) if (@deldevices > 0);
# HMCCU_NewDevices (\@newdevices) if (@newdevices > 0);
HMCCU_DeleteDevices (\@deldevices) if (@deldevices > 0);
my @hm_pids;
my @ex_pids;
@ -1593,11 +1620,13 @@ sub HMCCU_GetDatapoint ($@)
{
my ($hash, $param, $reading) = @_;
my $name = $hash->{NAME};
my $type = $hash->{TYPE};
my $hmccu_hash;
my $value = '';
$hmccu_hash = HMCCU_GetHash ($hash);
return (-3, $value) if (!defined ($hmccu_hash));
return (-4, $value) if ($type ne 'HMCCU' && $hash->{ccudevstate} eq 'Deleted');
my $ccureadings = AttrVal ($name, 'ccureadings', 1);
my $readingformat = AttrVal ($name, 'ccureadingformat', 'name');
@ -1642,7 +1671,7 @@ sub HMCCU_GetDatapoint ($@)
}
return (0, $value) if ($reading eq '');
if ($hash->{TYPE} eq 'HMCCU') {
if ($type eq 'HMCCU') {
$value = HMCCU_UpdateClientReading ($hmccu_hash, $add, $chn, $reading,
$value);
}
@ -1672,9 +1701,11 @@ sub HMCCU_GetDatapoint ($@)
sub HMCCU_SetDatapoint ($$$)
{
my ($hash, $param, $value) = @_;
my $type = $hash->{TYPE};
my $hmccu_hash = HMCCU_GetHash ($hash);;
return -3 if (!defined ($hmccu_hash));
return -4 if ($type ne 'HMCCU' && $hash->{ccudevstate} eq 'Deleted');
my $url = 'http://'.$hmccu_hash->{host}.':8181/do.exe?r1=dom.GetObject("';
my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($param, $HMCCU_FLAG_INTERFACE);
@ -1764,9 +1795,11 @@ sub HMCCU_SetVariable ($$$)
sub HMCCU_GetUpdate ($$$)
{
my ($cl_hash, $addr, $ccuget) = @_;
my $type = $cl_hash->{TYPE};
my $hmccu_hash = HMCCU_GetHash ($cl_hash);
return -3 if (!defined ($hmccu_hash));
return -4 if ($type ne 'HMCCU' && $cl_hash->{ccudevstate} eq 'Deleted');
my $nam = '';
my $script;
@ -1789,10 +1822,13 @@ sub HMCCU_GetUpdate ($$$)
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.$ccuget());
if (oChannel) {
foreach(sDPId, oChannel.DPs()) {
object oDP = dom.GetObject(sDPId);
if (oDP) {
WriteLine (sChnName # "=" # oDP.Name() # "=" # oDP.$ccuget());
}
}
}
);
}
@ -1804,14 +1840,18 @@ foreach(sDPId, oChannel.DPs().EnumUsedIDs())
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.$ccuget());
}
if (odev) {
foreach (chnid, odev.Channels()) {
object ochn = dom.GetObject(chnid);
if (ochn) {
foreach(sDPId, ochn.DPs()) {
object oDP = dom.GetObject(sDPId);
if (oDP) {
WriteLine (ochn.Name() # "=" # oDP.Name() # "=" # oDP.$ccuget());
}
}
}
}
}
);
}
@ -1872,6 +1912,7 @@ sub HMCCU_GetChannel ($$)
{
my ($hash, $chnref) = @_;
my $name = $hash->{NAME};
my $type = $hash->{TYPE};
my $count = 0;
my %chnpars;
my $chnlist = '';
@ -1879,6 +1920,7 @@ sub HMCCU_GetChannel ($$)
my $hmccu_hash = HMCCU_GetHash ($hash);
return (-3, $result) if (!defined ($hmccu_hash));;
return (-4, $result) if ($type ne 'HMCCU' && $hash->{ccudevstate} eq 'Deleted');
my $ccuget = HMCCU_GetAttribute ($hmccu_hash, $hash, 'ccuget', 'Value');
my $ccureadings = AttrVal ($name, 'ccureadings', 1);
@ -1915,21 +1957,23 @@ sub HMCCU_GetChannel ($$)
string sDPId;
string sChannel;
string sChnList = "$chnlist";
foreach (sChannel, sChnList.Split(","))
{
object oChannel = dom.GetObject (sChannel);
foreach(sDPId, oChannel.DPs().EnumUsedIDs())
{
foreach (sChannel, sChnList.Split(",")) {
object oChannel = dom.GetObject (sChannel);
if (oChannel) {
foreach(sDPId, oChannel.DPs()) {
object oDP = dom.GetObject(sDPId);
WriteLine (sChannel # "=" # oDP.Name() # "=" # oDP.$ccuget());
}
if (oDP) {
WriteLine (sChannel # "=" # oDP.Name() # "=" # oDP.$ccuget());
}
}
}
}
);
my $response = HMCCU_HMScript ($hmccu_hash->{host}, $script);
return (-2, $result) if ($response eq '');
readingsBeginUpdate ($hash) if ($hash->{TYPE} ne 'HMCCU' && $ccureadings);
readingsBeginUpdate ($hash) if ($type ne 'HMCCU' && $ccureadings);
foreach my $dpdef (split /\n/, $response) {
my @dpdata = split /=/, $dpdef;
@ -1961,7 +2005,7 @@ foreach (sChannel, sChnList.Split(","))
$count++;
}
readingsEndUpdate ($hash, 1) if ($hash->{TYPE} ne 'HMCCU' && $ccureadings);
readingsEndUpdate ($hash, 1) if ($type ne 'HMCCU' && $ccureadings);
return ($count, $result);
}