2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-19 12:46:03 +00:00

HMCCU: Update Beta 4.4

git-svn-id: https://svn.fhem.de/fhem/trunk@21305 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2020-02-28 13:29:08 +00:00
parent ead9ad6a84
commit 00796b43c2
4 changed files with 109 additions and 57 deletions

View File

@ -45,6 +45,7 @@ use HMCCUConf;
# Import configuration data
my $HMCCU_ROLES = \%HMCCUConf::HMCCU_ROLES;
my $HMCCU_ATTR = \%HMCCUConf::HMCCU_ATTR;
my $HMCCU_CONVERSIONS = \%HMCCUConf::HMCCU_CONVERSIONS;
my $HMCCU_CHN_DEFAULTS = \%HMCCUConf::HMCCU_CHN_DEFAULTS;
my $HMCCU_DEV_DEFAULTS = \%HMCCUConf::HMCCU_DEV_DEFAULTS;
my $HMCCU_SCRIPTS = \%HMCCUConf::HMCCU_SCRIPTS;
@ -1619,27 +1620,45 @@ sub HMCCU_Set ($@)
return HMCCU_SetState ($hash, "OK");
}
elsif ($opt eq 'datapoint') {
$usage = "set $name $opt DevSpec [Channel].Datapoint=Value [...]\n";
$usage = "set $name $opt [DevSpec] [Device[,...]].[Channel].Datapoint=Value [...]\n";
my $devSpec = shift @$a;
return HMCCU_SetError ($hash, $usage) if (scalar (keys %$h) < 1 || !defined($devSpec));
return HMCCU_SetError ($hash, $usage) if (scalar (keys %$h) < 1);
my $cmd = 1;
my %dpValues;
my @devSpecList = ();
my @devList = devspec2array ($devSpec);
if (defined($devSpec)) {
@devSpecList = devspec2array ($devSpec);
return HMCCU_SetError ($hash, "No FHEM device matching $devSpec in command set datapoint")
if (scalar (@devList) == 0);
if (scalar (@devSpecList) == 0);
}
foreach my $dptSpec (keys %$h) {
my $adr;
my $chn;
my $dpt;
my ($t1, $t2) = split (/\./, $dptSpec);
my $objvalue = $h->{$dptSpec};
my @t = split (/\./, $dptSpec);
my @devList = ();
if (scalar(@t) == 3 || (scalar(@t) == 2 && $dptSpec !~ /^[0-9]{1,2}\.(.+)$/)) {
$devSpec = shift @t;
@devList = split (',', $devSpec);
}
else {
@devList = @devSpecList;
}
my ($t1, $t2) = @t;
foreach my $devName (@devList) {
my $dh = $defs{$devName};
my $ccuif = $dh->{ccuif};
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($dh, '', '', '', '');
my $roleCmds = HMCCU_GetSpecialCommands ($dh, $cc);
my $stateVals = HMCCU_GetStateValues ($dh, $roleCmds, $cd, 2);
if ($dh->{TYPE} eq 'HMCCUCHN') {
if (defined ($t2)) {
@ -1655,7 +1674,7 @@ sub HMCCU_Set ($@)
return HMCCU_SetError ($hash, "Missing channel number for device $devName")
if (!defined ($t2));
return HMCCU_SetError ($hash, "Invalid channel number specified for device $devName")
if ($t1 !~ /^[0-9]+$/ || $t1 > $dh->{hmccu}{channels});
if ($t1 !~ /^[0-9]+$/ || $t1 > $dh->{channels});
$adr = $dh->{ccuaddr};
$chn = $t1;
$dpt = $t2;
@ -1667,10 +1686,10 @@ sub HMCCU_Set ($@)
return HMCCU_SetError ($hash, "Invalid datapoint $dpt specified for device $devName")
if (!HMCCU_IsValidDatapoint ($dh, $dh->{ccutype}, $chn, $dpt, 2));
my $statevals = AttrVal ($dh->{NAME}, 'statevals', '');
$objvalue = HMCCU_Substitute ($objvalue, $stateVals, 1, undef, '')
if ($stateVals ne '' && "$chn" eq "$cc" && $dpt eq $cd);
my $no = sprintf ("%03d", $cmd);
$dpValues{"$no.$ccuif.$devName:$chn.$dpt"} = HMCCU_Substitute ($h->{$dptSpec}, $statevals, 1, undef, '');
$dpValues{"$no.$ccuif.$devName:$chn.$dpt"} = $objvalue;
$cmd++;
}
}
@ -2990,28 +3009,6 @@ sub HMCCU_Substitute ($$$$$;$$)
my $rc = 0;
my $newvalue;
my %conversion = (
'SHUTTER_CONTACT' => {
'STATE' => { '0' => 'closed', '1' => 'open', 'false' => 'closed', 'true' => 'open' }
},
'SWITCH' => {
'STATE' => { '0' => 'off', 'false' => 'off', '1' => 'on', 'true' => 'on', 'off' => '0', 'on' => '1' },
},
'BLIND' => {
'LEVEL' => { '0' => 'closed', '100' => 'open', 'close' => '0', 'open' => '100' }
},
'DIMMER' => {
'LEVEL' => { '0' => 'off', '100' => 'on', 'off' => '0', 'on' => '100' }
},
'DEFAULT' => {
'AES_KEY' => { '0' => 'off', 'false' => 'off', '1' => 'on', 'true' => 'on' },
'LOW_BAT' => { '0' => 'ok', 'false' => 'ok', '1' => 'low', 'true' => 'low' },
'LOWBAT' => { '0' => 'ok', 'false' => 'ok', '1' => 'low', 'true' => 'low' },
'STATE' => { '0' => 'false', '1' => 'true' },
'UNREACH' => { '0' => 'alive', 'false' => 'alive', '1' => 'dead', 'true' => 'dead' }
}
);
# return $value if (!defined ($substrule) || $substrule eq '');
# Remove channel number from datapoint if specified
@ -3075,11 +3072,11 @@ sub HMCCU_Substitute ($$$$$;$$)
}
$type = 'DEFAULT' if (!defined($type) || $type eq '');
if (exists($conversion{$type}{$dpt}{$value})) {
return $conversion{$type}{$dpt}{$value};
if (exists($HMCCU_CONVERSIONS->{$type}{$dpt}{$value})) {
return $HMCCU_CONVERSIONS->{$type}{$dpt}{$value};
}
elsif (exists($conversion{DEFAULT}{$dpt}{$value})) {
return $conversion{DEFAULT}{$dpt}{$value};
elsif (exists($HMCCU_CONVERSIONS->{DEFAULT}{$dpt}{$value})) {
return $HMCCU_CONVERSIONS->{DEFAULT}{$dpt}{$value};
}
return $value;
@ -3104,7 +3101,7 @@ sub HMCCU_SubstRule ($$$)
$substitutes =~ s/\$\{value\}/$value/g;
my @sub_list = split /,/,$substitutes;
my @sub_list = split /[, ]/,$substitutes;
foreach my $s (@sub_list) {
my ($regexp, $text) = split /:/,$s,2;
next if (!defined ($regexp) || !defined($text));
@ -4450,11 +4447,8 @@ sub HMCCU_UpdateSingleDatapoint ($$$$)
my $ccuaddr = $clHash->{ccuaddr};
my ($devaddr, $chnnum) = HMCCU_SplitChnAddr ($ccuaddr);
# $objects{$devaddr}{$chn}{$dpt} = $value;
$objects{$devaddr}{$chn}{VALUES}{$dpt} = $value;
# my $rc = HMCCU_UpdateMultipleDevices ($hmccu_hash, \%objects);
# my $rc = HMCCU_UpdateSingleDevice ($hmccu_hash, $hash, \%objects, undef);
my $rc = HMCCU_UpdateParamsetReadings ($ioHash, $clHash, \%objects);
return (ref($rc)) ? $rc->{$devaddr}{$chn}{VALUES}{$dpt} : $value;
}
@ -4517,12 +4511,22 @@ sub HMCCU_UpdateParamsetReadings ($$$;$)
foreach my $c (keys %{$objects->{$a}}) {
next if (($clType eq 'HMCCUCHN' && "$c" ne "$chnNo" && "$c" ne "0" && "$c" ne "d"));
if (ref($objects->{$a}{$c}) ne 'HASH') {
HMCCU_Log ($ioHash, 2, "object $a $c is not a hash reference\n".stacktraceAsString(undef));
next;
}
my $chnAddr = "$a:$c";
my $devDesc = HMCCU_GetDeviceDesc ($ioHash, $chnAddr, $clHash->{ccuif});
my $chnType = defined($devDesc) ? $devDesc->{TYPE} : HMCCU_GetChannelRole ($clHash, $c);
# Loop over all parameter sets
foreach my $ps (keys %{$objects->{$a}{$c}}) {
if (ref($objects->{$a}{$c}{$ps}) ne 'HASH') {
HMCCU_Log ($ioHash, 2, "object $a $c $ps is not a hash reference\n".stacktraceAsString(undef));
next;
}
# Loop over all parameters
foreach my $p (keys %{$objects->{$a}{$c}{$ps}}) {
my $v = $objects->{$a}{$c}{$ps}{$p};
@ -7450,7 +7454,7 @@ sub HMCCU_ReadRPCQueue ($)
my ($et, @par) = HMCCU_ProcessEvent ($hash, $element);
if (defined ($et)) {
if ($et eq 'EV') {
$events{$par[0]}{$par[1]}{$par[2]} = $par[3];
$events{$par[0]}{$par[1]}{VALUES}{$par[2]} = $par[3];
$eventno++;
last if ($eventno == $maxevents);
}

View File

@ -66,7 +66,7 @@ sub HMCCUCHN_Define ($@)
my ($hash, $a, $h) = @_;
my $name = $hash->{NAME};
my $usage = "Usage: define $name HMCCUCHN {device} ['readonly'] ['defaults'] [iodev={iodevname}]";
my $usage = "Usage: define $name HMCCUCHN {device} ['readonly'] ['noDefaults'] [iodev={iodevname}]";
return $usage if (@$a < 3);
my $devname = shift @$a;
@ -91,7 +91,7 @@ sub HMCCUCHN_Define ($@)
while (defined ($arg)) {
return $usage if ($n == 3);
if ($arg eq 'readonly') { $hash->{readonly} = "yes"; }
elsif ($arg eq 'defaults') { HMCCU_SetDefaults ($hash) if ($init_done); }
elsif ($arg ne 'noDefaults' && $init_done) { $hash->{hmccu}{nodefaults} = 1; }
else { return $usage; }
$n++;
$arg = shift @$a;
@ -171,6 +171,11 @@ sub HMCCUCHN_InitDevice ($$)
HMCCU_AddDevice ($ioHash, $di, $da, $devHash->{NAME});
HMCCU_UpdateDevice ($ioHash, $devHash);
HMCCU_UpdateDeviceRoles ($ioHash, $devHash);
if (!exists($devHash->{hmccu}{nodefaults})) {
if (!HMCCU_SetDefaultAttributes ($devHash)) {
HMCCU_SetDefaults ($devHash);
}
}
HMCCU_GetUpdate ($devHash, $da, 'Value');
}
@ -723,11 +728,10 @@ sub HMCCUCHN_Get ($@)
<b>Define</b><br/><br/>
<ul>
<code>define &lt;name&gt; HMCCUCHN {&lt;channel-name&gt; | &lt;channel-address&gt;}
[readonly] [defaults] [iodev=&lt;iodev-name&gt;]</code>
[readonly] [noDefaults] [iodev=&lt;iodev-name&gt;]</code>
<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.<br/>
If option 'readonly' is specified no set command will be available. With option 'noDefaults'
no default attributes will be set during interactive device definition. <br/>
The define command accepts a CCU2 channel name or channel address as parameter.
<br/><br/>
Examples:<br/>

View File

@ -388,15 +388,32 @@ sub HMCCUDEV_Set ($@)
my $ccuaddr = $hash->{ccuaddr};
my $ccuif = $hash->{ccuif};
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my $statevals = AttrVal ($name, 'statevals', '');
# Get state and control datapoints
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', '', '', '');
# Get additional commands (including state commands)
my $roleCmds = HMCCU_GetSpecialCommands ($hash, $cc);
my $cmdList = '';
my %addCmds;
foreach my $d (keys %$roleCmds) {
my @cmds = split(' ', $roleCmds->{$d});
foreach my $cmdDef (@cmds) {
my ($cmd, $argDef) = split(':', $cmdDef);
$addCmds{$cmd} = "$d=$argDef";
$cmdList .= " $cmd";
if ($argDef !~ /^\?/) {
my @argList = split(',', $argDef);
$cmdList .= scalar(@argList) > 1 ? ':'.$argDef : ':noArg';
}
}
}
# Get state values related to control command and datapoint
my $stateVals = HMCCU_GetStateValues ($hash, $roleCmds, $cd, 2);
my %stateCmds = split (/[:\s]/, $stateVals);
my @stateCmdList = split (/[:\s]/, $stateVals);
my %stateCmds = @stateCmdList;
my @states = keys %stateCmds;
my $result = '';
@ -440,7 +457,7 @@ sub HMCCUDEV_Set ($@)
my $no = sprintf ("%03d", $i);
$objvalue =~ s/\\_/%20/g;
$dpval{"$no.$ccuif.$ccuaddr:$objname"} = HMCCU_Substitute ($objvalue, $statevals, 1, undef, '');
$dpval{"$no.$ccuif.$ccuaddr:$objname"} = HMCCU_Substitute ($objvalue, $stateVals, 1, undef, '');
}
return HMCCU_SetError ($hash, $usage) if (scalar (keys %dpval) < 1);
@ -459,7 +476,7 @@ sub HMCCUDEV_Set ($@)
$objvalue =~ s/\\_/%20/g;
$rc = HMCCU_SetMultipleDatapoints ($hash,
{ "001.$ccuif.$ccuaddr:$cc.$cd" => HMCCU_Substitute ($objvalue, $statevals, 1, undef, '') }
{ "001.$ccuif.$ccuaddr:$cc.$cd" => HMCCU_Substitute ($objvalue, $stateVals, 1, undef, '') }
);
return HMCCU_SetError ($hash, min(0, $rc));
}
@ -566,7 +583,7 @@ sub HMCCUDEV_Set ($@)
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'on-for-timer' || $opt eq 'on-till') {
return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{hmccu}{statevals}));
return HMCCU_SetError ($hash, -15) if ($stateVals eq '' || !exists($hash->{hmccu}{statevals}));
return HMCCU_SetError ($hash, "No state value for 'on' defined")
if ("on" !~ /($hash->{hmccu}{statevals})/);
return HMCCU_SetError ($hash, -11) if ($sc eq '');
@ -585,7 +602,7 @@ sub HMCCUDEV_Set ($@)
$rc = HMCCU_SetMultipleDatapoints ($hash, {
"001.$ccuif.$ccuaddr:$sc.ON_TIME" => $timespec,
"002.$ccuif.$ccuaddr:$sc.$sd" => HMCCU_Substitute ("on", $statevals, 1, undef, '')
"002.$ccuif.$ccuaddr:$sc.$sd" => HMCCU_Substitute ("on", $stateVals, 1, undef, '')
});
return HMCCU_SetError ($hash, min(0, $rc));
}

View File

@ -19,6 +19,7 @@ use warnings;
use vars qw(%HMCCU_ROLES);
use vars qw(%HMCCU_ATTR);
use vars qw(%HMCCU_CONVERSIONS);
use vars qw(%HMCCU_CHN_DEFAULTS);
use vars qw(%HMCCU_DEV_DEFAULTS);
use vars qw(%HMCCU_SCRIPTS);
@ -90,6 +91,32 @@ use vars qw(%HMCCU_SCRIPTS);
}
);
######################################################################
# Value conversions
######################################################################
%HMCCU_CONVERSIONS = (
'SHUTTER_CONTACT' => {
'STATE' => { '0' => 'closed', '1' => 'open', 'false' => 'closed', 'true' => 'open' }
},
'SWITCH' => {
'STATE' => { '0' => 'off', 'false' => 'off', '1' => 'on', 'true' => 'on', 'off' => '0', 'on' => '1' },
},
'BLIND' => {
'LEVEL' => { '0' => 'closed', '100' => 'open', 'close' => '0', 'open' => '100' }
},
'DIMMER' => {
'LEVEL' => { '0' => 'off', '100' => 'on', 'off' => '0', 'on' => '100' }
},
'DEFAULT' => {
'AES_KEY' => { '0' => 'off', 'false' => 'off', '1' => 'on', 'true' => 'on' },
'LOW_BAT' => { '0' => 'ok', 'false' => 'ok', '1' => 'low', 'true' => 'low' },
'LOWBAT' => { '0' => 'ok', 'false' => 'ok', '1' => 'low', 'true' => 'low' },
'STATE' => { '0' => 'false', '1' => 'true' },
'UNREACH' => { '0' => 'alive', 'false' => 'alive', '1' => 'dead', 'true' => 'dead' }
}
);
######################################################################
# Default attributes for Homematic devices of type HMCCUCHN
######################################################################