Ich habe mehrere Arduino Nano über JeeLink an meine FHEM-Systeme angebunden. Diese erledigen verschiedene Aufgaben, wie z.B. Strom- Gas und Wasserzähler auszulesen oder meine Funk-Rauchmelder zu überwachen.
Die Messwerte werden über KeyValueProtocol übertragen.
Wenn ich jetzt aber irgendwelche Parameter (Erkennungsschwellen, Transmitzeiten ...) ändern will, muss ich jedesmal den entsprechenden Arduino abhängen und mit der Arduino-IDE den geänderten Sketch neu flashen.
Jetzt ist bei mir die Idee entstanden, ob ich nicht die entsprechenden Parameter in FHEM verwalte und nach dem Initialisieren an den Arduino schicke.
Dazu habe ich einen kleinen Probeaufbau gemacht: An einem Test-FHEM-System auf dem Raspberry hängt ein Arduino Nano über USB. Auf letzterem habe ich SoftwareSerial installiert, so dass ich über einen TTL<->USB Adapter alles überwachen kann, was FHEM über die im Arduino eingebaute USB-Schnittstelle schickt.
Den Arduino habe ich als JeeLink-Device definiert:
Internals:
Clients :PCA301:EC3000:RoomNode:LaCrosse:ETH200comfort:CUL_IR:HX2272:FS20:AliRF:Level:EMT7110:KeyValueProtocol
DEF /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AL03ZR46-if00-port0@9600
DeviceName /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AL03ZR46-if00-port0@9600
FD 4
FUUID 5e598369-f33f-6a44-afad-05e749d78830d637
NAME Test_JeeLink
NR 14
PARTIAL
STATE opened
TYPE JeeLink
MatchList:
1:PCA301 ^\S+\s+24
2:EC3000 ^\S+\s+22
3:RoomNode ^\S+\s+11
4:LaCrosse ^(\S+\s+9 |OK\sWS\s)
5:AliRF ^\S+\s+5
6:EMT7110 ^OK\sEMT7110\s
7:KeyValueProtocol ^OK\sVALUES\s
READINGS:
2020-02-29 11:25:09 state opened
Attributes:
flashCommand avrdude -p atmega328P -c arduino -P [PORT] -D -U flash:w:[HEXFILE] 2>[LOGFILE]
verbose 5
Wenn ich jetzt manuell "set Test_JeeLink raw XXX" ausführe, taucht wunderbar "XXX" auf dem Arduino auf.
Um die Sache zu automatisieren, habe ich ein notify definiert:
Internals:
CFGFN
DEF Test_JeeLink:CONNECTED.* sleep 5; set Test_JeeLink raw XXX
FUUID 5e5a35f8-f33f-6a44-dee0-10537cd8a3293336
NAME notify_Test_JeeLink
NOTIFYDEV Test_JeeLink
NR 23
NTFY_ORDER 50-notify_Test_JeeLink
REGEXP Test_JeeLink:CONNECTED.*
STATE 2020-02-29 12:59:58
TRIGGERTIME 1582977598.66129
TYPE notify
READINGS:
2020-02-29 12:59:25 state active
Attributes:
Das notify löst aus, wenn ich "set Test_JeeLink reset" ausführe - im Log steht auch
2020.02.29 13:00:00 4: set Test_JeeLink raw XXX
2020.02.29 13:00:00 5: SW: XXX
Im Arduino kommt aber nichts an.
Ich habe noch einen zweiten Versuch unternommen:
Wenn ich "define at_Test at +00:00:05 set Test_JeeLink raw XXX" ausführe, kommt nach 5 Sekunden "XXX" im Arduino an.
Wenn ich das Notify so definiere: "define notify_Test_JeeLink notify Test_JeeLink:CONNECTED.* define at_Test at +00:00:05 set Test_JeeLink raw XXX", löst das Notify bei einem Reset des Arduino aus, das at wird nach 5 Sekunden ausgeführt, aber auf dem Arduino kommt nichts an.
Jetzt komme ich irgendwie nicht mehr weiter.
Ich schiebe das Thema nochmal hoch.
Meine Frage ist, warum FHEM-Kommandos, die von einem Notify ausgelöst werden, anders ausgeführt werden, als wenn ich sie händisch im Kommandofeld ausführe.
probier es doch mal statt mit Notify mit einem DOIF oder MSwitch.
Ich habe bei mir fast 95% auf MSwitch umgestellt - ist sehr empfehlenswert,
da sich Trigger und auszuführende Befehle vorab auch getrennt testen lassen.
da greift eventuell der sicherheitsmechanismus, um endlosschleifen zu verhindern.
trigger und set cmd sind vom selben device.
mit userreading sollte es dann funktionieren.
@Panik: Von DOIF habe ich bisher die Finger gelassen - die Syntax ist mir im Vergleich zu Perl etwas schräg.
@frank: Wie ist das gemeint? Ein userreading für das JeeLink-Device einrichten, auf dieses triggern und dann das notify ein set ... ausführen lassen?
userreading statt notify.
ein userreading ist quasi ein spezielles notify, dass ein reading im selben device erzeugt/befüllt.
im "ausführungsteil" wird der wert des userreadings mit perlcode erzeugt und an das reading übergeben.
dort könnte man zusätzlich den set cmd mit der perlfunktion "fhem("set cmd")" einbauen.
ich habe es noch nicht probiert, könnte aber funktionieren.
Ah, verstanden. Ich bin unterwegs und probiere das nächste Woche mal aus.
Mit userreadings geht es auch nicht.
Ich habe jetzt auch versucht, mit dem notify auf Test_JeeLink:CONNECTED.* ein Dummy-Device zu schalten - das funktioniert.
Der Dummy löst dann ein weiteres notify aus, das "set Test_JeeLink raw XXX" ausführt. Auch mit dieser Variante kommt nichts an.
Wenn ich den Dummy manuell schalte, funktioniert es.
Es funktioniert jetzt. Nach einem Reset kann anscheinend der Arduino eine Zeitlang keine Daten empfangen.
Ich habe das Notify jetzt mit global:INITIALIZED.* getriggert und eine Wartezeit von 5 Sekunden eingebaut.
Jetzt kommen die Daten an.
Für alle, die es mal nachmachen wollen, poste ich hier mal meine endgültige Lösung:
So sieht mein JeeLink-Device für den Arduino aus:
Internals:
Clients :PCA301:EC3000:RoomNode:LaCrosse:ETH200comfort:CUL_IR:HX2272:FS20:AliRF:Level:EMT7110:KeyValueProtocol
DEF /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AL05RIDZ-if00-port0@9600
Detector_01_MSGCNT 602
Detector_01_TIME 2020-03-15 11:36:51
DeviceName /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AL05RIDZ-if00-port0@9600
FD 28
FUUID 5e57901f-f33f-c1fa-f170-3cf56638bd8420db
NAME Detector_01
NR 303
PARTIAL
RAWMSG OK VALUES Detector 01 A=0,P=47.00,L=48
STATE opened
TYPE JeeLink
Helper:
DBLOG:
UNKNOWNCODE Parameter:
myDbLog:
TIME 1584268015.11332
VALUE 90 40 20 1000 100 10
state:
myDbLog:
TIME 1584268015.08035
VALUE UNKNOWNCODE Sound- und LED-Detektor 1.6
MatchList:
1:PCA301 ^\S+\s+24
2:EC3000 ^\S+\s+22
3:RoomNode ^\S+\s+11
4:LaCrosse ^(\S+\s+9 |OK\sWS\s)
5:AliRF ^\S+\s+5
6:EMT7110 ^OK\sEMT7110\s
7:KeyValueProtocol ^OK\sVALUES\s
READINGS:
2020-03-15 11:36:51 state opened
Attributes:
alias Arduino LED und Geräusch
comment Parameter im Attribut initCommands (Trennung mit Leerzeichen):
LED Erkennung: 1 obere Schwelle, 2 untere Schwelle, 3 Alarmlimit,
Geräuscherkennung: 4 Sammelzeit (ms), 5 Alarmlimit, 6 Übertragungsintervall (min.)
flashCommand avrdude -p atmega328P -c arduino -P [PORT] -D -U flash:w:[HEXFILE] 2>[LOGFILE]
initCommands 90 40 20 1000 100 10
room System->Main,System->Protokolle->KeyValueProtocol
im Attribut initCommands stehen durch Leerzeichen getrennt die Parameter.
Die Übertragung zum Arduino erledigt ein Watchdog:
Internals:
CMD { my $Parameters = AttrVal("Detector_01","initCommands",""); fhem("set Detector_01 raw $Parameters") }
DEF global:INITIALIZED.*|Detector_01:CONNECTED.* 00:00:05 SAME { my $Parameters = AttrVal("Detector_01","initCommands",""); fhem("set Detector_01 raw $Parameters") }
FUUID 5e6dfdc0-f33f-c1fa-1a43-b6cd461bc2a60854
NAME watchdog_Detector_01
NOTIFYDEV Detector_01,watchdog_Detector_01,global
NR 60918
NTFY_ORDER 50-watchdog_Detector_01
RE1 global:INITIALIZED.*|Detector_01:CONNECTED.*
RE2 global:INITIALIZED.*|Detector_01:CONNECTED.*
STATE defined
TO 5
TYPE watchdog
Helper:
DBLOG:
state:
myDbLog:
TIME 1584267010.12895
VALUE defined
READINGS:
2020-03-15 11:26:50 Activated activated
2020-03-15 11:26:55 Reset reset
2020-03-15 11:26:55 Triggered triggered
2020-03-15 11:10:10 state defined
Attributes:
autoRestart 1
comment sendet nach den Start oder nach dem Reset Parameter an den Arduino Detector_01 (LED und Geräuschüberwachung)
room System->Protokolle->KeyValueProtocol
Der Arduino-Code, der die Daten empfängt, steht im setup()-Teil des Sketches:
parameter[0] = 90; // set all parameters to default values
parameter[1] = 40;
parameter[2] = 20;
parameter[3] = 1000;
parameter[4] = 100;
parameter[5] = 10;
actualTime = millis();
while ((inChar != 10) && (((unsigned long)(millis() - actualTime)) < 15000) && (i < 6)) { // read parameters until newline is received or time limit of 15 sec. is exceeded
while (Serial.available() > 0) {
inChar = Serial.read();
if (isDigit(inChar)) { // convert the incoming byte to a char and add it to the string:
inString += (char)inChar;
}
if ((inChar == 32) || (inChar == 10)) { // if you get a space or a newline store the string's value:
parameter[i] = inString.toInt();
i++;
inString = ""; // clear the string for new input:
}
}
}