00_SIGNALduino.pm:
Added Version 3.3.0 with new Firwmware and new / updated logical modules: 14_Hideki.pm (updated) 14_SD_WS.pm (new) 14_SD_WS07.pm (updated) 14_SD_WS09.pm (updated) 14_SD_WS_Maverick.pm (new) 98_Dooya.pm (new) git-svn-id: https://svn.fhem.de/fhem/trunk@12233 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -89,7 +89,7 @@ Hideki_Parse($$)
|
||||
if (!@decodedBytes)
|
||||
{
|
||||
Log3 $iohash, 4, "$name decrypt failed";
|
||||
return undef;
|
||||
return '';
|
||||
}
|
||||
|
||||
my $sensorTyp=getSensorType($decodedBytes[3]);
|
||||
@@ -98,7 +98,7 @@ Hideki_Parse($$)
|
||||
if (!Hideki_crc(\@decodedBytes))
|
||||
{
|
||||
Log3 $iohash, 4, "$name crc failed";
|
||||
return undef;
|
||||
return '';
|
||||
}
|
||||
|
||||
my $id=substr($decodedString,2,2); # get the random id from the data
|
||||
@@ -351,6 +351,8 @@ Hideki_Attr(@)
|
||||
1;
|
||||
|
||||
=pod
|
||||
=item summary Supports various rf sensors with hideki protocol
|
||||
=item summary_DE Unterstützt verschiedenen Funksensoren mit hideki Protokol
|
||||
=begin html
|
||||
|
||||
<a name="Hideki"></a>
|
||||
@@ -446,7 +448,7 @@ Hideki_Attr(@)
|
||||
<code> besteht aus dem Sensortyp und der Kanalnummer (1..5) oder wenn das Attribut longid im IO Device gesetzt ist aus einer Zufallsadresse, die durch den Sensor beim einlegen der
|
||||
Batterie generiert wird (Die Adresse aendert sich bei jedem Batteriewechsel).<br>
|
||||
</li>
|
||||
<li>Wenn autocreate aktiv ist, dann wird der Sensor automatisch in FHEM angelegt. Das ist der empfohlene Weg, neue Sensoren hinzuzufuegen.</li>
|
||||
<li>Wenn autocreate aktiv ist, dann wird der Sensor automatisch in FHEM angelegt. Das ist der empfohlene Weg, neue Sensoren hinzuzufügen.</li>
|
||||
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
395
fhem/FHEM/14_SD_WS.pm
Normal file
395
fhem/FHEM/14_SD_WS.pm
Normal file
@@ -0,0 +1,395 @@
|
||||
##############################################
|
||||
# $Id$
|
||||
#
|
||||
# The purpose of this module is to support serval
|
||||
# weather sensors which use various protocol
|
||||
# Sidey79 & Ralf9 2016
|
||||
#
|
||||
|
||||
package main;
|
||||
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
#use Data::Dumper;
|
||||
|
||||
|
||||
sub SD_WS_Initialize($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{Match} = '^[W]\d+#.*';
|
||||
$hash->{DefFn} = "SD_WS_Define";
|
||||
$hash->{UndefFn} = "SD_WS_Undef";
|
||||
$hash->{ParseFn} = "SD_WS_Parse";
|
||||
$hash->{AttrFn} = "SD_WS_Attr";
|
||||
$hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 showtime:1,0 " .
|
||||
"$readingFnAttributes ";
|
||||
$hash->{AutoCreate} =
|
||||
{
|
||||
"SD_WS37_TH.*" => { ATTR => "event-min-interval:.*:300 event-on-change-reading:.*", FILTER => "%NAME", GPLOT => "temp4hum4:Temp/Hum,", autocreateThreshold => "2:180"},
|
||||
"SD_WS50_SM.*" => { ATTR => "event-min-interval:.*:300 event-on-change-reading:.*", FILTER => "%NAME", GPLOT => "temp4hum4:Temp/Hum,", autocreateThreshold => "2:180"}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#############################
|
||||
sub SD_WS_Define($$)
|
||||
{
|
||||
my ($hash, $def) = @_;
|
||||
my @a = split("[ \t][ \t]*", $def);
|
||||
|
||||
return "wrong syntax: define <name> SD_WS <code> ".int(@a) if(int(@a) < 3 );
|
||||
|
||||
$hash->{CODE} = $a[2];
|
||||
$hash->{lastMSG} = "";
|
||||
$hash->{bitMSG} = "";
|
||||
|
||||
$modules{SD_WS}{defptr}{$a[2]} = $hash;
|
||||
$hash->{STATE} = "Defined";
|
||||
|
||||
my $name= $hash->{NAME};
|
||||
return undef;
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub SD_WS_Undef($$)
|
||||
{
|
||||
my ($hash, $name) = @_;
|
||||
delete($modules{SD_WS}{defptr}{$hash->{CODE}})
|
||||
if(defined($hash->{CODE}) && defined($modules{SD_WS}{defptr}{$hash->{CODE}}));
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
###################################
|
||||
sub SD_WS_Parse($$)
|
||||
{
|
||||
my ($iohash, $msg) = @_;
|
||||
#my $rawData = substr($msg, 2);
|
||||
my $name = $iohash->{NAME};
|
||||
my ($protocol,$rawData) = split("#",$msg);
|
||||
$protocol=~ s/^[WP](\d+)/$1/; # extract protocol
|
||||
|
||||
|
||||
|
||||
my $dummyreturnvalue= "Unknown, please report";
|
||||
my $hlen = length($rawData);
|
||||
my $blen = $hlen * 4;
|
||||
my $bitData = unpack("B$blen", pack("H$hlen", $rawData));
|
||||
my $bitData2;
|
||||
|
||||
my $model; # wenn im elsif Abschnitt definiert, dann wird der Sensor per AutoCreate angelegt
|
||||
my $SensorTyp;
|
||||
my $id;
|
||||
my $bat;
|
||||
my $channel;
|
||||
my $rawTemp;
|
||||
my $temp;
|
||||
my $hum;
|
||||
my $trend;
|
||||
|
||||
my %decodingSubs = (
|
||||
50 => # Protocol 50
|
||||
# FF550545FF9E
|
||||
# FF550541FF9A
|
||||
# AABCDDEEFFGG
|
||||
# A = Preamble, always FF
|
||||
# B = TX type, always 5
|
||||
# C = Address (5/6/7) > low 2 bits = 1/2/3
|
||||
# D = Soil moisture 05%
|
||||
# E = temperature
|
||||
# F = security code, always F
|
||||
# G = Checksum 55+05+45+FF=19E CRC value = 9E
|
||||
{ # subs to decode this
|
||||
sensortype => 'XT300',
|
||||
model => 'SD_WS_50_SM',
|
||||
prematch => sub {my $msg = shift; return 1 if ($msg =~ /^FF5[0-9A-F]{5}FF[0-9A-F]{2}/); }, # prematch
|
||||
crcok => sub {my $msg = shift; return 1 if ((hex(substr($msg,2,2))+hex(substr($msg,4,2))+hex(substr($msg,6,2))+hex(substr($msg,8,2))&0xFF) == (hex(substr($msg,10,2))) ); }, # crc
|
||||
id => sub {my $msg = shift; return (hex(substr($msg,2,2)) &0x03 ); }, #id
|
||||
#temp => sub {my $msg = shift; return (sprintf('%x',((hex(substr($msg,6,2)) <<4)/2/10))); }, #temp
|
||||
#temphex => sub {my $msg = shift; return sprintf("%04X",((hex(substr($msg,6,2)))<<4)/2); }, #temp
|
||||
temp => sub {my $msg = shift; return ((hex(substr($msg,6,2)))-40) }, #temp
|
||||
#hum => sub {my $msg = shift; return (printf('%02x',hex(substr($msg,4,2)))); }, #hum
|
||||
hum => sub {my $msg = shift; return hex(substr($msg,4,2)); }, #hum
|
||||
channel => sub {my (undef,$bitData) = @_; return ( SD_WS_binaryToNumber($bitData,12,15)&0x03 ); }, #channel
|
||||
},
|
||||
33 =>
|
||||
{
|
||||
sensortype => 's014/TFA 30.3200/TCM/Conrad',
|
||||
model => 'SD_WS_33_TH',
|
||||
prematch => sub {my $msg = shift; return 1 if ($msg =~ /^[0-9A-F]{10,11}/); }, # prematch
|
||||
crcok => sub {return SD_WS_binaryToNumber($bitData,36,39); }, # crc
|
||||
id => sub {my (undef,$bitData) = @_; return SD_WS_binaryToNumber($bitData,0,9); }, # id
|
||||
# sendmode => sub {my (undef,$bitData) = @_; return SD_WS_binaryToNumber($bitData,10,11) eq "1" ? "manual" : "auto"; }
|
||||
temp => sub {my (undef,$bitData) = @_; return (((SD_WS_binaryToNumber($bitData,22,25)*256 + SD_WS_binaryToNumber($bitData,18,21)*16 + SD_WS_binaryToNumber($bitData,14,17)) *10 -12200) /18)/10; }, #temp
|
||||
hum => sub {my (undef,$bitData) = @_; return (SD_WS_binaryToNumber($bitData,30,33)*16 + SD_WS_binaryToNumber($bitData,26,29)); }, #hum
|
||||
channel => sub {my (undef,$bitData) = @_; return (SD_WS_binaryToNumber($bitData,12,13)+1 ); }, #channel
|
||||
bat => sub {my (undef,$bitData) = @_; return (SD_WS_binaryToNumber($bitData,34) eq "1" ? "ok" : "critical");},
|
||||
# sync => sub {my (undef,$bitData) = @_; return (SD_WS_binaryToNumber($bitData,35,35) eq "1" ? "true" : "false");},
|
||||
}
|
||||
|
||||
|
||||
);
|
||||
|
||||
|
||||
Log3 $name, 4, "SD_WS_Parse: Protocol: $protocol, rawData: $rawData";
|
||||
|
||||
if ($protocol == "37") # Bresser 7009994
|
||||
{
|
||||
# 0 7 8 9 10 12 22 25 31
|
||||
# 01011010 0 0 01 01100001110 10 0111101 11001010
|
||||
# ID B? T Kan Temp ?? Hum Pruefsumme?
|
||||
|
||||
# MU;P0=729;P1=-736;P2=483;P3=-251;P4=238;P5=-491;D=010101012323452323454523454545234523234545234523232345454545232345454545452323232345232340;CP=4;
|
||||
|
||||
$model = "SD_WS37_TH";
|
||||
$SensorTyp = "Bresser 7009994";
|
||||
|
||||
$id = SD_WS_binaryToNumber($bitData,0,7);
|
||||
#$bat = int(substr($bitData,8,1)) eq "1" ? "ok" : "low";
|
||||
$channel = SD_WS_binaryToNumber($bitData,10,11);
|
||||
$rawTemp = SD_WS_binaryToNumber($bitData,12,22);
|
||||
$hum = SD_WS_binaryToNumber($bitData,25,31);
|
||||
|
||||
$id = sprintf('%02X', $id); # wandeln nach hex
|
||||
$temp = ($rawTemp - 609.93) / 9.014;
|
||||
$temp = sprintf("%.1f", $temp);
|
||||
|
||||
if ($hum < 10 || $hum > 99 || $temp < -30 || $temp > 70) {
|
||||
return "";
|
||||
}
|
||||
|
||||
$bitData2 = substr($bitData,0,8) . ' ' . substr($bitData,8,4) . ' ' . substr($bitData,12,11);
|
||||
$bitData2 = $bitData2 . ' ' . substr($bitData,23,2) . ' ' . substr($bitData,25,7) . ' ' . substr($bitData,32,8);
|
||||
Log3 $iohash, 4, "$name converted to bits: " . $bitData2;
|
||||
Log3 $iohash, 4, "$name decoded protocolid: $protocol ($SensorTyp) sensor id=$id, channel=$channel, rawTemp=$rawTemp, temp=$temp, hum=$hum";
|
||||
}
|
||||
elsif ($protocol != "37" && defined($decodingSubs{$protocol})) # alles was nicht Protokoll #37 ist, durch den hash decodieren
|
||||
{
|
||||
|
||||
$SensorTyp=$decodingSubs{$protocol}{sensortype};
|
||||
|
||||
return "Prematch Error" && Log3 $iohash, 4, "$name decoded protocolid: $protocol ($SensorTyp) prematch error" if (!$decodingSubs{$protocol}{prematch}->( $rawData ));
|
||||
return "crc Error" && Log3 $iohash, 4, "$name decoded protocolid: $protocol ($SensorTyp) crc error" if (!$decodingSubs{$protocol}{crcok}->( $rawData ));
|
||||
|
||||
$id=$decodingSubs{$protocol}{id}->( $rawData,$bitData );
|
||||
#my $temphex=$decodingSubs{$protocol}{temphex}->( $rawData,$bitData );
|
||||
|
||||
$temp=$decodingSubs{$protocol}{temp}->( $rawData,$bitData );
|
||||
$hum=$decodingSubs{$protocol}{hum}->( $rawData,$bitData );
|
||||
$channel=$decodingSubs{$protocol}{channel}->( $rawData,$bitData );
|
||||
$model = $decodingSubs{$protocol}{model};
|
||||
$bat = $decodingSubs{$protocol}{bat};
|
||||
|
||||
Log3 $iohash, 4, "$name decoded protocolid: $protocol ($SensorTyp) sensor id=$id, channel=$channel, temp=$temp, hum=$hum";
|
||||
|
||||
}
|
||||
else {
|
||||
Log3 $iohash, 4, "SD_WS_Parse_unknown: converted to bits: $bitData";
|
||||
return $dummyreturnvalue;
|
||||
}
|
||||
|
||||
|
||||
if (!defined($model)) {
|
||||
return $dummyreturnvalue;
|
||||
}
|
||||
|
||||
my $deviceCode;
|
||||
|
||||
my $longids = AttrVal($iohash->{NAME},'longids',0);
|
||||
if (($longids ne "0") && ($longids eq "1" || $longids eq "ALL" || (",$longids," =~ m/,$model,/)))
|
||||
{
|
||||
$deviceCode = $model . '_' . $id . $channel;
|
||||
Log3 $iohash,4, "$name using longid: $longids model: $model";
|
||||
} else {
|
||||
$deviceCode = $model . "_" . $channel;
|
||||
}
|
||||
|
||||
#print Dumper($modules{SD_WS}{defptr});
|
||||
|
||||
my $def = $modules{SD_WS}{defptr}{$iohash->{NAME} . "." . $deviceCode};
|
||||
$def = $modules{SD_WS}{defptr}{$deviceCode} if(!$def);
|
||||
|
||||
if(!$def) {
|
||||
Log3 $iohash, 1, 'SD_WS: UNDEFINED sensor ' . $model . ' detected, code ' . $deviceCode;
|
||||
return "UNDEFINED $deviceCode SD_WS $deviceCode";
|
||||
}
|
||||
#Log3 $iohash, 3, 'SD_WS: ' . $def->{NAME} . ' ' . $id;
|
||||
|
||||
my $hash = $def;
|
||||
$name = $hash->{NAME};
|
||||
Log3 $name, 4, "SD_WS: $name ($rawData)";
|
||||
|
||||
if (!defined(AttrVal($hash->{NAME},"event-min-interval",undef)))
|
||||
{
|
||||
my $minsecs = AttrVal($iohash->{NAME},'minsecs',0);
|
||||
if($hash->{lastReceive} && (time() - $hash->{lastReceive} < $minsecs)) {
|
||||
Log3 $hash, 4, "$deviceCode Dropped due to short time. minsecs=$minsecs";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
$hash->{lastReceive} = time();
|
||||
$hash->{lastMSG} = $rawData;
|
||||
if (defined($bitData2)) {
|
||||
$hash->{bitMSG} = $bitData2;
|
||||
} else {
|
||||
$hash->{bitMSG} = $bitData;
|
||||
}
|
||||
|
||||
my $state = "T: $temp" . ($hum > 0 ? " H: $hum":"");
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
readingsBulkUpdate($hash, "state", $state);
|
||||
readingsBulkUpdate($hash, "temperature", $temp) if (defined($temp));
|
||||
readingsBulkUpdate($hash, "humidity", $hum) if (defined($hum) && $hum > 0);
|
||||
readingsBulkUpdate($hash, "battery", $bat) if (defined($bat));
|
||||
readingsBulkUpdate($hash, "channel", $channel) if (defined($channel));
|
||||
readingsBulkUpdate($hash, "trend", $trend) if (defined($trend));
|
||||
|
||||
readingsEndUpdate($hash, 1); # Notify is done by Dispatch
|
||||
|
||||
return $name;
|
||||
|
||||
}
|
||||
|
||||
sub SD_WS_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_WS}{defptr}{$cde});
|
||||
$modules{SD_WS}{defptr}{$iohash->{NAME} . "." . $cde} = $hash;
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
sub SD_WS_binaryToNumber
|
||||
{
|
||||
my $binstr=shift;
|
||||
my $fbit=shift;
|
||||
my $lbit=$fbit;
|
||||
$lbit=shift if @_;
|
||||
|
||||
return oct("0b".substr($binstr,$fbit,($lbit-$fbit)+1));
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
=item summary Supports various weather stations
|
||||
=item summary_DE Unterstützt verschiedene Funk Wetterstationen
|
||||
=begin html
|
||||
|
||||
<a name="SD_WS"></a>
|
||||
<h3>Weather Sensors various protocols</h3>
|
||||
<ul>
|
||||
The SD_WS module interprets temperature sensor messages received by a Device like CUL, CUN, SIGNALduino etc.<br>
|
||||
<br>
|
||||
<b>Known models:</b>
|
||||
<ul>
|
||||
<li>Bresser 7009994</li>
|
||||
<li>Opus XT300</li>
|
||||
</ul>
|
||||
<br>
|
||||
New received device are add in fhem with autocreate.
|
||||
<br><br>
|
||||
|
||||
<a name="SD_WS_Define"></a>
|
||||
<b>Define</b>
|
||||
<ul>The received devices created automatically.<br>
|
||||
The ID of the defice is the cannel or, if the longid attribute is specified, it is a combination of channel and some random generated bits at powering the sensor and the channel.<br>
|
||||
If you want to use more sensors, than channels available, you can use the longid option to differentiate them.
|
||||
</ul>
|
||||
<br>
|
||||
<a name="SD_WS 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:)</li>
|
||||
<li>temperature (°C)</li>
|
||||
<li>humidity: (The humidity (1-100 if available)</li>
|
||||
<li>battery: (low or ok)</li>
|
||||
<li>channel: (The Channelnumber (number if)</li>
|
||||
</ul>
|
||||
<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>
|
||||
</ul>
|
||||
|
||||
<a name="SD_WS_Set"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
|
||||
<a name="SD_WS_Parse"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
|
||||
</ul>
|
||||
|
||||
=end html
|
||||
|
||||
=begin html_DE
|
||||
|
||||
<a name="SD_WS"></a>
|
||||
<h3>SD_WS</h3>
|
||||
<ul>
|
||||
Das SD_WS Modul verarbeitet von einem IO Gerät (CUL, CUN, SIGNALDuino, etc.) empfangene Nachrichten von Temperatur-Sensoren.<br>
|
||||
<br>
|
||||
<b>Unterstützte Modelle:</b>
|
||||
<ul>
|
||||
<li>Bresser 7009994</li>
|
||||
<li>Opus XT300</li>
|
||||
|
||||
</ul>
|
||||
<br>
|
||||
Neu empfangene Sensoren werden in FHEM per autocreate angelegt.
|
||||
<br><br>
|
||||
|
||||
<a name="SD_WS_Define"></a>
|
||||
<b>Define</b>
|
||||
<ul>Die empfangenen Sensoren werden automatisch angelegt.<br>
|
||||
Die ID der angelgten Sensoren ist entweder der Kanal des Sensors, oder wenn das Attribut longid gesetzt ist, dann wird die ID aus dem Kanal und einer Reihe von Bits erzeugt, welche der Sensor beim Einschalten zufällig vergibt.<br>
|
||||
</ul>
|
||||
<br>
|
||||
<a name="SD_WS Events"></a>
|
||||
<b>Generierte Readings:</b>
|
||||
<ul>
|
||||
<li>State (T: H:)</li>
|
||||
<li>temperature (°C)</li>
|
||||
<li>humidity: (Luftfeuchte (1-100)</li>
|
||||
<li>battery: (low oder ok)</li>
|
||||
<li>channel: (Der Sensor Kanal)</li>
|
||||
</ul>
|
||||
<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>
|
||||
</ul>
|
||||
|
||||
<a name="SD_WS_Set"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
|
||||
<a name="SD_WS_Parse"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
|
||||
</ul>
|
||||
|
||||
=end html_DE
|
||||
=cut
|
||||
@@ -115,11 +115,11 @@ SD_WS07_Parse($$)
|
||||
}
|
||||
|
||||
if ($hum > 100) {
|
||||
return undef; # Eigentlich muesste sowas wie ein skip rein, damit ggf. spaeter noch weitre Sensoren dekodiert werden koennen.
|
||||
return ''; # Eigentlich muesste sowas wie ein skip rein, damit ggf. spaeter noch weitre Sensoren dekodiert werden koennen.
|
||||
}
|
||||
|
||||
if ($temp > 700 && $temp < 3840) {
|
||||
return undef;
|
||||
return '';
|
||||
} elsif ($temp >= 3840) { # negative Temperaturen, muss noch ueberprueft und optimiert werden
|
||||
$temp -= 4095;
|
||||
}
|
||||
@@ -201,6 +201,8 @@ sub SD_WS07_Attr(@)
|
||||
|
||||
|
||||
=pod
|
||||
=item summary Supports weather sensors protocl 7 from SIGNALduino
|
||||
=item summary_DE Unterstützt Wettersensoren mit Protokol 7 vom SIGNALduino
|
||||
=begin html
|
||||
|
||||
<a name="SD_WS07"></a>
|
||||
@@ -261,7 +263,7 @@ sub SD_WS07_Attr(@)
|
||||
<ul>
|
||||
Das SD_WS07 Module verarbeitet von einem IO Geraet (CUL, CUN, SIGNALDuino, etc.) empfangene Nachrichten von Temperatur-Sensoren.<br>
|
||||
<br>
|
||||
<b>Unterstuetze Modelle:</b>
|
||||
<b>Unterstützte Modelle:</b>
|
||||
<ul>
|
||||
<li>Eurochon EAS800z</li>
|
||||
<li>Technoline WS6750/TX70DTH</li>
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Digest::CRC qw(crc);
|
||||
|
||||
#use Math::Round qw/nearest/;
|
||||
|
||||
sub SD_WS09_Initialize($)
|
||||
@@ -25,7 +27,7 @@
|
||||
."windKorrektur:-3,-2,-1,0,1,2,3 "
|
||||
."$readingFnAttributes ";
|
||||
$hash->{AutoCreate} =
|
||||
{ "SD_WS09.*" => { ATTR => "event-min-interval:.*:300 event-on-change-reading:.* windKorrektur:.*:0", FILTER => "%NAME", GPLOT => "temp4hum4:Temp/Hum,", autocreateThreshold => "2:180"} };
|
||||
{ "SD_WS09.*" => { ATTR => "event-min-interval:.*:300 event-on-change-reading:.* windKorrektur:.*:0 " , FILTER => "%NAME", GPLOT => "temp4hum4:Temp/Hum,", autocreateThreshold => "2:180"} };
|
||||
|
||||
|
||||
}
|
||||
@@ -71,9 +73,12 @@
|
||||
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 $modelattr ;
|
||||
my $modelid;
|
||||
my $windSpeed = 0;
|
||||
my $windguest =0;
|
||||
@@ -86,23 +91,79 @@
|
||||
my $windDirectionText;
|
||||
|
||||
|
||||
Log3 $name, 4, "SD_WS09_Parse HEX=$msg length: $hlen";
|
||||
my $syncpos= index($bitData,"11111110"); #7x1 1x0 preamble
|
||||
$modelattr = AttrVal($iohash->{NAME},'WS09_WSModel',0);
|
||||
if ($modelattr eq '0'){
|
||||
$modelattr = "undef";
|
||||
}
|
||||
|
||||
Log3 $iohash, 3, "SD_WS09_Parse Bin=$bitData syncp=$syncpos length:".length($bitData) ;
|
||||
my $crcwh1080 = AttrVal($iohash->{NAME},'WS09_CRCAUS',0);
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse CRC_AUS:$crcwh1080 Model=$modelattr" ;
|
||||
|
||||
my $syncpos= index($bitData,"11111110"); #7x1 1x0 preamble
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse0 Bin=$bitData syncp=$syncpos length:".length($bitData) ;
|
||||
|
||||
if ($syncpos ==-1 || length($bitData)-$syncpos < 78)
|
||||
{
|
||||
Log3 $iohash, 3, "EXIT SD_WS09_Parse msg=$rawData syncp=$syncpos length:".length($bitData) ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse EXIT: msg=$rawData syncp=$syncpos length:".length($bitData) ;
|
||||
return undef;
|
||||
}
|
||||
|
||||
my $wh = substr($bitData,0,8);
|
||||
if($wh == "11111111") {
|
||||
#CRC-Check bei WH1080/WS0101 WS09_CRCAUS=0 und WS09_WSModel = undef oder Wh1080
|
||||
if(($crcwh1080 == 0) && ($modelattr ne "CTW600")) {
|
||||
if($wh == "11111111") {
|
||||
if ($syncpos == 0)
|
||||
{
|
||||
$hlen = length($rawData);
|
||||
$blen = $hlen * 4;
|
||||
$bitData2 = '11'.unpack("B$blen", pack("H$hlen", $rawData));
|
||||
$bitData20 = substr($bitData2,0,length($bitData2)-2);
|
||||
$blen = length($bitData20);
|
||||
$hlen = $blen / 4;
|
||||
$msg = 'P9#'.unpack("H$hlen", pack("B$blen", $bitData20));
|
||||
$bitData = $bitData20;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse sync1 msg=$msg syncp=$syncpos length:".length($bitData) ;
|
||||
}
|
||||
|
||||
if ($syncpos == 1)
|
||||
{
|
||||
$hlen = length($rawData);
|
||||
$blen = $hlen * 4;
|
||||
$bitData2 = '1'.unpack("B$blen", pack("H$hlen", $rawData));
|
||||
$bitData20 = substr($bitData2,0,length($bitData2)-1);
|
||||
$blen = length($bitData20);
|
||||
$hlen = $blen / 4;
|
||||
$msg = 'P9#'.unpack("H$hlen", pack("B$blen", $bitData20));
|
||||
$bitData = $bitData20;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse sync2 msg=$msg syncp=$syncpos length:".length($bitData) ;
|
||||
}
|
||||
|
||||
|
||||
my $datacheck = pack( 'H*', substr($msg,5,length($msg)-5) );
|
||||
my $crcmein = Digest::CRC->new(width => 8, poly => 0x31);
|
||||
my $rr2 = $crcmein->add($datacheck)->hexdigest;
|
||||
if ($rr2 eq "0"){
|
||||
$model = "WH1080";
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse CRC_OK: CRC=$rr2 Model=$model attr=$modelattr" ;
|
||||
}else{
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse CRC_Error: msg=$msg CRC=$rr2 " ;
|
||||
return undef;
|
||||
}
|
||||
}else{
|
||||
$model = "CTW600";
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse CTW600: Model=$model attr=$modelattr" ;
|
||||
}
|
||||
};
|
||||
|
||||
if( ($wh == "11111111") || ($model eq "WH1080")) {
|
||||
if ($modelattr eq "CTW600"){
|
||||
Log3 $iohash, 3, "$name: SD_WS09_WH1080 off=$modelattr Model=$model " ;
|
||||
return undef;
|
||||
}
|
||||
$sensdata = substr($bitData,8);
|
||||
my $whid = substr($sensdata,0,4);
|
||||
if( $whid == "1010" ){ # A
|
||||
Log3 $iohash, 3, "WH SD_WS09_Parse WH=$wh msg=$sensdata syncp=$syncpos length:".length($sensdata) ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse WH=$wh msg=$sensdata syncp=$syncpos 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
|
||||
@@ -111,11 +172,11 @@
|
||||
$windDirection = SD_WS09_bin2dec(substr($sensdata,68,4));
|
||||
$windDirectionText = $winddir_name[$windDirection];
|
||||
$windSpeed = round((SD_WS09_bin2dec(substr($sensdata,32,8))* 34)/100,01);
|
||||
Log3 $iohash, 3, "SD_WS09_Parse ".$model." Windspeed bit: ".substr($sensdata,32,8)." Dec: " . $windSpeed ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse ".$model." Windspeed bit: ".substr($sensdata,32,8)." Dec: " . $windSpeed ;
|
||||
$windguest = round((SD_WS09_bin2dec(substr($sensdata,40,8)) * 34)/100,01);
|
||||
Log3 $iohash, 3, "SD_WS09_Parse ".$model." Windguest bit: ".substr($sensdata,40,8)." Dec: " . $windguest ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse ".$model." Windguest bit: ".substr($sensdata,40,8)." Dec: " . $windguest ;
|
||||
$rain = SD_WS09_bin2dec(substr($sensdata,56,8)) * 0.3;
|
||||
Log3 $iohash, 3, "SD_WS09_Parse ".$model." Rain bit: ".substr($sensdata,56,8)." Dec: " . $rain ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse ".$model." Rain bit: ".substr($sensdata,56,8)." Dec: " . $rain ;
|
||||
} else {
|
||||
if( $whid == "1011" ){ # B DCF-77 Zeitmeldungen vom Sensor
|
||||
my $hrs1 = substr($sensdata,16,8);
|
||||
@@ -125,57 +186,70 @@
|
||||
my $mday;
|
||||
my $month;
|
||||
my $year;
|
||||
Log3 $iohash, 3, "Zeitmeldung SD_WS09_Parse HRS1=$hrs1" ;
|
||||
# $hrs = SD_WS09_BCD2bin(substr($sensdata,16,8) & 0x3F) ; #h
|
||||
$id = SD_WS09_bin2dec(substr($sensdata,4,8));
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse Zeitmeldung0: HRS1=$hrs1 id:$id" ;
|
||||
$hrs = SD_WS09_BCD2bin(substr($sensdata,18,6) ) ; # Stunde
|
||||
$mins = SD_WS09_BCD2bin(substr($sensdata,24,8)); # Minute
|
||||
$sec = SD_WS09_BCD2bin(substr($sensdata,32,8)); # Sekunde
|
||||
#day month year
|
||||
$year = SD_WS09_BCD2bin(substr($sensdata,40,8)); # Jahr
|
||||
#$month = SD_WS09_BCD2bin(substr($sensdata,48,8) & 0x1f); #d
|
||||
$month = SD_WS09_BCD2bin(substr($sensdata,51,5)); # Monat
|
||||
$mday = SD_WS09_BCD2bin(substr($sensdata,56,8)); # Tag
|
||||
Log3 $iohash, 3, "Zeitmeldung SD_WS09_Parse msg=$rawData syncp=$syncpos length:".length($bitData) ;
|
||||
Log3 $iohash, 3, "Zeitmeldung SD_WS09_Parse HH:mm:ss - ".$hrs.":".$mins.":".$sec ;
|
||||
Log3 $iohash, 3, "Zeitmeldung SD_WS09_Parse dd:mm:yy - ".$mday.":".$month.":".$year ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse Zeitmeldung1: msg=$rawData syncp=$syncpos length:".length($bitData) ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse Zeitmeldung2: HH:mm:ss - ".$hrs.":".$mins.":".$sec ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse Zeitmeldung3: dd.mm.yy - ".$mday.":".$month.":".$year ;
|
||||
return $name;
|
||||
}
|
||||
Log3 $iohash, 3, "Zeitmeldung SD_WS09_Parse msg=$rawData syncp=$syncpos length:".length($sensdata) ;
|
||||
return undef;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse Zeitmeldung4: msg=$rawData syncp=$syncpos length:".length($sensdata) ;
|
||||
return undef;
|
||||
}
|
||||
}else{
|
||||
if ($modelattr eq "WH1080"){
|
||||
Log3 $iohash, 3, "$name: SD_WS09_CTW600 off=$modelattr Model=$model " ;
|
||||
return undef;
|
||||
} else {
|
||||
# eine CTW600 wurde erkannt
|
||||
$sensdata = substr($bitData,$syncpos+8);
|
||||
Log3 $iohash, 3, "WH_2 SD_WS09_Parse WH=$wh msg=$sensdata syncp=$syncpos length:".length($sensdata) ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse CTW WH=$wh msg=$sensdata syncp=$syncpos length:".length($sensdata) ;
|
||||
$model = "CTW600";
|
||||
my $nn1 = substr($sensdata,10,2); # Keine Bedeutung
|
||||
my $nn2 = substr($sensdata,62,4); # Keine Bedeutung
|
||||
$modelid = substr($sensdata,0,4);
|
||||
Log3 $iohash, 3, "SD_WS09_Parse Id: ".$modelid." Bin-Sync=$sensdata syncp=$syncpos length:".length($sensdata) ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse Id: ".$modelid." NN1:$nn1 NN2:$nn2" ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse 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));
|
||||
$hum = SD_WS09_bin2dec(substr($sensdata,22,8));
|
||||
$windDirection = SD_WS09_bin2dec(substr($sensdata,66,4));
|
||||
$windDirectionText = $winddir_name[$windDirection];
|
||||
$windSpeed = round(SD_WS09_bin2dec(substr($sensdata,30,16))/240,01);
|
||||
Log3 $iohash, 3, "SD_WS09_Parse ".$model." Windspeed bit: ".substr($sensdata,32,8)." Dec: " . $windSpeed ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse ".$model." Windspeed bit: ".substr($sensdata,32,8)." Dec: " . $windSpeed ;
|
||||
$windguest = round((SD_WS09_bin2dec(substr($sensdata,40,8)) * 34)/100,01);
|
||||
Log3 $iohash, 3, "SD_WS09_Parse ".$model." Windguest bit: ".substr($sensdata,40,8)." Dec: " . $windguest ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse ".$model." Windguest bit: ".substr($sensdata,40,8)." Dec: " . $windguest ;
|
||||
$rain = round(SD_WS09_bin2dec(substr($sensdata,46,16)) * 0.3,01);
|
||||
Log3 $iohash, 3, "SD_WS09_Parse ".$model." Rain bit: ".substr($sensdata,46,16)." Dec: " . $rain ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse ".$model." Rain bit: ".substr($sensdata,46,16)." Dec: " . $rain ;
|
||||
}
|
||||
}
|
||||
|
||||
Log3 $iohash, 3, "SD_WS09_Parse ".$model." id:$id :$sensdata ";
|
||||
Log3 $iohash, 3, "SD_WS09_Parse ".$model." id:$id, bat:$bat, temp=$temp, hum=$hum, winddir=$windDirection:$windDirectionText wS=$windSpeed, wG=$windguest, rain=$rain";
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse ".$model." id:$id :$sensdata ";
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse ".$model." id:$id, bat:$bat, temp=$temp, hum=$hum, winddir=$windDirection:$windDirectionText wS=$windSpeed, wG=$windguest, rain=$rain";
|
||||
|
||||
if($hum > 100 || $hum < 0) {
|
||||
Log3 $iohash, 3, "Hum SD_WS09_Parse hum=$hum msg=$rawData " ;
|
||||
Log3 $iohash, 3, "$name: SD_WS09_Parse HUM: hum=$hum msg=$rawData " ;
|
||||
return undef;
|
||||
}
|
||||
if($temp > 60 || $temp < -40) {
|
||||
Log3 $iohash, 3, "$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 using longid: $longids model: $model";
|
||||
Log3 $iohash,4, "$name: SD_WS09_Parse using longid: $longids model: $model";
|
||||
} else {
|
||||
$deviceCode = $model;
|
||||
}
|
||||
@@ -184,14 +258,15 @@
|
||||
$def = $modules{SD_WS09}{defptr}{$deviceCode} if(!$def);
|
||||
|
||||
if(!$def) {
|
||||
Log3 $iohash, 1, 'SD_WS09: UNDEFINED sensor ' . $model . ' detected, code ' . $deviceCode;
|
||||
Log3 $iohash, 1, 'SD_WS09_Parse UNDEFINED sensor ' . $model . ' detected, code ' . $deviceCode;
|
||||
return "UNDEFINED $deviceCode SD_WS09 $deviceCode";
|
||||
}
|
||||
|
||||
my $hash = $def;
|
||||
my $hash = $def;
|
||||
$name = $hash->{NAME};
|
||||
Log3 $name, 4, "SD_WS09_Parse: $name ($rawData)";
|
||||
|
||||
|
||||
my $windkorr = AttrVal($hash->{NAME},'windKorrektur',0);
|
||||
if ($windkorr != 0 )
|
||||
{
|
||||
@@ -205,17 +280,14 @@
|
||||
{
|
||||
my $minsecs = AttrVal($iohash->{NAME},'minsecs',0);
|
||||
if($hash->{lastReceive} && (time() - $hash->{lastReceive} < $minsecs)) {
|
||||
Log3 $hash, 4, "$deviceCode Dropped due to short time. minsecs=$minsecs";
|
||||
Log3 $hash, 4, "SD_WS09_Parse $deviceCode Dropped due to short time. minsecs=$minsecs";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$def->{lastMSG} = $rawData;
|
||||
#$def->{bitMSG} = $bitData2;
|
||||
|
||||
my $state = "T: $temp ". ($hum>0 ? " H: $hum ":" ")." Ws: $windSpeed "." Wg: $windguest "." Wd: $windDirectionText "." R: $rain";
|
||||
# my $state = "T: $temp". ($hum>0 ? " H: $hum":"");
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
readingsBulkUpdate($hash, "state", $state);
|
||||
@@ -228,7 +300,8 @@
|
||||
readingsBulkUpdate($hash, "rain", $rain );
|
||||
readingsBulkUpdate($hash, "windGust", $windguest );
|
||||
readingsBulkUpdate($hash, "windSpeed", $windSpeed );
|
||||
readingsBulkUpdate($hash, "windDirectionDegree", $windDirection );
|
||||
readingsBulkUpdate($hash, "windDirection", $windDirection );
|
||||
readingsBulkUpdate($hash, "windDirectionDegree", $windDirection * 360 / 16);
|
||||
readingsBulkUpdate($hash, "windDirectionText", $windDirectionText );
|
||||
readingsEndUpdate($hash, 1); # Notify is done by Dispatch
|
||||
|
||||
@@ -272,11 +345,13 @@
|
||||
return $flip;
|
||||
}
|
||||
|
||||
sub SD_WS09_BCD2bin($) {
|
||||
my $BCD = shift;
|
||||
return (10 * ($BCD >> 4 & 0xF) + ($BCD & 0xF));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -284,12 +359,18 @@
|
||||
|
||||
|
||||
=pod
|
||||
=item summary Supports weather sensors protocl 9 from SIGNALduino
|
||||
=item summary_DE Unterstützt Wettersensoren mit 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>
|
||||
Requires Perl-Modul Digest::CRC. <br>
|
||||
<br>
|
||||
cpan install Digest::CRC or sudo apt-get install libdigest-crc-perl <br>
|
||||
<br>
|
||||
<br>
|
||||
<b>Known models:</b>
|
||||
<ul>
|
||||
@@ -328,10 +409,9 @@
|
||||
<li><a href="#ignore">ignore</a></li>
|
||||
<li><a href="#showtime">showtime</a></li>
|
||||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
||||
<li>model<br>
|
||||
<li>Model<br>
|
||||
WH1080, CTW600
|
||||
</li><br>
|
||||
|
||||
<li>windKorrektur<br>
|
||||
-3,-2,-1,0,1,2,3
|
||||
</li><br>
|
||||
@@ -353,6 +433,12 @@
|
||||
<ul>
|
||||
Das SD_WS09 Module verarbeitet von einem IO Gerät (CUL, CUN, SIGNALDuino, etc.) empfangene Nachrichten von Temperatur-Sensoren.<br>
|
||||
<br>
|
||||
Perl-Modul Digest::CRC erforderlich. <br>
|
||||
<br>
|
||||
cpan install Digest::CRC oder auch <br>
|
||||
sudo apt-get install libdigest-crc-perl <br>
|
||||
<br>
|
||||
<br>
|
||||
<b>Unterstütze Modelle:</b>
|
||||
<ul>
|
||||
<li>WS-0101 --> Model: WH1080</li>
|
||||
@@ -367,8 +453,8 @@
|
||||
<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>
|
||||
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 Events"></a>
|
||||
@@ -389,10 +475,9 @@
|
||||
<li><a href="#ignore">ignore</a></li>
|
||||
<li><a href="#showtime">showtime</a></li>
|
||||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
||||
<li>model<br>
|
||||
<li>Model<br>
|
||||
WH1080, CTW600
|
||||
</li><br>
|
||||
|
||||
<li>windKorrektur<br>
|
||||
Korrigiert die Nord-Ausrichtung des Windrichtungsmessers, wenn dieser nicht richtig nach Norden ausgerichtet ist.
|
||||
-3,-2,-1,0,1,2,3
|
||||
|
||||
298
fhem/FHEM/14_SD_WS_Maverick.pm
Normal file
298
fhem/FHEM/14_SD_WS_Maverick.pm
Normal file
@@ -0,0 +1,298 @@
|
||||
##############################################
|
||||
# $Id$
|
||||
#
|
||||
# The purpose of this module is to support Maverick sensors
|
||||
# Sidey79 & Cruizer 2016
|
||||
#
|
||||
|
||||
package main;
|
||||
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
#use Data::Dumper;
|
||||
|
||||
|
||||
sub
|
||||
SD_WS_Maverick_Initialize($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{Match} = "^P47#AA9995[A-Fa-f0-9]+";
|
||||
$hash->{DefFn} = "SD_WS_Maverick_Define";
|
||||
$hash->{UndefFn} = "SD_WS_Maverick_Undef";
|
||||
$hash->{ParseFn} = "SD_WS_Maverick_Parse";
|
||||
$hash->{AttrFn} = "SD_WS_Maverick_Attr";
|
||||
$hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 showtime:1,0 " .
|
||||
"$readingFnAttributes ";
|
||||
$hash->{AutoCreate} =
|
||||
{ "SD_WS_Maverick.*" => { ATTR => "event-min-interval:.*:300 event-on-change-reading:.*", FILTER => "%NAME", autocreateThreshold => "2:180"} };
|
||||
## Todo: Pruefen der Autocreate Einstellungen
|
||||
|
||||
}
|
||||
|
||||
#############################
|
||||
sub
|
||||
SD_WS_Maverick_Define($$)
|
||||
{
|
||||
my ($hash, $def) = @_;
|
||||
my @a = split("[ \t][ \t]*", $def);
|
||||
|
||||
return "wrong syntax: define <name> SD_WS_Maverick <model> ".int(@a)
|
||||
if(int(@a) < 3 );
|
||||
|
||||
$hash->{CODE} = $a[2];
|
||||
$hash->{lastMSG} = "";
|
||||
# $hash->{bitMSG} = "";
|
||||
|
||||
$modules{SD_WS_Maverick}{defptr}{$a[2]} = $hash;
|
||||
$hash->{STATE} = "Defined";
|
||||
|
||||
my $name= $hash->{NAME};
|
||||
return undef;
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub
|
||||
SD_WS_Maverick_Undef($$)
|
||||
{
|
||||
my ($hash, $name) = @_;
|
||||
delete($modules{SD_WS_Maverick}{defptr}{$hash->{CODE}})
|
||||
if(defined($hash->{CODE}) &&
|
||||
defined($modules{SD_WS_Maverick}{defptr}{$hash->{CODE}}));
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
###################################
|
||||
sub
|
||||
SD_WS_Maverick_Parse($$)
|
||||
{
|
||||
my ($iohash, $msg) = @_;
|
||||
#my $rawData = substr($msg, 2);
|
||||
my $name = $iohash->{NAME};
|
||||
my (undef ,$rawData) = split("#",$msg);
|
||||
#$protocol=~ s/^P(\d+)/$1/; # extract protocol
|
||||
|
||||
my $model = "SD_WS_Maverick";
|
||||
my $hlen = length($rawData);
|
||||
#my $blen = $hlen * 4;
|
||||
#my $bitData = unpack("B$blen", pack("H$hlen", $rawData));
|
||||
|
||||
Log3 $name, 3, "SD_WS_Maverick_Parse $model ($msg) length: $hlen";
|
||||
|
||||
#1 8 13 18 26
|
||||
#AA999559 55555 95999 A9A9A669 Sensor 1 =21 2Grad
|
||||
#AA999559 95996 55555 95A65565 Sensor 2 =22 2Grad
|
||||
#
|
||||
#Header Sen1 Sens2
|
||||
#my $hashumidity = FALSE;
|
||||
|
||||
## Todo: Change decoding per model into a foreach
|
||||
#foreach $key (keys %models) {
|
||||
# ....
|
||||
#}
|
||||
|
||||
#
|
||||
my $startup = substr($rawData,6,2);
|
||||
my $temp_str1 = substr($rawData,8,5);
|
||||
my $temp_str2 = substr($rawData,13,5);
|
||||
my $unknown = substr($rawData,18);
|
||||
|
||||
Log3 $iohash, 4, "$model decoded protocolid: 47 sensor startup=$startup, temp1=$temp_str1, temp2=$temp_str2, unknown=$unknown";
|
||||
|
||||
# Convert
|
||||
$temp_str1 =~ tr/569A/0123/;
|
||||
$temp_str2 =~ tr/569A/0123/;
|
||||
|
||||
# Calculate temp from data
|
||||
my $c;
|
||||
my $temp1=-532;
|
||||
for ( my $i = 0; $i < length($temp_str1); $i++ ) {
|
||||
$c = substr( $temp_str1, $i, 1);
|
||||
$temp1 += $c*4**(4-$i);
|
||||
}
|
||||
|
||||
my $temp2=-532;
|
||||
for ( my $i = 0; $i < length($temp_str2); $i++ ) {
|
||||
$c = substr( $temp_str2, $i, 1);
|
||||
$temp2 += $c*4**(4-$i);
|
||||
}
|
||||
|
||||
|
||||
Log3 $iohash, 4, "$model decoded protocolid: temp1=$temp1, temp2=$temp2;";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#print Dumper($modules{SD_WS_Maverick}{defptr});
|
||||
|
||||
my $def = $modules{SD_WS_Maverick}{defptr}{$iohash->{NAME} };
|
||||
$def = $modules{SD_WS_Maverick}{defptr}{$model} if(!$def);
|
||||
|
||||
if(!$def) {
|
||||
Log3 $iohash, 1, 'SD_WS_Maverick: UNDEFINED sensor ' . $model;
|
||||
return "UNDEFINED $model SD_WS_Maverick $model";
|
||||
}
|
||||
#Log3 $iohash, 3, 'SD_WS_Maverick: ' . $def->{NAME} . ' ' . $id;
|
||||
|
||||
my $hash = $def;
|
||||
$name = $hash->{NAME};
|
||||
Log3 $name, 4, "SD_WS_Maverick: $name ($rawData)";
|
||||
|
||||
if (!defined(AttrVal($hash->{NAME},"event-min-interval",undef)))
|
||||
{
|
||||
my $minsecs = AttrVal($iohash->{NAME},'minsecs',0);
|
||||
if($hash->{lastReceive} && (time() - $hash->{lastReceive} < $minsecs)) {
|
||||
Log3 $hash, 4, "$model Dropped due to short time. minsecs=$minsecs";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
$hash->{lastReceive} = time();
|
||||
$hash->{lastMSG} = $rawData;
|
||||
#$hash->{bitMSG} = $bitData2;
|
||||
|
||||
my $state = "T: $temp1"." T2: $temp2" ;
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
readingsBulkUpdate($hash, "state", $state);
|
||||
readingsBulkUpdate($hash, "messageType", $startup);
|
||||
|
||||
readingsBulkUpdate($hash, "temp1", $temp1) if ($temp1 ne"");
|
||||
readingsBulkUpdate($hash, "temp2", $temp2) if ($temp2 ne"");
|
||||
|
||||
readingsEndUpdate($hash, 1); # Notify is done by Dispatch
|
||||
|
||||
return $name;
|
||||
|
||||
}
|
||||
|
||||
sub SD_WS_Maverick_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_WS_Maverick}{defptr}{$cde});
|
||||
$modules{SD_WS_Maverick}{defptr}{$iohash->{NAME} . "." . $cde} = $hash;
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
|
||||
=pod
|
||||
=item summary Supports maverick temperature sensors protocl 47 from SIGNALduino
|
||||
=item summary_DE Unterstützt Maverick Temperatursensoren mit Protokol 47 vom SIGNALduino
|
||||
=begin html
|
||||
|
||||
<a name="SD_WS_Maverick"></a>
|
||||
<h3>Wether Sensors protocol #7</h3>
|
||||
<ul>
|
||||
The SD_WS_Maverick module interprets temperature sensor messages received by a Device like CUL, CUN, SIGNALduino etc.<br>
|
||||
<br>
|
||||
<b>Known models:</b>
|
||||
<ul>
|
||||
<li>Eurochon EAS800z</li>
|
||||
<li>Technoline WS6750/TX70DTH</li>
|
||||
</ul>
|
||||
<br>
|
||||
New received device are add in fhem with autocreate.
|
||||
<br><br>
|
||||
|
||||
<a name="SD_WS_Maverick_Define"></a>
|
||||
<b>Define</b>
|
||||
<ul>The received devices created automatically.<br>
|
||||
The ID of the defice is the cannel or, if the longid attribute is specified, it is a combination of channel and some random generated bits at powering the sensor and the channel.<br>
|
||||
If you want to use more sensors, than channels available, you can use the longid option to differentiate them.
|
||||
</ul>
|
||||
<br>
|
||||
<a name="SD_WS_Maverick 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:)</li>
|
||||
<li>temperature (°C)</li>
|
||||
<li>humidity: (The humidity (1-100 if available)</li>
|
||||
<li>battery: (low or ok)</li>
|
||||
<li>channel: (The Channelnumber (number if)</li>
|
||||
</ul>
|
||||
<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="#model">model</a> ()</li>
|
||||
<li><a href="#showtime">showtime</a></li>
|
||||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
||||
</ul>
|
||||
|
||||
<a name="SD_WS_Maverick_Set"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
|
||||
<a name="SD_WS_Maverick_Parse"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
|
||||
</ul>
|
||||
|
||||
=end html
|
||||
|
||||
=begin html_DE
|
||||
|
||||
<a name="SD_WS_Maverick"></a>
|
||||
<h3>SD_WS_Maverick</h3>
|
||||
<ul>
|
||||
Das SD_WS_Maverick Module verarbeitet von einem IO Geraet (CUL, CUN, SIGNALDuino, etc.) empfangene Nachrichten von Temperatur-Sensoren.<br>
|
||||
<br>
|
||||
<b>Unterstützte Modelle:</b>
|
||||
<ul>
|
||||
<li>Maverick</li>
|
||||
</ul>
|
||||
<br>
|
||||
Neu empfangene Sensoren werden in FHEM per autocreate angelegt.
|
||||
<br><br>
|
||||
|
||||
<a name="SD_WS_Maverick_Define"></a>
|
||||
<b>Define</b>
|
||||
<ul>Die empfangenen Sensoren werden automatisch angelegt.<br>
|
||||
Die ID der angelegten Sensoren ist entweder der Kanal des Sensors, oder wenn das Attribut longid gesetzt ist, dann wird die ID aus dem Kanal und einer Reihe von Bits erzeugt, welche der Sensor beim Einschalten zufällig vergibt.<br>
|
||||
</ul>
|
||||
<br>
|
||||
<a name="SD_WS_Maverick Events"></a>
|
||||
<b>Generierte Readings:</b>
|
||||
<ul>
|
||||
<li>State (T: H:)</li>
|
||||
<li>temperature (°C)</li>
|
||||
<li>humidity: (Luftfeuchte (1-100)</li>
|
||||
<li>battery: (low oder ok)</li>
|
||||
<li>channel: (Der Sensor Kanal)</li>
|
||||
</ul>
|
||||
<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="#model">model</a> ()</li>
|
||||
<li><a href="#showtime">showtime</a></li>
|
||||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
||||
</ul>
|
||||
|
||||
<a name="SD_WS_Maverick1_Set"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
|
||||
<a name="SD_WS_Maverick_Parse"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
|
||||
</ul>
|
||||
|
||||
=end html_DE
|
||||
=cut
|
||||
@@ -382,6 +382,8 @@ SIGNALduino_un_binflip($)
|
||||
1;
|
||||
|
||||
=pod
|
||||
=item summary Helper module for SIGNALduino
|
||||
=item summary_DE Unterstützungsmodul für SIGNALduino
|
||||
=begin html
|
||||
|
||||
<a name="SIGNALduino_un"></a>
|
||||
@@ -426,7 +428,7 @@ SIGNALduino_un_binflip($)
|
||||
<h3>SIGNALduino_un</h3>
|
||||
<ul>
|
||||
Das SIGNALduino_un module ist ein Hilfsmodul um unbekannte Nachrichten debuggen und analysieren zu koennen.
|
||||
Das Modul legt keinerlei Geraete oder aehnliches an.
|
||||
Das Modul legt keinerlei Geräte oder ähnliches an.
|
||||
<br><br>
|
||||
|
||||
<a name="SIGNALduino_undefine"></a>
|
||||
@@ -437,7 +439,7 @@ SIGNALduino_un_binflip($)
|
||||
Es ist moeglich ein Geraet manuell zu definieren, aber damit passiert ueberhaupt nichts.
|
||||
Autocreate wird auch keinerlei Geraete aus diesem Modul anlegen.
|
||||
<br>
|
||||
Die einzgeste Funktion dieses Modules ist, ab Verbose 4 Logmeldungen ueber die Empfangene Nachricht ins Log zu schreiben. Dabei kann man sich leider nicht darauf verlassen, dass die Nachricht korrekt dekodiert wurde.<br>
|
||||
Die einzgeste Funktion dieses Modules ist, ab Verbose 4 Logmeldungen über die Empfangene Nachricht ins Log zu schreiben. Dabei kann man sich leider nicht darauf verlassen, dass die Nachricht korrekt dekodiert wurde.<br>
|
||||
Dieses Modul wird alle Nachrichten verarbeiten, welche von anderen Modulen nicht verarbeitet wurden.
|
||||
<a name="SIGNALduino_unset"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
|
||||
1251
fhem/FHEM/98_Dooya.pm
Normal file
1251
fhem/FHEM/98_Dooya.pm
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user