mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
HMCCU: New datapoint based calculation modes
git-svn-id: https://svn.fhem.de/fhem/trunk@14157 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
16777da1c8
commit
d0d429fce1
@ -1,5 +1,6 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
# 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.
|
# Do not insert empty lines here, update check depends on it.
|
||||||
|
- feature: 88_HMCCU: New reading based calculation modes
|
||||||
- feature: 34_ESPEasy.pm: Added ESPeasy Mega internals build.*
|
- feature: 34_ESPEasy.pm: Added ESPeasy Mega internals build.*
|
||||||
- bugfix 73_km200.pm: Errorlist unsorted timestamp
|
- bugfix 73_km200.pm: Errorlist unsorted timestamp
|
||||||
- bugfix: 72_FB_CALLMONITOR: fix reverse-search of dasschnelle.at
|
- bugfix: 72_FB_CALLMONITOR: fix reverse-search of dasschnelle.at
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# $Id$
|
# $Id$
|
||||||
#
|
#
|
||||||
# Version 4.0.002
|
# Version 4.0.003
|
||||||
#
|
#
|
||||||
# Module for communication between FHEM and Homematic CCU2.
|
# Module for communication between FHEM and Homematic CCU2.
|
||||||
#
|
#
|
||||||
@ -105,22 +105,29 @@ my %HMCCU_CUST_CHN_DEFAULTS;
|
|||||||
my %HMCCU_CUST_DEV_DEFAULTS;
|
my %HMCCU_CUST_DEV_DEFAULTS;
|
||||||
|
|
||||||
# HMCCU version
|
# HMCCU version
|
||||||
my $HMCCU_VERSION = '4.0.002';
|
my $HMCCU_VERSION = '4.0.003';
|
||||||
|
|
||||||
# RPC Ports and URL extensions
|
# Default RPC port (BidCos-RF)
|
||||||
my $HMCCU_RPC_PORT_DEFAULT = 2001;
|
my $HMCCU_RPC_PORT_DEFAULT = 2001;
|
||||||
|
|
||||||
|
# RPC port name by port number
|
||||||
my %HMCCU_RPC_NUMPORT = (
|
my %HMCCU_RPC_NUMPORT = (
|
||||||
2000 => 'BidCos-Wired', 2001 => 'BidCos-RF', 2010 => 'HmIP-RF', 9292 => 'VirtualDevices',
|
2000 => 'BidCos-Wired', 2001 => 'BidCos-RF', 2010 => 'HmIP-RF', 9292 => 'VirtualDevices',
|
||||||
2003 => 'Homegear', 8701 => 'CUxD'
|
2003 => 'Homegear', 8701 => 'CUxD'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
# RPC port number by port name
|
||||||
my %HMCCU_RPC_PORT = (
|
my %HMCCU_RPC_PORT = (
|
||||||
'BidCos-Wired', 2000, 'BidCos-RF', 2001, 'HmIP-RF', 2010, 'VirtualDevices', 9292,
|
'BidCos-Wired', 2000, 'BidCos-RF', 2001, 'HmIP-RF', 2010, 'VirtualDevices', 9292,
|
||||||
'Homegear', 2003, 'CUxD', 8701
|
'Homegear', 2003, 'CUxD', 8701
|
||||||
);
|
);
|
||||||
|
|
||||||
|
# RPC URL extensions by port number
|
||||||
my %HMCCU_RPC_URL = (
|
my %HMCCU_RPC_URL = (
|
||||||
9292, 'groups'
|
9292, 'groups'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
# RPC protocol types by port name. A=ASCII, B=Binary
|
||||||
my %HMCCU_RPC_PROT = (
|
my %HMCCU_RPC_PROT = (
|
||||||
2000 => 'A', 2001 => 'A', 2010 => 'A', 9292 => 'A', 2003 => 'A', 8701 => 'B'
|
2000 => 'A', 2001 => 'A', 2010 => 'A', 9292 => 'A', 2003 => 'A', 8701 => 'B'
|
||||||
);
|
);
|
||||||
@ -171,15 +178,12 @@ my $HMCCU_FLAG_FULLADDR = 32;
|
|||||||
# Valid flag combinations
|
# Valid flag combinations
|
||||||
my $HMCCU_FLAGS_IACD = $HMCCU_FLAG_INTERFACE | $HMCCU_FLAG_ADDRESS |
|
my $HMCCU_FLAGS_IACD = $HMCCU_FLAG_INTERFACE | $HMCCU_FLAG_ADDRESS |
|
||||||
$HMCCU_FLAG_CHANNEL | $HMCCU_FLAG_DATAPOINT;
|
$HMCCU_FLAG_CHANNEL | $HMCCU_FLAG_DATAPOINT;
|
||||||
my $HMCCU_FLAGS_IAC = $HMCCU_FLAG_INTERFACE | $HMCCU_FLAG_ADDRESS |
|
my $HMCCU_FLAGS_IAC = $HMCCU_FLAG_INTERFACE | $HMCCU_FLAG_ADDRESS | $HMCCU_FLAG_CHANNEL;
|
||||||
$HMCCU_FLAG_CHANNEL;
|
my $HMCCU_FLAGS_ACD = $HMCCU_FLAG_ADDRESS | $HMCCU_FLAG_CHANNEL | $HMCCU_FLAG_DATAPOINT;
|
||||||
my $HMCCU_FLAGS_ACD = $HMCCU_FLAG_ADDRESS | $HMCCU_FLAG_CHANNEL |
|
|
||||||
$HMCCU_FLAG_DATAPOINT;
|
|
||||||
my $HMCCU_FLAGS_AC = $HMCCU_FLAG_ADDRESS | $HMCCU_FLAG_CHANNEL;
|
my $HMCCU_FLAGS_AC = $HMCCU_FLAG_ADDRESS | $HMCCU_FLAG_CHANNEL;
|
||||||
my $HMCCU_FLAGS_ND = $HMCCU_FLAG_NAME | $HMCCU_FLAG_DATAPOINT;
|
my $HMCCU_FLAGS_ND = $HMCCU_FLAG_NAME | $HMCCU_FLAG_DATAPOINT;
|
||||||
my $HMCCU_FLAGS_NC = $HMCCU_FLAG_NAME | $HMCCU_FLAG_CHANNEL;
|
my $HMCCU_FLAGS_NC = $HMCCU_FLAG_NAME | $HMCCU_FLAG_CHANNEL;
|
||||||
my $HMCCU_FLAGS_NCD = $HMCCU_FLAG_NAME | $HMCCU_FLAG_CHANNEL |
|
my $HMCCU_FLAGS_NCD = $HMCCU_FLAG_NAME | $HMCCU_FLAG_CHANNEL | $HMCCU_FLAG_DATAPOINT;
|
||||||
$HMCCU_FLAG_DATAPOINT;
|
|
||||||
|
|
||||||
# Binary RPC data types
|
# Binary RPC data types
|
||||||
my $BINRPC_INTEGER = 1;
|
my $BINRPC_INTEGER = 1;
|
||||||
@ -222,6 +226,7 @@ sub HMCCU_UpdateDeviceTable ($$);
|
|||||||
sub HMCCU_UpdateSingleDatapoint ($$$$);
|
sub HMCCU_UpdateSingleDatapoint ($$$$);
|
||||||
sub HMCCU_UpdateSingleDevice ($$$);
|
sub HMCCU_UpdateSingleDevice ($$$);
|
||||||
sub HMCCU_UpdateMultipleDevices ($$);
|
sub HMCCU_UpdateMultipleDevices ($$);
|
||||||
|
sub HMCCU_UpdatePeers ($$$$$);
|
||||||
sub HMCCU_GetRPCPortList ($);
|
sub HMCCU_GetRPCPortList ($);
|
||||||
sub HMCCU_RPCRegisterCallback ($);
|
sub HMCCU_RPCRegisterCallback ($);
|
||||||
sub HMCCU_RPCDeRegisterCallback ($);
|
sub HMCCU_RPCDeRegisterCallback ($);
|
||||||
@ -2145,8 +2150,12 @@ sub HMCCU_UpdateDeviceTable ($$)
|
|||||||
$nm = $devices->{$da}{name} if (defined ($devices->{$da}{name}));
|
$nm = $devices->{$da}{name} if (defined ($devices->{$da}{name}));
|
||||||
|
|
||||||
if ($devices->{$da}{flag} eq 'N' && defined ($nm)) {
|
if ($devices->{$da}{flag} eq 'N' && defined ($nm)) {
|
||||||
|
my $at = HMCCU_IsChnAddr ($da, 0) ? 'chn' : 'dev';
|
||||||
|
Log3 $name, 2, "HMCCU: Duplicate name for device/channel $nm address=$da in CCU."
|
||||||
|
if (exists ($hash->{hmccu}{adr}{$nm}) && $at ne $hash->{hmccu}{adr}{$nm}{addtype});
|
||||||
|
|
||||||
# Updated or new device/channel
|
# Updated or new device/channel
|
||||||
$hash->{hmccu}{dev}{$da}{addtype} = HMCCU_IsChnAddr ($da, 0) ? 'chn' : 'dev';
|
$hash->{hmccu}{dev}{$da}{addtype} = $at;
|
||||||
$hash->{hmccu}{dev}{$da}{name} = $nm if (defined ($nm));
|
$hash->{hmccu}{dev}{$da}{name} = $nm if (defined ($nm));
|
||||||
$hash->{hmccu}{dev}{$da}{valid} = 1;
|
$hash->{hmccu}{dev}{$da}{valid} = 1;
|
||||||
$hash->{hmccu}{dev}{$da}{channels} = $devices->{$da}{channels}
|
$hash->{hmccu}{dev}{$da}{channels} = $devices->{$da}{channels}
|
||||||
@ -2438,6 +2447,44 @@ sub HMCCU_UpdateMultipleDevices ($$)
|
|||||||
return $c;
|
return $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Update peer devices.
|
||||||
|
# Syntax of peer definitions is:
|
||||||
|
# [channel.]datapoint oper value:{hmccu:object=expr|fhem:command}
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
sub HMCCU_UpdatePeers ($$$$$)
|
||||||
|
{
|
||||||
|
my ($clt_hash, $chn, $dpt, $val, $peerattr) = @_;
|
||||||
|
|
||||||
|
my @rules = split (/[;\n]+/, $peerattr);
|
||||||
|
foreach my $r (@rules) {
|
||||||
|
my ($cond, $type, $act) = split (/:/, $r, 3);
|
||||||
|
next if (!defined ($act));
|
||||||
|
my ($src, $oper, $expr) = split (/ /, $cond, 3);
|
||||||
|
next if (!defined ($expr));
|
||||||
|
my ($cchn, $cdpt) = split (/\./, $src, 2);
|
||||||
|
next if (!defined ($cchn));
|
||||||
|
if (!defined ($cdpt)) {
|
||||||
|
$cdpt = $cchn;
|
||||||
|
$cchn = '';
|
||||||
|
}
|
||||||
|
next if ($chn ne '' || $cchn ne '' || $cchn ne $chn || $cdpt ne $dpt);
|
||||||
|
my $e = eval "$val $oper $expr";
|
||||||
|
next if (!defined ($e) || $e eq '');
|
||||||
|
|
||||||
|
if ($type eq 'hmccu') {
|
||||||
|
my ($aobj, $aexp) = split (/=/, $act);
|
||||||
|
$aexp =~ s/\$value/$val/g;
|
||||||
|
HMCCU_SetDatapoint ($clt_hash, $aobj, $aexp);
|
||||||
|
}
|
||||||
|
elsif ($type eq 'fhem') {
|
||||||
|
$act =~ s/\$value/$val/g;
|
||||||
|
AnalyzeCommandChain (undef, $act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Get list of valid RPC ports.
|
# Get list of valid RPC ports.
|
||||||
# Considers binary RPC ports and interfaces used by CCU devices.
|
# Considers binary RPC ports and interfaces used by CCU devices.
|
||||||
@ -2993,7 +3040,7 @@ foreach(devid, root.Devices().EnumUsedIDs()) {
|
|||||||
%{$hash->{hmccu}{adr}} = ();
|
%{$hash->{hmccu}{adr}} = ();
|
||||||
$hash->{hmccu}{updatetime} = time ();
|
$hash->{hmccu}{updatetime} = time ();
|
||||||
|
|
||||||
# Hash elements:
|
# Device hash elements for HMCCU_UpdateDeviceTable():
|
||||||
#
|
#
|
||||||
# {address}{flag} := [N, D, R]
|
# {address}{flag} := [N, D, R]
|
||||||
# {address}{addtype} := [chn, dev]
|
# {address}{addtype} := [chn, dev]
|
||||||
@ -3020,7 +3067,7 @@ foreach(devid, root.Devices().EnumUsedIDs()) {
|
|||||||
$objects{$hmdata[2]}{type} = ($hmdata[2] =~ /^CUX/) ? "CUX-".$hmdata[4] : $hmdata[4];
|
$objects{$hmdata[2]}{type} = ($hmdata[2] =~ /^CUX/) ? "CUX-".$hmdata[4] : $hmdata[4];
|
||||||
# Count used interfaces
|
# Count used interfaces
|
||||||
$hash->{hmccu}{iface}{$hmdata[1]}++;
|
$hash->{hmccu}{iface}{$hmdata[1]}++;
|
||||||
# CCU information
|
# CCU information (address = BidCoS-RF)
|
||||||
if ($hmdata[2] eq 'BidCoS-RF') {
|
if ($hmdata[2] eq 'BidCoS-RF') {
|
||||||
$hash->{ccuname} = $hmdata[3];
|
$hash->{ccuname} = $hmdata[3];
|
||||||
$hash->{ccuaddr} = $hmdata[2];
|
$hash->{ccuaddr} = $hmdata[2];
|
||||||
@ -5246,9 +5293,11 @@ sub HMCCU_GetTimeSpec ($)
|
|||||||
}
|
}
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Calculate special readings. Requires hash of client device and
|
# Calculate special readings. Requires hash of client device, channel
|
||||||
# channel number and datapoint.
|
# number and datapoint. Supported functions:
|
||||||
# Return readings.
|
# dewpoint, absolute humidity, increasing/decreasing counters,
|
||||||
|
# minimum/maximum, average, sum.
|
||||||
|
# Return readings array with reading/value pairs.
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
sub HMCCU_CalculateReading ($$$)
|
sub HMCCU_CalculateReading ($$$)
|
||||||
@ -5261,12 +5310,13 @@ sub HMCCU_CalculateReading ($$$)
|
|||||||
my $ccucalculate = AttrVal ($name, 'ccucalculate', '');
|
my $ccucalculate = AttrVal ($name, 'ccucalculate', '');
|
||||||
return @result if ($ccucalculate eq '');
|
return @result if ($ccucalculate eq '');
|
||||||
|
|
||||||
my @calclist = split (';', $ccucalculate);
|
my @calclist = split (/[;\n]+/, $ccucalculate);
|
||||||
foreach my $calculation (@calclist) {
|
foreach my $calculation (@calclist) {
|
||||||
my ($valuetype, $reading, $datapoints) = split (':', $calculation);
|
my ($vt, $rn, $dpts) = split (':', $calculation);
|
||||||
next if (!defined ($reading));
|
next if (!defined ($rn));
|
||||||
|
|
||||||
my @dplist = defined ($datapoints) ? split (',', $datapoints) : ();
|
# Get parameters values stored in device hash
|
||||||
|
my @dplist = defined ($dpts) ? split (',', $dpts) : ();
|
||||||
next if (@dplist > 0 && !(grep { $_ eq "$chnno.$dpt"} @dplist));
|
next if (@dplist > 0 && !(grep { $_ eq "$chnno.$dpt"} @dplist));
|
||||||
my @pars = ();
|
my @pars = ();
|
||||||
foreach my $dp (@dplist) {
|
foreach my $dp (@dplist) {
|
||||||
@ -5275,8 +5325,9 @@ sub HMCCU_CalculateReading ($$$)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($valuetype eq 'dewpoint' || $valuetype eq 'abshumidity') {
|
if ($vt eq 'dewpoint' || $vt eq 'abshumidity') {
|
||||||
next if (@pars < 2);
|
# Dewpoint and absolute humidity
|
||||||
|
next if (scalar (@pars) < 2);
|
||||||
my ($tmp, $hum) = @pars;
|
my ($tmp, $hum) = @pars;
|
||||||
if ($tmp >= 0.0) {
|
if ($tmp >= 0.0) {
|
||||||
$a = 7.5;
|
$a = 7.5;
|
||||||
@ -5289,16 +5340,57 @@ sub HMCCU_CalculateReading ($$$)
|
|||||||
|
|
||||||
my $sdd = 6.1078*(10.0**(($a*$tmp)/($b+$tmp)));
|
my $sdd = 6.1078*(10.0**(($a*$tmp)/($b+$tmp)));
|
||||||
my $dd = $hum/100.0*$sdd;
|
my $dd = $hum/100.0*$sdd;
|
||||||
if ($valuetype eq 'dewpoint') {
|
if ($vt eq 'dewpoint') {
|
||||||
my $v = log($dd/6.1078)/log(10.0);
|
my $v = log($dd/6.1078)/log(10.0);
|
||||||
my $td = $b*$v/($a-$v);
|
my $td = $b*$v/($a-$v);
|
||||||
push (@result, $reading, (sprintf "%.1f", $td));
|
push (@result, $rn, (sprintf "%.1f", $td));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
my $af = 100000.0*18.016/8314.3*$dd/($tmp+273.15);
|
my $af = 100000.0*18.016/8314.3*$dd/($tmp+273.15);
|
||||||
push (@result, $reading, (sprintf "%.1f", $af));
|
push (@result, $rn, (sprintf "%.1f", $af));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elsif ($vt eq 'min' || $vt eq 'max') {
|
||||||
|
# Minimum or maximum values
|
||||||
|
next if (scalar (@pars) < 1);
|
||||||
|
my $newval = shift @pars;
|
||||||
|
my $curval = ReadingsVal ($name, $rn, 0);
|
||||||
|
$curval = $newval if ($vt eq 'min' && $newval < $curval);
|
||||||
|
$curval = $newval if ($vt eq 'max' && $newval > $curval);
|
||||||
|
push (@result, $rn, $curval);
|
||||||
|
}
|
||||||
|
elsif ($vt eq 'inc' || $vt eq 'dec') {
|
||||||
|
# Increasing or decreasing values without reset
|
||||||
|
next if (scalar (@pars) < 1);
|
||||||
|
my $newval = shift @pars;
|
||||||
|
my $oldval = ReadingsVal ($name, $rn."_old", 0);
|
||||||
|
my $curval = ReadingsVal ($name, $rn, 0);
|
||||||
|
if (($vt eq 'inc' && $newval < $curval) || ($vt eq 'dec' && $newval > $curval)) {
|
||||||
|
$oldval = $curval;
|
||||||
|
push (@result, $rn."_old", $oldval);
|
||||||
|
}
|
||||||
|
$curval = $newval+$oldval;
|
||||||
|
push (@result, $rn, $curval);
|
||||||
|
}
|
||||||
|
elsif ($vt eq 'avg') {
|
||||||
|
# Average value
|
||||||
|
next if (scalar (@pars) < 1);
|
||||||
|
my $newval = shift @pars;
|
||||||
|
my $cnt = ReadingsVal ($name, $rn."_cnt", 0);
|
||||||
|
my $sum = ReadingsVal ($name, $rn."_sum", 0);
|
||||||
|
$cnt++;
|
||||||
|
$sum += $newval;
|
||||||
|
my $curval = $sum/$cnt;
|
||||||
|
push (@result, $rn."_cnt", $cnt, $rn."_sum", $sum, $rn, $curval);
|
||||||
|
}
|
||||||
|
elsif ($vt eq 'sum') {
|
||||||
|
# Sum of values
|
||||||
|
next if (scalar (@pars) < 1);
|
||||||
|
my $newval = shift @pars;
|
||||||
|
my $curval = ReadingsVal ($name, $rn, 0);
|
||||||
|
$curval += $newval;
|
||||||
|
push (@result, $rn, $curval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return @result;
|
return @result;
|
||||||
@ -5312,9 +5404,9 @@ sub HMCCU_CalculateReading ($$$)
|
|||||||
# msg := parameter=value[,...]
|
# msg := parameter=value[,...]
|
||||||
#
|
#
|
||||||
# text1-3=Text
|
# text1-3=Text
|
||||||
# icon1-3=Icon
|
# icon1-3=IconName
|
||||||
# sound=
|
# sound=SoundName
|
||||||
# signal=
|
# signal=SignalName
|
||||||
# pause=1-160
|
# pause=1-160
|
||||||
# repeat=0-15
|
# repeat=0-15
|
||||||
#
|
#
|
||||||
@ -5485,7 +5577,7 @@ sub HMCCU_ExprNotMatch ($$$)
|
|||||||
}
|
}
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Read duty cycles of interfaces 2001 and 2010.
|
# Read duty cycles of interfaces 2001 and 2010 and update readings.
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
sub HMCCU_GetDutyCycle ($)
|
sub HMCCU_GetDutyCycle ($)
|
||||||
|
Loading…
Reference in New Issue
Block a user