2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 09:16:53 +00:00

HMCCU: Update for 4.4 Beta

git-svn-id: https://svn.fhem.de/fhem/trunk@21191 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2020-02-13 17:28:28 +00:00
parent 2fd87d451a
commit df6a1f0d7c
3 changed files with 102 additions and 70 deletions

View File

@ -3659,7 +3659,6 @@ sub HMCCU_UpdateDeviceRoles ($$;$$)
my ($ioHash, $clHash, $iface, $address) = @_;
my $clType = $clHash->{TYPE};
return if ($clType ne 'HMCCUCHN');
$iface = $clHash->{ccuif} if (!defined($iface));
$address = $clHash->{ccuaddr} if (!defined($address));
@ -6922,57 +6921,90 @@ sub HMCCU_GetSpecialDatapoints ($$$$$)
my $type = $hash->{TYPE};
my $ccutype = $hash->{ccutype};
# F: 1=Channel, 2=Device, 3=Both
# S: State Datapoint, C: Control datapoint
my %roleDPs = (
'SHUTTER_CONTACT' => { F => 3, S => 'STATE', C => '' },
'KEY' => { F => 3, S => 'PRESS_SHORT', C => 'PRESS_SHORT' },
'BLIND' => { F => 3, S => 'LEVEL', C => 'LEVEL' },
'SWITCH' => { F => 3, S => 'STATE', C => 'STATE' },
'DIMMER' => { F => 3, S => 'LEVEL', C => 'LEVEL' },
'WEATHER_TRANSMIT' => { F => 1, S => 'TEMPERATURE', C => 'TEMPERATURE' },
'THERMALCONTROL_TRANSMIT' => { F => 3, S => 'ACTUAL_TEMPERATURE', C => 'SET_TEMPERATURE' },
'CLIMATECONTROL_RT_TRANSCEIVER' => { F => 3, S => 'ACTUAL_TEMPERATURE', C => 'SET_TEMPERATURE' }
);
my $statedatapoint = AttrVal ($name, 'statedatapoint', '');
my $statechannel = AttrVal ($name, 'statechannel', '');
my $controldatapoint = AttrVal ($name, 'controldatapoint', $statedatapoint);
# If attribute statedatapoint is specified, use it
if ($statedatapoint ne '') {
if ($statedatapoint =~ /^([0-9]+)\.(.+)$/) {
($sc, $sd) = ($1, $2);
}
else {
$sd = $statedatapoint;
if ($statechannel eq '') {
# Try to find state channel
my $c = HMCCU_FindDatapoint ($hash, $type, -1, $sd, 3);
$sc = $c if ($c >= 0);
}
else {
$sc = $statechannel;
}
}
}
$sc = $statechannel if ($statechannel ne '' && $sc eq '');
# If attribute controldatapoint is specified, use it
if ($controldatapoint ne '') {
if ($controldatapoint =~ /^([0-9]+)\.(.+)$/) {
($cc, $cd) = ($1, $2);
}
else {
$cd = $controldatapoint;
# Try to find control channel
my $c = HMCCU_FindDatapoint ($hash, $type, -1, $cd, 3);
$cc = $c if ($c >= 0);
}
}
# For devices of type HMCCUCHN extract channel numbers from CCU device address
if (exists($hash->{ccurole})) {
my $ccuRole = $hash->{ccurole};
if ($type eq 'HMCCUCHN') {
$sc = $hash->{ccuaddr};
$sc =~ s/^[\*]*[0-9A-Z]+://;
$cc = $sc;
if ($sd eq '') {
if (HMCCU_IsValidDatapoint ($hash, $ccutype, $sc, 'STATE', 3)) { $sd = 'STATE'; }
elsif (HMCCU_IsValidDatapoint ($hash, $ccutype, $sc, 'LEVEL', 3)) { $sd = 'LEVEL'; }
elsif (HMCCU_IsValidDatapoint ($hash, $ccutype, $sc, 'PRESS_SHORT', 3)) { $sd = 'PRESS_SHORT'; }
my ($da, $dc) = HMCCU_SplitChnAddr ($hash->{ccuaddr});
$sc = $dc;
$cc = $dc;
if (exists($roleDPs{$ccuRole}) && $roleDPs{$ccuRole}{F} & 1) {
$sd = $roleDPs{$ccuRole}{S} if ($roleDPs{$ccuRole}{S} ne '');
$cd = $roleDPs{$ccuRole}{C} if ($roleDPs{$ccuRole}{C} ne '');
}
}
else {
# Try to find state channel
my $c = -1;
if ($sc eq '' && $sd ne '') {
$c = HMCCU_FindDatapoint ($hash, $type, -1, $sd, 3);
$sc = $c if ($c >= 0);
elsif ($type eq 'HMCCUDEV') {
foreach my $roleDef (split(',', $ccuRole)) {
my ($dc, $role) = split(':', $roleDef);
if (exists($roleDPs{$role}) && $roleDPs{$role}{F} & 2) {
if ($roleDPs{$role}{S} ne '' && $sd eq '') {
$sd = $roleDPs{$role}{S};
$sc = $dc;
}
if ($roleDPs{$role}{C} ne '' && $cd eq '') {
$cd = $roleDPs{$role}{C} ;
$cc = $dc;
}
}
last if ($sd ne '' && $cd ne '');
}
# Try to find control channel
if ($cc eq '' && $cd ne '') {
$c = HMCCU_FindDatapoint ($hash, $type, -1, $cd, 3);
$cc = $c if ($c >= 0);
}
}
# By default set control channel and datapoint to state channel and datapoint
$cc = $sc if ($cc eq '');
$cd = $sd if ($cd eq '');
$hash->{hmccu}{state}{dpt} = $sd;
$hash->{hmccu}{state}{chn} = $sc;
$hash->{hmccu}{control}{dpt} = $cd;
$hash->{hmccu}{control}{chn} = $cc;
return ($sc, $sd, $cc, $cd);
}

View File

@ -254,7 +254,7 @@ sub HMCCUCHN_Set ($@)
return undef if ($disable == 1);
my $ioHash = $hash->{IODev};
my $hmccu_name = $ioHash->{NAME};
my $ioName = $ioHash->{NAME};
if (HMCCU_IsRPCStateBlocking ($ioHash)) {
return undef if ($opt eq '?');
return "HMCCUCHN: CCU busy";
@ -274,7 +274,7 @@ sub HMCCUCHN_Set ($@)
# Log commands
HMCCU_Log ($hash, 3, "set $name $opt ".join (' ', @$a))
if ($opt ne '?' && $ccuflags =~ /logCommand/ || HMCCU_IsFlag ($hmccu_name, 'logCommand'));
if ($opt ne '?' && $ccuflags =~ /logCommand/ || HMCCU_IsFlag ($ioName, 'logCommand'));
if ($opt eq 'datapoint') {
my $usage = "Usage: set $name datapoint {{datapoint} {value} | {datapoint}={value}} [...]";
@ -329,7 +329,7 @@ sub HMCCUCHN_Set ($@)
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif (exists($stateCmds{$opt})) {
return HMCCU_SetError ($hash, -13) if ($sd eq '');
return HMCCU_SetError ($hash, -14) if ($cd eq '');
return HMCCU_SetError ($hash, -8)
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $cd, 2));
@ -340,7 +340,8 @@ sub HMCCUCHN_Set ($@)
}
elsif ($opt eq 'toggle') {
return HMCCU_SetError ($hash, -15) if ($stateVals eq '');
return HMCCU_SetError ($hash, -13) if ($cd eq '');
return HMCCU_SetError ($hash, -12) if ($cc eq '');
return HMCCU_SetError ($hash, -14) if ($cd eq '');
return HMCCU_SetError ($hash, -8)
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $cd, 2));
@ -427,7 +428,7 @@ sub HMCCUCHN_Set ($@)
return HMCCU_SetError ($hash, -15) if ($stateVals eq '');
return HMCCU_SetError ($hash, "No state value for 'on' defined")
if (!exists($stateCmds{"on"}));
return HMCCU_SetError ($hash, -13) if ($cd eq '');
return HMCCU_SetError ($hash, -14) if ($cd eq '');
return HMCCU_SetError ($hash, -8)
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $cd, 2));
return HMCCU_SetError ($hash, "Can't find ON_TIME datapoint for device type")
@ -504,15 +505,22 @@ sub HMCCUCHN_Set ($@)
return HMCCU_SetError ($hash, "Receiver $receiver is not a HMCCUCHN or HMCCUDEV device");
}
}
elsif (!HMCCU_IsChnAddr ($receiver, 0)) {
my ($rcvAdd, $rcvChn) = HMCCU_GetAddress ($ioHash, $receiver, '', '');
return HMCCU_SetError ($hash, "$receiver is not a valid CCU channel name")
if ($rcvAdd eq '' || $rcvChn eq '');
$receiver = "$rcvAdd:$rcvChn";
}
return HMCCU_SetError ($hash, "$receiver is not a link receiver of $name")
if (!HMCCU_IsValidReceiver ($ioHash, $ccuaddr, $ccuif, $receiver));
push @rcvList, $receiver;
}
else {
push @rcvList, HMCCU_GetReceivers ($ioHash, $ccuaddr, $ccuif);
}
return HMCCU_SetError ($hash, "$receiver is not a link receiver of $name")
if (!HMCCU_IsValidReceiver ($ioHash, $ccuaddr, $ccuif, $receiver));
my $devDesc = HMCCU_GetDeviceDesc ($ioHash, $ccuaddr, $ccuif);
return HMCCU_SetError ($hash, "Can't get device description")
if (!defined($devDesc));
@ -568,7 +576,7 @@ sub HMCCUCHN_Get ($@)
return undef if ($disable == 1);
my $ioHash = $hash->{IODev};
my $hmccu_name = $ioHash->{NAME};
my $ioName = $ioHash->{NAME};
if (HMCCU_IsRPCStateBlocking ($ioHash)) {
return undef if ($opt eq '?');
return "HMCCUCHN: CCU busy";
@ -577,7 +585,6 @@ sub HMCCUCHN_Get ($@)
my $ccutype = $hash->{ccutype};
my $ccuaddr = $hash->{ccuaddr};
my $ccuif = $hash->{ccuif};
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', 'STATE', '', '');
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my $result = '';
@ -585,7 +592,7 @@ sub HMCCUCHN_Get ($@)
# Log commands
HMCCU_Log ($hash, 3, "get $name $opt ".join (' ', @$a))
if ($opt ne '?' && $ccuflags =~ /logCommand/ || HMCCU_IsFlag ($hmccu_name, 'logCommand'));
if ($opt ne '?' && $ccuflags =~ /logCommand/ || HMCCU_IsFlag ($ioName, 'logCommand'));
if ($opt eq 'datapoint') {
my $objname = shift @$a;
@ -768,8 +775,9 @@ sub HMCCUCHN_Get ($@)
</li><br/>
<li><b>set &lt;name&gt; link &lt;receiver&gt; [&lt;channel&gt;] &lt;parameter&gt;=&lt;value&gt;[:&lt;type&gt;]</b><br/>
Set multiple link parameters (parameter set LINK). Parameter <i>receiver</i> is the
name of a FHEM device of type HMCCUDEV or HMCCUCHN or a channel address. For FHEM
devices of type HMCCUDEV a <i>channel</i> number must be specified. Parameter <i>parameter</i> must be a valid
name of a FHEM device of type HMCCUDEV or HMCCUCHN or a channel address or a CCU
channel name. For FHEM devices of type HMCCUDEV a <i>channel</i> number must be specified.
Parameter <i>parameter</i> must be a valid
link configuration parameter name. If <i>type</i> is not specified, it's taken from
parameter set definition. The default <i>type</i> is STRING.
Valid types are STRING, BOOL, INTEGER, FLOAT, DOUBLE.

View File

@ -389,7 +389,10 @@ sub HMCCUDEV_Set ($@)
my $ccuif = $hash->{ccuif};
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
my $statevals = AttrVal ($name, 'statevals', '');
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', 'STATE', '', '');
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash, '', '', '', '');
my $stateVals = HMCCU_GetStateValues ($hash, $cd, 2);
my %stateCmds = split (/[:,]/, $stateVals);
my @states = keys %stateCmds;
my $result = '';
my $rc;
@ -455,44 +458,33 @@ sub HMCCUDEV_Set ($@)
);
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt =~ /^($hash->{hmccu}{statevals})$/) {
my $cmd = $1;
my $objvalue = ($cmd ne 'devstate') ? $cmd : shift @$a;
elsif (exists($stateCmds{$opt})) {
return HMCCU_SetError ($hash, -12) if ($cc eq '');
return HMCCU_SetError ($hash, -14) if ($cd eq '');
return HMCCU_SetError ($hash, -8)
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $cd, 2));
return HMCCU_SetError ($hash, -11) if ($sc eq '');
return HMCCU_SetError ($hash, -13) if ($sd eq '');
return HMCCU_SetError ($hash, "Usage: set $name devstate {value}") if (!defined ($objvalue));
$objvalue =~ s/\\_/%20/g;
$rc = HMCCU_SetMultipleDatapoints ($hash,
{ "001.$ccuif.$ccuaddr:$sc.$sd" => HMCCU_Substitute ($objvalue, $statevals, 1, undef, '') }
{ "001.$ccuif.$ccuaddr:$cc.$cd" => $stateCmds{$opt} }
);
return HMCCU_SetError ($hash, min(0, $rc));
}
elsif ($opt eq 'toggle') {
return HMCCU_SetError ($hash, -15) if ($statevals eq '' || !exists($hash->{hmccu}{statevals}));
return HMCCU_SetError ($hash, -11) if ($sc eq '');
return HMCCU_SetError ($hash, -13) if ($sd eq '');
return HMCCU_SetError ($hash, -8) if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $sc, $sd, 2));
return HMCCU_SetError ($hash, -15) if ($stateVals eq '');
return HMCCU_SetError ($hash, -12) if ($cc eq '');
return HMCCU_SetError ($hash, -14) if ($cd eq '');
return HMCCU_SetError ($hash, -8)
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $cc, $cd, 2));
my $tstates = $hash->{hmccu}{statevals};
$tstates =~ s/devstate\|//;
my @states = split /\|/, $tstates;
my $stc = scalar (@states);
my $curState = defined($hash->{hmccu}{dp}{"$cc.$cd"}{VALUES}{SVAL}) ?
$hash->{hmccu}{dp}{"$cc.$cd"}{VALUES}{SVAL} : $states[0];
my $objname = $ccuif.'.'.$ccuaddr.':'.$sc.'.'.$sd;
# Read current value of datapoint without updating reading
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname, 1);
Log3 $name, 2, "HMCCU: set toggle: GetDatapoint returned $rc, $result"
if ($ccuflags =~ /trace/);
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
my $objvalue = '';
my $newState = '';
my $st = 0;
while ($st < $stc) {
if ($states[$st] eq $result) {
$objvalue = ($st == $stc-1) ? $states[0] : $states[$st+1];
if ($states[$st] eq $curState) {
$newState = ($st == $stc-1) ? $states[0] : $states[$st+1];
last;
}
else {
@ -500,11 +492,11 @@ sub HMCCUDEV_Set ($@)
}
}
return HMCCU_SetError ($hash, "Current device state doesn't match statevals")
if ($objvalue eq '');
return HMCCU_SetError ($hash, "Current device state doesn't match any state value")
if ($newState eq '');
$rc = HMCCU_SetMultipleDatapoints ($hash,
{ "001.$objname" => HMCCU_Substitute ($objvalue, $statevals, 1, undef, '') }
{ "001.$ccuif.$ccuaddr:$cc.$cd" => $stateCmds{$newState} }
);
return HMCCU_SetError ($hash, min(0, $rc));
}