[Gelöst] Subroutine mit AT-Befehl aufrufen --> FHEM hängt sich auf

Begonnen von Qaldak, 03 September 2018, 23:35:18

Vorheriges Thema - Nächstes Thema

Qaldak

Hallo Leute

Meine FHEM Installation läuft (bislang) erfolgreich auf meiner Raspberry Pi.
Unter anderem versendet FHEM auch UDP Messages innerhalb des Netzwerks. Nun wollte ich erweitern, dass FHEM auch UDP Meldungen vom Temperatursensor empfangen kann.

Folgende Sub habe ich erstellt:
sub ReceiveUDPMsg() {
Log 4, "ReceiveUDPMsg: run script"; # log start script (nice to know only)
use IO::Socket::INET;

# flush after every write
$| = 1;

my ($sock,$recv_cmd,$temp);

my $sock = IO::Socket::INET->new(
Proto => 'udp',
Port => '12345'
);

if(!$sock) {
return "ReceiveUDPMsg: something went wrong (socket: $sock)"
}

# read operation on the socket
$sock->recv($recv_cmd,1024);

# Check received data message and set to device attribute
if($recv_cmd =~ "^TempC") {
Log 3, "Incoming temperature message: $recv_cmd";
$temp = substr($recv_cmd,5);
fhem("set tr_tortoiseEnclGroundTemp $temp");;
$temp = AttrVal("tr_tortoiseEnclGroundTemp", "state", undef);
Log 3, "Set temperature on device attribute: $temp";

} else {
Log 3, "Undefined received data message: $recv_cmd";
}

$sock->close();
}


Die Überwachung der eingehenden UDP Meldungen habe ich wie folgt umgesetzt:
define chk_recvudpmsg at +*00:00:03 ({ReceiveUDPMsg()})

Das Problem ist nun: immer wenn der DEFINE ablaufen und ReceiveDUPMsg ausgeführt werden soll, bleibt FHEM stehen.
Damit FHEM wieder gestartet werden kann, passe ich via Putty das Fhem.cfg wieder an und deaktiviere den AT-Befehl (siehe oben). Nach Restart Fhem läuft's dann wieder...

Im Logfile sehe ich folgendes:
2018.09.03 23:19:10.230 1: ./log/fhem.save: Please define chk_recvudpmsg first
Please define chk_recvudpmsg first


Aber der Befehl ist ja definiert. Hab's auch mit watchdog versucht, gibt aber dasselbe Ergebnis.
Weil das ganze stehen bleibt, finde ich auch nicht heraus, ob die sub korrekt läuft...

Danke.

DS_Starter

Meine Empfehlung wäre dass du dir das Log2Syslog-Modul anschaust: https://fhem.de/commandref_DE.html#Log2Syslog

Es hat einen Sender- und einen Collector-Modus. Im Collector-Modus kannst du mit dem Attribut "parseProfile=raw" oder "parseProfile=parseFn" wahrscheinlich genau das erreichen was du möchtest.

Sollte es sich bei den Daten die du empfangen willst um Daten im Syslog-Format handeln, hast du noch mehr eingebaute Funktionen.

LG
Heiko
Proxmox+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

CoolTux

Zitat von: Qaldak am 03 September 2018, 23:35:18
Hallo Leute

Meine FHEM Installation läuft (bislang) erfolgreich auf meiner Raspberry Pi.
Unter anderem versendet FHEM auch UDP Messages innerhalb des Netzwerks. Nun wollte ich erweitern, dass FHEM auch UDP Meldungen vom Temperatursensor empfangen kann.

Folgende Sub habe ich erstellt:
sub ReceiveUDPMsg() {
Log 4, "ReceiveUDPMsg: run script"; # log start script (nice to know only)
use IO::Socket::INET;

# flush after every write
$| = 1;

my ($sock,$recv_cmd,$temp);

my $sock = IO::Socket::INET->new(
Proto => 'udp',
Port => '12345'
);

if(!$sock) {
return "ReceiveUDPMsg: something went wrong (socket: $sock)"
}

# read operation on the socket
$sock->recv($recv_cmd,1024);

# Check received data message and set to device attribute
if($recv_cmd =~ "^TempC") {
Log 3, "Incoming temperature message: $recv_cmd";
$temp = substr($recv_cmd,5);
fhem("set tr_tortoiseEnclGroundTemp $temp");;
$temp = AttrVal("tr_tortoiseEnclGroundTemp", "state", undef);
Log 3, "Set temperature on device attribute: $temp";

} else {
Log 3, "Undefined received data message: $recv_cmd";
}

$sock->close();
}


Die Überwachung der eingehenden UDP Meldungen habe ich wie folgt umgesetzt:
define chk_recvudpmsg at +*00:00:03 ({ReceiveUDPMsg()})

Das Problem ist nun: immer wenn der DEFINE ablaufen und ReceiveDUPMsg ausgeführt werden soll, bleibt FHEM stehen.
Damit FHEM wieder gestartet werden kann, passe ich via Putty das Fhem.cfg wieder an und deaktiviere den AT-Befehl (siehe oben). Nach Restart Fhem läuft's dann wieder...

Im Logfile sehe ich folgendes:
2018.09.03 23:19:10.230 1: ./log/fhem.save: Please define chk_recvudpmsg first
Please define chk_recvudpmsg first


Aber der Befehl ist ja definiert. Hab's auch mit watchdog versucht, gibt aber dasselbe Ergebnis.
Weil das ganze stehen bleibt, finde ich auch nicht heraus, ob die sub korrekt läuft...

Danke.

So ganz sehe ich da nicht durch. Was genau hast Du vor mit dem Code? Soll da local auf dem FHEM Server ein Serversocket geöffnet werden wo Daten empfangen werden sollen?
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Wzut

Zitat von: Qaldak am 03 September 2018, 23:35:18
$sock->recv($recv_cmd,1024);

Was passiert wohl solange noch keine 1024 Byte auf deinem Port 12345 empfangen wurden ?
IMHO wird gewartet bis es soweit ist, was in deinem Fall bedeutet FHEM steht :)
Versuch : Wert kleiner machen / dafür sorgen das genug Daten in der Zeit ankommen  oder besser -> solche Warteaufgaben mittels BlockingCall auslagern. 
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

CoolTux

Er wird dennoch Probleme bekommen.

Das ganze gehört in die select Schleife von FHEM und sollte über die ReadFn dann ausgelesen werden und nicht anders.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

DS_Starter

Darum hatte ich ihm ja vorgeschlagen mein Log2Syslog Modul zu nutzen. Dann braucht man sich darüber zumindest diese Gedanken nivht machen.

Lg
Heiko
Proxmox+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Qaldak

Zitat von: CoolTux am 04 September 2018, 06:56:43
So ganz sehe ich da nicht durch. Was genau hast Du vor mit dem Code? Soll da local auf dem FHEM Server ein Serversocket geöffnet werden wo Daten empfangen werden sollen?

Mein Temperatursensor sendet die Temperatur in regelmässigen Abständen per UDP an FHEM. In FHEM soll die eingehende UDP Meldung empfangen und der Wert in ein FHEM (Dummy) Device geschrieben werden. So kann ich die aktuelle Temperatur in FHEM sehen und weiterverwenden.


Ich werde sonst gerne mal ReadFN oder Log2Syslog prüfen. Ich dachte jedoch, dass es eine einfachere Lösung gibt. Beim UDP Senden ist es relativ einfach, daher habe ich denselben Ansatz auch für Receive UDP gewählt.

betateilchen

die Meldung bezüglich fhem.save kannst Du getrost ignorieren, die kommt daher, dass Du von aussen manuell in der fhem.cfg rumpfuscht, ohne verstanden zu haben, was Du da tust.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Qaldak

Zitat von: betateilchen am 04 September 2018, 11:45:41
die Meldung bezüglich fhem.save kannst Du getrost ignorieren, die kommt daher, dass Du von aussen manuell in der fhem.cfg rumpfuscht, ohne verstanden zu haben, was Du da tust.

Ok, thx. Wobei ich nur nicht alle Auswirkungen kannte. ;)

Beta-User

Zitat von: Qaldak am 04 September 2018, 11:43:39
Mein Temperatursensor sendet die Temperatur in regelmässigen Abständen per UDP an FHEM.
Wenn du dem Sensor zufällig MQTT beibringen kannst (oder der das schon kann): Schau' dir mal die neuen MQTT2-Module an; kann sein, dass es damit ruck zuck funktioniert...

Ansonsten gibt es irgendwo auch ein (inoffizielles) Modul für den 360-Grad IR-Blaster, das UDP-Daten empfängt; vielleicht schaust du dir das mal an, wie da das Empfangen usw. gelöst ist.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

Qaldak

Zitat von: Beta-User am 04 September 2018, 12:03:10
Wenn du dem Sensor zufällig MQTT beibringen kannst

ja, das geht natürlich.
Ich war bislang auf UDP eingeschossen, weil meine anderen Umsysteme mit UDP kommunizieren. Aber MQTT wäre gangbar...

Beta-User

Zitat von: Qaldak am 04 September 2018, 15:21:44
ja, das geht natürlich.
Ich war bislang auf UDP eingeschossen, weil meine anderen Umsysteme mit UDP kommunizieren. Aber MQTT wäre gangbar...
MQTT2 ist wirklich einfach:
Wenn du bisher keinen Broker laufen hast, einfach einen mit MQTT2_SERVER (global) definieren, (eine allowed-Instanz dafür anlegen, wenn User/passwort erforderlich ist) und das Server-Device auf autocreate stellen.
Dann sollten die MQTT2_DEVICE's automatisch angelegt werden, sobald der Sensor MQTT-kompatible Infos an deinen FHEM-Rechner schickt.
Wenn irgendwo schon Mosquitto oä. laufen sollte: geht auch, dann aber einen anderen Port wählen (auch auf dem Sensor-Interface).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

Qaldak

Habe das ganze auf MQTT umgebaut. Scheint ja ressourcensparender und ein gängiges Protokoll für IoT zu sein. Muss noch genau schauen, ob das ganze auch mit MQTT-SN funktionieren wird. Oder weiss das jemand?
Für meinen (einzigen) Temp.-Sensor spielt's noch keine Rolle, aber wenn allenfalls noch weitere Daten dazu kommen, wäre es allenfalls ein Thema.


Aber dennoch, hat mir die UDP-Variante keine Ruhe gelassen. ;-) Habe also mit Internet-Recherche und etwas hin- und herkopieren eine Möglichkeit gefunden.
Mit folgendem .pm können UDP-Meldungen einfach empfangen und verarbeitet werden.

package main;

use strict;
use warnings;
use POSIX;
use IO::Socket;


sub
myUDPUtils_Initialize($$) {
  my ($hash) = @_;
 
  $hash->{DefFn}   = "initUDPSocket";
  $hash->{UndefFn} = "closeUDPSocket";
  $hash->{ReadFn}  = "readUDPMsg";
}


# initUDPSocket
sub initUDPSocket($$) {
Log 4, "initUDPSocket started";
my ($hash, $def) = @_;
my @a = split("[ \t][ \t]*", $def);
 
  Log 4, "initUDPSocket: $hash, $def";

# Check Aufruf aus fhem.cfg
  if(@a < 3 || @a > 3) {
    my $msg = "initUDPSocket: wrong syntax (define <name> UDP <port>)";
    Log3 undef, 2, $msg;
    return $msg;
  }

  my $name = $a[0]; # Device Name gem define aus fhem.cfg
  my $port = $a[2]; # Parameter gem define aus fhem.cfg

# Socket initialisieren
  my $sock = IO::Socket::INET->new(
  Proto=>"udp",
LocalPort=>$port
);

if(!$sock) {
Log 2, "initUDPSocket: couldn't initiate new socket (socket: $sock)"
}


# $hash Attribute definieren und Eintrag in selectlist
$hash->{FD} = $sock->fileno();
$hash->{CD} = $sock;
$selectlist{$name} = $hash;

Log 4, "initUDPSocket: socket successfully created (socket: $sock)";
return 0;
}


# closeUDPSocket
sub closeUDPSocket($$) {
Log 4, "closeUDPSocket started";
my ($hash, $arg) = @_;
my $name = $hash->{NAME};

$hash->{CD}->close();
return undef;
}


# readUDPMsg
sub readUDPMsg($) {
my ($hash) = @_;
my $name = $hash->{NAME};
my $recv_msg;
my $temp;

$hash->{STATE} = 'Last: '.localtime(); # Setzt Datum der letzten UDP Meldung auf Device
$hash->{CD}->recv($recv_msg, 255);
Log 4, "readUDPMsg: incoming message: $recv_msg";

# Check received data message and set to device attribute
if($recv_msg =~ "^TempC") {
$temp = substr($recv_msg,6);
fhem("set tr_tortoiseEnclGroundTemp $temp");;
Log 3, "readUDPMsg: Set incoming temperature ($recv_msg) to device";
} else {
Log 2, "readUDPMsg: Undefined received data message: $recv_msg";
}
}

# Do not delete
1;


Vielleicht hilft's mal jemandem, der nach sowas sucht.