refactoring of layout
This commit is contained in:
parent
ff9a60241e
commit
3ce4c900b2
973
flows.json
973
flows.json
@ -2,18 +2,979 @@
|
|||||||
{
|
{
|
||||||
"id": "f6f2187d.f17ca8",
|
"id": "f6f2187d.f17ca8",
|
||||||
"type": "tab",
|
"type": "tab",
|
||||||
"label": "Flow 1",
|
"label": "Main Flows",
|
||||||
"disabled": false,
|
"disabled": false,
|
||||||
"info": ""
|
"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",
|
"type": "comment",
|
||||||
"z": "f6f2187d.f17ca8",
|
"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",
|
"name": "Missing Values",
|
||||||
"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.",
|
"info": "",
|
||||||
"x": 350,
|
"x": 140,
|
||||||
"y": 80,
|
"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": []
|
"wires": []
|
||||||
}
|
}
|
||||||
]
|
]
|
File diff suppressed because one or more lines are too long
10
package.json
10
package.json
@ -1,8 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "nodered-mainscnt",
|
"name": "nodered-mainscnt",
|
||||||
"description": "A Node-RED Project",
|
"description": "Mainscnt - Ingress and Alarm Processor",
|
||||||
"version": "0.0.1",
|
"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": {
|
"node-red": {
|
||||||
"settings": {
|
"settings": {
|
||||||
"flowFile": "flows.json",
|
"flowFile": "flows.json",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user