LÖSUNG:Dekodieren Temperatur Feuchte T/H sensor von PEARL NC7427(NC7415) 433MHz

Begonnen von maxtox, 25 September 2016, 19:37:33

Vorheriges Thema - Nächstes Thema

FHEm2005

Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

Kornelius777

...mal vorsichtig nachfragen...
gibt es hier schon Neuigkeiten?
Kann ich irgendwie unterstützen?

Grüße!

Kornelius

FHEm2005

Hallo Jürgen,

ich verstehe leider nicht, worin die Schwierigkeit besteht das Gerät in das Modul einzuarbeiten. Die eigentliche Dekodierung ist klar, daran kann es also nicht liegen. Ich kann mich Kornelius nur anschließen: Wie kann ich Dich unterstützen?

Was habe ich?

Ich habe zwei dieser Geräte. Sie haben die (momentane) ID 58 ind 145. In der folgenden Definition werden die ankommenden Daten decodiert und als Readings (ID, temperature, humidity) angezeigt.
Zwei Readings (absFeuchte, dewpoint) werden automatisch zusätzlich hinzugefügt. Danach gehe ich hin und ordne die Daten, abhängig von der ID, den beiden Räumen Gästezimmer (rot) und Gästezimmer (blau) zu uns zeige diese sortierten Daten als Readings an. (siehe Bild). Im Bild sind gerade die Daten für die ID 58 neu angekommen.

Das ist nur eine Übergangslösung, weil eine Definition für zwei Devices zuständig ist. Es macht aber die Funktionsweise klar. Damit sind die Grundlagen für eine Programmierung IMHO auch gelegt. Wir sind also ziemlich weit.
Ziel ist es ja für jedes Gerät, abhängig von der ID, eine eigene Definition zu haben.

defmod Pearl_1 CUL_TCM97001 CUL_TCM97001_Unknown
attr Pearl_1 IODev nanoCUL
attr Pearl_1 group CUL_TCM97001
attr Pearl_1 ignore 0
attr Pearl_1 model Unknown
attr Pearl_1 room Klima
attr Pearl_1 userReadings stateHEX {my $s = (ReadingsVal($name,'state',''));;\
my @a = split(/\s+/,$s);;\
$s = $a[1];;\
return($s);;},\
\
ID {my $s = (ReadingsVal($name,'stateHEX',''));;\
my @a = split("",$s);;\
my $u="";;\
$u = ((hex($a[0].$a[1].$a[2])& 0x3FC) >> 2);;\
return($u);;},\
\
temperature {my $s = (ReadingsVal($name,'stateHEX',''));;\
my @a = split("",$s);;\
my $t= ((hex($a[3].$a[4])& 0x3C) >> 2);;\
$t += ((hex($a[4].$a[5])& 0x3C) >> 2) * 16;;\
$t += ((hex($a[5].$a[6])& 0x3C) >> 2) * 256;;\
$t = (($t-900)/10 - 32)*5/9;;\
$t = int(10 * $t + 0.5) / 10;;\
return($t);;},\
\
humidity {my $s = (ReadingsVal($name,'stateHEX',''));;\
my @a = split("",$s);;\
my $t= (hex($a[6].$a[7])& 0x3C) >> 2;;\
$t += ((hex($a[7].$a[8])& 0x3C) >> 2) * 16;;\
return($t);;},\
\
GzBName {my $n="Bastian (GzB)";;\
return($n);;},\
\
GzBtemperature {my $s = (ReadingsVal($name,'stateHEX',''));;\
my @a = split("",$s);;\
my $u="";;\
$u = (hex($a[0].$a[1].$a[2])& 0x3FC) >> 2;;\
if ($u == 145) {my $t = (ReadingsVal($name,'temperature',''));;\
return($t);;}\
return();;},\
\
GzBhumidity {if ((ReadingsVal($name,'ID','')) == 145) {my $s = (ReadingsVal($name,'stateHEX',''));;\
my @a = split("",$s);;\
my $t= (hex($a[6].$a[7])& 0x3C) >> 2;;\
$t += ((hex($a[7].$a[8])& 0x3C) >> 2) * 16;;\
return($t)};;\
return();;},\
\
GzBdewpoint {if ((ReadingsVal($name,'ID','')) == 145) {my $d = (ReadingsVal($name,'dewpoint',''));;\
return($d)};;\
return();;},\
\
GzBabsFeuchte {if ((ReadingsVal($name,'ID','')) == 145) {my $aF = (ReadingsVal($name,'absFeuchte',''));;\
return($aF)};;\
return();;},\
\
GzBlueften {my $aFMG = ReadingsVal("Prologue_144","absFeuchte","0");;\
my $aFGzB = ReadingsVal($name,"GzBabsFeuchte","0");;\
my $ lue = "";;\
if ($aFMG < $aFGzB){\
$lue = "ja"}\
else\
{$lue = "nein"};;\
return ($lue);;},\
\
GzBtime-stamp {if ((ReadingsVal($name,'ID','')) == 145) {my $t = substr(ReadingsTimestamp($name,'GzBhumidity',''),11,8);;\
return($t)};;\
return();;},\
\
GzRName {my $n="Carolin (GzR)";;\
return($n);;},\
\
GzRtemperature {my $s = (ReadingsVal($name,'stateHEX',''));;\
my @a = split("",$s);;\
my $u="";;\
$u = (hex($a[0].$a[1].$a[2])& 0x3FC) >> 2;;\
if ($u == 58) {my $t = (ReadingsVal($name,'temperature',''));;\
return($t)};;\
return();;},\
\
GzRhumidity {if ((ReadingsVal($name,'ID','')) == 58) {my $s = (ReadingsVal($name,'stateHEX',''));;\
my @a = split("",$s);;\
my $t= (hex($a[6].$a[7])& 0x3C) >> 2;;\
$t += ((hex($a[7].$a[8])& 0x3C) >> 2) * 16;;\
return($t)};;\
return();;},\
\
GzRdewpoint {if ((ReadingsVal($name,'ID','')) == 58) {my $d = (ReadingsVal($name,'dewpoint',''));;\
return($d)};;\
return();;},\
\
GzRabsFeuchte {if ((ReadingsVal($name,'ID','')) == 58) {my $aF = (ReadingsVal($name,'absFeuchte',''));;\
return($aF)};;\
return();;},\
\
GzRtime-stamp {if ((ReadingsVal($name,'ID','')) == 58) {my $t = substr(ReadingsTimestamp($name,'GzRhumidity',''),11,8);;\
return($t)};;\
return();;},\
\
GzRlueften {my $aFMG = ReadingsVal("Prologue_144","absFeuchte","0");;\
my $aFGzR = ReadingsVal($name,"GzRabsFeuchte","0");;\
my $ lue = "";;\
if ($aFMG < $aFGzR){\
$lue = "ja"}\
else\
{$lue = "nein"};;\
return ($lue)}


Damit habe ich hoffentlich eine Grundlage legen können; die Einarbeitung in das Modul überlasse ich Jürgen, weil dazu meine Kenntnisse leider nicht ausreichen.

Gruß Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

FHEm2005

@Kornelius
Wenn Du es ausprobieren möchtest, hier der Text den Du unter UserReadings eintragen musst:
stateHEX {my $s = (ReadingsVal($name,'state',''));
my @a = split(/\s+/,$s);
$s = $a[1];
return($s);},

ID {my $s = (ReadingsVal($name,'stateHEX',''));
my @a = split("",$s);
my $u="";
$u = ((hex($a[0].$a[1].$a[2])& 0x3FC) >> 2);
return($u);},

temperature {my $s = (ReadingsVal($name,'stateHEX',''));
my @a = split("",$s);
my $t= ((hex($a[3].$a[4])& 0x3C) >> 2);
$t += ((hex($a[4].$a[5])& 0x3C) >> 2) * 16;
$t += ((hex($a[5].$a[6])& 0x3C) >> 2) * 256;
$t = (($t-900)/10 - 32)*5/9;
$t = int(10 * $t + 0.5) / 10;
return($t);},

humidity {my $s = (ReadingsVal($name,'stateHEX',''));
my @a = split("",$s);
my $t= (hex($a[6].$a[7])& 0x3C) >> 2;
$t += ((hex($a[7].$a[8])& 0x3C) >> 2) * 16;
return($t);},

GzBName {my $n="Bastian (GzB)";
return($n);},

GzBtemperature {my $s = (ReadingsVal($name,'stateHEX',''));
my @a = split("",$s);
my $u="";
$u = (hex($a[0].$a[1].$a[2])& 0x3FC) >> 2;
if ($u == 145) {my $t = (ReadingsVal($name,'temperature',''));
return($t);}
return();},

GzBhumidity {if ((ReadingsVal($name,'ID','')) == 145) {my $s = (ReadingsVal($name,'stateHEX',''));
my @a = split("",$s);
my $t= (hex($a[6].$a[7])& 0x3C) >> 2;
$t += ((hex($a[7].$a[8])& 0x3C) >> 2) * 16;
return($t)};
return();},

GzBdewpoint {if ((ReadingsVal($name,'ID','')) == 145) {my $d = (ReadingsVal($name,'dewpoint',''));
return($d)};
return();},

GzBabsFeuchte {if ((ReadingsVal($name,'ID','')) == 145) {my $aF = (ReadingsVal($name,'absFeuchte',''));
return($aF)};
return();},

GzBlueften {my $aFMG = ReadingsVal("Prologue_144","absFeuchte","0");
my $aFGzB = ReadingsVal($name,"GzBabsFeuchte","0");
my $ lue = "";
if ($aFMG < $aFGzB){
$lue = "ja"}
else
{$lue = "nein"};
return ($lue);},

GzBtime-stamp {if ((ReadingsVal($name,'ID','')) == 145) {my $t = substr(ReadingsTimestamp($name,'GzBhumidity',''),11,8);
return($t)};
return();},

GzRName {my $n="Carolin (GzR)";
return($n);},

GzRtemperature {my $s = (ReadingsVal($name,'stateHEX',''));
my @a = split("",$s);
my $u="";
$u = (hex($a[0].$a[1].$a[2])& 0x3FC) >> 2;
if ($u == 58) {my $t = (ReadingsVal($name,'temperature',''));
return($t)};
return();},

GzRhumidity {if ((ReadingsVal($name,'ID','')) == 58) {my $s = (ReadingsVal($name,'stateHEX',''));
my @a = split("",$s);
my $t= (hex($a[6].$a[7])& 0x3C) >> 2;
$t += ((hex($a[7].$a[8])& 0x3C) >> 2) * 16;
return($t)};
return();},

GzRdewpoint {if ((ReadingsVal($name,'ID','')) == 58) {my $d = (ReadingsVal($name,'dewpoint',''));
return($d)};
return();},

GzRabsFeuchte {if ((ReadingsVal($name,'ID','')) == 58) {my $aF = (ReadingsVal($name,'absFeuchte',''));
return($aF)};
return();},

GzRtime-stamp {if ((ReadingsVal($name,'ID','')) == 58) {my $t = substr(ReadingsTimestamp($name,'GzRhumidity',''),11,8);
return($t)};
return();},

GzRlueften {my $aFMG = ReadingsVal("Prologue_144","absFeuchte","0");
my $aFGzR = ReadingsVal($name,"GzRabsFeuchte","0");
my $ lue = "";
if ($aFMG < $aFGzR){
$lue = "ja"}
else
{$lue = "nein"};
return ($lue)}


Aufpassen die Ziffern 145 und 58 müssen Deinen IDs entsprechen. Die findest Du ja nacheinander unter dem Reading ID.
Edit: Im Reading  GzB/GzRlueften kann es einen Fehler geben, weil es auf einen Außenluft-Sensor (Prologue_144) zugreift, der bei Dir nicht vorhanden ist.  Entweder anpassen oder Löschen.

Gruß Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

juergs

Hallo Eberhard,

Du bist mir zuvorgekommen.  ;) :)

Ich wollte ebenfals erst mal wieder den Status Quo beleuchten und mich dann über das lange WoE dranmachen.
Noch unreflektiert sehe ich im Moment noch folgende ToDos:

1.) ich bevorzugte den Einsatz eines Transmitters der die Validierung des Telegramms übernimmt und nur gültige Telegramme in ein CUL_TX-Format wandelt.
Nachteil: die Unknown Messages-Infos tauchen zusätzlich noch im fhem-log auf und man benötigt eine Art "SignalDuino" als zusätzliches Zwischenglied.
2.) Die Lösung von Eberhard in fhem als Perl-Modul.

Also bitte noch etwas Geduld, bis ich wieder alles aufgebaut und mich eingearbeitet habe.

Aber immernoch Zweifel:
Trotz günstigen Preises des Sensors: Ein LaCrosse-Sensor kostet ca. 15€ sendet über die LGW ohne Probleme im 868MHz Band.
Der Sensor "PEARL NC7427" müllt das ISM-Band mit vielen Repetitions und viel zu kurzen Abständen zu.
Bei mehreren Sensoren verschlimmert sich das Ganze noch erheblich, insbesondere wenn man viele 433MHz Sensoren im Einsatz hat....
... und da kommt die Implementierung des CRCs ins Spiel und ist bei meiner Infrastruktur erforderlich, da viele Telegramme sich überlagern.
Nur mal so 'ne Überlegung...  ???

Grüße,
Jürgen

FHEm2005

Hallo Jürgen,

ich bevorzuge:
Zitat2.) Die Lösung von Eberhard in fhem als Perl-Modul.
;D
Ich verstehe die Problematik bzgl. des Zumüllens des ISM-Bandes. Wenn ich noch zusätzlich einen Signalduino einsetzen muss, der wiederum Geld kostet, sollte ich mich besser mit dem Kauf eines LaCrosse-Sensors anfreunden. Ich glaube wir sollten uns hier auf eine "Quick and Dirty" Lösung einstellen und die Nachteile in allerDeutlichkeit noch einmal herausheben. Ein ganzes Haus mit solchen Sensoren auszustatten ist sicher nicht Sinn der Sache.
ZitatBei mehreren Sensoren verschlimmert sich das Ganze noch erheblich, insbesondere wenn man viele 433MHz Sensoren im Einsatz hat....
... und da kommt die Implementierung des CRCs ins Spiel und ist bei meiner Infrastruktur erforderlich, da viele Telegramme sich überlagern.
Ich habe nicht den ganzen Thread im Kopf, aber irgendwie meine ich wäre das Problem CRC auch gelöst. Ich mach' mich mal auf die Suche...

Gruß Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

FHEm2005

Hallo Jürgen,

gesucht - gefunden. In den Beiträgen von #68 bis #85 ist eine Lösung für das Theme CRC vorgestellt. In 85 habe ich die bis dahin vorhandenen Erkenntnisse der CRC/Prüfsummenbildung versucht in einem Pearl-Code abzubilden. Mit Sicherheit ebenfalls eine gute Basis für Deine Arbeit.

Viele Grüße
Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

juergs

Zitat von: FHEm2005 am 30 Oktober 2018, 11:08:09
Hallo Jürgen,

gesucht - gefunden. In den Beiträgen von #68 bis #85 ist eine Lösung für das Theme CRC vorgestellt. In 85 habe ich die bis dahin vorhandenen Erkenntnisse der CRC/Prüfsummenbildung versucht in einem Pearl-Code abzubilden. Mit Sicherheit ebenfalls eine gute Basis für Deine Arbeit.

Viele Grüße
Eberhard

Hallo Eberhard,
ja, die meinte ich, mit einer Umsetzung auf C.
Da sind noch ein paar Umsetzungsfragen offen, z.B. welcher Anteil des Telegramms über die CRC-Berechnung gehen muß.

Ich melde mich wieder.  8)

Jürgen


FHEm2005

Hallo Jürgen,
Zitatz.B. welcher Anteil des Telegramms über die CRC-Berechnung gehen muß.
Da die Bildung der Prüfsumme bereits als Programm vorliegt, steht darin auch der Bereich:
Speichert man das Reading state binär in stateBIN  und dann das Ganze in einem Array  $a[n], gehen die Nutzdaten von n=2 bis n=37. 

Weitere Fragen?  :D :D
Gruß Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

Kornelius777

@FHEm2005:

Danke, sehr cool!
Ich habe hier (im Büro) gerade nur mein Handy dabei. Dennoch: Nachdem ich Deinen Code (stumpf) per Copy/Paste eingefügt habe (und die ID ersetzt), sehe ich zumindest schon einmal ein paar sehr brauchbare Readings. Ein guter Start!

@juergs:

Toll, dass es weitergeht!
Wenn Du Unterstützung brauchst (z.B. beim Testen, ...) helfe ich gerne!

Grüße in die Runde!

Kornelius

FHEm2005

Hallo Jürgen,

Zitatja, die meinte ich, mit einer Umsetzung auf C.
Das verstehe ich nicht: Meine Codeschnipsel bezüglich der CRC/Prüfziffer sind doch in Perl geschrieben und das Modul ebenfalls. Wieso eine Umsetzung in C??

Gruß
Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

juergs

Zitat von: FHEm2005 am 30 Oktober 2018, 11:53:30
Hallo Jürgen,
Das verstehe ich nicht: Meine Codeschnipsel bezüglich der CRC/Prüfziffer sind doch in Perl geschrieben und das Modul ebenfalls. Wieso eine Umsetzung in C??

Gruß
Eberhard

Ist ein Mißverständnis. Kann mich erst ab Do. darum kümmern.  8)


FHEm2005

Hallo Jürgen,

ZitatVielleicht passt es als Basis?
Das kann ich nicht beurteilen. Ich verstehe zu wenig von Perl, um die dort verwendete Logik erfassen zu können. Das ist umso schwerer, je besser die Programmierer sind. Ob ein neues Modul Sinn macht, musst Du entscheiden. Bei der Sache bin ich raus.

Viele Grüße
Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM