2
0
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:
zap 2018-09-11 07:54:43 +00:00
parent a3a6316db1
commit e60d131d86
6 changed files with 1107 additions and 460 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.
- 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

View File

@ -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 [&lt;datapoint-expr&gt;!]{<u>0</u>|1|2|-n|%fmt}[;...]</b><br/>
<li><b>stripnumber [&lt;datapoint-expr&gt;!]{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/>

View File

@ -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/>

View File

@ -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 &lt;name&gt; rpcrequest &lt;method&gt; [&lt;parameters&gt;]</b><br/>
<li><b>set &lt;name&gt; deregister</b><br/>
Deregister RPC server at CCU.
</li><br/>
<li><b>set &lt;name&gt; 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 &lt;name&gt; rpcrequest &lt;method&gt; [&lt;parameters&gt;]</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/>

View File

@ -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);
}
)
}