mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
14_SD_WS.pm: updated to version 3.5.4
added serval new sensors easier battery replace via set command git-svn-id: https://svn.fhem.de/fhem/trunk@26982 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
aa9e2afc80
commit
e2bb20f19b
@ -1,5 +1,13 @@
|
||||
# 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.
|
||||
- feature: 14_SD_WS.pm: new sensor Bresser 7-in-1 Comfort Wetter Center
|
||||
new set command to allow battery replacement
|
||||
new sensor SM60020 multi purpose environment sensor
|
||||
new sensor TFA 30.3251.10
|
||||
new senosr TFA 35.1077.54.S2 with 30.3151
|
||||
temp/hum, 30.3152 (rain) and 30.3153 (wind)
|
||||
new sensor TM40, wireless Grill-, Meat-,
|
||||
Roasting-Thermometer with 4 temp sensors
|
||||
- feature: 00_SIGNALduino.pm: Updated to vversion 3.5.4
|
||||
update commandref
|
||||
make SIGNALduino_IdList more robust
|
||||
|
@ -40,14 +40,21 @@
|
||||
# 05.01.2022 Protokoll 108: neuer Sensor Fody E42
|
||||
# 08.01.2022 neues Protokoll 107: Soil Moisture Sensor Fine Offset WH51, ECOWITT WH51, MISOL/1, Froggit DP100
|
||||
# 14.01.2022 neues Protokoll 116: Thunder and lightning sensor Fine Offset WH57, aka Froggit DP60, aka Ambient Weather WH31L
|
||||
# 29.01.2022 neues Protokoll 117: Bresser 7-in-1 Comfort Wetter Center
|
||||
# 04.02.2022 neu: set replaceBatteryForSec (Ident ersetzen bei Batteriewechsel Sensor)
|
||||
# 12.03.2022 Protokoll 115: neue Sensoren SM60020 Boden-/Erd-Sensor für Feuchte- und Temperatur, Innensensor für Feuchte- und Temperatur
|
||||
# 11.04.2022 Protokoll 85: neuer Sensor Windmesser TFA 30.3251.10 mit Windrichtung, Pruefung CRC8 eingearbeitet
|
||||
# 23.05.2022 neues Protokoll 120: Wetterstation TFA 35.1077.54.S2 mit 30.3151 (Thermo/Hygro-Sender), 30.3152 (Regenmesser), 30.3153 (Windmesser)
|
||||
# 11.06.2022 neues Protokoll 122: TM40, Wireless Grill-, Meat-, Roasting-Thermometer with 4 Temperature Sensors
|
||||
|
||||
package main;
|
||||
|
||||
#use version 0.77; our $VERSION = version->declare('v3.4.3');
|
||||
#use version 0.77; our $VERSION = version->declare('v3.5.4');
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Carp qw(carp);
|
||||
use FHEM::Meta;
|
||||
|
||||
# Forward declarations
|
||||
sub SD_WS_LFSR_digest8_reflect;
|
||||
@ -59,11 +66,11 @@ sub SD_WS_WH2SHIFT;
|
||||
sub SD_WS_Initialize {
|
||||
my $hash = shift // return;
|
||||
$hash->{Match} = '^W\d+x{0,1}#.*';
|
||||
$hash->{DefFn} = "SD_WS_Define";
|
||||
$hash->{UndefFn} = "SD_WS_Undef";
|
||||
$hash->{ParseFn} = "SD_WS_Parse";
|
||||
$hash->{DefFn} = \&SD_WS_Define;
|
||||
$hash->{UndefFn} = \&SD_WS_Undef;$hash->{SetFn} = \&SD_WS_Set;
|
||||
$hash->{ParseFn} = \&SD_WS_Parse;
|
||||
$hash->{AttrList} = "do_not_notify:1,0 ignore:0,1 showtime:1,0 " .
|
||||
"model:E0001PA,S522,TX-EZ6,other " .
|
||||
"model:E0001PA,S522,TFA_30.3251.10,TX-EZ6,other " .
|
||||
"max-deviation-temp:1,2,3,4,5,6,7,8,9,10,15,20,25,30,35,40,45,50 ".
|
||||
"max-deviation-hum:1,2,3,4,5,6,7,8,9,10,15,20,25,30,35,40,45,50 ".
|
||||
"$readingFnAttributes ";
|
||||
@ -95,8 +102,11 @@ sub SD_WS_Initialize {
|
||||
'SD_WS_113_T.*' => { ATTR => 'event-min-interval:.*:60 event-on-change-reading:.*', FILTER => '%NAME', GPLOT => 'temp4:Temp,', autocreateThreshold => '10:180'},
|
||||
'SD_WS_115.*' => { ATTR => 'event-min-interval:.*:300 event-on-change-reading:.*', FILTER => '%NAME', GPLOT => 'temp4hum4:Temp/Hum,', autocreateThreshold => '5:120'},
|
||||
'SD_WS_116.*' => { ATTR => 'event-min-interval:.*:300 event-on-change-reading:.*', FILTER => '%NAME', GPLOT => q{}, autocreateThreshold => '2:180'},
|
||||
'SD_WS_117.*' => { ATTR => 'event-min-interval:.*:300 event-on-change-reading:.*', FILTER => '%NAME', GPLOT => 'temp4hum4:Temp/Hum,', autocreateThreshold => '5:120'},
|
||||
'SD_WS_120.*' => { ATTR => 'event-min-interval:.*:300 event-on-change-reading:.*', FILTER => '%NAME', GPLOT => 'temp4hum4:Temp/Hum,', autocreateThreshold => '2:180'},
|
||||
'SD_WS_122_T.*' => { ATTR => 'event-min-interval:.*:60 event-on-change-reading:.*', FILTER => '%NAME', GPLOT => 'temp4:Temp,', autocreateThreshold => '10:180'},
|
||||
};
|
||||
return;
|
||||
return FHEM::Meta::InitMod( __FILE__, $hash );
|
||||
}
|
||||
|
||||
#############################
|
||||
@ -123,6 +133,52 @@ sub SD_WS_Undef {
|
||||
my ($hash, $name) = @_;
|
||||
carp "SD_WS_Undef, too few arguments ($hash, $name)" if @_ < 2;
|
||||
delete($modules{SD_WS}{defptr}{$hash->{CODE}}) if(defined($hash->{CODE}) && defined($modules{SD_WS}{defptr}{$hash->{CODE}}));
|
||||
RemoveInternalTimer($hash);
|
||||
return;
|
||||
}
|
||||
|
||||
#############################
|
||||
sub SD_WS_Set {
|
||||
my $hash = shift // carp 'device hash needs to be first parameter';
|
||||
my $name = shift // carp 'name of the device must be second parameter';
|
||||
my $cmd = shift // carp 'Specify the command as third prarameter';
|
||||
my @args = @_;
|
||||
|
||||
my $ret = undef;
|
||||
my $LastInputDev = $hash->{LASTInputDev};
|
||||
return $ret if (!defined $LastInputDev);
|
||||
|
||||
my $rhash = $defs{$LastInputDev};
|
||||
my $rlongids = AttrVal($rhash->{NAME},'longids',0);
|
||||
my $def = $hash->{DEF};
|
||||
my @array = split(/_/,$def);
|
||||
my $model = $array[0] . '_' . $array[1] . '_' . $array[2];
|
||||
if (($rlongids ne "0") && ($rlongids eq "1" || $rlongids eq "ALL" || ($rlongids =~ m/$model/))) {
|
||||
if ($cmd eq '?') {
|
||||
$ret = 'replaceBatteryForSec'; # return setList
|
||||
} elsif ($cmd eq 'replaceBatteryForSec') {
|
||||
return "$name: No or too small value specified for the replaceBatteryForSec command" if (scalar(@args) < 1 || $args[0] < 1);
|
||||
my @found = devspec2array("TYPE=SD_WS:FILTER=i:replaceBattery>0");
|
||||
return "$name: Only one sensor at a time, replaceBatteryForSec is already activated at @found" if (scalar(@found) > 0);
|
||||
my $repBatForSec = $args[0];
|
||||
$hash->{replaceBattery} = $repBatForSec;
|
||||
InternalTimer(gettimeofday() + $repBatForSec, \&SD_WS_TimerRemoveReplaceBattery, $hash, 0);
|
||||
Log3 $name, 3, "$name: SD_WS_Set, wait $repBatForSec seconds for a new identity of the sensor";
|
||||
} else {
|
||||
$ret = "$name: Unknown argument $cmd, choose replaceBatteryForSec";
|
||||
}
|
||||
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
#############################
|
||||
sub SD_WS_TimerRemoveReplaceBattery {
|
||||
my $hash = shift;
|
||||
my $name = $hash->{NAME};
|
||||
delete($hash->{replaceBattery});
|
||||
RemoveInternalTimer($hash);
|
||||
Log3 $name, 3, "$name: SD_WS_TimerRemoveReplaceBattery, no sensor with unknown identity received";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -151,11 +207,13 @@ sub SD_WS_Parse {
|
||||
my $rawTemp;
|
||||
my $temp;
|
||||
my $temp2;
|
||||
my $temp3;
|
||||
my $temp4;
|
||||
my $hum;
|
||||
my $windspeed;
|
||||
my $winddir;
|
||||
my $winddirtxt;
|
||||
my @winddirtxtar=('N','NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW');
|
||||
my @winddirtxtar=('N','NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW','N');
|
||||
my $windgust;
|
||||
my $trend;
|
||||
my $trendTemp;
|
||||
@ -168,8 +226,12 @@ sub SD_WS_Parse {
|
||||
my $distance;
|
||||
my $uv;
|
||||
my $adc;
|
||||
my $brightness;
|
||||
my @moisture_map=(0, 7, 13, 20, 27, 33, 40, 47, 53, 60, 67, 73, 80, 87, 93, 99); # ID 115
|
||||
my $count;
|
||||
my $identified;
|
||||
my $transmitter;
|
||||
my $dcf;
|
||||
|
||||
my %decodingSubs = (
|
||||
50 => # Protocol 50
|
||||
@ -584,12 +646,13 @@ sub SD_WS_Parse {
|
||||
} ,
|
||||
85 =>
|
||||
{
|
||||
# Protokollbeschreibung: Kombisensor TFA 30.3222.02 fuer Wetterstation TFA 35.1140.01
|
||||
# -----------------------------------------------------------------------------------
|
||||
# Protokollbeschreibung: Kombisensor TFA 30.3222.02 fuer Wetterstation TFA 35.1140.01, Windmesser TFA 30.3251.10
|
||||
# --------------------------------------------------------------------------------------------------------------
|
||||
# 0 4 | 8 12 | 16 20 | 24 28 | 32 36 | 40 44 | 48 52 | 56 60 | 64
|
||||
# 0000 1001 | 0001 0110 | 0001 0000 | 0000 0111 | 0100 1001 | 0100 0000 | 0100 1001 | 0100 1001 | 1
|
||||
# ???? iiii | iiii iiii | iiii iiii | b??? ??yy | tttt tttt | tttt ???? | hhhh hhhh | ???? ???? | ? message 1
|
||||
# ???? iiii | iiii iiii | iiii iiii | b?cc ??yy | wwww wwww | wwww ???? | 0000 0000 | ???? ???? | ? message 2
|
||||
# 0000 iiii | iiii iiii | iiii iiii | b??? ??yy | tttt tttt | tttt 0000 | hhhh hhhh | CCCC CCCC | ? message 1 TFA 30.3222.02
|
||||
# 0000 iiii | iiii iiii | iiii iiii | b?cc ??yy | wwww wwww | wwww 0000 | 0000 0000 | CCCC CCCC | ? message 2 TFA 30.3222.02
|
||||
# 0000 iiii | iiii iiii | iiii iiii | b?cc ??yy | wwww wwww | wwww dddd | dddd dddd | CCCC CCCC | ? message 2 TFA 30.3251.10
|
||||
# i: 20 bit random id (changes on power-loss)
|
||||
# b: 1 bit battery indicator (0=>OK, 1=>LOW)
|
||||
# c: 2 bit channel valid channels are (always 00 stands for channel 1)
|
||||
@ -597,14 +660,14 @@ sub SD_WS_Parse {
|
||||
# t: 12 bit unsigned temperature, offset 500, scaled by 10 - if message 1
|
||||
# h: 8 bit relative humidity percentage - if message 1
|
||||
# w: 12 bit unsigned windspeed, scaled by 10 - if message 2
|
||||
# d: 12 bit unsigned winddirection - only TFA 30.3251.10
|
||||
# C: 8 bit CRC of the preceding 7 bytes (Polynomial 0x31, Initial value 0x00, Input not reflected, Result not reflected)
|
||||
# ?: unknown
|
||||
# The sensor sends at intervals of about 30 seconds
|
||||
|
||||
sensortype => 'TFA 30.3222.02',
|
||||
sensortype => 'TFA 30.3222.02, TFA 30.3251.10, LaCrosse TX141W',
|
||||
model => 'SD_WS_85_THW',
|
||||
prematch => sub {my $msg = shift; return 1 if ($msg =~ /^[0-9A-F]{16}/); }, # min 16 nibbles
|
||||
crcok => sub {return 1;}, # crc test method is so far unknown
|
||||
id => sub {my (undef,$bitData) = @_; return substr($rawData,1,5); }, # 0952CF012B1021DF0
|
||||
id => sub {my ($rawData,undef) = @_; return substr($rawData,1,5); }, # 0952CF012B1021DF0
|
||||
bat => sub {my (undef,$bitData) = @_; return substr($bitData,24,1) eq "0" ? "ok" : "low";},
|
||||
channel => sub {my (undef,$bitData) = @_; return (SD_WS_binaryToNumber($bitData,26,27) + 1 ); }, # unknown
|
||||
temp => sub {my (undef,$bitData) = @_;
|
||||
@ -628,6 +691,34 @@ sub SD_WS_Parse {
|
||||
return;
|
||||
}
|
||||
},
|
||||
winddir => sub {my (undef,$bitData) = @_;
|
||||
if (substr($bitData,30,2) eq "10") { # message 2 winddirection
|
||||
$winddir = SD_WS_binaryToNumber($bitData,44,55);
|
||||
return ($winddir * 1, $winddirtxtar[round(($winddir / 22.5),0)]);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
crcok => sub {my ($rawData,undef) = @_;
|
||||
my $rc = eval {
|
||||
require Digest::CRC;
|
||||
Digest::CRC->import();
|
||||
1;
|
||||
};
|
||||
if ($rc) {
|
||||
my $datacheck1 = pack( 'H*', substr($rawData,0,14) );
|
||||
my $crcmein1 = Digest::CRC->new(width => 8, poly => 0x31);
|
||||
my $rr3 = $crcmein1->add($datacheck1)->hexdigest;
|
||||
if (hex($rr3) != hex(substr($rawData,14,2))) {
|
||||
Log3 $name, 3, "$name: SD_WS_85 Parse msg $rawData - ERROR CRC8";
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
Log3 $name, 1, "$name: SD_WS_85 Parse msg $rawData - ERROR CRC not load, please install modul Digest::CRC";
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
} ,
|
||||
89 =>
|
||||
{
|
||||
@ -986,64 +1077,92 @@ sub SD_WS_Parse {
|
||||
# 0123456789012345678901234567890123456789
|
||||
# ----------------------------------------
|
||||
# 3DA820B00C1618FFFFFF1808152294FFF01E0000 Msg 1, 40 Nibble from SIGNALduino, T: 15.2 H: 94 G:0 W: 0 D:180
|
||||
# CCCCIIIIIIIIFFGGGWWWDDD?TTT?HH????SS Msg 1, 36 Nibble
|
||||
# CCCCIIIIIIIIFFGGGWWWDDD?ffRRRRVVV?SS Msg 2, 36 Nibble
|
||||
# CCCCIIIIIIIIFFGGGWWWDDD?TTTFHHVVVXSS Msg 1, 36 Nibble, wind, temperature, humidity, uv
|
||||
# CCCCIIIIIIIIFFGGGWWWDDD?RRRRRR???XSS Msg 2, 36 Nibble, wind, rain
|
||||
# C = CRC16
|
||||
# I = station ID
|
||||
# F = flags, 4 bit (1: weather station, 2: indoor?, 4: soil probe), 1 bit battery (1=ok, 0=low), 3 bit channel
|
||||
# F = flags, 8 bit (nibble 12 1: weather station, 2: indoor, 4: soil probe, nibble 13 1 bit battery change, 3 bit channel)
|
||||
# G = wind gust in 1/10 m/s, inverted, BCD coded, GGG = FE6 =~ 019 => 1.9 m/s.
|
||||
# W = wind speed in 1/10 m/s, inverted, BCD coded, LSB first nibble, MSB last two nibble, WWW = EFE =~ 101 => 1.1 m/s.
|
||||
# D = wind direction in grad, BCD coded, DDD = 158 => 158 °
|
||||
# ? = unknown, always 0x8
|
||||
# T = temperature in 1/10 °C, only if byte 12 ne 0xFF, BCD coded, TTT = 312 => 31.2 °C
|
||||
# ? = unknown
|
||||
# H = humidity in percent, only if byte 12 ne 0xFF, BCD coded, HH = 23 => 23 %
|
||||
# R = rain counter, only if byte 12 eq 0xFF, inverted, BCD coded
|
||||
# V = uv, only if byte 12 eq 0xFF and byte 15/16 not 0xFF01, inverted, BCD coded
|
||||
# ? = unknown
|
||||
# ? = unknown, 0x0, 0x8 or 0xE
|
||||
# T = temperature in 1/10 °C, TTT = 312 => 31.2 °C
|
||||
# F = flags, 4 bit - bit 3 temperature (0=positive, 1=negative), bit 2 ?, bit 1 battery (1=ok, 0=low), bit 0 ?
|
||||
# H = humidity in percent, BCD coded, HH = 23 => 23 %
|
||||
# R = rain counter, inverted, BCD coded
|
||||
# V = uv, inverted, BCD coded
|
||||
# X = message type, 0 = temp, hum, wind, uv, 1 = wind, rain
|
||||
# S = checksum (sum over byte 2 - 17 must be 255)
|
||||
sensortype => 'Bresser_6in1, new Bresser_5in1',
|
||||
model => 'SD_WS_115',
|
||||
prematch => sub { return 1; }, # no precheck known
|
||||
id => sub {my ($rawData,undef) = @_; return substr($rawData,4,8); },
|
||||
bat => sub {my (undef,$bitData) = @_; return substr($bitData,52,1) eq '1' ? 'ok' : 'low';},
|
||||
channel => sub {my (undef,$bitData) = @_; return (SD_WS_binaryToNumber($bitData,53,55));},
|
||||
bat => sub {my ($rawData,$bitData) = @_;
|
||||
return if (substr($rawData,12,1) eq '1' && substr($rawData,33,1) eq '1'); # not by weather station & rain
|
||||
return substr($bitData,110,1) eq '1' ? 'ok' : 'low';
|
||||
},
|
||||
batChange => sub {my (undef,$bitData) = @_; return substr($bitData,52,1);},
|
||||
channel => sub {my ($rawData,$bitData) = @_;
|
||||
$channel = '';
|
||||
$channel = substr($rawData,12,1) if (substr($rawData,12,1) ne '1'); # not weather station
|
||||
return ($channel . SD_WS_binaryToNumber($bitData,53,55));
|
||||
},
|
||||
windgust => sub {my ($rawData,undef) = @_;
|
||||
return if (substr($rawData,12,1) ne '1'); # only weather station
|
||||
$windgust = substr($rawData,14,3);
|
||||
$windgust =~ tr/0123456789ABCDEF/FEDCBA9876543210/;
|
||||
# uncoverable branch true
|
||||
return if ($windgust !~ m/^\d+$/xms);
|
||||
return $windgust * 0.1;
|
||||
},
|
||||
windspeed => sub {my ($rawData,undef) = @_;
|
||||
return if (substr($rawData,12,1) ne '1'); # only weather station
|
||||
$windspeed = substr($rawData,18,2) . substr($rawData,17,1);
|
||||
$windspeed =~ tr/0123456789ABCDEF/FEDCBA9876543210/;
|
||||
# uncoverable branch true
|
||||
return if ($windspeed !~ m/^\d+$/xms);
|
||||
return $windspeed * 0.1;
|
||||
},
|
||||
winddir => sub {my ($rawData,undef) = @_;
|
||||
return if (substr($rawData,12,1) ne '1' || substr($rawData,20,3) !~ m/^\d+$/xms); # only weather station
|
||||
$winddir = substr($rawData,20,3);
|
||||
return if ($winddir !~ m/^\d+$/xms);
|
||||
return ($winddir * 1, $winddirtxtar[round(($winddir / 22.5),0)]);
|
||||
},
|
||||
temp => sub {my ($rawData,undef) = @_;
|
||||
return if (substr($rawData,24,2) eq 'FF');
|
||||
$rawTemp = (substr($rawData,24,1) . substr($rawData,25,1) . substr($rawData,26,1)) * 0.1;
|
||||
if ($rawTemp > 60) {$rawTemp -= 100};
|
||||
return $rawTemp;
|
||||
temp => sub {my ($rawData,$bitData) = @_;
|
||||
# uncoverable condition right
|
||||
return if ((substr($rawData,12,1) eq '1' && substr($rawData,33,1) eq '1') || substr($rawData,24,3) !~ m/^\d+$/xms); # not by weather station & rain
|
||||
$rawTemp = substr($rawData,24,3) * 0.1;
|
||||
if (substr($bitData,108,1) eq '1') {
|
||||
if ($rawTemp > 60) {
|
||||
$rawTemp -= 100; # Bresser 6in1
|
||||
} else {
|
||||
$rawTemp *= -1; # Bresser 3in1
|
||||
}
|
||||
}
|
||||
return round($rawTemp,1);
|
||||
},
|
||||
hum => sub {my ($rawData,undef) = @_;
|
||||
return if (substr($rawData,24,2) eq 'FF');
|
||||
return substr($rawData,28,2) + 0;
|
||||
# uncoverable condition right
|
||||
return if ((substr($rawData,12,1) eq '1' && substr($rawData,33,1) eq '1') || substr($rawData,28,2) !~ m/^\d+$/xms); # not by weather station & rain
|
||||
$hum = substr($rawData,28,2) * 1;
|
||||
if (substr($rawData,12,1) eq '4' && $hum >= 1 && $hum <= 16) { # Soil Moisture
|
||||
return $moisture_map[$hum - 1];
|
||||
}
|
||||
return $hum;
|
||||
},
|
||||
rain => sub {my ($rawData,undef) = @_;
|
||||
return if (substr($rawData,24,2) ne 'FF');
|
||||
$rain = substr($rawData,26,4);
|
||||
return if (substr($rawData,33,1) ne '1' || substr($rawData,12,1) ne '1'); # message type || weather station
|
||||
$rain = substr($rawData,24,6);
|
||||
$rain =~ tr/0123456789ABCDEF/FEDCBA9876543210/;
|
||||
# uncoverable branch true
|
||||
return if ($rain !~ m/^\d+$/xms);
|
||||
return $rain * 0.1;
|
||||
},
|
||||
uv => sub {my ($rawData,undef) = @_;
|
||||
return if (substr($rawData,24,2) ne 'FF' || substr($rawData,30,3) !~ m/^\d+$/xms);
|
||||
return if (substr($rawData,33,1) ne '0' || substr($rawData,12,1) ne '1'); # message type || weather station
|
||||
$uv = substr($rawData,30,3);
|
||||
$uv =~ tr/0123456789ABCDEF/FEDCBA9876543210/;
|
||||
# uncoverable branch true
|
||||
return if ($uv !~ m/^\d+$/xms);
|
||||
return $uv * 0.1;
|
||||
},
|
||||
@ -1116,6 +1235,187 @@ sub SD_WS_Parse {
|
||||
return 1;
|
||||
}
|
||||
} ,
|
||||
117 => {
|
||||
# https://github.com/merbanan/rtl_433/blob/master/src/devices/bresser_7in1.c
|
||||
# The compact 7-in-1 multifunction outdoor sensor transmits the data on 868.3 MHz.
|
||||
# The device uses FSK-PCM encoding, the device sends a transmission every 12 seconds.
|
||||
# A transmission starts with a preamble of 0xAA.
|
||||
# Preamble: aa aa aa aa aa 2d d4
|
||||
#
|
||||
# 1 2 3 4
|
||||
# 01234567890123456789012345678901234567890123456789
|
||||
# --------------------------------------------------
|
||||
# 0CF0A6F5B98A10AAAAAAAAAAAAAABABC3EAABBFCAAAAAAAAAA000000 original message
|
||||
# A65A0C5F1320BA000000000000001016940011560000000000AAAAAA message after all nibbles xor 0xA
|
||||
# CCCCIIIIDDD??FGGGWWWRRRRRR??TTTBHHbbbbbbVVVttttttt
|
||||
# C = LFSR-16 digest, generator 0x8810 key 0xba95 with a final xor 0x6df1, which likely means we got that wrong.
|
||||
# I = station ID
|
||||
# D = wind direction in degree, BCD coded, DDD = 158 => 158 °
|
||||
# F = flags, 4 bit
|
||||
# Bit: 0123
|
||||
# 1010
|
||||
# r???
|
||||
# r: 1 bit device reset, 1 after inserting battery
|
||||
# ???: always 010
|
||||
# G = wind gust in 1/10 m/s, BCD coded, GGG = 123 => 12.3 m/s.
|
||||
# W = wind speed in 1/10 m/s, BCD coded, WWW = 123 => 12.3 m/s.
|
||||
# R = rain counter, in 0.1 mm, BCD coded RRRRRR = 000084 => 8.4 mm
|
||||
# T = temperature in 1/10 °C, BCD coded, TTT = 312 => 31.2 °C
|
||||
# B = battery. 0=Ok, 6=Low
|
||||
# H = humidity in percent, BCD coded, HH = 23 => 23 %
|
||||
# b = brightness, BCD coded, BBBBBB = 005584 => 5.584 klx
|
||||
# V = uv, BCD coded, VVV = 012 => 1.2
|
||||
# ? = unknown
|
||||
# t = trailer
|
||||
sensortype => 'Bresser_7in1',
|
||||
model => 'SD_WS_117',
|
||||
prematch => sub {my $rawData = shift; return 1 if ($rawData =~ /^[0-9A-F]{8}[0-9]{3}[0-9A-F]{3}[0-9]{12}[0-9A-F]{2}[0-9]{15}/); },
|
||||
id => sub {my ($rawData,undef) = @_; return substr($rawData,4,4); },
|
||||
winddir => sub {my ($rawData,undef) = @_;
|
||||
$winddir = substr($rawData,8,3);
|
||||
return ($winddir * 1, $winddirtxtar[round(($winddir / 22.5),0)]);
|
||||
},
|
||||
batChange => sub {my (undef,$bitData) = @_; return substr($bitData,52,1) eq '0' ? '1' : '0';},
|
||||
windgust => sub {my ($rawData,undef) = @_; return substr($rawData,14,3) * 0.1;},
|
||||
windspeed => sub {my ($rawData,undef) = @_; return substr($rawData,17,3) * 0.1;},
|
||||
rain => sub {my ($rawData,undef) = @_; return substr($rawData,20,6) * 0.1;},
|
||||
temp => sub {my ($rawData,undef) = @_;
|
||||
$rawTemp = substr($rawData,28,3) * 0.1;
|
||||
if ($rawTemp > 60) {$rawTemp -= 100};
|
||||
return $rawTemp;
|
||||
},
|
||||
bat => sub {my ($rawData,undef) = @_; return substr($rawData,31,1) eq '0' ? 'ok' : 'low';},
|
||||
hum => sub {my ($rawData,undef) = @_; return substr($rawData,32,2) * 1;},
|
||||
brightness => sub {my ($rawData,undef) = @_; return substr($rawData,34,6) * 0.001;},
|
||||
uv => sub {my ($rawData,undef) = @_; return substr($rawData,40,3) * 0.1;},
|
||||
crcok => sub {return 1;}, # checks are in SD_Protocols.pm sub ConvBresser_7in1
|
||||
},
|
||||
120 => {
|
||||
# Weather station TFA 35.1077.54.S2 with 30.3151 (T/H-transmitter), 30.3152 (rain gauge), 30.3153 (anemometer)
|
||||
# ------------------------------------------------------------------------------------------------------------
|
||||
# https://forum.fhem.de/index.php/topic,119335.msg1221926.html#msg1221926
|
||||
# 0 4 | 8 12 | 16 20 | 24 28 | 32 36 | 40 44 | 48 52 | 56 60 | 64 68 | 72 76
|
||||
# 1111 1110 | 1010 1011 | 0000 0100 | 1001 1110 | 1010 1010 | 0000 1000 | 0000 1100 | 0000 1100 | 0101 0011 | 0000 0000 - T: 19.1 H: 85 W: 1.3 R: 473.1
|
||||
# PPPP PPPW | WWWI IIII | IIIF BTTT | TTTT TTTH | HHHH HHHS | SSSS SSSG | GGGG GGGR | RRRR RRRR | RRRR RRR? | CCCC CCCC
|
||||
# 1111 1110 | 1100 1011 | 0001 0101 | 0011 0000 | 0000 0110 | 0000 1100 | 0100 0100 | 1000 1100 | 0100 1111 | 1011 1000 - 2022-06-27 18:03:06
|
||||
# PPPP PPPW | WWWI IIII | IIIF ???? | ?hhh hhh? | mmmm mmm? | ssss sssY | YYYY YYY? | ??MM MMM? | ?DDD DDD? | CCCC CCCC
|
||||
# P - 7 bit preamble
|
||||
# W - 4 bit whid, 0101=weather, 0110=time
|
||||
# I - 8 bit ident
|
||||
# F - 1 bit flag, 0=weather, 1=time
|
||||
# B - 1 bit battery
|
||||
# T - 10 bit temperature in 1/10 °C, offset 40
|
||||
# H - 8 bit humidity in percent
|
||||
# S - 8 bit windspeed in 1/10 m/s, resolution 0.33333
|
||||
# G - 8 bit windgust in 1/10 m/s, resolution 0.33333
|
||||
# R - 16 bit rain counter, resolution 0.3 mm
|
||||
# C - 8 bit CRC8 of byte 1-10 bytes, result must be 0 (Polynomial 0x31)
|
||||
# h - 6 bit hour, BCD coded
|
||||
# m - 7 bit minute, BCD coded
|
||||
# s - 7 bit second, BCD coded
|
||||
# Y - 8 bit year, BCD coded
|
||||
# M - 5 bit month, BCD coded
|
||||
# D - 6 bit day, BCD coded
|
||||
# ? - x bit unknown
|
||||
sensortype => 'TFA_35.1077',
|
||||
model => 'SD_WS_120',
|
||||
prematch => sub {return 1;}, # no precheck known
|
||||
id => sub {my (undef,$bitData) = @_; return SD_WS_binaryToNumber($bitData,11,18);},
|
||||
bat => sub {my (undef,$bitData) = @_; return substr($bitData,20,1) eq '0' ? 'ok' : 'low';},
|
||||
temp => sub {my (undef,$bitData) = @_;
|
||||
return if (substr($bitData,19,1) eq '1');
|
||||
return SD_WS_binaryToNumber($bitData,21,30) * 0.1 - 40;
|
||||
},
|
||||
hum => sub {my (undef,$bitData) = @_;
|
||||
return if (substr($bitData,19,1) eq '1');
|
||||
return SD_WS_binaryToNumber($bitData,31,38);
|
||||
},
|
||||
windspeed => sub {my (undef,$bitData) = @_;
|
||||
return if (substr($bitData,19,1) eq '1');
|
||||
return round((SD_WS_binaryToNumber($bitData,39,46) / 3.0),1);
|
||||
},
|
||||
windgust => sub {my (undef,$bitData) = @_;
|
||||
return if (substr($bitData,19,1) eq '1');
|
||||
return round((SD_WS_binaryToNumber($bitData,47,54) / 3.0),1);
|
||||
},
|
||||
rawRainCounter => sub {my (undef,$bitData) = @_;
|
||||
return if (substr($bitData,19,1) eq '1');
|
||||
return SD_WS_binaryToNumber($bitData,55,70);
|
||||
},
|
||||
rain => sub {my (undef,$bitData) = @_;
|
||||
return if (substr($bitData,19,1) eq '1');
|
||||
return SD_WS_binaryToNumber($bitData,55,70) * 0.3;
|
||||
},
|
||||
dcf => sub {my (undef,$bitData) = @_;
|
||||
return if (substr($bitData,19,1) eq '0');
|
||||
return '20' . SD_WS_binaryToNumber($bitData,47,50) . SD_WS_binaryToNumber($bitData,51,54) . '-' # year
|
||||
. substr($bitData,58,1) . SD_WS_binaryToNumber($bitData,59,62) . '-' # month
|
||||
. SD_WS_binaryToNumber($bitData,65,66) . SD_WS_binaryToNumber($bitData,67,70) . ' ' # day
|
||||
. SD_WS_binaryToNumber($bitData,25,26) . SD_WS_binaryToNumber($bitData,27,30) . ':' # hour
|
||||
. SD_WS_binaryToNumber($bitData,32,34) . SD_WS_binaryToNumber($bitData,35,38) . ':' # minute
|
||||
. SD_WS_binaryToNumber($bitData,40,42) . SD_WS_binaryToNumber($bitData,43,46) # second
|
||||
},
|
||||
crcok => sub {my $rawData = shift;
|
||||
my $rc = eval {
|
||||
require Digest::CRC;
|
||||
Digest::CRC->import();
|
||||
1;
|
||||
};
|
||||
if ($rc) {
|
||||
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;
|
||||
if (hex($rr3) != 0) {
|
||||
Log3 $name, 3, "$name: SD_WS_120 Parse msg $rawData - ERROR CRC8";
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
Log3 $name, 1, "$name: SD_WS_120 Parse msg $rawData - ERROR CRC not load, please install modul Digest::CRC";
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
},
|
||||
122 => {
|
||||
# TM40, Wireless Grill-, Meat-, Roasting-Thermometer with 4 Temperature Sensors
|
||||
# -----------------------------------------------------------------------------
|
||||
# 0 4 | 8 12 | 16 20 | 24 28 | 32 36 | 40 44 | 48 52 | 56 60 | 64 68 | 72 76 | 80 84 | 88 92 | 96 100 | 104
|
||||
# 1001 0010 | 0110 0011 | 0000 0001 | 0011 0110 | 0000 0001 | 0011 0110 | 0000 0001 | 0100 0000 | 0000 0001 | 0110 1000 | 0000 0000 | 0000 0000 | 1011 1000 | 1000
|
||||
# iiii iiii | iiii iiii | 4444 4444 | 4444 4444 | 3333 3333 | 3333 3333 | 2222 2222 | 2222 2222 | tttt tttt | tttt tttt | ???? ???? | b??? p??? | CCCC CCCC | 1
|
||||
# i: 16 bit id, changes when the batteries are inserted
|
||||
# 4: 16 bit unsigned temperature 4, 65235 = sensor not connected
|
||||
# 3: 16 bit unsigned temperature 3, 65235 = sensor not connected
|
||||
# 2: 16 bit unsigned temperature 2, 65235 = sensor not connected
|
||||
# t: 16 bit unsigned temperature 1, 65235 = sensor not connected
|
||||
# b: 1 bit battery. 0 = Ok, 1 = Low
|
||||
# p: 1 bit transmitter power. 0 = On, 1 = off
|
||||
# ?: 16 bit flags, 4 bits per sensor, meaning of the lower 3 bits 101 = not connected, 000 = connected
|
||||
# C: 8 bit check???, always changes bit 1-7, bit 0 always 0
|
||||
# Sensor transmits at intervals of about 3 to 4 seconds
|
||||
sensortype => 'TM40',
|
||||
model => 'SD_WS_122_T',
|
||||
prematch => sub { return 1; }, # no precheck known
|
||||
id => sub { my ($rawData,undef) = @_; return substr($rawData,0,4); },
|
||||
temp4 => sub { my (undef,$bitData) = @_;
|
||||
return if (substr($bitData,81,3) ne '000');
|
||||
return SD_WS_binaryToNumber($bitData,16,31) / 10;
|
||||
},
|
||||
temp3 => sub { my (undef,$bitData) = @_;
|
||||
return if (substr($bitData,85,3) ne '000');
|
||||
return SD_WS_binaryToNumber($bitData,32,47) / 10;
|
||||
},
|
||||
temp2 => sub { my (undef,$bitData) = @_;
|
||||
return if (substr($bitData,89,3) ne '000');
|
||||
return SD_WS_binaryToNumber($bitData,48,63) / 10;
|
||||
},
|
||||
temp => sub { my (undef,$bitData) = @_;
|
||||
return if (substr($bitData,93,3) ne '000');
|
||||
return SD_WS_binaryToNumber($bitData,64,79) / 10;
|
||||
},
|
||||
bat => sub { my (undef,$bitData) = @_; return substr($bitData,88,1) eq "0" ? "ok" : "low"; },
|
||||
transmitter => sub { my (undef,$bitData) = @_; return substr($bitData,92,1) eq "0" ? "on" : "off"; },
|
||||
crcok => sub {return 1;}, # Check could not be determined yet.
|
||||
},
|
||||
);
|
||||
|
||||
Log3 $name, 4, "$name: SD_WS_Parse protocol $protocol, rawData $rawData";
|
||||
@ -1430,6 +1730,8 @@ sub SD_WS_Parse {
|
||||
$id = $decodingSubs{$protocol}{id}->( $rawData,$bitData );
|
||||
$temp = $decodingSubs{$protocol}{temp}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{temp}));
|
||||
$temp2 = $decodingSubs{$protocol}{temp2}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{temp2}));
|
||||
$temp3 = $decodingSubs{$protocol}{temp3}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{temp3}));
|
||||
$temp4 = $decodingSubs{$protocol}{temp4}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{temp4}));
|
||||
$hum = $decodingSubs{$protocol}{hum}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{hum}));
|
||||
$windspeed = $decodingSubs{$protocol}{windspeed}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{windspeed}));
|
||||
($winddir,$winddirtxt) = $decodingSubs{$protocol}{winddir}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{winddir}));
|
||||
@ -1455,6 +1757,9 @@ sub SD_WS_Parse {
|
||||
$count = $decodingSubs{$protocol}{count}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{count}));
|
||||
$identified = $decodingSubs{$protocol}{identified}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{identified}));
|
||||
$uv = $decodingSubs{$protocol}{uv}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{uv}));
|
||||
$brightness = $decodingSubs{$protocol}{brightness}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{brightness}));
|
||||
$transmitter = $decodingSubs{$protocol}{transmitter}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{transmitter}));
|
||||
$dcf = $decodingSubs{$protocol}{dcf}->( $rawData,$bitData ) if (exists($decodingSubs{$protocol}{dcf}));
|
||||
Log3 $iohash, 4, "$name: SD_WS_Parse decoded protocol-id $protocol ($SensorTyp), sensor-id $id";
|
||||
}
|
||||
else {
|
||||
@ -1487,6 +1792,22 @@ sub SD_WS_Parse {
|
||||
$def = $modules{SD_WS}{defptr}{$deviceCode} if(!$def);
|
||||
|
||||
if(!$def) {
|
||||
if (($longids ne "0") && ($longids eq "1" || $longids eq "ALL" || (",$longids," =~ m/,$model,/))) {
|
||||
my @found = devspec2array(q[TYPE=SD_WS:FILTER=i:replaceBattery>0]);
|
||||
if (scalar(@found) > 0) {
|
||||
my $rname = $found[0];
|
||||
my $rproto = InternalVal($rname, $ioname. q[_Protocol_ID], undef);
|
||||
if (defined $rproto && $rproto eq $protocol) {
|
||||
my $rhash = $defs{$rname};
|
||||
my $rdef = $rhash->{DEF};
|
||||
Log3 $name, 3, qq[$rname: SD_WS_Parse, change DEF from $rdef in $deviceCode];
|
||||
CommandModify(undef, qq[$rname $deviceCode]);
|
||||
delete($rhash->{replaceBattery});
|
||||
RemoveInternalTimer($rhash);
|
||||
return $rname;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log3 $iohash, 1, "$name: SD_WS_Parse UNDEFINED sensor $model detected, code $deviceCode";
|
||||
return "UNDEFINED $deviceCode SD_WS $deviceCode";
|
||||
}
|
||||
@ -1496,7 +1817,7 @@ sub SD_WS_Parse {
|
||||
return "" if(IsIgnored($name));
|
||||
|
||||
if (defined $temp) {
|
||||
if (($temp < -30 || $temp > 70) && $protocol ne '106' && $protocol ne '113') { # not forBBQ temperature sensor GT-TMBBQ-01s and Wireless Grill Thermometer GFGT 433 B1
|
||||
if (($temp < -30 || $temp > 70) && $protocol ne '106' && $protocol ne '113' && $protocol ne '122') { # not forBBQ temperature sensor GT-TMBBQ-01s, Wireless Grill Thermometer GFGT 433 B1 and TM40
|
||||
Log3 $name, 3, "$ioname: SD_WS_Parse $deviceCode - ERROR temperature $temp";
|
||||
return "";
|
||||
}
|
||||
@ -1509,18 +1830,14 @@ sub SD_WS_Parse {
|
||||
}
|
||||
|
||||
# Sanity checks
|
||||
if($def && $protocol ne '106' && $protocol ne '113') { # not forBBQ temperature sensor GT-TMBBQ-01s and Wireless Grill Thermometer GFGT 433 B1
|
||||
my $timeSinceLastUpdate = abs(ReadingsAge($name, "state", 0));
|
||||
if($def && $protocol ne '106' && $protocol ne '113' && $protocol ne '122') { # not forBBQ temperature sensor GT-TMBBQ-01s, Wireless Grill Thermometer GFGT 433 B1 and TM40
|
||||
my $timeSinceLastUpdate = abs(ReadingsAge($name, 'state', 0));
|
||||
# temperature
|
||||
if (defined($temp) && defined(ReadingsVal($name, "temperature", undef))) {
|
||||
my $diffTemp = 0;
|
||||
my $oldTemp = ReadingsVal($name, "temperature", undef);
|
||||
my $oldTemp = ReadingsVal($name, 'temperature', undef);
|
||||
if (defined $oldTemp && defined $temp) {
|
||||
#my $oldTemp = ReadingsVal($name, "temperature", undef);
|
||||
my $maxdeviation = AttrVal($name, "max-deviation-temp", 1); # default 1 K
|
||||
if ($temp > $oldTemp) {
|
||||
$diffTemp = ($temp - $oldTemp);
|
||||
} else {
|
||||
$diffTemp = ($oldTemp - $temp);
|
||||
}
|
||||
my $diffTemp = abs($temp - $oldTemp);
|
||||
$diffTemp = sprintf("%.1f", $diffTemp);
|
||||
Log3 $name, 4, "$ioname: $name old temp $oldTemp, age $timeSinceLastUpdate, new temp $temp, diff temp $diffTemp";
|
||||
my $maxDiffTemp = $timeSinceLastUpdate / 60 + $maxdeviation; # maxdeviation + 1.0 Kelvin/Minute
|
||||
@ -1532,15 +1849,11 @@ sub SD_WS_Parse {
|
||||
}
|
||||
}
|
||||
# humidity
|
||||
if (defined($hum) && defined(ReadingsVal($name, "humidity", undef))) {
|
||||
my $diffHum = 0;
|
||||
my $oldHum = ReadingsVal($name, "humidity", undef);
|
||||
my $oldHum = ReadingsVal($name, 'humidity', undef);
|
||||
if (defined $oldHum && defined $hum) {
|
||||
#my $oldHum = ReadingsVal($name, "humidity", undef);
|
||||
my $maxdeviation = AttrVal($name, "max-deviation-hum", 1); # default 1 %
|
||||
if ($hum > $oldHum) {
|
||||
$diffHum = ($hum - $oldHum);
|
||||
} else {
|
||||
$diffHum = ($oldHum - $hum);
|
||||
}
|
||||
my $diffHum = abs($hum - $oldHum);
|
||||
$diffHum = sprintf("%.1f", $diffHum);
|
||||
Log3 $name, 4, "$ioname: $name old hum $oldHum, age $timeSinceLastUpdate, new hum $hum, diff hum $diffHum";
|
||||
my $maxDiffHum = $timeSinceLastUpdate / 60 + $maxdeviation; # $maxdeviation + 1.0 %/Minute
|
||||
@ -1566,12 +1879,20 @@ sub SD_WS_Parse {
|
||||
#my $state = (($temp > -60 && $temp < 70) ? "T: $temp":"T: xx") . (($hum > 0 && $hum < 100) ? " H: $hum":"");
|
||||
my $state = "";
|
||||
if (defined($temp)) {
|
||||
$state .= "T: $temp"
|
||||
$state .= "T: $temp";
|
||||
}
|
||||
if (defined($temp2)) {
|
||||
$state .= ' ' if (length($state) > 0);
|
||||
$state .= "T2: $temp2";
|
||||
}
|
||||
if (defined($temp3)) {
|
||||
$state .= ' ' if (length($state) > 0);
|
||||
$state .= "T3: $temp3";
|
||||
}
|
||||
if (defined($temp4)) {
|
||||
$state .= ' ' if (length($state) > 0);
|
||||
$state .= "T4: $temp4";
|
||||
}
|
||||
if (defined($hum) && ($hum > 0 && $hum < 100)) {
|
||||
$state .= " H: $hum"
|
||||
}
|
||||
@ -1595,6 +1916,11 @@ sub SD_WS_Parse {
|
||||
$state .= ' ' if (length($state) > 0);
|
||||
$state .= "D: $distance";
|
||||
}
|
||||
if (defined($brightness)) {
|
||||
$state .= ' ' if (length($state) > 0);
|
||||
$state .= "B: $brightness";
|
||||
}
|
||||
|
||||
### protocol 33 has different bits per sensor type
|
||||
if ($protocol eq "33") {
|
||||
if (AttrVal($name,'model',0) eq "S522") { # Conrad S522
|
||||
@ -1611,10 +1937,20 @@ sub SD_WS_Parse {
|
||||
}
|
||||
}
|
||||
|
||||
### Protocol 85 without wind direction
|
||||
if ($protocol eq "85") {
|
||||
if (AttrVal($name,'model',0) ne "TFA_30.3251.10") {
|
||||
$winddir = undef;
|
||||
$winddirtxt = undef;
|
||||
}
|
||||
}
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
readingsBulkUpdate($hash, "state", $state);
|
||||
readingsBulkUpdate($hash, "temperature", $temp) if (defined($temp) && (($temp > -60 && $temp < 70 ) || $protocol eq '106' || $protocol eq '113'));
|
||||
readingsBulkUpdate($hash, "temperature2", $temp2) if (defined($temp2) && (($temp2 > -60 && $temp < 70 ) || $protocol eq '113'));
|
||||
readingsBulkUpdate($hash, "temperature", $temp) if (defined($temp) && (($temp > -60 && $temp < 70 ) || $protocol eq '106' || $protocol eq '113' || $protocol eq '122'));
|
||||
readingsBulkUpdate($hash, "temperature2", $temp2) if (defined($temp2) && (($temp2 > -60 && $temp2 < 70 ) || $protocol eq '113' || $protocol eq '122'));
|
||||
readingsBulkUpdate($hash, "temperature3", $temp3) if (defined($temp3) && (($temp3 > -60 && $temp3 < 70 ) || $protocol eq '122'));
|
||||
readingsBulkUpdate($hash, "temperature4", $temp4) if (defined($temp4) && (($temp4 > -60 && $temp4 < 70 ) || $protocol eq '122'));
|
||||
readingsBulkUpdate($hash, "humidity", $hum) if (defined($hum) && ($hum > 0 && $hum < 100 )) ;
|
||||
readingsBulkUpdate($hash, 'windSpeed', $windspeed) if (defined($windspeed)) ;
|
||||
readingsBulkUpdate($hash, 'windDirectionDegree', $winddir) if (defined($winddir)) ;
|
||||
@ -1640,10 +1976,12 @@ sub SD_WS_Parse {
|
||||
readingsBulkUpdate($hash, 'count', $count) if (defined($count));
|
||||
readingsBulkUpdate($hash, 'identified', $identified) if (defined($identified));
|
||||
readingsBulkUpdate($hash, "uv", $uv) if (defined($uv));
|
||||
readingsBulkUpdate($hash, 'brightness', $brightness) if (defined($brightness));
|
||||
readingsBulkUpdateIfChanged($hash, 'transmitter', $transmitter) if (defined($transmitter));
|
||||
readingsBulkUpdate($hash, 'dcf', $dcf) if (defined($dcf));
|
||||
readingsEndUpdate($hash, 1); # Notify is done by Dispatch
|
||||
|
||||
return $name;
|
||||
|
||||
}
|
||||
|
||||
#############################
|
||||
@ -1737,7 +2075,7 @@ sub SD_WS_WH2SHIFT {
|
||||
<li>ADE WS1907 Weather station with rain gauge</li>
|
||||
<li>Atech wireless weather station</li>
|
||||
<li>BBQ temperature sensor GT-TMBBQ-01s (transmitter), GT-TMBBQ-01e (receiver)</li>
|
||||
<li>Bresser 5-in-1 and 6-in-1 Comfort Weather Center, 7009994, Professional rain gauge, Temeo</li>
|
||||
<li>Bresser 5-in-1, 6-in-1 and 7-in-1 Comfort Weather Center, 7009994, Professional rain gauge, Temeo</li>
|
||||
<li>Conrad S522</li>
|
||||
<li>EuroChron EFTH-800, EFS-3110A (temperature and humidity sensor)</li>
|
||||
<li>Fine Offset WH51, aka ECOWITT WH51, aka Froggit DP100, aka MISOL/1 (soil moisture sensor)</li>
|
||||
@ -1749,14 +2087,14 @@ sub SD_WS_WH2SHIFT {
|
||||
<li>Renkforce E0001PA</li>
|
||||
<li>Rain gauge DROP TFA 47.3005.01 with rain sensor TFA 30.3233.01</li>
|
||||
<li>TECVANCE TV-4848</li>
|
||||
<li>Thermometer TFA 30.3228.02, TFA 30.3229.02, FT007T, FT007TP, F007T, F007TP</li>
|
||||
<li>Thermo-Hygrometer TFA 30.3208.02, FT007TH, F007TH</li>
|
||||
<li>Thermometer FT007T, FT007TP, F007T, F007TP</li>
|
||||
<li>Thermo-Hygrometer FT007TH, F007TH</li>
|
||||
<li>TS-FT002 Water tank level monitor with temperature</li>
|
||||
<li>TX-EZ6 for Weatherstation TZS First Austria</li>
|
||||
<li>WH2, WH2A (TFA Dostmann/Wertheim 30.3157 (sold in Germany), Agimex Rosenborg 66796 (sold in Denmark),ClimeMET CM9088 (Sold in UK)</li>
|
||||
<li>Weatherstation Auriol IAN 283582 Version 06/2017 (Lidl), Modell-Nr.: HG02832D</li>
|
||||
<li>Weatherstation Auriol AHFL 433 B2, IAN 314695 (Lidl)</li>
|
||||
<li>Weatherstation TFA 35.1140.01 with temperature / humidity sensor TFA 30.3221.02 and temperature / humidity / windspeed sensor TFA 30.3222.02</li>
|
||||
<li>Weatherstations and sensors TFA 30.3151, 30.3152, 30.3153, 30.3157, 30.3200, 30.3208.02, 30.3221.02, 30.3222.02, 30.3228.02, 30.3229.02, 30.3233.01, 30.3251.10, 35.1077.54.S2, 35.1140.01</li>
|
||||
<li>Wireless Grill Thermometer, Model name: GFGT 433 B1</li>
|
||||
</ul><br><br>
|
||||
|
||||
@ -1787,6 +2125,7 @@ sub SD_WS_WH2SHIFT {
|
||||
<li>batteryState (low or ok)</li>
|
||||
<li>batteryVoltage (battery voltage in volts)</li>
|
||||
<li>batteryPercent (battery level in %)</li>
|
||||
<li>brightness (kLux)</li>
|
||||
<li>channel (number of channel</li>
|
||||
<li>distance (distance in cm (protocol 111) or km (protocol 116)</li>
|
||||
<li>humidity (humidity (1-100 % only if available)</li>
|
||||
@ -1798,6 +2137,7 @@ sub SD_WS_WH2SHIFT {
|
||||
<li>temperature (°C)</li>
|
||||
<li>temperatureTrend (consistent, rising, falling)</li>
|
||||
<li>type (type of sensor)</li>
|
||||
<li>uv (ultraviolet radiation)</li>
|
||||
<li>windDirectionDegree (Wind direction, grad)</li>
|
||||
<li>windDirectionText (Wind direction, N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW)</li>
|
||||
<li>windGust (Gust of wind, m/s)</li>
|
||||
@ -1833,19 +2173,32 @@ sub SD_WS_WH2SHIFT {
|
||||
<a name="end_max-deviation-temp"></a>
|
||||
</li><br>
|
||||
<li>model<br>
|
||||
(Default: other, currently supported sensors: E0001PA, S522 and TX-EZ6)<br>
|
||||
(Default: other, currently supported sensors: E0001PA, S522, TFA_30.3251.10 and TX-EZ6)<br>
|
||||
<a name="model"></a>
|
||||
The sensors of the "SD_WS_33 series" use different positions for the battery bit and different readings.
|
||||
If the battery bit is detected incorrectly (low instead of ok), then you can possibly adjust with the model selection of the sensor.<br>
|
||||
So far, 3 variants are known. All sensors are created by Autocreate as model "other".
|
||||
If you receive a Conrad S522, Renkforce E0001PA or TX-EZ6, then set the appropriate model for the proper processing of readings.
|
||||
<br>
|
||||
Protocol 85 (SD_WS_85_THW) decodes two different sensor types: TFA 30.3222.02 (thermo-hygro-wind) and 30.3251.10 (wind).
|
||||
The attribute must be set to this value "TFA_30.3251.10" so that the wind direction is also displayed for the sensor TFA 30.3251.10.
|
||||
<a name="end_model"></a>
|
||||
</li><br>
|
||||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li><br>
|
||||
<li><a href="#showtime">showtime</a></li><br>
|
||||
</ul><br>
|
||||
<b>Set</b>
|
||||
<ul>N/A</ul><br>
|
||||
<a name="SD_WS Set"></a>
|
||||
<b>Set</b><br><br>
|
||||
<ul>
|
||||
<li>replaceBatteryForSec<br>
|
||||
(Only available for devices whose SIGNALduinos have the "longids" attribute activated.)
|
||||
<br><br>
|
||||
<code>replaceBatteryForSec <seconds></code>
|
||||
<br><br>
|
||||
Puts the device into battery change mode for <code><secondes></code>.
|
||||
The first unknown address with the same protocol that is received replaces the current device address.
|
||||
</li>
|
||||
</ul><br>
|
||||
</ul>
|
||||
|
||||
=end html
|
||||
@ -1862,7 +2215,7 @@ sub SD_WS_WH2SHIFT {
|
||||
<li>ADE WS1907 Wetterstation mit Regenmesser</li>
|
||||
<li>Atech Wetterstation</li>
|
||||
<li>BBQ Temperatur Sensor GT-TMBBQ-01s (Sender), GT-TMBBQ-01e (Empfaenger)</li>
|
||||
<li>Bresser 5-in-1 und 6-in-1 Comfort Wetter Center, 7009994, Profi Regenmesser, Temeo</li>
|
||||
<li>Bresser 5-in-1, 6-in-1 und 7-in-1 Comfort Wetter Center, 7009994, Profi Regenmesser, Temeo</li>
|
||||
<li>Conrad S522</li>
|
||||
<li>EuroChron EFTH-800, EFS-3110A (Temperatur- und Feuchtigkeitssensor)</li>
|
||||
<li>Fine Offset WH51, aka ECOWITT WH51, aka Froggit DP100, aka MISOL/1 (Bodenfeuchtesensor)</li>
|
||||
@ -1875,14 +2228,14 @@ sub SD_WS_WH2SHIFT {
|
||||
<li>Regenmesser DROP TFA 47.3005.01 mit Regensensor TFA 30.3233.01</li>
|
||||
<li>Renkforce E0001PA</li>
|
||||
<li>TECVANCE TV-4848</li>
|
||||
<li>Temperatur-Sensor TFA 30.3228.02, TFA 30.3229.02, FT007T, FT007TP, F007T, F007TP</li>
|
||||
<li>Temperatur/Feuchte-Sensor TFA 30.3208.02, FT007TH, F007TH</li>
|
||||
<li>Temperatur-Sensor FT007T, FT007TP, F007T, F007TP</li>
|
||||
<li>Temperatur/Feuchte-Sensor FT007TH, F007TH</li>
|
||||
<li>TS-FT002 Wassertank Füllstandswächter mit Temperatur</li>
|
||||
<li>TX-EZ6 fuer Wetterstation TZS First Austria</li>
|
||||
<li>WH2, WH2A (TFA Dostmann/Wertheim 30.3157 (Deutschland), Agimex Rosenborg 66796 (Denmark), ClimeMET CM9088 (UK)</li>
|
||||
<li>Wetterstation Auriol IAN 283582 Version 06/2017 (Lidl), Modell-Nr.: HG02832D</li>
|
||||
<li>Wetterstation Auriol AHFL 433 B2, IAN 314695 (Lidl)</li>
|
||||
<li>Wetterstation TFA 35.1140.01 mit Temperatur-/Feuchtesensor TFA 30.3221.02 und Temperatur-/Feuchte- und Windsensor TFA 30.3222.02</li>
|
||||
<li>Wetterstationen und Sensoren TFA 30.3151, 30.3152, 30.3153, 30.3157, 30.3200, 30.3208.02, 30.3221.02, 30.3222.02, 30.3228.02, 30.3229.02, 30.3233.01, 30.3251.10, 35.1077.54.S2, 35.1140.01</li>
|
||||
</ul>
|
||||
<br><br>
|
||||
|
||||
@ -1913,6 +2266,7 @@ sub SD_WS_WH2SHIFT {
|
||||
<li>batteryState (low oder ok)</li>
|
||||
<li>batteryVoltage (Batteriespannung in Volt)</li>
|
||||
<li>batteryPercent (Batteriestand in %)</li>
|
||||
<li>brightness (Helligkeit in kLux)</li>
|
||||
<li>channel (Sensor-Kanal)</li>
|
||||
<li>distance (Entfernung in cm (Protokoll 111) oder km (Protokoll 116)</li>
|
||||
<li>humidity (Luft-/Bodenfeuchte, 1-100 %)</li>
|
||||
@ -1924,6 +2278,7 @@ sub SD_WS_WH2SHIFT {
|
||||
<li>temperature (Temperatur °C)</li>
|
||||
<li>temperatureTrend (Trend Temperatur gleichbleibend, steigend, fallend)</li>
|
||||
<li>type (Sensortypen)</li>
|
||||
<li>uv (Ultraviolettstrahlung)</li>
|
||||
<li>windDirectionDegree (Windrichtung, Grad)</li>
|
||||
<li>windDirectionText (Windrichtung, N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW)</li>
|
||||
<li>windGust (Windboe, m/s)</li>
|
||||
@ -1961,11 +2316,14 @@ sub SD_WS_WH2SHIFT {
|
||||
</li><br>
|
||||
<li>model<br>
|
||||
<a name="model"></a>
|
||||
(Standard: other, zur Zeit unterstützte Sensoren: E0001PA, S522, TX-EZ6)<br>
|
||||
(Standard: other, zur Zeit unterstützte Sensoren: E0001PA, S522, TFA_30.3251.10, TX-EZ6)<br>
|
||||
Die Sensoren der "SD_WS_33 - Reihe" verwenden unterschiedliche Positionen für das Batterie-Bit und unterstützen verschiedene Readings.
|
||||
Sollte das Batterie-Bit falsch erkannt werden (low statt ok), so kann man mit der Modelauswahl des Sensors das evtl. anpassen.<br>
|
||||
Bisher sind 3 Varianten bekannt. Alle Sensoren werden durch Autocreate als Model "other" angelegt.
|
||||
Empfangen Sie einen Sensor vom Typ Conrad S522, Renkforce E0001PA oder TX-EZ6, so stellen Sie das jeweilige Modell für die richtige Verarbeitung der Readings ein.
|
||||
<br>
|
||||
Protokoll 85 (SD_WS_85_THW) dekodiert zwei verschiedene Sensortypen: TFA 30.3222.02 (Thermo-Hygro-Wind) und 30.3251.10 (Wind).
|
||||
Damit auch die Windrichtung bei dem Sensor TFA 30.3251.10 angezeigt wird, muss das Attribut auf diesen Wert "TFA_30.3251.10" gesetzt werden.
|
||||
<a name="end_model"></a>
|
||||
</li><br>
|
||||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li><br>
|
||||
@ -1973,8 +2331,108 @@ sub SD_WS_WH2SHIFT {
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
<a name="SD_WS Set"></a>
|
||||
<b>Set</b><br><br>
|
||||
<ul>
|
||||
<li>replaceBatteryForSec<br>
|
||||
(Nur verfügbar bei Geräten, bei deren SIGNALduinos das Attribut "longids" aktiviert ist.)
|
||||
<br><br>
|
||||
<code>replaceBatteryForSec <Sekunden></code>
|
||||
<br><br>
|
||||
Versetzt das Gerät für <code><Sekunden></code> Sekunden in den Batteriewechselmodus.
|
||||
Die erste unbekannte Adresse mit gleichem Protokoll, die empfangen wird, ersetzt die aktuelle Geräteadresse.
|
||||
</li>
|
||||
</ul><br>
|
||||
</ul>
|
||||
|
||||
=end html_DE
|
||||
=for :application/json;q=META.json 14_SD_WS.pm
|
||||
{
|
||||
"abstract": "Supports various weather stations",
|
||||
"author": [
|
||||
"Sidey <>",
|
||||
"ralf9 <>"
|
||||
],
|
||||
"x_fhem_maintainer": [
|
||||
"Sidey"
|
||||
],
|
||||
"x_fhem_maintainer_github": [
|
||||
"Sidey79"
|
||||
],
|
||||
"description": "The SD_WS module processes the messages from various environmental sensors received from an IO device (CUL, CUN, SIGNALDuino, SignalESP etc.)",
|
||||
"dynamic_config": 1,
|
||||
"keywords": [
|
||||
"fhem-sonstige-systeme",
|
||||
"fhem-hausautomations-systeme",
|
||||
"fhem-mod",
|
||||
"signalduino",
|
||||
"weather",
|
||||
"station",
|
||||
"sensor",
|
||||
"Hama",
|
||||
"TFA",
|
||||
"Bresser"
|
||||
],
|
||||
"license": [
|
||||
"GPL_2"
|
||||
],
|
||||
"meta-spec": {
|
||||
"url": "https://metacpan.org/pod/CPAN::Meta::Spec",
|
||||
"version": 2
|
||||
},
|
||||
"name": "FHEM::SD_WS",
|
||||
"prereqs": {
|
||||
"runtime": {
|
||||
"requires": {
|
||||
"Carp": "0",
|
||||
"Digest:CRC": "0"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
"requires": {
|
||||
"Carp": "0",
|
||||
"Digest:CRC": "0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"release_status": "stable",
|
||||
"resources": {
|
||||
"bugtracker": {
|
||||
"web": "https://github.com/RFD-FHEM/RFFHEM/issues/"
|
||||
},
|
||||
"x_testData": [
|
||||
{
|
||||
"url": "https://raw.githubusercontent.com/RFD-FHEM/RFFHEM/master/t/FHEM/14_SD_WS/testData.json",
|
||||
"testname": "Testdata with SD_WS sensors"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"x_master": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/RFD-FHEM/RFFHEM.git",
|
||||
"web": "https://github.com/RFD-FHEM/RFFHEM/tree/master"
|
||||
},
|
||||
"type": "svn",
|
||||
"url": "https://svn.fhem.de/fhem",
|
||||
"web": "https://svn.fhem.de/trac/browser/trunk/fhem/FHEM/14_Hideki.pm",
|
||||
"x_branch": "trunk",
|
||||
"x_filepath": "fhem/FHEM/",
|
||||
"x_raw": "https://svn.fhem.de/trac/export/latest/trunk/fhem/FHEM/14_SD_WS.pm"
|
||||
},
|
||||
"x_support_community": {
|
||||
"board": "Sonstige Systeme",
|
||||
"boardId": "29",
|
||||
"cat": "FHEM - Hausautomations-Systeme",
|
||||
"description": "Sonstige Hausautomations-Systeme",
|
||||
"forum": "FHEM Forum",
|
||||
"rss": "https://forum.fhem.de/index.php?action=.xml;type=rss;board=29",
|
||||
"title": "FHEM Forum: Sonstige Systeme",
|
||||
"web": "https://forum.fhem.de/index.php/board,29.0.html"
|
||||
},
|
||||
"x_wiki": {
|
||||
"web": "https://wiki.fhem.de/wiki/SIGNALduino"
|
||||
}
|
||||
}
|
||||
}
|
||||
=end :application/json;q=META.json
|
||||
=cut
|
||||
|
Loading…
Reference in New Issue
Block a user