mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-03 16:56:54 +00:00
HMCCU: Added support for client devices
git-svn-id: https://svn.fhem.de/fhem/trunk@9342 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
888704d115
commit
9d655e5df1
@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# $Id$
|
# $Id$
|
||||||
#
|
#
|
||||||
# Version 1.7
|
# Version 1.8
|
||||||
#
|
#
|
||||||
# (c) 2015 zap (zap01 <at> t-online <dot> de)
|
# (c) 2015 zap (zap01 <at> t-online <dot> de)
|
||||||
#
|
#
|
||||||
@ -13,21 +13,22 @@
|
|||||||
# define <name> HMCCU <host_or_ip>
|
# define <name> HMCCU <host_or_ip>
|
||||||
#
|
#
|
||||||
# set <name> devstate <ccu_object> <value>
|
# set <name> devstate <ccu_object> <value>
|
||||||
# set <name> datapoint <channel>.<datapoint> <value>
|
# set <name> datapoint <device>:<channel>.<datapoint> <value>
|
||||||
|
# set <name> var <value>
|
||||||
# set <name> execute <ccu_program>
|
# set <name> execute <ccu_program>
|
||||||
# set <name> clearmsg
|
# set <name> clearmsg
|
||||||
#
|
#
|
||||||
# get <name> devstate <ccu_object> [<reading>]
|
# get <name> devstate <ccu_object> [<reading>]
|
||||||
# get <name> vars <regexp>[,...]
|
# get <name> vars <regexp>[,...]
|
||||||
# get <name> channel <channel>[.<datapoint>]
|
# get <name> channel <device>:<channel>[.<datapoint_exp>]
|
||||||
# get <name> datapoint <channel>.<datapoint> [<reading>]
|
# get <name> datapoint <channel>.<datapoint> [<reading>]
|
||||||
# get <name> parfile [<parfile>]
|
# get <name> parfile [<parfile>]
|
||||||
#
|
#
|
||||||
# attr <name> ccureadings { 0 | 1 }
|
# attr <name> ccureadings { 0 | 1 }
|
||||||
# attr <name> stripchar <character>
|
# attr <name> stripchar <character>
|
||||||
# attr <name> parfile <parfile>
|
# attr <name> parfile <parfile>
|
||||||
# attr <name> substitute <regexp>:<text>[,...]
|
# attr <name> stateval <text1>:<subtext1>[,...]
|
||||||
# attr <name> units { 0 | 1 }
|
# attr <name> substitute <regexp1>:<subtext1>[,...]
|
||||||
#
|
#
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
@ -40,12 +41,18 @@ use XML::Simple qw(:strict);
|
|||||||
# use Data::Dumper;
|
# use Data::Dumper;
|
||||||
|
|
||||||
sub HMCCU_Define ($$);
|
sub HMCCU_Define ($$);
|
||||||
|
sub HMCCU_Undef ($$);
|
||||||
sub HMCCU_Set ($@);
|
sub HMCCU_Set ($@);
|
||||||
sub HMCCU_Get ($@);
|
sub HMCCU_Get ($@);
|
||||||
|
sub HMCCU_Attr ($@);
|
||||||
sub HMCCU_ParseCCUDev ($);
|
sub HMCCU_ParseCCUDev ($);
|
||||||
sub HMCCU_SetError ($$);
|
sub HMCCU_SetError ($$);
|
||||||
|
sub HMCCU_SetState ($$);
|
||||||
sub HMCCU_Substitute ($$);
|
sub HMCCU_Substitute ($$);
|
||||||
|
sub HMCCU_UpdateClientReading ($$$);
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
# Initialize module
|
||||||
#####################################
|
#####################################
|
||||||
|
|
||||||
sub HMCCU_Initialize ($)
|
sub HMCCU_Initialize ($)
|
||||||
@ -53,12 +60,16 @@ sub HMCCU_Initialize ($)
|
|||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
|
|
||||||
$hash->{DefFn} = "HMCCU_Define";
|
$hash->{DefFn} = "HMCCU_Define";
|
||||||
|
$hash->{UndefFn} = "HMCCU_Undef";
|
||||||
$hash->{SetFn} = "HMCCU_Set";
|
$hash->{SetFn} = "HMCCU_Set";
|
||||||
$hash->{GetFn} = "HMCCU_Get";
|
$hash->{GetFn} = "HMCCU_Get";
|
||||||
|
$hash->{AttrFn} = "HMCCU_Attr";
|
||||||
|
|
||||||
$hash->{AttrList} = "model:HMCCU stripchar ccureadings:0,1 parfile substitute units:0,1 loglevel:0,1,2,3,4,5,6 ". $readingFnAttributes;
|
$hash->{AttrList} = "stripchar ccureadings:0,1 parfile stateval substitute units:0,1 loglevel:0,1,2,3,4,5,6 ". $readingFnAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
# Define device
|
||||||
#####################################
|
#####################################
|
||||||
|
|
||||||
sub HMCCU_Define ($$)
|
sub HMCCU_Define ($$)
|
||||||
@ -67,22 +78,51 @@ sub HMCCU_Define ($$)
|
|||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my @a = split("[ \t][ \t]*", $def);
|
my @a = split("[ \t][ \t]*", $def);
|
||||||
|
|
||||||
return "Define the CCU hostname or IP address as a parameter i.e. MyCCU" if(@a < 3);
|
return "Define CCU hostname or IP address as a parameter" if(@a < 3);
|
||||||
|
|
||||||
my $host = $a[2];
|
my $host = $a[2];
|
||||||
|
|
||||||
$attr{$name}{stripchar} = '';
|
|
||||||
$attr{$name}{ccureadings} = 1;
|
|
||||||
$attr{$name}{parfile} = '';
|
|
||||||
$attr{$name}{substitute} = '';
|
|
||||||
$attr{$name}{units} = 0;
|
|
||||||
|
|
||||||
$hash->{host} = $host;
|
$hash->{host} = $host;
|
||||||
readingsSingleUpdate ($hash, "state", "Initialized", 1);
|
$hash->{Clients} = ':HMCCUDEV:';
|
||||||
|
|
||||||
|
HMCCU_SetState ($hash, "Initialized");
|
||||||
|
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
# Set attribute
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
sub HMCCU_Attr ($@)
|
||||||
|
{
|
||||||
|
my ($cmd, $name, $attrname, $attrval) = @_;
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
# Delete device
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
sub HMCCU_Undef ($$)
|
||||||
|
{
|
||||||
|
my ($hash, $arg) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
|
# Delete reference to IO module in client devices
|
||||||
|
foreach my $d (sort keys %defs) {
|
||||||
|
if (defined ($defs{$d}) && defined($defs{$d}{IODev}) &&
|
||||||
|
$defs{$d}{IODev} == $hash) {
|
||||||
|
delete $defs{$d}{IODev};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
# Set commands
|
||||||
#####################################
|
#####################################
|
||||||
|
|
||||||
sub HMCCU_Set ($@)
|
sub HMCCU_Set ($@)
|
||||||
@ -90,62 +130,49 @@ sub HMCCU_Set ($@)
|
|||||||
my ($hash, @a) = @_;
|
my ($hash, @a) = @_;
|
||||||
my $name = shift @a;
|
my $name = shift @a;
|
||||||
my $opt = shift @a;
|
my $opt = shift @a;
|
||||||
my $stripchar = AttrVal ($name, "stripchar", '');
|
my $options = "devstate datapoint var execute clearmsg";
|
||||||
my $host = $hash->{host};
|
my $host = $hash->{host};
|
||||||
|
|
||||||
|
my $stripchar = AttrVal ($name, "stripchar", '');
|
||||||
|
my $stateval = AttrVal ($name, "stateval", '');
|
||||||
|
|
||||||
# process set <name> command par1 par2 ...
|
# process set <name> command par1 par2 ...
|
||||||
# if more than one parameter is specified parameters
|
# if more than one parameter is specified parameters
|
||||||
# are concatenated by blanks
|
# are concatenated by blanks
|
||||||
if ($opt eq "state" || $opt eq "devstate") {
|
if ($opt eq 'state' || $opt eq 'devstate' || $opt eq 'datapoint' || $opt eq 'var') {
|
||||||
my $objname = shift @a;
|
my $objname = shift @a;
|
||||||
my $objvalue = join ('%20', @a);
|
my $objvalue = join ('%20', @a);
|
||||||
|
my $url = 'http://'.$host.':8181/do.exe?r1=dom.GetObject("';
|
||||||
|
|
||||||
if (!defined ($objname) || !defined ($objvalue)) {
|
if (!defined ($objname) || !defined ($objvalue)) {
|
||||||
return HMCCU_SetError ($hash, "Usage: set <device> devstate <objname> <objvalue>");
|
return HMCCU_SetError ($hash, "Usage: set <device> $opt <objname> <objvalue>");
|
||||||
}
|
}
|
||||||
|
|
||||||
$objname =~ s/$stripchar$// if ($stripchar ne '');
|
$objname =~ s/$stripchar$// if ($stripchar ne '');
|
||||||
|
$objvalue = HMCCU_Substitute ($objvalue, $stateval);
|
||||||
|
|
||||||
my $url = 'http://'.$host.':8181/do.exe?r1=dom.GetObject("'.$objname.'").State("'.$objvalue.'")';
|
my ($dev, $chn, $dpt, $flags) = HMCCU_ParseCCUDev ($objname);
|
||||||
|
if ($opt eq 'devstate' || $opt eq 'state' || $opt eq 'var') {
|
||||||
|
if ($flags > 3) {
|
||||||
|
return HMCCU_SetError ($hash, "Specify varname or device:channel");
|
||||||
|
}
|
||||||
|
$url = $url.$objname.'").State("'.$objvalue.'")';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($flags != 7) {
|
||||||
|
return HMCCU_SetError ($hash, "Specify device:channel.datapoint");
|
||||||
|
}
|
||||||
|
$url = $url.$dev.':'.$chn.'").DPByHssDP("'.$dpt.'").State("'.$objvalue.'")';
|
||||||
|
}
|
||||||
|
|
||||||
my $response;
|
my $response = GetFileFromURL ($url);
|
||||||
my $retcode = '';
|
|
||||||
|
|
||||||
$response = GetFileFromURL ($url);
|
|
||||||
if ($response =~ /<r1>null</) {
|
if ($response =~ /<r1>null</) {
|
||||||
return HMCCU_SetError ($hash, "Error during CCU communication");
|
return HMCCU_SetError ($hash, "Error during CCU communication");
|
||||||
}
|
}
|
||||||
|
|
||||||
readingsSingleUpdate ($hash, "state", "OK", 1);
|
HMCCU_SetState ($hash, "OK");
|
||||||
|
|
||||||
return $retcode;
|
return undef;
|
||||||
}
|
|
||||||
elsif ($opt eq "datapoint") {
|
|
||||||
my $objname = shift @a;
|
|
||||||
my $objvalue = join ('%20', @a);
|
|
||||||
|
|
||||||
if (!defined ($objname) || !defined ($objvalue)) {
|
|
||||||
return HMCCU_SetError ($hash, "Usage: set <device> datapoint <objname> <objvalue>");
|
|
||||||
}
|
|
||||||
|
|
||||||
my ($device, $channel, $datapoint) = HMCCU_ParseCCUDev ($objname);
|
|
||||||
if ($device eq '?' || $channel eq '?' || $datapoint eq '.*') {
|
|
||||||
return HMCCU_SetError ($hash, "Format for objname is device:channel.datapoint");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $url = 'http://'.$host.':8181/do.exe?r1=dom.GetObject("'.$channel.'").DPByHssDP("'.$datapoint.'").State("'.$objvalue.'")';
|
|
||||||
|
|
||||||
my $response;
|
|
||||||
my $retcode = '';
|
|
||||||
|
|
||||||
$response = GetFileFromURL ($url);
|
|
||||||
if ($response =~ /<r1>null</) {
|
|
||||||
return HMCCU_SetError ($hash, "Error during CCU communication");
|
|
||||||
}
|
|
||||||
|
|
||||||
readingsSingleUpdate ($hash, "state", "OK", 1);
|
|
||||||
|
|
||||||
return $retcode;
|
|
||||||
}
|
}
|
||||||
elsif ($opt eq "execute") {
|
elsif ($opt eq "execute") {
|
||||||
my $program = shift @a;
|
my $program = shift @a;
|
||||||
@ -162,7 +189,6 @@ sub HMCCU_Set ($@)
|
|||||||
# Query program ID
|
# Query program ID
|
||||||
$response = GetFileFromURL ($url);
|
$response = GetFileFromURL ($url);
|
||||||
my $xmlin = XMLin ($response, ForceArray => 0, KeyAttr => ['name']);
|
my $xmlin = XMLin ($response, ForceArray => 0, KeyAttr => ['name']);
|
||||||
|
|
||||||
if (!defined ($xmlin->{program}->{$program}->{id})) {
|
if (!defined ($xmlin->{program}->{$program}->{id})) {
|
||||||
return HMCCU_SetError ($hash, "Program not found");
|
return HMCCU_SetError ($hash, "Program not found");
|
||||||
}
|
}
|
||||||
@ -170,25 +196,28 @@ sub HMCCU_Set ($@)
|
|||||||
$programid = $xmlin->{program}->{$program}->{id};
|
$programid = $xmlin->{program}->{$program}->{id};
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = GetFileFromURL ($runurl . $programid);
|
GetFileFromURL ($runurl . $programid);
|
||||||
readingsSingleUpdate ($hash, "state", "OK", 1);
|
|
||||||
|
|
||||||
return $response;
|
HMCCU_SetState ($hash, "OK");
|
||||||
|
|
||||||
|
return undef;
|
||||||
}
|
}
|
||||||
elsif ($opt eq 'clearmsg') {
|
elsif ($opt eq 'clearmsg') {
|
||||||
my $url = 'http://'.$host.'/config/xmlapi/systemNotificationClear.cgi';
|
my $url = 'http://'.$host.'/config/xmlapi/systemNotificationClear.cgi';
|
||||||
my $response;
|
|
||||||
|
|
||||||
$response = GetFileFromURL ($url);
|
GetFileFromURL ($url);
|
||||||
readingsSingleUpdate ($hash, "state", "OK", 1);
|
|
||||||
|
|
||||||
return '';
|
HMCCU_SetState ($hash, "OK");
|
||||||
|
|
||||||
|
return undef;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return "HMCCU: Unknown argument $opt, choose one of devstate datapoint execute clearmsg";
|
return "HMCCU: Unknown argument $opt, choose one of ".$options;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
# Get commands
|
||||||
#####################################
|
#####################################
|
||||||
|
|
||||||
sub HMCCU_Get ($@)
|
sub HMCCU_Get ($@)
|
||||||
@ -196,12 +225,11 @@ sub HMCCU_Get ($@)
|
|||||||
my ($hash, @a) = @_;
|
my ($hash, @a) = @_;
|
||||||
my $name = shift @a;
|
my $name = shift @a;
|
||||||
my $opt = shift @a;
|
my $opt = shift @a;
|
||||||
my $host = $hash->{host};
|
my $options = "devstate datapoint vars channel parfile";
|
||||||
|
my $host = $hash->{host};
|
||||||
|
|
||||||
my $readings = AttrVal ($name, "ccureadings", 1);
|
my $readings = AttrVal ($name, "ccureadings", 1);
|
||||||
my $parfile = AttrVal ($name, "parfile", '');
|
my $parfile = AttrVal ($name, "parfile", '');
|
||||||
my $substitute = AttrVal ($name, "substitute", '');
|
|
||||||
my $units = AttrVal ($name, "units", 0);
|
|
||||||
|
|
||||||
if ($opt eq 'state' || $opt eq 'devstate') {
|
if ($opt eq 'state' || $opt eq 'devstate') {
|
||||||
my $ccuobj = shift @a;
|
my $ccuobj = shift @a;
|
||||||
@ -210,25 +238,26 @@ my $host = $hash->{host};
|
|||||||
my $retcode;
|
my $retcode;
|
||||||
|
|
||||||
if (!defined ($ccuobj)) {
|
if (!defined ($ccuobj)) {
|
||||||
return HMCCU_SetError ($hash, "Usage: get <device> devstate <objname> [<reading>]");
|
return HMCCU_SetError ($hash,
|
||||||
|
"Usage: get <device> devstate <device>:<channel> [<reading>]");
|
||||||
|
}
|
||||||
|
|
||||||
|
my ($dev, $chn, $dpt, $flags) = HMCCU_ParseCCUDev ($ccuobj);
|
||||||
|
if ($flags != 3) {
|
||||||
|
return HMCCU_SetError ($hash, "Specify <device>:<channel>");
|
||||||
}
|
}
|
||||||
|
|
||||||
my $url = 'http://'.$host.':8181/do.exe?r1=dom.GetObject("'.$ccuobj.'").State()';
|
my $url = 'http://'.$host.':8181/do.exe?r1=dom.GetObject("'.$ccuobj.'").State()';
|
||||||
$reading = $ccuobj if (!defined ($reading));
|
$reading = $ccuobj.".STATE" if (!defined ($reading));
|
||||||
|
|
||||||
$response = GetFileFromURL ($url);
|
$response = GetFileFromURL ($url);
|
||||||
$response =~ m/<r1>(.*)<\/r1>/;
|
$response =~ m/<r1>(.*)<\/r1>/;
|
||||||
$retcode = $1;
|
$retcode = $1;
|
||||||
|
|
||||||
if (defined ($retcode) && $retcode ne '' && $retcode ne 'null') {
|
if (defined ($retcode) && $retcode ne '' && $retcode ne 'null') {
|
||||||
readingsSingleUpdate ($hash, "state", "OK", 1);
|
HMCCU_SetState ($hash, "OK");
|
||||||
if ($readings) {
|
$retcode = HMCCU_UpdateClientReading ($hash, $reading, $retcode);
|
||||||
readingsSingleUpdate ($hash, $reading, $retcode, 1);
|
return $readings ? undef : $retcode;
|
||||||
return '';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return $retcode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return HMCCU_SetError ($hash, "Error during CCU request");
|
return HMCCU_SetError ($hash, "Error during CCU request");
|
||||||
@ -241,14 +270,15 @@ my $host = $hash->{host};
|
|||||||
my $retcode;
|
my $retcode;
|
||||||
|
|
||||||
if (!defined ($ccuobj)) {
|
if (!defined ($ccuobj)) {
|
||||||
return HMCCU_SetError ($hash, "Usage: get <device> datapoint <objname> [<reading>]");
|
return HMCCU_SetError ($hash,
|
||||||
|
"Usage: get <device> datapoint <device>:<channel>.<datapoint> [<reading>]");
|
||||||
}
|
}
|
||||||
my ($device, $channel, $datapoint) = HMCCU_ParseCCUDev ($ccuobj);
|
my ($dev, $chn, $dpt, $flags) = HMCCU_ParseCCUDev ($ccuobj);
|
||||||
if ($device eq '?' || $channel eq '?' || $datapoint eq '.*') {
|
if ($flags != 7) {
|
||||||
return HMCCU_SetError ($hash, "Format for objname is device:channel.datapoint");
|
return HMCCU_SetError ($hash, "Specify device:channel.datapoint");
|
||||||
}
|
}
|
||||||
|
|
||||||
my $url = 'http://'.$host.':8181/do.exe?r1=dom.GetObject("'.$channel.'").DPByHssDP("'.$datapoint.'").Value()';
|
my $url = 'http://'.$host.':8181/do.exe?r1=dom.GetObject("'.$dev.':'.$chn.'").DPByHssDP("'.$dpt.'").Value()';
|
||||||
$reading = $ccuobj if (!defined ($reading));
|
$reading = $ccuobj if (!defined ($reading));
|
||||||
|
|
||||||
$response = GetFileFromURL ($url);
|
$response = GetFileFromURL ($url);
|
||||||
@ -256,14 +286,9 @@ my $host = $hash->{host};
|
|||||||
$retcode = $1;
|
$retcode = $1;
|
||||||
|
|
||||||
if (defined ($retcode) && $retcode ne '' && $retcode ne 'null') {
|
if (defined ($retcode) && $retcode ne '' && $retcode ne 'null') {
|
||||||
readingsSingleUpdate ($hash, "state", "OK", 1);
|
HMCCU_SetState ($hash, "OK");
|
||||||
if ($readings) {
|
$retcode = HMCCU_UpdateClientReading ($hash, $ccuobj, $retcode);
|
||||||
readingsSingleUpdate ($hash, $reading, $retcode, 1);
|
return $readings ? undef : $retcode;
|
||||||
return '';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return $retcode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return HMCCU_SetError ($hash, "Error during CCU request");
|
return HMCCU_SetError ($hash, "Error during CCU request");
|
||||||
@ -276,7 +301,7 @@ my $host = $hash->{host};
|
|||||||
my $result = '';
|
my $result = '';
|
||||||
|
|
||||||
if (!defined ($varname)) {
|
if (!defined ($varname)) {
|
||||||
return HMCCU_SetError ($hash, "Usage: get <device> vars <regexp>");
|
return HMCCU_SetError ($hash, "Usage: get <device> vars <regexp>[,...]");
|
||||||
}
|
}
|
||||||
|
|
||||||
my @varlist = split /,/, $varname;
|
my @varlist = split /,/, $varname;
|
||||||
@ -291,7 +316,7 @@ my $host = $hash->{host};
|
|||||||
foreach my $variable (@{$xmlin->{systemVariable}}) {
|
foreach my $variable (@{$xmlin->{systemVariable}}) {
|
||||||
foreach my $varexp (@varlist) {
|
foreach my $varexp (@varlist) {
|
||||||
if ($variable->{name} =~ /$varexp/) {
|
if ($variable->{name} =~ /$varexp/) {
|
||||||
$result = $result . $variable->{name} . "=" . $variable->{value} . "\n";
|
$result .= $variable->{name}."=".$variable->{value}."\n";
|
||||||
if ($readings) {
|
if ($readings) {
|
||||||
readingsBulkUpdate ($hash, $variable->{name}, $variable->{value});
|
readingsBulkUpdate ($hash, $variable->{name}, $variable->{value});
|
||||||
}
|
}
|
||||||
@ -300,8 +325,8 @@ my $host = $hash->{host};
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($readings) {
|
if ($readings) {
|
||||||
readingsEndUpdate ($hash, defined ($hash->{LOCAL} ? 0 : 1));
|
readingsEndUpdate ($hash, 1);
|
||||||
return '';
|
return undef;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return $result;
|
return $result;
|
||||||
@ -314,51 +339,40 @@ my $host = $hash->{host};
|
|||||||
my $result = '';
|
my $result = '';
|
||||||
my $rname;
|
my $rname;
|
||||||
|
|
||||||
my ($device, $channel, $datapoint) = HMCCU_ParseCCUDev ($param);
|
my ($dev, $chn, $dpt, $flags) = HMCCU_ParseCCUDev ($param);
|
||||||
if ($device eq '?' || $channel eq '?') {
|
if (($flags & 3 ) != 3) {
|
||||||
return HMCCU_SetError ($hash, "Usage: get <device> channel <ccudev>:<channel>[.<datapoint>]");
|
return HMCCU_SetError ($hash,
|
||||||
|
"Usage: get <device> channel <ccudev>:<channel>[.<datapoint>]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $devch = $dev.':'.$chn;
|
||||||
$response = GetFileFromURL ($url);
|
$response = GetFileFromURL ($url);
|
||||||
my $xmlin = XMLin ($response, ForceArray => ['device', 'channel', 'datapoint'], KeyAttr => { device => 'name', channel => 'name' });
|
my $xmlin = XMLin ($response,
|
||||||
|
ForceArray => ['device', 'channel', 'datapoint'],
|
||||||
if (!defined (@{$xmlin->{device}->{$device}->{channel}->{$channel}->{datapoint}})) {
|
KeyAttr => { device => 'name', channel => 'name' }
|
||||||
|
);
|
||||||
|
if (!defined (@{$xmlin->{device}->{$dev}->{channel}->{$devch}->{datapoint}})) {
|
||||||
return HMCCU_SetError ($hash, "Device or channel not defined");
|
return HMCCU_SetError ($hash, "Device or channel not defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
my @dps = @{$xmlin->{device}->{$device}->{channel}->{$channel}->{datapoint}};
|
my @dps = @{$xmlin->{device}->{$dev}->{channel}->{$devch}->{datapoint}};
|
||||||
if ($readings) {
|
|
||||||
readingsBeginUpdate ($hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $dp (@dps) {
|
foreach my $dp (@dps) {
|
||||||
if ($dp->{name} =~ /$datapoint/) {
|
if ($dp->{name} =~ /$dpt/) {
|
||||||
my $dpname = $dp->{name};
|
my $dpname = $dp->{name};
|
||||||
my $v = $dp->{value};
|
my $v = $dp->{value};
|
||||||
|
|
||||||
$dpname =~ /.*\.(.*)$/;
|
$dpname =~ /.*\.(.*)$/;
|
||||||
$rname = $channel . ".$1";
|
$rname = $devch.".$1";
|
||||||
|
|
||||||
$v = HMCCU_Substitute ($v, $substitute);
|
$v = HMCCU_UpdateClientReading ($hash, $rname, $v);
|
||||||
if ($units == 1) {
|
$result .= $rname."=".$v."\n";
|
||||||
$v .= ' ' . $dp->{valueunit};
|
|
||||||
}
|
|
||||||
$result = $result . $rname . "=" . $v . "\n";
|
|
||||||
if ($readings) {
|
|
||||||
readingsBulkUpdate ($hash, $rname, $v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readingsSingleUpdate ($hash, "state", "OK", 1);
|
HMCCU_SetState ($hash, "OK");
|
||||||
|
|
||||||
if ($readings) {
|
return $readings ? undef : $result;
|
||||||
readingsEndUpdate ($hash, defined ($hash->{LOCAL} ? 0 : 1));
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
elsif ($opt eq 'parfile') {
|
elsif ($opt eq 'parfile') {
|
||||||
my $par_parfile = shift @a;
|
my $par_parfile = shift @a;
|
||||||
@ -394,11 +408,11 @@ my $host = $hash->{host};
|
|||||||
}
|
}
|
||||||
|
|
||||||
$response = GetFileFromURL ($url);
|
$response = GetFileFromURL ($url);
|
||||||
my $xmlin = XMLin ($response, ForceArray => ['device', 'channel', 'datapoint'], KeyAttr => { device => 'name', channel => 'name' });
|
my $xmlin = XMLin (
|
||||||
|
$response,
|
||||||
if ($readings) {
|
ForceArray => ['device', 'channel', 'datapoint'],
|
||||||
readingsBeginUpdate ($hash);
|
KeyAttr => { device => 'name', channel => 'name' }
|
||||||
}
|
);
|
||||||
|
|
||||||
foreach my $param (@parameters) {
|
foreach my $param (@parameters) {
|
||||||
my @partoks = split /\s+/, $param;
|
my @partoks = split /\s+/, $param;
|
||||||
@ -407,54 +421,46 @@ my $host = $hash->{host};
|
|||||||
next if (scalar @partoks == 0);
|
next if (scalar @partoks == 0);
|
||||||
next if ($partoks[0] =~ /^#/);
|
next if ($partoks[0] =~ /^#/);
|
||||||
|
|
||||||
my ($device, $channel, $datapoint) = HMCCU_ParseCCUDev ($partoks[0]);
|
|
||||||
|
|
||||||
# Ignore wrong CCU device specifications
|
# Ignore wrong CCU device specifications
|
||||||
next if ($device eq '?' || $channel eq '?');
|
my ($dev, $chn, $dpt, $flags) = HMCCU_ParseCCUDev ($partoks[0]);
|
||||||
|
next if (($flags & 3) != 3);
|
||||||
|
my $devch = $dev.':'.$chn;
|
||||||
|
|
||||||
# Ignore not existing devices/channels/datapoints
|
# Ignore not existing devices/channels/datapoints
|
||||||
next if (!defined (@{$xmlin->{device}->{$device}->{channel}->{$channel}->{datapoint}}));
|
next if (!defined (@{$xmlin->{device}->{$dev}->{channel}->{$devch}->{datapoint}}));
|
||||||
my @dps = @{$xmlin->{device}->{$device}->{channel}->{$channel}->{datapoint}};
|
my @dps = @{$xmlin->{device}->{$dev}->{channel}->{$devch}->{datapoint}};
|
||||||
|
|
||||||
foreach my $dp (@dps) {
|
foreach my $dp (@dps) {
|
||||||
if ($dp->{name} =~ /$datapoint/) {
|
if ($dp->{name} =~ /$dpt/) {
|
||||||
my $dpname = $dp->{name};
|
my $dpname = $dp->{name};
|
||||||
my $v = $dp->{value};
|
my $v = $dp->{value};
|
||||||
|
|
||||||
if (@partoks > 1) {
|
$v = HMCCU_Substitute ($v, $partoks[1]) if (@partoks > 1);
|
||||||
$v = HMCCU_Substitute ($v, $partoks[1]);
|
|
||||||
}
|
|
||||||
$dpname =~ /.*\.(.*)$/;
|
$dpname =~ /.*\.(.*)$/;
|
||||||
$rname = $channel . ".$1";
|
$rname = $devch.".$1";
|
||||||
$result = $result . $rname . "=" . $v . ' ' . $dp->{valueunit} . "\n";
|
$v = HMCCU_UpdateClientReading ($hash, $rname, $v);
|
||||||
if ($readings) {
|
$result .= $rname."=".$v.' '.$dp->{valueunit}."\n";
|
||||||
readingsBulkUpdate ($hash, $rname, $v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readingsSingleUpdate ($hash, "state", "OK", 1);
|
HMCCU_SetState ($hash, "OK");
|
||||||
|
|
||||||
if ($readings) {
|
return $readings ? undef : $result;
|
||||||
readingsEndUpdate ($hash, defined ($hash->{LOCAL} ? 0 : 1));
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return "HMCCU: Unknown argument $opt, choose one of devstate datapoint vars channel parfile";
|
return "HMCCU: Unknown argument $opt, choose one of ".$options;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#####################################
|
##################################################################
|
||||||
# Parse CCU object name
|
# Parse CCU object name.
|
||||||
#
|
#
|
||||||
# Input: object name in format device:channel.datapoint
|
# Input: object name in format device:channel.datapoint
|
||||||
# Output: array with ( device, device:channel, datapoint )
|
#
|
||||||
#####################################
|
# Output: array with ( device, channel, datapoint, flags )
|
||||||
|
# flag bits: 0=Device 1=Channel 2=Datapoint
|
||||||
|
##################################################################
|
||||||
|
|
||||||
sub HMCCU_ParseCCUDev ($)
|
sub HMCCU_ParseCCUDev ($)
|
||||||
{
|
{
|
||||||
@ -462,47 +468,56 @@ sub HMCCU_ParseCCUDev ($)
|
|||||||
my $p1 = '?';
|
my $p1 = '?';
|
||||||
my $p2 = '?';
|
my $p2 = '?';
|
||||||
my $p3 = '.*';
|
my $p3 = '.*';
|
||||||
|
my $p4 = 0;
|
||||||
|
|
||||||
#
|
|
||||||
# Syntax of CCU device specification is:
|
# Syntax of CCU device specification is:
|
||||||
#
|
|
||||||
# devicename:channelno[.datapoint]
|
# devicename:channelno[.datapoint]
|
||||||
#
|
|
||||||
# Parameter datapoint is optional.
|
|
||||||
#
|
|
||||||
if ($param =~ /^.+:/) {
|
if ($param =~ /^.+:/) {
|
||||||
$param =~ /^(.*):/;
|
$param =~ /^(.*):/;
|
||||||
$p1 = $1;
|
$p1 = $1;
|
||||||
|
$p4 = 1;
|
||||||
|
|
||||||
if ($param =~ /^.+:[0-9]+/) {
|
if ($param =~ /^.+:[0-9]+/) {
|
||||||
$param =~ /^.*:([0-9]+)/;
|
$param =~ /^.*:([0-9]+)/;
|
||||||
$p2 = $p1 . ":" . $1;
|
$p2 = $1;
|
||||||
|
$p4 |= 2;
|
||||||
|
|
||||||
if ($param =~ /\..*$/) {
|
if ($param =~ /\..*$/) {
|
||||||
$param =~ /\.(.*)$/;
|
$param =~ /\.(.*)$/;
|
||||||
$p3 = $1;
|
$p3 = $1;
|
||||||
|
$p4 |= 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($p1, $p2, $p3);
|
return ($p1, $p2, $p3, $p4);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub HMCCU_SetError ($$)
|
sub HMCCU_SetError ($$)
|
||||||
{
|
{
|
||||||
my ($hash, $text) = @_;
|
my ($hash, $text) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
$text = "HMCCU: " . $text;
|
$text = "HMCCU: ".$name." ". $text;
|
||||||
readingsSingleUpdate ($hash, "state", "Error", 1);
|
HMCCU_SetState ($hash, "Error");
|
||||||
Log 1, $text;
|
Log 1, $text;
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub HMCCU_SetState ($$)
|
||||||
|
{
|
||||||
|
my ($hash, $text) = @_;
|
||||||
|
|
||||||
|
if (defined ($hash) && defined ($text)) {
|
||||||
|
readingsSingleUpdate ($hash, "state", $text, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub HMCCU_Substitute ($$)
|
sub HMCCU_Substitute ($$)
|
||||||
{
|
{
|
||||||
my ($value, $substitutes) = @_;
|
my ($value, $substitutes) = @_;
|
||||||
|
|
||||||
return $value if (!defined ($substitutes));
|
return $value if (!defined ($substitutes) || $substitutes eq '');
|
||||||
|
|
||||||
my @sub_list = split /,/,$substitutes;
|
my @sub_list = split /,/,$substitutes;
|
||||||
|
|
||||||
@ -518,6 +533,64 @@ sub HMCCU_Substitute ($$)
|
|||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
# Update HMCCU readings and client readings.
|
||||||
|
# Reading values are substituted with client priority
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
sub HMCCU_UpdateClientReading ($$$)
|
||||||
|
{
|
||||||
|
my ($hash, $reading, $value) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
|
my $hmccu_substitute = AttrVal ($name, 'substitute', '');
|
||||||
|
my $hmccu_updreadings = AttrVal ($name, 'ccureadings', 1);
|
||||||
|
|
||||||
|
# Check syntax
|
||||||
|
return 0 if (!defined ($hash) || !defined ($reading) || !defined ($value));
|
||||||
|
|
||||||
|
# Get CCU device name from reading name
|
||||||
|
my ($dev, $chn, $dpt, $flags) = HMCCU_ParseCCUDev ($reading);
|
||||||
|
return 0 if ($flags == 0);
|
||||||
|
|
||||||
|
# Update HMCCU reading
|
||||||
|
my $hmccu_value = HMCCU_Substitute ($value, $hmccu_substitute);
|
||||||
|
if ($hmccu_updreadings) {
|
||||||
|
readingsSingleUpdate ($hash, $reading, $hmccu_value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update client readings
|
||||||
|
foreach my $d (keys %defs) {
|
||||||
|
# Get hash of device
|
||||||
|
my $ch = $defs{$d};
|
||||||
|
|
||||||
|
if (defined ($ch->{IODev}) && $ch->{IODev} == $hash &&
|
||||||
|
defined ($ch->{ccudev}) && $ch->{ccudev} eq $dev) {
|
||||||
|
my $upd = AttrVal ($ch->{NAME}, 'ccureadings', 1);
|
||||||
|
my $substitute = AttrVal ($ch->{NAME}, 'substitute', '');
|
||||||
|
|
||||||
|
# Client substitute attribute has priority
|
||||||
|
if ($substitute ne '') {
|
||||||
|
$value = HMCCU_Substitute ($value, $substitute);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$value = $hmccu_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($upd == 1) {
|
||||||
|
readingsSingleUpdate ($ch, $reading, $value, 1);
|
||||||
|
if ($dpt eq 'STATE') {
|
||||||
|
HMCCU_SetState ($ch, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hmccu_value;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
|
|
||||||
@ -563,6 +636,10 @@ sub HMCCU_Substitute ($$)
|
|||||||
Example:<br/>
|
Example:<br/>
|
||||||
<code> set d_ccu datapoint THERMOSTAT_WOHNEN:2.SET_TEMPERATURE 21</code>
|
<code> set d_ccu datapoint THERMOSTAT_WOHNEN:2.SET_TEMPERATURE 21</code>
|
||||||
</li><br/>
|
</li><br/>
|
||||||
|
<li>set <<i>Name</i>> var <<i>variable</i>> <<i>Value</i>>
|
||||||
|
<br/>
|
||||||
|
Set CCU variable value.
|
||||||
|
</li><br/>
|
||||||
<li>set <<i>Name</i>> clearmsg
|
<li>set <<i>Name</i>> clearmsg
|
||||||
<br/>
|
<br/>
|
||||||
Clear CCU messages.
|
Clear CCU messages.
|
||||||
@ -622,6 +699,10 @@ sub HMCCU_Substitute ($$)
|
|||||||
<br/>
|
<br/>
|
||||||
Define parameter file for command get parfile.
|
Define parameter file for command get parfile.
|
||||||
</li><br/>
|
</li><br/>
|
||||||
|
<li>stateval <<i>text</i>:<i>text</i>[,...]</i>>
|
||||||
|
<br/>
|
||||||
|
Define substitions for values in set devstate/datapoint command.
|
||||||
|
</li><br/>
|
||||||
<li>substitude <<i>expression</i>:<i>string</i>[,...]</i>>
|
<li>substitude <<i>expression</i>:<i>string</i>[,...]</i>>
|
||||||
<br/>
|
<br/>
|
||||||
Define substitions for reading values. Substitutions for parfile values must
|
Define substitions for reading values. Substitutions for parfile values must
|
||||||
|
Loading…
x
Reference in New Issue
Block a user