RFLink Receiving 433MHz RF data in Node-Red

This is a rather flow receiving, transforming and processing RF data sent by the RFLink 433MHz receiver. This flow is only about receiving data, I will cover sending data and more processing separately in the future.

RFLink blog: http://www.rflink.nl/blog2/ 433MHz gateway kit listing: https://www.nodo-shop.nl/en/rflink-gateway/148-rflink-gateway-components.html

There is a details video on this flow here: https://youtu.be/yR_o82oZADQ

[{"id":"a9289d4a.d3a0b","type":"tab","label":"RFLink","disabled":false,"info":""},{"id":"40227d13.412234","type":"serial in","z":"a9289d4a.d3a0b","name":"RFLink","serial":"a8474845.153098","x":110,"y":100,"wires":[["de9526f0.e584a8","cae1aa24.94e848"]]},{"id":"de9526f0.e584a8","type":"debug","z":"a9289d4a.d3a0b","name":"Raw messages","active":false,"console":"false","complete":"payload","x":360,"y":40,"wires":[]},{"id":"5f15bc96.02f164","type":"comment","z":"a9289d4a.d3a0b","name":"Examples","info":"20;B7;Digitech;ID=01bc;TEMP=0060;BAT=OK;\n20;B8;Prologue;ID=9722;TEMP=00e3;HUM=10;\n20;B9;Oregon TempHygro;ID=928F5;TEMP=00d1;HUM=56;HSTATUS=1;BAT=OK;\n20;BA;Tunex;ID=7B02;TEMP=0000;HUM=99;BAT=OK;\n20;BB;Oregon TempHygro;ID=528F1;TEMP=00c6;HUM=59;HSTATUS=0;BAT=OK;\n20;BC;AlectoV3;ID=3099;TEMP=00b3;HUM=61;BAT=OK;\n20;BD;Prologue;ID=9722;TEMP=00e3;HUM=10;\n20;BE;Oregon TempHygro;ID=528F1;TEMP=00c6;HUM=59;HSTATUS=0;BAT=OK;\n20;BF;Prologue;ID=9722;TEMP=00e3;HUM=10;\n20;C0;AlectoV3;ID=3099;TEMP=00b3;HUM=61;BAT=OK;\n20;C1;Tunex;ID=7B02;TEMP=0000;HUM=99;BAT=OK;\n20;C2;Prologue;ID=9722;TEMP=00e3;HUM=10;\n20;C3;AlectoV3;ID=3099;TEMP=00b4;HUM=61;BAT=OK;\n20;C4;Oregon TempHygro;ID=928F5;TEMP=00d1;HUM=56;HSTATUS=1;BAT=OK;\n20;C5;Digitech;ID=01bc;TEMP=0060;BAT=OK;\n20;C6;Tunex;ID=7B02;TEMP=0000;HUM=99;BAT=OK;\n20;C7;AlectoV3;ID=3099;TEMP=00b3;HUM=61;BAT=OK;\n20;C8;Prologue;ID=9722;TEMP=00e2;HUM=10;\n20;C9;AlectoV3;ID=3099;TEMP=00b4;HUM=61;BAT=OK;\n20;CA;Tunex;ID=7B02;TEMP=0000;HUM=99;BAT=OK;\n20;CB;Prologue;ID=9722;TEMP=00e2;HUM=10;\n20;CC;AlectoV3;ID=3099;TEMP=00b3;HUM=61;BAT=OK;\n20;CD;Doorbell;ID=99ff;SWITCH=1;CMD=ON;CHIME=01;\n20;CE;Doorbell;ID=99ff;SWITCH=1;CMD=ON;CHIME=01;\n20;CF;Doorbell;ID=99ff;SWITCH=1;CMD=ON;CHIME=01;\n20;D0;Prologue;ID=9722;TEMP=00e2;HUM=10;\n20;D1;Doorbell;ID=99ff;SWITCH=1;CMD=ON;CHIME=01;\n20;D2;Doorbell;ID=99ff;SWITCH=1;CMD=ON;CHIME=01;\n20;D3;Tunex;ID=7B02;TEMP=0000;HUM=99;BAT=OK;\n20;D4;AlectoV3;ID=3099;TEMP=00b4;HUM=61;BAT=OK;\n20;D5;Oregon TempHygro;ID=928F5;TEMP=00d1;HUM=56;HSTATUS=1;BAT=OK;\n20;D6;Prologue;ID=9722;TEMP=00e2;HUM=10;\n20;D7;Digitech;ID=01bc;TEMP=0060;BAT=OK;\n20;D8;Tunex;ID=7B02;TEMP=0000;HUM=99;BAT=OK;\n20;D9;AlectoV3;ID=3099;TEMP=00b3;HUM=61;BAT=OK;\n20;DA;Prologue;ID=9722;TEMP=00e2;HUM=10;\n20;DB;AlectoV3;ID=3099;TEMP=00b4;HUM=61;BAT=OK;\n20;DC;Tunex;ID=7B02;TEMP=0001;HUM=99;BAT=OK;\n20;DD;Prologue;ID=9722;TEMP=00e2;HUM=10;\n20;DE;AlectoV3;ID=3099;TEMP=00b3;HUM=61;BAT=OK;\n20;DF;Tunex;ID=7B02;TEMP=0001;HUM=99;BAT=OK;\n20;E0;Oregon TempHygro;ID=928F5;TEMP=00d1;HUM=56;HSTATUS=1;BAT=OK;\n20;E1;AlectoV3;ID=3099;TEMP=00b3;HUM=61;BAT=OK;\n20;E2;Prologue;ID=9722;TEMP=00e2;HUM=10;\n","x":90,"y":31,"wires":[]},{"id":"cae1aa24.94e848","type":"function","z":"a9289d4a.d3a0b","name":"Parse message","func":"var msg433 = {};\nmsg.payload = msg.payload.replace(/(\\r\\n|\\n|\\r)/gm,\"\");\nvar parts433 = msg.payload.split(\";\");\n\nmsg433.p1 = parts433[0];\nmsg433.p2 = parts433[1];\nmsg433.name = parts433[2];\nfor (var i=3; i<parts433.length; i++) {\n    var keyvalue = parts433[i].split(\"=\");\n    if (keyvalue.length===2) {\n        msg433[keyvalue[0]] = keyvalue[1];\n    }\n}\n\nmsg.msg433 = msg433;\n\nreturn msg;\n\n/*\n\n// So firstly a generic means of getting incoming items into an object\n\nvar the433 = {};\nmsg.payload = msg.payload.replace(/(\\r\\n|\\n|\\r)/gm,\"\");\nnode.warn(msg.payload);\nvar parts433 = msg.payload.split(\";\");\n\nthe433.p1 = parts433[0];\nthe433.p2 = parts433[1];\nthe433.name = parts433[2];\n\nvar a = 3;\nwhile (a < parts433.length) {\n    var bits433 = parts433[a].split(\"=\");\n    switch (bits433[0]) {\n        case \"ID\": the433.id = bits433[1]; break;\n        case \"SWITCH\": the433.switch = bits433[1]; break;\n        case \"CMD\": the433.cmd = bits433[1]; break;\n        case \"SET_LEVEL\": the433.set_level = parseInt(bits433[1], 10); break;\n        case \"TEMP\": the433.temp = parseInt(bits433[1], 16) / 10; break;\n        case \"HUM\": the433.hum = parseInt(bits433[1], 10); break;\n        case \"BARO\": the433.baro = parseInt(bits433[1], 16); break;\n        case \"HSTATUS\": the433.hstatus = parseInt(bits433[1], 10); break;\n        case \"BFORECAST\": the433.bforecast = parseInt(bits433[1], 10); break;\n        case \"UV\": the433.uv = parseInt(bits433[1], 16); break;\n        case \"LUX\": the433.lux = parseInt(bits433[1], 16); break;\n        case \"BAT\": the433.bat = bits433[1]; break;\n        case \"RAIN\": the433.rain = parseInt(bits433[1], 16) / 10; break;\n        case \"RAIN\": the433.rainrate = parseInt(bits433[1], 16) / 10; break;\n        case \"WINSP\": the433.winsp = parseInt(bits433[1], 16) / 10; break;\n        case \"AWINSP\": the433.awinsp = parseInt(bits433[1], 16) / 10; break;\n        case \"WINGS\": the433.wings = parseInt(bits433[1], 16); break;\n        case \"WINDIR\": the433.windir = parseInt(bits433[1], 10); break;\n        case \"WINCHL\": the433.winchl = parseInt(bits433[1], 16); break;\n        case \"WINTMP\": the433.wintmp = parseInt(bits433[1], 16); break;\n        case \"CHIME\": the433.chime = parseInt(bits433[1], 10); break;\n        case \"SMOKEALERT\": the433.smokealert = bits433[1]; break;\n        case \"PIR\": the433.pir = bits433[1]; break;\n        case \"CO2\": the433.co2 = parseInt(bits433[1], 10); break;\n        case \"SOUND\": the433.sound = parseInt(bits433[1], 10); break;\n        case \"KWATT\": the433.kwatt = parseInt(bits433[1], 16); break;\n        case \"WATT\": the433.watt = parseInt(bits433[1], 16); break;\n        case \"CURRENT\": the433.current = parseInt(bits433[1], 10); break;\n        case \"CURRENT2\": the433.current2 = parseInt(bits433[1], 10); break;\n        case \"CURRENT3\": the433.current3 = parseInt(bits433[1], 10); break;\n        case \"DIST\": the433.dist = parseInt(bits433[1], 10); break;\n        case \"METER\": the433.meter = parseInt(bits433[1], 10); break;\n        case \"VOLT\": the433.volt = parseInt(bits433[1], 10); break;\n        case \"RGBW\": the433.rgbc = parseInt(bits433[1].substring(0, 2), 16);\n            the433.rgbw = parseInt(bits433[1].substring(2, 4), 16); break;\n    }\n    a++;\n}\n\n// SO - the above is general... here is my specific setup for temporarily displaying\n// the Acurite info\nif ((the433.p1 == \"20\") && (the433.name == \"Acurite\") && (the433.id == \"c826\")) {\n    if (typeof the433.temp !== 'undefined') temp = the433.temp;\n    if (typeof the433.hum !== 'undefined') hum = the433.hum;\n    if (typeof the433.bat !== 'undefined') bat = the433.bat;\n    if (typeof the433.rain !== 'undefined') rain = the433.rain;\n    if (typeof the433.winsp !== 'undefined') winsp = the433.winsp;\n    if (typeof the433.windir !== 'undefined') windir = the433.windir;\n\n    node.warn(\"Temperature: \" + temp + \"c\");\n    node.warn(\"Humidity: \" + hum + \"%\");\n    node.warn(\"Battery: \" + bat);\n    node.warn(\"Rain: \" + rain + \"mm\");\n    node.warn(\"Wind Speed: \" + winsp + \"km/h\");\n    node.warn(\"Wind Dir: \" + (windir * 22.5) + \" degrees\");\n}\n\n*/","outputs":1,"noerr":0,"x":340,"y":100,"wires":[["64d75f5a.9425e","5000175f.8cf878"]]},{"id":"1424c5a5.aa05da","type":"debug","z":"a9289d4a.d3a0b","name":"","active":false,"console":"false","complete":"true","x":2330,"y":80,"wires":[]},{"id":"64d75f5a.9425e","type":"function","z":"a9289d4a.d3a0b","name":"TEMP conversion","func":"if (msg.msg433.TEMP!==undefined) {\n    if (parseInt(msg.msg433.TEMP, 16) >= 0x8000) {\n        msg.msg433.TEMP = (parseInt(msg.msg433.TEMP, 16) & 0x7FFF) / 10 * -1;\n    } else {\n        msg.msg433.TEMP = parseInt(msg.msg433.TEMP, 16) / 10;\n    }\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":550,"y":100,"wires":[["da307ed5.6d24f"]]},{"id":"da307ed5.6d24f","type":"function","z":"a9289d4a.d3a0b","name":"HUM conversion","func":"if (msg.msg433.HUM!==undefined) {\n    msg.msg433.HUM = parseInt(msg.msg433.HUM, 10);\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"x":760,"y":100,"wires":[["6b37feb2.a5ee4"]]},{"id":"6b37feb2.a5ee4","type":"function","z":"a9289d4a.d3a0b","name":"ID conversion","func":"if (msg.msg433.ID!==undefined) {\n    msg.msg433.ID = parseInt(msg.msg433.ID, 16);\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"x":960,"y":100,"wires":[["f8289b5e.0a3e38"]]},{"id":"f8289b5e.0a3e38","type":"function","z":"a9289d4a.d3a0b","name":"RAIN conversion","func":"if (msg.msg433.RAIN!==undefined) {\n    msg.msg433.RAIN = parseInt(msg.msg433.RAIN, 16) /10;\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"x":1170,"y":100,"wires":[["1c6f087d.071bd8"]]},{"id":"1c6f087d.071bd8","type":"function","z":"a9289d4a.d3a0b","name":"WINSP conversion","func":"if (msg.msg433.WINSP!==undefined) {\n    msg.msg433.WINSP = parseInt(msg.msg433.WINSP, 16) /10;\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"x":1390,"y":100,"wires":[["330ac16e.ce46fe"]]},{"id":"330ac16e.ce46fe","type":"function","z":"a9289d4a.d3a0b","name":"WINGS conversion","func":"if (msg.msg433.WINGS!==undefined) {\n    msg.msg433.WINGS  = parseInt(msg.msg433.WINGS , 16);\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"x":1610,"y":100,"wires":[["2bfbab0c.82e074"]]},{"id":"2bfbab0c.82e074","type":"function","z":"a9289d4a.d3a0b","name":"SWITCH conversion","func":"if (msg.msg433.SWITCH !==undefined) {\n    msg.msg433.SWITCH   = parseInt(msg.msg433.SWITCH  , 16);\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"x":1860,"y":100,"wires":[["66f86631.b57bb8"]]},{"id":"66f86631.b57bb8","type":"function","z":"a9289d4a.d3a0b","name":"CHIME conversion","func":"if (msg.msg433.CHIME  !==undefined) {\n    msg.msg433.CHIME    = parseInt(msg.msg433.CHIME   , 16);\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"x":2090,"y":100,"wires":[["1424c5a5.aa05da","824eee18.ebeb2"]]},{"id":"824eee18.ebeb2","type":"switch","z":"a9289d4a.d3a0b","name":"Select device","property":"msg433.ID","propertyType":"msg","rules":[{"t":"eq","v":"109","vt":"num"},{"t":"eq","v":"38690","vt":"str"},{"t":"eq","v":"19458","vt":"str"},{"t":"eq","v":"39423","vt":"str"},{"t":"eq","v":"838656","vt":"str"},{"t":"else"}],"checkall":"true","outputs":6,"x":150,"y":220,"wires":[["d6c3cccd.9d922","393e4d81.93a382","d4af10cf.43cfc","42454cd0.30c984","a3cc4c80.967e7","47989dc2.cf2d54","fbc0098f.253928","d5be5b7b.d96408"],["add497dc.b79c68","c58e4b82.706c08","f2730243.8a301","494ffec8.9ead9","d01ac7b4.a6a8d8"],["f576801e.a93c7","e62572d9.9b811","8fce0547.d360c8","5c31c437.13645c"],["9e895b6b.d10718","83b59819.194bb8","e641de4b.b9d65"],["e641de4b.b9d65","9e895b6b.d10718","83b59819.194bb8"],["fb709b5e.6d8818"]],"outputLabels":["Maplin Weather Station","Digoo RS8 Temp Sensor","Digoo Weather Station","Door bell (Door Bell)","Door bell (Eurodomest)","Unhandled"]},{"id":"d6c3cccd.9d922","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":1,"width":0,"height":0,"name":"","label":"Name","format":"{{msg.msg433.name}}","layout":"row-spread","x":670,"y":220,"wires":[]},{"id":"393e4d81.93a382","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":2,"width":0,"height":0,"name":"","label":"Temperature","format":"{{msg.msg433.TEMP}} &deg;C","layout":"row-spread","x":690,"y":260,"wires":[]},{"id":"d4af10cf.43cfc","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":3,"width":0,"height":0,"name":"","label":"Humidity","format":"{{msg.msg433.HUM}} %","layout":"row-spread","x":680,"y":300,"wires":[]},{"id":"42454cd0.30c984","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":4,"width":0,"height":0,"name":"","label":"Wind Speed","format":"{{msg.msg433.WINSP}} km/h","layout":"row-spread","x":690,"y":340,"wires":[]},{"id":"a3cc4c80.967e7","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":5,"width":0,"height":0,"name":"","label":"Wind Gust","format":"{{msg.msg433.WINGS}} km/h","layout":"row-spread","x":690,"y":380,"wires":[]},{"id":"47989dc2.cf2d54","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":6,"width":0,"height":0,"name":"","label":"Rain","format":"{{msg.msg433.RAIN}} mm?","layout":"row-spread","x":670,"y":420,"wires":[]},{"id":"fbc0098f.253928","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":7,"width":0,"height":0,"name":"","label":"Battery","format":"{{msg.msg433.BAT}}","layout":"row-spread","x":680,"y":460,"wires":[]},{"id":"add497dc.b79c68","type":"ui_text","z":"a9289d4a.d3a0b","group":"9d2ab8e.1031948","order":1,"width":0,"height":0,"name":"","label":"Name","format":"{{msg.msg433.name}}","layout":"row-spread","x":650,"y":620,"wires":[]},{"id":"c58e4b82.706c08","type":"ui_text","z":"a9289d4a.d3a0b","group":"9d2ab8e.1031948","order":2,"width":0,"height":0,"name":"","label":"Temperature","format":"{{msg.msg433.TEMP}} &deg;C","layout":"row-spread","x":670,"y":660,"wires":[]},{"id":"f2730243.8a301","type":"ui_text","z":"a9289d4a.d3a0b","group":"9d2ab8e.1031948","order":3,"width":0,"height":0,"name":"","label":"Humidity","format":"{{msg.msg433.HUM}} %","layout":"row-spread","x":660,"y":700,"wires":[]},{"id":"f576801e.a93c7","type":"ui_text","z":"a9289d4a.d3a0b","group":"d67fd8d2.672158","order":1,"width":0,"height":0,"name":"","label":"Name","format":"{{msg.msg433.name}}","layout":"row-spread","x":650,"y":920,"wires":[]},{"id":"e62572d9.9b811","type":"ui_text","z":"a9289d4a.d3a0b","group":"d67fd8d2.672158","order":2,"width":0,"height":0,"name":"","label":"Temperature","format":"{{msg.msg433.TEMP}} &deg;C","layout":"row-spread","x":670,"y":960,"wires":[]},{"id":"8fce0547.d360c8","type":"ui_text","z":"a9289d4a.d3a0b","group":"d67fd8d2.672158","order":3,"width":0,"height":0,"name":"","label":"Humidity","format":"{{msg.msg433.HUM}} %","layout":"row-spread","x":660,"y":1000,"wires":[]},{"id":"494ffec8.9ead9","type":"ui_text","z":"a9289d4a.d3a0b","group":"9d2ab8e.1031948","order":4,"width":0,"height":0,"name":"","label":"Battery","format":"{{msg.msg433.BAT}}","layout":"row-spread","x":660,"y":740,"wires":[]},{"id":"fb709b5e.6d8818","type":"function","z":"a9289d4a.d3a0b","name":"New devices","func":"// Get the previously stored commands\nvar temp = context.get(\"commands\");\nif (temp===undefined) {\n    temp = [];\n}\n\nif (msg.topic===\"--ClearList--\") {\n    // Clear the current list\n    temp = [];\n} else {\n    // Add the new one \n    var found = false;\n    for (var i=0; i<temp.length; i++) {\n        if (temp[i].id===msg.msg433.ID) {\n            // device already registered, update the existing entry\n            found = true;\n            temp[i].name = msg.msg433.name;\n            temp[i].full = msg.payload;\n        }\n    }\n    if (!found) {\n        // this is a new device, add to the list\n        temp.push({id: msg.msg433.ID, name: msg.msg433.name, full: msg.payload});\n    }\n}\ncontext.set(\"commands\",temp);\n\n\n//Format the output\nmsg.payload = \"\";\nfor (var i=0; i<temp.length; i++) {\n    msg.payload += \"ID=\"+temp[i].id +\" | Name=\"+temp[i].name+\" | Full=\"+temp[i].full + \"<br/>\";\n}\nreturn msg;","outputs":1,"noerr":0,"x":430,"y":1360,"wires":[["79a97ebe.57b2b"]]},{"id":"79a97ebe.57b2b","type":"ui_template","z":"a9289d4a.d3a0b","group":"93d2cb96.91ea98","name":"Log output","order":2,"width":0,"height":0,"format":"<div ng-bind-html=\"msg.payload\" height=\"600\" style=\"height: 600px;\"><br/></div>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":890,"y":1360,"wires":[[]]},{"id":"3618cd71.356912","type":"ui_button","z":"a9289d4a.d3a0b","name":"","group":"93d2cb96.91ea98","order":1,"width":0,"height":0,"passthru":false,"label":"Clear List","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"--ClearList--","x":160,"y":1360,"wires":[["fb709b5e.6d8818"]]},{"id":"d5be5b7b.d96408","type":"function","z":"a9289d4a.d3a0b","name":"Last Update","func":"var temp = context.get(\"last_update\");\nvar current = new Date();\n\nif (msg.topic!==\"update\") {\n    \n    if (temp!== undefined && temp!==null) {\n        msg.payload = current.getTime() - temp;\n        context.set(\"last_update\",current.getTime());\n    } else {\n        msg.payload = \"\";\n        context.set(\"last_update\",current.getTime());\n    }    \n    \n    // Update the status with current timestamp\n    var now = new Date();\n    var yyyy = now.getFullYear();\n    var mm = now.getMonth() < 9 ? \"0\" + (now.getMonth() + 1) : (now.getMonth() + 1); // getMonth() is zero-based\n    var dd  = now.getDate() < 10 ? \"0\" + now.getDate() : now.getDate();\n    var hh = now.getHours() < 10 ? \"0\" + now.getHours() : now.getHours();\n    var mmm  = now.getMinutes() < 10 ? \"0\" + now.getMinutes() : now.getMinutes();\n    var ss  = now.getSeconds() < 10 ? \"0\" + now.getSeconds() : now.getSeconds();\n    node.status({fill:\"blue\",shape:\"ring\",text:\"Last update: \"+dd + \".\" + mm + \".\" + yyyy + \" \" + hh + \":\" + mmm + \":\" + ss});\n    \n    msg.formattedtime = dd + \".\" + mm + \".\" + yyyy + \" \" + hh + \":\" + mmm + \":\" + ss;\n}\n\nif (temp!==undefined) {\n    current = current - temp;\n    current = Math.floor(current/1000);\n    msg.secsincelast = current;\n    var minute = Math.floor(current/60);\n    var hour = Math.floor(minute/60);\n    var day = Math.floor(hour/24);\n    if (current>=24*60*60) {\n        msg.lastupdate = \"Last update \" + day + \" days, \" + hour%24 + \" hours, \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else if (current>=60*60) {\n        msg.lastupdate = \"Last update \" + hour%24 + \" hours, \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else if (current>=60) {\n        msg.lastupdate = \"Last update \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else {\n        msg.lastupdate = \"Last update \" + current%60 + \" seconds ago\";\n    }\n}\n\n\nif (msg.topic===\"update\") {\n    return [null,msg];\n} else {\n    return [msg,msg];\n}\n\n\n","outputs":"2","noerr":0,"x":690,"y":500,"wires":[["ffe1548b.0c5c18"],["64740a65.0c42a4","fbb50675.c92588"]]},{"id":"24d4bf33.19205","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"update","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":150,"y":500,"wires":[["d5be5b7b.d96408"]]},{"id":"ffe1548b.0c5c18","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":8,"width":0,"height":0,"name":"","label":"Last Update","format":"{{msg.formattedtime}}","layout":"row-spread","x":971.0000228881836,"y":498.99999237060547,"wires":[]},{"id":"64740a65.0c42a4","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":9,"width":0,"height":0,"name":"Seconds since last update","label":"","format":"{{msg.lastupdate}}","layout":"row-spread","x":1010,"y":540,"wires":[]},{"id":"d01ac7b4.a6a8d8","type":"function","z":"a9289d4a.d3a0b","name":"Last Update","func":"var temp = context.get(\"last_update\");\nvar current = new Date();\n\nif (msg.topic!==\"update\") {\n    \n    if (temp!== undefined && temp!==null) {\n        msg.payload = current.getTime() - temp;\n        context.set(\"last_update\",current.getTime());\n    } else {\n        msg.payload = \"\";\n        context.set(\"last_update\",current.getTime());\n    }    \n    \n    // Update the status with current timestamp\n    var now = new Date();\n    var yyyy = now.getFullYear();\n    var mm = now.getMonth() < 9 ? \"0\" + (now.getMonth() + 1) : (now.getMonth() + 1); // getMonth() is zero-based\n    var dd  = now.getDate() < 10 ? \"0\" + now.getDate() : now.getDate();\n    var hh = now.getHours() < 10 ? \"0\" + now.getHours() : now.getHours();\n    var mmm  = now.getMinutes() < 10 ? \"0\" + now.getMinutes() : now.getMinutes();\n    var ss  = now.getSeconds() < 10 ? \"0\" + now.getSeconds() : now.getSeconds();\n    node.status({fill:\"blue\",shape:\"ring\",text:\"Last update: \"+dd + \".\" + mm + \".\" + yyyy + \" \" + hh + \":\" + mmm + \":\" + ss});\n    \n    msg.formattedtime = dd + \".\" + mm + \".\" + yyyy + \" \" + hh + \":\" + mmm + \":\" + ss;\n}\n\nif (temp!==undefined) {\n    current = current - temp;\n    current = Math.floor(current/1000);\n    msg.secsincelast = current;\n    var minute = Math.floor(current/60);\n    var hour = Math.floor(minute/60);\n    var day = Math.floor(hour/24);\n    if (current>=24*60*60) {\n        msg.lastupdate = \"Last update \" + day + \" days, \" + hour%24 + \" hours, \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else if (current>=60*60) {\n        msg.lastupdate = \"Last update \" + hour%24 + \" hours, \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else if (current>=60) {\n        msg.lastupdate = \"Last update \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else {\n        msg.lastupdate = \"Last update \" + current%60 + \" seconds ago\";\n    }\n}\n\n\nif (msg.topic===\"update\") {\n    return [null,msg];\n} else {\n    return [msg,msg];\n}\n\n\n","outputs":"2","noerr":0,"x":670,"y":780,"wires":[["bc21b81.5594c48"],["ca285bb4.359c98","c47566b3.377df8"]]},{"id":"17e234f6.154d5b","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"update","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":130,"y":780,"wires":[["d01ac7b4.a6a8d8"]]},{"id":"bc21b81.5594c48","type":"ui_text","z":"a9289d4a.d3a0b","group":"9d2ab8e.1031948","order":5,"width":0,"height":0,"name":"","label":"Last Update","format":"{{msg.formattedtime}}","layout":"row-spread","x":951.0000228881836,"y":778.9999923706055,"wires":[]},{"id":"ca285bb4.359c98","type":"ui_text","z":"a9289d4a.d3a0b","group":"9d2ab8e.1031948","order":6,"width":0,"height":0,"name":"Seconds since last update","label":"","format":"{{msg.lastupdate}}","layout":"row-spread","x":990,"y":820,"wires":[]},{"id":"5c31c437.13645c","type":"function","z":"a9289d4a.d3a0b","name":"Last Update","func":"var temp = context.get(\"last_update\");\nvar current = new Date();\n\nif (msg.topic!==\"update\") {\n    \n    if (temp!== undefined && temp!==null) {\n        msg.payload = current.getTime() - temp;\n        context.set(\"last_update\",current.getTime());\n    } else {\n        msg.payload = \"\";\n        context.set(\"last_update\",current.getTime());\n    }    \n    \n    // Update the status with current timestamp\n    var now = new Date();\n    var yyyy = now.getFullYear();\n    var mm = now.getMonth() < 9 ? \"0\" + (now.getMonth() + 1) : (now.getMonth() + 1); // getMonth() is zero-based\n    var dd  = now.getDate() < 10 ? \"0\" + now.getDate() : now.getDate();\n    var hh = now.getHours() < 10 ? \"0\" + now.getHours() : now.getHours();\n    var mmm  = now.getMinutes() < 10 ? \"0\" + now.getMinutes() : now.getMinutes();\n    var ss  = now.getSeconds() < 10 ? \"0\" + now.getSeconds() : now.getSeconds();\n    node.status({fill:\"blue\",shape:\"ring\",text:\"Last update: \"+dd + \".\" + mm + \".\" + yyyy + \" \" + hh + \":\" + mmm + \":\" + ss});\n    \n    msg.formattedtime = dd + \".\" + mm + \".\" + yyyy + \" \" + hh + \":\" + mmm + \":\" + ss;\n}\n\nif (temp!==undefined) {\n    current = current - temp;\n    current = Math.floor(current/1000);\n    msg.secsincelast = current;\n    var minute = Math.floor(current/60);\n    var hour = Math.floor(minute/60);\n    var day = Math.floor(hour/24);\n    if (current>=24*60*60) {\n        msg.lastupdate = \"Last update \" + day + \" days, \" + hour%24 + \" hours, \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else if (current>=60*60) {\n        msg.lastupdate = \"Last update \" + hour%24 + \" hours, \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else if (current>=60) {\n        msg.lastupdate = \"Last update \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else {\n        msg.lastupdate = \"Last update \" + current%60 + \" seconds ago\";\n    }\n}\n\n\nif (msg.topic===\"update\") {\n    return [null,msg];\n} else {\n    return [msg,msg];\n}\n\n\n","outputs":"2","noerr":0,"x":670,"y":1040,"wires":[["5c420d6e.2a1b14"],["2444a05d.e2e1a","45ecf07d.d5b5c"]]},{"id":"82272012.ba316","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"update","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":130,"y":1040,"wires":[["5c31c437.13645c"]]},{"id":"5c420d6e.2a1b14","type":"ui_text","z":"a9289d4a.d3a0b","group":"d67fd8d2.672158","order":4,"width":0,"height":0,"name":"","label":"Last Update","format":"{{msg.formattedtime}}","layout":"row-spread","x":950,"y":1040,"wires":[]},{"id":"2444a05d.e2e1a","type":"ui_text","z":"a9289d4a.d3a0b","group":"d67fd8d2.672158","order":5,"width":0,"height":0,"name":"Seconds since last update","label":"","format":"{{msg.lastupdate}}","layout":"row-spread","x":988.9999771118164,"y":1081.0000076293945,"wires":[]},{"id":"83b59819.194bb8","type":"function","z":"a9289d4a.d3a0b","name":"Last Update","func":"var temp = context.get(\"last_update\");\nvar current = new Date();\n\nif (msg.topic!==\"update\") {\n    \n    if (temp!== undefined && temp!==null) {\n        msg.payload = current.getTime() - temp;\n        context.set(\"last_update\",current.getTime());\n    } else {\n        msg.payload = \"\";\n        context.set(\"last_update\",current.getTime());\n    }    \n    \n    // Update the status with current timestamp\n    var now = new Date();\n    var yyyy = now.getFullYear();\n    var mm = now.getMonth() < 9 ? \"0\" + (now.getMonth() + 1) : (now.getMonth() + 1); // getMonth() is zero-based\n    var dd  = now.getDate() < 10 ? \"0\" + now.getDate() : now.getDate();\n    var hh = now.getHours() < 10 ? \"0\" + now.getHours() : now.getHours();\n    var mmm  = now.getMinutes() < 10 ? \"0\" + now.getMinutes() : now.getMinutes();\n    var ss  = now.getSeconds() < 10 ? \"0\" + now.getSeconds() : now.getSeconds();\n    node.status({fill:\"blue\",shape:\"ring\",text:\"Last update: \"+dd + \".\" + mm + \".\" + yyyy + \" \" + hh + \":\" + mmm + \":\" + ss});\n    \n    msg.formattedtime = dd + \".\" + mm + \".\" + yyyy + \" \" + hh + \":\" + mmm + \":\" + ss;\n}\n\nif (temp!==undefined) {\n    current = current - temp;\n    current = Math.floor(current/1000);\n    msg.secsincelast = current;\n    var minute = Math.floor(current/60);\n    var hour = Math.floor(minute/60);\n    var day = Math.floor(hour/24);\n    if (current>=24*60*60) {\n        msg.lastupdate = \"Last update \" + day + \" days, \" + hour%24 + \" hours, \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else if (current>=60*60) {\n        msg.lastupdate = \"Last update \" + hour%24 + \" hours, \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else if (current>=60) {\n        msg.lastupdate = \"Last update \" + minute%60 + \" minutes, \" + current%60 + \" seconds ago\";\n    } else {\n        msg.lastupdate = \"Last update \" + current%60 + \" seconds ago\";\n    }\n}\n\n\nif (msg.topic===\"update\") {\n    return [null,msg];\n} else {\n    return [msg,msg];\n}\n\n\n","outputs":"2","noerr":0,"x":670,"y":1260,"wires":[["f107f5f8.9b45e8"],["eaf8ef24.59942"]]},{"id":"6ece8c7d.3769e4","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"update","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":130,"y":1220,"wires":[["83b59819.194bb8"]]},{"id":"f107f5f8.9b45e8","type":"ui_text","z":"a9289d4a.d3a0b","group":"8db8f1a7.fbda4","order":2,"width":0,"height":0,"name":"","label":"Last Update","format":"{{msg.formattedtime}}","layout":"row-spread","x":950,"y":1260,"wires":[]},{"id":"eaf8ef24.59942","type":"ui_text","z":"a9289d4a.d3a0b","group":"8db8f1a7.fbda4","order":3,"width":0,"height":0,"name":"Seconds since last update","label":"","format":"{{msg.lastupdate}}","layout":"row-spread","x":988.9999771118164,"y":1301.0000076293945,"wires":[]},{"id":"64cf3767.db7e28","type":"googlehome-notify","z":"a9289d4a.d3a0b","server":"4bea401f.bb33b","name":"Google Home","x":1140,"y":1220,"wires":[]},{"id":"6e6f22b3.fbc55c","type":"change","z":"a9289d4a.d3a0b","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"There is someone at the door","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":920,"y":1220,"wires":[["64cf3767.db7e28"]]},{"id":"9e895b6b.d10718","type":"function","z":"a9289d4a.d3a0b","name":"30 second debounce","func":"var temp = context.get(\"last_update\");\nvar current = new Date();\n\nif (temp===undefined) {\n    // If this is the first event store time and forward\n    context.set(\"last_update\",current.getTime());\n    return msg;\n} else {\n    if (current.getTime() - temp>30*1000) {\n        // If the time since the last event more than 30 seconds, forward\n        context.set(\"last_update\",current.getTime());\n        return msg;\n    }\n}    \n\n    \n\n","outputs":"1","noerr":0,"x":700,"y":1220,"wires":[["6e6f22b3.fbc55c","5469911b.e982c"]]},{"id":"5469911b.e982c","type":"link out","z":"a9289d4a.d3a0b","name":"","links":["64328069.048da","b44b2f2b.f23be"],"x":932.5,"y":1177.5,"wires":[]},{"id":"e641de4b.b9d65","type":"ui_text","z":"a9289d4a.d3a0b","group":"8db8f1a7.fbda4","order":1,"width":0,"height":0,"name":"","label":"Name","format":"{{msg.msg433.name}}","layout":"row-spread","x":650,"y":1180,"wires":[]},{"id":"fbb50675.c92588","type":"function","z":"a9289d4a.d3a0b","name":"System Diag","func":"var devicename = \"Maplin_weather_state\";    // This is used as the name of the global variable\nvar devicetext = \"Maplin weather station\";  // This will go into system messages\nvar systemid = 30;                          // ID of the system\n\n// Set a default value\nif (global.get(devicename)===undefined) {\n    global.set(devicename,0);\n}\n\nif (msg.secsincelast<10) {\n    // There is a recent update from the sensor\n    if ((global.get(devicename)!==1)&&(global.get(devicename)!==60)) {\n        global.set(devicename,1);\n        msg.payload = devicetext + \" is up\";\n        msg.system = systemid; // System id, use 1 for Dummy\n        msg.state = 1; // specify if the message is to change system status\n        msg.severity = 0; // 0: information, 1: warning, 2: error\n        node.status({fill:\"green\",shape:\"ring\",text:\"Online\"});\n    }  \n}\n\nif (msg.msg433!==undefined) {\n    if (msg.msg433.BAT!==undefined) {\n        if (msg.msg433.BAT===\"LOW\") {\n            if (global.get(devicename)!==60) {\n                global.set(devicename,60);\n                msg.payload = devicetext + \" battery is low\";\n                msg.system = systemid; // System id, use 1 for Dummy\n                msg.state = 60; // specify if the message is to change system status\n                msg.severity = 1; // 0: information, 1: warning, 2: error\n                node.status({fill:\"yellow\",shape:\"ring\",text:\"Low battery\"});\n            }\n        }                \n        if (msg.msg433.BAT===\"OK\") {\n            if (global.get(devicename)===60) {\n                global.set(devicename,1);\n                msg.payload = devicetext + \" battery is OK\";\n                msg.system = systemid; // System id, use 1 for Dummy\n                msg.state = 1; // specify if the message is to change system status\n                msg.severity = 0; // 0: information, 1: warning, 2: error\n                node.status({fill:\"green\",shape:\"ring\",text:\"Online\"});\n            }\n        }  \n    }\n}\n\nif (msg.secsincelast>10*60) {\n    // There is a recent update from the sensor\n    if (global.get(devicename)!==99) {\n        global.set(devicename,99);\n        msg.payload = devicetext + \" is not transmitting\";\n        msg.system = systemid; // System id, use 1 for Dummy\n        msg.state = 99; // specify if the message is to change system status\n        msg.severity = 1; // 0: information, 1: warning, 2: error\n        node.status({fill:\"grey\",shape:\"ring\",text:\"Offline\"});\n    }  \n}\n\nif (msg.system===systemid) {\n    return msg;\n}","outputs":1,"noerr":0,"x":970,"y":580,"wires":[["97e50242.4d8f2"]]},{"id":"97e50242.4d8f2","type":"link out","z":"a9289d4a.d3a0b","name":"","links":["13e089a7.73cb46"],"x":1155,"y":580,"wires":[]},{"id":"c47566b3.377df8","type":"function","z":"a9289d4a.d3a0b","name":"System Diag","func":"var devicename = \"Digoo_weather_state\";    // This is used as the name of the global variable\nvar devicetext = \"Digoo weather sensor\";  // This will go into system messages\nvar systemid = 31;                          // ID of the system\n\n// Set a default value\nif (global.get(devicename)===undefined) {\n    global.set(devicename,0);\n}\n\nif (msg.secsincelast<10) {\n    // There is a recent update from the sensor\n    if ((global.get(devicename)!==1)&&(global.get(devicename)!==60)) {\n        global.set(devicename,1);\n        msg.payload = devicetext + \" is up\";\n        msg.system = systemid; // System id, use 1 for Dummy\n        msg.state = 1; // specify if the message is to change system status\n        msg.severity = 0; // 0: information, 1: warning, 2: error\n        node.status({fill:\"green\",shape:\"ring\",text:\"Online\"});\n    }  \n}\n\nif (msg.msg433!==undefined) {\n    if (msg.msg433.BAT!==undefined) {\n        if (msg.msg433.BAT===\"LOW\") {\n            if (global.get(devicename)!==60) {\n                global.set(devicename,60);\n                msg.payload = devicetext + \" battery is low\";\n                msg.system = systemid; // System id, use 1 for Dummy\n                msg.state = 60; // specify if the message is to change system status\n                msg.severity = 1; // 0: information, 1: warning, 2: error\n                node.status({fill:\"yellow\",shape:\"ring\",text:\"Low battery\"});\n            }\n        }                \n        if (msg.msg433.BAT===\"OK\") {\n            if (global.get(devicename)===60) {\n                global.set(devicename,1);\n                msg.payload = devicetext + \" battery is OK\";\n                msg.system = systemid; // System id, use 1 for Dummy\n                msg.state = 1; // specify if the message is to change system status\n                msg.severity = 0; // 0: information, 1: warning, 2: error\n                node.status({fill:\"green\",shape:\"ring\",text:\"Online\"});\n            }\n        }  \n    }\n}\n\nif (msg.secsincelast>10*60) {\n    // There is a recent update from the sensor\n    if (global.get(devicename)!==99) {\n        global.set(devicename,99);\n        msg.payload = devicetext + \" is not transmitting\";\n        msg.system = systemid; // System id, use 1 for Dummy\n        msg.state = 99; // specify if the message is to change system status\n        msg.severity = 1; // 0: information, 1: warning, 2: error\n        node.status({fill:\"grey\",shape:\"ring\",text:\"Offline\"});\n    }  \n}\n\nif (msg.system===systemid) {\n    return msg;\n}","outputs":1,"noerr":0,"x":950,"y":860,"wires":[["ecdb8eb5.d251a"]]},{"id":"ecdb8eb5.d251a","type":"link out","z":"a9289d4a.d3a0b","name":"","links":["13e089a7.73cb46"],"x":1135,"y":860,"wires":[]},{"id":"45ecf07d.d5b5c","type":"function","z":"a9289d4a.d3a0b","name":"System Diag","func":"var devicename = \"Digoo_sensor_state\";    // This is used as the name of the global variable\nvar devicetext = \"Digoo temperature sensor\";  // This will go into system messages\nvar systemid = 32;                          // ID of the system\n\n// Set a default value\nif (global.get(devicename)===undefined) {\n    global.set(devicename,0);\n}\n\nif (msg.secsincelast<10) {\n    // There is a recent update from the sensor\n    if ((global.get(devicename)!==1)&&(global.get(devicename)!==60)) {\n        global.set(devicename,1);\n        msg.payload = devicetext + \" is up\";\n        msg.system = systemid; // System id, use 1 for Dummy\n        msg.state = 1; // specify if the message is to change system status\n        msg.severity = 0; // 0: information, 1: warning, 2: error\n        node.status({fill:\"green\",shape:\"ring\",text:\"Online\"});\n    }  \n}\n\nif (msg.msg433!==undefined) {\n    if (msg.msg433.BAT!==undefined) {\n        if (msg.msg433.BAT===\"LOW\") {\n            if (global.get(devicename)!==60) {\n                global.set(devicename,60);\n                msg.payload = devicetext + \" battery is low\";\n                msg.system = systemid; // System id, use 1 for Dummy\n                msg.state = 60; // specify if the message is to change system status\n                msg.severity = 1; // 0: information, 1: warning, 2: error\n                node.status({fill:\"yellow\",shape:\"ring\",text:\"Low battery\"});\n            }\n        }                \n        if (msg.msg433.BAT===\"OK\") {\n            if (global.get(devicename)===60) {\n                global.set(devicename,1);\n                msg.payload = devicetext + \" battery is OK\";\n                msg.system = systemid; // System id, use 1 for Dummy\n                msg.state = 1; // specify if the message is to change system status\n                msg.severity = 0; // 0: information, 1: warning, 2: error\n                node.status({fill:\"green\",shape:\"ring\",text:\"Online\"});\n            }\n        }  \n    }\n}\n\nif (msg.secsincelast>10*60) {\n    // There is a recent update from the sensor\n    if (global.get(devicename)!==99) {\n        global.set(devicename,99);\n        msg.payload = devicetext + \" is not transmitting\";\n        msg.system = systemid; // System id, use 1 for Dummy\n        msg.state = 99; // specify if the message is to change system status\n        msg.severity = 1; // 0: information, 1: warning, 2: error\n        node.status({fill:\"grey\",shape:\"ring\",text:\"Offline\"});\n    }  \n}\n\nif (msg.system===systemid) {\n    return msg;\n}","outputs":1,"noerr":0,"x":950,"y":1120,"wires":[["124a58bd.5fe997"]]},{"id":"124a58bd.5fe997","type":"link out","z":"a9289d4a.d3a0b","name":"","links":["13e089a7.73cb46"],"x":1135,"y":1120,"wires":[]},{"id":"5000175f.8cf878","type":"debug","z":"a9289d4a.d3a0b","name":"","active":false,"console":"false","complete":"true","x":490,"y":140,"wires":[]},{"id":"a8474845.153098","type":"serial-port","z":"","serialport":"/dev/ttyUSB1","serialbaud":"57600","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":false},{"id":"d5bfb431.21f7c8","type":"ui_group","z":"","name":"Maplin Weather Station","tab":"7489c36d.a74f5c","order":1,"disp":true,"width":"6"},{"id":"9d2ab8e.1031948","type":"ui_group","z":"","name":"Digoo RS8 Sensor","tab":"7489c36d.a74f5c","order":2,"disp":true,"width":"6"},{"id":"d67fd8d2.672158","type":"ui_group","z":"","name":"Digoo Weather Station","tab":"7489c36d.a74f5c","order":3,"disp":true,"width":"6"},{"id":"93d2cb96.91ea98","type":"ui_group","z":"","name":"New Devices","tab":"7489c36d.a74f5c","order":5,"disp":true,"width":"18"},{"id":"8db8f1a7.fbda4","type":"ui_group","z":"","name":"Door Bell","tab":"7489c36d.a74f5c","order":4,"disp":true,"width":"6"},{"id":"4bea401f.bb33b","type":"googlehome-config-node","z":"","ipaddress":"192.168.1.109","language":"en"},{"id":"7489c36d.a74f5c","type":"ui_tab","z":"","name":"RFLink","icon":"settings_remote","order":19}]

Flow Info

Created 6 years, 7 months ago
Rating: not yet rated

Owner

Actions

Rate:

Node Types

Core
  • change (x1)
  • comment (x1)
  • debug (x3)
  • function (x18)
  • inject (x4)
  • link out (x4)
  • switch (x1)
Other
  • googlehome-config-node (x1)
  • googlehome-notify (x1)
  • serial in (x1)
  • serial-port (x1)
  • tab (x1)
  • ui_button (x1)
  • ui_group (x5)
  • ui_tab (x1)
  • ui_template (x1)
  • ui_text (x23)

Tags

  • rflink
  • 433Mhz
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option