2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-01 07:19:24 +00:00

HMCCU: Fixed delayed initialization function

git-svn-id: https://svn.fhem.de/fhem/trunk@17372 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2018-09-19 11:39:04 +00:00
parent 24614b2078
commit c2f5b9cb25
3 changed files with 369 additions and 91 deletions

View File

@ -4,7 +4,7 @@
#
# $Id$
#
# Version 4.3.001
# Version 4.3.002
#
# Module for communication between FHEM and Homematic CCU2.
#
@ -25,6 +25,7 @@
# set <name> execute <ccu_program>
# set <name> importdefaults <filename>
# set <name> hmscript {<scriptfile>|!<function>|'['<code>']'} [dump] [<parname>=<value> [...]]
# set <name> rpcregister [{all|<interface>}]
# set <name> rpcserver {on|off|restart}
# set <name> var [<type>] <name> <value> [<parameter>=<value> [...]]
#
@ -37,7 +38,7 @@
# [defattr] [duplicates] [save] [<attr>=<val> [...]]}]
# get <name> dump {devtypes|datapoints} [<filter>]
# get <name> dutycycle
# get <name> exportdefaults {filename}
# get <name> exportdefaults {filename} [csv]
# get <name> firmware [{type-expr}|full]
# get <name> parfile [<parfile>]
# get <name> rpcevents
@ -245,6 +246,7 @@ sub HMCCU_AggregationRules ($$);
# Handling of default attributes
sub HMCCU_ExportDefaults ($);
sub HMCCU_ExportDefaultsCSV ($);
sub HMCCU_ImportDefaults ($);
sub HMCCU_FindDefaults ($$);
sub HMCCU_SetDefaults ($);
@ -313,6 +315,7 @@ sub HMCCU_IODeviceStates ();
sub HMCCU_IsFlag ($$);
# Handle interfaces, devices and channels
sub HMCCU_CreateDevice ($$$$$);
sub HMCCU_FormatDeviceInfo ($);
sub HMCCU_GetAddress ($$$$);
sub HMCCU_GetCCUDeviceParam ($$);
@ -489,7 +492,7 @@ sub HMCCU_Define ($$)
if ($hash->{ccustate} eq 'active') {
# If CCU is alive read devices, channels, interfaces and groups
HMCCU_Log ($hash, 1, "HMCCU: Initializing device", 0);
HMCCU_InitDevice ($hash);
$rc = HMCCU_InitDevice ($hash);
}
if ($hash->{ccustate} ne 'active' || $rc > 0) {
@ -855,6 +858,56 @@ sub HMCCU_ExportDefaults ($)
return 1;
}
######################################################################
# Export default attributes as CSV file.
######################################################################
sub HMCCU_ExportDefaultsCSV ($)
{
my ($filename) = @_;
my %attrlist = (
'_type' => '', '_description' => '', '_channels' => '',
'ccureadingfilter' => '', 'ccureadingname' => '', 'ccuscaleval' => '', 'cmdIcon' => '', 'controldatapoint' => '',
'eventMap' => '', 'event-on-change-reading' => '', 'event-on-update-reading' => '',
'genericDeviceType' => '',
'hmstatevals' => '',
'statedatapoint' => '', 'statevals' => '', 'stripnumber' => '', 'substexcl' => '', 'substitute' => '',
'webCmd' => '', 'widgetOverride' => ''
);
return 0 if (!open (DEFFILE, ">$filename"));
# Write header
print DEFFILE "_flag,".join (',', sort keys %attrlist)."\n";
# Write channel configurations
foreach my $t (keys %{$HMCCU_CHN_DEFAULTS}) {
print DEFFILE "C";
$attrlist{'_type'} = $t;
foreach $a (sort keys %attrlist) {
my $v = exists ($HMCCU_CHN_DEFAULTS->{$t}{$a}) ? $HMCCU_CHN_DEFAULTS->{$t}{$a} : $attrlist{$a};
print DEFFILE ",\"$v\"";
}
print DEFFILE "\n";
}
# Write device configurations
foreach my $t (keys %{$HMCCU_DEV_DEFAULTS}) {
print DEFFILE "D";
$attrlist{'_type'} = $t;
foreach $a (sort keys %attrlist) {
my $v = exists ($HMCCU_DEV_DEFAULTS->{$t}{$a}) ? $HMCCU_DEV_DEFAULTS->{$t}{$a} : $attrlist{$a};
print DEFFILE ",\"$v\"";
}
print DEFFILE "\n";
}
close (DEFFILE);
return 1;
}
######################################################################
# Import customer default attributes
# Returns 1 on success. Returns negative line number on syntax errors.
@ -1327,7 +1380,12 @@ sub HMCCU_Set ($@)
my $name = shift @$a;
my $opt = shift @$a;
my $options = "var delete execute hmscript cleardefaults:noArg defaults:noArg ".
"importdefaults rpcserver:on,off,restart datapoint ackmessages:noArg";
"importdefaults rpcregister:all rpcserver:on,off,restart datapoint ackmessages:noArg";
my @ifList = HMCCU_GetRPCInterfaceList ($hash);
if (scalar (@ifList) > 0) {
my $ifStr = join (',', @ifList);
$options =~ s/register:all/rpcregister:all,$ifStr/;
}
my $usage = "HMCCU: Unknown argument $opt, choose one of $options";
my $host = $hash->{host};
@ -1341,6 +1399,7 @@ sub HMCCU_Set ($@)
my $ccureqtimeout = AttrVal ($name, "ccuReqTimeout", $HMCCU_TIMEOUT_REQUEST);
my $readingformat = HMCCU_GetAttrReadingFormat ($hash, $hash);
my $substitute = HMCCU_GetAttrSubstitute ($hash, $hash);
my $result;
# Add program names to command execute
if (exists ($hash->{hmccu}{prg})) {
@ -1361,7 +1420,6 @@ sub HMCCU_Set ($@)
my $objname = shift @$a;
my $objvalue = shift @$a;
$usage = "set $name $opt [{'bool'|'list'|'number'|'test'}] variable value [param=value [...]]";
my $result;
return HMCCU_SetError ($hash, $usage) if (!defined ($objvalue));
@ -1395,7 +1453,7 @@ sub HMCCU_Set ($@)
return HMCCU_SetError ($hash, $usage)
if (!defined ($objname) || $objtype !~ /^(OT_VARDP|OT_DEVICE)$/);
my $result = HMCCU_HMScriptExt ($hash, "!DeleteObject", { name => $objname, type => $objtype });
$result = HMCCU_HMScriptExt ($hash, "!DeleteObject", { name => $objname, type => $objtype });
return HMCCU_SetError ($hash, -2) if ($result =~ /^ERROR:.*/);
return HMCCU_SetState ($hash, "OK");
@ -1469,6 +1527,25 @@ sub HMCCU_Set ($@)
return defined ($dump) ? $response : undef;
}
elsif ($opt eq 'rpcregister') {
return HMCCU_SetError ($hash, "HMCCU: Command not supported by internal RPC server")
if ($ccuflags !~ /procrpc/);
my $ifName = shift @$a;
$result = '';
@ifList = (defined ($ifName) && $ifName ne 'all') ? ($ifName) : HMCCU_GetRPCInterfaceList ($hash);
foreach my $i (@ifList) {
my ($rpcdev, $save) = HMCCU_GetRPCDevice ($hash, 0, $i);
if ($rpcdev eq '') {
Log3 $name, 2, "HMCCU: Can't find HMCCURPCPROC device for interface $i";
next;
}
my $res = AnalyzeCommandChain (undef, "set $rpcdev register");
$result .= $res if (defined ($res));
}
return HMCCU_SetState ($hash, "OK", $result);
}
elsif ($opt eq 'rpcserver') {
my $action = shift @$a;
$action = shift @$a if ($action eq $opt);
@ -1884,10 +1961,14 @@ sub HMCCU_Get ($@)
}
elsif ($opt eq 'exportdefaults') {
my $filename = shift @$a;
$usage = "Usage: get $name $opt filename";
return HMCCU_SetError ($hash, $usage) if (!defined ($filename));
my $csv = shift @$a;
my $rc = HMCCU_ExportDefaults ($filename);
$csv = 'default' if (!defined ($csv));
$usage = "Usage: get $name $opt filename [{csv|default}]";
return HMCCU_SetError ($hash, $usage) if (!defined ($filename));
return HMCCU_SetError ($hash, $usage) if ($csv !~ /^(default|csv)$/);
my $rc = $csv ne 'csv' ? HMCCU_ExportDefaults ($filename) : HMCCU_ExportDefaultsCSV ($filename);
return HMCCU_SetError ($hash, -16) if ($rc == 0);
return HMCCU_SetState ($hash, "OK", "Default attributes written to $filename");
}
@ -2688,7 +2769,7 @@ sub HMCCU_UpdateClients ($$$$$)
}
else {
Log3 $fhname, 2, "HMCCU: Update of device ".$ch->{ccuaddr}." failed"
if ($ch->{ccuif} ne 'VirtualDevices');
if ($ch->{ccuif} ne 'VirtualDevices' && $ch->{ccuif} ne 'fhem');
}
$c_err++;
}
@ -2701,6 +2782,61 @@ sub HMCCU_UpdateClients ($$$$$)
return ($c_ok, $c_err);
}
##########################################################################
# Create virtual device in internal device tables.
# If sourceAddr is specified, parameter newType will be ignored.
# Return 0 on success or error code:
# 1 = newType not defined
# 2 = Device with newType not found in internal tables
##########################################################################
sub HMCCU_CreateDevice ($$$$$)
{
my ($hash, $newAddr, $newName, $newType, $sourceAddr) = @_;
my %object;
if (!defined ($sourceAddr)) {
# Search for type in device table
return 1 if (!defined ($newType));
for my $da (keys %{$hash->{hmccu}{dev}}) {
if ($hash->{hmccu}{dev}{$da}{type} eq $newType) {
$sourceAddr = $da;
last;
}
}
return 2 if (!defined ($sourceAddr));
}
else {
$newType = $hash->{hmccu}{dev}{$sourceAddr}{type};
}
# Device attributes
$object{$newAddr}{flag} = 'N';
$object{$newAddr}{addtype} = 'dev';
$object{$newAddr}{channels} = $hash->{hmccu}{dev}{$sourceAddr}{channels};
$object{$newAddr}{name} = $newName;
$object{$newAddr}{type} = $newType;
$object{$newAddr}{interface} = 'fhem';
$object{$newAddr}{chndir} = 0;
# Channel attributes
for (my $chn=0; $chn<$object{$newAddr}{channels}; $chn++) {
my $ca = "$newAddr:$chn";
$object{$ca}{flag} = 'N';
$object{$ca}{addtype} = 'chn';
$object{$ca}{channels} = 1;
$object{$ca}{name} = "$newName:$chn";
$object{$ca}{chndir} = $hash->{hmccu}{dev}{"$sourceAddr:$chn"}{chndir};
$object{$ca}{rxmode} = $hash->{hmccu}{dev}{"$sourceAddr:$chn"}{rxmode};
$object{$ca}{usetype} = $hash->{hmccu}{dev}{"$sourceAddr:$chn"}{usetype};
}
HMCCU_UpdateDeviceTable ($hash, \%object);
return 0;
}
##########################################################################
# Update parameters in internal device tables and client devices.
# Parameter devices is a hash reference with following keys:
@ -2768,9 +2904,11 @@ sub HMCCU_UpdateDeviceTable ($$)
if (defined ($devices->{$da}{rxmode}));
$hash->{hmccu}{dev}{$da}{chndir} = $devices->{$da}{chndir}
if (defined ($devices->{$da}{chndir}));
$hash->{hmccu}{adr}{$nm}{address} = $da;
$hash->{hmccu}{adr}{$nm}{addtype} = $hash->{hmccu}{dev}{$da}{addtype};
$hash->{hmccu}{adr}{$nm}{valid} = 1 if (defined ($nm));
if (defined ($nm)) {
$hash->{hmccu}{adr}{$nm}{address} = $da;
$hash->{hmccu}{adr}{$nm}{addtype} = $hash->{hmccu}{dev}{$da}{addtype};
$hash->{hmccu}{adr}{$nm}{valid} = 1;
}
}
elsif ($devices->{$da}{flag} eq 'D' && exists ($hash->{hmccu}{dev}{$da})) {
# Device deleted, mark as invalid
@ -2932,7 +3070,7 @@ sub HMCCU_UpdateSingleDevice ($$$)
# Build device list including virtual devices
my @grplist = ($cltname);
my @virlist = HMCCU_FindClientDevices ($ccuhash, "HMCCUDEV", undef, "ccuif=VirtualDevices");
my @virlist = HMCCU_FindClientDevices ($ccuhash, "HMCCUDEV", undef, "ccuif=(VirtualDevices|fhem)");
foreach my $vd (@virlist) {
my $vh = $defs{$vd};
next if (!defined ($vh->{ccugroup}));
@ -2974,7 +3112,7 @@ sub HMCCU_UpdateSingleDevice ($$$)
my @devlist = ($ch->{ccuaddr});
push @devlist, split (",", $ch->{ccugroup})
if ($ch->{ccuif} eq 'VirtualDevices' && exists ($ch->{ccugroup}));
if (($ch->{ccuif} eq 'VirtualDevices' || $ch->{ccuif} eq 'fhem') && exists ($ch->{ccugroup}));
readingsBeginUpdate ($ch);
@ -3730,27 +3868,39 @@ sub HMCCU_GetDeviceInfo ($$$)
my ($hash, $device, $ccuget) = @_;
my $name = $hash->{NAME};
my $devname = '';
my $response = '';
my $hmccu_hash = HMCCU_GetHash ($hash);
return '' if (!defined ($hmccu_hash));
$ccuget = HMCCU_GetAttribute ($hmccu_hash, $hash, 'ccuget', 'Value') if ($ccuget eq 'Attr');
my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($hmccu_hash, $device, 0);
if ($flags == $HMCCU_FLAG_ADDRESS) {
$devname = HMCCU_GetDeviceName ($hmccu_hash, $add, '');
return '' if ($devname eq '');
my @devlist;
if ($hash->{ccuif} eq 'fhem' && exists ($hash->{ccugroup})) {
push @devlist, split (",", $hash->{ccugroup});
}
else {
$devname = $nam;
push @devlist, $device;
}
return '' if (scalar (@devlist) == 0);
$ccuget = HMCCU_GetAttribute ($hmccu_hash, $hash, 'ccuget', 'Value') if ($ccuget eq 'Attr');
my $response = HMCCU_HMScriptExt ($hmccu_hash, "!GetDeviceInfo",
{ devname => $devname, ccuget => $ccuget });
HMCCU_Trace ($hash, 2, undef,
"Device=$device Devname=$devname<br>".
"Script response = \n".$response."<br>".
"Script = GetDeviceInfo");
for my $dev (@devlist) {
my ($int, $add, $chn, $dpt, $nam, $flags) = HMCCU_ParseObject ($hmccu_hash, $dev, 0);
if ($flags == $HMCCU_FLAG_ADDRESS) {
$devname = HMCCU_GetDeviceName ($hmccu_hash, $add, '');
return '' if ($devname eq '');
}
else {
$devname = $nam;
}
$response .= HMCCU_HMScriptExt ($hmccu_hash, "!GetDeviceInfo",
{ devname => $devname, ccuget => $ccuget });
HMCCU_Trace ($hash, 2, undef,
"Device=$devname Devname=$devname<br>".
"Script response = \n".$response."<br>".
"Script = GetDeviceInfo");
}
return $response;
}
@ -4786,7 +4936,8 @@ sub HMCCU_GetRPCDevice ($$$)
if (!defined ($ifname));
$rpcdevname = HMCCU_GetRPCServerInfo ($hash, $ifname, 'device');
$rpchost = HMCCU_GetRPCServerInfo ($hash, $ifname, 'host');
return ($rpcdevname, 0) if (defined ($rpcdevname) || !defined ($rpchost));
return ($rpcdevname, 0) if (defined ($rpcdevname));
return ('', 0) if (!defined ($rpchost));
# $rpcdevtype = 'HMCCURPCPROC';
}
# elsif ($ccuflags =~ /extrpc/) {
@ -6035,11 +6186,12 @@ sub HMCCU_GetUpdate ($$$)
elsif (HMCCU_IsValidDevice ($hmccu_hash, $addr, $HMCCU_FL_ADDRESS)) {
$nam = HMCCU_GetDeviceName ($hmccu_hash, $addr, '');
return -1 if ($nam eq '');
$list = $nam;
$list = $nam if ($cl_hash->{ccuif} ne 'fhem');
$script = "!GetDatapointsByDevice";
# Consider members of group device
if ($type eq 'HMCCUDEV' && $cl_hash->{ccuif} eq 'VirtualDevices' &&
if ($type eq 'HMCCUDEV' &&
($cl_hash->{ccuif} eq 'VirtualDevices' || $cl_hash->{ccuif} eq 'fhem') &&
exists ($cl_hash->{ccugroup})) {
foreach my $gd (split (",", $cl_hash->{ccugroup})) {
$nam = HMCCU_GetDeviceName ($hmccu_hash, $gd, '');
@ -6078,6 +6230,21 @@ sub HMCCU_GetUpdate ($$$)
$events{$add}{$chn}{$dpt} = $value;
}
if ($cl_hash->{ccuif} eq 'fhem') {
# Calculate datapoints of virtual group device
if ($cl_hash->{ccutype} ne 'n/a') {
foreach my $da (split (",", $cl_hash->{ccugroup})) {
foreach my $cn (keys %{$events{$da}}) {
foreach my $dp (keys %{$events{$da}{$cn}}) {
if (defined ($events{$da}{$cn}{$dp})) {
$events{$cl_hash->{ccuaddr}}{$cn}{$dp} = $events{$da}{$cn}{$dp}
}
}
}
}
}
}
HMCCU_UpdateSingleDevice ($hmccu_hash, $cl_hash, \%events);
return 1;
@ -7373,6 +7540,9 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
<li><b>set &lt;name&gt; importdefaults &lt;filename&gt;</b><br/>
Import default attributes from file.
</li><br/>
<li><b>set &lt;name&gt; rpcregister [{all | &lt;interface&gt;}]</b><br/>
Register RPC servers at CCU.
</li><br/>
<li><b>set &lt;name&gt; rpcserver {on | off | restart}</b><br/>
Start, stop or restart RPC server(s). This command executed with option 'on'
will fork a RPC server process for each RPC interface defined in attribute 'rpcinterfaces'.
@ -7441,7 +7611,7 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
iface_conn_n = interface connection state (1=connected, 0=disconnected)<br/>
iface_ducy_n = duty cycle of interface (0-100)
</li><br/>
<li><b>get &lt;name&gt; exportdefaults &lt;filename&gt;</b><br/>
<li><b>get &lt;name&gt; exportdefaults &lt;filename&gt; [{<u>default</u>|csv}]</b><br/>
Export default attributes into file.
</li><br/>
<li><b>get &lt;name&gt; firmware [{&lt;type-expr&gt; | full}]</b><br/>

View File

@ -4,7 +4,7 @@
#
# $Id$
#
# Version 4.3.002
# Version 4.3.003
#
# (c) 2018 zap (zap01 <at> t-online <dot> de)
#
@ -108,6 +108,16 @@ sub HMCCUDEV_Define ($@)
"['readonly'] ['defaults'] [iodev={iodev-name}] ".
"[{groupexp=regexp|group={device|channel}[,...]]";
return $usage if (scalar (@$a) < 3);
my @errmsg = (
"OK",
"Invalid or unknown CCU device name or address",
"Can't assign I/O device",
"No devices in group",
"No matching CCU devices found",
"Type of virtual device not defined",
"Device type not found"
);
my $devname = shift @$a;
my $devtype = shift @$a;
@ -144,22 +154,6 @@ sub HMCCUDEV_Define ($@)
# 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
my $no = 0;
foreach my $d (sort keys %defs) {
my $ch = $defs{$d};
next if (!exists ($ch->{TYPE}));
next if ($ch->{TYPE} ne 'HMCCUDEV' || $d eq $name);
next if ($ch->{ccuif} ne 'VirtualDevices' || $ch->{ccuname} ne 'none');
$no++;
}
$hash->{ccuif} = "VirtualDevices";
$hash->{ccuaddr} = sprintf ("VIR%07d", $no+1);
$hash->{ccuname} = "none";
$hash->{statevals} = 'readonly';
}
if ($init_done) {
# Interactive define command while CCU not ready
@ -185,9 +179,7 @@ sub HMCCUDEV_Define ($@)
# 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 $errmsg[$rc] if ($rc > 0);
return undef;
}
@ -199,64 +191,107 @@ sub HMCCUDEV_Define ($@)
# 1 = Invalid channel name or address
# 2 = Cannot assign IO device
# 3 = No devices in group
# 4 = No matching CCU devices found
# 5 = Type of virtual device not defined
# 6 = Device type not found
######################################################################
sub HMCCUDEV_InitDevice ($$)
{
my ($hmccu_hash, $dev_hash) = @_;
my $name = $dev_hash->{NAME};
my $devspec = $dev_hash->{hmccu}{devspec};
my $gdcount = 0;
my $gdname = $devspec;
return 1 if (! HMCCU_IsValidDevice ($hmccu_hash, $devspec, 7));
if ($devspec eq 'virtual') {
# Virtual device FHEM only, search for free address
my $no = 0;
foreach my $d (sort keys %defs) {
my $ch = $defs{$d};
next if (!exists ($ch->{TYPE}));
next if ($ch->{TYPE} ne 'HMCCUDEV' || $d eq $name);
next if ($ch->{ccuif} ne 'fhem' || $ch->{ccuname} ne 'virtual');
$no++;
}
$dev_hash->{ccuif} = 'fhem';
$dev_hash->{ccuaddr} = sprintf ("VIR%07d", $no+1);
$dev_hash->{ccuname} = 'virtual';
}
else {
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;
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;
}
$dev_hash->{ccuif} = $di;
$dev_hash->{ccuaddr} = $da;
$dev_hash->{ccuname} = $dn;
$dev_hash->{ccutype} = $dt;
$dev_hash->{channels} = $dc;
# Parse group options
if ($dev_hash->{ccuif} eq "VirtualDevices") {
if ($dev_hash->{ccuif} eq 'VirtualDevices' || $dev_hash->{ccuif} eq 'fhem') {
my @devlist = ();
if (exists ($dev_hash->{hmccu}{groupexp})) {
my @devlist;
# Group devices specified by name expression
$gdcount = HMCCU_GetMatchingDevices ($hmccu_hash, $dev_hash->{hmccu}{groupexp}, 'dev', \@devlist);
return "No matching CCU devices found" if ($gdcount == 0);
$dev_hash->{ccugroup} = join (',', @devlist);
return 4 if ($gdcount == 0);
}
elsif (exists ($dev_hash->{hmccu}{group})) {
# Group devices specified by comma separated name list
my @gdevlist = split (",", $dev_hash->{hmccu}{group});
$dev_hash->{ccugroup} = '' if (@gdevlist > 0);
foreach my $gd (@gdevlist) {
my ($gda, $gdc, $gdo) = ('', '', '', '');
return "Invalid device or channel $gd" if (!HMCCU_IsValidDevice ($hmccu_hash, $gd, 7));
return 1 if (!HMCCU_IsValidDevice ($hmccu_hash, $gd, 7));
($gda, $gdc) = HMCCU_GetAddress ($hmccu_hash, $gd, '', '');
$gdo = $gda;
$gdo .= ':'.$gdc if ($gdc ne '');
if (exists ($dev_hash->{ccugroup}) && $dev_hash->{ccugroup} ne '') {
$dev_hash->{ccugroup} .= ",".$gdo;
}
else {
$dev_hash->{ccugroup} = $gdo;
}
push @devlist, $gdo;
$gdcount++;
}
}
else {
my @devlist = HMCCU_GetGroupMembers ($hmccu_hash, $gdname);
# Group specified by CCU virtual group name
@devlist = HMCCU_GetGroupMembers ($hmccu_hash, $gdname);
$gdcount = scalar (@devlist);
$dev_hash->{ccugroup} = join (',', @devlist);
return 5 if ($gdcount == 0);
}
return 3 if ($gdcount == 0);
$dev_hash->{ccugroup} = join (',', @devlist);
if ($devspec eq 'virtual') {
my $dev = shift @devlist;
my $devtype = HMCCU_GetDeviceType ($hmccu_hash, $dev, 'n/a');
my $devna = $devtype eq 'n/a' ? 1 : 0;
for my $d (@devlist) {
if (HMCCU_GetDeviceType ($hmccu_hash, $d, 'n/a') ne $devtype) {
$devna = 1;
last;
}
}
my $rc = 0;
if ($devna) {
$dev_hash->{ccutype} = 'n/a';
$dev_hash->{statevals} = 'readonly';
$rc = HMCCU_CreateDevice ($hmccu_hash, $dev_hash->{ccuaddr}, $name, undef, $dev);
}
else {
$dev_hash->{ccutype} = $devtype;
$rc = HMCCU_CreateDevice ($hmccu_hash, $dev_hash->{ccuaddr}, $name, $devtype, $dev);
}
return $rc+4 if ($rc > 0);
# Set default attributes
$attr{$name}{ccureadingformat} = 'name';
}
}
# Inform HMCCU device about client device
@ -642,7 +677,7 @@ sub HMCCUDEV_Get ($@)
my $result = '';
my $rc;
if ($ccuif eq "VirtualDevices" && $hash->{ccuname} eq "none" && $opt ne 'update') {
if ($ccuif eq "VirtualDevices" && $hash->{ccuname} eq "virtual" && $opt ne 'update') {
return "HMCCUDEV: Unknown argument $opt, choose one of update:noArg";
}
@ -688,19 +723,19 @@ sub HMCCUDEV_Get ($@)
return HMCCU_SetError ($hash, "Usage: get $name update [{'State'|'Value'}]");
}
if ($hash->{ccuname} ne 'none') {
if ($hash->{ccuname} ne 'virtual') {
$rc = HMCCU_GetUpdate ($hash, $ccuaddr, $ccuget);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
}
# Update other devices belonging to group
if ($hash->{ccuif} eq "VirtualDevices" && exists ($hash->{ccugroup})) {
my @vdevs = split (",", $hash->{ccugroup});
foreach my $vd (@vdevs) {
$rc = HMCCU_GetUpdate ($hash, $vd, $ccuget);
return HMCCU_SetError ($hash, $rc) if ($rc < 0);
}
}
# if ($hash->{ccuif} eq "VirtualDevices" && exists ($hash->{ccugroup})) {
# my @vdevs = split (",", $hash->{ccugroup});
# foreach my $vd (@vdevs) {
# $rc = HMCCU_GetUpdate ($hash, $vd, $ccuget);
# return HMCCU_SetError ($hash, $rc) if ($rc < 0);
# }
# }
return undef;
}

View File

@ -4,7 +4,7 @@
#
# $Id$
#
# Version 4.2.005
# Version 4.3
#
# Configuration parameters for HomeMatic devices.
#
@ -131,6 +131,21 @@ use vars qw(%HMCCU_SCRIPTS);
webCmd => "control:on:off",
widgetOverride => "control:slider,0,10,100"
},
"HmIP-BDT" => {
_description => "Dimmaktor",
_channels => "4",
ccureadingfilter => "(ERROR_CODE|ERROR_OVERHEAT|ACTUAL_TEMPERATURE|ACTIVITY_STATE|LEVEL)",
ccuscaleval => "LEVEL:0:1:0:100",
controldatapoint => "LEVEL",
hmstatevals => "ACTUAL_TEMPERATURE_STATUS!2:tempOverflow,3:tempUnderflow;ERROR_OVERHEAT!(1|true):overheat",
statedatapoint => "LEVEL",
statevals => "on:100,off:0",
stripnumber => 1,
substexcl => "control",
substitute => "LEVEL!#0-0:off,#1-100:on;ACTIVITY_STATE!0:unknown,1:up,2:down,3:stop;ERROR_OVERHEAT!(0|false):no,(1|true):yes;ACTUAL_TEMPERATURE_STATUS!0:normal,1:unknown,2:overflow,3:underflow",
webCmd => "control:on:off",
widgetOverride => "control:slider,0,10,100"
},
"HM-LC-Dim1T-Pl|HM-LC-Dim1T-CV|HM-LC-Dim1T-FM|HM-LC-Dim1T-CV-2|HM-LC-Dim2T-SM|HM-LC-Dim2T-SM-2|HM-LC-Dim1T-DR|HM-LC-Dim1T-FM-LF|HM-LC-Dim1T-FM-2|HM-LC-Dim1T-Pl-3|HM-LC-Dim1TPBU-FM|HM-LC-Dim1TPBU-FM-2" => {
_description => "Funk-Abschnitt-Dimmaktor",
_channels => "1",
@ -276,6 +291,23 @@ use vars qw(%HMCCU_SCRIPTS);
webCmd => "control:up:stop:down",
widgetOverride => "control:slider,0,10,100"
},
"HmIP-BROLL" => {
_description => "Rollladenaktor",
_channels => "4",
ccureadingfilter => "(ERROR_CODE|ERROR_OVERHEAT|ACTUAL_TEMPERATURE|LEVEL|ACTIVITY_STATE)",
ccureadingname => "LEVEL:+pct",
ccuscaleval => "LEVEL:0:1:0:100",
cmdIcon => "up:fts_shutter_up stop:fts_shutter_manual down:fts_shutter_down",
controldatapoint => "LEVEL",
hmstatevals => "ACTUAL_TEMPERATURE_STATUS!2:tempOverflow,3:tempUnderflow;ERROR_OVERHEAT!(1|true):overheat",
eventMap => "/datapoint STOP true:stop/datapoint LEVEL 0:down/datapoint LEVEL 100:up/",
statedatapoint => "LEVEL",
stripnumber => 1,
substexcl => "control|pct",
substitute => "LEVEL!#0-0:closed,#100-100:open;ACTIVITY_STATE!0:unknown,1:up,2:down,3:stop;ERROR_OVERHEAT!(0|false):no,(1|true):yes;ACTUAL_TEMPERATURE_STATUS!0:normal,1:unknown,2:overflow,3:underflow",
webCmd => "control:up:stop:down",
widgetOverride => "control:slider,0,10,100"
},
"HM-WDS40-TH-I|HM-WDS10-TH-O|HM-WDS20-TH-O|IS-WDS-TH-OD-S-R3|ASH550I|ASH550" => {
_description => "Temperatur/Luftfeuchte Sensor",
_channels => "1",
@ -504,7 +536,8 @@ use vars qw(%HMCCU_SCRIPTS);
substitute => "STATE!(true|1):on,(false|0):off",
webCmd => "control",
widgetOverride => "control:uzsuToggle,off,on"
}, "HM-LC-Dim1L-Pl|HM-LC-Dim1L-Pl-2|HM-LC-Dim1L-CV|HM-LC-Dim2L-CV|HM-LC-Dim2L-SM|HM-LC-Dim1L-Pl-3|HM-LC-Dim1L-CV-2" => {
},
"HM-LC-Dim1L-Pl|HM-LC-Dim1L-Pl-2|HM-LC-Dim1L-CV|HM-LC-Dim2L-CV|HM-LC-Dim2L-SM|HM-LC-Dim1L-Pl-3|HM-LC-Dim1L-CV-2" => {
_description => "Funk-Anschnitt-Dimmaktor",
ccureadingfilter => "(^LEVEL\$|DIRECTION)",
ccuscaleval => "LEVEL:0:1:0:100",
@ -549,6 +582,20 @@ use vars qw(%HMCCU_SCRIPTS);
webCmd => "control:on:off",
widgetOverride => "control:slider,0,10,100"
},
"HmIP-BDT" => {
_description => "Dimmaktor",
ccureadingfilter => "(ERROR_CODE|ERROR_OVERHEAT|ACTUAL_TEMPERATURE|ACTIVITY_STATE|LEVEL)",
ccuscaleval => "LEVEL:0:1:0:100",
controldatapoint => "4.LEVEL",
hmstatevals => "ACTUAL_TEMPERATURE_STATUS!2:tempOverflow,3:tempUnderflow;ERROR_OVERHEAT!(1|true):overheat",
statedatapoint => "4.LEVEL",
statevals => "on:100,off:0",
stripnumber => 1,
substexcl => "control",
substitute => "LEVEL!#0-0:off,#1-100:on;ACTIVITY_STATE!0:unknown,1:up,2:down,3:stop;ERROR_OVERHEAT!(0|false):no,(1|true):yes;ACTUAL_TEMPERATURE_STATUS!0:normal,1:unknown,2:overflow,3:underflow",
webCmd => "control:on:off",
widgetOverride => "control:slider,0,10,100"
},
"HM-PB-2-FM" => {
_description => "Funk-Wandtaster 2-fach",
ccureadingfilter => "PRESS",
@ -639,6 +686,22 @@ use vars qw(%HMCCU_SCRIPTS);
webCmd => "control:up:stop:down",
widgetOverride => "control:slider,0,10,100"
},
"HmIP-BROLL" => {
_description => "Rollladenaktor",
ccureadingfilter => "(ERROR_CODE|ERROR_OVERHEAT|ACTUAL_TEMPERATURE|LEVEL|ACTIVITY_STATE|SELF_CALIBRATION_RESULT)",
ccureadingname => "LEVEL:+pct",
ccuscaleval => "LEVEL:0:1:0:100",
cmdIcon => "up:fts_shutter_up stop:fts_shutter_manual down:fts_shutter_down",
controldatapoint => "4.LEVEL",
hmstatevals => "ACTUAL_TEMPERATURE_STATUS!2:tempOverflow,3:tempUnderflow;ERROR_OVERHEAT!(1|true):overheat",
eventMap => "/datapoint 4.STOP true:stop/datapoint 4.LEVEL 0:down/datapoint 4.LEVEL 100:up/datapoint 3.SELF_CALIBRATION 0:stopCalibration/datapoint 3.SELF_CALIBRATION 1:startCalibration/",
statedatapoint => "4.LEVEL",
stripnumber => 1,
substexcl => "control|pct",
substitute => "LEVEL!#0-0:closed,#100-100:open;ACTIVITY_STATE!0:unknown,1:up,2:down,3:stop;ERROR_OVERHEAT!(0|false):no,(1|true):yes;ACTUAL_TEMPERATURE_STATUS!0:normal,1:unknown,2:overflow,3:underflow;SELF_CALIBRATION_RESULT!(0|false):failed,(1|true):ok",
webCmd => "control:up:stop:down",
widgetOverride => "control:slider,0,10,100"
},
"HM-TC-IT-WM-W-EU" => {
_description => "Wandthermostat",
ccureadingfilter => "(^HUMIDITY|^TEMPERATURE|^SET_TEMPERATURE|^WINDOW_OPEN)",
@ -683,7 +746,7 @@ use vars qw(%HMCCU_SCRIPTS);
webCmd => "control:Boost:Auto:Manual:Holiday:on:off",
widgetOverride => "control:slider,4.5,0.5,30.5,1"
},
"HmIP-WTH|HmIP-WTH-2" => {
"HmIP-WTH|HmIP-WTH-2|HmIP-BWTH" => {
_description => "Wandthermostat HM-IP",
controldatapoint => "1.SET_POINT_TEMPERATURE",
eventMap => "/datapoint 1.BOOST_MODE true:Boost/datapoint 1.CONTROL_MODE 0:Auto/datapoint 1.CONTROL_MODE 1:Manual/datapoint 1.CONTROL_MODE 2:Holiday/datapoint 1.SET_POINT_TEMPERATURE 4.5:off/datapoint 1.SET_POINT_TEMPERATURE 30.5:on/",
@ -730,16 +793,18 @@ use vars qw(%HMCCU_SCRIPTS);
},
"HM-CC-VG-1" => {
_description => "Heizungsgruppe",
ccureadingfilter => "(^SET_TEMPERATURE|^TEMPERATURE|^HUMIDITY|^VALVE|^CONTROL|^WINDOW_OPEN)",
ccucalculate => "dewpoint:DEWPOINT:1.ACTUAL_TEMPERATURE,1.ACTUAL_HUMIDITY",
ccureadingfilter => "1.(^SET_TEMPERATURE|^ACTUAL|^VALVE|^CONTROL);2.^WINDOW_OPEN;4.^VALVE",
cmdIcon => "Auto:sani_heating_automatic Manu:sani_heating_manual Boost:sani_heating_boost on:general_an off:general_aus",
controldatapoint => "1.SET_TEMPERATURE",
eventMap => "/datapoint 1.MANU_MODE 20.0:Manu/datapoint 1.AUTO_MODE 1:Auto/datapoint 1.BOOST_MODE 1:Boost/datapoint 1.MANU_MODE 4.5:off/datapoint 1.MANU_MODE 30.5:on/",
statedatapoint => "1.SET_TEMPERATURE",
stateFormat => "T: 1.ACTUAL_TEMPERATURE° H: 1.ACTUAL_HUMIDITY% D: 1.SET_TEMPERATURE° P: DEWPOINT° V: 4.VALVE_STATE% 1.CONTROL_MODE",
stripnumber => 1,
substexcl => "control",
substitute => "CONTROL_MODE!0:AUTO,1:MANU,2:PARTY,3:BOOST;WINDOW_OPEN_REPORTING!(true|1):open,(false|0):closed;SET_TEMPERATURE!#0-4.5:off,#30.5-40:on",
webCmd => "control:Auto:Manu:Boost:on:off",
widgetOverride => "control:slider,3.5,0.5,30.5,1"
widgetOverride => "control:slider,4.5,0.5,30.5,1"
},
"HM-Sec-MD|HM-Sec-MDIR|HM-Sec-MDIR-2|HM-Sec-MDIR-3" => {
_description => "Bewegungsmelder",
@ -755,6 +820,14 @@ use vars qw(%HMCCU_SCRIPTS);
statedatapoint => "1.MOTION",
substitute => "MOTION!(0|false):no,(1|true):yes"
},
"HmIP-SMI55" => {
_description => "Bewegungsmelder",
ccureadingfilter => "(ILLUMINATION|MOTION|PRESS)",
"event-on-update-reading" => ".*",
eventMap => "/datapoint 3.MOTION_DETECTION_ACTIVE 1:detection-on/datapoint 3.MOTION_DETECTION_ACTIVE 0:detection-off/datapoint 3.RESET_MOTION 1:reset/",
statedatapoint => "3.MOTION",
substitute => "PRESS_LONG,PRESS_SHORT!(1|true):pressed,(0|false):released;MOTION,MOTION_DETECTION_ACTIVE!(0|false):no,(1|true):yes;ILLUMINATION_STATUS!0:normal,1:unknown,2:overflow"
},
"HmIP-SPI" => {
_description => "Anwesenheitssensor",
ccureadingfilter => "(ILLUMINATION|PRESENCE)",