Die Temperatursensoren werden über einen JeeLink USB Stick empfangen. Der USB Stick ist als Serielles Gerät in Node Red eingebunden und empfängt die Signale der Temperatursensoren.

Die Konfiguration ist fix hinterlegt im ersten Node.

Die Sensorwerte werden mit dem Sensornamen als Topic angereichert und wenn ein gültiger Feuchtigkeitswert gemeldet wird, wird zusätzlich auch der Taupunkt berechnet und als JSON Daten an MQTT gesendet.
Wegen der Datenflut werden nur Änderungen gesendet. Zusätzlich wird alle 5 Minuten der aktuelle Wert ebenso gesendet, auch wenn dieser nicht geändert hat. Die . Man spart hierdurch beinahe 90% an Daten.
Hier ein Export des Flows:
[{"id":"a91667da.046088","type":"serial in","z":"b96d75fb.65f7c8","name":"JeeLink","serial":"da813241.9e625","x":82,"y":52,"wires":[["a9a730c.d1cb4d"]]},{"id":"a9a730c.d1cb4d","type":"function","z":"b96d75fb.65f7c8","name":"Configuration","func":"msg.context = {}\nmsg.context['58'] = {'name':'Wintergarten','area':'Wintergarten'}\nmsg.context['18'] = {'name':'Wintergarten2','area':'Wintergarten'}\nmsg.context['50'] = {'name':'AussenTemp','area':'Aussen'}\nmsg.context['54'] = {'name':'Bad1OG','area':'Beheizt'}\nmsg.context['61'] = {'name':'Bunker','area':'Unbeheizt'}\nmsg.context['23'] = {'name':'Dachstock','area':'Unbeheizt'}\nmsg.context['46'] = {'name':'HausEingang','area':'Beheizt'}\nmsg.context['7'] = {'name':'Keller','area':'Unbeheizt'}\n//msg.context['10'] = {'name':'Schlafzimmer','area':'Beheizt'}\nmsg.context['10'] = {'name':'PflanzenThermometer','area':'Beheizt'}\nmsg.context['22'] = {'name':'Stube','area':'Beheizt'}\nmsg.context['13'] = {'name':'Stube2','area':'Beheizt'}\nmsg.context['0'] = {'name':'Trockenraum','area':'Unbeheizt'}\nmsg.context['8'] = {'name':'UntermDach','area':'Unbeheizt'}\n\nnode.status({fill:\"blue\",shape:\"ring\",text:${msg.payload}
})\nmsg.measurement = \"LaCrosse_Sensors\"\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":183,"y":134,"wires":[["10f0dee1.5ae9a1"]]},{"id":"10f0dee1.5ae9a1","type":"function","z":"b96d75fb.65f7c8","name":"ParseLaCrosseInput","func":"var code = msg.payload\nvar new_payload = {}\nvar unknown_payload = {}\n// check if valid values\nif(code.match(/^OK 9/)) {\n // split input into a byte array and deletes the first two bytes\n var bytes = code.split(\" \");\n bytes.shift()\n bytes.shift()\n\n var addr = bytes[0].toString()\n if(!(addr in msg.context)){\n node.status({fill:\"blue\",shape:\"ring\",text:addr:${addr} is not defined !
})\n unknown_payload.payload=addr + \" \" + ((parseInt(bytes[2]) * 256) + parseInt(bytes[3]) - 1000)/10 + \"°C\";\n return [null,unknown_payload];\n }\n \n new_payload.sensor = msg.context[addr].name\n new_payload.area = msg.context[addr].area\n new_payload.battery_new = (parseInt(bytes[1]) & 0x80) >> 7\n new_payload.battery_low = (parseInt(bytes[4]) & 0x80) >> 7\n new_payload.type = (parseInt(bytes[1]) & 0x70) >> 4\n new_payload.channel = parseInt(bytes[1]) & 0x0F\n new_payload.temperature = ((parseInt(bytes[2]) * 256) + parseInt(bytes[3]) - 1000)/10\n new_payload.humidity = parseInt(bytes[4]) & 0x7f\n new_payload.message = msg.payload\n \n if (new_payload.humidity < 106)\n {\n //Magische dew point Berechnung :)\n\tvar A = 17.2694;\n\tvar B = (new_payload.temperature > 0) ? 237.3 : 265.5;\n\tvar es = 610.78 * Math.exp( A * new_payload.temperature / (new_payload.temperature + B) );\n\tvar e = new_payload.humidity/ 100 * es;\n\tif (e === 0) { \n\t\treturn [null,null];\n\t} \n\tvar e1 = e / 610.78;\n\tvar f = Math.log( e1 ) / A;\n\tvar f1 = 1 - f;\n\tif (f1 === 0) { \n\t\treturn [null,null];\n\t}\n\tnew_payload.dew = B * f / f1 ;\n }\n node.status({fill:\"blue\",shape:\"ring\",text:T[${new_payload.temperature}°C]/H[${new_payload.humidity}%]
})\n msg.payload = new_payload\n msg.topic=\"sensor/temp/\"+msg.context[addr].name\n return [msg,null]\n}\nreturn [null,null];\n\n\n\n/\n# Temperature sensor - Format:\n# 0 1 2 3 4\n# -------------------------\n# OK 9 56 1 4 156 37 ID = 56 T: 18.0 H: 37 no NewBatt\n# OK 9 49 1 4 182 54 ID = 49 T: 20.6 H: 54 no NewBatt\n# OK 9 55 129 4 192 56 ID = 55 T: 21.6 H: 56 WITH NewBatt\n\n# OK 9 2 1 4 212 106 ID = 2 T: 23.6 H: -- Channel: 1\n# OK 9 2 130 4 225 125 ID = 2 T: 24.9 H: -- Channel: 2\n\n# OK 9 ID XXX XXX XXX XXX\n# | | | | | | |\n# | | | | | | --- Humidity incl. WeakBatteryFlag\n# | | | | | |------ Temp * 10 + 1000 LSB\n# | | | | |---------- Temp * 10 + 1000 MSB\n# | | | |-------------- Sensor type (1 or 2) +128 if NewBatteryFlag\n# | | |----------------- Sensor ID\n# | |------------------- fix \"9\"\n# |---------------------- fix \"OK\"\n/","outputs":2,"noerr":0,"initialize":"","finalize":"","x":414,"y":130,"wires":[["fce169d3.8868b8","82b2749d.7f5928","6bdc6ee.2acdf9"],["e5f4e8e.ea65718","5997291f.c0b538","d5f8bcb9.e5c16"]]},{"id":"6bdc6ee.2acdf9","type":"trigger","z":"b96d75fb.65f7c8","name":"watchdog","op1":"","op2":"Keine Temperatur Daten seit 5 Min empfangen.","op1type":"nul","op2type":"str","duration":"5","extend":true,"units":"min","reset":"","bytopic":"all","outputs":1,"x":741.5,"y":72,"wires":[["49f87495.77117c","507cc2a7.a729cc","f5ad09ff.10ae28"]]},{"id":"f5ad09ff.10ae28","type":"delay","z":"b96d75fb.65f7c8","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":905.5,"y":48,"wires":[["7c238d65.774784"]]},{"id":"7c238d65.774784","type":"exec","z":"b96d75fb.65f7c8","command":"nohup sudo service nodered restart","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":1141.5,"y":36.5,"wires":[[],[],[]]},{"id":"507cc2a7.a729cc","type":"mqtt out","z":"b96d75fb.65f7c8","name":"","topic":"stat/alarm/message","qos":"","retain":"","broker":"489ebd83.1c1664","x":1077.5,"y":96,"wires":[]},{"id":"d5f8bcb9.e5c16","type":"ui_template","z":"b96d75fb.65f7c8","group":"623c9aa5.9e3a14","name":"Unkonfigurierte Sensoren","order":1,"width":"","height":"","format":"
{{msg.topic}}
\n{{msg.payload}}
\n","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":1030,"y":195,"wires":[[]]},{"id":"5997291f.c0b538","type":"Message Counter","z":"b96d75fb.65f7c8","name":"","units":"hours","interval":"1","alignToClock":true,"generator":"internal","x":1010,"y":237,"wires":[[],[]]},{"id":"fce169d3.8868b8","type":"Message Counter","z":"b96d75fb.65f7c8","name":"","units":"hours","interval":"1","alignToClock":true,"generator":"internal","x":604,"y":229,"wires":[[],[]]},{"id":"101cca1f.157f56","type":"Message Counter","z":"b96d75fb.65f7c8","name":"","units":"hours","interval":"1","alignToClock":true,"generator":"internal","x":371,"y":230,"wires":[[],[]]},{"id":"82b2749d.7f5928","type":"rbe","z":"b96d75fb.65f7c8","name":"","func":"narrowband","gap":"20%","start":"","inout":"in","property":"payload.temperature","x":150.5,"y":219,"wires":[["2ed88e02.2d3f12","101cca1f.157f56"]]},{"id":"2ed88e02.2d3f12","type":"rbe","z":"b96d75fb.65f7c8","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload.temperature","x":125.5,"y":281,"wires":[["290d8f4e.3c77f","bb03fa34.a8be28","e722cadc.e827c8","74789fd1.3205d","b0e8b046.929f8","8c3c4f60.1df9a","c37d6ac5.6a44a8","6f38d38c.0789cc","fbc57e0f.23296"]]},{"id":"c37d6ac5.6a44a8","type":"function","z":"b96d75fb.65f7c8","name":"","func":"var new_payload = {}\nvar msg1 = {};\nif (msg.payload.humidity<101) {\n//Magische dew point Berechnung :)\n\tvar A = 17.2694;\n\tvar B = (msg.payload.temperature > 0) ? 237.3 : 265.5;\n\tvar es = 610.78 * Math.exp( A * msg.payload.temperature / (msg.payload.temperature + B) );\n\tvar e = msg.payload.humidity/ 100 * es;\n\tif (e === 0) { \n\t\treturn null;\n\t} \n\tvar e1 = e / 610.78;\n\tvar f = Math.log( e1 ) / A;\n\tvar f1 = 1 - f;\n\tif (f1 === 0) { \n\t\treturn null;\n\t}\n\tdp = B * f / f1 ;\n} else {\n dp=msg.payload.temperature;\n msg.payload.humidity=0;\n}\n\nnew_payload = [{\n temperature: msg.payload.temperature,\n humidity: msg.payload.humidity,\n dew: dp,\n sensor: msg.payload.sensor,\n battery_new: msg.payload.battery_new,\n battery_low: msg.payload.battery_low,\n type: msg.payload.type,\n channel: msg.payload.channel\n},\n{\n site_name:msg.payload.sensor,\n area:msg.payload.area,\n sensor:\"lacrosse\"\n}];\n\nmsg1.payload=new_payload;\nreturn msg1;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":359.5,"y":284,"wires":[["b9b722e3.909d5"]]},{"id":"c033f70e.053118","type":"inject","z":"b96d75fb.65f7c8","name":"resend data every 5 minutes","repeat":"300","crontab":"","once":true,"onceDelay":"3","topic":"","payload":"reset","payloadType":"str","x":478.5,"y":335,"wires":[["b4e0a9c.0698958"]]},{"id":"b4e0a9c.0698958","type":"function","z":"b96d75fb.65f7c8","name":"","func":"msg.reset=1;\nreturn msg;","outputs":1,"noerr":0,"x":733.5,"y":326,"wires":[["2ed88e02.2d3f12"]]},{"id":"74789fd1.3205d","type":"function","z":"b96d75fb.65f7c8","name":"","func":"var new_payload = {}\nvar msg1 = {};\nif (msg.payload.humidity>100) return null\n\n//Magische dew point Berechnung :)\n\tvar A = 17.2694;\n\tvar B = (msg.payload.temperature > 0) ? 237.3 : 265.5;\n\tvar es = 610.78 * Math.exp( A * msg.payload.temperature / (msg.payload.temperature + B) );\n\tvar e = msg.payload.humidity/ 100 * es;\n\tif (e === 0) { \n\t\treturn null;\n\t} \n\tvar e1 = e / 610.78;\n\tvar f = Math.log( e1 ) / A;\n\tvar f1 = 1 - f;\n\tif (f1 === 0) { \n\t\treturn null;\n\t}\n\tdp = B * f / f1 ;\n\t\n\nnew_payload = [{\n value: dp,\n},\n{\n site_name:msg.payload.sensor,\n type:\"dew\",\n sensor:\"lacrosse\",\n area:msg.payload.area\n}];\n\nmsg1.payload=new_payload;\nreturn msg1;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":404,"y":380,"wires":[["7f24b8ed.6b61d8"]]},{"id":"e722cadc.e827c8","type":"function","z":"b96d75fb.65f7c8","name":"","func":"var new_payload = {}\nvar msg1 = {};\n\nif (msg.payload.humidity>100) return null\n\nnew_payload = [{\n value: msg.payload.humidity,\n},\n{\n site_name:msg.payload.sensor,\n type:\"humidity\",\n sensor:\"lacrosse\",\n area:msg.payload.area\n}];\n\nmsg1.payload=new_payload;\nreturn msg1;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":405,"y":433,"wires":[["31656493.62196c"]]},{"id":"290d8f4e.3c77f","type":"function","z":"b96d75fb.65f7c8","name":"","func":"var new_payload = {}\nvar msg1 = {};\n\nnew_payload = [{\n value: msg.payload.temperature,\n},\n{\n site_name:msg.payload.sensor,\n type:\"temperature\",\n sensor:\"lacrosse\",\n area:msg.payload.area\n}];\n\nmsg1.payload=new_payload;\nreturn msg1;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":407.5,"y":477,"wires":[["40b10983.d23088","cb4e79fb.6ee0d8"]]},{"id":"bb03fa34.a8be28","type":"mqtt out","z":"b96d75fb.65f7c8","name":"sensor/temp","topic":"","qos":"","retain":"","broker":"489ebd83.1c1664","x":432.5,"y":539,"wires":[]},{"id":"b0e8b046.929f8","type":"Message Counter","z":"b96d75fb.65f7c8","name":"","units":"hours","interval":"1","alignToClock":true,"generator":"internal","x":452.5,"y":602,"wires":[[],[]]},{"id":"8c3c4f60.1df9a","type":"function","z":"b96d75fb.65f7c8","name":"","func":"var new_payload = {}\nvar msg1 = {};\n\nif (msg.payload.humidity>100) return null\n\nnew_payload = [{\n value: msg.payload.battery_low,\n},\n{\n site_name:msg.payload.sensor,\n type:\"battery_low\",\n sensor:\"lacrosse\"\n}];\n\nmsg1.payload=new_payload;\nreturn msg1;","outputs":1,"noerr":0,"x":411,"y":685,"wires":[["382f8915.114246"]]},{"id":"6f38d38c.0789cc","type":"deduplicate","z":"b96d75fb.65f7c8","name":"","keyproperty":"payload.sensor","registryclass":"","noderole":"standalone","expiry":"300","x":302,"y":729,"wires":[["82e19100.9d987"],[]]},{"id":"82e19100.9d987","type":"journal","z":"b96d75fb.65f7c8","name":"Journal","max":"20","persist":false,"persistInterval":"5","storeName":"tempsensors","clocked":true,"clockInterval":"300","keysToAverage":"temperature","topicSuffix":"/journal","x":340.5,"y":829,"wires":[["573c7aab.b46584"],[]]},{"id":"573c7aab.b46584","type":"ui_template","z":"b96d75fb.65f7c8","group":"623c9aa5.9e3a14","name":"","order":1,"width":"","height":"","format":"\n Sensor\n Temp\n Hum\n Dew\n
\n\n {{sensor.sensor| limitTo: 7}}\n {{sensor.temperature| number:'1.0'}}°C\n {{sensor.humidity}}%\n {{sensor.dew| number:'1.1'}}°C\n
\n","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":644.5,"y":836,"wires":[[]]},{"id":"da813241.9e625","type":"serial-port","z":"b96d75fb.65f7c8","serialport":"/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_DEINEADAPTERADRESSE0","serialbaud":"57600","databits":"8","parity":"none","stopbits":"1","waitfor":"","newline":"\n","bin":"false","out":"char","addchar":"false","responsetimeout":""},{"id":"489ebd83.1c1664","type":"mqtt-broker","z":"","name":"mqtt","broker":"mqtt","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"623c9aa5.9e3a14","type":"ui_group","z":"","name":"Default","tab":"d741167d.772088","order":1,"disp":true,"width":"6","collapse":false},{"id":"d741167d.772088","type":"ui_tab","z":"","name":"Home","icon":"dashboard","order":2}]
Guten Tag, gibt es zu dem Thema noch weitere Infos zum Aufbau der Flows ? Leider sieht man ja nur den Inhalt der esrsten Config.
Liebe Grüße
Hallo,
Ich habe einen Export beigelegt. Dieser Flow ist nun schon einige Zeit aktiv und restartet Node Red zuverlässig wenn über 5 Minuten lang keine neuen Temperaturen rein kommen.
Ein Nachteil: Wenn man die Batterien wechselt muss man den Sensor neu konfigurieren.
Inzwischen stelle ich alles um auf Zigbee Mesh Netzwerk, da weit entfernte Technoline Sensoren (im Luftschutzkeller…) doch ab und an Verbindungsprobleme haben.
Vielen Lieben Dank, sie helfen mir damit ungemein weiter.