mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-07 16:59:18 +00:00
917 lines
34 KiB
Perl
917 lines
34 KiB
Perl
##############################################
|
||
# $Id$
|
||
#
|
||
# The purpose of this module is to support serval
|
||
# weather sensors like WS-0101 (Sender 868MHz ASK Epmfänger RX868SH-DV elv)
|
||
#
|
||
# 2015 Sidey79, pejonp
|
||
# 2019 Ralf9
|
||
# 2020 Sidey79, HomeAutoUser
|
||
#
|
||
# 20170922: rainTotal --> rain_total
|
||
# 20170923: windDirAverage - https://forum.fhem.de/index.php/topic,75225.msg669950.html#msg669950 @SabineT
|
||
# 20191003: UV/Solar Nachrichten WH2315 - https://forum.fhem.de/index.php/topic,67587.msg980092.html#msg980092 @Ralf
|
||
# 20200126: PERL WARNING - https://forum.fhem.de/index.php/topic,67587.msg982425.html#msg982425 @rob
|
||
# 20200127: Corrected line indents @HomeAutoUser
|
||
# 20200127: fix, WindDirAverage return undef --> return $windDirection_old @HomeAutoUser
|
||
# 20200127: revised commandref @HomeAutoUser
|
||
#
|
||
|
||
package main;
|
||
|
||
use strict;
|
||
use warnings;
|
||
|
||
# werden benötigt, aber im Programm noch extra abgetestet
|
||
#use Digest::CRC qw(crc);
|
||
#use Math::Trig;
|
||
|
||
sub SD_WS09_Initialize($) {
|
||
my ($hash) = @_;
|
||
|
||
$hash->{Match} = "^P9#F[A-Fa-f0-9]+"; ## pos 7 ist aktuell immer 0xF
|
||
$hash->{DefFn} = "SD_WS09_Define";
|
||
$hash->{UndefFn} = "SD_WS09_Undef";
|
||
$hash->{ParseFn} = "SD_WS09_Parse";
|
||
$hash->{AttrFn} = "SD_WS09_Attr";
|
||
$hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 showtime:1,0 "
|
||
."model:CTW600,WH1080 ignore:0,1 "
|
||
."windKorrektur:-3,-2,-1,0,1,2,3 "
|
||
."Unit_of_Wind:m/s,km/h,ft/s,mph,bft,knot "
|
||
."WindDirAverageTime "
|
||
."WindDirAverageMinSpeed "
|
||
."WindDirAverageDecay "
|
||
."$readingFnAttributes ";
|
||
$hash->{AutoCreate} =
|
||
{ "SD_WS09.*" => { ATTR => "event-min-interval:.*:300 event-on-change-reading:.* windKorrektur:.*:0 verbose:5" , FILTER => "%NAME", GPLOT => "WH1080wind4:windSpeed/windGust,", autocreateThreshold => "2:180"} };
|
||
}
|
||
|
||
#############################
|
||
sub SD_WS09_Define($$) {
|
||
my ($hash, $def) = @_;
|
||
my @a = split("[ \t][ \t]*", $def);
|
||
|
||
return "wrong syntax: define <name> SD_WS09 <code> ".int(@a) if(int(@a) < 3 );
|
||
|
||
$hash->{CODE} = $a[2];
|
||
$hash->{lastMSG} = "";
|
||
$hash->{bitMSG} = "";
|
||
|
||
$modules{SD_WS09}{defptr}{$a[2]} = $hash;
|
||
$hash->{STATE} = "Defined";
|
||
|
||
my $model = $a[2];
|
||
$model =~ s/_.*$//;
|
||
$hash->{MODEL} = $model;
|
||
|
||
my $name= $hash->{NAME};
|
||
return undef;
|
||
}
|
||
|
||
#####################################
|
||
sub SD_WS09_Undef($$) {
|
||
my ($hash, $name) = @_;
|
||
|
||
delete($modules{SD_WS09}{defptr}{$hash->{CODE}})
|
||
if(defined($hash->{CODE}) &&
|
||
defined($modules{SD_WS09}{defptr}{$hash->{CODE}}));
|
||
return undef;
|
||
}
|
||
|
||
###################################
|
||
sub SD_WS09_Parse($$) {
|
||
my ($iohash, $msg) = @_;
|
||
my $name = $iohash->{NAME};
|
||
my (undef ,$rawData) = split("#",$msg);
|
||
my @winddir_name=("N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW");
|
||
my %uowind_unit= ("m/s",'1',"km/h",'3.6',"ft/s",'3.28',"bft",'-1',"mph",'2.24',"knot",'1.94');
|
||
my %uowind_index = ("m/s",'0',"km/h",'1',"ft/s",'2',"mph",'3',"knot",'4',"bft",'5');
|
||
my $hlen = length($rawData);
|
||
my $blen = $hlen * 4;
|
||
my $bitData = unpack("B$blen", pack("H$hlen", $rawData));
|
||
my $bitData2;
|
||
my $bitData20;
|
||
my $rain = 0;
|
||
my $deviceCode = 0;
|
||
my $model = "undef"; # 0xFFA -> WS0101/WH1080 alles andere -> CTW600
|
||
my $modelid;
|
||
my $windSpeed = 0;
|
||
my $windSpeed_kmh;
|
||
my $windSpeed_fts;
|
||
my $windSpeed_bft;
|
||
my $windSpeed_mph;
|
||
my $windSpeed_kn;
|
||
my $windguest = 0;
|
||
my $windguest_kmh;
|
||
my $windguest_fts;
|
||
my $windguest_bft;
|
||
my $windguest_mph;
|
||
my $windguest_kn;
|
||
my $sensdata;
|
||
my $id;
|
||
my $bat = 0;
|
||
my $temp = 0;
|
||
my $hum = 1;
|
||
my $windDirection = 1 ;
|
||
my $windDirectionText = "N";
|
||
my $windDirectionDegree = 0;
|
||
my $FOuvo ; # UV data nybble ?
|
||
my $FOlux ; # Lux High byte (full scale = 4,000,000?) # Lux Middle byte # Lux Low byte, Unit = 0.1 Lux (binary)
|
||
my $rr2 ;
|
||
my $state;
|
||
my $msg_vor = 'P9#';
|
||
my $minL1 = 70;
|
||
my $minL2 = 60;
|
||
my $whid;
|
||
my $wh;
|
||
my $rawData_merk;
|
||
my $wfaktor = 1;
|
||
my @windstat;
|
||
my $syncpos;
|
||
|
||
if ($hlen < 20) { # WH3080 UV/Solar
|
||
$syncpos = index($bitData,"1111110111"); # FF7 UV/Solar
|
||
if ($syncpos >= 0 && $syncpos < 3) {
|
||
$model = "WH1080";
|
||
if ($syncpos < 2) {
|
||
$rawData = SD_WS09_SHIFT($iohash, $rawData);
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_0 raw:$rawData";
|
||
}
|
||
if ($syncpos == 0) {
|
||
$rawData = SD_WS09_SHIFT($iohash, $rawData);
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_1 raw:$rawData";
|
||
}
|
||
} else {
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse WH1080 EXIT (sync no found): msg=$rawData length:".length($bitData);
|
||
return "";
|
||
}
|
||
} else {
|
||
$syncpos= index($bitData,"11111110"); #7x1 1x0 preamble
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse0 msg=$rawData Bin=$bitData syncp=$syncpos length:".length($bitData) ;
|
||
|
||
if ($syncpos ==-1 || length($bitData)-$syncpos < $minL2) {
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse EXIT: msg=$rawData syncp=$syncpos length:".length($bitData) ;
|
||
return undef;
|
||
}
|
||
}
|
||
|
||
my $crcwh1080 = AttrVal($iohash->{NAME},'WS09_CRCAUS',0);
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse CRC_AUS:$crcwh1080 " ;
|
||
$rawData_merk = $rawData;
|
||
|
||
my $rc = eval
|
||
{
|
||
require Digest::CRC;
|
||
Digest::CRC->import();
|
||
1;
|
||
};
|
||
|
||
# test ob Digest::CRC geladen
|
||
if($rc) {
|
||
$rr2 = SD_WS09_CRCCHECK($rawData);
|
||
if ($model eq "WH1080") { # FF7 UV/Solar
|
||
if ($rr2 != 0) {
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse WH1080: sensorTyp: 7 UV/Solar, CRC_Error Exit: raw:$rawData CRC=$rr2";
|
||
return "";
|
||
}
|
||
} else {
|
||
if ($rr2 == 0 || (($rr2 == 49) && ($crcwh1080 == 2)) ) {
|
||
# 1. OK
|
||
$model = "WH1080";
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_0 OK raw:$rawData crc:$rr2";
|
||
} else {
|
||
# 1. nok
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_1 NOK raw:$rawData crc:$rr2 -> shift";
|
||
$rawData = SD_WS09_SHIFT($iohash, $rawData);
|
||
$rr2 = SD_WS09_CRCCHECK($rawData);
|
||
if ($rr2 == 0 || (($rr2 == 49) && ($crcwh1080 == 2)) ) {
|
||
# 2.ok
|
||
$msg = $msg_vor.$rawData;
|
||
$model = "WH1080";
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_2 OK raw:$rawData msg:$msg crc:$rr2";
|
||
} else {
|
||
# 2. nok
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_3 NOK raw:$rawData crc:$rr2 -> shift";
|
||
$rawData = SD_WS09_SHIFT($iohash, $rawData);
|
||
$rr2 = SD_WS09_CRCCHECK($rawData);
|
||
if ($rr2 == 0 || (($rr2 == 49) && ($crcwh1080 == 2)) ) {
|
||
# 3. ok
|
||
$msg = $msg_vor.$rawData;
|
||
$model = "WH1080";
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_4 OK raw:$rawData msg:$msg crc:$rr2";
|
||
} else {
|
||
# 3. nok
|
||
$rawData = $rawData_merk;
|
||
$msg = $msg_vor.$rawData;
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_5 NOK raw:$rawData msg:$msg crc:$rr2";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
# Digest::CRC failed
|
||
Log3 $iohash, 1, "$name: SD_WS09 CRC_not_load: Modul Digest::CRC fehlt: cpan install Digest::CRC or sudo apt-get install libdigest-crc-perl" ;
|
||
return "";
|
||
}
|
||
|
||
$hlen = length($rawData);
|
||
$blen = $hlen * 4;
|
||
$bitData = unpack("B$blen", pack("H$hlen", $rawData));
|
||
Log3 $iohash, 4, "$name: SD_WS09_CRC_test2 rwa:$rawData msg:$msg CRC:".SD_WS09_CRCCHECK($rawData) ;
|
||
|
||
if( $model eq "WH1080") {
|
||
$sensdata = substr($bitData,8);
|
||
$whid = substr($sensdata,0,4);
|
||
Log3 $iohash, 5, "$name: SD_WS09_Parse_0 whid=$whid";
|
||
|
||
# A Wettermeldungen
|
||
if( $whid eq '1010' ){
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_1 msg=$sensdata length:".length($sensdata) ;
|
||
$model = "WH1080";
|
||
$id = SD_WS09_bin2dec(substr($sensdata,4,8));
|
||
$bat = (SD_WS09_bin2dec((substr($sensdata,64,4))) == 0) ? 'ok':'low' ; # decode battery = 0 --> ok
|
||
$temp = (SD_WS09_bin2dec(substr($sensdata,12,12)) - 400)/10;
|
||
$hum = SD_WS09_bin2dec(substr($sensdata,24,8));
|
||
$windDirection = SD_WS09_bin2dec(substr($sensdata,68,4));
|
||
$windDirectionText = $winddir_name[$windDirection];
|
||
$windDirectionDegree = $windDirection * 360 / 16;
|
||
$windSpeed = round((SD_WS09_bin2dec(substr($sensdata,32,8))* 34)/100,01);
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_2 ".$model." id:$id, Windspeed bit: ".substr($sensdata,32,8)." Dec: " . $windSpeed ;
|
||
$windguest = round((SD_WS09_bin2dec(substr($sensdata,40,8)) * 34)/100,01);
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_3 ".$model." id:$id, Windguest bit: ".substr($sensdata,40,8)." Dec: " . $windguest ;
|
||
$rain = SD_WS09_bin2dec(substr($sensdata,52,12)) * 0.3;
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_4 ".$model." id:$id, Rain bit: ".substr($sensdata,52,12)." Dec: " . $rain ;
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_5 ".$model." id:$id, bat:$bat, temp=$temp, hum=$hum, winddir=$windDirection:$windDirectionText wS=$windSpeed, wG=$windguest, rain=$rain";
|
||
|
||
# B DCF-77 Zeitmeldungen vom Sensor
|
||
} elsif ( $whid eq '1011' ) {
|
||
my $hrs1 = substr($sensdata,16,8);
|
||
my $hrs;
|
||
my $mins;
|
||
my $sec;
|
||
my $mday;
|
||
my $month;
|
||
my $year;
|
||
$id = SD_WS09_bin2dec(substr($sensdata,4,8));
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_6 Zeitmeldung0: HRS1=$hrs1 id:$id" ;
|
||
$hrs = sprintf "%02d" , SD_WS09_BCD2bin(substr($sensdata,18,6) ) ; # Stunde
|
||
$mins = sprintf "%02d" , SD_WS09_BCD2bin(substr($sensdata,24,8)); # Minute
|
||
$sec = sprintf "%02d" ,SD_WS09_BCD2bin(substr($sensdata,32,8)); # Sekunde
|
||
#day month year
|
||
$year = SD_WS09_BCD2bin(substr($sensdata,40,8)); # Jahr
|
||
$month = sprintf "%02d" ,SD_WS09_BCD2bin(substr($sensdata,51,5)); # Monat
|
||
$mday = sprintf "%02d" ,SD_WS09_BCD2bin(substr($sensdata,56,8)); # Tag
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_7 Zeitmeldung1: id:$id, msg=$rawData length:".length($bitData) ;
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_8 Zeitmeldung2: id:$id, HH:mm:ss - ".$hrs.":".$mins.":".$sec ;
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_9 Zeitmeldung3: id:$id, dd.mm.yy - ".$mday.".".$month.".".$year ;
|
||
return $name;
|
||
|
||
# 7 UV/Solar Meldungen vom Sensor
|
||
} elsif ( $whid eq '0111' ) {
|
||
# Fine Offset (Solar Data) message BYTE offsets (within receive buffer)
|
||
# Examples= FF 75 B0 55 00 97 8E 0E *CRC*OK*
|
||
# =FF 75 B0 55 00 8F BE 92 *CRC*OK*
|
||
# symbol FOrunio = 0 ; Fine Offset Runin byte = FF
|
||
# symbol FOsaddo = 1 ; Solar Pod address word
|
||
# symbol FOuvo = 3 ; UV data nybble ?
|
||
# symbol FOluxHo = 4 ; Lux High byte (full scale = 4,000,000?)
|
||
# symbol FOluxMo = 5 ; Lux Middle byte
|
||
# symbol FOluxLo = 6 ; Lux Low byte, Unit = 0.1 Lux (binary)
|
||
# symbol FOcksumo= 7 ; CRC checksum (CRC-8 shifting left)
|
||
$id = SD_WS09_bin2dec(substr($sensdata,4,8));
|
||
$FOuvo = SD_WS09_bin2dec(substr($sensdata,12,4));
|
||
$FOlux = SD_WS09_bin2dec(substr($sensdata,24,24))/10;
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_10 UV-Solar1: id:$id, UV:".$FOuvo." Lux:".$FOlux ;
|
||
} else {
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_Ex Exit: msg=$rawData length:".length($sensdata) ;
|
||
Log3 $iohash, 4, "$name: SD_WS09_WH10 Exit: Model=$model " ;
|
||
return undef;
|
||
}
|
||
} else {
|
||
# es wird eine CTW600 angenommen
|
||
$syncpos= index($bitData,'11111110'); #7x1 1x0 preamble
|
||
$wh = substr($bitData,0,8);
|
||
if ( $wh eq '11111110' && length($bitData) > $minL1 ) {
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_11 CTW600 EXIT: msg=$bitData wh:$wh length:".length($bitData) ;
|
||
$sensdata = substr($bitData,$syncpos+8);
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_12 CTW WH=$wh msg=$sensdata syncp=$syncpos length:".length($sensdata) ;
|
||
$model = "CTW600";
|
||
$whid = "0000";
|
||
my $nn1 = substr($sensdata,10,2); # Keine Bedeutung
|
||
my $nn2 = substr($sensdata,62,4); # Keine Bedeutung
|
||
$modelid = substr($sensdata,0,4);
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_13 Id: ".$modelid." NN1:$nn1 NN2:$nn2" ;
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_14 Id: ".$modelid." Bin-Sync=$sensdata syncp=$syncpos length:".length($sensdata) ;
|
||
$bat = SD_WS09_bin2dec((substr($sensdata,0,3))) ;
|
||
$id = SD_WS09_bin2dec(substr($sensdata,4,6));
|
||
$temp = (SD_WS09_bin2dec(substr($sensdata,12,10)) - 400)/10;
|
||
$hum = SD_WS09_bin2dec(substr($sensdata,22,8));
|
||
$windDirection = SD_WS09_bin2dec(substr($sensdata,66,4));
|
||
$windDirectionText = $winddir_name[$windDirection];
|
||
$windDirectionDegree = $windDirection * 360 / 16;
|
||
$windSpeed = round(SD_WS09_bin2dec(substr($sensdata,30,16))/240,01);
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_15 ".$model." Windspeed bit: ".substr($sensdata,32,8)." Dec: " . $windSpeed ;
|
||
$windguest = round((SD_WS09_bin2dec(substr($sensdata,40,8)) * 34)/100,01);
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_16 ".$model." Windguest bit: ".substr($sensdata,40,8)." Dec: " . $windguest ;
|
||
$rain = round(SD_WS09_bin2dec(substr($sensdata,46,16)) * 0.3,01);
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_17 ".$model." Rain bit: ".substr($sensdata,46,16)." Dec: " . $rain ;
|
||
} else {
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_18 CTW600 EXIT: msg=$bitData length:".length($bitData) ;
|
||
return undef;
|
||
}
|
||
}
|
||
|
||
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse_19 ".$model." id:$id :$sensdata ";
|
||
|
||
if($hum > 100 || $hum < 0) {
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse HUM: hum=$hum msg=$rawData " ;
|
||
return undef;
|
||
}
|
||
if($temp > 60 || $temp < -40) {
|
||
Log3 $iohash, 4, "$name: SD_WS09_Parse TEMP: Temp=$temp msg=$rawData " ;
|
||
return undef;
|
||
}
|
||
|
||
my $longids = AttrVal($iohash->{NAME},'longids',0);
|
||
if ( ($longids ne "0") && ($longids eq "1" || $longids eq "ALL" || (",$longids," =~ m/,$model,/))) {
|
||
$deviceCode=$model."_".$id;
|
||
Log3 $iohash,4, "$name: SD_WS09_Parse using longid: $longids model: $model";
|
||
} else {
|
||
$deviceCode = $model;
|
||
}
|
||
|
||
my $def = $modules{SD_WS09}{defptr}{$iohash->{NAME} . "." . $deviceCode};
|
||
$def = $modules{SD_WS09}{defptr}{$deviceCode} if(!$def);
|
||
|
||
if(!$def) {
|
||
Log3 $iohash, 1, 'SD_WS09_Parse UNDEFINED sensor ' . $model . ' detected, code ' . $deviceCode;
|
||
return "UNDEFINED $deviceCode SD_WS09 $deviceCode";
|
||
}
|
||
|
||
my $hash = $def;
|
||
$name = $hash->{NAME};
|
||
Log3 $name, 4, "SD_WS09_Parse_20: $name ($rawData)";
|
||
|
||
if (!defined(AttrVal($name,"event-min-interval",undef))) {
|
||
my $minsecs = AttrVal($iohash->{NAME},'minsecs',0);
|
||
if($hash->{lastReceive} && (time() - $hash->{lastReceive} < $minsecs)) {
|
||
Log3 $hash, 4, "SD_WS09_Parse_End $deviceCode Dropped due to short time. minsecs=$minsecs";
|
||
return undef;
|
||
}
|
||
}
|
||
|
||
my $windkorr = AttrVal($name,'windKorrektur',0);
|
||
if ($windkorr != 0 ) {
|
||
my $oldwinddir = $windDirection;
|
||
$windDirection = $windDirection + $windkorr;
|
||
$windDirectionText = $winddir_name[$windDirection];
|
||
Log3 $hash, 4, "SD_WS09_Parse_WK ".$model." Faktor:$windkorr wD:$oldwinddir Korrektur wD:$windDirection:$windDirectionText" ;
|
||
}
|
||
|
||
# "Unit_of_Wind:m/s,km/h,ft/s,bft,knot "
|
||
# my %uowind_unit= ("m/s",'1',"km/h",'3.6',"ft/s",'3.28',"bft",'-1',"mph",'2.24',"knot",'1.94');
|
||
# B = Wurzel aus ( 9 + 6 * V ) - 3
|
||
# V = 17 Meter pro Sekunde ergibt: B = Wurzel aus( 9 + 6 * 17 ) - 3
|
||
# Das ergibt : 7,53 Beaufort
|
||
|
||
$windstat[0]= " Ws:$windSpeed Wg:$windguest m/s";
|
||
Log3 $hash, 4, "SD_WS09_Wind $windstat[0] : Faktor:$wfaktor" ;
|
||
|
||
$wfaktor = $uowind_unit{"km/h"};
|
||
$windguest_kmh = round ($windguest * $wfaktor,01);
|
||
$windSpeed_kmh = round ($windSpeed * $wfaktor,01);
|
||
$windstat[1]= " Ws:$windSpeed_kmh Wg:$windguest_kmh km/h";
|
||
Log3 $hash, 4, "SD_WS09_Wind $windstat[1] : Faktor:$wfaktor" ;
|
||
|
||
$wfaktor = $uowind_unit{"ft/s"};
|
||
$windguest_fts = round ($windguest * $wfaktor,01);
|
||
$windSpeed_fts = round ($windSpeed * $wfaktor,01);
|
||
$windstat[2]= " Ws:$windSpeed_fts Wg:$windguest_fts ft/s";
|
||
Log3 $hash, 4, "SD_WS09_Wind $windstat[2] : Faktor:$wfaktor" ;
|
||
|
||
$wfaktor = $uowind_unit{"mph"};
|
||
$windguest_mph = round ($windguest * $wfaktor,01);
|
||
$windSpeed_mph = round ($windSpeed * $wfaktor,01);
|
||
$windstat[3]= " Ws:$windSpeed_mph Wg:$windguest_mph mph";
|
||
Log3 $hash, 4, "SD_WS09_Wind $windstat[3] : Faktor:$wfaktor" ;
|
||
|
||
$wfaktor = $uowind_unit{"knot"};
|
||
$windguest_kn = round ($windguest * $wfaktor,01);
|
||
$windSpeed_kn = round ($windSpeed * $wfaktor,01);
|
||
$windstat[4]= " Ws:$windSpeed_kn Wg:$windguest_kn kn" ;
|
||
Log3 $hash, 4, "SD_WS09_Wind $windstat[4] : Faktor:$wfaktor" ;
|
||
|
||
$windguest_bft = round(sqrt( 9 + (6 * $windguest)) - 3,0) ;
|
||
$windSpeed_bft = round(sqrt( 9 + (6 * $windSpeed)) - 3,0) ;
|
||
$windstat[5]= " Ws:$windSpeed_bft Wg:$windguest_bft bft";
|
||
Log3 $hash, 4, "SD_WS09_Wind $windstat[5] " ;
|
||
|
||
# Resets des rain counters abfangen:
|
||
# wenn der aktuelle Wert < letzter Wert ist, dann fand ein reset statt
|
||
# die Differenz "letzer Wert - aktueller Wert" wird dann als offset für zukünftige Ausgaben zu rain addiert
|
||
# offset wird auch im Reading ".rain_offset" gespeichert
|
||
my $last_rain = ReadingsVal($name, "rain", 0);
|
||
my $rain_offset = ReadingsVal($name, ".rainOffset", 0);
|
||
$rain_offset += $last_rain if($rain < $last_rain);
|
||
my $rain_total = $rain + $rain_offset;
|
||
Log3 $hash, 4, "SD_WS09_Parse_rain_offset ".$model." rain:$rain raintotal:$rain_total rainoffset:$rain_offset " ;
|
||
|
||
# windDirectionAverage berechnen
|
||
my $average = SD_WS09_WindDirAverage($hash, $windSpeed, $windDirectionDegree);
|
||
|
||
$hash->{lastReceive} = time();
|
||
$def->{lastMSG} = $rawData;
|
||
readingsBeginUpdate($hash);
|
||
|
||
if($whid ne "0111") {
|
||
#my $uowind = AttrVal($hash->{NAME},'Unit_of_Wind',0) ;
|
||
my $uowind = AttrVal($name,'Unit_of_Wind',0) ;
|
||
my $windex = $uowind_index{$uowind};
|
||
if (!defined $windex) {
|
||
$windex = 0;
|
||
}
|
||
|
||
$state = "T: $temp ". ($hum>0 ? " H: $hum ":" "). $windstat[$windex]." Wd: $windDirectionText "." R: $rain";
|
||
readingsBulkUpdate($hash, "id", $id) if ($id ne "");
|
||
readingsBulkUpdate($hash, "state", $state);
|
||
readingsBulkUpdate($hash, "temperature", $temp) if ($temp ne"");
|
||
readingsBulkUpdate($hash, "humidity", $hum) if ($hum ne "" && $hum != 0 );
|
||
readingsBulkUpdate($hash, "battery", $bat) if ($bat ne "");
|
||
readingsBulkUpdate($hash, "batteryState", $bat) if ($bat ne "");
|
||
|
||
#zusätzlich Daten für Wetterstation
|
||
readingsBulkUpdate($hash, "rain", $rain );
|
||
readingsBulkUpdate($hash, ".rainOffset", $rain_offset ); # Zwischenspeicher für den offset
|
||
readingsBulkUpdate($hash, "rain_total", $rain_total ); # monoton steigender Wert von rain
|
||
readingsBulkUpdate($hash, "windGust", $windguest );
|
||
readingsBulkUpdate($hash, "windSpeed", $windSpeed );
|
||
readingsBulkUpdate($hash, "windGust_kmh", $windguest_kmh );
|
||
readingsBulkUpdate($hash, "windSpeed_kmh", $windSpeed_kmh );
|
||
readingsBulkUpdate($hash, "windGust_fts", $windguest_fts );
|
||
readingsBulkUpdate($hash, "windSpeed_fts", $windSpeed_fts );
|
||
readingsBulkUpdate($hash, "windGust_mph", $windguest_mph );
|
||
readingsBulkUpdate($hash, "windSpeed_mph", $windSpeed_mph );
|
||
readingsBulkUpdate($hash, "windGust_kn", $windguest_kn );
|
||
readingsBulkUpdate($hash, "windSpeed_kn", $windSpeed_kn );
|
||
readingsBulkUpdate($hash, "windDirectionAverage", $average );
|
||
readingsBulkUpdate($hash, "windDirection", $windDirection );
|
||
readingsBulkUpdate($hash, "windDirectionDegree", $windDirectionDegree);
|
||
readingsBulkUpdate($hash, "windDirectionText", $windDirectionText );
|
||
}
|
||
|
||
if (($whid eq "0111") && ($model eq "WH1080")) {
|
||
$state = "UV: $FOuvo Lux: $FOlux ";
|
||
readingsBulkUpdate($hash, "id", $id) if ($id ne "");
|
||
readingsBulkUpdate($hash, "state", $state);
|
||
#zusätzliche Daten UV + Lux
|
||
readingsBulkUpdate($hash, "UV", $FOuvo );
|
||
readingsBulkUpdate($hash, "Lux", $FOlux );
|
||
}
|
||
|
||
readingsEndUpdate($hash, 1); # Notify is done by Dispatch
|
||
return $name;
|
||
}
|
||
|
||
###################################
|
||
sub SD_WS09_Attr(@) {
|
||
my @a = @_;
|
||
# Make possible to use the same code for different logical devices when they
|
||
# are received through different physical devices.
|
||
return if($a[0] ne "set" || $a[2] ne "IODev");
|
||
my $hash = $defs{$a[1]};
|
||
my $iohash = $defs{$a[3]};
|
||
my $cde = $hash->{CODE};
|
||
delete($modules{SD_WS09}{defptr}{$cde});
|
||
$modules{SD_WS09}{defptr}{$iohash->{NAME} . "." . $cde} = $hash;
|
||
return undef;
|
||
}
|
||
|
||
###################################
|
||
sub SD_WS09_WindDirAverage($$$){
|
||
###############################################################################
|
||
# übernommen von SabineT https://forum.fhem.de/index.php/topic,75225.msg669950.html#msg669950
|
||
# WindDirAverage
|
||
# z.B.: myWindDirAverage('WH1080','windSpeed','windDirectionDegree',900,0.75,0.5)
|
||
# avtime ist optional, default ist 600 s Zeitspanne, die berücksichtig werden soll
|
||
# decay ist optional, default ist 1 Parameter, um ältere Werte geringer zu gewichten
|
||
# minspeed ist optional, default ist 0 m/s
|
||
#
|
||
# Als Ergebnis wird die Windrichtung zurück geliefert, die aus dem aktuellen und
|
||
# vergangenen Werten über eine Art exponentiellen Mittelwert berechnet werden.
|
||
# Dabei wird zusätzlich die jeweilige Windgeschwindigkeit mit berücksichtigt (höhere Geschwindigkeit
|
||
# bedeutet höhere Gewichtung).
|
||
#
|
||
# decay: 1 -> alle Werte werden gleich gewichtet
|
||
# 0 -> nur der aktuelle Wert wird verwendet.
|
||
# in der Praxis wird man Werte so um 0.75 nehmen
|
||
#
|
||
# minspeed: da bei sehr geringer Windgeschwindigkeit die Windrichtung üblicherweise nicht
|
||
# eindeutig ist, kann mit minspeed ein Schwellwert angegeben werden
|
||
# Ist die (gewichtetete) mittlere Geschwindigkeit < minspeed wird undef zurück geliefert
|
||
#
|
||
###############################################################################
|
||
|
||
my ($hash, $ws, $wd) = @_;
|
||
my $name = $hash->{NAME};
|
||
Log3 $hash, 4, "SD_WS09_WindDirAverage --- OK ----" ;
|
||
|
||
my $rc = eval
|
||
{
|
||
require Math::Trig;
|
||
Math::Trig->import();
|
||
1;
|
||
};
|
||
|
||
if($rc) # test ob Math::Trig geladen wurde
|
||
{
|
||
Log3 $hash, 4, "SD_WS09_WindDirAverage Math::Trig:OK" ;
|
||
} else {
|
||
Log3 $hash, 1, "SD_WS09_WindDirAverage Math::Trig:fehlt : cpan install Math::Trig" ;
|
||
return "";
|
||
}
|
||
|
||
my $avtime = AttrVal($name,'WindDirAverageTime',0);
|
||
my $decay = AttrVal($name,'WindDirAverageDecay',0);
|
||
my $minspeed = AttrVal($name,'WindDirAverageMinSpeed',0);
|
||
my $windDirection_old = $wd;
|
||
|
||
# default Werte für die optionalen Parameter, falls nicht beim Aufruf mit angegeben
|
||
$avtime = 600 if (!(defined $avtime) || $avtime == 0 );
|
||
$decay = 1 if (!(defined $decay));
|
||
$decay = 1 if ($decay > 1); # darf nicht >1 sein
|
||
$decay = 0 if ($decay < 0); # darf nicht <0 sein
|
||
$minspeed = 0 if (!(defined $minspeed));
|
||
|
||
$wd = deg2rad($wd);
|
||
my $ctime = time;
|
||
my $time = FmtDateTime($ctime);
|
||
my @new = ($ws,$wd,$time);
|
||
|
||
Log3 $hash, 4,"SD_WS09_WindDirAverage_01 $name :Speed=".$ws." DirR=".round($wd,2)." Time=".$time;
|
||
Log3 $hash, 4,"SD_WS09_WindDirAverage_02 $name :avtime=".$avtime." decay=".$decay." minspeed=".$minspeed;
|
||
|
||
my $num;
|
||
my $arr;
|
||
|
||
#-- initialize if requested
|
||
if( ($avtime eq "-1") ){
|
||
$hash->{helper}{history}=undef;
|
||
}
|
||
|
||
#-- test for existence
|
||
if(!$hash->{helper}{history}){
|
||
Log3 $hash, 4,"SD_WS09_WindDirAverage_03 $name :ARRAY CREATED";
|
||
push(@{$hash->{helper}{history}},\@new);
|
||
$num = 1;
|
||
$arr=\@{$hash->{helper}{history}};
|
||
} else {
|
||
$num = int(@{$hash->{helper}{history}});
|
||
$arr=\@{$hash->{helper}{history}};
|
||
my $stime = time_str2num($arr->[0][2]); # Zeitpunkt des ältesten Eintrags
|
||
my $ltime = time_str2num($arr->[$num-1][2]); # Zeitpunkt des letzten Eintrags
|
||
Log3 $hash,4,"SD_WS09_WindDirAverage_04 $name :Speed=".$ws." Dir=".round($wd,2)." Time=".$time." minspeed=".$minspeed." ctime=".$ctime." ltime=".$ltime." stime=".$stime." num=".$num;
|
||
|
||
if((($ctime - $ltime) > 10) || ($num == 0)) {
|
||
if(($num < 25) && (($ctime-$stime) < $avtime)){
|
||
Log3 $hash,4,"SD_WS09_WindDirAverage_05 $name :Speed=".$ws." Dir=".round($wd,2)." Time=".$time." minspeed=".$minspeed." num=".$num;
|
||
push(@{$hash->{helper}{history}},\@new);
|
||
} else {
|
||
shift(@{$hash->{helper}{history}});
|
||
push(@{$hash->{helper}{history}},\@new);
|
||
Log3 $hash,4,"SD_WS09_WindDirAverage_06 $name :Speed=".$ws." Dir=".round($wd,2)." Time=".$time." minspeed=".$minspeed." num=".$num;
|
||
}
|
||
} else {
|
||
return $windDirection_old; # old undef | different behavior dispatch <-> UnitTest´s ($ctime - $ltime)
|
||
}
|
||
}
|
||
|
||
#-- output and average
|
||
my ($anz, $sanz) = 0;
|
||
$num = int(@{$hash->{helper}{history}});
|
||
my ($sumSin, $sumCos, $sumSpeed, $age, $maxage, $weight) = 0;
|
||
for(my $i=0; $i<$num; $i++){
|
||
($ws, $wd, $time) = @{ $arr->[$i] };
|
||
$age = $ctime - time_str2num($time);
|
||
if (($time eq "") || ($age > $avtime)) {
|
||
#-- zu alte Einträge entfernen
|
||
Log3 $hash,4,"SD_WS09_WindDirAverage_07 $name i=".$i." Speed=".round($ws,2)." Dir=".round($wd,2)." Time=".substr($time,11)." ctime=".$ctime." akt.=".time_str2num($time);
|
||
shift(@{$hash->{helper}{history}});
|
||
$i--;
|
||
$num--;
|
||
} else {
|
||
#-- Werte aufsummieren, Windrichtung gewichtet über Geschwindigkeit und decay/"alter"
|
||
$weight = $decay ** ($age / $avtime);
|
||
#-- für die Mittelwertsbildung der Geschwindigkeit wird nur ein 10tel von avtime genommen
|
||
if ($age < ($avtime / 10)) {
|
||
$sumSpeed += $ws * $weight if ($age < ($avtime / 10));
|
||
$sanz++;
|
||
}
|
||
$sumSin += sin($wd) * $ws * $weight;
|
||
$sumCos += cos($wd) * $ws * $weight;
|
||
$anz++;
|
||
Log3 $hash,4,"SD_WS09_WindDirAverage_08 $name i=".$i." Speed=".round($ws,2)." Dir=".round($wd,2)." Time=".substr($time,11)." vec=".round($sumSin,2)."/".round($sumCos,2)." age=".$age." ".round($weight,2);
|
||
}
|
||
}
|
||
my $average = int((rad2deg(atan2($sumSin, $sumCos)) + 360) % 360);
|
||
Log3 $hash,4,"SD_WS09_WindDirAverage_09 $name Mittelwert über $anz Werte ist $average, avspeed=".round($sumSpeed/$num,1) if ($num > 0);
|
||
|
||
#-- undef zurückliefern, wenn die durchschnittliche Geschwindigkeit zu gering oder gar keine Werte verfügbar
|
||
return undef if (($anz == 0) || ($sanz == 0));
|
||
return undef if (($sumSpeed / $sanz) < $minspeed);
|
||
|
||
Log3 $hash,4,"SD_WS09_WindDirAverage_END $name Mittelwert=$average";
|
||
return $average;
|
||
}
|
||
|
||
###################################
|
||
sub SD_WS09_bin2dec($) {
|
||
my $h = shift;
|
||
my $int = unpack("N", pack("B32",substr("0" x 32 . $h, -32)));
|
||
return sprintf("%d", $int);
|
||
}
|
||
|
||
###################################
|
||
sub SD_WS09_binflip($) {
|
||
my $h = shift;
|
||
my $hlen = length($h);
|
||
my $i = 0;
|
||
my $flip = "";
|
||
|
||
for ($i=$hlen-1; $i >= 0; $i--) {
|
||
$flip = $flip.substr($h,$i,1);
|
||
}
|
||
return $flip;
|
||
}
|
||
|
||
###################################
|
||
sub SD_WS09_BCD2bin($) {
|
||
my $binary = shift;
|
||
my $int = unpack("N", pack("B32", substr("0" x 32 . $binary, -32)));
|
||
my $BCD = sprintf("%x", $int );
|
||
return $BCD;
|
||
}
|
||
|
||
###################################
|
||
sub SD_WS09_SHIFT($$){
|
||
my ($hash, $rawData) = @_;
|
||
my $name = $hash->{NAME};
|
||
my $hlen = length($rawData);
|
||
my $blen = $hlen * 4;
|
||
my $bitData = unpack("B$blen", pack("H$hlen", $rawData));
|
||
my $bitData2 = '1'.$bitData;
|
||
my $bitData20 = substr($bitData2,0,length($bitData2)-1);
|
||
$blen = length($bitData20);
|
||
$hlen = $blen / 4;
|
||
$rawData = uc(unpack("H$hlen", pack("B$blen", $bitData20)));
|
||
$bitData = $bitData20;
|
||
#Log3 $hash, 4, "$name: SD_WS09_SHIFT_0 raw: $rawData length:".length($bitData);
|
||
Log3 $hash, 5, "$name: SD_WS09_SHIFT_1 bitdata: $bitData length:".length($bitData);
|
||
return $rawData;
|
||
}
|
||
|
||
###################################
|
||
sub SD_WS09_CRCCHECK($) {
|
||
my $rawData = shift;
|
||
my $datacheck1 = pack( 'H*', substr($rawData,2,length($rawData)-2) );
|
||
my $crcmein1 = Digest::CRC->new(width => 8, poly => 0x31);
|
||
my $rr3 = $crcmein1->add($datacheck1)->hexdigest;
|
||
$rr3 = sprintf("%d", hex($rr3));
|
||
Log3 "SD_WS09_CRCCHECK", 4, "SD_WS09_CRCCHECK : raw:$rawData CRC=$rr3 " ;
|
||
return $rr3 ;
|
||
}
|
||
|
||
1;
|
||
|
||
|
||
=pod
|
||
=item summary Supports weather sensors (WH1080/3080/CTW-600) protocl 9 from SIGNALduino
|
||
=item summary_DE Unterstuetzt Wettersensoren (WH1080/3080/CTW-600) / Protokol 9 vom SIGNALduino
|
||
=begin html
|
||
|
||
<a name="SD_WS09"></a>
|
||
<h3>Wether Sensors protocol #9</h3>
|
||
<ul>
|
||
The SD_WS09 module interprets temperature sensor messages received by a Device like CUL, CUN, SIGNALduino etc.<br><br>
|
||
Requires Perl-Modul Digest::CRC / Math::Trig <br>
|
||
<ul>
|
||
<li>cpan install Digest::CRC or <br>
|
||
sudo apt-get install libdigest-crc-perl </li>
|
||
<li>cpan install Math::Trig </li></ul><br>
|
||
<br>
|
||
<b>Known models:</b>
|
||
<ul>
|
||
<li>WS-0101 --> Model: WH1080</li>
|
||
<li>TFA 30.3189 / WH1080 --> Model: WH1080</li>
|
||
<li>1073 (WS1080) --> Model: WH1080</li>
|
||
<li>WH2315 --> Model: WH1080</li>
|
||
<li>WH3080 --> Model: WH1080</li>
|
||
<li>CTW600 --> Model: CTW600</li>
|
||
</ul>
|
||
<br>
|
||
New received device are add in fhem with autocreate.
|
||
<br><br><br>
|
||
|
||
<a name="SD_WS09_Define"></a>
|
||
<b>Define</b>
|
||
<ul>The received devices created automatically.<br>
|
||
The ID of the defice is the model or, if the longid attribute is specified, it is a combination of model and some random generated bits at powering the sensor.<br>
|
||
If you want to use more sensors, you can use the longid option to differentiate them.
|
||
</ul>
|
||
<br>
|
||
|
||
<a name="SD_WS09_Set"></a>
|
||
<b>Set</b> <ul>N/A</ul><br>
|
||
|
||
<a name="SD_WS09_Get"></a>
|
||
<b>Get</b> <ul>N/A</ul><br><br>
|
||
|
||
|
||
<b>Attributes</b>
|
||
<ul>
|
||
<li><a href="#do_not_notify">do_not_notify</a></li>
|
||
<li><a href="#ignore">ignore</a></li>
|
||
<li><a href="#showtime">showtime</a></li>
|
||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
||
|
||
<a name="Model"></a>
|
||
<li>Model: WH1080,CTW600
|
||
</li>
|
||
|
||
<a name="windKorrektur"></a>
|
||
<li>windKorrektur: -3,-2,-1,0,1,2,3
|
||
</li>
|
||
|
||
<a name="Unit_of_Wind"></a>
|
||
<li>Unit_of_Wind<br>
|
||
Unit of windSpeed and windGuest. State-Format: Value + Unit.
|
||
<br>m/s,km/h,ft/s,mph,bft,knot
|
||
</li><br>
|
||
|
||
<a name="WindDirAverageTime"></a>
|
||
<li>WindDirAverageTime<br>
|
||
default is 600s, time span to be considered for the calculation
|
||
</li><br>
|
||
|
||
<a name="WindDirAverageMinSpeed"></a>
|
||
<li>WindDirAverageMinSpeed<br>
|
||
since the wind direction is usually not clear at very low wind speeds,
|
||
minspeed can be used to specify a threshold value.
|
||
<br>The (weighted) mean velocity < minspeed is returned undef
|
||
</li><br>
|
||
|
||
<a name="WindDirAverageDecay"></a>
|
||
<li>WindDirAverageDecay<br>
|
||
1 -> all values are weighted equally <br>
|
||
0 -> only the current value is used. <br>
|
||
in practice, you will take values around 0.75
|
||
</li><br>
|
||
|
||
<a name="WS09_CRCAUS"></a>
|
||
<li>WS09_CRCAUS (set in Signalduino-Modul 00_SIGNALduino.pm)
|
||
<br>0: CRC-Check WH1080 CRC-Summe = 0 on, default
|
||
<br>2: CRC-Summe = 49 (x031) WH1080, set OK
|
||
</li>
|
||
</ul> <br><br>
|
||
|
||
<a name="SD_WS09 Events"></a>
|
||
<b>Generated readings:</b>
|
||
<br>Some devices may not support all readings, so they will not be presented<br>
|
||
<ul>
|
||
<li>State (T: H: Ws: Wg: Wd: R: ) temperature, humidity, windSpeed, windGuest, windDirection, Rain</li>
|
||
<li>Temperature (°C)</li>
|
||
<li>Humidity: (The humidity (1-100 if available)</li>
|
||
<li>Battery: (low or ok)</li>
|
||
<li>ID: (The ID-Number (number if)</li>
|
||
<li>windSpeed/windGuest (Unit_of_Wind)) and windDirection (N-O-S-W)</li>
|
||
<li>Rain (mm)</li>
|
||
<li>windDirectionAverage<br>
|
||
As a result, the wind direction is returned, which are calculated from the current and past values
|
||
via a kind of exponential mean value.
|
||
The respective wind speed is additionally taken into account (higher speed means higher weighting)</li><br>
|
||
<b>WH2315 / WH3080:</b>
|
||
<li>UV Index</li>
|
||
<li>Lux</li>
|
||
|
||
</ul>
|
||
</ul>
|
||
|
||
=end html
|
||
=begin html_DE
|
||
|
||
<a name="SD_WS09"></a>
|
||
<h3>SD_WS09</h3>
|
||
<ul>
|
||
Das SD_WS09 Module verarbeitet von einem IO Gerät (CUL, CUN, SIGNALDuino, etc.) empfangene Nachrichten von Temperatur-Sensoren.<br>
|
||
<br>
|
||
Perl-Module Digest::CRC / Math::Trig erforderlich. <br>
|
||
<ul>
|
||
<li>cpan install Digest::CRC oder auch <br>
|
||
sudo apt-get install libdigest-crc-perl </li>
|
||
<li>cpan install Math::Trig </li></ul><br>
|
||
<br>
|
||
<b>Unterstütze Modelle:</b>
|
||
<ul>
|
||
<li>WS-0101 --> Model: WH1080</li>
|
||
<li>TFA 30.3189 / WH1080 --> Model: WH1080</li>
|
||
<li>1073 (WS1080) --> Model: WH1080</li>
|
||
<li>WH2315 --> Model: WH1080</li>
|
||
<li>WH3080 --> Model: WH1080</li>
|
||
<li>CTW600 --> Model: CTW600</li>
|
||
</ul>
|
||
<br>
|
||
Neu empfangene Sensoren werden in FHEM per autocreate angelegt.
|
||
<br><br><br>
|
||
|
||
<a name="SD_WS09_Define"></a>
|
||
<b>Define</b>
|
||
<ul>Die empfangenen Sensoren werden automatisch angelegt.<br>
|
||
Die ID der angelegten Sensoren wird nach jedem Batteriewechsel geändert, welche der Sensor beim Einschalten zufällig vergibt.<br>
|
||
CRC Checksumme wird zur Zeit noch nicht überprüft, deshalb werden Sensoren bei denen die Luftfeuchte < 0 oder > 100 ist, nicht angelegt.<br>
|
||
</ul>
|
||
<br>
|
||
|
||
<a name="SD_WS09_Set"></a>
|
||
<b>Set</b> <ul>N/A</ul><br>
|
||
|
||
<a name="SD_WS09_Get"></a>
|
||
<b>Get</b> <ul>N/A</ul><br><br>
|
||
|
||
<b>Attribute</b>
|
||
<ul>
|
||
<li><a href="#do_not_notify">do_not_notify</a></li>
|
||
<li><a href="#ignore">ignore</a></li>
|
||
<li><a href="#showtime">showtime</a></li>
|
||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
||
|
||
<a name="Model"></a>
|
||
<li>Model<br>
|
||
WH1080, CTW600
|
||
</li><br>
|
||
|
||
<a name="windKorrektur"></a>
|
||
<li>windKorrektur<br>
|
||
Korrigiert die Nord-Ausrichtung des Windrichtungsmessers, wenn dieser nicht richtig nach Norden ausgerichtet ist.
|
||
-3,-2,-1,0,1,2,3
|
||
</li><br>
|
||
|
||
<a name="Unit_of_Wind"></a>
|
||
<li>Unit_of_Wind<br>
|
||
Hiermit wird der Einheit eingestellt und im State die entsprechenden Werte + Einheit angezeigt.
|
||
<br>m/s,km/h,ft/s,mph,bft,knot
|
||
</li><br>
|
||
|
||
<a name="WindDirAverageTime"></a>
|
||
<li>WindDirAverageTime<br>
|
||
default ist 600s, Zeitspanne die für die Berechung berücksichtig werden soll
|
||
</li><br>
|
||
|
||
<a name="WindDirAverageMinSpeed"></a>
|
||
<li>WindDirAverageMinSpeed<br>
|
||
da bei sehr geringer Windgeschwindigkeit die Windrichtung üblicherweise nicht
|
||
eindeutig ist, kann mit minspeed ein Schwellwert angegeben werden
|
||
Ist die (gewichtetete) mittlere Geschwindigkeit < minspeed wird undef zurück geliefert
|
||
</li><br>
|
||
|
||
<a name="WindDirAverageDecay"></a>
|
||
<li>WindDirAverageDecay<br>
|
||
1 -> alle Werte werden gleich gewichtet <br>
|
||
0 -> nur der aktuelle Wert wird verwendet.<br>
|
||
in der Praxis wird man Werte so um 0.75 nehmen
|
||
</li><br>
|
||
|
||
<a name="WS09_CRCAUS"></a>
|
||
<li>WS09_CRCAUS<br>
|
||
Wird im Signalduino-Modul (00_SIGNALduino.pm) gesetzt
|
||
<br>0: CRC-Prüfung bei WH1080 CRC-Summe = 0
|
||
<br>2: CRC-Summe = 49 (x031) bei WH1080 wird als OK verarbeitet
|
||
</li><br>
|
||
</ul><br>
|
||
|
||
<a name="SD_WS09 Events"></a>
|
||
<b>Generierte Readings:</b>
|
||
<ul>
|
||
<li>State (T: H: Ws: Wg: Wd: R: ) temperature, humidity, windSpeed, windGuest, Einheit, windDirection, Rain</li>
|
||
<li>Temperature (°C)</li>
|
||
<li>Humidity: (1-100 wenn verfügbar)</li>
|
||
<li>Battery: (low or ok)</li>
|
||
<li>ID: (ID-Nummer wenn verfügbar)</li>
|
||
<li>windSpeed/windgust (Einheit siehe Unit_of_Wind) und windDirection (N-O-S-W)</li>
|
||
<li>Rain (mm)</li>
|
||
<li>windDirectionAverage
|
||
Als Ergebnis wird die Windrichtung zurück geliefert, die aus dem aktuellen und
|
||
vergangenen Werten über eine Art exponentiellen Mittelwert berechnet werden.
|
||
Dabei wird zusätzlich die jeweilige Windgeschwindigkeit mit berücksichtigt (höhere Geschwindigkeit
|
||
bedeutet höhere Gewichtung).</li><br>
|
||
<b>WH2315 / WH3080:</b>
|
||
<li>UV Index</li>
|
||
<li>Lux</li>
|
||
|
||
</ul>
|
||
|
||
</ul>
|
||
|
||
=end html_DE
|
||
=cut
|
||
|