mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-09 20:57:11 +00:00
HMCCU: New release
git-svn-id: https://svn.fhem.de/fhem/trunk@17325 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
a3a6316db1
commit
e60d131d86
@ -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.
|
||||
- change: 88_HMCCU: New release
|
||||
- feature: 93_DbLog: 3.11.0, function reduceLog[Nbl] syntax extended to limit
|
||||
days to reduce (pls. see commandref for details)
|
||||
- change: 01_FHEMWEB.pm: change default style to f18
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.2.003
|
||||
# Version 4.3
|
||||
#
|
||||
# (c) 2018 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
@ -62,14 +62,16 @@ use SetExtensions;
|
||||
|
||||
# use Time::HiRes qw( gettimeofday usleep );
|
||||
|
||||
sub HMCCUCHN_Initialize ($);
|
||||
sub HMCCUCHN_Define ($@);
|
||||
sub HMCCUCHN_InitDevice ($$);
|
||||
sub HMCCUCHN_Set ($@);
|
||||
sub HMCCUCHN_Get ($@);
|
||||
sub HMCCUCHN_Attr ($@);
|
||||
|
||||
##################################################
|
||||
######################################################################
|
||||
# Initialize module
|
||||
##################################################
|
||||
######################################################################
|
||||
|
||||
sub HMCCUCHN_Initialize ($)
|
||||
{
|
||||
@ -90,9 +92,9 @@ sub HMCCUCHN_Initialize ($)
|
||||
"substexcl stripnumber peer:textField-long ". $readingFnAttributes;
|
||||
}
|
||||
|
||||
##################################################
|
||||
######################################################################
|
||||
# Define device
|
||||
##################################################
|
||||
######################################################################
|
||||
|
||||
sub HMCCUCHN_Define ($@)
|
||||
{
|
||||
@ -108,50 +110,101 @@ sub HMCCUCHN_Define ($@)
|
||||
|
||||
my $hmccu_hash = undef;
|
||||
|
||||
# IO device can be set by command line parameter iodev
|
||||
if (exists ($h->{iodev})) {
|
||||
$hmccu_hash = $defs{$h->{iodev}} if (exists ($defs{$h->{iodev}}));
|
||||
}
|
||||
$hmccu_hash = HMCCU_FindIODevice ($devspec) if (!defined ($hmccu_hash));
|
||||
return "Cannot detect IO device" if (!defined ($hmccu_hash));
|
||||
|
||||
return "Invalid or unknown CCU channel name or address"
|
||||
if (! HMCCU_IsValidChannel ($hmccu_hash, $devspec, 7));
|
||||
|
||||
my ($di, $da, $dn, $dt, $dc) = HMCCU_GetCCUDeviceParam ($hmccu_hash, $devspec);
|
||||
return "Invalid or unknown CCU device name or address" if (!defined ($da));
|
||||
|
||||
$hash->{ccuif} = $di;
|
||||
$hash->{ccuaddr} = $da;
|
||||
$hash->{ccuname} = $dn;
|
||||
$hash->{ccutype} = $dt;
|
||||
# Store some definitions for delayed initialization
|
||||
$hash->{hmccu}{devspec} = $devspec;
|
||||
|
||||
# Defaults
|
||||
$hash->{channels} = 1;
|
||||
$hash->{statevals} = 'devstate';
|
||||
|
||||
|
||||
# Parse optional command line parameters
|
||||
my $n = 0;
|
||||
my $arg = shift @$a;
|
||||
while (defined ($arg)) {
|
||||
return $usage if ($n == 3);
|
||||
if ($arg eq 'readonly') { $hash->{statevals} = $arg; }
|
||||
elsif ($arg eq 'defaults') { HMCCU_SetDefaults ($hash); }
|
||||
elsif ($arg eq 'defaults' && !$init_done) { HMCCU_SetDefaults ($hash); }
|
||||
else { return $usage; }
|
||||
$n++;
|
||||
$arg = shift @$a;
|
||||
}
|
||||
|
||||
# Inform HMCCU device about client device
|
||||
AssignIoPort ($hash, $hmccu_hash->{NAME});
|
||||
|
||||
readingsSingleUpdate ($hash, "state", "Initialized", 1);
|
||||
$hash->{ccudevstate} = 'active';
|
||||
|
||||
# IO device can be set by command line parameter iodev, otherwise try to detect IO device
|
||||
if (exists ($h->{iodev})) {
|
||||
return "Specified IO Device ".$h->{iodev}." does not exist" if (!exists ($defs{$h->{iodev}}));
|
||||
return "Specified IO Device ".$h->{iodev}." is not a HMCCU device"
|
||||
if ($defs{$h->{iodev}}->{TYPE} ne 'HMCCU');
|
||||
$hmccu_hash = $defs{$h->{iodev}};
|
||||
}
|
||||
else {
|
||||
# The following call will fail during FHEM start if CCU is not ready
|
||||
$hmccu_hash = HMCCU_FindIODevice ($devspec);
|
||||
}
|
||||
|
||||
if ($init_done) {
|
||||
# Interactive define command while CCU not ready or no IO device defined
|
||||
if (!defined ($hmccu_hash)) {
|
||||
my ($ccuactive, $ccuinactive) = HMCCU_IODeviceStates ();
|
||||
if ($ccuinactive > 0) {
|
||||
return "CCU and/or IO device not ready. Please try again later";
|
||||
}
|
||||
else {
|
||||
return "Cannot detect IO device";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
# CCU not ready during FHEM start
|
||||
if (!defined ($hmccu_hash) || $hmccu_hash->{ccustate} ne 'active') {
|
||||
Log3 $name, 2, "HMCCUCHN: [$devname] Cannot detect IO device, maybe CCU not ready. Trying later ...";
|
||||
readingsSingleUpdate ($hash, "state", "Pending", 1);
|
||||
$hash->{ccudevstate} = 'pending';
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
# Initialize FHEM device, set IO device
|
||||
my $rc = HMCCUCHN_InitDevice ($hmccu_hash, $hash);
|
||||
return "Invalid or unknown CCU channel name or address" if ($rc == 1);
|
||||
return "Can't assign I/O device ".$hmccu_hash->{NAME} if ($rc == 2);
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
#####################################
|
||||
######################################################################
|
||||
# Initialization of FHEM device.
|
||||
# Called during Define() or by HMCCU after CCU ready.
|
||||
# Return 0 on successful initialization or >0 on error:
|
||||
# 1 = Invalid channel name or address
|
||||
# 2 = Cannot assign IO device
|
||||
######################################################################
|
||||
|
||||
sub HMCCUCHN_InitDevice ($$) {
|
||||
my ($hmccu_hash, $dev_hash) = @_;
|
||||
my $devspec = $dev_hash->{hmccu}{devspec};
|
||||
|
||||
return 1 if (!HMCCU_IsValidChannel ($hmccu_hash, $devspec, 7));
|
||||
|
||||
my ($di, $da, $dn, $dt, $dc) = HMCCU_GetCCUDeviceParam ($hmccu_hash, $devspec);
|
||||
return 1 if (!defined ($da));
|
||||
|
||||
# Inform HMCCU device about client device
|
||||
return 2 if (!HMCCU_AssignIODevice ($dev_hash, $hmccu_hash->{NAME}, undef));
|
||||
|
||||
$dev_hash->{ccuif} = $di;
|
||||
$dev_hash->{ccuaddr} = $da;
|
||||
$dev_hash->{ccuname} = $dn;
|
||||
$dev_hash->{ccutype} = $dt;
|
||||
|
||||
readingsSingleUpdate ($dev_hash, "state", "Initialized", 1);
|
||||
$dev_hash->{ccudevstate} = 'active';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Set attribute
|
||||
#####################################
|
||||
######################################################################
|
||||
|
||||
sub HMCCUCHN_Attr ($@)
|
||||
{
|
||||
@ -195,6 +248,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 ($hash->{statevals} eq 'readonly' && $opt ne '?' &&
|
||||
$opt !~ /^(clear|config|defaults)$/);
|
||||
@ -211,7 +266,7 @@ sub HMCCUCHN_Set ($@)
|
||||
my $ccutype = $hash->{ccutype};
|
||||
my $ccuaddr = $hash->{ccuaddr};
|
||||
my $ccuif = $hash->{ccuif};
|
||||
my $statevals = AttrVal ($name, "statevals", '');
|
||||
my $statevals = AttrVal ($name, 'statevals', '');
|
||||
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', 'STATE', '', '');
|
||||
|
||||
my $result = '';
|
||||
@ -919,12 +974,12 @@ sub HMCCUCHN_Get ($@)
|
||||
set my_switch on
|
||||
</code>
|
||||
</li><br/>
|
||||
<li><b>stripnumber [<datapoint-expr>!]{<u>0</u>|1|2|-n|%fmt}[;...]</b><br/>
|
||||
<li><b>stripnumber [<datapoint-expr>!]{0|1|2|-n|%fmt}[;...]</b><br/>
|
||||
Remove trailing digits or zeroes from floating point numbers, round or format
|
||||
numbers. If attribute is negative (-0 is valid) floating point values are rounded
|
||||
to the specified number of digits before they are stored in readings. The meaning of
|
||||
values 0,1,2 is:<br/>
|
||||
0 = Floating point numbers are stored as read from CCU (i.e. with trailing zeros)<br/>
|
||||
0 = Floating point numbers are stored as integer.<br/>
|
||||
1 = Trailing zeros are stripped from floating point numbers except one digit.<br/>
|
||||
2 = All trailing zeros are stripped from floating point numbers.<br/>
|
||||
With %fmt one can specify any valid sprintf() format string.<br/>
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.2.003
|
||||
# Version 4.3
|
||||
#
|
||||
# (c) 2018 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
@ -65,7 +65,9 @@ use SetExtensions;
|
||||
|
||||
# use Time::HiRes qw( gettimeofday usleep );
|
||||
|
||||
sub HMCCUDEV_Initialize ($);
|
||||
sub HMCCUDEV_Define ($@);
|
||||
sub HMCCUDEV_InitDevice ($$);
|
||||
sub HMCCUDEV_Set ($@);
|
||||
sub HMCCUDEV_Get ($@);
|
||||
sub HMCCUDEV_Attr ($@);
|
||||
@ -110,20 +112,39 @@ sub HMCCUDEV_Define ($@)
|
||||
my $devname = shift @$a;
|
||||
my $devtype = shift @$a;
|
||||
my $devspec = shift @$a;
|
||||
my $gdcount = 0;
|
||||
|
||||
my $hmccu_hash = undef;
|
||||
|
||||
# IO device can be set by command line parameter iodev
|
||||
if (exists ($h->{iodev})) {
|
||||
$hmccu_hash = $defs{$h->{iodev}} if (exists ($defs{$h->{iodev}}));
|
||||
}
|
||||
# Store some definitions for delayed initialization
|
||||
$hash->{hmccu}{devspec} = $devspec;
|
||||
$hash->{hmccu}{groupexp} = $h->{groupexp} if (exists ($h->{groupexp}));
|
||||
$hash->{hmccu}{group} = $h->{group} if (exists ($h->{group}));
|
||||
|
||||
# Defaults
|
||||
$hash->{statevals} = 'devstate';
|
||||
|
||||
# Parse optional command line parameters
|
||||
foreach my $arg (@$a) {
|
||||
if ($arg eq 'readonly') { $hash->{statevals} = $arg; }
|
||||
elsif ($arg eq 'defaults' && !$init_done) { HMCCU_SetDefaults ($hash); }
|
||||
elsif ($arg =~ /^[0-9]+$/) { $attr{$name}{statechannel} = $arg; }
|
||||
else { return $usage; }
|
||||
}
|
||||
|
||||
# IO device can be set by command line parameter iodev, otherwise try to detect IO device
|
||||
if (exists ($h->{iodev})) {
|
||||
return "Specified IO Device ".$h->{iodev}." does not exist" if (!exists ($defs{$h->{iodev}}));
|
||||
return "Specified IO Device ".$h->{iodev}." is not a HMCCU device"
|
||||
if ($defs{$h->{iodev}}->{TYPE} ne 'HMCCU');
|
||||
$hmccu_hash = $defs{$h->{iodev}};
|
||||
}
|
||||
else {
|
||||
# The following call will fail during FHEM start if CCU is not ready
|
||||
$hmccu_hash = $devspec eq 'virtual' ? HMCCU_GetHash (0) : HMCCU_FindIODevice ($devspec);
|
||||
}
|
||||
|
||||
if ($devspec eq 'virtual') {
|
||||
# Virtual device FHEM only
|
||||
$hmccu_hash = HMCCU_GetHash (0);
|
||||
return "Cannot detect IO device" if (!defined ($hmccu_hash));
|
||||
|
||||
my $no = 0;
|
||||
foreach my $d (sort keys %defs) {
|
||||
my $ch = $defs{$d};
|
||||
@ -137,43 +158,77 @@ sub HMCCUDEV_Define ($@)
|
||||
$hash->{ccuname} = "none";
|
||||
$hash->{statevals} = 'readonly';
|
||||
}
|
||||
|
||||
if ($init_done) {
|
||||
# Interactive define command while CCU not ready
|
||||
if (!defined ($hmccu_hash)) {
|
||||
my ($ccuactive, $ccuinactive) = HMCCU_IODeviceStates ();
|
||||
if ($ccuinactive > 0) {
|
||||
return "CCU and/or IO device not ready. Please try again later";
|
||||
}
|
||||
else {
|
||||
return "Cannot detect IO device";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$hmccu_hash = HMCCU_FindIODevice ($devspec) if (!defined ($hmccu_hash));
|
||||
return "Cannot detect IO device" if (!defined ($hmccu_hash));
|
||||
|
||||
return "Invalid or unknown CCU device name or address: $devspec"
|
||||
if (! HMCCU_IsValidDevice ($hmccu_hash, $devspec, 7));
|
||||
|
||||
my ($di, $da, $dn, $dt, $dc) = HMCCU_GetCCUDeviceParam ($hmccu_hash, $devspec);
|
||||
return "Invalid or unknown CCU device name or address: $devspec" if (!defined ($da));
|
||||
|
||||
$hash->{ccuif} = $di;
|
||||
$hash->{ccuaddr} = $da;
|
||||
$hash->{ccuname} = $dn;
|
||||
$hash->{ccutype} = $dt;
|
||||
$hash->{channels} = $dc;
|
||||
$hash->{statevals} = 'devstate';
|
||||
# CCU not ready during FHEM start
|
||||
if (!defined ($hmccu_hash) || $hmccu_hash->{ccustate} ne 'active') {
|
||||
Log3 $name, 2, "HMCCUDEV: [$devname] Cannot detect IO device, maybe CCU not ready. Trying later ...";
|
||||
readingsSingleUpdate ($hash, "state", "Pending", 1);
|
||||
$hash->{ccudevstate} = 'pending';
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
# Parse optional command line parameters
|
||||
foreach my $arg (@$a) {
|
||||
if ($arg eq 'readonly') { $hash->{statevals} = $arg; }
|
||||
elsif ($arg eq 'defaults') { HMCCU_SetDefaults ($hash); }
|
||||
elsif ($arg =~ /^[0-9]+$/) { $attr{$name}{statechannel} = $arg; }
|
||||
else { return $usage; }
|
||||
}
|
||||
# Initialize FHEM device, set IO device
|
||||
my $rc = HMCCUDEV_InitDevice ($hmccu_hash, $hash);
|
||||
return "Invalid or unknown CCU device name or address" if ($rc == 1);
|
||||
return "Can't assign I/O device ".$hmccu_hash->{NAME} if ($rc == 2);
|
||||
return "No devices in group" if ($rc == 3);
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Initialization of FHEM device.
|
||||
# Called during Define() or by HMCCU after CCU ready.
|
||||
# Return 0 on successful initialization or >0 on error:
|
||||
# 1 = Invalid channel name or address
|
||||
# 2 = Cannot assign IO device
|
||||
# 3 = No devices in group
|
||||
######################################################################
|
||||
|
||||
sub HMCCUDEV_InitDevice ($$)
|
||||
{
|
||||
my ($hmccu_hash, $dev_hash) = @_;
|
||||
my $devspec = $dev_hash->{hmccu}{devspec};
|
||||
my $gdcount = 0;
|
||||
my $gdname = $devspec;
|
||||
|
||||
return 1 if (! HMCCU_IsValidDevice ($hmccu_hash, $devspec, 7));
|
||||
|
||||
my ($di, $da, $dn, $dt, $dc) = HMCCU_GetCCUDeviceParam ($hmccu_hash, $devspec);
|
||||
return 1 if (!defined ($da));
|
||||
$gdname = $dn;
|
||||
|
||||
$dev_hash->{ccuif} = $di;
|
||||
$dev_hash->{ccuaddr} = $da;
|
||||
$dev_hash->{ccuname} = $dn;
|
||||
$dev_hash->{ccutype} = $dt;
|
||||
$dev_hash->{channels} = $dc;
|
||||
|
||||
# Parse group options
|
||||
if ($hash->{ccuif} eq "VirtualDevices") {
|
||||
if (exists ($h->{groupexp}) && $hash->{ccuif} eq "VirtualDevices") {
|
||||
if ($dev_hash->{ccuif} eq "VirtualDevices") {
|
||||
if (exists ($dev_hash->{hmccu}{groupexp})) {
|
||||
my @devlist;
|
||||
$gdcount = HMCCU_GetMatchingDevices ($hmccu_hash, $h->{groupexp}, 'dev', \@devlist);
|
||||
$gdcount = HMCCU_GetMatchingDevices ($hmccu_hash, $dev_hash->{hmccu}{groupexp}, 'dev', \@devlist);
|
||||
return "No matching CCU devices found" if ($gdcount == 0);
|
||||
$hash->{ccugroup} = join (',', @devlist);
|
||||
$dev_hash->{ccugroup} = join (',', @devlist);
|
||||
}
|
||||
elsif (exists ($h->{group}) && $hash->{ccuif} eq "VirtualDevices") {
|
||||
my @gdevlist = split (",", $h->{group});
|
||||
$hash->{ccugroup} = '' if (@gdevlist > 0);
|
||||
elsif (exists ($dev_hash->{hmccu}{group})) {
|
||||
my @gdevlist = split (",", $dev_hash->{hmccu}{group});
|
||||
$dev_hash->{ccugroup} = '' if (@gdevlist > 0);
|
||||
foreach my $gd (@gdevlist) {
|
||||
my ($gda, $gdc, $gdo) = ('', '', '', '');
|
||||
|
||||
@ -183,26 +238,32 @@ sub HMCCUDEV_Define ($@)
|
||||
$gdo = $gda;
|
||||
$gdo .= ':'.$gdc if ($gdc ne '');
|
||||
|
||||
if (exists ($hash->{ccugroup}) && $hash->{ccugroup} ne '') {
|
||||
$hash->{ccugroup} .= ",".$gdo;
|
||||
if (exists ($dev_hash->{ccugroup}) && $dev_hash->{ccugroup} ne '') {
|
||||
$dev_hash->{ccugroup} .= ",".$gdo;
|
||||
}
|
||||
else {
|
||||
$hash->{ccugroup} = $gdo;
|
||||
$dev_hash->{ccugroup} = $gdo;
|
||||
}
|
||||
|
||||
$gdcount++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
my @devlist = HMCCU_GetGroupMembers ($hmccu_hash, $gdname);
|
||||
$gdcount = scalar (@devlist);
|
||||
$dev_hash->{ccugroup} = join (',', @devlist);
|
||||
}
|
||||
|
||||
return "No devices in group" if ($hash->{ccuif} eq "VirtualDevices" && $gdcount == 0);
|
||||
return 3 if ($gdcount == 0);
|
||||
}
|
||||
|
||||
# Inform HMCCU device about client device
|
||||
return 2 if (!HMCCU_AssignIODevice ($dev_hash, $hmccu_hash->{NAME}, undef));
|
||||
|
||||
AssignIoPort ($hash, $hmccu_hash->{NAME});
|
||||
|
||||
readingsSingleUpdate ($hash, "state", "Initialized", 1);
|
||||
$hash->{ccudevstate} = 'active';
|
||||
|
||||
return undef;
|
||||
readingsSingleUpdate ($dev_hash, "state", "Initialized", 1);
|
||||
$dev_hash->{ccudevstate} = 'active';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#####################################
|
||||
@ -252,9 +313,10 @@ sub HMCCUDEV_Set ($@)
|
||||
# Valid commands for read only devices
|
||||
my $rocmds = "clear config defaults:noArg";
|
||||
|
||||
# Get I/O device
|
||||
my $hmccu_hash = HMCCU_GetHash ($hash);
|
||||
return HMCCU_SetError ($hash, -3) if (!defined ($hmccu_hash));
|
||||
# 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}));
|
||||
my $hmccu_hash = $hash->{IODev};
|
||||
my $hmccu_name = $hmccu_hash->{NAME};
|
||||
|
||||
# Handle read only and disabled devices
|
||||
@ -274,7 +336,7 @@ sub HMCCUDEV_Set ($@)
|
||||
my $ccuaddr = $hash->{ccuaddr};
|
||||
my $ccuif = $hash->{ccuif};
|
||||
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
|
||||
my $statevals = AttrVal ($name, "statevals", '');
|
||||
my $statevals = AttrVal ($name, 'statevals', '');
|
||||
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', 'STATE', '', '');
|
||||
|
||||
my $result = '';
|
||||
@ -545,8 +607,8 @@ sub HMCCUDEV_Get ($@)
|
||||
my $opt = shift @$a;
|
||||
|
||||
# Get I/O device
|
||||
my $hmccu_hash = HMCCU_GetHash ($hash);
|
||||
return HMCCU_SetError ($hash, -3) if (!defined ($hmccu_hash));
|
||||
return HMCCU_SetError ($hash, -3) if (!defined ($hash->{IODev}));
|
||||
my $hmccu_hash = $hash->{IODev};
|
||||
my $hmccu_name = $hmccu_hash->{NAME};
|
||||
|
||||
# Handle disabled devices
|
||||
@ -740,12 +802,14 @@ sub HMCCUDEV_Get ($@)
|
||||
<br/><br/>
|
||||
If option 'readonly' is specified no set command will be available. With option 'defaults'
|
||||
some default attributes depending on CCU device type will be set. Default attributes are only
|
||||
available for some device types. Parameter <i>statechannel</i> corresponds to attribute
|
||||
'statechannel'.<br/>
|
||||
available for some device types. The option is ignored during FHEM start.
|
||||
Parameter <i>statechannel</i> corresponds to attribute 'statechannel'.<br/>
|
||||
A HMCCUDEV device supports CCU group devices. The CCU devices or channels related to a group
|
||||
device are specified by using options 'group' or 'groupexp' followed by the names or
|
||||
addresses of the CCU devices or channels. By using 'groupexp' one can specify a regular
|
||||
expression for CCU device or channel names.<br/>
|
||||
expression for CCU device or channel names. Since version 4.2.009 of HMCCU HMCCUDEV
|
||||
is able to detect members of group devices automatically. So options 'group' or
|
||||
'groupexp' are no longer necessary to define a group device.<br/>
|
||||
It's also possible to group any kind of CCU devices or channels without defining a real
|
||||
group in CCU by using option 'virtual' instead of a CCU device specification.
|
||||
<br/><br/>
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 1.0.006
|
||||
# Version 1.1
|
||||
#
|
||||
# Subprocess based RPC Server module for HMCCU.
|
||||
#
|
||||
@ -35,7 +35,7 @@ use SetExtensions;
|
||||
######################################################################
|
||||
|
||||
# HMCCURPC version
|
||||
my $HMCCURPCPROC_VERSION = '1.0.006';
|
||||
my $HMCCURPCPROC_VERSION = '1.0.007';
|
||||
|
||||
# Maximum number of events processed per call of Read()
|
||||
my $HMCCURPCPROC_MAX_EVENTS = 100;
|
||||
@ -105,6 +105,7 @@ my $BINRPC_ERROR = 0x42696EFF;
|
||||
# Standard functions
|
||||
sub HMCCURPCPROC_Initialize ($);
|
||||
sub HMCCURPCPROC_Define ($$);
|
||||
sub HMCCURPCPROC_InitDevice ($$);
|
||||
sub HMCCURPCPROC_Undef ($$);
|
||||
sub HMCCURPCPROC_Shutdown ($);
|
||||
sub HMCCURPCPROC_Attr ($@);
|
||||
@ -115,7 +116,7 @@ sub HMCCURPCPROC_SetError ($$$);
|
||||
sub HMCCURPCPROC_SetState ($$);
|
||||
sub HMCCURPCPROC_ProcessEvent ($$);
|
||||
|
||||
# RPC server functions
|
||||
# RPC server control functions
|
||||
sub HMCCURPCPROC_GetRPCServerID ($$);
|
||||
sub HMCCURPCPROC_RegisterCallback ($$);
|
||||
sub HMCCURPCPROC_DeRegisterCallback ($$);
|
||||
@ -217,8 +218,10 @@ sub HMCCURPCPROC_Define ($$)
|
||||
my $ioname = '';
|
||||
my $rpcip = '';
|
||||
my $iface;
|
||||
my $usage = "Usage: define $name HMCCURPCPROC { CCUHost } { RPCPort | RPCInterface } [iodev={device}]";
|
||||
my $usage = "Usage: define $name HMCCURPCPROC { CCUHost | iodev={device} } { RPCPort | RPCInterface }";
|
||||
|
||||
$hash->{version} = $HMCCURPCPROC_VERSION;
|
||||
|
||||
if (exists ($h->{iodev})) {
|
||||
$ioname = $h->{iodev};
|
||||
return $usage if (scalar (@$a) < 3);
|
||||
@ -246,6 +249,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) {
|
||||
@ -253,61 +258,108 @@ sub HMCCURPCPROC_Define ($$)
|
||||
last;
|
||||
}
|
||||
}
|
||||
return "Can't find HMCCU I/O device" if (!defined ($hmccu_hash));
|
||||
$ioname = $hmccu_hash->{NAME};
|
||||
}
|
||||
|
||||
|
||||
# Store some definitions for delayed initialization
|
||||
$hash->{hmccu}{devspec} = $iface;
|
||||
$hash->{rpcip} = $rpcip;
|
||||
|
||||
if ($init_done) {
|
||||
# Interactive define command while CCU not ready or no IO device defined
|
||||
if (!defined ($hmccu_hash)) {
|
||||
my ($ccuactive, $ccuinactive) = HMCCU_IODeviceStates ();
|
||||
if ($ccuinactive > 0) {
|
||||
return "CCU and/or IO device not ready. Please try again later";
|
||||
}
|
||||
else {
|
||||
return "Cannot detect IO device";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
# CCU not ready during FHEM start
|
||||
if (!defined ($hmccu_hash) || $hmccu_hash->{ccustate} ne 'active') {
|
||||
Log3 $name, 2, "HMCCURPCPROC: [$name] Cannot detect IO device, maybe CCU not ready. Trying later ...";
|
||||
readingsSingleUpdate ($hash, "state", "Pending", 1);
|
||||
$hash->{ccudevstate} = 'pending';
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
# Initialize FHEM device, set IO device
|
||||
my $rc = HMCCURPCPROC_InitDevice ($hmccu_hash, $hash);
|
||||
return "Invalid port or interface $iface" if ($rc == 1);
|
||||
return "Can't assign I/O device $ioname" if ($rc == 2);
|
||||
return "Invalid local IP address ".$hash->{hmccu}{localaddr} if ($rc == 3);
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Initialization of FHEM device.
|
||||
# Called during Define() or by HMCCU after CCU ready.
|
||||
# Return 0 on successful initialization or >0 on error:
|
||||
# 1 = Invalid port or interface
|
||||
# 2 = Cannot assign IO device
|
||||
# 3 = Invalid local IP address
|
||||
######################################################################
|
||||
|
||||
sub HMCCURPCPROC_InitDevice ($$) {
|
||||
my ($hmccu_hash, $dev_hash) = @_;
|
||||
my $name = $dev_hash->{NAME};
|
||||
my $iface = $dev_hash->{hmccu}{devspec};
|
||||
|
||||
# Check if interface is valid
|
||||
my $ifname = HMCCU_GetRPCServerInfo ($hmccu_hash, $iface, 'name');
|
||||
my $ifport = HMCCU_GetRPCServerInfo ($hmccu_hash, $iface, 'port');
|
||||
return "Invalid port or interface $iface" if (!defined ($ifname) || !defined ($ifport));
|
||||
return 1 if (!defined ($ifname) || !defined ($ifport));
|
||||
|
||||
# Check if RPC device with same interface already exists
|
||||
for my $d (keys %defs) {
|
||||
my $dh = $defs{$d};
|
||||
next if (!exists ($dh->{TYPE}) || !exists ($dh->{NAME}));
|
||||
if ($dh->{TYPE} eq 'HMCCURPCPROC' && $dh->{NAME} ne $name) {
|
||||
if ($dh->{TYPE} eq 'HMCCURPCPROC' && $dh->{NAME} ne $name && IsDisabled ($dh->{NAME}) != 1) {
|
||||
return "RPC device for CCU/port already exists"
|
||||
if ($hash->{host} eq $dh->{host} && $dh->{rpcport} == $ifport);
|
||||
if ($dev_hash->{host} eq $dh->{host} && exists ($dh->{rpcport}) && $dh->{rpcport} == $ifport);
|
||||
}
|
||||
}
|
||||
|
||||
# Detect local IP address and check if CCU is reachable
|
||||
my $localaddr = HMCCU_TCPConnect ($hash->{host}, $ifport);
|
||||
return "Can't connect to CCU ".$hash->{host}." port $ifport" if ($localaddr eq '');
|
||||
$hash->{hmccu}{localaddr} = $localaddr;
|
||||
$hash->{hmccu}{defaultaddr} = $hash->{hmccu}{localaddr};
|
||||
my $localaddr = HMCCU_TCPConnect ($dev_hash->{host}, $ifport);
|
||||
return "Can't connect to CCU ".$dev_hash->{host}." port $ifport" if ($localaddr eq '');
|
||||
$dev_hash->{hmccu}{localaddr} = $localaddr;
|
||||
$dev_hash->{hmccu}{defaultaddr} = $dev_hash->{hmccu}{localaddr};
|
||||
|
||||
# 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 (/\./, $hash->{hmccu}{localaddr});
|
||||
return "Invalid local IP address ".$hash->{hmccu}{localaddr} if (scalar (@ipseg) != 4);
|
||||
$hash->{rpcid} = sprintf ("%03d%03d", $ipseg[2], $ipseg[3]);
|
||||
my @ipseg = split (/\./, $dev_hash->{hmccu}{localaddr});
|
||||
return 3 if (scalar (@ipseg) != 4);
|
||||
$dev_hash->{rpcid} = sprintf ("%03d%03d", $ipseg[2], $ipseg[3]);
|
||||
|
||||
# Set I/O device and store reference for RPC device in I/O device
|
||||
AssignIoPort ($hash, $hmccu_hash->{NAME});
|
||||
$hmccu_hash->{hmccu}{interfaces}{$ifname}{device} = $name;
|
||||
my $ioname = $hmccu_hash->{NAME};
|
||||
return 2 if (!HMCCU_AssignIODevice ($dev_hash, $ioname, $ifname));
|
||||
|
||||
# Store internals
|
||||
$hash->{rpcip} = $rpcip;
|
||||
$hash->{rpcport} = $ifport;
|
||||
$hash->{rpcinterface} = $ifname;
|
||||
$hash->{ccuip} = $hmccu_hash->{ccuip};
|
||||
$hash->{ccutype} = $hmccu_hash->{ccutype};
|
||||
$hash->{CCUNum} = $hmccu_hash->{CCUNum};
|
||||
$hash->{ccustate} = $hmccu_hash->{ccustate};
|
||||
$hash->{version} = $HMCCURPCPROC_VERSION;
|
||||
$dev_hash->{rpcport} = $ifport;
|
||||
$dev_hash->{rpcinterface} = $ifname;
|
||||
$dev_hash->{ccuip} = $hmccu_hash->{ccuip};
|
||||
$dev_hash->{ccutype} = $hmccu_hash->{ccutype};
|
||||
$dev_hash->{CCUNum} = $hmccu_hash->{CCUNum};
|
||||
$dev_hash->{ccustate} = $hmccu_hash->{ccustate};
|
||||
|
||||
Log3 $name, 1, "HMCCURPCPROC: [$name] Initialized version $HMCCURPCPROC_VERSION for interface $ifname with I/O device $ioname";
|
||||
|
||||
# Set some attributes
|
||||
$attr{$name}{stateFormat} = "rpcstate/state";
|
||||
$attr{$name}{verbose} = 2;
|
||||
if ($init_done) {
|
||||
$attr{$name}{stateFormat} = "rpcstate/state";
|
||||
$attr{$name}{verbose} = 2;
|
||||
}
|
||||
|
||||
HMCCURPCPROC_ResetRPCState ($hash);
|
||||
HMCCURPCPROC_SetState ($hash, 'Initialized');
|
||||
HMCCURPCPROC_ResetRPCState ($dev_hash);
|
||||
HMCCURPCPROC_SetState ($dev_hash, 'Initialized');
|
||||
|
||||
return undef;
|
||||
return 0;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
@ -386,7 +438,7 @@ sub HMCCURPCPROC_Set ($@)
|
||||
my $opt = shift @$a;
|
||||
|
||||
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
|
||||
my $options = $ccuflags =~ /expert/ ? "cleanup:noArg deregister:noArg rpcrequest rpcserver:on,off" : "";
|
||||
my $options = $ccuflags =~ /expert/ ? "cleanup:noArg deregister:noArg register:noArg rpcrequest rpcserver:on,off" : "";
|
||||
my $busyoptions = $ccuflags =~ /expert/ ? "rpcserver:off" : "";
|
||||
|
||||
return "HMCCURPCPROC: CCU busy, choose one of $busyoptions"
|
||||
@ -396,6 +448,21 @@ sub HMCCURPCPROC_Set ($@)
|
||||
HMCCURPCPROC_Housekeeping ($hash);
|
||||
return undef;
|
||||
}
|
||||
elsif ($opt eq 'register') {
|
||||
if ($hash->{RPCState} eq 'running') {
|
||||
my ($rc, $rcmsg) = HMCCURPCPROC_RegisterCallback ($hash, 2);
|
||||
if ($rc) {
|
||||
$hash->{ccustate} = 'active';
|
||||
return HMCCURPCPROC_SetState ($hash, "OK");
|
||||
}
|
||||
else {
|
||||
return HMCCURPCPROC_SetError ($hash, $rcmsg, 2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return HMCCURPCPROC_SetError ($hash, "RPC server not running", 2);
|
||||
}
|
||||
}
|
||||
elsif ($opt eq 'deregister') {
|
||||
my ($rc, $err) = HMCCURPCPROC_DeRegisterCallback ($hash, 1);
|
||||
return HMCCURPCPROC_SetError ($hash, $err, 2) if (!$rc);
|
||||
@ -759,7 +826,7 @@ sub HMCCURPCPROC_ProcessEvent ($$)
|
||||
$rh->{sumdelay} += $delay;
|
||||
$rh->{avgdelay} = $rh->{sumdelay}/$rh->{rec}{$et};
|
||||
$hash->{ccustate} = 'active' if ($hash->{ccustate} ne 'active');
|
||||
Log3 $name, 2, "HMCCURPCPROC: [$name] Received CENTRAL event. ".$t[2]."=".$t[3] if ($t[1] eq 'CENTRAL');
|
||||
Log3 $name, 3, "HMCCURPCPROC: [$name] Received CENTRAL event. ".$t[2]."=".$t[3] if ($t[1] eq 'CENTRAL');
|
||||
my ($add, $chn) = split (/:/, $t[1]);
|
||||
return defined ($chn) ? ($et, $clkey, $add, $chn, $t[2], $t[3]) : undef;
|
||||
}
|
||||
@ -1079,7 +1146,7 @@ sub HMCCURPCPROC_InitRPCServer ($$$$)
|
||||
Log3 $name, 4, "HMCCURPCPROC: [$name] Adding callback for modified devices for server $clkey";
|
||||
$server->add_method (
|
||||
{ name=>"updateDevice",
|
||||
signature=>["string string string int"],
|
||||
signature=>["string string string int", "string string string i4"],
|
||||
code=>\&HMCCURPCPROC_UpdateDeviceCB
|
||||
}
|
||||
);
|
||||
@ -1096,7 +1163,7 @@ sub HMCCURPCPROC_InitRPCServer ($$$$)
|
||||
# Callback for readded devices
|
||||
Log3 $name, 4, "HMCCURPCPROC: [$name] Adding callback for readded devices for server $clkey";
|
||||
$server->add_method (
|
||||
{ name=>"replaceDevice",
|
||||
{ name=>"readdedDevice",
|
||||
signature=>["string string array"],
|
||||
code=>\&HMCCURPCPROC_ReaddDeviceCB
|
||||
}
|
||||
@ -2563,7 +2630,8 @@ sub HMCCURPCPROC_DecodeResponse ($)
|
||||
<code>define myccurpc HMCCURPCPROC iodev=myccudev BidCos-RF</code><br/>
|
||||
<br/><br/>
|
||||
The parameter <i>HostOrIP</i> is the hostname or IP address of a Homematic CCU2.
|
||||
The I/O device can also be specified with parameter iodev. Supported interfaces or
|
||||
The I/O device can also be specified with parameter iodev. If more than one CCU exist
|
||||
it's highly recommended to specify IO device with option iodev. Supported interfaces or
|
||||
ports are:
|
||||
<table>
|
||||
<tr><td><b>Port</b></td><td><b>Interface</b></td></tr>
|
||||
@ -2580,7 +2648,14 @@ sub HMCCURPCPROC_DecodeResponse ($)
|
||||
<a name="HMCCURPCPROCset"></a>
|
||||
<b>Set</b><br/><br/>
|
||||
<ul>
|
||||
<li><b> set <name> rpcrequest <method> [<parameters>]</b><br/>
|
||||
<li><b>set <name> deregister</b><br/>
|
||||
Deregister RPC server at CCU.
|
||||
</li><br/>
|
||||
<li><b>set <name> register</b><br/>
|
||||
Register RPC server at CCU. RPC server must be running. Helpful when CCU lost
|
||||
connection to FHEM and events timed out.
|
||||
</li><br/>
|
||||
<li><b>set <name> rpcrequest <method> [<parameters>]</b><br/>
|
||||
Send RPC request to CCU. The result is displayed in FHEM browser window. See EQ-3
|
||||
RPC XML documentation for mor information about valid methods and requests.
|
||||
</li><br/>
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.2.003
|
||||
# Version 4.2.005
|
||||
#
|
||||
# Configuration parameters for HomeMatic devices.
|
||||
#
|
||||
@ -334,6 +334,13 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
statedatapoint => "LUX",
|
||||
stripnumber => 1
|
||||
},
|
||||
"HmIP-SLO" => {
|
||||
_description => "Lichtsensor",
|
||||
_channels => "1",
|
||||
ccureadingfilter => "_ILLUMINATION\$",
|
||||
statedatapoint => "CURRENT_ILLUMINATION",
|
||||
stripnumber => 1
|
||||
},
|
||||
"HM-CC-SCD" => {
|
||||
_description => "CO2 Sensor",
|
||||
_channels => "1",
|
||||
@ -648,7 +655,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
},
|
||||
"HM-CC-RT-DN" => {
|
||||
_description => "Heizkoerperthermostat",
|
||||
ccureadingfilter => "(TEMPERATURE|VALVE_STATE|CONTROL)",
|
||||
ccureadingfilter => "(TEMPERATURE|VALVE_STATE|CONTROL|BATTERY_STATE)",
|
||||
cmdIcon => "Auto:sani_heating_automatic Manu:sani_heating_manual Boost:sani_heating_boost on:general_an off:general_aus",
|
||||
controldatapoint => "4.SET_TEMPERATURE",
|
||||
eventMap => "/datapoint 4.MANU_MODE 20.0:Manu/datapoint 4.AUTO_MODE 1:Auto/datapoint 4.BOOST_MODE 1:Boost/datapoint 4.MANU_MODE 4.5:off/datapoint 4.MANU_MODE 30.5:on/",
|
||||
@ -766,6 +773,12 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
statedatapoint => "1.LUX",
|
||||
stripnumber => 1
|
||||
},
|
||||
"HmIP-SLO" => {
|
||||
_description => "Lichtsensor",
|
||||
ccureadingfilter => "_ILLUMINATION\$",
|
||||
statedatapoint => "1.CURRENT_ILLUMINATION",
|
||||
stripnumber => 1
|
||||
},
|
||||
"HM-CC-SCD" => {
|
||||
_description => "CO2 Sensor",
|
||||
ccureadingfilter => "STATE",
|
||||
@ -1079,24 +1092,37 @@ if (odev) {
|
||||
code => qq(
|
||||
string devid;
|
||||
string chnid;
|
||||
string sifId;
|
||||
string sifid;
|
||||
string prgid;
|
||||
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()) {
|
||||
object ochn=dom.GetObject(chnid);
|
||||
WriteLine("C;" # ochn.Address() # ";" # ochn.Name() # ";" # ochn.ChnDirection());
|
||||
cc=cc+1;
|
||||
if(odev) {
|
||||
var intid=odev.Interface();
|
||||
object oiface=dom.GetObject(intid);
|
||||
if(oiface) {
|
||||
string intna=oiface.Name();
|
||||
integer cc=0;
|
||||
foreach (chnid, odev.Channels()) {
|
||||
object ochn=dom.GetObject(chnid);
|
||||
WriteLine("C;" # ochn.Address() # ";" # ochn.Name() # ";" # ochn.ChnDirection());
|
||||
cc=cc+1;
|
||||
}
|
||||
WriteLine("D;" # intna # ";" # odev.Address() # ";" # odev.Name() # ";" # odev.HssType() # ";" # cc);
|
||||
}
|
||||
}
|
||||
WriteLine("D;" # intna # ";" # odev.Address() # ";" # odev.Name() # ";" # odev.HssType() # ";" # cc);
|
||||
}
|
||||
foreach(sifId, root.Interfaces().EnumIDs()) {
|
||||
object oIf=dom.GetObject(sifId);
|
||||
foreach(sifid, root.Interfaces().EnumIDs()) {
|
||||
object oIf=dom.GetObject(sifid);
|
||||
if (oIf) {
|
||||
WriteLine("I;" # oIf.Name() # ';' # oIf.InterfaceInfo() # ';' # oIf.InterfaceUrl());
|
||||
}
|
||||
}
|
||||
string prgid;
|
||||
foreach(prgid, dom.GetObject(ID_PROGRAMS).EnumIDs()) {
|
||||
object oProg=dom.GetObject(prgid);
|
||||
if(oProg) {
|
||||
WriteLine ("P;" # oProg.Name() # ";" # oProg.Active() # ";" # oProg.Internal());
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
@ -1266,6 +1292,21 @@ foreach(itemID, dom.GetObject(ID_DEVICES).EnumUsedIDs()) {
|
||||
object lObjDevice = xmlrpc.GetObjectByHSSAddress(interfaces.Get("\$iface"),"\$address");
|
||||
if (lObjDevice) {
|
||||
WriteLine (lObjDevice.Name());
|
||||
}
|
||||
)
|
||||
},
|
||||
"GetGroupDevices" => {
|
||||
description => "Get virtual group configuration",
|
||||
syntax => "",
|
||||
parameters => 0,
|
||||
code => qq(
|
||||
string lGetOut = "";
|
||||
string lGetErr = "";
|
||||
string lCommand = "cat /usr/local/etc/config/groups.gson";
|
||||
integer lResult;
|
||||
lResult = system.Exec(lCommand,&lGetOut,&lGetErr);
|
||||
if(lResult == 0) {
|
||||
WriteLine(lGetOut);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user