mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-07 19:04:20 +00:00
HMCCU: Update for version 4.4 beta
git-svn-id: https://svn.fhem.de/fhem/trunk@22102 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
d5d226b682
commit
10037472af
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id: 88_HMCCUCHN.pm 18552 2019-02-10 11:52:28Z zap $
|
||||
#
|
||||
# Version 4.4.016
|
||||
# Version 4.4.019
|
||||
#
|
||||
# (c) 2020 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
@ -39,22 +39,22 @@ sub HMCCUCHN_Initialize ($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{DefFn} = "HMCCUCHN_Define";
|
||||
$hash->{UndefFn} = "HMCCUCHN_Undef";
|
||||
$hash->{RenameFn} = "HMCCUCHN_Rename";
|
||||
$hash->{SetFn} = "HMCCUCHN_Set";
|
||||
$hash->{GetFn} = "HMCCUCHN_Get";
|
||||
$hash->{AttrFn} = "HMCCUCHN_Attr";
|
||||
$hash->{DefFn} = 'HMCCUCHN_Define';
|
||||
$hash->{UndefFn} = 'HMCCUCHN_Undef';
|
||||
$hash->{RenameFn} = 'HMCCUCHN_Rename';
|
||||
$hash->{SetFn} = 'HMCCUCHN_Set';
|
||||
$hash->{GetFn} = 'HMCCUCHN_Get';
|
||||
$hash->{AttrFn} = 'HMCCUCHN_Attr';
|
||||
$hash->{parseParams} = 1;
|
||||
|
||||
$hash->{AttrList} = "IODev ccucalculate ".
|
||||
"ccuflags:multiple-strict,ackState,logCommand,noReadings,trace,showMasterReadings,showLinkReadings,showDeviceReadings ".
|
||||
"ccureadingfilter ".
|
||||
"ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ".
|
||||
"ccureadingname:textField-long ccuSetOnChange ccuReadingPrefix ".
|
||||
"ccuscaleval ccuverify:0,1,2 ccuget:State,Value controldatapoint ".
|
||||
"disable:0,1 hmstatevals:textField-long statedatapoint statevals substitute:textField-long ".
|
||||
"substexcl stripnumber peer:textField-long ". $readingFnAttributes;
|
||||
$hash->{AttrList} = 'IODev ccucalculate '.
|
||||
'ccuflags:multiple-strict,ackState,logCommand,noReadings,trace,showMasterReadings,showLinkReadings,showDeviceReadings '.
|
||||
'ccureadingfilter:textField-long '.
|
||||
'ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc '.
|
||||
'ccureadingname:textField-long ccuSetOnChange ccuReadingPrefix '.
|
||||
'ccuscaleval ccuverify:0,1,2 ccuget:State,Value controldatapoint '.
|
||||
'disable:0,1 hmstatevals:textField-long statedatapoint statevals substitute:textField-long '.
|
||||
'substexcl stripnumber peer:textField-long '. $readingFnAttributes;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
@ -69,9 +69,7 @@ sub HMCCUCHN_Define ($@)
|
||||
my $usage = "Usage: define $name HMCCUCHN {device} ['readonly'] ['noDefaults'|'defaults'] [iodev={iodevname}]";
|
||||
return $usage if (@$a < 3);
|
||||
|
||||
my $devname = shift @$a;
|
||||
my $devtype = shift @$a;
|
||||
my $devspec = shift @$a;
|
||||
my ($devname, $devtype, $devspec) = splice (@$a, 0, 3);
|
||||
my $ioHash;
|
||||
|
||||
my $existDev = HMCCU_ExistsClientDevice ($devspec, $devtype);
|
||||
@ -81,25 +79,25 @@ sub HMCCUCHN_Define ($@)
|
||||
$hash->{hmccu}{devspec} = $devspec;
|
||||
|
||||
# Defaults
|
||||
$hash->{readonly} = "no";
|
||||
$hash->{readonly} = 'no';
|
||||
$hash->{hmccu}{channels} = 1;
|
||||
$hash->{hmccu}{defaults} = 0;
|
||||
|
||||
# Parse optional command line parameters
|
||||
my $n = 0;
|
||||
while (my $arg = shift @$a) {
|
||||
return $usage if ($n == 3);
|
||||
if ($arg eq 'readonly') { $hash->{readonly} = "yes"; }
|
||||
if ($arg eq 'readonly') { $hash->{readonly} = "yes"; }
|
||||
elsif (lc($arg) eq 'nodefaults' && $init_done) { $hash->{hmccu}{nodefaults} = 1; }
|
||||
elsif ($arg eq 'defaults' && $init_done) { $hash->{hmccu}{nodefaults} = 0; }
|
||||
else { return $usage; }
|
||||
elsif ($arg eq 'defaults' && $init_done) { $hash->{hmccu}{nodefaults} = 0; }
|
||||
else { return $usage; }
|
||||
$n++;
|
||||
}
|
||||
|
||||
# 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');
|
||||
if (exists($h->{iodev})) {
|
||||
return "Device $h->{iodev} does not exist" if (!exists($defs{$h->{iodev}}));
|
||||
return "Type of device $h->{iodev} is not HMCCU" if ($defs{$h->{iodev}}->{TYPE} ne 'HMCCU');
|
||||
$ioHash = $defs{$h->{iodev}};
|
||||
}
|
||||
else {
|
||||
@ -111,18 +109,15 @@ sub HMCCUCHN_Define ($@)
|
||||
# Interactive define command while CCU not ready or no IO device defined
|
||||
if (!defined($ioHash)) {
|
||||
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";
|
||||
}
|
||||
return $ccuinactive > 0 ?
|
||||
'CCU and/or IO device not ready. Please try again later' :
|
||||
'Cannot detect IO device';
|
||||
}
|
||||
}
|
||||
else {
|
||||
# CCU not ready during FHEM start
|
||||
if (!defined ($ioHash) || $ioHash->{ccustate} ne 'active') {
|
||||
Log3 $name, 2, "HMCCUCHN: [$devname] Cannot detect IO device, maybe CCU not ready. Trying later ...";
|
||||
if (!defined($ioHash) || $ioHash->{ccustate} ne 'active') {
|
||||
HMCCU_Log ($hash, 2, 'Cannot detect IO device, maybe CCU not ready. Trying later ...');
|
||||
$hash->{ccudevstate} = 'pending';
|
||||
return undef;
|
||||
}
|
||||
@ -130,8 +125,8 @@ sub HMCCUCHN_Define ($@)
|
||||
|
||||
# Initialize FHEM device, set IO device
|
||||
my $rc = HMCCUCHN_InitDevice ($ioHash, $hash);
|
||||
return "Invalid or unknown CCU channel name or address" if ($rc == 1);
|
||||
return "Can't assign I/O device ".$ioHash->{NAME} if ($rc == 2);
|
||||
return 'Invalid or unknown CCU channel name or address' if ($rc == 1);
|
||||
return "Can't assign I/O device $ioHash->{NAME}" if ($rc == 2);
|
||||
|
||||
return undef;
|
||||
}
|
||||
@ -152,22 +147,23 @@ sub HMCCUCHN_InitDevice ($$)
|
||||
return 1 if (!HMCCU_IsValidChannel ($ioHash, $devspec, 7));
|
||||
|
||||
my ($di, $da, $dn, $dt, $dc) = HMCCU_GetCCUDeviceParam ($ioHash, $devspec);
|
||||
return 1 if (!defined ($da));
|
||||
return 1 if (!defined($da));
|
||||
|
||||
# Inform HMCCU device about client device
|
||||
return 2 if (!HMCCU_AssignIODevice ($devHash, $ioHash->{NAME}, undef));
|
||||
return 2 if (!HMCCU_AssignIODevice ($devHash, $ioHash->{NAME}));
|
||||
|
||||
$devHash->{ccuif} = $di;
|
||||
$devHash->{ccuaddr} = $da;
|
||||
$devHash->{ccuname} = $dn;
|
||||
$devHash->{ccutype} = $dt;
|
||||
$devHash->{ccudevstate} = 'active';
|
||||
$devHash->{ccuif} = $di;
|
||||
$devHash->{ccuaddr} = $da;
|
||||
$devHash->{ccuname} = $dn;
|
||||
$devHash->{ccutype} = $dt;
|
||||
$devHash->{ccudevstate} = 'active';
|
||||
|
||||
if ($init_done) {
|
||||
# Interactive device definition
|
||||
HMCCU_AddDevice ($ioHash, $di, $da, $devHash->{NAME});
|
||||
HMCCU_UpdateDevice ($ioHash, $devHash);
|
||||
HMCCU_UpdateDeviceRoles ($ioHash, $devHash);
|
||||
HMCCU_UpdateRoleCommands ($ioHash, $devHash);
|
||||
if (!exists($devHash->{hmccu}{nodefaults}) || $devHash->{hmccu}{nodefaults} == 0) {
|
||||
if (!HMCCU_SetDefaultAttributes ($devHash)) {
|
||||
HMCCU_SetDefaults ($devHash);
|
||||
@ -217,19 +213,17 @@ sub HMCCUCHN_Attr ($@)
|
||||
my ($cmd, $name, $attrname, $attrval) = @_;
|
||||
my $hash = $defs{$name};
|
||||
|
||||
if ($cmd eq "set") {
|
||||
return "Missing attribute value" if (!defined ($attrval));
|
||||
if ($cmd eq 'set') {
|
||||
return 'Missing attribute value' if (!defined($attrval));
|
||||
if ($attrname eq 'IODev') {
|
||||
$hash->{IODev} = $defs{$attrval};
|
||||
}
|
||||
elsif ($attrname eq 'statevals') {
|
||||
return "Device is read only" if ($hash->{readonly} eq 'yes');
|
||||
return 'Device is read only' if ($hash->{readonly} eq 'yes');
|
||||
}
|
||||
}
|
||||
|
||||
if ($init_done) {
|
||||
HMCCU_RefreshReadings ($hash);
|
||||
}
|
||||
HMCCU_RefreshReadings ($hash) if ($init_done);
|
||||
|
||||
return undef;
|
||||
}
|
||||
@ -242,24 +236,20 @@ sub HMCCUCHN_Set ($@)
|
||||
{
|
||||
my ($hash, $a, $h) = @_;
|
||||
my $name = shift @$a;
|
||||
my $opt = shift @$a;
|
||||
|
||||
return 'No set command specified' if (!defined($opt));
|
||||
my $opt = shift @$a // return 'No set command specified';
|
||||
$opt = lc($opt);
|
||||
|
||||
# Check device state
|
||||
return undef if (!defined($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' ||
|
||||
!defined($hash->{IODev}));
|
||||
return undef if ($hash->{readonly} eq 'yes' && $opt ne '?' &&
|
||||
$opt !~ /^(clear|config|defaults)$/);
|
||||
return undef if (AttrVal ($name, 'disable', 0) == 1);
|
||||
return "Device state doesn't allow set commands"
|
||||
if (!defined($hash->{ccudevstate}) ||
|
||||
$hash->{ccudevstate} eq 'pending' || !defined($hash->{IODev}) ||
|
||||
($hash->{readonly} eq 'yes' && $opt !~ /^(\?|clear|config|defaults)$/) ||
|
||||
AttrVal ($name, 'disable', 0) == 1);
|
||||
|
||||
my $ioHash = $hash->{IODev};
|
||||
my $ioName = $ioHash->{NAME};
|
||||
if (HMCCU_IsRPCStateBlocking ($ioHash)) {
|
||||
return undef if ($opt eq '?');
|
||||
return 'HMCCUCHN: CCU busy';
|
||||
}
|
||||
return ($opt eq '?' ? undef : 'Cannot perform set commands. CCU busy')
|
||||
if (HMCCU_IsRPCStateBlocking ($ioHash));
|
||||
|
||||
my $ccutype = $hash->{ccutype};
|
||||
my $ccuaddr = $hash->{ccuaddr};
|
||||
@ -269,58 +259,31 @@ sub HMCCUCHN_Set ($@)
|
||||
# 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 %pset = ('V' => 'VALUES', 'M' => 'MASTER', 'D' => 'MASTER');
|
||||
my $cmdList = '';
|
||||
my %valLookup;
|
||||
foreach my $cmd (keys %$roleCmds) {
|
||||
$cmdList .= " $cmd";
|
||||
my @setList = split (/\s+/, $roleCmds->{$cmd});
|
||||
foreach my $set (@setList) {
|
||||
my ($ps, $dpt, $par) = split(/:/, $set);
|
||||
my @argList = ();
|
||||
if ($par =~ /^#/) {
|
||||
my $adr = $ccuaddr;
|
||||
$adr =~ s/:[0-9]{1,2}$//;
|
||||
my $paramDef = HMCCU_GetParamDef ($ioHash, $adr, $pset{$ps}, $dpt);
|
||||
if (defined($paramDef)) {
|
||||
if ($paramDef->{TYPE} eq 'ENUM' && defined($paramDef->{VALUE_LIST})) {
|
||||
$par = $paramDef->{VALUE_LIST};
|
||||
$par =~ s/[ ]+/-/g;
|
||||
@argList = split (',', $par);
|
||||
while (my ($i, $e) = each(@argList)) { $valLookup{$pset{$ps}}{$dpt}{$e} = $i; }
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($par !~ /^\?/) {
|
||||
@argList = split (',', $par);
|
||||
}
|
||||
$cmdList .= scalar(@argList) > 1 ? ":$par" : ":noArg";
|
||||
}
|
||||
}
|
||||
|
||||
# Get additional commands, including state commands
|
||||
my $cmdList = $hash->{hmccu}{cmdlist} // '';
|
||||
|
||||
# Get state values related to control command and datapoint
|
||||
my $stateVals = HMCCU_GetStateValues ($hash, $cd);
|
||||
my @stateCmdList = split (/[:,]/, $stateVals);
|
||||
my %stateCmds = @stateCmdList;
|
||||
my @states = keys %stateCmds;
|
||||
|
||||
# Some commands require a control datapoint
|
||||
if ($opt =~ /^(control|toggle|on-for-timer|on-till)$/) {
|
||||
return HMCCU_SetError ($hash, -14) if ($cd eq '');
|
||||
return HMCCU_SetError ($hash, -8) if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $cd, 2));
|
||||
}
|
||||
|
||||
my $result = '';
|
||||
my $rc;
|
||||
|
||||
# Log commands
|
||||
HMCCU_Log ($hash, 3, "set $name $opt ".join (' ', @$a))
|
||||
if ($opt ne '?' && $ccuflags =~ /logCommand/ || HMCCU_IsFlag ($ioName, 'logCommand'));
|
||||
|
||||
|
||||
if ($opt eq 'control') {
|
||||
return HMCCU_SetError ($hash, -14) if ($cd eq '');
|
||||
my $value = shift @$a;
|
||||
return HMCCU_SetError ($hash, "Usage: set $name control {value}") if (!defined($value));
|
||||
|
||||
my $value = shift @$a // return HMCCU_SetError ($hash, "Usage: set $name control {value}");
|
||||
$value =~ s/\\_/%20/g;
|
||||
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash,
|
||||
{ "001.$ccuif.$ccuaddr.$cd" => HMCCU_Substitute ($value, $stateVals, 1, undef, '') }
|
||||
);
|
||||
@ -331,14 +294,13 @@ sub HMCCUCHN_Set ($@)
|
||||
my %dpval;
|
||||
my $i = 0;
|
||||
|
||||
push (@$a, %${h}) if (defined($h));
|
||||
while (my $objname = shift @$a) {
|
||||
my $objvalue = shift @$a;
|
||||
$i++;
|
||||
|
||||
return HMCCU_SetError ($hash, $usage) if (!defined ($objvalue));
|
||||
my $objvalue = shift @$a // return HMCCU_SetError ($hash, $usage);
|
||||
return HMCCU_SetError ($hash, -8)
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $objname, 2));
|
||||
|
||||
$i++;
|
||||
my $no = sprintf ("%03d", $i);
|
||||
$objvalue =~ s/\\_/%20/g;
|
||||
$objvalue = HMCCU_Substitute ($objvalue, $stateVals, 1, undef, '')
|
||||
@ -346,36 +308,17 @@ sub HMCCUCHN_Set ($@)
|
||||
$dpval{"$no.$ccuif.$ccuaddr.$objname"} = $objvalue;
|
||||
}
|
||||
|
||||
if (defined($h)) {
|
||||
foreach my $objname (keys %$h) {
|
||||
my $objvalue = $h->{$objname};
|
||||
$i++;
|
||||
my $no = sprintf ("%03d", $i);
|
||||
return HMCCU_SetError ($hash, -8)
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $objname, 2));
|
||||
$objvalue =~ s/\\_/%20/g;
|
||||
$objvalue = HMCCU_Substitute ($objvalue, $stateVals, 1, undef, '')
|
||||
if ($stateVals ne '' && $objname eq $cd);
|
||||
$dpval{"$no.$ccuif.$ccuaddr.$objname"} = $objvalue;
|
||||
}
|
||||
}
|
||||
|
||||
return HMCCU_SetError ($hash, $usage) if (scalar (keys %dpval) < 1);
|
||||
return HMCCU_SetError ($hash, $usage) if (scalar(keys %dpval) < 1);
|
||||
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, \%dpval);
|
||||
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
|
||||
}
|
||||
elsif ($opt eq 'toggle') {
|
||||
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, $ccuaddr, $cd, 2));
|
||||
|
||||
my $stc = scalar (@states);
|
||||
return HMCCU_SetError ($hash, -15) if ($stc == 0);
|
||||
|
||||
my $curState = defined($hash->{hmccu}{dp}{"$cc.$cd"}{VALUES}{SVAL}) ?
|
||||
$hash->{hmccu}{dp}{"$cc.$cd"}{VALUES}{SVAL} : $states[0];
|
||||
|
||||
my $newState = '';
|
||||
my $st = 0;
|
||||
while ($st < $stc) {
|
||||
@ -383,9 +326,7 @@ sub HMCCUCHN_Set ($@)
|
||||
$newState = ($st == $stc-1) ? $states[0] : $states[$st+1];
|
||||
last;
|
||||
}
|
||||
else {
|
||||
$st++;
|
||||
}
|
||||
$st++;
|
||||
}
|
||||
|
||||
return HMCCU_SetError ($hash, "Current device state doesn't match any state value")
|
||||
@ -396,122 +337,8 @@ sub HMCCUCHN_Set ($@)
|
||||
);
|
||||
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
|
||||
}
|
||||
elsif (defined($roleCmds) && exists($roleCmds->{$opt})) {
|
||||
my $value;
|
||||
my %dpval;
|
||||
my %cfval;
|
||||
|
||||
my @setList = split (/\s+/, $roleCmds->{$opt});
|
||||
my $i = 0;
|
||||
foreach my $set (@setList) {
|
||||
my ($ps, $dpt, $par) = split(/:/, $set);
|
||||
|
||||
return HMCCU_SetError ($hash, "Syntax error in definition of command $opt")
|
||||
if (!defined($par));
|
||||
if (!HMCCU_IsValidParameter ($hash, $ccuaddr, $pset{$ps}, $dpt)) {
|
||||
HMCCU_Trace ($hash, 2, "Set", "Invalid parameter $ps $dpt");
|
||||
return HMCCU_SetError ($hash, -8);
|
||||
}
|
||||
|
||||
if ($par =~ /^\?(.+)$/) {
|
||||
$par = $1;
|
||||
my ($parName, $parDef) = split ('=', $par);
|
||||
$value = shift @$a;
|
||||
if (!defined($value) && defined($parDef)) {
|
||||
if ($parDef =~ /^[+-][0-9]+$/) {
|
||||
return HMCCU_SetError ($hash, "Current value of $cc.$dpt not available")
|
||||
if (!defined($hash->{hmccu}{dp}{"$cc.$dpt"}{$pset{$ps}}{SVAL}));
|
||||
$value = $hash->{hmccu}{dp}{"$cc.$dpt"}{$pset{$ps}}{SVAL}+int($parDef);
|
||||
}
|
||||
else {
|
||||
$value = $parDef;
|
||||
}
|
||||
}
|
||||
|
||||
return HMCCU_SetError ($hash, "Missing parameter $parName")
|
||||
if (!defined($value));
|
||||
}
|
||||
else {
|
||||
if (exists($valLookup{$ps}{$dpt})) {
|
||||
return HMCCU_SetError ($hash, "Illegal value $par. Use one of ".join(',', keys %{$valLookup{$ps}{$dpt}}))
|
||||
if (!exists($valLookup{$ps}{$dpt}{$par}));
|
||||
$value = $valLookup{$ps}{$dpt}{$par};
|
||||
}
|
||||
else {
|
||||
$value = $par;
|
||||
}
|
||||
}
|
||||
|
||||
if ($opt eq 'pct' || $opt eq 'level') {
|
||||
my $timespec = shift @$a;
|
||||
my $ramptime = shift @$a;
|
||||
|
||||
# Set on time
|
||||
if (defined ($timespec)) {
|
||||
return HMCCU_SetError ($hash, "Can't find ON_TIME datapoint for device type $ccutype")
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "ON_TIME", 2));
|
||||
if ($timespec =~ /^[0-9]{2}:[0-9]{2}/) {
|
||||
$timespec = HMCCU_GetTimeSpec ($timespec);
|
||||
return HMCCU_SetError ($hash, "Wrong time format. Use HH:MM[:SS]") if ($timespec < 0);
|
||||
}
|
||||
$dpval{"001.$ccuif.$ccuaddr.ON_TIME"} = $timespec if ($timespec > 0);
|
||||
}
|
||||
|
||||
# Set ramp time
|
||||
if (defined($ramptime)) {
|
||||
return HMCCU_SetError ($hash, "Can't find RAMP_TIME datapoint for device type $ccutype")
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "RAMP_TIME", 2));
|
||||
$dpval{"002.$ccuif.$ccuaddr.RAMP_TIME"} = $ramptime if (defined ($ramptime));
|
||||
}
|
||||
|
||||
$dpval{"003.$ccuif.$ccuaddr.$dpt"} = $value;
|
||||
last;
|
||||
}
|
||||
else {
|
||||
if ($ps eq 'V') {
|
||||
my $no = sprintf ("%03d", $i);
|
||||
$dpval{"$i.$ccuif.$ccuaddr.$dpt"} = $value;
|
||||
$i++;
|
||||
}
|
||||
else {
|
||||
$cfval{$dpt} = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %dpval) > 0) {
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, \%dpval);
|
||||
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
|
||||
}
|
||||
if (scalar(keys %cfval) > 0) {
|
||||
($rc, $result) = HMCCU_SetMultipleParameters ($hash, $ccuaddr, $h, 'MASTER');
|
||||
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
|
||||
}
|
||||
}
|
||||
elsif ($opt eq 'on-for-timer' || $opt eq 'on-till') {
|
||||
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, -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")
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "ON_TIME", 2));
|
||||
|
||||
my $timespec = shift @$a;
|
||||
return HMCCU_SetError ($hash, "Usage: set $name $opt {ontime-spec}")
|
||||
if (!defined ($timespec));
|
||||
|
||||
if ($opt eq 'on-till') {
|
||||
$timespec = HMCCU_GetTimeSpec ($timespec);
|
||||
return HMCCU_SetError ($hash, "Wrong time format. Use HH:MM[:SS]") if ($timespec < 0);
|
||||
}
|
||||
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, {
|
||||
"001.$ccuif.$ccuaddr.ON_TIME" => $timespec,
|
||||
"002.$ccuif.$ccuaddr.$cd" => $stateCmds{"on"}
|
||||
});
|
||||
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
|
||||
elsif (exists($hash->{hmccu}{roleCmds}{$opt})) {
|
||||
return HMCCU_ExecuteRoleCommand ($ioHash, $hash, $opt, $a, $h);
|
||||
}
|
||||
elsif ($opt eq 'clear') {
|
||||
my $rnexp = shift @$a;
|
||||
@ -569,7 +396,7 @@ sub HMCCUCHN_Set ($@)
|
||||
}
|
||||
}
|
||||
elsif (!HMCCU_IsChnAddr ($receiver, 0)) {
|
||||
my ($rcvAdd, $rcvChn) = HMCCU_GetAddress ($ioHash, $receiver, '', '');
|
||||
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";
|
||||
@ -583,18 +410,18 @@ sub HMCCUCHN_Set ($@)
|
||||
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
|
||||
}
|
||||
elsif ($opt eq 'defaults') {
|
||||
$rc = HMCCU_SetDefaultAttributes ($hash);
|
||||
my $mode = shift @$a // 'update';
|
||||
$rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, ctrlChn => $cc });
|
||||
$rc = HMCCU_SetDefaults ($hash) if (!$rc);
|
||||
HMCCU_RefreshReadings ($hash) if ($rc);
|
||||
return HMCCU_SetError ($hash, $rc == 0 ? "No default attributes found" : "OK");
|
||||
}
|
||||
else {
|
||||
my $retmsg = "clear defaults:noArg";
|
||||
my $retmsg = "clear defaults:reset,update";
|
||||
if ($hash->{readonly} ne 'yes') {
|
||||
$retmsg .= " config datapoint".$cmdList;
|
||||
# $retmsg .= ':'.join(',', @states) if (scalar(@states) > 0);
|
||||
$retmsg .= ' config datapoint';
|
||||
$retmsg .= " $cmdList" if ($cmdList ne '');
|
||||
$retmsg .= ' toggle:noArg' if (scalar(@states) > 0);
|
||||
$retmsg .= " on-for-timer on-till"
|
||||
if ($cc ne '' && HMCCU_IsValidDatapoint ($hash, $ccutype, $cc, "ON_TIME", 2));
|
||||
}
|
||||
return AttrTemplate_Set ($hash, $retmsg, $name, $opt, @$a);
|
||||
}
|
||||
@ -608,9 +435,7 @@ sub HMCCUCHN_Get ($@)
|
||||
{
|
||||
my ($hash, $a, $h) = @_;
|
||||
my $name = shift @$a;
|
||||
my $opt = shift @$a;
|
||||
|
||||
return "No get command specified" if (!defined ($opt));
|
||||
my $opt = shift @$a // return 'No get command specified';
|
||||
$opt = lc($opt);
|
||||
|
||||
return undef if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' ||
|
||||
@ -621,15 +446,15 @@ sub HMCCUCHN_Get ($@)
|
||||
|
||||
my $ioHash = $hash->{IODev};
|
||||
my $ioName = $ioHash->{NAME};
|
||||
if (HMCCU_IsRPCStateBlocking ($ioHash)) {
|
||||
return undef if ($opt eq '?');
|
||||
return "HMCCUCHN: CCU busy";
|
||||
}
|
||||
|
||||
return $opt eq '?' ? undef : 'Cannot perform get command. CCU busy'
|
||||
if (HMCCU_IsRPCStateBlocking ($ioHash));
|
||||
|
||||
my $ccutype = $hash->{ccutype};
|
||||
my $ccuaddr = $hash->{ccuaddr};
|
||||
my $ccuif = $hash->{ccuif};
|
||||
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
|
||||
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash);
|
||||
|
||||
my $result = '';
|
||||
my $rc;
|
||||
@ -639,33 +464,20 @@ sub HMCCUCHN_Get ($@)
|
||||
if ($opt ne '?' && $ccuflags =~ /logCommand/ || HMCCU_IsFlag ($ioName, 'logCommand'));
|
||||
|
||||
if ($opt eq 'datapoint') {
|
||||
my $objname = shift @$a;
|
||||
|
||||
return HMCCU_SetError ($hash, "Usage: get $name datapoint {datapoint}")
|
||||
if (!defined ($objname));
|
||||
my $objname = shift @$a // return HMCCU_SetError ($hash, "Usage: get $name datapoint {datapoint}");
|
||||
return HMCCU_SetError ($hash, -8)
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, $objname, 1));
|
||||
|
||||
$objname = $ccuif.'.'.$ccuaddr.'.'.$objname;
|
||||
($rc, $result) = HMCCU_GetDatapoint ($hash, $objname, 0);
|
||||
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
|
||||
return $result;
|
||||
return $rc < 0 ? HMCCU_SetError ($hash, $rc, $result) : $result;
|
||||
}
|
||||
# elsif ($opt eq 'update') {
|
||||
# my $ccuget = shift @$a;
|
||||
# $ccuget = 'Attr' if (!defined ($ccuget));
|
||||
# if ($ccuget !~ /^(Attr|State|Value)$/) {
|
||||
# return HMCCU_SetError ($hash, "Usage: get $name update [{'State'|'Value'}]");
|
||||
# }
|
||||
# $rc = HMCCU_GetUpdate ($hash, $ccuaddr, $ccuget);
|
||||
# return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
# return undef;
|
||||
# }
|
||||
elsif ($opt eq 'deviceinfo') {
|
||||
my ($a, $c) = HMCCU_SplitChnAddr ($ccuaddr);
|
||||
$result = HMCCU_GetDeviceInfo ($hash, $a);
|
||||
return HMCCU_SetError ($hash, -2) if ($result eq '');
|
||||
return HMCCU_SetError ($hash, -2) if ($result eq '');
|
||||
my $devInfo = HMCCU_FormatDeviceInfo ($result);
|
||||
$devInfo .= "StateDatapoint = $sc.$sd\nControlDatapoint = $cc.$cd";
|
||||
return $devInfo;
|
||||
}
|
||||
elsif ($opt =~ /^(config|values|update)$/) {
|
||||
@ -711,10 +523,10 @@ sub HMCCUCHN_Get ($@)
|
||||
$res .= "Device $da\n";
|
||||
foreach my $dc (sort keys %{$convRes->{$da}}) {
|
||||
foreach my $ps (sort keys %{$convRes->{$da}{$dc}}) {
|
||||
$res .= " Channel $dc [$ps]\n";
|
||||
$res .= join ("\n", map {
|
||||
" ".$_.' = '.$convRes->{$da}{$dc}{$ps}{$_}
|
||||
} sort keys %{$convRes->{$da}{$dc}{$ps}})."\n";
|
||||
$res .= " Channel $dc [$ps]\n".
|
||||
join ("\n", map {
|
||||
" ".$_.' = '.$convRes->{$da}{$dc}{$ps}{$_}
|
||||
} sort keys %{$convRes->{$da}{$dc}{$ps}})."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -734,6 +546,10 @@ sub HMCCUCHN_Get ($@)
|
||||
elsif ($opt eq 'defaults') {
|
||||
return HMCCU_GetDefaults ($hash, 0);
|
||||
}
|
||||
elsif ($opt eq 'weekprogram') {
|
||||
my $program = shift @$a;
|
||||
return HMCCU_DisplayWeekProgram ($hash, $program);
|
||||
}
|
||||
else {
|
||||
my $retmsg = "HMCCUCHN: Unknown argument $opt, choose one of defaults:noArg datapoint";
|
||||
|
||||
@ -743,6 +559,8 @@ sub HMCCUCHN_Get ($@)
|
||||
$retmsg .= ":".join(",",@valuelist) if ($valuecount > 0);
|
||||
$retmsg .= " update:noArg deviceInfo:noArg config:noArg".
|
||||
" deviceDesc:noArg paramsetDesc:noArg values:noArg";
|
||||
$retmsg .= ' weekProgram:all,'.join(',', sort keys %{$hash->{hmccu}{tt}})
|
||||
if (exists($hash->{hmccu}{tt}));
|
||||
|
||||
return $retmsg;
|
||||
}
|
||||
@ -753,7 +571,7 @@ sub HMCCUCHN_Get ($@)
|
||||
|
||||
=pod
|
||||
=item device
|
||||
=item summary controls HMCCU client devices for Homematic CCU2 - FHEM integration
|
||||
=item summary controls HMCCU client devices for Homematic CCU2/3 - FHEM integration
|
||||
=begin html
|
||||
|
||||
<a name="HMCCUCHN"></a>
|
||||
@ -816,9 +634,12 @@ sub HMCCUCHN_Get ($@)
|
||||
<code>set temp_control datapoint SET_TEMPERATURE 21</code><br/>
|
||||
<code>set temp_control datapoint AUTO_MODE 1 SET_TEMPERATURE 21</code>
|
||||
</li><br/>
|
||||
<li><b>set <name> defaults</b><br/>
|
||||
<li><b>set <name> defaults ['reset'|'<u>update</u>']</b><br/>
|
||||
Set default attributes for CCU device type. Default attributes are only available for
|
||||
some device types and for some channels of a device type.
|
||||
some device types and for some channels of a device type. If option 'reset' is specified,
|
||||
the following attributes are deleted before the new attributes are set:
|
||||
'ccureadingname', 'ccuscaleval', 'eventMap', 'substexcl', 'webCmd', 'widgetOverride'.
|
||||
During update to version 4.4 it's recommended to use option 'reset'.
|
||||
</li><br/>
|
||||
<li><b>set <name> down [<value>]</b><br/>
|
||||
Decrement value of datapoint LEVEL. This command is only available if channel contains
|
||||
@ -948,6 +769,9 @@ sub HMCCUCHN_Get ($@)
|
||||
</li><br/>
|
||||
<li><b>get <name> values</b><br/>
|
||||
Same as 'get update' but using RPC instead of ReGa.
|
||||
</li><br/>
|
||||
<li><b>get <name> weekProgram [<program-number>|<u>all</u>]</b><br/>
|
||||
Display week programs. This command is only available if a device supports week programs.
|
||||
</li>
|
||||
</ul>
|
||||
<br/>
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id: 88_HMCCUDEV.pm 18552 2019-02-10 11:52:28Z zap $
|
||||
#
|
||||
# Version 4.4.016
|
||||
# Version 4.4.022
|
||||
#
|
||||
# (c) 2020 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
@ -38,21 +38,22 @@ sub HMCCUDEV_Initialize ($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{DefFn} = "HMCCUDEV_Define";
|
||||
$hash->{UndefFn} = "HMCCUCHN_Undef";
|
||||
$hash->{RenameFn} = "HMCCUDEV_Rename";
|
||||
$hash->{SetFn} = "HMCCUDEV_Set";
|
||||
$hash->{GetFn} = "HMCCUDEV_Get";
|
||||
$hash->{AttrFn} = "HMCCUDEV_Attr";
|
||||
$hash->{DefFn} = 'HMCCUDEV_Define';
|
||||
$hash->{UndefFn} = 'HMCCUCHN_Undef';
|
||||
$hash->{RenameFn} = 'HMCCUDEV_Rename';
|
||||
$hash->{SetFn} = 'HMCCUDEV_Set';
|
||||
$hash->{GetFn} = 'HMCCUDEV_Get';
|
||||
$hash->{AttrFn} = 'HMCCUDEV_Attr';
|
||||
$hash->{parseParams} = 1;
|
||||
|
||||
$hash->{AttrList} = "IODev ccuaggregate:textField-long ccucalculate:textField-long ".
|
||||
"ccuflags:multiple-strict,ackState,logCommand,nochn0,noReadings,trace ccureadingfilter:textField-long ".
|
||||
"ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ".
|
||||
"ccureadingname:textField-long ".
|
||||
"ccuget:State,Value ccuscaleval ccuSetOnChange ccuverify:0,1,2 disable:0,1 ".
|
||||
"hmstatevals:textField-long statevals substexcl substitute:textField-long statechannel ".
|
||||
"controlchannel statedatapoint controldatapoint stripnumber peer:textField-long ".
|
||||
$hash->{AttrList} = 'IODev ccuaggregate:textField-long ccucalculate:textField-long '.
|
||||
'ccuflags:multiple-strict,ackState,logCommand,noReadings,trace,showMasterReadings,showLinkReadings,showDeviceReadings '.
|
||||
'ccureadingfilter:textField-long '.
|
||||
'ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc '.
|
||||
'ccureadingname:textField-long ccuSetOnChange ccuReadingPrefix '.
|
||||
'ccuget:State,Value ccuscaleval ccuverify:0,1,2 disable:0,1 '.
|
||||
'hmstatevals:textField-long statevals substexcl substitute:textField-long statechannel '.
|
||||
'controlchannel statedatapoint controldatapoint stripnumber peer:textField-long '.
|
||||
$readingFnAttributes;
|
||||
}
|
||||
|
||||
@ -68,7 +69,7 @@ sub HMCCUDEV_Define ($@)
|
||||
my $usage = "Usage: define $name HMCCUDEV {device|'virtual'} [control-channel] ".
|
||||
"['readonly'] ['noDefaults'|'defaults'] [iodev={iodev-name}] [address={virtual-device-no}]".
|
||||
"[{groupexp=regexp|group={device|channel}[,...]]";
|
||||
return $usage if (scalar (@$a) < 3);
|
||||
return $usage if (scalar(@$a) < 3);
|
||||
|
||||
my @errmsg = (
|
||||
"OK",
|
||||
@ -81,47 +82,37 @@ sub HMCCUDEV_Define ($@)
|
||||
"Too many virtual devices"
|
||||
);
|
||||
|
||||
my $devname = shift @$a;
|
||||
my $devtype = shift @$a;
|
||||
my $devspec = shift @$a;
|
||||
|
||||
my ($devname, $devtype, $devspec) = splice (@$a, 0, 3);
|
||||
my $ioHash = undef;
|
||||
|
||||
# my $existDev = HMCCU_ExistsClientDevice ($devspec, $devtype);
|
||||
# return "FHEM device $existDev for CCU device $devspec already exists" if (defined($existDev));
|
||||
|
||||
# Store some definitions for delayed initialization
|
||||
$hash->{readonly} = 'no';
|
||||
$hash->{hmccu}{devspec} = $devspec;
|
||||
$hash->{hmccu}{groupexp} = $h->{groupexp} if (exists ($h->{groupexp}));
|
||||
$hash->{hmccu}{group} = $h->{group} if (exists ($h->{group}));
|
||||
$hash->{hmccu}{defaults} = 0;
|
||||
|
||||
if (exists ($h->{address})) {
|
||||
if ($init_done || $devspec ne 'virtual') {
|
||||
return "Option address not allowed";
|
||||
}
|
||||
else {
|
||||
$hash->{hmccu}{address} = $h->{address};
|
||||
}
|
||||
if (exists($h->{address})) {
|
||||
return 'Option address not allowed' if ($init_done || $devspec ne 'virtual');
|
||||
$hash->{hmccu}{address} = $h->{address};
|
||||
}
|
||||
else {
|
||||
return "Option address not specified" if (!$init_done && $devspec eq 'virtual');
|
||||
return 'Option address not specified' if (!$init_done && $devspec eq 'virtual');
|
||||
}
|
||||
|
||||
# Parse optional command line parameters
|
||||
foreach my $arg (@$a) {
|
||||
if ($arg eq 'readonly') { $hash->{readonly} = 'yes'; }
|
||||
if ($arg eq 'readonly') { $hash->{readonly} = 'yes'; }
|
||||
elsif (lc($arg) eq 'nodefaults' && $init_done) { $hash->{hmccu}{nodefaults} = 1; }
|
||||
elsif ($arg eq 'defaults' && $init_done) { $hash->{hmccu}{nodefaults} = 0; }
|
||||
elsif ($arg =~ /^[0-9]+$/) { $attr{$name}{controlchannel} = $arg; }
|
||||
else { return $usage; }
|
||||
elsif ($arg eq 'defaults' && $init_done) { $hash->{hmccu}{nodefaults} = 0; }
|
||||
elsif ($arg =~ /^[0-9]+$/) { $attr{$name}{controlchannel} = $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');
|
||||
if (exists($h->{iodev})) {
|
||||
return "IO device $h->{iodev} does not exist" if (!exists($defs{$h->{iodev}}));
|
||||
return "Type of device $h->{iodev} is not HMCCU" if ($defs{$h->{iodev}}->{TYPE} ne 'HMCCU');
|
||||
$ioHash = $defs{$h->{iodev}};
|
||||
}
|
||||
else {
|
||||
@ -133,18 +124,14 @@ sub HMCCUDEV_Define ($@)
|
||||
# Interactive define command while CCU not ready
|
||||
if (!defined($ioHash)) {
|
||||
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";
|
||||
}
|
||||
return $ccuinactive > 0 ? 'CCU and/or IO device not ready. Please try again later' :
|
||||
'Cannot detect IO device';
|
||||
}
|
||||
}
|
||||
else {
|
||||
# CCU not ready during FHEM start
|
||||
if (!defined($ioHash) || $ioHash->{ccustate} ne 'active') {
|
||||
Log3 $name, 2, "HMCCUDEV: [$devname] Cannot detect IO device, maybe CCU not ready. Trying later ...";
|
||||
HMCCU_Log ($hash, 2, 'Cannot detect IO device, maybe CCU not ready. Trying later ...');
|
||||
$hash->{ccudevstate} = 'pending';
|
||||
return undef;
|
||||
}
|
||||
@ -152,7 +139,7 @@ sub HMCCUDEV_Define ($@)
|
||||
|
||||
# Initialize FHEM device, set IO device
|
||||
my $rc = HMCCUDEV_InitDevice ($ioHash, $hash);
|
||||
return $errmsg[$rc] if ($rc > 0);
|
||||
return $errmsg[$rc] if ($rc > 0 && $rc < scalar(@errmsg));
|
||||
|
||||
return undef;
|
||||
}
|
||||
@ -180,7 +167,7 @@ sub HMCCUDEV_InitDevice ($$)
|
||||
|
||||
if ($devspec eq 'virtual') {
|
||||
my $no = 0;
|
||||
if (exists ($devHash->{hmccu}{address})) {
|
||||
if (exists($devHash->{hmccu}{address})) {
|
||||
# Only true during FHEM start
|
||||
$no = $devHash->{hmccu}{address};
|
||||
}
|
||||
@ -198,11 +185,11 @@ sub HMCCUDEV_InitDevice ($$)
|
||||
}
|
||||
|
||||
# Inform HMCCU device about client device
|
||||
return 2 if (!HMCCU_AssignIODevice ($devHash, $ioHash->{NAME}, undef));
|
||||
return 2 if (!HMCCU_AssignIODevice ($devHash, $ioHash->{NAME}));
|
||||
|
||||
$devHash->{ccuif} = 'fhem';
|
||||
$devHash->{ccuaddr} = sprintf ("VIR%07d", $no);
|
||||
$devHash->{ccuname} = $name;
|
||||
$devHash->{ccuif} = 'fhem';
|
||||
$devHash->{ccuaddr} = sprintf ("VIR%07d", $no);
|
||||
$devHash->{ccuname} = $name;
|
||||
$devHash->{ccudevstate} = 'active';
|
||||
}
|
||||
else {
|
||||
@ -213,13 +200,13 @@ sub HMCCUDEV_InitDevice ($$)
|
||||
$gdname = $dn;
|
||||
|
||||
# Inform HMCCU device about client device
|
||||
return 2 if (!HMCCU_AssignIODevice ($devHash, $ioHash->{NAME}, undef));
|
||||
return 2 if (!HMCCU_AssignIODevice ($devHash, $ioHash->{NAME}));
|
||||
|
||||
$devHash->{ccuif} = $di;
|
||||
$devHash->{ccuaddr} = $da;
|
||||
$devHash->{ccuname} = $dn;
|
||||
$devHash->{ccutype} = $dt;
|
||||
$devHash->{ccudevstate} = 'active';
|
||||
$devHash->{ccuif} = $di;
|
||||
$devHash->{ccuaddr} = $da;
|
||||
$devHash->{ccuname} = $dn;
|
||||
$devHash->{ccutype} = $dt;
|
||||
$devHash->{ccudevstate} = 'active';
|
||||
$devHash->{hmccu}{channels} = $dc;
|
||||
|
||||
if ($init_done) {
|
||||
@ -227,6 +214,7 @@ sub HMCCUDEV_InitDevice ($$)
|
||||
HMCCU_AddDevice ($ioHash, $di, $da, $devHash->{NAME});
|
||||
HMCCU_UpdateDevice ($ioHash, $devHash);
|
||||
HMCCU_UpdateDeviceRoles ($ioHash, $devHash);
|
||||
HMCCU_UpdateRoleCommands ($ioHash, $devHash, $attr{$devHash->{NAME}}{controlchannel});
|
||||
if (!exists($devHash->{hmccu}{nodefaults}) || $devHash->{hmccu}{nodefaults} == 0) {
|
||||
if (!HMCCU_SetDefaultAttributes ($devHash)) {
|
||||
HMCCU_SetDefaults ($devHash);
|
||||
@ -246,17 +234,12 @@ sub HMCCUDEV_InitDevice ($$)
|
||||
}
|
||||
elsif (exists ($devHash->{hmccu}{group})) {
|
||||
# Group devices specified by comma separated name list
|
||||
my @gdevlist = split (",", $devHash->{hmccu}{group});
|
||||
$devHash->{ccugroup} = '' if (@gdevlist > 0);
|
||||
my @gdevlist = split (',', $devHash->{hmccu}{group});
|
||||
$devHash->{ccugroup} = '' if (scalar(@gdevlist) > 0);
|
||||
foreach my $gd (@gdevlist) {
|
||||
my ($gda, $gdc, $gdo) = ('', '', '', '');
|
||||
|
||||
return 1 if (!HMCCU_IsValidDevice ($ioHash, $gd, 7));
|
||||
|
||||
($gda, $gdc) = HMCCU_GetAddress ($ioHash, $gd, '', '');
|
||||
$gdo = $gda;
|
||||
$gdo .= ':'.$gdc if ($gdc ne '');
|
||||
push @devlist, $gdo;
|
||||
my ($gda, $gdc) = HMCCU_GetAddress ($ioHash, $gd);
|
||||
push @devlist, $gdc eq '' ? "$gda:$gdc" : $gda;
|
||||
$gdcount++;
|
||||
}
|
||||
}
|
||||
@ -310,9 +293,7 @@ sub HMCCUDEV_Undef ($$)
|
||||
|
||||
if ($hash->{IODev}) {
|
||||
HMCCU_RemoveDevice ($hash->{IODev}, $hash->{ccuif}, $hash->{ccuaddr}, $hash->{NAME});
|
||||
if ($hash->{ccuif} eq 'fhem') {
|
||||
HMCCU_DeleteDevice ($hash->{IODev});
|
||||
}
|
||||
HMCCU_DeleteDevice ($hash->{IODev}) if ($hash->{ccuif} eq 'fhem');
|
||||
}
|
||||
|
||||
return undef;
|
||||
@ -351,9 +332,7 @@ sub HMCCUDEV_Attr ($@)
|
||||
}
|
||||
}
|
||||
|
||||
if ($init_done) {
|
||||
HMCCU_RefreshReadings ($hash);
|
||||
}
|
||||
HMCCU_RefreshReadings ($hash) if ($init_done);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -366,24 +345,19 @@ sub HMCCUDEV_Set ($@)
|
||||
{
|
||||
my ($hash, $a, $h) = @_;
|
||||
my $name = shift @$a;
|
||||
my $opt = shift @$a;
|
||||
|
||||
return 'No set command specified' if (!defined($opt));
|
||||
my $opt = shift @$a // return 'No set command specified';
|
||||
$opt = lc($opt);
|
||||
|
||||
# Check device state
|
||||
return undef if (!defined($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' ||
|
||||
!defined($hash->{IODev}));
|
||||
return undef if ($hash->{readonly} eq 'yes' && $opt ne '?' && $opt !~ /^(clear|config|defaults)$/);
|
||||
return undef if (AttrVal ($name, 'disable', 0) == 1);
|
||||
return "Device state doesn't allow set commands"
|
||||
if (!defined($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' || !defined($hash->{IODev}) ||
|
||||
($hash->{readonly} eq 'yes' && $opt !~ /^(\?|clear|config|defaults)$/) ||
|
||||
AttrVal ($name, 'disable', 0) == 1);
|
||||
|
||||
my $ioHash = $hash->{IODev};
|
||||
my $hmccu_name = $ioHash->{NAME};
|
||||
|
||||
# Check if CCU is busy
|
||||
if (HMCCU_IsRPCStateBlocking ($ioHash)) {
|
||||
return undef if ($opt eq '?');
|
||||
return 'HMCCUDEV: CCU busy';
|
||||
}
|
||||
my $ioName = $ioHash->{NAME};
|
||||
return ($opt eq '?' ? undef : 'Cannot perform set commands. CCU busy')
|
||||
if (HMCCU_IsRPCStateBlocking ($ioHash));
|
||||
|
||||
# Get parameters of current device
|
||||
my $ccutype = $hash->{ccutype};
|
||||
@ -393,36 +367,9 @@ sub HMCCUDEV_Set ($@)
|
||||
|
||||
# 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 %pset = ('V' => 'VALUES', 'M' => 'MASTER', 'D' => 'MASTER');
|
||||
my $cmdList = '';
|
||||
my %valLookup;
|
||||
foreach my $cmd (keys %$roleCmds) {
|
||||
$cmdList .= " $cmd";
|
||||
my @setList = split (/\s+/, $roleCmds->{$cmd});
|
||||
foreach my $set (@setList) {
|
||||
my ($ps, $dpt, $par) = split(/:/, $set);
|
||||
my @argList = ();
|
||||
if ($par =~ /^#/) {
|
||||
my $paramDef = HMCCU_GetParamDef ($ioHash, $ccuaddr, $pset{$ps}, $dpt);
|
||||
if (defined($paramDef)) {
|
||||
if ($paramDef->{TYPE} eq 'ENUM' && defined($paramDef->{VALUE_LIST})) {
|
||||
$par = $paramDef->{VALUE_LIST};
|
||||
$par =~ s/[ ]+/-/g;
|
||||
@argList = split (',', $par);
|
||||
while (my ($i, $e) = each(@argList)) { $valLookup{$pset{$ps}}{$dpt}{$e} = $i; }
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($par !~ /^\?/) {
|
||||
@argList = split (',', $par);
|
||||
}
|
||||
$cmdList .= scalar(@argList) > 1 ? ":$par" : ":noArg";
|
||||
}
|
||||
}
|
||||
# Get additional commands
|
||||
my $cmdList = $hash->{hmccu}{cmdlist} // '';
|
||||
|
||||
# Get state values related to control command and datapoint
|
||||
my $stateVals = HMCCU_GetStateValues ($hash, $cd, $cc);
|
||||
@ -430,23 +377,24 @@ sub HMCCUDEV_Set ($@)
|
||||
my %stateCmds = @stateCmdList;
|
||||
my @states = keys %stateCmds;
|
||||
|
||||
# Some commands require a control channel and datapoint
|
||||
if ($opt =~ /^(control|toggle|on-for-timer|on-till)$/) {
|
||||
return HMCCU_SetError ($hash, -14) if ($cd eq '');
|
||||
return HMCCU_SetError ($hash, -12) if ($cc eq '');
|
||||
return HMCCU_SetError ($hash, -8) if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $cc, $cd, 2));
|
||||
return HMCCU_SetError ($hash, -7) if ($cc >= $hash->{hmccu}{channels});
|
||||
}
|
||||
|
||||
my $result = '';
|
||||
my $rc;
|
||||
|
||||
# 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 'control') {
|
||||
return HMCCU_SetError ($hash, -12) if ($cc eq '');
|
||||
return HMCCU_SetError ($hash, -14) if ($cd eq '');
|
||||
return HMCCU_SetError ($hash, -7) if ($cc >= $hash->{hmccu}{channels});
|
||||
|
||||
my $value = shift @$a;
|
||||
return HMCCU_SetError ($hash, "Usage: set $name control {value}") if (!defined($value));
|
||||
|
||||
my $value = shift @$a // return HMCCU_SetError ($hash, "Usage: set $name control {value}");
|
||||
$value =~ s/\\_/%20/g;
|
||||
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash,
|
||||
{ "001.$ccuif.$ccuaddr:$cc.$cd" => HMCCU_Substitute ($value, $stateVals, 1, undef, '') }
|
||||
);
|
||||
@ -457,6 +405,7 @@ sub HMCCUDEV_Set ($@)
|
||||
my %dpval;
|
||||
my $i = 0;
|
||||
|
||||
push (@$a, %${h}) if (defined($h));
|
||||
while (my $objname = shift @$a) {
|
||||
my $value = shift @$a;
|
||||
$i += 1;
|
||||
@ -464,24 +413,17 @@ sub HMCCUDEV_Set ($@)
|
||||
if ($ccutype eq 'HM-Dis-EP-WM55' && !defined($value)) {
|
||||
$value = '';
|
||||
foreach my $t (keys %{$h}) {
|
||||
if ($value eq '') {
|
||||
$value = $t.'='.$h->{$t};
|
||||
}
|
||||
else {
|
||||
$value .= ','.$t.'='.$h->{$t};
|
||||
}
|
||||
$value .= $value eq '' ? $t.'='.$h->{$t} : ','.$t.'='.$h->{$t};
|
||||
}
|
||||
}
|
||||
|
||||
return HMCCU_SetError ($hash, $usage) if (!defined ($value) || $value eq '');
|
||||
return HMCCU_SetError ($hash, $usage) if (!defined($value) || $value eq '');
|
||||
|
||||
if ($objname =~ /^([0-9]+)\..+$/) {
|
||||
my $chn = $1;
|
||||
return HMCCU_SetError ($hash, -7) if ($chn >= $hash->{hmccu}{channels});
|
||||
return HMCCU_SetError ($hash, -7) if ($1 >= $hash->{hmccu}{channels});
|
||||
}
|
||||
else {
|
||||
return HMCCU_SetError ($hash, -11) if ($cc eq '');
|
||||
$objname = $cc.'.'.$objname;
|
||||
$objname = "$cc.$objname";
|
||||
}
|
||||
|
||||
my $no = sprintf ("%03d", $i);
|
||||
@ -489,19 +431,15 @@ sub HMCCUDEV_Set ($@)
|
||||
$dpval{"$no.$ccuif.$ccuaddr:$objname"} = HMCCU_Substitute ($value, $stateVals, 1, undef, '');
|
||||
}
|
||||
|
||||
return HMCCU_SetError ($hash, $usage) if (scalar (keys %dpval) < 1);
|
||||
return HMCCU_SetError ($hash, $usage) if (scalar(keys %dpval) < 1);
|
||||
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, \%dpval);
|
||||
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
|
||||
}
|
||||
elsif ($opt eq 'toggle') {
|
||||
return HMCCU_SetError ($hash, -12) if ($cc eq '');
|
||||
return HMCCU_SetError ($hash, -14) if ($cd eq '');
|
||||
return HMCCU_SetError ($hash, -15) if ($stateVals eq '');
|
||||
return HMCCU_SetError ($hash, -8)
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $cc, $cd, 2));
|
||||
my $stc = scalar(@states);
|
||||
return HMCCU_SetError ($hash, -15) if ($stc == 0);
|
||||
|
||||
my $stc = scalar (@states);
|
||||
my $curState = defined($hash->{hmccu}{dp}{"$cc.$cd"}{VALUES}{SVAL}) ?
|
||||
$hash->{hmccu}{dp}{"$cc.$cd"}{VALUES}{SVAL} : $states[0];
|
||||
|
||||
@ -512,9 +450,7 @@ sub HMCCUDEV_Set ($@)
|
||||
$newState = ($st == $stc-1) ? $states[0] : $states[$st+1];
|
||||
last;
|
||||
}
|
||||
else {
|
||||
$st++;
|
||||
}
|
||||
$st++;
|
||||
}
|
||||
|
||||
return HMCCU_SetError ($hash, "Current device state doesn't match any state value")
|
||||
@ -525,126 +461,8 @@ sub HMCCUDEV_Set ($@)
|
||||
);
|
||||
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
|
||||
}
|
||||
elsif (defined($roleCmds) && exists($roleCmds->{$opt})) {
|
||||
return HMCCU_SetError ($hash, -12) if ($cc eq '');
|
||||
return HMCCU_SetError ($hash, -14) if ($cd eq '');
|
||||
|
||||
my $value;
|
||||
my %dpval;
|
||||
my %cfval;
|
||||
|
||||
my @setList = split (/\s+/, $roleCmds->{$opt});
|
||||
my $i = 0;
|
||||
foreach my $set (@setList) {
|
||||
my ($ps, $dpt, $par) = split(/:/, $set);
|
||||
|
||||
return HMCCU_SetError ($hash, "Syntax error in definition of command $opt")
|
||||
if (!defined($par));
|
||||
if (!HMCCU_IsValidParameter ($hash, $ccuaddr, $pset{$ps}, $dpt)) {
|
||||
HMCCU_Trace ($hash, 2, "Set", "Invalid parameter $ps $dpt");
|
||||
return HMCCU_SetError ($hash, -8);
|
||||
}
|
||||
|
||||
# Check if parameter is required
|
||||
if ($par =~ /^\?(.+)$/) {
|
||||
$par = $1;
|
||||
# Consider default value for parameter
|
||||
my ($parName, $parDef) = split ('=', $par);
|
||||
$value = shift @$a;
|
||||
if (!defined($value) && defined($parDef)) {
|
||||
if ($parDef =~ /^[+-][0-9]+$/) {
|
||||
return HMCCU_SetError ($hash, "Current value of $cc.$dpt not available")
|
||||
if (!defined($hash->{hmccu}{dp}{"$cc.$dpt"}{$pset{$ps}}{SVAL}));
|
||||
$value = $hash->{hmccu}{dp}{"$cc.$dpt"}{$pset{$ps}}{SVAL}+int($parDef);
|
||||
}
|
||||
else {
|
||||
$value = $parDef;
|
||||
}
|
||||
}
|
||||
|
||||
return HMCCU_SetError ($hash, "Missing parameter $parName")
|
||||
if (!defined($value));
|
||||
}
|
||||
else {
|
||||
if (exists($valLookup{$ps}{$dpt})) {
|
||||
return HMCCU_SetError ($hash, "Illegal value $par. Use one of ".join(',', keys %{$valLookup{$ps}{$dpt}}))
|
||||
if (!exists($valLookup{$ps}{$dpt}{$par}));
|
||||
$value = $valLookup{$ps}{$dpt}{$par};
|
||||
}
|
||||
else {
|
||||
$value = $par;
|
||||
}
|
||||
}
|
||||
|
||||
if ($opt eq 'pct' || $opt eq 'level') {
|
||||
my $timespec = shift @$a;
|
||||
my $ramptime = shift @$a;
|
||||
|
||||
# Set on time
|
||||
if (defined ($timespec)) {
|
||||
return HMCCU_SetError ($hash, "Can't find ON_TIME datapoint for device type $ccutype")
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "ON_TIME", 2));
|
||||
if ($timespec =~ /^[0-9]{2}:[0-9]{2}/) {
|
||||
$timespec = HMCCU_GetTimeSpec ($timespec);
|
||||
return HMCCU_SetError ($hash, "Wrong time format. Use HH:MM[:SS]") if ($timespec < 0);
|
||||
}
|
||||
$dpval{"001.$ccuif.$ccuaddr.$cc.ON_TIME"} = $timespec if ($timespec > 0);
|
||||
}
|
||||
|
||||
# Set ramp time
|
||||
if (defined($ramptime)) {
|
||||
return HMCCU_SetError ($hash, "Can't find RAMP_TIME datapoint for device type $ccutype")
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $ccuaddr, "RAMP_TIME", 2));
|
||||
$dpval{"002.$ccuif.$ccuaddr.$cc.RAMP_TIME"} = $ramptime if (defined ($ramptime));
|
||||
}
|
||||
|
||||
$dpval{"003.$ccuif.$ccuaddr.$cc.$dpt"} = $value;
|
||||
last;
|
||||
}
|
||||
else {
|
||||
if ($ps eq 'V') {
|
||||
my $no = sprintf ("%03d", $i);
|
||||
$dpval{"$i.$ccuif.$ccuaddr.$cc.$dpt"} = $value;
|
||||
$i++;
|
||||
}
|
||||
else {
|
||||
$cfval{$dpt} = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %dpval) > 0) {
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, \%dpval);
|
||||
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
|
||||
}
|
||||
if (scalar(keys %cfval) > 0) {
|
||||
($rc, $result) = HMCCU_SetMultipleParameters ($hash, $ccuaddr, $h, 'MASTER');
|
||||
return HMCCU_SetError ($hash, HMCCU_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, "No state value for 'on' defined")
|
||||
if ("on" !~ /($hash->{hmccu}{statevals})/);
|
||||
return HMCCU_SetError ($hash, -12) if ($cc eq '');
|
||||
return HMCCU_SetError ($hash, -14) if ($cd eq '');
|
||||
return HMCCU_SetError ($hash, "Can't find ON_TIME datapoint for device type")
|
||||
if (!HMCCU_IsValidDatapoint ($hash, $ccutype, $cc, 'ON_TIME', 2));
|
||||
|
||||
my $timespec = shift @$a;
|
||||
return HMCCU_SetError ($hash, "Usage: set $name $opt {ontime-spec}")
|
||||
if (!defined ($timespec));
|
||||
|
||||
if ($opt eq 'on-till') {
|
||||
$timespec = HMCCU_GetTimeSpec ($timespec);
|
||||
return HMCCU_SetError ($hash, 'Wrong time format. Use HH:MM[:SS]') if ($timespec < 0);
|
||||
}
|
||||
|
||||
$rc = HMCCU_SetMultipleDatapoints ($hash, {
|
||||
"001.$ccuif.$ccuaddr:$cc.ON_TIME" => $timespec,
|
||||
"002.$ccuif.$ccuaddr:$cc.$cd" => HMCCU_Substitute ('on', $stateVals, 1, undef, '')
|
||||
});
|
||||
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
|
||||
elsif (exists($hash->{hmccu}{roleCmds}{$opt})) {
|
||||
return HMCCU_ExecuteRoleCommand ($ioHash, $hash, $opt, $a, $h);
|
||||
}
|
||||
elsif ($opt eq 'clear') {
|
||||
my $rnexp = shift @$a;
|
||||
@ -673,13 +491,12 @@ sub HMCCUDEV_Set ($@)
|
||||
}
|
||||
|
||||
my $devDesc = HMCCU_GetDeviceDesc ($ioHash, $ccuobj, $ccuif);
|
||||
return HMCCU_SetError ($hash, "Can't get device description")
|
||||
if (!defined($devDesc));
|
||||
return HMCCU_SetError ($hash, "Can't get device description") if (!defined($devDesc));
|
||||
return HMCCU_SetError ($hash, "Paramset $paramset not supported by device or channel")
|
||||
if ($devDesc->{PARAMSETS} !~ /$paramset/);
|
||||
if (!HMCCU_IsValidParameter ($ioHash, $devDesc, $paramset, $h)) {
|
||||
my @parList = HMCCU_GetParamDef ($ioHash, $devDesc, $paramset);
|
||||
return HMCCU_SetError ($hash, "Invalid parameter specified. Valid parameters are ".
|
||||
return HMCCU_SetError ($hash, 'Invalid parameter specified. Valid parameters are '.
|
||||
join(',', @parList));
|
||||
}
|
||||
|
||||
@ -691,7 +508,7 @@ sub HMCCUDEV_Set ($@)
|
||||
my $clHash = $defs{$receiver};
|
||||
if ($clHash->{TYPE} eq 'HMCCUDEV') {
|
||||
my $chnNo = shift @$a;
|
||||
return HMCCU_SetError ($hash, "Channel number required for link receiver")
|
||||
return HMCCU_SetError ($hash, 'Channel number required for link receiver')
|
||||
if (!defined($chnNo) || $chnNo !~ /^[0-9]{1,2}$/);
|
||||
$receiver = $clHash->{ccuaddr}.":$chnNo";
|
||||
}
|
||||
@ -703,7 +520,7 @@ sub HMCCUDEV_Set ($@)
|
||||
}
|
||||
}
|
||||
elsif (!HMCCU_IsChnAddr ($receiver, 0)) {
|
||||
my ($rcvAdd, $rcvChn) = HMCCU_GetAddress ($ioHash, $receiver, '', '');
|
||||
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";
|
||||
@ -711,27 +528,25 @@ sub HMCCUDEV_Set ($@)
|
||||
|
||||
return HMCCU_SetError ($hash, "$receiver is not a link receiver of $name")
|
||||
if (!HMCCU_IsValidReceiver ($ioHash, $ccuaddr, $ccuif, $receiver));
|
||||
($rc, $result) = HMCCU_RPCRequest ($hash, "putParamset", $ccuaddr, $receiver, $h);
|
||||
($rc, $result) = HMCCU_RPCRequest ($hash, 'putParamset', $ccuaddr, $receiver, $h);
|
||||
}
|
||||
|
||||
return HMCCU_SetError ($hash, HMCCU_Min(0, $rc));
|
||||
}
|
||||
elsif ($opt eq 'defaults') {
|
||||
$rc = HMCCU_SetDefaultAttributes ($hash, $cc);
|
||||
my $mode = shift @$a // 'update';
|
||||
$rc = HMCCU_SetDefaultAttributes ($hash, { mode => $mode, role => undef, ctrlChn => $cc });
|
||||
$rc = HMCCU_SetDefaults ($hash) if (!$rc);
|
||||
return HMCCU_SetError ($hash, $rc == 0 ? "No default attributes found" : "OK");
|
||||
HMCCU_RefreshReadings ($hash) if ($rc);
|
||||
return HMCCU_SetError ($hash, $rc == 0 ? 'No default attributes found' : 'OK');
|
||||
}
|
||||
else {
|
||||
my $retmsg = "clear defaults:noArg";
|
||||
my $retmsg = 'clear defaults:reset,update';
|
||||
|
||||
if ($hash->{readonly} ne 'yes') {
|
||||
$retmsg .= " datapoint rpcparameter";
|
||||
if ($sc ne '') {
|
||||
$retmsg .= " config datapoint".$cmdList;
|
||||
$retmsg .= " toggle:noArg" if (scalar(@states) > 0);
|
||||
$retmsg .= " on-for-timer on-till"
|
||||
if ($cc ne '' && HMCCU_IsValidDatapoint ($hash, $hash->{ccutype}, $cc, "ON_TIME", 2));
|
||||
}
|
||||
$retmsg .= ' config datapoint';
|
||||
$retmsg .= " $cmdList" if ($cmdList ne '');
|
||||
$retmsg .= ' toggle:noArg' if (scalar(@states) > 0);
|
||||
}
|
||||
return AttrTemplate_Set ($hash, $retmsg, $name, $opt, @$a);
|
||||
}
|
||||
@ -745,27 +560,20 @@ sub HMCCUDEV_Get ($@)
|
||||
{
|
||||
my ($hash, $a, $h) = @_;
|
||||
my $name = shift @$a;
|
||||
my $opt = shift @$a;
|
||||
|
||||
return "No get command specified" if (!defined ($opt));
|
||||
my $opt = shift @$a // return 'No get command specified';
|
||||
$opt = lc($opt);
|
||||
|
||||
# Get I/O device
|
||||
return undef if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' ||
|
||||
!defined ($hash->{IODev}));
|
||||
return "Device state doesn't allow set commands"
|
||||
if (!defined ($hash->{ccudevstate}) || $hash->{ccudevstate} eq 'pending' ||
|
||||
!defined ($hash->{IODev}) || AttrVal ($name, "disable", 0) == 1);
|
||||
my $ioHash = $hash->{IODev};
|
||||
my $hmccu_name = $ioHash->{NAME};
|
||||
|
||||
# Handle disabled devices
|
||||
my $disable = AttrVal ($name, "disable", 0);
|
||||
return undef if ($disable == 1);
|
||||
my $ioName = $ioHash->{NAME};
|
||||
|
||||
# Check if CCU is busy
|
||||
if (HMCCU_IsRPCStateBlocking ($ioHash)) {
|
||||
return undef if ($opt eq '?');
|
||||
return "HMCCUDEV: CCU busy";
|
||||
}
|
||||
|
||||
return $opt eq '?' ? undef : 'Cannot perform get commands. CCU busy'
|
||||
if (HMCCU_IsRPCStateBlocking ($ioHash));
|
||||
|
||||
# Get parameters of current device
|
||||
my $ccutype = $hash->{ccutype};
|
||||
my $ccuaddr = $hash->{ccuaddr};
|
||||
@ -773,22 +581,19 @@ sub HMCCUDEV_Get ($@)
|
||||
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
|
||||
my ($sc, $sd, $cc, $cd) = HMCCU_GetSpecialDatapoints ($hash);
|
||||
|
||||
# Virtual devices only support command get update
|
||||
return "HMCCUDEV: Unknown argument $opt, choose one of update:noArg"
|
||||
if ($ccuif eq 'fhem' && $opt ne 'update');
|
||||
|
||||
my $result = '';
|
||||
my $rc;
|
||||
|
||||
# Virtual devices only support command get update
|
||||
if ($ccuif eq 'fhem' && $opt ne 'update') {
|
||||
return "HMCCUDEV: Unknown argument $opt, choose one of update:noArg";
|
||||
}
|
||||
|
||||
# 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;
|
||||
return HMCCU_SetError ($hash, "Usage: get $name datapoint [{channel-number}.]{datapoint}")
|
||||
if (!defined ($objname));
|
||||
my $objname = shift @$a // return HMCCU_SetError ($hash, "Usage: get $name datapoint [{channel-number}.]{datapoint}");
|
||||
|
||||
if ($objname =~ /^([0-9]+)\..+$/) {
|
||||
my $chn = $1;
|
||||
@ -809,35 +614,8 @@ sub HMCCUDEV_Get ($@)
|
||||
HMCCU_SetState ($hash, "OK") if (exists ($hash->{STATE}) && $hash->{STATE} eq "Error");
|
||||
return $result;
|
||||
}
|
||||
# elsif ($opt eq 'update') {
|
||||
# my $ccuget = shift @$a;
|
||||
# $ccuget = 'Attr' if (!defined ($ccuget));
|
||||
# if ($ccuget !~ /^(Attr|State|Value)$/) {
|
||||
# return HMCCU_SetError ($hash, "Usage: get $name update [{'State'|'Value'}]");
|
||||
# }
|
||||
#
|
||||
# if ($hash->{ccuif} ne 'fhem') {
|
||||
# $rc = HMCCU_GetUpdate ($hash, $ccuaddr, $ccuget);
|
||||
# return HMCCU_SetError ($hash, $rc) if ($rc < 0);
|
||||
# }
|
||||
# else {
|
||||
# # Update all devices belonging to group
|
||||
# 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;
|
||||
# }
|
||||
elsif ($opt eq 'deviceinfo') {
|
||||
my $ccuget = shift @$a;
|
||||
$ccuget = 'Attr' if (!defined ($ccuget));
|
||||
if ($ccuget !~ /^(Attr|State|Value)$/) {
|
||||
return HMCCU_SetError ($hash, "Usage: get $name deviceinfo [{'State'|'Value'}]");
|
||||
}
|
||||
$result = HMCCU_GetDeviceInfo ($hash, $ccuaddr, $ccuget);
|
||||
$result = HMCCU_GetDeviceInfo ($hash, $ccuaddr);
|
||||
return HMCCU_SetError ($hash, -2) if ($result eq '');
|
||||
my $devInfo = HMCCU_FormatDeviceInfo ($result);
|
||||
$devInfo .= "StateDatapoint = $sc.$sd\nControlDatapoint = $cc.$cd";
|
||||
@ -874,9 +652,12 @@ sub HMCCUDEV_Get ($@)
|
||||
}
|
||||
}
|
||||
else {
|
||||
# The following request could fail if device description or parameter set
|
||||
# description is not correct.
|
||||
($rc, $result) = HMCCU_RPCRequest ($hash, 'getRawParamset', $a, $ps, undef);
|
||||
return HMCCU_SetError ($hash, $rc, $result) if ($rc < 0);
|
||||
foreach my $p (keys %$result) { $objects{$da}{$dc}{$ps}{$p} = $result->{$p}; }
|
||||
if ($rc >= 0) {
|
||||
foreach my $p (keys %$result) { $objects{$da}{$dc}{$ps}{$p} = $result->{$p}; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -889,10 +670,10 @@ sub HMCCUDEV_Get ($@)
|
||||
$res .= "Device $da\n";
|
||||
foreach my $dc (sort keys %{$convRes->{$da}}) {
|
||||
foreach my $ps (sort keys %{$convRes->{$da}{$dc}}) {
|
||||
$res .= " Channel $dc [$ps]\n";
|
||||
$res .= join ("\n", map {
|
||||
" ".$_.' = '.$convRes->{$da}{$dc}{$ps}{$_}
|
||||
} sort keys %{$convRes->{$da}{$dc}{$ps}})."\n";
|
||||
$res .= " Channel $dc [$ps]\n".
|
||||
join ("\n", map {
|
||||
" ".$_.' = '.$convRes->{$da}{$dc}{$ps}{$_}
|
||||
} sort keys %{$convRes->{$da}{$dc}{$ps}})."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -913,6 +694,10 @@ sub HMCCUDEV_Get ($@)
|
||||
$result = HMCCU_GetDefaults ($hash, 0);
|
||||
return $result;
|
||||
}
|
||||
elsif ($opt eq 'weekprogram') {
|
||||
my $program = shift @$a;
|
||||
return HMCCU_DisplayWeekProgram ($hash, $program);
|
||||
}
|
||||
else {
|
||||
my $retmsg = "HMCCUDEV: Unknown argument $opt, choose one of datapoint";
|
||||
|
||||
@ -921,12 +706,13 @@ sub HMCCUDEV_Get ($@)
|
||||
$retmsg .= ':'.join(",", @valuelist) if ($valuecount > 0);
|
||||
$retmsg .= ' defaults:noArg update:noArg config'.
|
||||
' paramsetDesc:noArg deviceDesc:noArg deviceInfo:noArg values:noArg';
|
||||
$retmsg .= ' weekProgram:all,'.join(',', sort keys %{$hash->{hmccu}{tt}})
|
||||
if (exists($hash->{hmccu}{tt}));
|
||||
|
||||
return $retmsg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
@ -1002,9 +788,12 @@ sub HMCCUDEV_Get ($@)
|
||||
<code>set temp_control datapoint 2.SET_TEMPERATURE 21</code><br/>
|
||||
<code>set temp_control datapoint 2.AUTO_MODE 1 2.SET_TEMPERATURE 21</code>
|
||||
</li><br/>
|
||||
<li><b>set <name> defaults</b><br/>
|
||||
<li><b>set <name> defaults ['reset'|'<u>update</u>']</b><br/>
|
||||
Set default attributes for CCU device type. Default attributes are only available for
|
||||
some device types.
|
||||
some device types and for some channels of a device type. If option 'reset' is specified,
|
||||
the following attributes are deleted before the new attributes are set:
|
||||
'ccureadingname', 'ccuscaleval', 'eventMap', 'substexcl', 'webCmd', 'widgetOverride'.
|
||||
During update to version 4.4 it's recommended to use option 'reset'.
|
||||
</li><br/>
|
||||
<li><b>set <name> down [<value>]</b><br/>
|
||||
<a href="#HMCCUCHNset">see HMCCUCHN</a>
|
||||
@ -1018,13 +807,6 @@ sub HMCCUDEV_Get ($@)
|
||||
<li><b>set <name> pct <value;> [<ontime> [<ramptime>]]</b><br/>
|
||||
<a href="#HMCCUCHNset">see HMCCUCHN</a>
|
||||
</li><br/>
|
||||
<li><b>set <name> rpcparameter [<channel>] { VALUES | MASTER | LINK } <parameter>=<value> [...]</b><br/>
|
||||
Set multiple datapoints or config parameters by using RPC interface instead of ReGa.
|
||||
Supports attribute 'ccuscaleval' for datapoints. Methods VALUES (setting datapoints)
|
||||
and LINK require a channel number. For method MASTER (setting parameters) a channel number
|
||||
is optional (setting device parameters). Parameter <i>parameter</i> must be a valid
|
||||
datapoint or config parameter name.
|
||||
</li><br/>
|
||||
<li><b>set <name> <statevalue></b><br/>
|
||||
State datapoint of a CCU device channel is set to 'statevalue'. State channel and state
|
||||
datapoint must be defined as attribute 'statedatapoint'. Values for <i>statevalue</i>
|
||||
@ -1105,6 +887,9 @@ sub HMCCUDEV_Get ($@)
|
||||
<li><b>get <name> update [{State | <u>Value</u>}]</b><br/>
|
||||
<a href="#HMCCUCHNget">see HMCCUCHN</a>
|
||||
</li><br/>
|
||||
<li><b>get <name> weekProgram [<program-number>|<u>all</u>]</b><br/>
|
||||
Display week programs. This command is only available if a device supports week programs.
|
||||
</li>
|
||||
</ul>
|
||||
<br/>
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id: HMCCUConf.pm 18552 2019-02-10 11:52:28Z zap $
|
||||
#
|
||||
# Version 4.8
|
||||
# Version 4.8.002
|
||||
#
|
||||
# Configuration parameters for HomeMatic devices.
|
||||
#
|
||||
@ -100,7 +100,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
# Command-Defintion:
|
||||
# Command => 'Datapoint-Definition [...]'
|
||||
# Datapoint-Definition:
|
||||
# Paramset:Datapoint:FixedValue[,FixedValue]
|
||||
# Paramset:Datapoint:[Parameter=]FixedValue[,FixedValue]
|
||||
# Paramset:Datapoint:?Parameter
|
||||
# Paramset:Datapoint:?Parameter=Default-Value
|
||||
# Paramset:Datapoint:#Parameter
|
||||
@ -115,21 +115,21 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
|
||||
%HMCCU_ROLECMDS = (
|
||||
'MOTIONDETECTOR_TRANSCEIVER' => {
|
||||
'on' => 'V:MOTION_DETECTION_ACTIVE:true',
|
||||
'off' => 'V:MOTION_DETECTION_ACTIVE:false'
|
||||
'on' => 'V:MOTION_DETECTION_ACTIVE:active=true',
|
||||
'off' => 'V:MOTION_DETECTION_ACTIVE:active=false'
|
||||
},
|
||||
'SMOKE_DETECTOR' => {
|
||||
'command' => 'V:SMOKE_DETECTOR_COMMAND:#command'
|
||||
},
|
||||
'KEY' => {
|
||||
'on' => 'V:PRESS_SHORT:true',
|
||||
'off' => 'V:PRESS_SHORT:true',
|
||||
'press' => 'V:PRESS_SHORT:true'
|
||||
'on' => 'V:PRESS_SHORT:1',
|
||||
'off' => 'V:PRESS_SHORT:1',
|
||||
'press' => 'V:PRESS_SHORT:1'
|
||||
},
|
||||
'KEY_TRANSCEIVER' => {
|
||||
'on' => 'V:PRESS_SHORT:true',
|
||||
'off' => 'V:PRESS_SHORT:true',
|
||||
'press' => 'V:PRESS_SHORT:true'
|
||||
'on' => 'V:PRESS_SHORT:1',
|
||||
'off' => 'V:PRESS_SHORT:1',
|
||||
'press' => 'V:PRESS_SHORT:1'
|
||||
},
|
||||
'BLIND' => {
|
||||
'pct' => 'V:LEVEL:?level',
|
||||
@ -137,7 +137,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
'close' => 'V:LEVEL:0',
|
||||
'up' => 'V:LEVEL:?delta=+10',
|
||||
'down' => 'V:LEVEL:?delta=-10',
|
||||
'stop' => 'V:STOP:true'
|
||||
'stop' => 'V:STOP:1'
|
||||
},
|
||||
'BLIND_VIRTUAL_RECEIVER' => {
|
||||
'pct' => 'V:LEVEL:?level',
|
||||
@ -145,7 +145,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
'close' => 'V:LEVEL:0',
|
||||
'up' => 'V:LEVEL:?delta=+10',
|
||||
'down' => 'V:LEVEL:?delta=-10',
|
||||
'stop' => 'V:STOP:true'
|
||||
'stop' => 'V:STOP:1'
|
||||
},
|
||||
'SHUTTER_VIRTUAL_RECEIVER' => {
|
||||
'pct' => 'V:LEVEL:?level',
|
||||
@ -153,30 +153,34 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
'close' => 'V:LEVEL:0',
|
||||
'up' => 'V:LEVEL:?delta=+10',
|
||||
'down' => 'V:LEVEL:?delta=-10',
|
||||
'stop' => 'V:STOP:true'
|
||||
'stop' => 'V:STOP:1'
|
||||
},
|
||||
'SWITCH' => {
|
||||
'on' => 'V:STATE:true',
|
||||
'off' => 'V:STATE:false'
|
||||
'on' => 'V:STATE:1',
|
||||
'off' => 'V:STATE:0',
|
||||
'on-for-timer' => 'V:ON_TIME:?duration V:STATE:1',
|
||||
'on-till' => 'V:ON_TIME:?duration V:STATE:1'
|
||||
},
|
||||
'SWITCH_VIRTUAL_RECEIVER' => {
|
||||
'on' => 'V:STATE:true',
|
||||
'off' => 'V:STATE:false'
|
||||
'on' => 'V:STATE:1',
|
||||
'off' => 'V:STATE:0',
|
||||
'on-for-timer' => 'V:ON_TIME:?duration V:STATE:1',
|
||||
'on-till' => 'V:ON_TIME:?duration V:STATE:1'
|
||||
},
|
||||
'DIMMER' => {
|
||||
'pct' => 'V:LEVEL:?level',
|
||||
'pct' => 'V:LEVEL:?level V:ON_TIME:?time=0.0 V:RAMP_TIME:?ramp=0.5',
|
||||
'on' => 'V:LEVEL:100',
|
||||
'off' => 'V:LEVEL:0',
|
||||
'stop' => 'V:RAMP_STOP:true'
|
||||
'stop' => 'V:RAMP_STOP:1'
|
||||
},
|
||||
'DIMMER_VIRTUAL_RECEIVER' => {
|
||||
'pct' => 'V:LEVEL:?level',
|
||||
'pct' => 'V:LEVEL:?level V:ON_TIME:?time V:RAMP_TIME:?ramp',
|
||||
'on' => 'V:LEVEL:100',
|
||||
'off' => 'V:LEVEL:0'
|
||||
},
|
||||
'THERMALCONTROL_TRANSMIT' => {
|
||||
'desired-temp' => 'V:SET_TEMPERATURE:?temperature',
|
||||
'manu' => 'V:MANU_MODE:?temperature',
|
||||
'manu' => 'V:MANU_MODE:?temperature=20',
|
||||
'on' => 'V:MANU_MODE:30.5',
|
||||
'off' => 'V:MANU_MODE:4.5',
|
||||
'auto' => 'V:AUTO_MODE:1',
|
||||
@ -185,7 +189,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
},
|
||||
'CLIMATECONTROL_RT_TRANSCEIVER' => {
|
||||
'desired-temp' => 'V:SET_TEMPERATURE:?temperature',
|
||||
'manu' => 'V:MANU_MODE:?temperature',
|
||||
'manu' => 'V:MANU_MODE:?temperature=20',
|
||||
'on' => 'V:MANU_MODE:30.5',
|
||||
'off' => 'V:MANU_MODE:4.5',
|
||||
'auto' => 'V:AUTO_MODE:1',
|
||||
@ -196,7 +200,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
'auto' => 'V:CONTROL_MODE:0',
|
||||
'manu' => 'V:CONTROL_MODE:1',
|
||||
'holiday' => 'V:CONTROL_MODE:2',
|
||||
'boost' => 'V:BOOST_MODE:true',
|
||||
'boost' => 'V:BOOST_MODE:1',
|
||||
'on' => 'V:CONTROL_MODE:1 V:SET_POINT_TEMPERATURE:30.5',
|
||||
'off' => 'V:CONTROL_MODE:1 V:SET_POINT_TEMPERATURE:4.5'
|
||||
}
|
||||
@ -243,12 +247,12 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
},
|
||||
'CLIMATECONTROL_RT_TRANSCEIVER' => {
|
||||
'cmdIcon' => 'auto:sani_heating_automatic manu:sani_heating_manual boost:sani_heating_boost on:general_an off:general_aus',
|
||||
'webCmd' => 'desired-temp',
|
||||
'webCmd' => 'desired-temp:auto:manu:boost:on:off',
|
||||
'widgetOverride' => 'desired-temp:slider,4.5,0.5,30.5,1'
|
||||
},
|
||||
'HEATING_CLIMATECONTROL_TRANSCEIVER' => {
|
||||
'cmdIcon' => 'auto:sani_heating_automatic manu:sani_heating_manual boost:sani_heating_boost on:general_an off:general_aus',
|
||||
'webCmd' => 'desired-temp:auto:manu:boost',
|
||||
'webCmd' => 'desired-temp:auto:manu:boost:on:off',
|
||||
'widgetOverride' => 'desired-temp:slider,4.5,0.5,30.5,1'
|
||||
}
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user