diff --git a/flows.json b/flows.json index abce8d3..f097965 100644 --- a/flows.json +++ b/flows.json @@ -2,18 +2,979 @@ { "id": "f6f2187d.f17ca8", "type": "tab", - "label": "Flow 1", + "label": "Main Flows", "disabled": false, "info": "" }, { - "id": "3cc11d24.ff01a2", + "id": "21801ad4.5fea0e", + "type": "postgresdb", + "cfgname": "timescaledb", + "hostname": "172.16.10.27", + "port": "5432", + "db": "mainscnt", + "ssl": true + }, + { + "id": "3358c20a.fe8336", + "type": "twitter-credentials", + "screen_name": "wollud1969" + }, + { + "id": "bde268f2.c163d8", + "type": "ui_tab", + "name": "MainsCnt", + "icon": "dashboard", + "disabled": false, + "hidden": false + }, + { + "id": "c5c107b9.c41048", + "type": "ui_base", + "theme": { + "name": "theme-light", + "lightTheme": { + "default": "#0094CE", + "baseColor": "#0094CE", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", + "edited": true, + "reset": false + }, + "darkTheme": { + "default": "#097479", + "baseColor": "#097479", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", + "edited": false + }, + "customTheme": { + "name": "Untitled Theme 1", + "default": "#4B7930", + "baseColor": "#4B7930", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" + }, + "themeState": { + "base-color": { + "default": "#0094CE", + "value": "#0094CE", + "edited": false + }, + "page-titlebar-backgroundColor": { + "value": "#0094CE", + "edited": false + }, + "page-backgroundColor": { + "value": "#fafafa", + "edited": false + }, + "page-sidebar-backgroundColor": { + "value": "#ffffff", + "edited": false + }, + "group-textColor": { + "value": "#1bbfff", + "edited": false + }, + "group-borderColor": { + "value": "#ffffff", + "edited": false + }, + "group-backgroundColor": { + "value": "#ffffff", + "edited": false + }, + "widget-textColor": { + "value": "#111111", + "edited": false + }, + "widget-backgroundColor": { + "value": "#0094ce", + "edited": false + }, + "widget-borderColor": { + "value": "#ffffff", + "edited": false + }, + "base-font": { + "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" + } + }, + "angularTheme": { + "primary": "indigo", + "accents": "blue", + "warn": "red", + "background": "grey" + } + }, + "site": { + "name": "Node-RED Dashboard", + "hideToolbar": "false", + "allowSwipe": "false", + "lockMenu": "false", + "allowTempTheme": "true", + "dateFormat": "DD.MM.YYYY", + "sizes": { + "sx": 48, + "sy": 48, + "gx": 6, + "gy": 6, + "cx": 6, + "cy": 6, + "px": 0, + "py": 0 + } + } + }, + { + "id": "a4c5e228.94ac28", + "type": "ui_group", + "name": "Deviation", + "tab": "bde268f2.c163d8", + "order": 2, + "disp": false, + "width": "12", + "collapse": false + }, + { + "id": "b44c1611.48c72", + "type": "ui_group", + "name": "Frequency&Alarm", + "tab": "bde268f2.c163d8", + "order": 3, + "disp": false, + "width": "6", + "collapse": false + }, + { + "id": "ee409cd5.fa48e8", + "type": "ui_spacer", + "name": "spacer", + "group": "b44c1611.48c72", + "order": 3, + "width": 1, + "height": 1 + }, + { + "id": "938dc565.b607f", + "type": "tls-config", + "name": "", + "cert": "", + "key": "", + "ca": "", + "certname": "wn-mainscnt-broker-client.crt", + "keyname": "wn-mainscnt-broker-client.pem", + "caname": "isrgrootx1.pem", + "servername": "broker.mainscnt.eu", + "verifyservercert": true + }, + { + "id": "48a55c40.d99ddc", + "type": "mqtt-broker", + "name": "ExternalBroker", + "broker": "broker.mainscnt.eu", + "port": "8883", + "tls": "938dc565.b607f", + "clientid": "", + "usetls": true, + "protocolVersion": "4", + "keepalive": "60", + "cleansession": true, + "birthTopic": "", + "birthQos": "0", + "birthPayload": "", + "birthMsg": {}, + "closeTopic": "", + "closeQos": "0", + "closePayload": "", + "closeMsg": {}, + "willTopic": "", + "willQos": "0", + "willPayload": "", + "willMsg": {}, + "sessionExpiry": "" + }, + { + "id": "911fb610.7082e", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "missing values", + "func": "msg.queryParameters = {\n \"threshold\": msg.threshold\n}\nmsg.payload = `\n SELECT count(freq) AS cnt, location\n FROM mainsfrequency\n WHERE time BETWEEN\n now() - interval '10 minutes' AND now() - interval '5 minutes'\n GROUP BY location\n HAVING count(freq) <= $threshold\n`\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 140, + "y": 180, + "wires": [ + [ + "b6ffa593.3030a8" + ] + ] + }, + { + "id": "4faba5e0.e01474", + "type": "change", + "z": "f6f2187d.f17ca8", + "name": "Threshold 100", + "rules": [ + { + "t": "set", + "p": "threshold", + "pt": "msg", + "to": "100", + "tot": "num" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 140, + "y": 140, + "wires": [ + [ + "911fb610.7082e" + ] + ] + }, + { + "id": "b6ffa593.3030a8", + "type": "postgres", + "z": "f6f2187d.f17ca8", + "postgresdb": "21801ad4.5fea0e", + "name": "mainscnt", + "output": true, + "perrow": false, + "rowspermsg": "1", + "return_on_error": false, + "limit_queries": "0", + "limit_by": "payload", + "limit_value": "1", + "limit_drop_intermediate": false, + "limit_drop_if_in_queue": false, + "outputs": true, + "x": 160, + "y": 220, + "wires": [ + [ + "9dcb400a.e79da" + ] + ] + }, + { + "id": "9dcb400a.e79da", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "Prepare", + "func": "if (msg.payload.length > 0) {\n msg.queryResult = msg.payload\n let output = \"Missing/too few values five minutes ago \"\n output += `(<= ${msg.threshold}), in `\n for (const [idx, item] of msg.payload.entries()) {\n output += `${item.location} (${item.cnt})`\n if (idx != msg.payload.length - 1) {\n output += \", \"\n }\n }\n output += \".\\n\"\n msg.payload = output\n msg.payloadLength = output.length\n return msg\n} else {\n return null\n}", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 160, + "y": 260, + "wires": [ + [ + "b38b3cf3.92f31" + ] + ] + }, + { + "id": "b38b3cf3.92f31", + "type": "pushover", + "z": "f6f2187d.f17ca8", + "name": "MainsCntAlarm", + "device": "", + "title": "", + "priority": 0, + "sound": "", + "url": "", + "url_title": "", + "html": false, + "x": 140, + "y": 300, + "wires": [] + }, + { + "id": "e4b652d9.980e8", + "type": "inject", + "z": "f6f2187d.f17ca8", + "name": "Once a minute", + "props": [ + { + "p": "payload" + } + ], + "repeat": "60", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "true", + "payloadType": "bool", + "x": 140, + "y": 100, + "wires": [ + [ + "4faba5e0.e01474" + ] + ] + }, + { + "id": "df8fb736.a86528", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "Frequency Average by Day", + "func": "msg.payload = `\n SELECT avg(freq) AS avg, \n count(freq) as cnt_freq, \n count(distinct location) as cnt_loc\n FROM mainsfrequency\n WHERE time >= current_date - interval '1 day' AND \n time < current_date AND\n valid = 1\n`\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 520, + "y": 140, + "wires": [ + [ + "8fc75864.aa5a18" + ] + ] + }, + { + "id": "8fc75864.aa5a18", + "type": "postgres", + "z": "f6f2187d.f17ca8", + "postgresdb": "21801ad4.5fea0e", + "name": "mainscnt", + "output": true, + "perrow": false, + "rowspermsg": "1", + "return_on_error": false, + "limit_queries": "0", + "limit_by": "payload", + "limit_value": "1", + "limit_drop_intermediate": false, + "limit_drop_if_in_queue": false, + "outputs": true, + "x": 580, + "y": 180, + "wires": [ + [ + "bec353dd.5865c" + ] + ] + }, + { + "id": "bec353dd.5865c", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "Prepare", + "func": "msg.result = msg.payload[0]\nmsg.result.avg = msg.result.avg.toFixed(3)\nmsg.result.cnt_freq = parseInt(msg.result.cnt_freq)\nmsg.result.cnt_loc = parseInt(msg.result.cnt_loc)\nmsg.result.pos_freq = msg.result.cnt_loc * 86400\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 580, + "y": 220, + "wires": [ + [ + "cfef36ff.319b98" + ] + ] + }, + { + "id": "eacf880.4329d78", + "type": "inject", + "z": "f6f2187d.f17ca8", + "name": "Once a day", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "30 09 * * *", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "true", + "payloadType": "bool", + "x": 570, + "y": 100, + "wires": [ + [ + "df8fb736.a86528" + ] + ] + }, + { + "id": "cfef36ff.319b98", + "type": "template", + "z": "f6f2187d.f17ca8", + "name": "Format", + "field": "payload", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "#netzfrequenz Yesterday, according to my measurement, the average mains frequency measured at {{result.cnt_loc}} locations and calculated from {{result.cnt_freq}} of {{result.pos_freq}} possible values was {{result.avg}} Hz. For details see https://grafana.mainscnt.eu \nPowered by #nodered, #timescaledb and #grafana.", + "output": "str", + "x": 580, + "y": 260, + "wires": [ + [ + "52acdab3.188644" + ] + ] + }, + { + "id": "405ce4ce.49e93c", + "type": "twitter out", + "z": "f6f2187d.f17ca8", + "twitter": "3358c20a.fe8336", + "name": "Tweet", + "x": 590, + "y": 340, + "wires": [] + }, + { + "id": "52acdab3.188644", + "type": "jimp-image", + "z": "f6f2187d.f17ca8", + "name": "", + "data": "https://grafana.mainscnt.eu/render/d-solo/tg1-U6XGz/mainscnt?orgId=1&from=now-1d%2Fd&to=now-1d%2Fd&panelId=2&width=1000&height=1200&tz=UTC", + "dataType": "str", + "ret": "buf", + "parameter1": "", + "parameter1Type": "msg", + "parameter2": "", + "parameter2Type": "msg", + "parameter3": "", + "parameter3Type": "msg", + "parameter4": "", + "parameter4Type": "msg", + "parameter5": "", + "parameter5Type": "msg", + "parameter6": "", + "parameter6Type": "msg", + "parameter7": "", + "parameter7Type": "msg", + "parameter8": "", + "parameter8Type": "msg", + "sendProperty": "media", + "sendPropertyType": "msg", + "parameterCount": 0, + "jimpFunction": "none", + "selectedJimpFunction": { + "name": "none", + "fn": "none", + "description": "Just loads the image.", + "parameters": [] + }, + "x": 590, + "y": 300, + "wires": [ + [ + "405ce4ce.49e93c" + ] + ] + }, + { + "id": "f6a43d0d.ebddc", "type": "comment", "z": "f6f2187d.f17ca8", - "name": "WARNING: please check you have started this container with a volume that is mounted to /data\\n otherwise any flow changes are lost when you redeploy or upgrade the container\\n (e.g. upgrade to a more recent node-red docker image).\\n If you are using named volumes you can ignore this warning.\\n Double click or see info side panel to learn how to start Node-RED in Docker to save your work", - "info": "\nTo start docker with a bind mount volume (-v option), for example:\n\n```\ndocker run -it -p 1880:1880 -v /home/user/node_red_data:/data --name mynodered nodered/node-red\n```\n\nwhere `/home/user/node_red_data` is a directory on your host machine where you want to store your flows.\n\nIf you do not do this then you can experiment and redploy flows, but if you restart or upgrade the container the flows will be disconnected and lost. \n\nThey will still exist in a hidden data volume, which can be recovered using standard docker techniques, but that is much more complex than just starting with a named volume as described above.", - "x": 350, - "y": 80, + "name": "Missing Values", + "info": "", + "x": 140, + "y": 60, + "wires": [] + }, + { + "id": "b73c5463.505428", + "type": "comment", + "z": "f6f2187d.f17ca8", + "name": "Daily Average Frequency Tweet", + "info": "", + "x": 510, + "y": 60, + "wires": [] + }, + { + "id": "56cef6df.8ecbe8", + "type": "inject", + "z": "f6f2187d.f17ca8", + "name": "Once a minute", + "props": [ + { + "p": "payload" + } + ], + "repeat": "60", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "true", + "payloadType": "bool", + "x": 920, + "y": 100, + "wires": [ + [ + "aad599a3.46ee48" + ] + ] + }, + { + "id": "aad599a3.46ee48", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "Averaging Statement", + "func": "msg.payload = `\n SELECT avg(freq) AS mean\n FROM mainsfrequency\n WHERE valid = 1 AND \n time BETWEEN\n now() - interval '7 minutes' AND now() - interval '5 minutes'\n`\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 900, + "y": 140, + "wires": [ + [ + "efab1827.7067d8" + ] + ] + }, + { + "id": "efab1827.7067d8", + "type": "postgres", + "z": "f6f2187d.f17ca8", + "postgresdb": "21801ad4.5fea0e", + "name": "mainscnt", + "output": true, + "perrow": false, + "rowspermsg": "1", + "return_on_error": false, + "limit_queries": "0", + "limit_by": "payload", + "limit_value": "1", + "limit_drop_intermediate": false, + "limit_drop_if_in_queue": false, + "outputs": true, + "x": 940, + "y": 180, + "wires": [ + [ + "27bc28c6.5d5b58" + ] + ] + }, + { + "id": "27bc28c6.5d5b58", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "Extract (absolute) deviation", + "func": "let DESIRED_FREQUENCY = 50.0\nif (msg.payload.length > 0) {\n let v = msg.payload[0].mean\n node.status({fill:\"green\",shape:\"dot\",text:`${v}`})\n msg.payload = v\n return [ \n { 'payload': v.toFixed(3) }, \n { 'payload': (v - DESIRED_FREQUENCY).toFixed(3) }\n ]\n} else {\n node.status({fill:\"red\",shape:\"dot\",text:\"no data\"})\n node.error(\"no data\")\n return null\n}\n", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 880, + "y": 220, + "wires": [ + [ + "5a6c06e7.dca6e8" + ], + [ + "5594701d.41a81", + "7c63eb69.6d1b24" + ] + ] + }, + { + "id": "7c63eb69.6d1b24", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "Alarm", + "func": "let ALARM_THRESHOLD = 0.1\nlet RE_ARM_THRESHOLD = 0.075\nlet ARMED_STATE_KEY = 'ARMED_STATE'\nlet value = msg.payload\nlet absValue = Math.abs(value)\n\nif (! context.keys().includes(ARMED_STATE_KEY)) {\n context.set(ARMED_STATE_KEY, true)\n}\n\nlet armedState = context.get(ARMED_STATE_KEY)\nlet newEvent = false\nif (armedState) {\n if (absValue > ALARM_THRESHOLD) {\n armedState = false\n newEvent = true\n }\n} else {\n if (absValue < RE_ARM_THRESHOLD) {\n armedState = true\n newEvent = true\n }\n}\n\nnode.status(\n {\n fill: armedState ? \"green\" : \"red\",\n shape:\"dot\",\n text: armedState ? \"armed\" : \"alarm sent\"\n }\n)\n\ncontext.set(ARMED_STATE_KEY, armedState)\n\nreturn [ \n {'payload': armedState}, \n newEvent ?\n { \n 'payload': {\n 'value': value,\n 'state': armedState,\n 'high': ALARM_THRESHOLD,\n 'low': RE_ARM_THRESHOLD\n }\n } : null\n]", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 950, + "y": 260, + "wires": [ + [ + "5701a2b2.9ca59c" + ], + [ + "85489c32.b49ff", + "33c01fa2.d6e88", + "13ebfe6b.4e6262" + ] + ] + }, + { + "id": "5594701d.41a81", + "type": "ui_chart", + "z": "f6f2187d.f17ca8", + "name": "", + "group": "a4c5e228.94ac28", + "order": 1, + "width": "12", + "height": "9", + "label": "Deviation", + "chartType": "line", + "legend": "false", + "xformat": "HH:mm:ss", + "interpolate": "linear", + "nodata": "", + "dot": true, + "ymin": "-0.15", + "ymax": "0.15", + "removeOlder": 1, + "removeOlderPoints": "", + "removeOlderUnit": "3600", + "cutout": 0, + "useOneColor": false, + "useUTC": false, + "colors": [ + "#1f77b4", + "#aec7e8", + "#ff7f0e", + "#2ca02c", + "#98df8a", + "#d62728", + "#ff9896", + "#9467bd", + "#c5b0d5" + ], + "outputs": 1, + "useDifferentColor": false, + "x": 1140, + "y": 220, + "wires": [ + [] + ] + }, + { + "id": "5a6c06e7.dca6e8", + "type": "ui_gauge", + "z": "f6f2187d.f17ca8", + "name": "", + "group": "b44c1611.48c72", + "order": 4, + "width": 0, + "height": 0, + "gtype": "gage", + "title": "Frequency", + "label": "Hz", + "format": "{{value}}", + "min": "49.85", + "max": "50.15", + "colors": [ + "#ff0000", + "#00ff00", + "#ff0000" + ], + "seg1": "49.9", + "seg2": "50.1", + "x": 1150, + "y": 180, + "wires": [] + }, + { + "id": "5701a2b2.9ca59c", + "type": "ui_switch", + "z": "f6f2187d.f17ca8", + "name": "", + "label": "Alarm", + "tooltip": "", + "group": "b44c1611.48c72", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "topic", + "topicType": "msg", + "style": "", + "onvalue": "true", + "onvalueType": "bool", + "onicon": "mood", + "oncolor": "green", + "offvalue": "false", + "offvalueType": "bool", + "officon": "mood_bad", + "offcolor": "red", + "animate": true, + "x": 1130, + "y": 260, + "wires": [ + [] + ] + }, + { + "id": "88a1710c.11068", + "type": "twitter out", + "z": "f6f2187d.f17ca8", + "twitter": "3358c20a.fe8336", + "name": "MainsCntTweet", + "x": 920, + "y": 600, + "wires": [] + }, + { + "id": "c7c60031.05b2f", + "type": "pushover", + "z": "f6f2187d.f17ca8", + "name": "MainsCntAlarm", + "device": "", + "title": "", + "priority": 0, + "sound": "", + "url": "", + "url_title": "", + "html": false, + "x": 920, + "y": 560, + "wires": [] + }, + { + "id": "33c01fa2.d6e88", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "Prepare", + "func": "let info = `Deviation is ${msg.payload.value}, High mark is ${msg.payload.high}, Low mark is ${msg.payload.low}`\nlet status = msg.payload.state ? 'clear&armed' : 'alarm'\n\nlet output = \"Frequency Out of Range Alarm\\n\"\noutput += `Status: ${status}\\n`\noutput += `Absolute devivation ${info} Hz\\n`\noutput += \"https://shorty.mainscnt.eu/30m\"\nmsg.payload = output\nmsg.payloadLength = output.length\nreturn msg\n", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 940, + "y": 520, + "wires": [ + [ + "c7c60031.05b2f" + ] + ] + }, + { + "id": "85489c32.b49ff", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "Alarm Event Statement", + "func": "msg.queryParameters = {\n 'info': `Deviation is ${msg.payload.value}, High mark is ${msg.payload.high}, Low mark is ${msg.payload.low}`,\n 'status': msg.payload.state ? 'clear&armed' : 'alarm'\n}\nmsg.payload = `\n INSERT INTO alarm_event_t\n (name, status, info)\n values('freq_out_of_range', $status, $info)\n`\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1190, + "y": 420, + "wires": [ + [ + "a392562a.918b58" + ] + ] + }, + { + "id": "a392562a.918b58", + "type": "postgres", + "z": "f6f2187d.f17ca8", + "postgresdb": "21801ad4.5fea0e", + "name": "mainscnt", + "output": false, + "perrow": false, + "rowspermsg": "1", + "return_on_error": false, + "limit_queries": "0", + "limit_by": "payload", + "limit_value": "1", + "limit_drop_intermediate": false, + "limit_drop_if_in_queue": false, + "outputs": false, + "x": 1140, + "y": 460, + "wires": [] + }, + { + "id": "13ebfe6b.4e6262", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "EventCounter", + "func": "let cnt = context.get('EventCounter') || 0\ncnt += 1\ncontext.set('EventCounter', cnt)\nnode.status({fill:\"blue\",shape:\"dot\",text:`${cnt}`})\nmsg.payload = cnt\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1160, + "y": 320, + "wires": [ + [ + "94287849.0ee7e8" + ] + ] + }, + { + "id": "94287849.0ee7e8", + "type": "ui_text", + "z": "f6f2187d.f17ca8", + "group": "b44c1611.48c72", + "order": 2, + "width": 0, + "height": 0, + "name": "", + "label": "EventCnt", + "format": "{{msg.payload}}", + "layout": "row-spread", + "x": 1140, + "y": 360, + "wires": [] + }, + { + "id": "d7c897ea.2f7c78", + "type": "comment", + "z": "f6f2187d.f17ca8", + "name": "Frequency Out of Range Alarm", + "info": "", + "x": 870, + "y": 60, + "wires": [] + }, + { + "id": "f41aea58.180338", + "type": "mqtt in", + "z": "f6f2187d.f17ca8", + "name": "", + "topic": "MainsCnt/#", + "qos": "2", + "datatype": "json", + "broker": "48a55c40.d99ddc", + "nl": false, + "rap": true, + "rh": 0, + "x": 230, + "y": 540, + "wires": [ + [ + "776c7457.dfa35c" + ] + ] + }, + { + "id": "f37a3ea0.54c97", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "Check and Prepare", + "func": "const LOWER_BOUND = 48.5\nconst UPPER_BOUND = 51.5\n\nlet valid = msg.incoming.Valid\nlet freq = msg.incoming.Freq\n\nif (freq < LOWER_BOUND || freq > UPPER_BOUND) {\n valid = false\n}\n\nmsg.queryParameters = {\n \"time\": msg.incoming.Time,\n \"freq\": freq,\n \"location\": msg.location,\n \"valid\": valid\n}\nmsg.payload = `\n INSERT INTO mainsfrequency\n (time, freq, location)\n VALUES($time, $freq, $location)\n`\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 210, + "y": 700, + "wires": [ + [ + "afbde352.0aaa6" + ] + ] + }, + { + "id": "afbde352.0aaa6", + "type": "postgres", + "z": "f6f2187d.f17ca8", + "postgresdb": "21801ad4.5fea0e", + "name": "mainscnt", + "output": true, + "perrow": false, + "rowspermsg": "1", + "return_on_error": false, + "limit_queries": "0", + "limit_by": "payload", + "limit_value": "1", + "limit_drop_intermediate": false, + "limit_drop_if_in_queue": false, + "outputs": true, + "x": 240, + "y": 740, + "wires": [ + [] + ] + }, + { + "id": "776c7457.dfa35c", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "FindDevice", + "func": "msg.incoming = msg.payload\nmsg.queryParameters = {\n \"deviceid\": msg.topic\n}\nmsg.payload = `\n SELECT location \n FROM device_t\n WHERE active = 't' AND\n deviceid = $deviceid\n`\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 230, + "y": 580, + "wires": [ + [ + "b8c55ac0.707e08" + ] + ] + }, + { + "id": "b8c55ac0.707e08", + "type": "postgres", + "z": "f6f2187d.f17ca8", + "postgresdb": "21801ad4.5fea0e", + "name": "mainscnt", + "output": true, + "perrow": false, + "rowspermsg": "1", + "return_on_error": false, + "limit_queries": "0", + "limit_by": "payload", + "limit_value": "1", + "limit_drop_intermediate": false, + "limit_drop_if_in_queue": false, + "outputs": true, + "x": 240, + "y": 620, + "wires": [ + [ + "46831f13.0e29d" + ] + ] + }, + { + "id": "46831f13.0e29d", + "type": "function", + "z": "f6f2187d.f17ca8", + "name": "ExtractLocation", + "func": "if (msg.payload.length == 1) {\n msg.location = msg.payload[0].location\n return msg\n} else {\n return\n}", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 220, + "y": 660, + "wires": [ + [ + "f37a3ea0.54c97" + ] + ] + }, + { + "id": "52a9852a.c634dc", + "type": "comment", + "z": "f6f2187d.f17ca8", + "name": "MQTT Ingress Processor", + "info": "", + "x": 190, + "y": 500, "wires": [] } ] \ No newline at end of file diff --git a/flows_cred.json b/flows_cred.json index 9bc8766..972fd64 100644 --- a/flows_cred.json +++ b/flows_cred.json @@ -1 +1,3 @@ -{"$":"a618d667de0ba9752f98121bdf11d152uAo="} \ No newline at end of file +{ + "$": "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" +} \ No newline at end of file diff --git a/package.json b/package.json index 0dcdd99..a72966b 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,14 @@ { "name": "nodered-mainscnt", - "description": "A Node-RED Project", + "description": "Mainscnt - Ingress and Alarm Processor", "version": "0.0.1", - "dependencies": {}, + "dependencies": { + "node-red-contrib-image-tools": "2.0.2", + "node-red-contrib-re-postgres": "0.3.2", + "node-red-dashboard": "2.29.0", + "node-red-node-pushover": "0.0.24", + "node-red-node-twitter": "1.2.0" + }, "node-red": { "settings": { "flowFile": "flows.json",