2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-30 05:57:08 +00:00

14_Hideki.pm: Fixed wind direction and output as floatingpoint values

git-svn-id: https://svn.fhem.de/fhem/trunk@26983 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
sidey79 2023-01-06 11:58:49 +00:00
parent 3f405f301d
commit f350fa902b
2 changed files with 157 additions and 38 deletions

View File

@ -1,5 +1,7 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it. # Do not insert empty lines here, update check depends on it.
- change: 14_Hideki.pm: output wind values always as floatingpoint
- bugix: 14_Hideki.pm: fixed wind direction
- feature: 14_SD_WS.pm: new sensor Bresser 7-in-1 Comfort Wetter Center - feature: 14_SD_WS.pm: new sensor Bresser 7-in-1 Comfort Wetter Center
new set command to allow battery replacement new set command to allow battery replacement
new sensor SM60020 multi purpose environment sensor new sensor SM60020 multi purpose environment sensor

View File

@ -15,6 +15,7 @@ package main;
use strict; use strict;
use warnings; use warnings;
use POSIX; use POSIX;
use FHEM::Meta;
#use Data::Dumper; #use Data::Dumper;
@ -37,6 +38,7 @@ Hideki_Initialize($)
$hash->{AutoCreate}= $hash->{AutoCreate}=
{ "Hideki.*" => { ATTR => "event-min-interval:.*:300 event-on-change-reading:.*", FILTER => "%NAME", GPLOT => "temp4hum4:Temp/Hum,", autocreateThreshold => "2:180"} }; { "Hideki.*" => { ATTR => "event-min-interval:.*:300 event-on-change-reading:.*", FILTER => "%NAME", GPLOT => "temp4hum4:Temp/Hum,", autocreateThreshold => "2:180"} };
return FHEM::Meta::InitMod( __FILE__, $hash );
} }
@ -79,9 +81,9 @@ Hideki_Parse($$)
my ($iohash,$msg) = @_; my ($iohash,$msg) = @_;
my (undef ,$rawData) = split("#",$msg); my (undef ,$rawData) = split("#",$msg);
my $name = $iohash->{NAME}; my $ioname = $iohash->{NAME};
my @a = split("", $msg); my @a = split("", $msg);
Log3 $iohash, 4, "$name Hideki_Parse: incomming $msg"; Log3 $iohash, 4, "$ioname Hideki_Parse: incomming $msg";
my @decodedData; my @decodedData;
my $crc1crc2OK = 0; my $crc1crc2OK = 0;
@ -93,16 +95,16 @@ Hideki_Parse($$)
# decrypt and decodedBytes are now done with decryptAndCheck # decrypt and decodedBytes are now done with decryptAndCheck
my $decodedString = join '', unpack('H*', pack('C*',@decodedData)); # get hex string my $decodedString = join '', unpack('H*', pack('C*',@decodedData)); # get hex string
Log3 $iohash, 4, "$name Hideki_Parse: raw=$rawData, decoded=$decodedString"; Log3 $iohash, 4, "$ioname Hideki_Parse: raw=$rawData, decoded=$decodedString";
if (!@decodedData) { if (!@decodedData) {
Log3 $iohash, 4, "$name Hideki_Parse: decrypt failed"; Log3 $iohash, 4, "$ioname Hideki_Parse: decrypt failed";
return ''; return '';
} }
Log3 $iohash, 5, "$name Hideki_Parse: getSensorType for ".$decodedData[3]; Log3 $iohash, 5, "$ioname Hideki_Parse: getSensorType for ".$decodedData[3];
my $sensorTyp=($decodedData[3] & 0x1F); my $sensorTyp=($decodedData[3] & 0x1F);
Log3 $iohash, 4, "$name Hideki_Parse: SensorTyp = $sensorTyp decodedString = $decodedString"; Log3 $iohash, 4, "$ioname Hideki_Parse: SensorTyp = $sensorTyp decodedString = $decodedString";
my $id=substr($decodedString,2,2); # get the random id from the data my $id=substr($decodedString,2,2); # get the random id from the data
my $channel=0; my $channel=0;
@ -136,75 +138,74 @@ Hideki_Parse($$)
elsif ($comfort == 2) { $comfort = 'Dry. Less than 40% RH' } elsif ($comfort == 2) { $comfort = 'Dry. Less than 40% RH' }
elsif ($comfort == 3) { $comfort = 'Temp. and Hum. comfortable' } elsif ($comfort == 3) { $comfort = 'Temp. and Hum. comfortable' }
$val = "T: $temp H: $hum"; $val = "T: $temp H: $hum";
Log3 $iohash, 4, "$name decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp, humidity=$hum, comfort=$comfort"; Log3 $iohash, 4, "$ioname decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp, humidity=$hum, comfort=$comfort";
}elsif($sensorTyp==31){ }elsif($sensorTyp==31){
($channel, $temp) = decodeThermo(\@decodedData); ($channel, $temp) = decodeThermo(\@decodedData);
$bat = ($decodedData[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery $bat = ($decodedData[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery
$count = $decodedData[3] >> 6; # verifiziert, MSG_Counter $count = $decodedData[3] >> 6; # verifiziert, MSG_Counter
$val = "T: $temp"; $val = "T: $temp";
Log3 $iohash, 4, "$name decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp"; Log3 $iohash, 4, "$ioname decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp";
}elsif($sensorTyp==14){ }elsif($sensorTyp==14){
($channel, $rain) = decodeRain(\@decodedData); # decodeThermoHygro($decodedString); ($channel, $rain) = decodeRain(\@decodedData); # decodeThermoHygro($decodedString);
$bat = ($decodedData[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery $bat = ($decodedData[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery
$count = $decodedData[3] >> 6; # UNVERIFIZIERT, MSG_Counter $count = $decodedData[3] >> 6; # UNVERIFIZIERT, MSG_Counter
$val = "R: $rain"; $val = "R: $rain";
Log3 $iohash, 4, "$name decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, rain=$rain, unknown=$unknown"; Log3 $iohash, 4, "$ioname decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, rain=$rain, unknown=$unknown";
}elsif($sensorTyp==12){ }elsif($sensorTyp==12){
($channel, $temp) = decodeThermo(\@decodedData); # decodeThermoHygro($decodedString); ($channel, $temp) = decodeThermo(\@decodedData); # decodeThermoHygro($decodedString);
($windchill,$windspeed,$windgust,$winddir,$winddirdeg,$winddirtext) = wind(\@decodedData); #($windchill,$windspeed,$windgust,$winddir,$winddirdeg,$winddirtext) = wind(\@decodedData); ## nach unten verschoben
$bat = ($decodedData[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery $bat = ($decodedData[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery
$count = $decodedData[3] >> 6; # UNVERIFIZIERT, MSG_Counter $count = $decodedData[3] >> 6; # UNVERIFIZIERT, MSG_Counter
$val = "T: $temp Ws: $windspeed Wg: $windgust Wd: $winddirtext"; #$val = "T: $temp Ws: $windspeed Wg: $windgust Wd: $winddirtext"; ## nach unten verschoben
Log3 $iohash, 4, "$name decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp, Wc=$windchill, Ws=$windspeed, Wg=$windgust, Wd=$winddir, WdDeg=$winddirdeg, Wdtxt=$winddirtext"; Log3 $iohash, 4, "$ioname decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp";
}elsif($sensorTyp==13){ }elsif($sensorTyp==13){
($channel, $temp) = decodeThermo(\@decodedData); # decodeThermoHygro($decodedString); ($channel, $temp) = decodeThermo(\@decodedData); # decodeThermoHygro($decodedString);
$bat = ($decodedData[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery $bat = ($decodedData[2] >> 6 == 3) ? 'ok' : 'low'; # decode battery
$count = $decodedData[3] >> 6; # UNVERIFIZIERT, MSG_Counter $count = $decodedData[3] >> 6; # UNVERIFIZIERT, MSG_Counter
$val = "T: $temp"; $val = "T: $temp";
Log3 $iohash, 4, "$name decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp"; Log3 $iohash, 4, "$ioname decoded Hideki protocol model=$model, sensor id=$id, channel=$channel, cnt=$count, bat=$bat, temp=$temp";
Log3 $iohash, 4, "$name Sensor Typ $sensorTyp currently not full supported, please report sensor information!"; Log3 $iohash, 4, "$ioname Sensor Typ $sensorTyp currently not full supported, please report sensor information!";
} }
else{ else{
Log3 $iohash, 4, "$name Sensor Typ $sensorTyp not supported, please report sensor information!"; Log3 $iohash, 4, "$ioname Sensor Typ $sensorTyp not supported, please report sensor information!";
return ""; return "";
} }
my $longids = AttrVal($iohash->{NAME},'longids',0); my $longids = AttrVal($iohash->{NAME},'longids',0);
if ( ($longids ne "0") && ($longids eq "1" || $longids eq "ALL" || (",$longids," =~ m/,$model,/))) if ( ($longids ne "0") && ($longids eq "1" || $longids eq "ALL" || (",$longids," =~ m/,$model,/)))
{ {
$deviceCode=$model . "_" . $id . "." . $channel; $deviceCode=$model . "_" . $id . "." . $channel;
Log3 $iohash,4, "$name Hideki_Parse: using longid: $longids model: $model"; Log3 $iohash,4, "$ioname Hideki_Parse: using longid: $longids model: $model";
} else { } else {
$deviceCode = $model . "_" . $channel; $deviceCode = $model . "_" . $channel;
} }
Log3 $iohash, 5, "$name Hideki_Parse deviceCode: $deviceCode"; Log3 $iohash, 5, "$ioname Hideki_Parse deviceCode: $deviceCode";
my $def = $modules{Hideki}{defptr}{$iohash->{NAME} . "." . $deviceCode}; my $def = $modules{Hideki}{defptr}{$iohash->{NAME} . "." . $deviceCode};
$def = $modules{Hideki}{defptr}{$deviceCode} if(!$def); $def = $modules{Hideki}{defptr}{$deviceCode} if(!$def);
if(!$def) { if(!$def) {
Log3 $iohash, 1, "$name Hideki: UNDEFINED sensor $deviceCode detected, code $msg"; Log3 $iohash, 1, "$ioname Hideki: UNDEFINED sensor $deviceCode detected, code $msg";
return "UNDEFINED $deviceCode Hideki $deviceCode"; return "UNDEFINED $deviceCode Hideki $deviceCode";
} }
my $hash = $def; my $hash = $def;
$name = $hash->{NAME}; my $name = $hash->{NAME};
return "" if(IsIgnored($name)); return "" if(IsIgnored($name));
#Log3 $name, 4, "Hideki: $name ($msg)"; #Log3 $name, 4, "Hideki: $name ($msg)";
my $WindSpeedCorr = AttrVal($name,"windSpeedCorr",0); if ($sensorTyp == 12) { # Wind
if ($WindSpeedCorr > 0 && $sensorTyp == 12) { ($windchill,$windspeed,$windgust,$winddir,$winddirdeg,$winddirtext) = wind($name, \@decodedData);
$windspeed = sprintf("%.2f", $windspeed * $WindSpeedCorr); $val = "T: $temp Ws: $windspeed Wg: $windgust Wd: $winddirtext";
$windgust = sprintf("%.2f", $windgust * $WindSpeedCorr); Log3 $name, 4, "$ioname $name Parse: model=12(wind), T: $temp, Wc=$windchill, Ws=$windspeed, Wg=$windgust, Wd=$winddir, WdDeg=$winddirdeg, Wdtxt=$winddirtext";
Log3 $name, 4, "$name Hideki_Parse: WindSpeedCorr=$WindSpeedCorr, WindSpeed=$windspeed, WindGust=$windgust";
} }
if (!defined(AttrVal($hash->{NAME},"event-min-interval",undef))) if (!defined(AttrVal($name,"event-min-interval",undef)))
{ {
my $minsecs = AttrVal($iohash->{NAME},'minsecs',0); my $minsecs = AttrVal($ioname,'minsecs',0);
if($hash->{lastReceive} && (time() - $hash->{lastReceive} < $minsecs)) { if($hash->{lastReceive} && (time() - $hash->{lastReceive} < $minsecs)) {
Log3 $iohash, 4, "$name Hideki_Parse: $deviceCode Dropped ($decodedString) due to short time. minsecs=$minsecs"; Log3 $name, 4, "$name Hideki_Parse: $deviceCode Dropped ($decodedString) due to short time. minsecs=$minsecs";
return ""; return "";
} }
} }
@ -399,7 +400,9 @@ sub decodeRain {
# P12#758BB244074007400F00001C6E7A01 # P12#758BB244074007400F00001C6E7A01
sub wind { sub wind {
my $name = shift;
my @Hidekibytes = @{$_[0]}; my @Hidekibytes = @{$_[0]};
my @wd=(0, 15, 13, 14, 9, 10, 12, 11, 1, 2, 4, 3, 8, 7, 5, 6);
my @winddir_name=("N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"); my @winddir_name=("N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW");
my $windspeed; my $windspeed;
my $windchill; my $windchill;
@ -416,7 +419,19 @@ sub wind {
$windchill = $windchill / 10; $windchill = $windchill / 10;
$windspeed = ($Hidekibytes[9] & 0x0f ) * 100 + ($Hidekibytes[8] >> 4) * 10 + ($Hidekibytes[8] & 0x0f); $windspeed = ($Hidekibytes[9] & 0x0f ) * 100 + ($Hidekibytes[8] >> 4) * 10 + ($Hidekibytes[8] & 0x0f);
$windgust = ($Hidekibytes[10] >> 4) * 100 + ($Hidekibytes[10] & 0x0f) * 10 + ($Hidekibytes[9] >> 4); $windgust = ($Hidekibytes[10] >> 4) * 100 + ($Hidekibytes[10] & 0x0f) * 10 + ($Hidekibytes[9] >> 4);
$winddir = ($Hidekibytes[11] >> 4); my $windSpeedCorr = AttrVal($name,'windSpeedCorr',1); ### -> hierher verschoben
if ($windSpeedCorr > 0) {
$windspeed = sprintf("%.2f", $windspeed * $windSpeedCorr);
$windgust = sprintf("%.2f", $windgust * $windSpeedCorr);
Log3 $name, 5, "$name Hideki_Parse: WindSpeedCorr factor=$windSpeedCorr";
}
$winddir = $wd[$Hidekibytes[11] >> 4];
my $windDirCorr = AttrVal($name,'windDirCorr',0);
if ($windDirCorr > 0) {
$winddir += $windDirCorr;
$winddir &= 15;
Log3 $name, 5, "$name Hideki_Parse: windDirCorr=$windDirCorr";
}
$winddirtext = $winddir_name[$winddir]; $winddirtext = $winddir_name[$winddir];
$winddirdeg = $winddir * 22.5; $winddirdeg = $winddir * 22.5;
@ -469,7 +484,7 @@ sub wind {
<li>battery & batteryState (ok or low)</li> <li>battery & batteryState (ok or low)</li>
<li>channel (The Channelnumber (number if)</li> <li>channel (The Channelnumber (number if)</li>
<li>humidity (0-100)</li> <li>humidity (0-100)</li>
<li>state (T:x H:y B:z)</li> <li>state (T:x.xx H:y B:z)</li>
<li>temperature (&deg;C)</li> <li>temperature (&deg;C)</li>
<br><i>- Hideki only -</i> <br><i>- Hideki only -</i>
<li>comfort_level (Status: Humidity OK... , Wet. More than 69% RH, Dry. Less than 40% RH, Temperature and humidity comfortable)</li> <li>comfort_level (Status: Humidity OK... , Wet. More than 69% RH, Dry. Less than 40% RH, Temperature and humidity comfortable)</li>
@ -491,8 +506,16 @@ sub wind {
<li><a href="#ignore">ignore</a></li> <li><a href="#ignore">ignore</a></li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li> <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
<li><a href="#showtime">showtime</a></li> <li><a href="#showtime">showtime</a></li>
<li><a name="windDirCorr"></a>windDirCorr<br>
correction value of your displayed wind direction deztimal degree value. The correction value is added to the measured direction in dgrees.<br>
Example value: 5<br>
Default value: 0<br>
</li>
<li><a name="windSpeedCorr"></a>windSpeedCorr<br> <li><a name="windSpeedCorr"></a>windSpeedCorr<br>
correction value of your displayed windSpeed </li> correction value of your displayed wind speed as floatingpoint value. The measured speed is multiplied with the specified value. The value 0 disables the feature.<br>
Example value: 1.25<br>
Default value: 1<br>
</li>
</ul> </ul>
<br> <br>
</ul> </ul>
@ -540,7 +563,7 @@ sub wind {
<li>battery & batteryState (ok oder low)</li> <li>battery & batteryState (ok oder low)</li>
<li>channel (Der Sensor Kanal)</li> <li>channel (Der Sensor Kanal)</li>
<li>humidity (0-100)</li> <li>humidity (0-100)</li>
<li>state (T:x H:y B:z)</li> <li>state (T:x.xx H:y B:z)</li>
<li>temperature (&deg;C)</li> <li>temperature (&deg;C)</li>
<br><i>- Hideki spezifisch -</i> <br><i>- Hideki spezifisch -</i>
@ -561,11 +584,105 @@ sub wind {
<li><a href="#ignore">ignore</a></li> <li><a href="#ignore">ignore</a></li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li> <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
<li><a href="#showtime">showtime</a></li> <li><a href="#showtime">showtime</a></li>
<li><a name="windDirCorr"></a>windDirCorr<br>
Korrekturwert Ihrer angezeigten Windrichtung in Grad. Der Korrekturwert wird zu dem gemessenen Grad Wert Addiert.<br>
Beispielwert: 5<br>
Standardwert: 0<br>
</li>
<li><a name="windSpeedCorr"></a>windSpeedCorr<br> <li><a name="windSpeedCorr"></a>windSpeedCorr<br>
Korrekturwert Ihrer angezeigten Windgeschwindigkeit</li> Korrekturwert Ihrer angezeigten Windgeschwindigkeit als Fließkommezahk. Die gemessene Geschwindigkeit wird mit dem angegeben Wert multiplizuert. Der Wert 0 deaktiviert die Funktion.<br>
Beispielwert: 1.25<br>
Standardwert: 1<br>
</li> <br>
</ul> </ul>
<br>
</ul> </ul>
=end html_DE =end html_DE
=for :application/json;q=META.json 14_Hideki.pm
{
"abstract": "Supports various rf sensors with hideki protocol",
"author": [
"Sidey <>",
"ralf9 <>"
],
"x_fhem_maintainer": [
"Sidey"
],
"x_fhem_maintainer_github": [
"Sidey79",
"HomeAutoUser",
"elektron-bbs"
],
"description": "The Hideki module is a module for decoding weather sensors, which use the hideki protocol. Known brands are Bresser, Cresta, TFA and Hama",
"dynamic_config": 1,
"keywords": [
"fhem-sonstige-systeme",
"fhem-hausautomations-systeme",
"fhem-mod",
"signalduino",
"Hideki",
"Hama",
"TFA",
"Bresser"
],
"license": [
"GPL_2"
],
"meta-spec": {
"url": "https://metacpan.org/pod/CPAN::Meta::Spec",
"version": 2
},
"name": "FHEM::Hideki",
"prereqs": {
"runtime": {
"requires": {
"POSIX": "0"
}
},
"develop": {
"requires": {
"POSIX": "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_Hideki/testData.json",
"testname": "Testdata with Hideki protocol 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_Hideki.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 =cut