iCelsius WLAN-Thermometer

Begonnen von Icinger, 06 Januar 2016, 12:37:10

Vorheriges Thema - Nächstes Thema

Icinger

Hi Leute,

habe jetzt verspätet noch ein nettes Weihnachtsgeschenk bekommen :)

Ein iCelsius-Grillthermometer.

Dieses sendet in mein hauseigenes WLAN mittels UPD-Broadcast seine Daten.

Hier mal vorläufig immer das aktuelle Modul dazu.
Dieses Modul hat aktuell 2 Möglichkeiten, die Daten an FHEM zu übergeben:
1) Direkt als einstufiges Modell
2) Die Temp des ersten Sensors wird als Oregon-Sensor dispatched. (als Vorbereitung auf das geplante BBQ-Modul)

Define:
define iCelsius iCelsius

Nach dem define läuft das Modul erstmal einstufig.
Durch ein
attr iCelsius emulate_THR 1
lässt es sich auf das zweistufige Model umschalten.

lg, Stefan

Update:
Neu:
set iCelsius Sampling <wert>
Damit kann das Sampling-Intervall in Sekundenschritten gesetzt werden.
Minimum 5 Sekunden, Höchstgrenze ist bislang keine bekannt.
Der neue Wert gilt ab dem folgenden Intervall.

set iCelsius ChangeSSID <irgendwas>
Damit kann das Netzwerk angegeben werden, in dem sich das Thermometer einloggen soll.
Verwende deine Zeit nicht mit Erklärungen. Die Menschen hören (lesen) nur, was sie hören (lesen) wollen. (c) Paulo Coelho

herrmannj

vielleicht  :)

Hast Du mal einen sniff mit verschiedenen temps dazu die raw ?

vg
joerg

btw:ich komme von da hier her: http://forum.fhem.de/index.php/topic,22977.0.html.

Papaloewe

Hallo Stefan,

ich finde deine Lösung mit dem iCelsius sehr interessant.

ZitatDieses sendet in mein hauseigenes WLAN mittels UPD seine Daten.
Habe es jetzt schon mal soweit, dass ich in FHEM die Daten empfange und aufbereite

Verräts du mir bitte womit (Modul) und wie du an die udp-Pakete im fhem gekommen bist?
Sendet das iCelsius per Broadcast und auf welchem UDP-Port?

Gruß
Thomas

Icinger

#3
Hi,

verrate ich gerne, hättre ich sowieso vorgehabt, allerdings wollte ich zuerst noch das Problem mit den Temperaturen lösen.

Kann ich ja aber immer noch nachreichen, sobald ich da draufgekommen bin ;)


Hier nun also die Sub mit der richtigen Temperaturumrechnung:
Also, erstmal hab ich mir eine neue 99_myiCelsius.pm angelegt mit folgendem Inhalt:
package main;

use locale;
use strict;
use warnings;
use POSIX;
use Time::Local;
use Data::Dumper;
use DBI;
use Net::Telnet;
use Data::Dumper;
use POSIX qw(strftime);


use IO::Socket::INET;

sub
myiCelsius_Initialize($$)
{
        my ($hash) = @_;
}

sub get_iCelsius($)
{
  my ($hash) = @_;
#Log 3,"Name is $name";

#my $hash=$defs{$name};
#delete($hash->{helper}{RUNNING_PID});
#if (exists($hash->{helper}{RUNNING_PID})) {return "Blocking already defined"};
$hash->{helper}{RUNNING_PID} = BlockingCall("SPS_RECV",$hash->{NAME},"set_iCelsius",120,"StopiCelsius",$hash) unless (exists($hash->{helper}{RUNNING_PID}));
}

sub StartiCelsius($)
{
  my ($hash) = @_;

readingsSingleUpdate($hash,"state","running",1);
InternalTimer(gettimeofday()+4, "get_iCelsius", $hash, 0);

}

sub StopiCelsius($)
{
  my ($hash) = @_;

  BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
  delete($hash->{helper}{RUNNING_PID});

  Log3 $hash->{NAME}, 3, "BlockingCall for ".$hash->{NAME}." was aborted";
readingsSingleUpdate($hash,"state","stopped",1);
  RemoveInternalTimer($hash);
#  InternalTimer(gettimeofday()+10, ...) # falls mit disable-Attribut gearbeitet wird, muss dieses hier geprüft werden}
}

sub set_iCelsius($)
{
my $string=shift;
my @a = split("\\|",$string);
my $hash = $defs{$a[0]};
RemoveInternalTimer($hash);
delete($hash->{helper}{RUNNING_PID});
#Log 3,$a[1];
my @b=split("\\&",$a[1]);
# Log 3,Dumper(@b);
my $x;
foreach $x (@b) {
  my @c=split("=",$x);
# Log 3,$x." = ".$c[0]." - ".$c[1];
if(ReadingsVal($hash->{NAME},$c[0],undef) ne $c[1]) {
if ($c[0]=~/temp./) {
readingsSingleUpdate($hash,$c[0],($c[1]-25000)/100,1)};
} else
{
readingsSingleUpdate($hash,$c[0],$c[1],1)
};
};
InternalTimer(gettimeofday()+4, "get_iCelsius", $hash, 0);
}

sub
SPS_RECV($) {
my $name=shift;
# flush after every write
$| = 1;

my $socket="";
my $recieved_data;
my $Pong;
my $Alarm;
my $peer_address;
my $peer_port;
my $txt=localtime();
$socket = new IO::Socket::INET (
LocalPort => '54521',
Proto => 'udp',
) or die "ERROR in Socket Creation : $!\n";
#Log 3,"Name is $name";
# read operation on the socket
$socket->recv($recieved_data,1024);
$socket->close();
return $name."|".$recieved_data;
}
cogito ergo sum;


Eventuell bau ich das später mal zu einem richtigen Modul um.

Danach ein Dummy angelegt:

define myiCelsius dummy
attr setList Start Stop


Weiters ein notify:

define ntf_iCelsius myiCelsius.Start|myiCelsius.Stop {if ($EVENT eq "Start") {StartiCelsius($defs{"myiCelsius"})};
if ($EVENT eq "Stop") {StopiCelsius($defs{"myiCelsius"})};
return undef;}


Jetzt kann ich zB ein
set myiCelsius Start
absetzen, damit starte ich einen internen Timer (aktuell noch fix 4 Sekunden), der nonblocking auf ein UDP-Paket wartet, dieses dann zerlegt und in die passenden Readings reinschreibt.

mit
set myiCelsius Stop
wird der Timer dann abgebrochen und beendet.

Theoretisch sollte nach 120 Sekunden ohne Empfang auch abgebrochen werden und das dummy auf "stopped" gehn.

Wie gesagt, ist aber noch recht unausgegoren, habe gestern vormittag erst angefangen, das ganze umzusetzen.
Da ich momentan auch ziemlich unter "Drogen" stehe, kann durchaus noch der eine oder andere Fehler drinnen sein.

lg, Stefan
Verwende deine Zeit nicht mit Erklärungen. Die Menschen hören (lesen) nur, was sie hören (lesen) wollen. (c) Paulo Coelho

herrmannj

Hey. schön.

Wenn Du einige samples rein stellst rate ich mit.

vg
joerg

Icinger

Hi Jörg,

hier mal auf die Schnelle ein paar Samples.
Raw gibts in diesem Sinne nicht, da die Daten als UPD im Textformat reinkommen, wie oben schon gezeigt.
Das UDP-Paket sieht folgendermaßen aus im plaintext:
SensorID=10002652&Mac=74:6a:89:00:46:b1&StoreForward=0&inFlash=0&Timestamp=3788567&RSSI=-85&battery=3932&sensorType=108&commMode=2&codeVersion=1.1.36&errorScanAp=0&SK=2448234605&ChargingStatus=0&temp1=27269&temp2=27157&

23218 --> -17,8°
23472 --> -15,3°
23690 --> -13,1°
23995 --> -10,1°
24222 --> -7,8°
25024 --> 0,2°
26186 --> 11,9°
26445 --> 14,5°
26526 --> 15,3°
26613 --> 16,1°
27296 --> 23°
28624 --> 36,2°
29989 --> 49,9°
31972 --> 69,7°
32861 --> 78,6°
34115 --> 91,1°
36091 --> 110,9°
37406 --> 124,1°
39069 --> 140,7°
39997 --> 150,0°
41859 --> 168,6°
42797 --> 178,0°
44624 --> 205,0°
47153 --> 221,5°

Links ist der Wert, der per UDP gesendet wird, rechts ist die Temp, welche von der Handy-App angezeigt wird.

Ach, und den Maverick-Thread verfolge ich schon länger. Da könnte sich ja dann vielleicht ein gemeinsames Grill-Modul entwickeln lassen, der zweistufige Ansatz ist ziemlich interessant :)

lg, Stefan
Verwende deine Zeit nicht mit Erklärungen. Die Menschen hören (lesen) nur, was sie hören (lesen) wollen. (c) Paulo Coelho

herrmannj

Hi

$out = ($in-25000)/100


ZitatDa könnte sich ja dann vielleicht ein gemeinsames Grill-Modul entwickeln lassen, der zweistufige Ansatz ist ziemlich interessant
Bin dabei !

Wir bräuchten ein receiver modul. Darf ich ein sceleton reinwerfen oder hast Du schon was ?

vg
joerg

Icinger

Na, das ging aber fix, danke :)

Nein, hab noch nichts, hab bisher nur den Hintergedanken "Da könnte man was machen" :D

lg, Stefan
Verwende deine Zeit nicht mit Erklärungen. Die Menschen hören (lesen) nur, was sie hören (lesen) wollen. (c) Paulo Coelho

herrmannj


herrmannj

Ola Stefan,

first wurf. Öffnet einen udp receiver auf port 5000:
Zitatdefine test iCelsius 5000

Ich mach die Tage weiter, ist nicht mehr viel.
#109: Regex auf die beiden Temp, umwandeln, weiter ins format des frx - parse und der Rest ist dann schon kosmetik.

Test mal bitte ab Du mit verbose 4 und dem richtigen port im define die sensor id im log siehst (nicht die msg aus #83 sondern die aus #111). Dazu muss der iCelsius die msg mit "\n" beenden, das sehe ich nicht an Deinem Post.

vg
joerg

Icinger

Ok, werd ich mir heute abend mal ansehen.

lg, Stefan
Verwende deine Zeit nicht mit Erklärungen. Die Menschen hören (lesen) nur, was sie hören (lesen) wollen. (c) Paulo Coelho

Papaloewe

#11
Das sieht schon mal gar nicht schlecht aus:

Ich habe zwar noch kein ICelsius und daher mit nc (netcat) ein upd-Paket gesendet:
echo "SensorID=10002652&Mac=74:6a:89:00:46:b1&StoreForward=0&inFlash=0&Timestamp=3788567&RSSI=-85&battery=3932&sensorType=108&commMode=2&codeVersion=1.1.36&errorScanAp=0&SK=2448234605&ChargingStatus=0&temp1=27269&temp2=27157&" | nc -w 1 -u -4 192.168.yyy.xxx 54521


Dann steht bei mir Folgendes im Log:
Zitat2016.01.08 18:53:18 4: BBQ: got that: SensorID=10002652&Mac=74:6a:89:00:46:b1&StoreForward=0&inFlash=0&Timestamp=3788567&RSSI=-85&battery=3932&sensorType=108&commMode=2&codeVersion=1.1.36&errorScanAp=0&SK=2448234605&ChargingStatus=0&temp1=27269&temp2=27157&
from 192.168.yyy.xxx 36259

2016.01.08 18:53:18 4: BBQ: receive sensor 10002652

Partial bleibt leer und STATE ist "drei Fragezeichen"

herrmannj

ja das ist beides  so richtig.

Ich weiß nicht ob das iCelsius die Nachricht mit \n abschließt weil daran erkenne ich jetzt das sie vollständig ist. nc macht es.
Wenn das iCelsius kein \n am ende schickt bliebe jetzt alles in partial, wenn ja ist es ist es so genau richtig...

state und so ist noch nix.

Wenn das mit \n passt läßst sich die anderen Werte (batt, rssi, temp1 und 2) genauso einfach rausholen wie die sensor id.
Dann heißt es das neu packen und ab ins dispatch. Dann "wäre" fertig.

vg
joerg

Papaloewe

Ok, die Frage nach dem "\n" kann dann nur Stefan beantworten.  ;)

Icinger

Hi,

Anbei eine Nachricht, wir sie von Wireshark angezeigt wird.
Da ist kein \n dahinter.

2 0.000591000 192.168.1.55 192.168.1.255 UDP 261 Source port: 4283  Destination port: 54521
0000   ff ff ff ff ff ff 74 6a 89 00 46 b1 08 00 45 00  ......tj..F...E.
0010   00 f7 00 02 00 00 ff 11 36 6d c0 a8 01 37 c0 a8  ........6m...7..
0020   01 ff 10 bb d4 f9 00 e3 b0 84 53 65 6e 73 6f 72  ..........Sensor
0030   49 44 3d 31 30 30 30 32 36 35 32 26 4d 61 63 3d  ID=10002652&Mac=
0040   37 34 3a 36 61 3a 38 39 3a 30 30 3a 34 36 3a 62  74:6a:89:00:46:b
0050   31 26 53 74 6f 72 65 46 6f 72 77 61 72 64 3d 30  1&StoreForward=0
0060   26 69 6e 46 6c 61 73 68 3d 30 26 54 69 6d 65 73  &inFlash=0&Times
0070   74 61 6d 70 3d 34 30 30 33 32 36 38 26 52 53 53  tamp=4003268&RSS
0080   49 3d 2d 36 35 26 62 61 74 74 65 72 79 3d 33 38  I=-65&battery=38
0090   35 39 26 73 65 6e 73 6f 72 54 79 70 65 3d 31 30  59&sensorType=10
00a0   38 26 63 6f 6d 6d 4d 6f 64 65 3d 32 26 63 6f 64  8&commMode=2&cod
00b0   65 56 65 72 73 69 6f 6e 3d 31 2e 31 2e 33 36 26  eVersion=1.1.36&
00c0   65 72 72 6f 72 53 63 61 6e 41 70 3d 30 26 53 4b  errorScanAp=0&SK
00d0   3d 32 34 34 38 32 33 34 36 30 35 26 43 68 61 72  =2448234605&Char
00e0   67 69 6e 67 53 74 61 74 75 73 3d 30 26 74 65 6d  gingStatus=0&tem
00f0   70 31 3d 32 36 39 39 36 26 74 65 6d 70 32 3d 32  p1=26996&temp2=2
0100   36 39 37 30 26                                   6970&


lg, Stefan
Verwende deine Zeit nicht mit Erklärungen. Die Menschen hören (lesen) nur, was sie hören (lesen) wollen. (c) Paulo Coelho