2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-19 18:56:03 +00:00

14_SD_WS09.pm: updated module

WH2315 support added

git-svn-id: https://svn.fhem.de/fhem/trunk@21622 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
sidey79 2020-04-07 21:42:13 +00:00
parent 4899d4ba0d
commit 609796307d
2 changed files with 686 additions and 646 deletions

View File

@ -1,5 +1,7 @@
# 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.
- bugfix: 14_SD_WS_09.pm: WindDirAverage
- feature: 14_SD_WS_09.pm: support for WH2315
- feature: 14_SD_UT.pm - feature: 14_SD_UT.pm
new model Novy_840039 new model Novy_840039
new remote control xavax 00111939 new remote control xavax 00111939

View File

@ -3,25 +3,30 @@
# #
# The purpose of this module is to support serval # The purpose of this module is to support serval
# weather sensors like WS-0101 (Sender 868MHz ASK Epmfänger RX868SH-DV elv) # weather sensors like WS-0101 (Sender 868MHz ASK Epmfänger RX868SH-DV elv)
# Sidey79 & pejonp 2015
# #
# 22.09.2017: rainTotal --> rain_total # 2015 Sidey79, pejonp
# 23.09.2017: windDirAverage SabineT https://forum.fhem.de/index.php/topic,75225.msg669950.html#msg669950 # 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; package main;
use strict; use strict;
use warnings; use warnings;
#use Math::Round qw/nearest/;
# werden benötigt, aber im Programm noch extra abgetestet # werden benötigt, aber im Programm noch extra abgetestet
#use Digest::CRC qw(crc); #use Digest::CRC qw(crc);
#use Math::Trig; #use Math::Trig;
sub SD_WS09_Initialize($) sub SD_WS09_Initialize($) {
{
my ($hash) = @_; my ($hash) = @_;
$hash->{Match} = "^P9#F[A-Fa-f0-9]+"; ## pos 7 ist aktuell immer 0xF $hash->{Match} = "^P9#F[A-Fa-f0-9]+"; ## pos 7 ist aktuell immer 0xF
@ -39,18 +44,14 @@
."$readingFnAttributes "; ."$readingFnAttributes ";
$hash->{AutoCreate} = $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"} }; { "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($$) sub SD_WS09_Define($$) {
{
my ($hash, $def) = @_; my ($hash, $def) = @_;
my @a = split("[ \t][ \t]*", $def); my @a = split("[ \t][ \t]*", $def);
return "wrong syntax: define <name> SD_WS09 <code> ".int(@a) return "wrong syntax: define <name> SD_WS09 <code> ".int(@a) if(int(@a) < 3 );
if(int(@a) < 3 );
$hash->{CODE} = $a[2]; $hash->{CODE} = $a[2];
$hash->{lastMSG} = ""; $hash->{lastMSG} = "";
@ -68,19 +69,17 @@
} }
##################################### #####################################
sub SD_WS09_Undef($$) sub SD_WS09_Undef($$) {
{
my ($hash, $name) = @_; my ($hash, $name) = @_;
delete($modules{SD_WS09}{defptr}{$hash->{CODE}}) delete($modules{SD_WS09}{defptr}{$hash->{CODE}})
if(defined($hash->{CODE}) && if(defined($hash->{CODE}) &&
defined($modules{SD_WS09}{defptr}{$hash->{CODE}})); defined($modules{SD_WS09}{defptr}{$hash->{CODE}}));
return undef; return undef;
} }
################################### ###################################
sub SD_WS09_Parse($$) sub SD_WS09_Parse($$) {
{
my ($iohash, $msg) = @_; my ($iohash, $msg) = @_;
my $name = $iohash->{NAME}; my $name = $iohash->{NAME};
my (undef ,$rawData) = split("#",$msg); my (undef ,$rawData) = split("#",$msg);
@ -96,13 +95,13 @@
my $deviceCode = 0; my $deviceCode = 0;
my $model = "undef"; # 0xFFA -> WS0101/WH1080 alles andere -> CTW600 my $model = "undef"; # 0xFFA -> WS0101/WH1080 alles andere -> CTW600
my $modelid; my $modelid;
my $windSpeed; my $windSpeed = 0;
my $windSpeed_kmh; my $windSpeed_kmh;
my $windSpeed_fts; my $windSpeed_fts;
my $windSpeed_bft; my $windSpeed_bft;
my $windSpeed_mph; my $windSpeed_mph;
my $windSpeed_kn; my $windSpeed_kn;
my $windguest; my $windguest = 0;
my $windguest_kmh; my $windguest_kmh;
my $windguest_fts; my $windguest_fts;
my $windguest_bft; my $windguest_bft;
@ -128,15 +127,33 @@
my $rawData_merk; my $rawData_merk;
my $wfaktor = 1; my $wfaktor = 1;
my @windstat; my @windstat;
my $syncpos;
my $syncpos= index($bitData,"11111110"); #7x1 1x0 preamble 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) ; Log3 $iohash, 4, "$name: SD_WS09_Parse0 msg=$rawData Bin=$bitData syncp=$syncpos length:".length($bitData) ;
if ($syncpos ==-1 || length($bitData)-$syncpos < $minL2) if ($syncpos ==-1 || length($bitData)-$syncpos < $minL2) {
{
Log3 $iohash, 4, "$name: SD_WS09_Parse EXIT: msg=$rawData syncp=$syncpos length:".length($bitData) ; Log3 $iohash, 4, "$name: SD_WS09_Parse EXIT: msg=$rawData syncp=$syncpos length:".length($bitData) ;
return undef; return undef;
} }
}
my $crcwh1080 = AttrVal($iohash->{NAME},'WS09_CRCAUS',0); my $crcwh1080 = AttrVal($iohash->{NAME},'WS09_CRCAUS',0);
Log3 $iohash, 4, "$name: SD_WS09_Parse CRC_AUS:$crcwh1080 " ; Log3 $iohash, 4, "$name: SD_WS09_Parse CRC_AUS:$crcwh1080 " ;
@ -149,42 +166,50 @@
1; 1;
}; };
if($rc) # test ob Digest::CRC geladen wurde # test ob Digest::CRC geladen
{ if($rc) {
$rr2 = SD_WS09_CRCCHECK($rawData); $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)) ) { if ($rr2 == 0 || (($rr2 == 49) && ($crcwh1080 == 2)) ) {
# 1. OK # 1. OK
$model = "WH1080"; $model = "WH1080";
Log3 $iohash, 4, "$name: SD_WS09_SHIFT_0 OK rwa:$rawData" ; Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_0 OK raw:$rawData crc:$rr2";
} else { } else {
# 1. nok # 1. nok
$rawData = SD_WS09_SHIFT($rawData); Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_1 NOK raw:$rawData crc:$rr2 -> shift";
Log3 $iohash, 4, "$name: SD_WS09_SHIFT_1 NOK rwa:$rawData" ; $rawData = SD_WS09_SHIFT($iohash, $rawData);
$rr2 = SD_WS09_CRCCHECK($rawData); $rr2 = SD_WS09_CRCCHECK($rawData);
if ($rr2 == 0 || (($rr2 == 49) && ($crcwh1080 == 2)) ) { if ($rr2 == 0 || (($rr2 == 49) && ($crcwh1080 == 2)) ) {
# 2.ok # 2.ok
$msg = $msg_vor.$rawData; $msg = $msg_vor.$rawData;
$model = "WH1080"; $model = "WH1080";
Log3 $iohash, 4, "$name: SD_WS09_SHIFT_2 OK rwa:$rawData msg:$msg" ; Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_2 OK raw:$rawData msg:$msg crc:$rr2";
} else { } else {
# 2. nok # 2. nok
$rawData = SD_WS09_SHIFT($rawData); Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_3 NOK raw:$rawData crc:$rr2 -> shift";
Log3 $iohash, 4, "$name: SD_WS09_SHIFT_3 NOK rwa:$rawData" ; $rawData = SD_WS09_SHIFT($iohash, $rawData);
$rr2 = SD_WS09_CRCCHECK($rawData); $rr2 = SD_WS09_CRCCHECK($rawData);
if ($rr2 == 0 || (($rr2 == 49) && ($crcwh1080 == 2)) ) { if ($rr2 == 0 || (($rr2 == 49) && ($crcwh1080 == 2)) ) {
# 3. ok # 3. ok
$msg = $msg_vor.$rawData; $msg = $msg_vor.$rawData;
$model = "WH1080"; $model = "WH1080";
Log3 $iohash, 4, "$name: SD_WS09_SHIFT_4 OK rwa:$rawData msg:$msg" ; Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_4 OK raw:$rawData msg:$msg crc:$rr2";
} else { } else {
# 3. nok # 3. nok
$rawData = $rawData_merk; $rawData = $rawData_merk;
$msg = $msg_vor.$rawData; $msg = $msg_vor.$rawData;
Log3 $iohash, 4, "$name: SD_WS09_SHIFT_5 NOK rwa:$rawData msg:$msg" ; Log3 $iohash, 4, "$name: SD_WS09_Parse_SHIFT_5 NOK raw:$rawData msg:$msg crc:$rr2";
}
} }
} }
} }
} else { } 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" ; 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 ""; return "";
} }
@ -197,8 +222,10 @@
if( $model eq "WH1080") { if( $model eq "WH1080") {
$sensdata = substr($bitData,8); $sensdata = substr($bitData,8);
$whid = substr($sensdata,0,4); $whid = substr($sensdata,0,4);
Log3 $iohash, 5, "$name: SD_WS09_Parse_0 whid=$whid";
if( $whid == "1010" ){ # A Wettermeldungen # A Wettermeldungen
if( $whid == "1010" ){
Log3 $iohash, 4, "$name: SD_WS09_Parse_1 msg=$sensdata length:".length($sensdata) ; Log3 $iohash, 4, "$name: SD_WS09_Parse_1 msg=$sensdata length:".length($sensdata) ;
$model = "WH1080"; $model = "WH1080";
$id = SD_WS09_bin2dec(substr($sensdata,4,8)); $id = SD_WS09_bin2dec(substr($sensdata,4,8));
@ -215,7 +242,9 @@
$rain = SD_WS09_bin2dec(substr($sensdata,52,12)) * 0.3; $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_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"; 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";
} elsif( $whid == "1011" ){ # B DCF-77 Zeitmeldungen vom Sensor
# B DCF-77 Zeitmeldungen vom Sensor
} elsif ( $whid == "1011" ) {
my $hrs1 = substr($sensdata,16,8); my $hrs1 = substr($sensdata,16,8);
my $hrs; my $hrs;
my $mins; my $mins;
@ -236,7 +265,9 @@
Log3 $iohash, 4, "$name: SD_WS09_Parse_8 Zeitmeldung2: id:$id, HH:mm:ss - ".$hrs.":".$mins.":".$sec ; 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 ; Log3 $iohash, 4, "$name: SD_WS09_Parse_9 Zeitmeldung3: id:$id, dd.mm.yy - ".$mday.".".$month.".".$year ;
return $name; return $name;
} elsif( $whid == "0111" ){ # 7 UV/Solar Meldungen vom Sensor
# 7 UV/Solar Meldungen vom Sensor
} elsif ( $whid == "0111" ) {
# Fine Offset (Solar Data) message BYTE offsets (within receive buffer) # Fine Offset (Solar Data) message BYTE offsets (within receive buffer)
# Examples= FF 75 B0 55 00 97 8E 0E *CRC*OK* # Examples= FF 75 B0 55 00 97 8E 0E *CRC*OK*
# =FF 75 B0 55 00 8F BE 92 *CRC*OK* # =FF 75 B0 55 00 8F BE 92 *CRC*OK*
@ -260,8 +291,7 @@
# es wird eine CTW600 angenommen # es wird eine CTW600 angenommen
$syncpos= index($bitData,"11111110"); #7x1 1x0 preamble $syncpos= index($bitData,"11111110"); #7x1 1x0 preamble
$wh = substr($bitData,0,8); $wh = substr($bitData,0,8);
if ( $wh == "11111110" && length($bitData) > $minL1 ) if ( $wh == "11111110" && length($bitData) > $minL1 ) {
{
Log3 $iohash, 4, "$name: SD_WS09_Parse_11 CTW600 EXIT: msg=$bitData wh:$wh length:".length($bitData) ; Log3 $iohash, 4, "$name: SD_WS09_Parse_11 CTW600 EXIT: msg=$bitData wh:$wh length:".length($bitData) ;
$sensdata = substr($bitData,$syncpos+8); $sensdata = substr($bitData,$syncpos+8);
Log3 $iohash, 4, "$name: SD_WS09_Parse_12 CTW WH=$wh msg=$sensdata syncp=$syncpos length:".length($sensdata) ; Log3 $iohash, 4, "$name: SD_WS09_Parse_12 CTW WH=$wh msg=$sensdata syncp=$syncpos length:".length($sensdata) ;
@ -304,8 +334,7 @@
} }
my $longids = AttrVal($iohash->{NAME},'longids',0); my $longids = AttrVal($iohash->{NAME},'longids',0);
if ( ($longids ne "0") && ($longids eq "1" || $longids eq "ALL" || (",$longids," =~ m/,$model,/))) if ( ($longids ne "0") && ($longids eq "1" || $longids eq "ALL" || (",$longids," =~ m/,$model,/))) {
{
$deviceCode=$model."_".$id; $deviceCode=$model."_".$id;
Log3 $iohash,4, "$name: SD_WS09_Parse using longid: $longids model: $model"; Log3 $iohash,4, "$name: SD_WS09_Parse using longid: $longids model: $model";
} else { } else {
@ -324,8 +353,7 @@
$name = $hash->{NAME}; $name = $hash->{NAME};
Log3 $name, 4, "SD_WS09_Parse_20: $name ($rawData)"; Log3 $name, 4, "SD_WS09_Parse_20: $name ($rawData)";
if (!defined(AttrVal($name,"event-min-interval",undef))) if (!defined(AttrVal($name,"event-min-interval",undef))) {
{
my $minsecs = AttrVal($iohash->{NAME},'minsecs',0); my $minsecs = AttrVal($iohash->{NAME},'minsecs',0);
if($hash->{lastReceive} && (time() - $hash->{lastReceive} < $minsecs)) { if($hash->{lastReceive} && (time() - $hash->{lastReceive} < $minsecs)) {
Log3 $hash, 4, "SD_WS09_Parse_End $deviceCode Dropped due to short time. minsecs=$minsecs"; Log3 $hash, 4, "SD_WS09_Parse_End $deviceCode Dropped due to short time. minsecs=$minsecs";
@ -334,8 +362,7 @@
} }
my $windkorr = AttrVal($name,'windKorrektur',0); my $windkorr = AttrVal($name,'windKorrektur',0);
if ($windkorr != 0 ) if ($windkorr != 0 ) {
{
my $oldwinddir = $windDirection; my $oldwinddir = $windDirection;
$windDirection = $windDirection + $windkorr; $windDirection = $windDirection + $windkorr;
$windDirectionText = $winddir_name[$windDirection]; $windDirectionText = $winddir_name[$windDirection];
@ -397,8 +424,7 @@
$def->{lastMSG} = $rawData; $def->{lastMSG} = $rawData;
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
if($whid ne "0111") if($whid ne "0111") {
{
#my $uowind = AttrVal($hash->{NAME},'Unit_of_Wind',0) ; #my $uowind = AttrVal($hash->{NAME},'Unit_of_Wind',0) ;
my $uowind = AttrVal($name,'Unit_of_Wind',0) ; my $uowind = AttrVal($name,'Unit_of_Wind',0) ;
my $windex = $uowind_index{$uowind}; my $windex = $uowind_index{$uowind};
@ -433,8 +459,8 @@
readingsBulkUpdate($hash, "windDirectionDegree", $windDirectionDegree); readingsBulkUpdate($hash, "windDirectionDegree", $windDirectionDegree);
readingsBulkUpdate($hash, "windDirectionText", $windDirectionText ); readingsBulkUpdate($hash, "windDirectionText", $windDirectionText );
} }
if(($whid eq "0111") && ($model eq "WH1080"))
{ if (($whid eq "0111") && ($model eq "WH1080")) {
$state = "UV: $FOuvo Lux: $FOlux "; $state = "UV: $FOuvo Lux: $FOlux ";
readingsBulkUpdate($hash, "id", $id) if ($id ne ""); readingsBulkUpdate($hash, "id", $id) if ($id ne "");
readingsBulkUpdate($hash, "state", $state); readingsBulkUpdate($hash, "state", $state);
@ -442,13 +468,13 @@
readingsBulkUpdate($hash, "UV", $FOuvo ); readingsBulkUpdate($hash, "UV", $FOuvo );
readingsBulkUpdate($hash, "Lux", $FOlux ); readingsBulkUpdate($hash, "Lux", $FOlux );
} }
readingsEndUpdate($hash, 1); # Notify is done by Dispatch
readingsEndUpdate($hash, 1); # Notify is done by Dispatch
return $name; return $name;
} }
sub SD_WS09_Attr(@) ###################################
{ sub SD_WS09_Attr(@) {
my @a = @_; my @a = @_;
# Make possible to use the same code for different logical devices when they # Make possible to use the same code for different logical devices when they
# are received through different physical devices. # are received through different physical devices.
@ -461,6 +487,7 @@
return undef; return undef;
} }
###################################
sub SD_WS09_WindDirAverage($$$){ sub SD_WS09_WindDirAverage($$$){
############################################################################### ###############################################################################
# übernommen von SabineT https://forum.fhem.de/index.php/topic,75225.msg669950.html#msg669950 # übernommen von SabineT https://forum.fhem.de/index.php/topic,75225.msg669950.html#msg669950
@ -488,6 +515,7 @@
my ($hash, $ws, $wd) = @_; my ($hash, $ws, $wd) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
Log3 $hash, 4, "SD_WS09_WindDirAverage --- OK ----" ; Log3 $hash, 4, "SD_WS09_WindDirAverage --- OK ----" ;
my $rc = eval my $rc = eval
{ {
require Math::Trig; require Math::Trig;
@ -498,8 +526,7 @@
if($rc) # test ob Math::Trig geladen wurde if($rc) # test ob Math::Trig geladen wurde
{ {
Log3 $hash, 4, "SD_WS09_WindDirAverage Math::Trig:OK" ; Log3 $hash, 4, "SD_WS09_WindDirAverage Math::Trig:OK" ;
}else } else {
{
Log3 $hash, 1, "SD_WS09_WindDirAverage Math::Trig:fehlt : cpan install Math::Trig" ; Log3 $hash, 1, "SD_WS09_WindDirAverage Math::Trig:fehlt : cpan install Math::Trig" ;
return ""; return "";
} }
@ -507,6 +534,7 @@
my $avtime = AttrVal($name,'WindDirAverageTime',0); my $avtime = AttrVal($name,'WindDirAverageTime',0);
my $decay = AttrVal($name,'WindDirAverageDecay',0); my $decay = AttrVal($name,'WindDirAverageDecay',0);
my $minspeed = AttrVal($name,'WindDirAverageMinSpeed',0); my $minspeed = AttrVal($name,'WindDirAverageMinSpeed',0);
my $windDirection_old = $wd;
# default Werte für die optionalen Parameter, falls nicht beim Aufruf mit angegeben # default Werte für die optionalen Parameter, falls nicht beim Aufruf mit angegeben
$avtime = 600 if (!(defined $avtime) || $avtime == 0 ); $avtime = 600 if (!(defined $avtime) || $avtime == 0 );
@ -554,9 +582,10 @@
Log3 $hash,4,"SD_WS09_WindDirAverage_06 $name :Speed=".$ws." Dir=".round($wd,2)." Time=".$time." minspeed=".$minspeed." num=".$num; Log3 $hash,4,"SD_WS09_WindDirAverage_06 $name :Speed=".$ws." Dir=".round($wd,2)." Time=".$time." minspeed=".$minspeed." num=".$num;
} }
} else { } else {
return undef; return $windDirection_old; # old undef | different behavior dispatch <-> UnitTest´s ($ctime - $ltime)
} }
} }
#-- output and average #-- output and average
my ($anz, $sanz) = 0; my ($anz, $sanz) = 0;
$num = int(@{$hash->{helper}{history}}); $num = int(@{$hash->{helper}{history}});
@ -586,22 +615,24 @@
} }
my $average = int((rad2deg(atan2($sumSin, $sumCos)) + 360) % 360); 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); 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 #-- 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 (($anz == 0) || ($sanz == 0));
return undef if (($sumSpeed / $sanz) < $minspeed); return undef if (($sumSpeed / $sanz) < $minspeed);
Log3 $hash,4,"SD_WS09_WindDirAverage_END $name Mittelwert=$average"; Log3 $hash,4,"SD_WS09_WindDirAverage_END $name Mittelwert=$average";
return $average; return $average;
} }
sub SD_WS09_bin2dec($) ###################################
{ sub SD_WS09_bin2dec($) {
my $h = shift; my $h = shift;
my $int = unpack("N", pack("B32",substr("0" x 32 . $h, -32))); my $int = unpack("N", pack("B32",substr("0" x 32 . $h, -32)));
return sprintf("%d", $int); return sprintf("%d", $int);
} }
sub SD_WS09_binflip($) ###################################
{ sub SD_WS09_binflip($) {
my $h = shift; my $h = shift;
my $hlen = length($h); my $hlen = length($h);
my $i = 0; my $i = 0;
@ -613,6 +644,7 @@
return $flip; return $flip;
} }
###################################
sub SD_WS09_BCD2bin($) { sub SD_WS09_BCD2bin($) {
my $binary = shift; my $binary = shift;
my $int = unpack("N", pack("B32", substr("0" x 32 . $binary, -32))); my $int = unpack("N", pack("B32", substr("0" x 32 . $binary, -32)));
@ -620,22 +652,25 @@
return $BCD; return $BCD;
} }
sub SD_WS09_SHIFT($){ ###################################
my $rawData = shift; sub SD_WS09_SHIFT($$){
my ($hash, $rawData) = @_;
my $name = $hash->{NAME};
my $hlen = length($rawData); my $hlen = length($rawData);
my $blen = $hlen * 4; my $blen = $hlen * 4;
my $bitData = unpack("B$blen", pack("H$hlen", $rawData)); my $bitData = unpack("B$blen", pack("H$hlen", $rawData));
my $bitData2 = '1'.unpack("B$blen", pack("H$hlen", $rawData)); my $bitData2 = '1'.$bitData;
my $bitData20 = substr($bitData2,0,length($bitData2)-1); my $bitData20 = substr($bitData2,0,length($bitData2)-1);
$blen = length($bitData20); $blen = length($bitData20);
$hlen = $blen / 4; $hlen = $blen / 4;
$rawData = uc(unpack("H$hlen", pack("B$blen", $bitData20))); $rawData = uc(unpack("H$hlen", pack("B$blen", $bitData20)));
$bitData = $bitData20; $bitData = $bitData20;
Log3 "SD_WS09_SHIFT", 4, "SD_WS09_SHIFT_0 raw: $rawData length:".length($bitData) ; #Log3 $hash, 4, "$name: SD_WS09_SHIFT_0 raw: $rawData length:".length($bitData);
Log3 "SD_WS09_SHIFT", 4, "SD_WS09_SHIFT_1 bitdata: $bitData" ; Log3 $hash, 5, "$name: SD_WS09_SHIFT_1 bitdata: $bitData length:".length($bitData);
return $rawData; return $rawData;
} }
###################################
sub SD_WS09_CRCCHECK($) { sub SD_WS09_CRCCHECK($) {
my $rawData = shift; my $rawData = shift;
my $datacheck1 = pack( 'H*', substr($rawData,2,length($rawData)-2) ); my $datacheck1 = pack( 'H*', substr($rawData,2,length($rawData)-2) );
@ -651,25 +686,27 @@
=pod =pod
=item summary Supports weather sensors (WH1080/3080/CTW-600) protocl 9 from SIGNALduino =item summary Supports weather sensors (WH1080/3080/CTW-600) protocl 9 from SIGNALduino
=item summary_DE Unterstuetzt Wettersensoren (WH1080/3080/CTW-600) mit Protokol 9 vom SIGNALduino =item summary_DE Unterstuetzt Wettersensoren (WH1080/3080/CTW-600) / Protokol 9 vom SIGNALduino
=begin html =begin html
<a name="SD_WS09"></a> <a name="SD_WS09"></a>
<h3>Wether Sensors protocol #9</h3> <h3>Wether Sensors protocol #9</h3>
<ul> <ul>
The SD_WS09 module interprets temperature sensor messages received by a Device like CUL, CUN, SIGNALduino etc.<br> The SD_WS09 module interprets temperature sensor messages received by a Device like CUL, CUN, SIGNALduino etc.<br><br>
Requires Perl-Modul Digest::CRC. <br> Requires Perl-Modul Digest::CRC / Math::Trig <br>
<br> <ul>
cpan install Digest::CRC or sudo apt-get install libdigest-crc-perl <br> <li>cpan install Digest::CRC or <br>
<br> sudo apt-get install libdigest-crc-perl </li>
<li>cpan install Math::Trig </li></ul><br>
<br> <br>
<b>Known models:</b> <b>Known models:</b>
<ul> <ul>
<li>WS-0101 --> Model: WH1080</li> <li>WS-0101 --> Model: WH1080</li>
<li>TFA 30.3189 / WH1080 --> Model: WH1080</li> <li>TFA 30.3189 / WH1080 --> Model: WH1080</li>
<li>1073 (WS1080) --> Model: WH1080</li> <li>1073 (WS1080) --> Model: WH1080</li>
<li>WH2315 --> Model: WH1080</li>
<li>WH3080 --> Model: WH1080</li> <li>WH3080 --> Model: WH1080</li>
<li>CTW600 --> Model: CTW600 (??) </li> <li>CTW600 --> Model: CTW600</li>
</ul> </ul>
<br> <br>
New received device are add in fhem with autocreate. New received device are add in fhem with autocreate.
@ -751,8 +788,8 @@
<li>windDirectionAverage<br> <li>windDirectionAverage<br>
As a result, the wind direction is returned, which are calculated from the current and past values As a result, the wind direction is returned, which are calculated from the current and past values
via a kind of exponential mean value. via a kind of exponential mean value.
The respective wind speed is additionally taken into account (higher speed means higher weighting)</li> The respective wind speed is additionally taken into account (higher speed means higher weighting)</li><br>
<b>WH3080:</b> <b>WH2315 / WH3080:</b>
<li>UV Index</li> <li>UV Index</li>
<li>Lux</li> <li>Lux</li>
@ -767,17 +804,18 @@
<ul> <ul>
Das SD_WS09 Module verarbeitet von einem IO Gerät (CUL, CUN, SIGNALDuino, etc.) empfangene Nachrichten von Temperatur-Sensoren.<br> Das SD_WS09 Module verarbeitet von einem IO Gerät (CUL, CUN, SIGNALDuino, etc.) empfangene Nachrichten von Temperatur-Sensoren.<br>
<br> <br>
Perl-Modul Digest::CRC erforderlich. <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> <br>
cpan install Digest::CRC oder auch <br> <b>Unterst&uuml;tze Modelle:</b>
sudo apt-get install libdigest-crc-perl <br>
<br>
<br>
<b>Unterstütze Modelle:</b>
<ul> <ul>
<li>WS-0101 --> Model: WH1080</li> <li>WS-0101 --> Model: WH1080</li>
<li>TFA 30.3189 / WH1080 --> Model: WH1080</li> <li>TFA 30.3189 / WH1080 --> Model: WH1080</li>
<li>1073 (WS1080) --> Model: WH1080</li> <li>1073 (WS1080) --> Model: WH1080</li>
<li>WH2315 --> Model: WH1080</li>
<li>WH3080 --> Model: WH1080</li> <li>WH3080 --> Model: WH1080</li>
<li>CTW600 --> Model: CTW600</li> <li>CTW600 --> Model: CTW600</li>
</ul> </ul>
@ -789,7 +827,7 @@
<b>Define</b> <b>Define</b>
<ul>Die empfangenen Sensoren werden automatisch angelegt.<br> <ul>Die empfangenen Sensoren werden automatisch angelegt.<br>
Die ID der angelegten Sensoren wird nach jedem Batteriewechsel ge&aumlndert, welche der Sensor beim Einschalten zuf&aumlllig vergibt.<br> Die ID der angelegten Sensoren wird nach jedem Batteriewechsel ge&aumlndert, welche der Sensor beim Einschalten zuf&aumlllig vergibt.<br>
CRC Checksumme wird zur Zeit noch nicht überpr&uumlft, deshalb werden Sensoren bei denen die Luftfeuchte < 0 oder > 100 ist, nicht angelegt.<br> CRC Checksumme wird zur Zeit noch nicht &uuml;berpr&uumlft, deshalb werden Sensoren bei denen die Luftfeuchte < 0 oder > 100 ist, nicht angelegt.<br>
</ul> </ul>
<br> <br>
@ -825,14 +863,14 @@
<a name="WindDirAverageTime"></a> <a name="WindDirAverageTime"></a>
<li>WindDirAverageTime<br> <li>WindDirAverageTime<br>
default ist 600s, Zeitspanne die für die Berechung berücksichtig werden soll default ist 600s, Zeitspanne die f&uuml;r die Berechung ber&uuml;cksichtig werden soll
</li><br> </li><br>
<a name="WindDirAverageMinSpeed"></a> <a name="WindDirAverageMinSpeed"></a>
<li>WindDirAverageMinSpeed<br> <li>WindDirAverageMinSpeed<br>
da bei sehr geringer Windgeschwindigkeit die Windrichtung üblicherweise nicht da bei sehr geringer Windgeschwindigkeit die Windrichtung &uuml;blicherweise nicht
eindeutig ist, kann mit minspeed ein Schwellwert angegeben werden eindeutig ist, kann mit minspeed ein Schwellwert angegeben werden
Ist die (gewichtetete) mittlere Geschwindigkeit < minspeed wird undef zurück geliefert Ist die (gewichtetete) mittlere Geschwindigkeit < minspeed wird undef zur&uuml;ck geliefert
</li><br> </li><br>
<a name="WindDirAverageDecay"></a> <a name="WindDirAverageDecay"></a>
@ -845,7 +883,7 @@
<a name="WS09_CRCAUS"></a> <a name="WS09_CRCAUS"></a>
<li>WS09_CRCAUS<br> <li>WS09_CRCAUS<br>
Wird im Signalduino-Modul (00_SIGNALduino.pm) gesetzt Wird im Signalduino-Modul (00_SIGNALduino.pm) gesetzt
<br>0: CRC-Prüfung bei WH1080 CRC-Summe = 0 <br>0: CRC-Pr&uuml;fung bei WH1080 CRC-Summe = 0
<br>2: CRC-Summe = 49 (x031) bei WH1080 wird als OK verarbeitet <br>2: CRC-Summe = 49 (x031) bei WH1080 wird als OK verarbeitet
</li><br> </li><br>
</ul><br> </ul><br>
@ -861,11 +899,11 @@
<li>windSpeed/windgust (Einheit siehe Unit_of_Wind) und windDirection (N-O-S-W)</li> <li>windSpeed/windgust (Einheit siehe Unit_of_Wind) und windDirection (N-O-S-W)</li>
<li>Rain (mm)</li> <li>Rain (mm)</li>
<li>windDirectionAverage <li>windDirectionAverage
Als Ergebnis wird die Windrichtung zurück geliefert, die aus dem aktuellen und Als Ergebnis wird die Windrichtung zur&uuml;ck geliefert, die aus dem aktuellen und
vergangenen Werten über eine Art exponentiellen Mittelwert berechnet werden. vergangenen Werten &uuml;ber eine Art exponentiellen Mittelwert berechnet werden.
Dabei wird zusätzlich die jeweilige Windgeschwindigkeit mit berücksichtigt (here Geschwindigkeit Dabei wird zusätzlich die jeweilige Windgeschwindigkeit mit ber&uuml;cksichtigt (h&ouml;here Geschwindigkeit
bedeutet höhere Gewichtung).</li> bedeutet h&ouml;here Gewichtung).</li><br>
<b>WH3080:</b> <b>WH2315 / WH3080:</b>
<li>UV Index</li> <li>UV Index</li>
<li>Lux</li> <li>Lux</li>