| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832 |
- # $Id: 98_dewpoint.pm 15927 2018-01-19 15:46:47Z hotbso $
- ##############################################
- #
- # Dewpoint computing
- #
- # based / modified from 98_average.pm (C) by Rudolf Koenig
- #
- # Copyright (C) 2012 Willi Herzig
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- #
- # The GNU General Public License may also be found at http://www.gnu.org/licenses/gpl-2.0.html .
- #
- package main;
- use strict;
- use warnings;
- sub Log3($$$);
- # default maximum time_diff for dewpoint
- my $dewpoint_time_diff_default = 1; # 1 Second
- ##########################
- sub
- dewpoint_Initialize($)
- {
- my ($hash) = @_;
- $hash->{DefFn} = "dewpoint_Define";
- $hash->{NotifyFn} = "dewpoint_Notify";
- $hash->{NotifyOrderPrefix} = "10-"; # Want to be called before the rest
- $hash->{AttrList} = "disable:0,1 verbose max_timediff absFeuchte";
- }
- ##########################
- sub
- dewpoint_Define($$)
- {
- my ($hash, $def) = @_;
- my @a = split("[ \t][ \t]*", $def);
- return "wrong syntax: define <name> dewpoint (dewpoint|fan|alarm) devicename [options]"
- if(@a < 4);
- my $name = $a[0];
- my $cmd_type = $a[2]; # dewpoint, fan, alarm
- my $devname = $a[3];
- if ($cmd_type eq "dewpoint") {
- # define <name> dewpoint dewpoint devicename-regex [temp_name hum_name new_name]
- if(@a == 7) {
- $hash->{TEMP_NAME} = $a[4];
- $hash->{HUM_NAME} = $a[5];
- $hash->{NEW_NAME} = $a[6];
- } elsif (@a == 4) {
- $hash->{TEMP_NAME} = "temperature";
- $hash->{HUM_NAME} = "humidity";
- $hash->{NEW_NAME} = "dewpoint";
- } else {
- return "wrong syntax: define <name> dewpoint dewpoint devicename-regex [temp_name hum_name new_name]"
- }
- } elsif ($cmd_type eq "fan") {
- # define <name> dewpoint fan devicename-regex devicename-outside min_temp
- if (@a == 6 || @a == 7) {
- $hash->{DEVNAME_OUT} = $a[4];
- $hash->{MIN_TEMP} = $a[5];
- if (@a == 6) {
- $hash->{DIFF_TEMP} = 0;
- } else {
- $hash->{DIFF_TEMP} = $a[6];
- }
- } else {
- return "wrong syntax: define <name> dewpoint fan devicename-regex devicename-outside min_temp [diff_temp]"
- }
- } elsif ($cmd_type eq "alarm") {
- # define <name> dewpoint alarm devicename-regex devicename-reference diff_temp
- if (@a == 6) {
- $hash->{DEVNAME_REF} = $a[4];
- $hash->{DIFF_TEMP} = $a[5];
- } else {
- return "wrong syntax: define <name> dewpoint alarm devicename-regex devicename-reference diff_temp"
- }
- } else {
- return "wrong syntax: define <name> dewpoint (dewpoint|fan|alarm) devicename-regex [options]"
- }
- $hash->{CMD_TYPE} = $cmd_type;
- eval { "Hallo" =~ m/^$devname$/ };
- return "Bad regexp: $@" if($@);
- $hash->{DEV_REGEXP} = $devname;
- # set NOTIFYDEV
- $hash->{NOTIFYDEV} = 'global';
- $hash->{STATE} = "active";
- return undef;
- }
- ##########################
- sub
- dewpoint_Notify($$)
- {
- my ($hash, $dev) = @_;
- my $hashName = $hash->{NAME};
- my $devName = $dev->{NAME};
- my $re = $hash->{DEV_REGEXP};
- # listen to global in order to update our NOTIFYDEV
- if ($devName eq 'global') {
- # look for INITIALIZED or any device change
- my $rebuild;
- foreach (@{deviceEvents($dev, 0)}) {
- if ($_ =~ m/^(INITIALIZED$)|((DEFINED|MODIFIED|RENAMED|DELETED)\s+)/) {
- $rebuild = 1;
- last;
- }
- }
- if ($rebuild) {
- # notifyRegexpChanged requires complete device names separated by '|'
- # while we allow a true regexp
- # build list of devices matching our RE
- my @matched_devs = ('global', grep { m/^$re$/ } keys(%defs));
- my $notify_re = join('|', @matched_devs);
- Log3($hashName, 5, "Update NOTIFYDEV to >>$notify_re<<");
- notifyRegexpChanged($hash, $notify_re);
- }
- return undef;
- }
- # fast exit
- return "" if (!defined($re) || $devName !~ m/^$re$/);
- return "" if (AttrVal($hashName, "disable", undef));
- my $cmd_type = $hash->{CMD_TYPE};
- # dewpoint
- my $temp_name = "temperature";
- my $hum_name = "humidity";
- my $new_name = "dewpoint";
- # fan
- my $devname_out = "";
- my $min_temp = 0;
- # alarm
- my $devname_ref = "";
- my $diff_temp = 0;
- if ($cmd_type eq "dewpoint") {
- if (!defined($hash->{TEMP_NAME}) || !defined($hash->{HUM_NAME}) || !defined($hash->{NEW_NAME})) {
- # should never happen!
- Log3($hashName, 1, "Error dewpoint: TEMP_NAME || HUM_NAME || NEW_NAME undefined");
- return "";
- }
- $temp_name = $hash->{TEMP_NAME};
- $hum_name = $hash->{HUM_NAME};
- $new_name = $hash->{NEW_NAME};
- Log3($hashName, 4, "dewpoint_notify: cmd_type=$cmd_type devname=$devName dewname=$hashName, dev=$devName, "
- . "dev_regex=$re temp_name=$temp_name hum_name=$hum_name");
- } elsif ($cmd_type eq "fan") {
- if (!defined($hash->{DEVNAME_OUT}) || !defined($hash->{MIN_TEMP})) {
- # should never happen!
- Log3($hashName, 1, "Error dewpoint: DEVNAME_OUT || MIN_TEMP undefined");
- return "";
- }
- $devname_out = $hash->{DEVNAME_OUT};
- $min_temp = $hash->{MIN_TEMP};
- $diff_temp = $hash->{DIFF_TEMP};
- Log3($hashName, 4, "dewpoint_notify: cmd_type=$cmd_type devname=$devName dewname=$hashName, dev=$devName, "
- . " dev_regex=$re, devname_out=$devname_out, min_temp=$min_temp, diff_temp=$diff_temp");
- } elsif ($cmd_type eq "alarm") {
- if (!defined($hash->{DEVNAME_REF}) || !defined($hash->{DIFF_TEMP})) {
- # should never happen!
- Log3($hashName, 1, "Error dewpoint: DEVNAME_REF || DIFF_TEMP undefined");
- return "";
- }
- $devname_ref = $hash->{DEVNAME_REF};
- $diff_temp = $hash->{DIFF_TEMP};
- Log3($hashName, 4, "dewpoint_notify: cmd_type=$cmd_type devname=$devName dewname=$hashName, dev=$devName, "
- . "dev_regex=$re, devname_ref=$devname_ref, diff_temp=$diff_temp");
- } else {
- # should never happen:
- Log3($hashName, 1, "Error notify_dewpoint: <1> unknown cmd_type ".$cmd_type);
- return "";
- }
- my $nev = int(@{$dev->{CHANGED}});
- # if we use the "T H" syntax we must track the index of the state event
- my $i_state_ev;
- my $temperature = "";
- my $humidity = "";
- for (my $i = 0; $i < $nev; $i++) {
- my $s = $dev->{CHANGED}[$i];
- Log3($hashName, 5, "dewpoint_notify: s='$s'");
- ################
- # Filtering
- next if(!defined($s));
- my ($evName, $val, $rest) = split(" ", $s, 3); # resets $1
- next if(!defined($evName));
- next if(!defined($val));
- Log3($hashName, 5, "dewpoint_notify: evName='$evName' val=$val'");
- if (($evName eq "T:") && ($temp_name eq "T")) {
- $i_state_ev = $i;
- #my ($evName1, $val1, $evName2, $val2, $rest) = split(" ", $s, 5); # resets $1
- if ($s =~ /T: ([-+]?[0-9]*\.[0-9]+|[-+]?[0-9]+)/) {
- $temperature = $1;
- }
- if ($s =~ /H: [-+]?([0-9]*\.[0-9]+|[0-9]+)/) {
- $humidity = $1;
- }
- Log3($hashName, 5, "dewpoint_notify T: H:, temp=$temperature hum=$humidity");
- } elsif ($evName eq $temp_name.":") {
- $temperature = $val;
- Log3($hashName, 5, "dewpoint_notify temperature! dev=$devName, temp_name=$temp_name, temp=$temperature");
- } elsif ($evName eq $hum_name.":") {
- $humidity = $val;
- Log3($hashName, 5, "dewpoint_notify humidity! dev=$devName, hum_name=$hum_name, hum=$humidity");
- }
- }
- #if (($temperature eq "") || ($humidity eq "")) { return undef; } # no way to calculate dewpoint!
- # Check if Attribute timeout is set
- my $timeout = AttrVal($hash->{NAME}, "max_timediff", $dewpoint_time_diff_default);
- Log3($hashName, 5,"dewpoint max_timediff=$timeout");
- if (($humidity eq "") && (($temperature eq ""))) {
- return undef; # no way to calculate dewpoint!
- } elsif (($humidity eq "") && (($temperature ne ""))) {
- # temperature set, but humidity not. Try to use a valid value from the appropriate reading
- $humidity = ReadingsNum($devName, $hum_name, undef);
- my $time_diff = ReadingsAge($devName, $hum_name, undef);
- if (defined($humidity) && defined($time_diff)) {
- Log3($hashName, 5, ">dev=$devName, hum_name=$hum_name, reference humidity=$humidity ($time_diff),"
- . " temp=$temperature");
- } else { return undef; }
- if ($time_diff > 0 && $time_diff > $timeout) { return undef; }
- } elsif (($temperature eq "") && ($humidity ne "")) {
- # humdidity set, but temperature not. Try to use a valid value from the appropriate reading
- $temperature = ReadingsNum($devName, $temp_name, undef);
- my $time_diff = ReadingsAge($devName, $temp_name, undef);
- if (defined($temperature) && defined($time_diff)) {
- Log3($hashName, 5, ">dev=$devName, temp_name=$temp_name, reference temperature=$temperature ($time_diff),"
- . " hum=$humidity");
- } else { return undef; }
- if ($time_diff > 0 && $time_diff > $timeout) { return undef; }
- }
- # We found temperature and humidity. so we can calculate dewpoint first
- # Prüfen, ob humidity im erlaubten Bereich ist
- if (($humidity <= 0) || ($humidity >= 110)){
- Log3($hashName, 1, "Error dewpoint: humidity invalid: $humidity");
- return undef;
- }
- my $dewpoint = dewpoint_dewpoint($temperature, $humidity);
- Log3($hashName, 5, "dewpoint_notify: dewpoint=$dewpoint");
- my $tn = TimeNow();
- if ($cmd_type eq "dewpoint") {
- # >define <name> dewpoint dewpoint <devicename> [<temp_name> <hum_name> <new_name>]
- #
- # Calculates dewpoint for device <devicename> from temperature and humidity and write it
- # to new Reading dewpoint.
- # If optional <temp_name>, <hum_name> and <newname> is specified
- # then read temperature from reading <temp_name>, humidity from reading <hum_name>
- # and write dewpoint to reading <temp_name>.
- # if temp_name eq "T" then use temperature from state T: H:, add <newname> to the state
- # Example:
- # define dewtest1 dewpoint dewpoint .*
- # define dewtest2 dewpoint dewpoint .* T H D
- readingsBeginUpdate($dev);
- my $current;
- my $sensor;
- my $aFeuchte = AttrVal($hash->{NAME},"absFeuchte", undef);
- if (defined($aFeuchte)) {
- $sensor = "absFeuchte";
- $current = dewpoint_absFeuchte($temperature, $humidity);
- readingsBulkUpdate($dev, $sensor, $current);
- Log3($hashName, 5, "dewpoint absFeuchte= $current");
- $aFeuchte = "A: " . $current;
- }
- $sensor = $new_name;
- if ($temp_name ne "T") {
- $current = $dewpoint;
- readingsBulkUpdate($dev, $sensor, $current);
- readingsEndUpdate($dev, 1);
- } else {
- # explicit manipulation of STATE here
- # first call readingsEndUpdate to finish STATE processing in the referenced device...
- readingsEndUpdate($dev, 1);
- # ... then update STATE
- # STATE begins with "T:". append dewpoint or insert before BAT
- my $lastval = $dev->{CHANGED}[$i_state_ev];
- if ($lastval =~ /BAT:/) {
- $current = $lastval;
- $current =~ s/BAT:/$sensor: $dewpoint BAT:/g;
- } elsif ($lastval =~ /<</) {
- $current = $lastval;
- $current =~ s/<</$sensor:$dewpoint <</g;
- } else {
- $current = $lastval." ".$sensor.": ".$dewpoint;
- if (defined($aFeuchte)) {
- $current = $current." ".$aFeuchte;
- }
- }
- $dev->{STATE} = $current;
- # the state event must be REPLACED
- $dev->{CHANGED}[$i_state_ev] = $current;
- }
- # remove cached "state:..." events if any
- $dev->{CHANGEDWITHSTATE} = [];
- Log3($hashName, 5, "dewpoint_notify: current=$current");
- } elsif ($cmd_type eq "fan") {
- # >define <name> dewpoint fan devicename devicename-outside min-temp [diff-temp]
- #
- # This define may be used to turn an fan on or off if the outside air has less
- # water
- #
- # - Generate reading/event "fan: on" if (dewpoint of <devicename-outside>) + diff_temp is lower
- # than dewpoint of <devicename> and temperature of <devicename-outside> is >= min-temp
- # and reading "fan" was not already "on".
- # - Generate reading/event "fan: off": else and if reading "fan" was not already "off".
- Log3($hashName, 5, "dewpoint_notify: fan devname_out=$devname_out, min_temp=$min_temp, diff_temp=$diff_temp");
- my $sensor;
- my $current;
- if (exists $defs{$devname_out}{READINGS}{temperature}{VAL} && exists $defs{$devname_out}{READINGS}{humidity}{VAL}) {
- my $temperature_out = $defs{$devname_out}{READINGS}{temperature}{VAL};
- my $humidity_out = $defs{$devname_out}{READINGS}{humidity}{VAL};
- my $dewpoint_out = dewpoint_dewpoint($temperature_out, $humidity_out);
- Log3($hashName, 5, "dewpoint_notify: fan dewpoint_out=$dewpoint_out");
- if (($dewpoint_out + $diff_temp) < $dewpoint && $temperature_out >= $min_temp) {
- $current = "on";
- Log3($hashName, 3, "dewpoint_notify: fan ON");
- } else {
- $current = "off";
- Log3($hashName, 3, "dewpoint_notify: fan OFF");
- }
- $sensor = "fan";
- if (!exists $defs{$devName}{READINGS}{$sensor}{VAL} || $defs{$devName}{READINGS}{$sensor}{VAL} ne $current) {
- Log3($hashName, 3, "dewpoint_notify: CHANGE fan $current");
- $dev->{READINGS}{$sensor}{TIME} = $tn;
- $dev->{READINGS}{$sensor}{VAL} = $current;
- $dev->{CHANGED}[$nev++] = $sensor . ": " . $current;
- }
- } else {
- Log3($hashName, 1, "dewpoint_notify: fan devname_out=$devname_out no temperature or humidity available"
- . " for dewpoint calculation");
- }
- } elsif ($cmd_type eq "alarm") {
- # >define <name> dewpoint alarm devicename devicename-reference diff
- #
- # - Generate reading/event "alarm: on" if temperature of <devicename-reference>-<diff> is lower
- # than dewpoint of <devicename> and reading "alarm" was not already "on".
- # - Generate reading/event "alarm: off" if temperature of <devicename-reference>-<diff> is higher
- # than dewpoint of <devicename> and reading "alarm" was not already "off".
- #
- # You have different options to use this define:
- # * Use a temperature sensor in or on the wall (<devicename-reference>) and use a temp/hum sensor
- # to measure the dewpoint of the air. Alarm if the temperature of the wall is lower than the dewpoint of the air.
- # In this case the water of the air will condense on the wall because the wall is cold.
- # Example: define alarmtest dewpoint alarm roomsensor wallsensor 0
- # * If you do not have a temperature sensor in/on the wall, you may also compare the rooms dewpoint to the
- # temperature of the same or another inside sensor. If you think that your walls are normally 5 degrees colder
- # than the inside temperature, set diff to 5.
- # Example: define alarmtest dewpoint alarm roomsensor roomsensor 5
- Log3($hashName, 5, "dewpoint_notify: alarm devname_ref=$devname_ref, diff_temp=$diff_temp");
- my $sensor;
- my $current;
- if (exists $defs{$devname_ref}{READINGS}{temperature}{VAL}) {
- my $temperature_ref = $defs{$devname_ref}{READINGS}{temperature}{VAL};
- Log3($hashName, 5, "dewpoint_notify: alarm temperature_ref=$temperature_ref");
- if ($temperature_ref - $diff_temp < $dewpoint) {
- $current = "on";
- Log3($hashName, 3, "dewpoint_notify: alarm ON");
- } else {
- $current = "off";
- Log3($hashName, 3, "dewpoint_notify: alarm OFF");
- }
- $sensor = "alarm";
- if (!exists $defs{$devName}{READINGS}{$sensor}{VAL} || $defs{$devName}{READINGS}{$sensor}{VAL} ne $current) {
- Log3($hashName, 5, "dewpoint_notify: CHANGE alarm $current");
- $dev->{READINGS}{$sensor}{TIME} = $tn;
- $dev->{READINGS}{$sensor}{VAL} = $current;
- $dev->{CHANGED}[$nev++] = $sensor . ": " . $current;
- }
- } else {
- Log3($hashName, 1, "dewpoint_notify: alarm devname_out=$devname_out no temperature or humidity available"
- . " for dewpoint calculation");
- }
- } else {
- # should never happen:
- Log3($hashName, 1, "Error notify_dewpoint: <2> unknown cmd_type ".$cmd_type);
- return "";
- }
- return undef;
- }
- # -----------------------------
- # Dewpoint calculation.
- # 'Magnus formula'
- #
- # Parameters from https://de.wikipedia.org/wiki/Taupunkt#S.C3.A4ttigungsdampfdruck
- # Good summary of formulas in http://www.wettermail.de/wetter/feuchte.html
- my $E0 = 0.6112; # saturation pressure at T=0 °C
- my @ab_gt0 = (17.62, 243.12); # T>0
- my @ab_le0 = (22.46, 272.6); # T<=0 over ice
- ### ** Public interface ** keep stable
- # vapour pressure in kPa
- sub dewpoint_vp($$)
- {
- my ($T, $Hr) = @_;
- my ($a, $b);
- if ($T > 0) {
- ($a, $b) = @ab_gt0;
- } else {
- ($a, $b) = @ab_le0;
- }
- return 0.01 * $Hr * $E0 * exp($a * $T / ($T + $b));
- }
- ### ** Public interface ** keep stable
- # dewpoint in °C
- sub
- dewpoint_dewpoint($$)
- {
- my ($T, $Hr) = @_;
- if ($Hr == 0) {
- Log(1, "Error: dewpoint() Hr==0 !: temp=$T, hum=$Hr");
- return undef;
- }
- my ($a, $b);
- if ($T > 0) {
- ($a, $b) = @ab_gt0;
- } else {
- ($a, $b) = @ab_le0;
- }
- # solve vp($dp, 100) = vp($T,$Hr) for $dp
- my $v = log(dewpoint_vp($T, $Hr) / $E0);
- my $D = $a - $v;
- # can this ever happen for valid input?
- if ($D == 0) {
- Log(1, "Error: dewpoint() D==0 !: temp=$T, hum=$Hr");
- return undef;
- }
- return round($b * $v / $D, 1);
- }
- ### ** Public interface ** keep stable
- # absolute Feuchte in g Wasserdampf pro m3 Luft
- sub
- dewpoint_absFeuchte ($$)
- {
- my ($T, $Hr) = @_;
- # 110 ?
- if (($Hr < 0) || ($Hr > 110)) {
- Log(1, "Error dewpoint: humidity invalid: $Hr");
- return "";
- }
- my $DD = dewpoint_vp($T, $Hr);
- my $AF = 1.0E6 * (18.016 / 8314.3) * ($DD / (273.15 + $T));
- return round($AF, 1);
- }
- 1;
- =pod
- =item helper
- =item summary compute dewpoint and/or generate events for starting a fan
- =item summary_DE berechne Taupunkt und/oder erzeuge events zum starten eines Lüfters
- =begin html
- <a name="dewpoint"></a>
- <h3>dewpoint</h3>
- <ul>
- Dewpoint calculations. Offers three different ways to use dewpoint: <br>
- <ul>
- <li><b>dewpoint</b><br>
- Compute additional event dewpoint from a sensor offering temperature and humidity.</li>
- <li><b>fan</b><br>
- Generate a event to turn a fan on if the outside air has less water than the inside.</li>
- <li><b>alarm</b><br>
- Generate a mold alarm if a reference temperature is lower that the current dewpoint.</li>
- <br>
- </ul>
- <a name="dewpointdefine"></a>
- <b>Define</b>
- <ul>
- <code>define <name> dewpoint dewpoint <devicename-regex> [<temp_name> <hum_name> <new_name>]</code><br>
- <br>
- <ul>
- Calculates dewpoint for device <devicename-regex> from temperature and humidity
- and write it to a new reading named dewpoint.
- If optional <temp_name>, <hum_name> and <new_name> is specified
- then read temperature from reading <temp_name>, humidity from reading <hum_name>
- and write the calculated dewpoint to reading <new_name>.<br>
- If <temp_name> is T then use temperature from state T: H:, add <new_name> to the state.
- </ul>
- <br>
- Example:<PRE>
- # Compute the dewpoint for the temperature/humidity
- # events of the temp1 device and generate reading dewpoint.
- define dew_temp1 dewpoint dewpoint temp1
- define dew_temp1 dewpoint dewpoint temp1 temperature humidity dewpoint
- # Compute the dewpoint for the temperature/humidity
- # events of all devices offering temperature and humidity
- # and generate reading dewpoint.
- define dew_all dewpoint dewpoint .*
- define dew_all dewpoint dewpoint .* temperature humidity dewpoint
- # Compute the dewpoint for the temperature/humidity
- # events of the device Aussen_1 offering temperature and humidity
- # and insert is into STATE.
- define dew_state dewpoint dewpoint Aussen_1 T H D
- # Compute the dewpoint for the temperature/humidity
- # events of all devices offering temperature and humidity
- # and insert the result into the STATE.
- # Example STATE: "T: 10 H: 62.5" will change to
- # "T: 10 H: 62.5 D: 3.2"
- define dew_state dewpoint dewpoint .* T H D
- </PRE>
- </ul>
- <ul>
- <code>define <name> dewpoint fan <devicename-regex> <devicename-outside> <min-temp> [<diff_temp>]</code><br>
- <br>
- <ul>
- May be used to turn an fan on or off if the outside air has less water.
- <ul>
- <li>
- Generate event "fan: on" if (dewpoint of <devicename-outside>) + <diff_temp> is lower
- than dewpoint of <devicename> and temperature of <devicename-outside> is >= min-temp
- and reading "fan" was not already "on". The event will be generated for <devicename>. Parameter <diff-temp> is optional</li>
- <li>Generate event "fan: off": else and if reading "fan" was not already "off".</li>
- </ul>
- </ul>
- <br>
- Example:<PRE>
- # Generate event "fan: on" when dewpoint of Aussen_1 is first
- # time lower than basement_tempsensor and outside temperature is >= 0
- # and change it to "fan: off" is this condition changes.
- # Set a switch on/off (fan_switch) depending on the state.
- define dew_fan1 dewpoint fan basement_tempsensor Aussen_1 0
- define dew_fan1_on notify basement_tempsensor.*fan:.*on set fan_switch on
- define dew_fan1_off notify basement_tempsensor.*fan:.*off set fan_switch off
- </PRE>
- </ul>
- <ul>
- <code>define <name> dewpoint alarm <devicename-regex> <devicename-reference> <diff-temp></code><br>
- <br>
- <ul>
- Generate a mold alarm if a reference temperature is lower that the current dewpoint.
- <ul>
- <li>
- Generate reading/event "alarm: on" if temperature of <devicename-reference> - <diff-temp> is lower
- than dewpoint of <devicename> and reading "alarm" was not already "on". The event will be generated for <devicename>.</li>
- <li>Generate reading/event "alarm: off" if temperature of <devicename-reference> - <diff-temp> is higher than dewpoint of <devicename> and reading "alarm" was not already "off".</li>
- </ul>
- </ul>
- <br>
- Example:<PRE>
- # Using a wall temperature sensor (wallsensor) and a temp/hum sensor
- # (roomsensor) to alarm if the temperature of the wall is lower than
- # the dewpoint of the air. In this case the water of the air will
- # condense on the wall because the wall is cold.
- # Set a switch on (alarm_siren) if alarm is on using notify.
- define dew_alarm1 dewpoint alarm roomsensor wallsensor 0
- define roomsensor_alarm_on notify roomsensor.*alarm:.*on set alarm_siren on
- define roomsensor_alarm_off notify roomsensor.*alarm:.*off set alarm_siren off
- # If you do not have a temperature sensor in/on the wall, you may also
- # compare the rooms dewpoint to the temperature of the same or another
- # inside sensor. Alarm is temperature is 5 degrees colder than the
- # inside dewpointinside.
- define dev_alarm2 dewpoint alarm roomsensor roomsensor 5
- </PRE>
- </ul>
- <a name="dewpointset"></a>
- <b>Set</b> <ul>N/A</ul><br>
- <a name="dewpointget"></a>
- <b>Get</b> <ul>N/A</ul><br>
- <a name="dewpointattr"></a>
- <b>Attributes</b>
- <ul>
- <li><a href="#disable">disable</a></li>
- <li>absFeuchte</li><br>
- <ul>
- AbsFeuchte also becomes by the absolute humidity set the attribute into the Readings of all things.
- One can by these show information also in the status.
- Example: (<Adapter> = the FHEM name of the adapter this one you must change)
- <PRE>
- stateFormat:
- {sprintf("T: %.1f H: %.1f D: %.1f A: %.1f", ReadingsVal("<Adapter>","temperature",0), ReadingsVal("<Adapter>","H",0), ReadingsVal("<Adapter>","dewpoint",0), ReadingsVal("<Adapter>","absFeuchte",0))}
- </PRE>
- </ul>
- <li>max_timediff<br>
- Maximum time difference in seconds allowed between the temperature and humidity values for a device. dewpoint uses the Readings for temperature or humidity if they are not delivered in the event. This is necessary for using dewpoint with event-on-change-reading. Also needed for sensors that do deliver temperature and humidity in different events like for example technoline sensors TX3TH.<br>
- If not set default is 1 second.
- <br><br>
- Examples:<PRE>
- # allow maximum time difference of 60 seconds
- define dew_all dewpoint dewpoint .*
- attr dew_all max_timediff 60
- </li><br>
- </ul>
- </ul>
- =end html
- =begin html_DE
- <a name="dewpoint"></a>
- <h3>dewpoint</h3>
- <ul>
- Berechnungen des Taupunkts. Es gibt drei Varianten, das Modul dewpoint zu verwenden: <br>
- <ul>
- <li><b>dewpoint</b>: Taupunkt<br>
- Erzeugt ein zusätzliches Ereignis "dewpoint" aus Temperatur- und Luftfeuchtewerten eines Fühlers.</li>
- <li><b>fan</b>: Lüfter<br>
- Erzeugt ein Ereignis, um einen Lüfter einzuschalten, wenn die Außenluft
- weniger Wasser als die Raumluft enthält.</li>
- <li><b>alarm</b>: Alarm<br>
- Erzeugt einen Schimmel-Alarm, wenn eine Referenz-Temperatur unter den Taupunkt fällt.</li>
- </ul>
- <br/>
- <a name="dewpointdefine"></a>
- <b>Define</b>
- <ul>
- <code>define <name> dewpoint dewpoint <devicename-regex> [<temp_name>
- <hum_name> <new_name>]</code><br>
- <br/>
- Berechnet den Taupunkt des Geräts <devicename-regex> basierend auf Temperatur
- und Luftfeuchte und erzeugt daraus ein neues Reading namens dewpoint.<br/>
- Wenn <temp_name>, <hum_name> und <new_name> angegeben sind,
- werden die Temperatur aus dem Reading <temp_name>, die Luftfeuchte aus dem
- Reading <hum_name> gelesen und als berechneter Taupunkt ins Reading <new_name> geschrieben.<br>
- Wenn <temp_name> T lautet, wird die Temperatur aus state T: H: benutzt
- und <new_name> zu state hinzugefügt.
- <br/>
- Beispiele:
- <pre>
- # Berechnet den Taupunkt aufgrund von Temperatur und Luftfeuchte
- # in Ereignissen, die vom Gerät temp1 erzeugt wurden und erzeugt ein Reading dewpoint.
- define dew_temp1 dewpoint dewpoint temp1
- define dew_temp1 dewpoint dewpoint temp1 temperature humidity dewpoint
- # Berechnet den Taupunkt aufgrund von Temperatur und Luftfeuchte
- # in Ereignissen, die von allen Geräten erzeugt wurden die diese Werte ausgeben
- # und erzeugt ein Reading dewpoint.
- define dew_all dewpoint dewpoint .*
- define dew_all dewpoint dewpoint .* temperature humidity dewpoint
- # Berechnet den Taupunkt aufgrund von Temperatur und Luftfeuchte
- # in Ereignissen, die vom Gerät Aussen_1 erzeugt wurden und ergänzt
- # mit diesem Wert den Status STATE.
- define dew_state dewpoint dewpoint Aussen_1 T H D
- # Berechnet den Taupunkt aufgrund von Temperatur und Luftfeuchte
- # in Ereignissen, die von allen Geräten erzeugt wurden die diese Werte ausgeben
- # und ergänzt mit diesem Wert den Status STATE.
- # Beispiel STATE: "T: 10 H: 62.5" wird verändert nach
- # "T: 10 H: 62.5 D: 3.2"
- define dew_state dewpoint dewpoint .* T H D
- </pre>
- <br/>
- <br/>
- <code>define <name> dewpoint fan <devicename-regex> <devicename-outside> <min-temp> [<diff_temp>]</code><br>
- <br>
- <ul>
- <li>Erzeugt ein Ereignis, um einen Lüfter einzuschalten, wenn die Außenluft
- weniger Wasser als die Raumluft enthält.</li>
- <li>Erzeugt das Ereignis "fan: on" wenn (Taupunkt von <devicename-outside>) +
- <diff_temp> ist niedriger als der Taupunkt von <devicename> und die Temperatur
- von <devicename-outside> >= min-temp ist. Das Ereignis wird nur erzeugt wenn das
- Reading "fan" nicht schon "on" war. Das Ereignis wird für das Gerät <devicename> erzeugt.
- Der Parameter <diff-temp> ist optional.</li>
- <li>Andernfalls wird das Ereignis "fan: off" erzeugt, wenn das Reading von "fan" nicht bereits "off" war.</li>
- </ul>
- <br>
- Beispiel:
- <pre>
- # Erzeugt das Ereignis "fan: on", wenn der Taupunkt des Geräts Aussen_1 zum ersten Mal
- # niedriger ist als der Taupunkt des Geräts basement_tempsensor und die
- # Außentemperatur >= 0 ist und wechselt nach "fan: off" wenn diese Bedingungen nicht
- # mehr zutreffen.
- # Schaltet den Schalter fan_switch abhängig vom Zustand ein oder aus.
- define dew_fan1 dewpoint fan basement_tempsensor Aussen_1 0
- define dew_fan1_on notify basement_tempsensor.*fan:.*on set fan_switch on
- define dew_fan1_off notify basement_tempsensor.*fan:.*off set fan_switch off
- </pre>
- <code>define <name> dewpoint alarm <devicename-regex> <devicename-reference> <diff-temp></code><br>
- <br>
- <ul>
- <li>Erzeugt einen Schimmel-Alarm, wenn eine Referenz-Temperatur unter den Taupunkt fällt.</li>
- <li>Erzeugt ein Reading/Ereignis "alarm: on" wenn die Temperatur von
- <devicename-reference> - <diff-temp> unter den Taupunkt von
- <devicename> fällt und das Reading "alarm" nicht bereits "on" ist.
- Das Ereignis wird für <devicename> erzeugt.</li>
- <li>Erzeugt ein Reading/Ereignis "alarm: off" wenn die Temperatur von
- <devicename-reference> - <diff-temp> über den Taupunkt
- von <devicename> steigt und das Reading "alarm" nicht bereits "off" ist.</li>
- </ul>
- <br>
- Beispiel:
- <pre>
- # Es wird ein Anlegefühler (Wandsensor) und ein Thermo-/Hygrometer (Raumfühler)
- # verwendet, um einen Alarm zu erzeugen, wenn die Wandtemperatur
- # unter den Taupunkt der Luft fällt. In diesem Fall würde sich Wasser an der Wand
- # niederschlagen (kondensieren), weil die Wand zu kalt ist.
- # Der Schalter einer Sirene (alarm_siren) wird über ein notify geschaltet.
- define dew_alarm1 dewpoint alarm roomsensor wallsensor 0
- define roomsensor_alarm_on notify roomsensor.*alarm:.*on set alarm_siren on
- define roomsensor_alarm_off notify roomsensor.*alarm:.*off set alarm_siren off
- # Ohne Wandsensor lässt sich auch der Taupunkt eines Raums mit der Temperatur desselben
- # (oder eines anderen) Fühlers vergleichen.
- # Die Alarmtemperatur ist 5 Grad niedriger gesetzt als die des Vergleichsthermostats.
- define dev_alarm2 dewpoint alarm roomsensor roomsensor 5
- </pre>
- </ul>
- <a name="dewpointset"></a>
- <b>Set</b> <ul>N/A</ul><br>
- <a name="dewpointget"></a>
- <b>Get</b> <ul>N/A</ul><br>
- <a name="dewpointattr"></a>
- <b>Attributes</b>
- <ul>
- <li><a href="#disable">disable</a></li>
- <li>absFeuchte</li><br>
- <ul>
- Durch setzen des Attributes absFeuchte wird in den Readings auch die absolute Feuchte mit ausgerechnet.
- Durch <a href="#stateFormat">stateFormat</a> kann man diese Info auch im Status anzeigen.
- Beispiel: (<Adapter> = Der FHEM Name des Adapters der geändert werden muss)
- <pre>
- stateFormat:
- {sprintf("T: %.1f H: %.1f D: %.1f A: %.1f", ReadingsVal("<Adapter>","temperature",0), ReadingsVal("<Adapter>","H",0), ReadingsVal("<Adapter>","dewpoint",0), ReadingsVal("<Adapter>","absFeuchte",0))}
- </pre>
- </ul>
- <li>max_timediff</li><br>
- <ul>
- Maximale erlaubter Zeitunterschied in Sekunden zwischen den Temperatur- und Luftfeuchtewerten eines
- Geräts. dewpoint verwendet Readings von Temperatur oder Luftfeuchte wenn sie nicht im Ereignis
- mitgeliefert werden. Das ist sowohl für den Betrieb mit event-on-change-reading nötig
- als auch bei Sensoren die Temperatur und Luftfeuchte in getrennten Ereignissen kommunizieren
- (z.B. Technoline Sensoren TX3TH).<br/>
- Der Standardwert ist 1 Sekunde.
- <br><br>
- Beispiel:
- <pre>
- # Maximal erlaubter Zeitunterschied soll 60 Sekunden sein
- define dew_all dewpoint dewpoint .*
- attr dew_all max_timediff 60
- </pre>
- </ul>
- </ul>
- </ul>
- =end html_DE
- =cut
|