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.

JeeLink

Die Konfiguration ist fix hinterlegt im ersten Node.

Temperatursensoren

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}]

3 thoughts on “Technoline Temperatursensoren

  • Kimbo

    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.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert