mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-16 04:36:02 +00:00
HMCCU: Improved attributes and bugfix
git-svn-id: https://svn.fhem.de/fhem/trunk@15429 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
263e14f63d
commit
27fc994ed2
@ -1,5 +1,6 @@
|
||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||
# Do not insert empty lines here, update check depends on it.
|
||||
- changed: 88_HMCCU: Improved attributes ccureadingfilter, stripnumber
|
||||
- feature: 89_FULLY: New commands for motion detection and brightness
|
||||
- update: 98_Siro.pm: add Disable attribute
|
||||
- bugfix: 50_TelegramBot: fix minusdesc warning / cleanup
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.1.003
|
||||
# Version 4.1.004
|
||||
#
|
||||
# Module for communication between FHEM and Homematic CCU2.
|
||||
#
|
||||
@ -65,10 +65,10 @@
|
||||
# attr <name> rpcserverport <base_port>
|
||||
# attr <name> rpctimeout <read>[,<write>]
|
||||
# attr <name> stripchar <character>
|
||||
# attr <name> stripnumber { -<digits> | 0 | 1 | 2 }
|
||||
# attr <name> stripnumber [<datapoint-expr!]{-<digits>|0|1|2}[;...]
|
||||
# attr <name> substitute <subst_rule>
|
||||
#
|
||||
# filter_rule := [channel-regexp!]datapoint-regexp[,...]
|
||||
# filter_rule := channel-regexp!datapoint-regexp[;...]
|
||||
# subst_rule := [[channel.]datapoint[,...]!]<regexp>:<subtext>[,...][;...]
|
||||
##############################################################################
|
||||
# Verbose levels:
|
||||
@ -105,7 +105,7 @@ my %HMCCU_CUST_CHN_DEFAULTS;
|
||||
my %HMCCU_CUST_DEV_DEFAULTS;
|
||||
|
||||
# HMCCU version
|
||||
my $HMCCU_VERSION = '4.1.003';
|
||||
my $HMCCU_VERSION = '4.1.004';
|
||||
|
||||
# Default RPC port (BidCos-RF)
|
||||
my $HMCCU_RPC_PORT_DEFAULT = 2001;
|
||||
@ -216,7 +216,7 @@ sub HMCCU_AggregateReadings ($$);
|
||||
sub HMCCU_ParseObject ($$$);
|
||||
sub HMCCU_FilterReading ($$$);
|
||||
sub HMCCU_GetReadingName ($$$$$$$);
|
||||
sub HMCCU_FormatReadingValue ($$);
|
||||
sub HMCCU_FormatReadingValue ($$$);
|
||||
sub HMCCU_Trace ($$$$);
|
||||
sub HMCCU_Log ($$$$);
|
||||
sub HMCCU_SetError ($@);
|
||||
@ -512,7 +512,7 @@ sub HMCCU_Attr ($@)
|
||||
# Parse aggregation rules for readings.
|
||||
# Syntax of aggregation rule is:
|
||||
# FilterSpec[;...]
|
||||
# FilterSpec := {Name|Filt|Read|Cond|Else|Pref|Coll}[,...]
|
||||
# FilterSpec := {Name|Filt|Read|Cond|Else|Pref|Coll|Html}[,...]
|
||||
# Name := name:Name
|
||||
# Filt := filter:{name|type|group|room|alias}=Regexp[!Regexp]
|
||||
# Read := read:Regexp
|
||||
@ -520,6 +520,7 @@ sub HMCCU_Attr ($@)
|
||||
# Else := else:Value
|
||||
# Pref := prefix:{RULE|Prefix}
|
||||
# Coll := coll:{NAME|Attribute}
|
||||
# Html := html:Template
|
||||
######################################################################
|
||||
|
||||
sub HMCCU_AggregationRules ($$)
|
||||
@ -547,12 +548,12 @@ sub HMCCU_AggregationRules ($$)
|
||||
# Parse aggregation rule
|
||||
my @specs = split (',', $r);
|
||||
foreach my $spec (@specs) {
|
||||
if ($spec =~ /^(name|filter|read|if|else|prefix|coll):(.+)$/) {
|
||||
if ($spec =~ /^(name|filter|read|if|else|prefix|coll|html):(.+)$/) {
|
||||
$opt{$1} = $2;
|
||||
}
|
||||
}
|
||||
|
||||
# Check if rule syntax is correct
|
||||
# Check if mandatory parameters are specified
|
||||
foreach my $p (@pars) {
|
||||
return HMCCU_Log ($hash, 1, "Parameter $p is missing in aggregation rule $cnt.", 0)
|
||||
if (!exists ($opt{$p}));
|
||||
@ -566,6 +567,46 @@ sub HMCCU_AggregationRules ($$)
|
||||
return 0 if (!defined ($fval));
|
||||
my ($fcoll, $fdflt) = split ('!', $opt{coll});
|
||||
$fdflt = 'no match' if (!defined ($fdflt));
|
||||
my $fhtml = exists ($opt{'html'}) ? $opt{'html'} : '';
|
||||
|
||||
# Read HTML template (optional)
|
||||
if ($fhtml ne '') {
|
||||
my %tdef;
|
||||
my @html;
|
||||
|
||||
# Read template file
|
||||
if (open (TEMPLATE, "<$fhtml")) {
|
||||
@html = <TEMPLATE>;
|
||||
close (TEMPLATE);
|
||||
}
|
||||
else {
|
||||
return HMCCU_Log ($hash, 1, "Can't open file $fhtml.", 0);
|
||||
}
|
||||
|
||||
# Parse template
|
||||
foreach my $line (@html) {
|
||||
chomp $line;
|
||||
my ($key, $h) = split /:/, $line, 2;
|
||||
next if (!defined ($h) || $key =~ /^#/);
|
||||
$tdef{$key} = $h;
|
||||
}
|
||||
|
||||
# Some syntax checks
|
||||
return HMCCU_Log ($hash, 1, "Missing definition row-odd in template file.", 0)
|
||||
if (!exists ($tdef{'row-odd'}));
|
||||
|
||||
# Set default values
|
||||
$tdef{'begin-html'} = '' if (!exists ($tdef{'begin-html'}));
|
||||
$tdef{'end-html'} = '' if (!exists ($tdef{'end-html'}));
|
||||
$tdef{'begin-table'} = "<table>" if (!exists ($tdef{'begin-table'}));
|
||||
$tdef{'end-table'} = "</table>" if (!exists ($tdef{'end-table'}));
|
||||
$tdef{'default'} = 'no data' if (!exists ($tdef{'default'}));;
|
||||
$tdef{'row-even'} = $tdef{'row-odd'} if (!exists ($tdef{'row-even'}));
|
||||
|
||||
foreach my $t (keys %tdef) {
|
||||
$hash->{hmccu}{agg}{$fname}{fhtml}{$t} = $tdef{$t};
|
||||
}
|
||||
}
|
||||
|
||||
$hash->{hmccu}{agg}{$fname}{ftype} = $ftype;
|
||||
$hash->{hmccu}{agg}{$fname}{fexpr} = $fexpr;
|
||||
@ -861,7 +902,7 @@ sub HMCCU_Notify ($$)
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Calculate reading aggregation.
|
||||
# Calculate reading aggregations.
|
||||
# Called by Notify or via command get aggregation.
|
||||
######################################################################
|
||||
|
||||
@ -873,17 +914,18 @@ sub HMCCU_AggregateReadings ($$)
|
||||
my $mc = 0;
|
||||
my $result = '';
|
||||
my $rl = '';
|
||||
my $table = '';
|
||||
|
||||
# Get rule parameters
|
||||
my $ftype = $hash->{hmccu}{agg}{$rule}{ftype};
|
||||
my $fexpr = $hash->{hmccu}{agg}{$rule}{fexpr};
|
||||
my $fexcl = $hash->{hmccu}{agg}{$rule}{fexcl};
|
||||
my $fread = $hash->{hmccu}{agg}{$rule}{fread};
|
||||
# my $fcoll = $hash->{hmccu}{agg}{$rule}{fcoll};
|
||||
my $fcond = $hash->{hmccu}{agg}{$rule}{fcond};
|
||||
my $ftrue = $hash->{hmccu}{agg}{$rule}{ftrue};
|
||||
my $felse = $hash->{hmccu}{agg}{$rule}{felse};
|
||||
my $fpref = $hash->{hmccu}{agg}{$rule}{fpref};
|
||||
my $fhtml = exists ($hash->{hmccu}{agg}{$rule}{fhtml}) ? 1 : 0;
|
||||
|
||||
my $resval;
|
||||
$resval = $ftrue if ($fcond =~ /^(max|min|sum|avg)$/);
|
||||
@ -906,38 +948,38 @@ sub HMCCU_AggregateReadings ($$)
|
||||
$cn : AttrVal ($cn, $hash->{hmccu}{agg}{$rule}{fcoll}, $cn);
|
||||
|
||||
# Compare readings
|
||||
my $f = 0;
|
||||
foreach my $r (keys %{$ch->{READINGS}}) {
|
||||
next if ($r !~ /$fread/);
|
||||
my $rv = $ch->{READINGS}{$r}{VAL};
|
||||
my $f = 0;
|
||||
|
||||
if (($fcond eq 'any' || $fcond eq 'all') && $rv =~ /$ftrue/) {
|
||||
$mc++;
|
||||
$rl .= ($mc > 1 ? ",$fcoll" : $fcoll);
|
||||
last;
|
||||
$f = 1;
|
||||
}
|
||||
if ($fcond eq 'max' && $rv > $resval) {
|
||||
$resval = $rv;
|
||||
$mc = 1;
|
||||
$rl = $fcoll;
|
||||
last;
|
||||
$f = 1;
|
||||
}
|
||||
if ($fcond eq 'min' && $rv < $resval) {
|
||||
$resval = $rv;
|
||||
$mc = 1;
|
||||
$rl = $fcoll;
|
||||
last;
|
||||
$f = 1;
|
||||
}
|
||||
if ($fcond eq 'sum' || $fcond eq 'avg') {
|
||||
$resval += $rv;
|
||||
$mc++;
|
||||
$f = 1;
|
||||
last;
|
||||
}
|
||||
if (($fcond eq 'gt' && $rv > $ftrue) ||
|
||||
($fcond eq 'lt' && $rv < $ftrue) ||
|
||||
($fcond eq 'ge' && $rv >= $ftrue) ||
|
||||
($fcond eq 'le' && $rv <= $ftrue)) {
|
||||
$mc++;
|
||||
$f = 1;
|
||||
}
|
||||
if ($f) {
|
||||
$rl .= ($mc > 1 ? ",$fcoll" : $fcoll);
|
||||
last;
|
||||
}
|
||||
@ -946,6 +988,34 @@ sub HMCCU_AggregateReadings ($$)
|
||||
}
|
||||
|
||||
$rl = $hash->{hmccu}{agg}{$rule}{fdflt} if ($rl eq '');
|
||||
|
||||
# HTML code generation
|
||||
if ($fhtml) {
|
||||
if ($rl ne '') {
|
||||
$table = $hash->{hmccu}{agg}{$rule}{fhtml}{'begin-html'}.
|
||||
$hash->{hmccu}{agg}{$rule}{fhtml}{'begin-table'};
|
||||
$table .= $hash->{hmccu}{agg}{$rule}{fhtml}{'header'}
|
||||
if (exists ($hash->{hmccu}{agg}{$rule}{fhtml}{'header'}));
|
||||
|
||||
my $row = 1;
|
||||
foreach my $v (split (",", $rl)) {
|
||||
my $t_row = ($row % 2) ? $hash->{hmccu}{agg}{$rule}{fhtml}{'row-odd'} :
|
||||
$hash->{hmccu}{agg}{$rule}{fhtml}{'row-even'};
|
||||
$t_row =~ s/\<reading\/\>/$v/;
|
||||
$table .= $t_row;
|
||||
$row++;
|
||||
}
|
||||
|
||||
$table .= $hash->{hmccu}{agg}{$rule}{fhtml}{'end-table'}.
|
||||
$hash->{hmccu}{agg}{$rule}{fhtml}{'end-html'};
|
||||
}
|
||||
else {
|
||||
$table = $hash->{hmccu}{agg}{$rule}{fhtml}{'begin-html'}.
|
||||
$hash->{hmccu}{agg}{$rule}{fhtml}{'default'}.
|
||||
$hash->{hmccu}{agg}{$rule}{fhtml}{'end-html'};
|
||||
}
|
||||
}
|
||||
|
||||
if ($fcond eq 'any') {
|
||||
$result = $mc > 0 ? $ftrue : $felse;
|
||||
}
|
||||
@ -968,6 +1038,7 @@ sub HMCCU_AggregateReadings ($$)
|
||||
readingsBulkUpdate ($hash, $fpref.'match', $mc);
|
||||
readingsBulkUpdate ($hash, $fpref.'count', $dc);
|
||||
readingsBulkUpdate ($hash, $fpref.'list', $rl);
|
||||
readingsBulkUpdate ($hash, $fpref.'table', $table) if ($fhtml);
|
||||
readingsEndUpdate ($hash, 1);
|
||||
|
||||
return $result;
|
||||
@ -1584,7 +1655,7 @@ sub HMCCU_Get ($@)
|
||||
else {
|
||||
if (exists ($hash->{hmccu}{agg})) {
|
||||
my @rules = keys %{$hash->{hmccu}{agg}};
|
||||
$options .= " aggregation:all,".join (',', @rules) if (scalar (@rules) > 0);
|
||||
$usage .= " aggregation:all,".join (',', @rules) if (scalar (@rules) > 0);
|
||||
}
|
||||
return $usage;
|
||||
}
|
||||
@ -1714,9 +1785,15 @@ sub HMCCU_ParseObject ($$$)
|
||||
######################################################################
|
||||
# Filter reading by datapoint and optionally by channel name or
|
||||
# channel address.
|
||||
# Parameters: hash, channel, datapoint
|
||||
# Parameter channel can be a channel name or a channel address without
|
||||
# interface specification.
|
||||
# Filter rule syntax is either:
|
||||
# [N:]{Channel-Number|Channel-Name-Expr}!Datapoint-Expr
|
||||
# or
|
||||
# [N:][Channel-Number.]Datapoint-Expr
|
||||
# Multiple filter rules must be separated by ;
|
||||
######################################################################
|
||||
|
||||
|
||||
sub HMCCU_FilterReading ($$$)
|
||||
{
|
||||
my ($hash, $chn, $dpt) = @_;
|
||||
@ -1725,42 +1802,79 @@ sub HMCCU_FilterReading ($$$)
|
||||
|
||||
my $hmccu_hash = HMCCU_GetHash ($hash);
|
||||
return 1 if (!defined ($hmccu_hash));
|
||||
|
||||
|
||||
my $grf = AttrVal ($hmccu_hash->{NAME}, 'ccudef-readingfilter', '');
|
||||
$grf = '.*' if ($grf eq '');
|
||||
my $rf = AttrVal ($name, 'ccureadingfilter', $grf);
|
||||
$rf = $grf.";".$rf if ($rf ne $grf && $grf ne '.*' && $grf ne '');
|
||||
|
||||
my $chnnam = HMCCU_IsChnAddr ($chn, 0) ? HMCCU_GetChannelName ($hmccu_hash, $chn, '') : $chn;
|
||||
my $chnnam = '';
|
||||
my $chnnum = '';
|
||||
my $devadd = '';
|
||||
|
||||
HMCCU_Trace ($hash, 2, $fnc, "chn=$chn, dpt=$dpt, rules=$rf");
|
||||
|
||||
my $rm = 1;
|
||||
my @rules = split (';', $rf);
|
||||
foreach my $r (@rules) {
|
||||
$rm = 1;
|
||||
# Get channel name and channel number
|
||||
if (HMCCU_IsChnAddr ($chn, 0)) {
|
||||
$chnnam = HMCCU_GetChannelName ($hmccu_hash, $chn, '');
|
||||
($devadd, $chnnum) = HMCCU_SplitChnAddr ($chn);
|
||||
}
|
||||
else {
|
||||
($devadd, $chnnum) = HMCCU_GetAddress ($hash, $chn, '', '');
|
||||
$chnnam = $chn;
|
||||
}
|
||||
|
||||
HMCCU_Trace ($hash, 2, $fnc, "chn=$chn, chnnam=$chnnam chnnum=$chnnum dpt=$dpt, rules=$rf");
|
||||
|
||||
foreach my $r (split (';', $rf)) {
|
||||
my $rm = 1;
|
||||
my $cn = '';
|
||||
|
||||
# Negative filter
|
||||
if ($r =~ /^N:/) {
|
||||
$rm = 0;
|
||||
$r =~ s/^N://;
|
||||
}
|
||||
|
||||
# Get filter criteria
|
||||
my ($c, $f) = split ("!", $r);
|
||||
HMCCU_Trace ($hash, 2, undef, " rm=$rm, r=$r, dpt=$dpt chnflt=$c chnnam=$chnnam");
|
||||
if (defined ($f) && $chnnam ne '') {
|
||||
if ($chnnam =~ /$c/) {
|
||||
HMCCU_Trace ($hash, 2, undef, " $chnnam = $c");
|
||||
return $rm if (($rm && $dpt =~ /$f/) || (!$rm && $dpt =~ /$f/));
|
||||
return $rm ? 0 : 1;
|
||||
}
|
||||
if (defined ($f)) {
|
||||
next if ($c eq '' || $chnnam eq '' || $chnnum eq '');
|
||||
$cn = $c if ($c =~ /^([0-9]{1,2})$/);
|
||||
}
|
||||
else {
|
||||
HMCCU_Trace ($hash, 2, undef, " check $rm=1 AND $dpt=$r OR $rm=0 AND $dpt=$r");
|
||||
return $rm if (($rm && $dpt =~ /$r/) || (!$rm && $dpt =~ /$r/));
|
||||
HMCCU_Trace ($hash, 2, undef, " check negative");
|
||||
$c = '';
|
||||
if ($r =~ /^([0-9]{1,2})\.(.+)$/) {
|
||||
$cn = $1;
|
||||
$f = $2;
|
||||
}
|
||||
else {
|
||||
$cn = '';
|
||||
$f = $r;
|
||||
}
|
||||
}
|
||||
|
||||
HMCCU_Trace ($hash, 2, undef, " check rm=$rm f=$f cn=$cn c=$c");
|
||||
# Positive filter
|
||||
return 1 if (
|
||||
$rm && (
|
||||
(
|
||||
($cn ne '' && "$chnnum" eq "$cn") ||
|
||||
($c ne '' && $chnnam =~ /$c/) ||
|
||||
($cn eq '' && $c eq '')
|
||||
) && $dpt =~ /$f/
|
||||
)
|
||||
);
|
||||
# Negative filter
|
||||
return 1 if (
|
||||
!$rm && (
|
||||
($cn ne '' && "$chnnum" ne "$cn") ||
|
||||
($c ne '' && $chnnam !~ /$c/) ||
|
||||
$dpt !~ /$f/
|
||||
)
|
||||
);
|
||||
HMCCU_Trace ($hash, 2, undef, " check result false");
|
||||
}
|
||||
|
||||
HMCCU_Trace ($hash, 2, $fnc, "return rm = $rm ? 0 : 1");
|
||||
return $rm ? 0 : 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
@ -1869,28 +1983,41 @@ sub HMCCU_GetReadingName ($$$$$$$)
|
||||
######################################################################
|
||||
# Format reading value depending on attribute stripnumber. Integer
|
||||
# values are ignored.
|
||||
# 0 = Preserve all digits
|
||||
# 1 = Preserve 1 digit
|
||||
# 2 = Remove trailing zeroes
|
||||
# -n = Round value to specified number of digits (-0 is valid)
|
||||
# Syntax of attribute stripnumber:
|
||||
# [datapoint-expr!]format[;...]
|
||||
# Valid formats:
|
||||
# 0 = Preserve all digits (default)
|
||||
# 1 = Preserve 1 digit
|
||||
# 2 = Remove trailing zeroes
|
||||
# -n = Round value to specified number of digits (-0 is allowed)
|
||||
######################################################################
|
||||
|
||||
sub HMCCU_FormatReadingValue ($$)
|
||||
sub HMCCU_FormatReadingValue ($$$)
|
||||
{
|
||||
my ($hash, $value) = @_;
|
||||
my ($hash, $value, $dpt) = @_;
|
||||
|
||||
my $stripnumber = AttrVal ($hash->{NAME}, 'stripnumber', '0');
|
||||
return $value if ($stripnumber eq '0' || $value !~ /\.[0-9]+$/);
|
||||
|
||||
if ($stripnumber eq '1') {
|
||||
return sprintf ("%.1f", $value);
|
||||
}
|
||||
elsif ($stripnumber eq '2') {
|
||||
return sprintf ("%g", $value);
|
||||
}
|
||||
elsif ($stripnumber =~ /^-([0-9])$/) {
|
||||
my $fmt = '%.'.$1.'f';
|
||||
return sprintf ($fmt, $value);
|
||||
|
||||
foreach my $sr (split (';', $stripnumber)) {
|
||||
my ($d, $s) = split ('!', $sr);
|
||||
if (defined ($s)) {
|
||||
next if ($d eq '' || $dpt !~ /$d/);
|
||||
}
|
||||
else {
|
||||
$s = $sr;
|
||||
}
|
||||
|
||||
if ($s eq '1') {
|
||||
return sprintf ("%.1f", $value);
|
||||
}
|
||||
elsif ($s eq '2') {
|
||||
return sprintf ("%g", $value);
|
||||
}
|
||||
elsif ($s =~ /^-([0-9])$/) {
|
||||
my $fmt = '%.'.$1.'f';
|
||||
return sprintf ($fmt, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
@ -2479,10 +2606,10 @@ sub HMCCU_UpdateSingleDevice ($$$)
|
||||
if (HMCCU_FilterReading ($ch, $chnadd, $dpt)) {
|
||||
my @readings = HMCCU_GetReadingName ($ch, '', $da, $chnnum, $dpt, '', $crf);
|
||||
my $svalue = HMCCU_ScaleValue ($ch, $dpt, $value, 0);
|
||||
my $fvalue = HMCCU_FormatReadingValue ($ch, $svalue);
|
||||
my $fvalue = HMCCU_FormatReadingValue ($ch, $svalue, $dpt);
|
||||
my $cvalue = HMCCU_Substitute ($fvalue, $substitute, 0, $chnnum, $dpt);
|
||||
my %calcs = HMCCU_CalculateReading ($ch, $chnnum, $dpt);
|
||||
|
||||
|
||||
# Store the resulting value after scaling, formatting and substitution
|
||||
if (exists ($clthash->{hmccu}{dp}{"$chnnum.$dpt"}{OSVAL})) {
|
||||
$clthash->{hmccu}{dp}{"$chnnum.$dpt"}{OSVAL} = $clthash->{hmccu}{dp}{"$chnnum.$dpt"}{SVAL};
|
||||
@ -2492,7 +2619,7 @@ sub HMCCU_UpdateSingleDevice ($$$)
|
||||
}
|
||||
$clthash->{hmccu}{dp}{"$chnnum.$dpt"}{SVAL} = $cvalue;
|
||||
$results{$da}{$chnnum}{$dpt} = $cvalue;
|
||||
|
||||
|
||||
HMCCU_Trace ($ch, 2, $fnc,
|
||||
"device=$cltname, readings=".join(',', @readings).
|
||||
", orgvalue=$value value=$cvalue peer=$peer");
|
||||
@ -4772,7 +4899,7 @@ sub HMCCU_GetVariables ($$)
|
||||
next if (@vardata != 3);
|
||||
next if ($vardata[0] !~ /$pattern/);
|
||||
my $rn = HMCCU_CorrectName ($vardata[0]);
|
||||
my $value = HMCCU_FormatReadingValue ($hash, $vardata[2]);
|
||||
my $value = HMCCU_FormatReadingValue ($hash, $vardata[2], $vardata[0]);
|
||||
readingsBulkUpdate ($hash, $rn, $value) if ($ccureadings);
|
||||
$result .= $vardata[0].'='.$vardata[2]."\n";
|
||||
$count++;
|
||||
@ -5076,7 +5203,7 @@ sub HMCCU_RPCGetConfig ($$$$)
|
||||
$result .= "$key=$value\n";
|
||||
next if (!$ccureadings);
|
||||
|
||||
$value = HMCCU_FormatReadingValue ($hash, $value);
|
||||
$value = HMCCU_FormatReadingValue ($hash, $value, $key);
|
||||
$value = HMCCU_Substitute ($value, $substitute, 0, $chn, $key);
|
||||
my @readings = HMCCU_GetReadingName ($hash, $int, $add, $chn, $key, $nam, $readingformat);
|
||||
foreach my $rn (@readings) {
|
||||
@ -5345,7 +5472,7 @@ sub HMCCU_GetHMState ($$$)
|
||||
}
|
||||
next if ($dp eq '');
|
||||
my ($chn, $dpt) = split (/\./, $dp);
|
||||
my $value = HMCCU_FormatReadingValue ($clhash, $clhash->{hmccu}{dp}{$dp}{VAL});
|
||||
my $value = HMCCU_FormatReadingValue ($clhash, $clhash->{hmccu}{dp}{$dp}{VAL}, $hmstate[0]);
|
||||
my ($rc, $newvalue) = HMCCU_SubstRule ($value, $subst, 0);
|
||||
return ($hmstate[0], $chn, $dpt, $newvalue) if ($rc);
|
||||
}
|
||||
@ -6165,7 +6292,7 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
|
||||
<b>Get</b><br/><br/>
|
||||
<ul>
|
||||
<li><b>get <name> aggregation {<rule>|all}</b><br/>
|
||||
Process aggregation rule defined with attribute ccuaggregation.
|
||||
Process aggregation rule defined with attribute ccuaggregate.
|
||||
</li><br/>
|
||||
<li><b>get <name> configdesc {<device>|<channel>}</b><br/>
|
||||
Get configuration parameter description of CCU device or channel (similar
|
||||
@ -6284,13 +6411,26 @@ sub HMCCU_CCURPC_ListDevicesCB ($$)
|
||||
<li><b>coll:{<attribute>|NAME}[!<default-text>]</b><br/>
|
||||
Attribute of matching devices stored in aggregation results. Default text in case
|
||||
of no matching devices found is optional.</li>
|
||||
<li><b>html:<template-file></b><br/>
|
||||
Create HTML code with matching devices.</li>
|
||||
</ul><br/>
|
||||
Aggregation results will be stored in readings <i>prefix</i>count, <i>prefix</i>list,
|
||||
<i>prefix</i>match, <i>prefix</i>state and <i>prefix</i>table.<br/><br/>
|
||||
Format of a line in <i>template-file</i> is <keyword>:<html-code>. See
|
||||
FHEM Wiki for an example. Valid keywords are:<br/><br/>
|
||||
<ul>
|
||||
<li><b>begin-html</b>: Start of html code.</li>
|
||||
<li><b>begin-table</b>: Start of table (i.e. the table header)</li>
|
||||
<li><b>row-odd</b>: HTML code for odd lines. A tag <reading/> is replaced by a matching device.</li>
|
||||
<li><b>row-even</b>: HTML code for event lines.</li>
|
||||
<li><b>end-table</b>: End of table.</li>
|
||||
<li><b>default</b>: HTML code for no matches.</li>
|
||||
<li><b>end-html</b>: End of html code.</li>
|
||||
</ul><br/>
|
||||
Aggregation results will be stored in readings <i>prefix</i>count, <i>prefix</i>
|
||||
list, <i>prefix</i>match and <i>prefix</i>state<br/><br/>
|
||||
Example: Find open windows<br/>
|
||||
name=lock,filter:type=^HM-Sec-SC.*,read:STATE,if:any=open,else:closed,prefix:lock_,coll:NAME!All windows closed<br/><br/>
|
||||
Example: Find devices with low batteries<br/>
|
||||
name=battery,filter:name=.*,read:(LOWBAT|LOW_BAT),if:any=yes,else:no,prefix:batt_,coll:NAME<br/>
|
||||
Example: Find devices with low batteries. Generate reading in HTML format.<br/>
|
||||
name=battery,filter:name=.*,read:(LOWBAT|LOW_BAT),if:any=yes,else:no,prefix:batt_,coll:NAME!All batteries OK,html:/home/battery.cfg<br/>
|
||||
</li><br/>
|
||||
<li><b>ccudef-hmstatevals <subst-rule[;...]></b><br/>
|
||||
Set global rules for calculation of reading hmstate.
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.1.001
|
||||
# Version 4.1.003
|
||||
#
|
||||
# (c) 2017 zap (zap01 <at> t-online <dot> de)
|
||||
#
|
||||
@ -38,7 +38,7 @@
|
||||
# attr <name> ccuflags { altread, nochn0, trace }
|
||||
# attr <name> ccuget { State | Value }
|
||||
# attr <name> ccureadings { 0 | 1 }
|
||||
# attr <name> ccureadingfilter <datapoint-expr>
|
||||
# attr <name> ccureadingfilter <filter-rule>[;...]
|
||||
# attr <name> ccureadingformat { name[lc] | address[lc] | datapoint[lc] }
|
||||
# attr <name> ccureadingname <oldname>:<newname>[;...]
|
||||
# attr <name> ccuverify { 0 | 1 | 2 }
|
||||
@ -84,7 +84,8 @@ sub HMCCUCHN_Initialize ($)
|
||||
|
||||
$hash->{AttrList} = "IODev ccuackstate:0,1 ccucalculate ".
|
||||
"ccuflags:multiple-strict,altread,nochn0,trace ccureadingfilter ".
|
||||
"ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ccureadingname ".
|
||||
"ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ".
|
||||
"ccureadingname:textField-long ".
|
||||
"ccureadings:0,1 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;
|
||||
@ -778,15 +779,19 @@ sub HMCCUCHN_Get ($@)
|
||||
</li><br/>
|
||||
<li><b>ccureadingfilter <filter-rule[;...]></b><br/>
|
||||
Only datapoints matching specified expression are stored as readings.<br/>
|
||||
Syntax for <i>filter-rule</i> is: [N:][<channel-name>!]<RegExp><br/>
|
||||
If <i>channel-name</i> is specified the following rule applies only to this channel.
|
||||
Syntax for <i>filter-rule</i> is either:<br/>
|
||||
[N:]{<channel-name>|<channel-number>}!<RegExp> or:<br/>
|
||||
[N:][<channel-number>.]<RegExp><br/>
|
||||
If <i>channel-name</i> or <i>channel-number</i> is specified the following rule
|
||||
applies only to this channel.
|
||||
By default all datapoints will be stored as readings. Attribute ccudef-readingfilter
|
||||
of I/O device will be checked before this attribute.<br/>
|
||||
If a rule starts with 'N:' the filter is negated which means that a reading is
|
||||
stored if rule doesn't match.
|
||||
</li><br/>
|
||||
<li><b>ccureadingformat {address[lc] | name[lc] | datapoint[lc]}</b><br/>
|
||||
Set format of reading names. Default is 'name'. If set to 'address' format of reading names
|
||||
Set format of reading names. Default for virtual device groups is 'name'. The default for all
|
||||
other device types is 'datapoint'. If set to 'address' format of reading names
|
||||
is channel-address.datapoint. If set to 'name' format of reading names is
|
||||
channel-name.datapoint. If set to 'datapoint' format is channel-number.datapoint. With
|
||||
suffix 'lc' reading names are converted to lowercase.
|
||||
@ -910,14 +915,16 @@ sub HMCCUCHN_Get ($@)
|
||||
set my_switch on
|
||||
</code>
|
||||
</li><br/>
|
||||
<li><b>stripnumber {<u>0</u> | 1 | 2 | -n}</b><br/>
|
||||
<li><b>stripnumber [<datapoint-expr>!]{<u>0</u>|1|2|-n}[;...]</b><br/>
|
||||
Remove trailing digits or zeroes from floating point numbers and/or round floating
|
||||
point numbers. If attribute is negative (-0 is valid) floating point values are rounded
|
||||
to the specified number of digits before they are stored in readings. The meaning of
|
||||
values 0-2 is:<br/>
|
||||
0 = Floating point numbers are stored as read from CCU (i.e. with trailing zeros)<br/>
|
||||
1 = Trailing zeros are stripped from floating point numbers except one digit.<br/>
|
||||
2 = All trailing zeros are stripped from floating point numbers.
|
||||
2 = All trailing zeros are stripped from floating point numbers.<br/>
|
||||
If <i>datapoint-expr</i> is specified the formatting applies only to datapoints
|
||||
matching the regular expression.
|
||||
</li><br/>
|
||||
<li><b>substexcl <reading-expr></b><br/>
|
||||
Exclude values of readings matching <i>reading-expr</i> from substitution. This is helpful
|
||||
@ -926,7 +933,7 @@ sub HMCCUCHN_Get ($@)
|
||||
</li><br/>
|
||||
<li><b>substitute <subst-rule>[;...]</b><br/>
|
||||
Define substitutions for datapoint/reading values. Syntax of <i>subst-rule</i> is<br/><br/>
|
||||
[[<channelno.>]<datapoint>[,...]!]<{#n1-m1|regexp}>:<text>[,...]
|
||||
[[<channelno>.]<datapoint>[,...]!]<{#n1-m1|regexp}>:<text>[,...]
|
||||
<br/><br/>
|
||||
Parameter <i>text</i> can contain variables in format ${<i>varname</i>}. The variable
|
||||
${value} is
|
||||
@ -937,11 +944,11 @@ sub HMCCUCHN_Get ($@)
|
||||
'T=<i>val</i> deg' and append current value of datapoint 1.HUMIDITY<br/>
|
||||
<code>
|
||||
attr my_weather substitute TEMPERATURE!.+:T=${value} deg H=${1.HUMIDITY}%
|
||||
</code>
|
||||
</code><br/><br/>
|
||||
If rule expression starts with a hash sign a numeric datapoint value is substituted if
|
||||
it fits in the number range n <= value <= m.
|
||||
<br/><br/>
|
||||
Example: Interpret LEVEL values of dimmer as "on" and "off"<br/>
|
||||
Example: Interpret LEVEL values 100 and 0 of dimmer as "on" and "off"<br/>
|
||||
<code>
|
||||
attr my_dim substitute LEVEL!#0-0:off,#1-100:on
|
||||
</code>
|
||||
|
@ -87,7 +87,8 @@ sub HMCCUDEV_Initialize ($)
|
||||
|
||||
$hash->{AttrList} = "IODev ccuackstate:0,1 ccucalculate:textField-long ".
|
||||
"ccuflags:multiple-strict,altread,nochn0,trace ccureadingfilter:textField-long ".
|
||||
"ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ccureadingname ".
|
||||
"ccureadingformat:name,namelc,address,addresslc,datapoint,datapointlc ".
|
||||
"ccureadingname:textField-long ".
|
||||
"ccureadings:0,1 ccuget:State,Value ccuscaleval ccuverify:0,1,2 disable:0,1 ".
|
||||
"hmstatevals:textField-long statevals substexcl substitute:textField-long statechannel ".
|
||||
"statedatapoint controldatapoint stripnumber peer:textField-long ".$readingFnAttributes;
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 0.97 beta
|
||||
# Version 0.98 beta
|
||||
#
|
||||
# Thread based RPC Server module for HMCCU.
|
||||
#
|
||||
@ -40,7 +40,7 @@ use SetExtensions;
|
||||
######################################################################
|
||||
|
||||
# HMCCURPC version
|
||||
my $HMCCURPC_VERSION = '0.97 beta';
|
||||
my $HMCCURPC_VERSION = '0.98 beta';
|
||||
|
||||
# Maximum number of events processed per call of Read()
|
||||
my $HMCCURPC_MAX_EVENTS = 50;
|
||||
@ -237,7 +237,7 @@ sub HMCCURPC_Initialize ($)
|
||||
$hash->{parseParams} = 1;
|
||||
|
||||
$hash->{AttrList} = "rpcInterfaces:multiple-strict,".join(',',sort keys %HMCCURPC_RPC_PORT).
|
||||
" ccuflags:multiple-strict,expert,keepThreads,reconnect".
|
||||
" ccuflags:multiple-strict,expert,keepThreads,logEvents,reconnect".
|
||||
" rpcMaxEvents rpcQueueSize rpcTriggerTime".
|
||||
" rpcServer:on,off rpcServerAddr rpcServerPort rpcWriteTimeout rpcAcceptTimeout".
|
||||
" rpcConnTimeout rpcWaitTime rpcStatistics rpcEventTimeout ".
|
||||
@ -652,7 +652,7 @@ sub HMCCURPC_Read ($)
|
||||
}
|
||||
elsif ($et eq 'TO') {
|
||||
$hmccu_hash->{ccustate} = 'timeout';
|
||||
if ($hash->{RPCState} eq 'running' && $hash->{$ccuflags} =~ /reconnect/) {
|
||||
if ($hash->{RPCState} eq 'running' && $ccuflags =~ /reconnect/) {
|
||||
if (HMCCU_TCPConnect ($hash->{host}, $par[0])) {
|
||||
$hmccu_hash->{ccustate} = 'active';
|
||||
Log3 $name, 2, "HMCCURPC: Reconnecting to CCU interface ".
|
||||
@ -833,6 +833,8 @@ sub HMCCURPC_ProcessEvent ($$)
|
||||
"ST", 11
|
||||
);
|
||||
|
||||
my $ccuflags = AttrVal ($name, 'ccuflags', 'null');
|
||||
|
||||
# Parse event
|
||||
return undef if (!defined ($event) || $event eq '');
|
||||
my @t = split (/\|/, $event);
|
||||
@ -865,6 +867,9 @@ sub HMCCURPC_ProcessEvent ($$)
|
||||
$rpceventargs{$et};
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Log event
|
||||
Log3 $name, 2, "HMCCURPC: CCUEvent = $event" if ($ccuflags =~ /logEvents/);
|
||||
|
||||
# Update statistic counters
|
||||
$rh->{$clkey}{rec}{$et}++;
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Version 4.1.001
|
||||
# Version 4.1.002
|
||||
#
|
||||
# Configuration parameters for HomeMatic devices.
|
||||
#
|
||||
@ -154,8 +154,8 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
statevals => "press:true",
|
||||
substitute => "PRESS_SHORT,PRESS_LONG,PRESS_CONT!(1|true):pressed,(0|false):released;PRESS_LONG_RELEASE!(0|false):no,(1|true):yes"
|
||||
},
|
||||
"HM-RC-Key4-2|HM-RC-Key4-3" => {
|
||||
_description => "Funk-Handsender Key",
|
||||
"HM-RC-Key4-2|HM-RC-Key4-3|HM-RC-Sec4-2|HM-RC-Sec4-3" => {
|
||||
_description => "Funk-Handsender",
|
||||
_channels => "1,2,3,4",
|
||||
ccureadingfilter => "PRESS",
|
||||
"event-on-update-reading" => ".*",
|
||||
@ -490,8 +490,8 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
ccureadingfilter => "PRESS",
|
||||
substitute => "PRESS_SHORT,PRESS_LONG,PRESS_CONT!(1|true):pressed,(0|false):released;PRESS_LONG_RELEASE!(0|false):no,(1|true):yes"
|
||||
},
|
||||
"HM-RC-Key4-2|HM-RC-Key4-3" => {
|
||||
_description => "Funk-Handsender Key",
|
||||
"HM-RC-Key4-2|HM-RC-Key4-3|HM-RC-Sec4-2|HM-RC-Sec4-3" => {
|
||||
_description => "Funk-Handsender",
|
||||
ccureadingfilter => "PRESS",
|
||||
"event-on-update-reading" => ".*",
|
||||
substitute => "PRESS_SHORT,PRESS_LONG!(1|true):pressed"
|
||||
@ -538,6 +538,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
cmdIcon => "Auto:sani_heating_automatic Manu:sani_heating_manual Boost:sani_heating_boost on:general_an off:general_aus",
|
||||
controldatapoint => "2.SET_TEMPERATURE",
|
||||
eventMap => "/datapoint 2.MANU_MODE 20.0:Manu/datapoint 2.AUTO_MODE 1:Auto/datapoint 2.BOOST_MODE 1:Boost/datapoint 2.MANU_MODE 4.5:off/datapoint 2.MANU_MODE 30.5:on/",
|
||||
genericDeviceType => "thermostat",
|
||||
statedatapoint => "2.SET_TEMPERATURE",
|
||||
stripnumber => 1,
|
||||
substexcl => "control",
|
||||
@ -551,6 +552,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
cmdIcon => "Auto:sani_heating_automatic Manu:sani_heating_manual Boost:sani_heating_boost on:general_an off:general_aus",
|
||||
controldatapoint => "4.SET_TEMPERATURE",
|
||||
eventMap => "/datapoint 4.MANU_MODE 20.0:Manu/datapoint 4.AUTO_MODE 1:Auto/datapoint 4.BOOST_MODE 1:Boost/datapoint 4.MANU_MODE 4.5:off/datapoint 4.MANU_MODE 30.5:on/",
|
||||
genericDeviceType => "thermostat",
|
||||
hmstatevals => "FAULT_REPORTING!1:valve_tight,2:range_too_large,3:range_too_small,4:communication_error,5:other_error,6:battery_low,7:valve_error_pos",
|
||||
statedatapoint => "4.SET_TEMPERATURE",
|
||||
stripnumber => 1,
|
||||
@ -559,12 +561,14 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
webCmd => "control:Auto:Manu:Boost:on:off",
|
||||
widgetOverride => "control:slider,4.5,0.5,30.5,1"
|
||||
},
|
||||
"HMIP-eTRV" => {
|
||||
"HmIP-eTRV|HmIP-eTRV-2" => {
|
||||
_description => "Heizkoerperthermostat HM-IP",
|
||||
ccureadingfilter => "^ACTUAL_TEMPERATURE|^BOOST_MODE|^SET_POINT_MODE|^SET_POINT_TEMPERATURE|^LEVEL|^WINDOW_STATE",
|
||||
ccureadingname => "1.LEVEL:valve_position",
|
||||
ccuscaleval => "LEVEL:0:1:0:100",
|
||||
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/",
|
||||
genericDeviceType => "thermostat",
|
||||
statedatapoint => "1.SET_POINT_TEMPERATURE",
|
||||
stripnumber => 1,
|
||||
substexcl => "control",
|
||||
@ -576,6 +580,7 @@ use vars qw(%HMCCU_SCRIPTS);
|
||||
_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/",
|
||||
genericDeviceType => "thermostat",
|
||||
statedatapoint => "1.SET_POINT_TEMPERATURE",
|
||||
stripnumber => 1,
|
||||
substexcl => "control",
|
||||
|
Loading…
x
Reference in New Issue
Block a user