Rainfall, usage, consumption measurement

This is a flow in which I calculate hourly, daily, weekly rainfall data from rain gauge data received from my weather station. The same flow can be used to calculate usage, consumption data for any other continuously increasing data like meter readings (water, gas, electricity).

Please have a look at my video on this flow in which I explain how this flow works, and how to adopt it: https://youtu.be/mWx5aa1ri2E

[{"id":"c4f163ca.1c882","type":"function","z":"a9289d4a.d3a0b","name":"Rain metering","func":"var global_name = \"rainstat\";   // Name of the global variable\nvar hourlysize = 24;            // Number of hourly stat to collect (24 for the last 24 hours)\nvar dailysize = 10;             // Number of daily stat to collect\nvar weeklysize = 10;             // Number of weekly stat to collect\nvar current = new Date();\n\nvar rainstat = global.get(global_name);\nif (rainstat===undefined) {\n    rainstat = {};\n}\n\n// If the message is coming from sensor, save the current value\nif (msg.topic===\"rflink\") {\n    if (msg.msg433.RAIN!==undefined) {\n        context.set(\"RAIN\",msg.msg433.RAIN);\n        msg.topic=\"reading\";\n    }\n}\n\n// Do not process stats until we have a valid reading\nif (context.get(\"RAIN\")!==undefined) {\n\n    // Update the hourly stats\n    if (msg.topic===\"hourly\") {\n        msg.topic=\"hourly\";\n        // First update the historical readings\n        if (rainstat.hourlyvalues===undefined) {\n            // this is the first reading, create the array first\n            rainstat.hourlyvalues = [];\n            rainstat.hourlyvalues.push({epoch: current.getTime(), reading:context.get(\"RAIN\")});\n        } else {\n            if (rainstat.hourlyvalues.length<hourlysize-1) {\n                // there is not enough history collected yet, add to the array\n                rainstat.hourlyvalues.push({epoch: current.getTime(), reading:context.get(\"RAIN\")});\n            } else {\n                // the array is full need to shift values\n                for (var i=1;i<rainstat.hourlyvalues.length;i++) {\n                    rainstat.hourlyvalues[i-1]=rainstat.hourlyvalues[i];\n                }\n                // add the current value to the end of the array\n                rainstat.hourlyvalues[hourlysize-1]={epoch: current.getTime(), reading:context.get(\"RAIN\")};\n            }\n        }\n        \n        // Calculate the delta values\n        rainstat.hourlydelta = [];\n        if (rainstat.hourlyvalues.length>1) {\n            // We need at least two readings\n            for (var i=1;i<rainstat.hourlyvalues.length;i++) {\n                var delta = Math.round((rainstat.hourlyvalues[i].reading - rainstat.hourlyvalues[i-1].reading)*10)/10;\n                if (delta<0) {\n                    // If for any reason readings from the sensor reset use delta as zero instead of a high negative value\n                    delta = 0;\n                }\n                rainstat.hourlydelta.push({epoch: rainstat.hourlyvalues[i].epoch, delta:delta});\n            }\n        }\n        \n    }\n   \n    // Update the daily stats\n    if (msg.topic===\"daily\") {\n        msg.topic=\"daily\";\n        // First update the historical readings\n        if (rainstat.dailyvalues===undefined) {\n            // this is the first reading, create the array first\n            rainstat.dailyvalues = [];\n            rainstat.dailyvalues.push({epoch: current.getTime(), reading:context.get(\"RAIN\")});\n        } else {\n            if (rainstat.dailyvalues.length<dailysize-1) {\n                // there is not enough history collected yet, add to the array\n                rainstat.dailyvalues.push({epoch: current.getTime(), reading:context.get(\"RAIN\")});\n            } else {\n                // the array is full need to shift values\n                for (var i=1;i<rainstat.dailyvalues.length;i++) {\n                    rainstat.dailyvalues[i-1]=rainstat.dailyvalues[i];\n                }\n                // add the current value to the end of the array\n                rainstat.dailyvalues[dailysize-1]={epoch: current.getTime(), reading:context.get(\"RAIN\")};\n            }\n        }\n        \n        // Calculate the delta values\n        rainstat.dailydelta = [];\n        if (rainstat.dailyvalues.length>1) {\n            // We need at least two readings\n            for (var i=1;i<rainstat.dailyvalues.length;i++) {\n                var delta = Math.round((rainstat.dailyvalues[i].reading - rainstat.dailyvalues[i-1].reading)*10)/10;\n                if (delta<0) {\n                    // If for any reason readings from the sensor reset use delta as zero instead of a high negative value\n                    delta = 0;\n                }\n                rainstat.dailydelta.push({epoch: rainstat.dailyvalues[i].epoch, delta:delta});\n            }\n        }\n        \n    }\n    \n    // Update the weekly stats\n    if (msg.topic===\"weekly\") {\n        msg.topic=\"weekly\";\n        // First update the historical readings\n        if (rainstat.weeklyvalues===undefined) {\n            // this is the first reading, create the array first\n            rainstat.weeklyvalues = [];\n            rainstat.weeklyvalues.push({epoch: current.getTime(), reading:context.get(\"RAIN\")});\n        } else {\n            if (rainstat.weeklyvalues.length<weeklysize-1) {\n                // there is not enough history collected yet, add to the array\n                rainstat.weeklyvalues.push({epoch: current.getTime(), reading:context.get(\"RAIN\")});\n            } else {\n                // the array is full need to shift values\n                for (var i=1;i<rainstat.weeklyvalues.length;i++) {\n                    rainstat.weeklyvalues[i-1]=rainstat.weeklyvalues[i];\n                }\n                // add the current value to the end of the array\n                rainstat.weeklyvalues[weeklysize-1]={epoch: current.getTime(), reading:context.get(\"RAIN\")};\n            }\n        }\n        \n        // Calculate the delta values\n        rainstat.weeklydelta = [];\n        if (rainstat.weeklyvalues.length>1) {\n            // We need at least two readings\n            for (var i=1;i<rainstat.weeklyvalues.length;i++) {\n                var delta = Math.round((rainstat.weeklyvalues[i].reading - rainstat.weeklyvalues[i-1].reading)*10)/10;\n                if (delta<0) {\n                    // If for any reason readings from the sensor reset use delta as zero instead of a high negative value\n                    delta = 0;\n                }\n                rainstat.weeklydelta.push({epoch: rainstat.weeklyvalues[i].epoch, delta:delta});\n            }\n        }\n        \n    }\n\n\n    // This week rainfall calculation\n    if (rainstat.weeklyvalues!==undefined) {\n        if (rainstat.weeklyvalues.length>0) {\n            rainstat.thisweek = Math.round((context.get(\"RAIN\") - rainstat.weeklyvalues[rainstat.weeklyvalues.length-1].reading)*10)/10;\n            if (rainstat.thisweek<0) {\n                rainstat.thisweek = 0.0;\n            }\n        } else {\n            rainstat.thisweek = 0.0;\n        }\n    }\n    // Today rainfall calculation\n    if (rainstat.dailyvalues!==undefined) {\n        if (rainstat.dailyvalues.length>0) {\n            rainstat.today = Math.round((context.get(\"RAIN\") - rainstat.dailyvalues[rainstat.dailyvalues.length-1].reading)*10)/10;\n            if (rainstat.today<0) {\n                rainstat.today = 0.0;\n            }\n        } else {\n            rainstat.today = 0.0;\n        }\n    }\n    // This hour rainfall calculation\n    if (rainstat.hourlyvalues!==undefined) {\n        if (rainstat.hourlyvalues.length>0) {\n            rainstat.thishour = Math.round((context.get(\"RAIN\") - rainstat.hourlyvalues[rainstat.hourlyvalues.length-1].reading)*10)/10;\n            if (rainstat.thishour<0) {\n                rainstat.thishour = 0.0;\n            }\n        } else {\n            rainstat.thishour = 0.0;\n        }\n    }        \n    \n    // Store the updates\n    global.set(global_name,rainstat);\n    msg.payload = rainstat;\n    node.status({fill:\"blue\",shape:\"ring\",text:msg.topic+\" performed\"});\n    return msg;\n} else {\n    node.status({fill:\"red\",shape:\"ring\",text:\"No reading\"});\n}","outputs":1,"noerr":0,"x":1620,"y":200,"wires":[["e91b0036.c04d2","b87bdc60.5a221"]]},{"id":"2e21bbb7.f3b0d4","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"hourly","payload":"","payloadType":"date","repeat":"3600","crontab":"","once":false,"onceDelay":"","x":1370,"y":260,"wires":[["c4f163ca.1c882"]]},{"id":"e91b0036.c04d2","type":"debug","z":"a9289d4a.d3a0b","name":"","active":false,"console":"false","complete":"false","x":1850,"y":200,"wires":[]},{"id":"1f9cf1d1.272c7e","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":2180,"y":780,"wires":[["de96e720.7b9dd8"]]},{"id":"de96e720.7b9dd8","type":"function","z":"a9289d4a.d3a0b","name":"Delete history","func":"var rainstat = {};\nglobal.set(\"rainstat\",rainstat);\n","outputs":1,"noerr":0,"x":2380,"y":780,"wires":[[]]},{"id":"7f45e72a.3b59b8","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"daily","payload":"","payloadType":"date","repeat":"","crontab":"01 00 * * *","once":false,"onceDelay":"","x":1370,"y":300,"wires":[["c4f163ca.1c882"]]},{"id":"5e297958.0d96d8","type":"function","z":"a9289d4a.d3a0b","name":"Generate hourly graph","func":"//msg.payload = global.get(\"rainstat\");  //uncomment this for debugging\n// Skeleton data structure for the bar graph\nvar m={\n    \"series\":[\"Hourly rainfall\"],\n    \"data\":[[]],\n    \"labels\":[]\n};\n\n// Transform the data\nif (msg.payload.hourlydelta!==undefined) {\n    if (msg.payload.hourlydelta.length>0) {\n        for (var i=0;i<msg.payload.hourlydelta.length;i++) {\n            m.data[0].push(msg.payload.hourlydelta[i].delta);\n            var d = new Date();\n            d.setTime(msg.payload.hourlydelta[i].epoch-1000*60*60);\n            var d2 = new Date();\n            d2.setTime(msg.payload.hourlydelta[i].epoch);\n            m.labels.push(d.getHours()+\"-\"+d2.getHours());\n        }\n    }\n}\n\n\nreturn {payload:[m]};\n\n/* sample data\n\nvar m={\n    \"series\":[\"Daily rainfall\"],\n    \"data\":[[5,3,6]],\n    \"labels\":[\"D-3\",\"D-2\",\"D-1\"]\n};\n\n*/","outputs":1,"noerr":0,"x":2160,"y":360,"wires":[["d035184c.6b2d18"]]},{"id":"d41e4cfe.fc601","type":"function","z":"a9289d4a.d3a0b","name":"Generate daily graph","func":"function getGetOrdinal(n) {\n    var s=[\"th\",\"st\",\"nd\",\"rd\"],\n    v=n%100;\n    return n+(s[(v-20)%10]||s[v]||s[0]);\n }\n\nvar dL = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\nvar dS = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n//msg.payload = global.get(\"rainstat\"); // uncomment this line if you want to debug\n// Skeleton data structure for the bar graph\nvar m={\n    \"series\":[\"Daily rainfall\"],\n    \"data\":[[]],\n    \"labels\":[]\n};\n\n// Transform the data\nif (msg.payload.dailydelta!==undefined) {\n    if (msg.payload.dailydelta.length>0) {\n        for (var i=0;i<msg.payload.dailydelta.length;i++) {\n            m.data[0].push(msg.payload.dailydelta[i].delta);\n            var d = new Date();\n            d.setTime(msg.payload.dailydelta[i].epoch-1000*60*60*24);\n            m.labels.push(dL[d.getDay()]+\", \"+getGetOrdinal(d.getDate()));\n        }\n    }\n}\n\n\nreturn {payload:[m]};\n\n/* sample data\n\nvar m={\n    \"series\":[\"Daily rainfall\"],\n    \"data\":[[5,3,6]],\n    \"labels\":[\"D-3\",\"D-2\",\"D-1\"]\n};\n\n*/","outputs":1,"noerr":0,"x":2160,"y":500,"wires":[["2d882ae5.f5b606"]]},{"id":"2d882ae5.f5b606","type":"ui_chart","z":"a9289d4a.d3a0b","name":"","group":"d5bfb431.21f7c8","order":13,"width":0,"height":0,"label":"Daily rainfall [mm]","chartType":"bar","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"no data","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":true,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":2470,"y":540,"wires":[["64c35a51.d618c4"],[]]},{"id":"9457d83b.d28268","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":1860,"y":500,"wires":[["d41e4cfe.fc601"]]},{"id":"d035184c.6b2d18","type":"ui_chart","z":"a9289d4a.d3a0b","name":"","group":"d5bfb431.21f7c8","order":11,"width":0,"height":0,"label":"Hourly rainfall [mm]","chartType":"bar","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"no data","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":true,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":2470,"y":400,"wires":[["bda1bd38.4f974"],[]]},{"id":"70478835.ea9f38","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":1860,"y":360,"wires":[["5e297958.0d96d8"]]},{"id":"b87bdc60.5a221","type":"switch","z":"a9289d4a.d3a0b","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"reading","vt":"str"},{"t":"eq","v":"hourly","vt":"str"},{"t":"eq","v":"daily","vt":"str"},{"t":"eq","v":"weekly","vt":"str"}],"checkall":"true","repair":false,"outputs":4,"x":1850,"y":260,"wires":[["7ea5cf9a.72897","3a9afab4.8b1fa6","baffe812.b0adb8"],["5e297958.0d96d8","b561ecc5.b768f"],["d41e4cfe.fc601","2f5f5d47.de27f2"],["b0de5ed4.2de47","40be628a.8ca5ac"]]},{"id":"7ea5cf9a.72897","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":10,"width":0,"height":0,"name":"","label":"This hour's rainfall","format":"{{msg.payload.thishour}} mm","layout":"row-spread","x":2310,"y":180,"wires":[]},{"id":"3a9afab4.8b1fa6","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":12,"width":0,"height":0,"name":"","label":"Today's rainfall","format":"{{msg.payload.today}} mm","layout":"row-spread","x":2300,"y":220,"wires":[]},{"id":"ef518175.a2257","type":"inject","z":"a9289d4a.d3a0b","name":"Startup","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"x":1940,"y":400,"wires":[["1ab80f69.de7111"]]},{"id":"1ab80f69.de7111","type":"file in","z":"a9289d4a.d3a0b","name":"Chart dump","filename":"/home/pi/charts/hourly_rainfall.dump","format":"utf8","sendError":true,"x":2110,"y":400,"wires":[["7851fb4a.697884"]]},{"id":"7851fb4a.697884","type":"json","z":"a9289d4a.d3a0b","name":"","x":2270,"y":400,"wires":[["d035184c.6b2d18"]]},{"id":"bda1bd38.4f974","type":"file","z":"a9289d4a.d3a0b","name":"Chart dump","filename":"/home/pi/charts/hourly_rainfall.dump","appendNewline":true,"createDir":false,"overwriteFile":"true","x":2679,"y":401,"wires":[]},{"id":"8c8a5b8b.8c4648","type":"inject","z":"a9289d4a.d3a0b","name":"Startup","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"x":1940,"y":540,"wires":[["6c469bf8.9f1c44"]]},{"id":"6c469bf8.9f1c44","type":"file in","z":"a9289d4a.d3a0b","name":"Chart dump","filename":"/home/pi/charts/daily_rainfall.dump","format":"utf8","sendError":true,"x":2110,"y":540,"wires":[["fb1b1dbf.30c7b"]]},{"id":"fb1b1dbf.30c7b","type":"json","z":"a9289d4a.d3a0b","name":"","x":2270,"y":540,"wires":[["2d882ae5.f5b606"]]},{"id":"64c35a51.d618c4","type":"file","z":"a9289d4a.d3a0b","name":"Chart dump","filename":"/home/pi/charts/daily_rainfall.dump","appendNewline":true,"createDir":false,"overwriteFile":"true","x":2679,"y":541,"wires":[]},{"id":"b561ecc5.b768f","type":"function","z":"a9289d4a.d3a0b","name":"Hourly SQL Update","func":"// This logic prevents multiple zero (delta) readings being stored in the database\n// if the (delta) reading is zero and the previous was zero as well, it will not be stored\nvar delta = msg.payload.hourlydelta[msg.payload.hourlydelta.length-1].delta;\nvar store = true;\nif (delta===0) {\n    if (context.get(\"last\")!==undefined) {\n        if (context.get(\"last\")===0) {\n            store = false;\n        }\n    }\n} \n\nif (store) {\n    context.set(\"last\", delta);\n    msg.topic=\"INSERT OR REPLACE INTO sensor_aggr (epoch,device,sensor,value) VALUES(\"+msg.payload.hourlydelta[msg.payload.hourlydelta.length-1].epoch+\",'maplin','rain_hourly',\"+delta+\");\";\n    return msg;\n}","outputs":1,"noerr":0,"x":2150,"y":320,"wires":[["b5a0a403.37d298"]]},{"id":"2f5f5d47.de27f2","type":"function","z":"a9289d4a.d3a0b","name":"Daily SQL Update","func":"msg.topic=\"INSERT OR REPLACE INTO sensor_aggr (epoch,device,sensor,value) VALUES(\"+msg.payload.dailydelta[msg.payload.dailydelta.length-1].epoch+\",'maplin','rain_daily',\"+msg.payload.dailydelta[msg.payload.dailydelta.length-1].delta+\");\";\n\nreturn msg;","outputs":1,"noerr":0,"x":2150,"y":460,"wires":[["26ed52a6.8f993e"]]},{"id":"baffe812.b0adb8","type":"ui_text","z":"a9289d4a.d3a0b","group":"d5bfb431.21f7c8","order":14,"width":0,"height":0,"name":"","label":"This week's rainfall","format":"{{msg.payload.thisweek}} mm","layout":"row-spread","x":2310,"y":260,"wires":[]},{"id":"40be628a.8ca5ac","type":"function","z":"a9289d4a.d3a0b","name":"Generate weekly graph","func":"function getGetOrdinal(n) {\n    var s=[\"th\",\"st\",\"nd\",\"rd\"],\n    v=n%100;\n    return n+(s[(v-20)%10]||s[v]||s[0]);\n }\n\nvar mL = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];\nvar mS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];\n//msg.payload = global.get(\"rainstat\");  // uncomment this line for debugging\n// Skeleton data structure for the bar graph\nvar m={\n    \"series\":[\"Weekly rainfall\"],\n    \"data\":[[]],\n    \"labels\":[]\n};\n\n// Transform the data\nif (msg.payload.weeklydelta!==undefined) {\n    if (msg.payload.weeklydelta.length>0) {\n        for (var i=0;i<msg.payload.weeklydelta.length;i++) {\n            m.data[0].push(msg.payload.weeklydelta[i].delta);\n            var d = new Date();\n            d.setTime(msg.payload.weeklydelta[i].epoch-1000*60*60*24*7);\n            m.labels.push(\"w/c \"+getGetOrdinal(d.getDate())+\" of \"+mL[d.getMonth()]);\n        }\n    }\n}\n\n\nreturn {payload:[m]};\n\n/* sample data\n\nvar m={\n    \"series\":[\"Daily rainfall\"],\n    \"data\":[[5,3,6]],\n    \"labels\":[\"D-3\",\"D-2\",\"D-1\"]\n};\n\n*/","outputs":1,"noerr":0,"x":2170,"y":640,"wires":[["ed29e60.1f04118"]]},{"id":"ed29e60.1f04118","type":"ui_chart","z":"a9289d4a.d3a0b","name":"","group":"d5bfb431.21f7c8","order":15,"width":0,"height":0,"label":"Weekly rainfall [mm]","chartType":"bar","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"no data","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":true,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":2480,"y":680,"wires":[["abd070eb.e529e"],[]]},{"id":"3b3a54ec.6db53c","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":1860,"y":640,"wires":[["40be628a.8ca5ac"]]},{"id":"b632948.206b968","type":"inject","z":"a9289d4a.d3a0b","name":"Startup","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"x":1940,"y":680,"wires":[["22fcc6d6.ea002a"]]},{"id":"22fcc6d6.ea002a","type":"file in","z":"a9289d4a.d3a0b","name":"Chart dump","filename":"/home/pi/charts/weekly_rainfall.dump","format":"utf8","sendError":true,"x":2110,"y":680,"wires":[["6cf2e833.ec5ae8"]]},{"id":"6cf2e833.ec5ae8","type":"json","z":"a9289d4a.d3a0b","name":"","x":2270,"y":680,"wires":[["ed29e60.1f04118"]]},{"id":"abd070eb.e529e","type":"file","z":"a9289d4a.d3a0b","name":"Chart dump","filename":"/home/pi/charts/weekly_rainfall.dump","appendNewline":true,"createDir":false,"overwriteFile":"true","x":2679,"y":681,"wires":[]},{"id":"b0de5ed4.2de47","type":"function","z":"a9289d4a.d3a0b","name":"Weekly SQL Update","func":"msg.topic=\"INSERT OR REPLACE INTO sensor_aggr (epoch,device,sensor,value) VALUES(\"+msg.payload.weeklydelta[msg.payload.weeklydelta.length-1].epoch+\",'maplin','rain_weekly',\"+msg.payload.weeklydelta[msg.payload.weeklydelta.length-1].delta+\");\";\n\nreturn msg;","outputs":1,"noerr":0,"x":2160,"y":600,"wires":[["f65d1e22.029cd"]]},{"id":"517c0724.afd378","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"weekly","payload":"","payloadType":"date","repeat":"","crontab":"02 00 * * 1","once":false,"onceDelay":"","x":1370,"y":340,"wires":[["c4f163ca.1c882"]]},{"id":"b5a0a403.37d298","type":"sqlite","z":"a9289d4a.d3a0b","mydb":"1c25415d.b8427f","name":"Node Red DB","x":2380,"y":320,"wires":[[]]},{"id":"26ed52a6.8f993e","type":"sqlite","z":"a9289d4a.d3a0b","mydb":"1c25415d.b8427f","name":"Node Red DB","x":2380,"y":460,"wires":[[]]},{"id":"f65d1e22.029cd","type":"sqlite","z":"a9289d4a.d3a0b","mydb":"1c25415d.b8427f","name":"Node Red DB","x":2380,"y":600,"wires":[[]]},{"id":"ee3be947.55d498","type":"inject","z":"a9289d4a.d3a0b","name":"","topic":"","payload":"rainstat","payloadType":"global","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":2170,"y":840,"wires":[["753a6afc.b518e4"]]},{"id":"753a6afc.b518e4","type":"debug","z":"a9289d4a.d3a0b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":2370,"y":840,"wires":[]},{"id":"d5bfb431.21f7c8","type":"ui_group","z":"","name":"Maplin Weather Station","tab":"7489c36d.a74f5c","order":1,"disp":true,"width":"6"},{"id":"1c25415d.b8427f","type":"sqlitedb","z":0,"db":"/home/pi/sqlite/nodered"},{"id":"7489c36d.a74f5c","type":"ui_tab","z":"","name":"RFLink","icon":"settings_remote","order":19}]

Flow Info

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

Owner

Actions

Rate:

Node Types

Core
  • debug (x2)
  • file (x3)
  • file in (x3)
  • function (x8)
  • inject (x11)
  • json (x3)
  • switch (x1)
Other
  • sqlite (x3)
  • sqlitedb (x1)
  • ui_chart (x3)
  • ui_group (x1)
  • ui_tab (x1)
  • ui_text (x3)

Tags

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