Make area weather alerts reusable, add a few areas

This commit is contained in:
2025-03-20 00:33:04 -04:00
parent 4044423dac
commit 45ea515d80

View File

@ -57,6 +57,38 @@
"color": "#DDAA99",
"icon": "font-awesome/fa-cloud"
},
{
"id": "0e70b91ae6570376",
"type": "subflow",
"name": "Area Weather Alerts",
"info": "",
"category": "",
"in": [
{
"x": 60,
"y": 140,
"wires": [
{
"id": "8ac36baa32177bd6"
}
]
}
],
"out": [],
"env": [],
"meta": {},
"color": "#DDAA99",
"status": {
"x": 580,
"y": 320,
"wires": [
{
"id": "404170ec56d4c845",
"port": 5
}
]
}
},
{
"id": "df425a30fbcfb2e9",
"type": "group",
@ -90,21 +122,68 @@
"label": true
},
"nodes": [
"8ac36baa32177bd6",
"aa989a69868fc5fe",
"846ac653b993bbec",
"fc63778f17491208",
"404170ec56d4c845",
"ab2e9b884521285a",
"9151c0cd48bb3c45",
"67561d51aaa61dfa",
"6e785299ac298ccd",
"4d8ca3ed3f302d97"
"bc210da75548aa27"
],
"x": 14,
"y": 239,
"w": 1032,
"h": 322
"w": 552,
"h": 142
},
{
"id": "56542cfc9d0c7a24",
"type": "group",
"z": "ed4ea3c2bc13d1ec",
"name": "KY Lake Alerts",
"style": {
"label": true
},
"nodes": [
"bce3a3a1210ab253",
"e8efcf839f012317",
"5a0e961755fd6b45"
],
"x": 14,
"y": 399,
"w": 552,
"h": 142
},
{
"id": "0cd2e4517585a8c3",
"type": "group",
"z": "ed4ea3c2bc13d1ec",
"name": "Ashland County Alerts",
"style": {
"label": true
},
"nodes": [
"e0c88351cce4178c",
"ee268b5bef276f45",
"028431d8cab86f80"
],
"x": 14,
"y": 559,
"w": 552,
"h": 142
},
{
"id": "b11deb643761dfcf",
"type": "group",
"z": "ed4ea3c2bc13d1ec",
"name": "Bayfield County Alerts",
"style": {
"label": true
},
"nodes": [
"d2c7d572608b7d19",
"26a089d3cbbb5ef1",
"eed501c9777eecb5"
],
"x": 14,
"y": 719,
"w": 552,
"h": 142
},
{
"id": "200f284a1171f0a8",
@ -175,6 +254,161 @@
[]
]
},
{
"id": "8ac36baa32177bd6",
"type": "http request",
"z": "0e70b91ae6570376",
"name": "NWS Alerts API",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 200,
"y": 140,
"wires": [
[
"404170ec56d4c845"
]
]
},
{
"id": "404170ec56d4c845",
"type": "function",
"z": "0e70b91ae6570376",
"name": "Filter",
"func": "const severeWarningEvents = [\"Severe Thunderstorm Warning\",\"Destructive Severe Thunderstorm Warning\",\"Considerable Destructive Severe Thunderstorm Warning\"]\nconst tornadoWarningEvents = [\"Tornado Warning\",\"Radar Indicated Tornado Warning\",\"Confirmed Tornado Warning\",\"Tornado Emergency\"]\nconst tornadoWatchEvents = [\"Tornado Watch\"]\nconst severeThunderstormWatchEvents = [\"Severe Thunderstorm Watch\"]\nconst area = msg.area\nconst mqttTopic = \"weather/alerts/\" + area\nconst tstormTopic = mqttTopic + \"/severe_thunderstorm_warning\"\nconst tornadoWarnTopic = mqttTopic + \"/tornado_warning\"\nconst tornadoWatchTopic = mqttTopic + \"/tornado_watch\"\nconst severeThunderstormWatchTopic = mqttTopic + \"/severe_thunderstorm_watch\"\n\nlet alerts = msg.payload.features\nlet tornado_possible = false\nlet considerable_destructive = false\nlet confirmed = false\n\n// Filter for Severe Thunderstorm Warnings\n\nlet ts = alerts.filter(function(alert) {\n if (alert.properties &&\n severeWarningEvents.includes(alert.properties.event)) {\n return true\n }\n})\n\n// Filter for Severe Thunderstorm Warnings with tornado detection\n// that have a tornado possible parameter\n\nlet tstp = alerts.filter(function(alert) {\n if (alert.properties &&\n severeWarningEvents.includes(alert.properties.event) &&\n alert.properties.parameters &&\n alert.properties.parameters.tornadoDetection &&\n alert.properties.parameters.tornadoDetection.length > 0) {\n let tornadoPossible = alert.properties.parameters.tornadoDetection[0]\n return tornadoPossible === \"POSSIBLE\"\n }\n})\n\nif (tstp.length > 0) {\n tornado_possible = true\n}\n\n// Filter for considerable destructive severe thunderstorm warnings\n\nlet cdst = alerts.filter(function(alert) {\n if (alert.properties &&\n alert.properties.event === \"Considerable Destructive Severe Thunderstorm Warning\") {\n return true\n }\n})\n\nif (cdst.length > 0) {\n considerable_destructive = true\n}\n\n// Filter for Tornado Warnings\n\nlet tornado = alerts.filter(function(alert) {\n if (alert.properties &&\n tornadoWarningEvents.includes(alert.properties.event)) {\n return true\n }\n})\n\nlet confirmed_tornado = alerts.filter(function(alert) {\n if (alert.properties &&\n alert.properties.event === \"Confirmed Tornado Warning\") {\n return true\n }\n})\n\nif (confirmed_tornado.length > 0) {\n confirmed = true\n}\n\n// Filter for Tornado Watches\n\nlet tornado_watch = alerts.filter(function(alert) {\n if (alert.properties &&\n tornadoWatchEvents.includes(alert.properties.event)) {\n return true\n }\n})\n\n// Filter for Severe Thunderstorm Watches\n\nlet severe_thunderstorm_watch = alerts.filter(function(alert) {\n if (alert.properties &&\n severeThunderstormWatchEvents.includes(alert.properties.event)) {\n return true\n }\n})\n\n// If there are any alerts, return them\n\nlet allAlerts = {\n \"payload\": msg.payload.features\n}\n\nlet tstormMsg = {\n \"payload\": {\n \"alerts\": ts,\n \"count\": ts.length,\n \"tornado_possible\": tornado_possible,\n \"considerable_destructive\": considerable_destructive\n },\n \"topic\": tstormTopic\n}\n\nlet tornadoWarnMsg = {\n \"payload\": {\n \"alerts\": tornado,\n \"count\": tornado.length,\n \"confirmed\": confirmed\n },\n \"topic\": tornadoWarnTopic\n}\n\nlet tornadoWatchMsg = {\n \"payload\": {\n \"alerts\": tornado_watch,\n \"count\": tornado_watch.length\n },\n \"topic\": tornadoWatchTopic\n}\n\nlet severeThunderstormWatchMsg = {\n \"payload\": {\n \"alerts\": severe_thunderstorm_watch,\n \"count\": severe_thunderstorm_watch.length\n },\n \"topic\": severeThunderstormWatchTopic\n}\n\n// Create status message for node\n\nlet statusMsg = {\n \"status\": {\n \"fill\": \"green\",\n \"shape\": \"dot\",\n \"text\": alerts.length + \" alerts processed at \" + new Date().toLocaleString()\n }\n}\n\n// Send messages to output nodes\n\nnode.send([allAlerts,tstormMsg,tornadoWarnMsg,tornadoWatchMsg,severeThunderstormWatchMsg,statusMsg])",
"outputs": 6,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 390,
"y": 140,
"wires": [
[
"846ac653b993bbec"
],
[
"9151c0cd48bb3c45"
],
[
"ab2e9b884521285a"
],
[
"6e785299ac298ccd"
],
[
"4d8ca3ed3f302d97"
],
[]
],
"outputLabels": [
"Severe Thunderstorm Warning",
"Tornado Warning",
"",
"",
"",
""
]
},
{
"id": "846ac653b993bbec",
"type": "mqtt out",
"z": "0e70b91ae6570376",
"name": "MQTT - All Alerts",
"topic": "",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "200f284a1171f0a8",
"x": 650,
"y": 20,
"wires": []
},
{
"id": "ab2e9b884521285a",
"type": "mqtt out",
"z": "0e70b91ae6570376",
"name": "MQTT - Tornado Warning",
"topic": "",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "200f284a1171f0a8",
"x": 670,
"y": 140,
"wires": []
},
{
"id": "9151c0cd48bb3c45",
"type": "mqtt out",
"z": "0e70b91ae6570376",
"name": "MQTT - Severe Thunderstorm Warning",
"topic": "",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "200f284a1171f0a8",
"x": 710,
"y": 80,
"wires": []
},
{
"id": "6e785299ac298ccd",
"type": "mqtt out",
"z": "0e70b91ae6570376",
"name": "MQTT - Tornado Watch",
"topic": "",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "200f284a1171f0a8",
"x": 670,
"y": 200,
"wires": []
},
{
"id": "4d8ca3ed3f302d97",
"type": "mqtt out",
"z": "0e70b91ae6570376",
"name": "MQTT - Severe Thunderstorm Watch",
"topic": "",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "200f284a1171f0a8",
"x": 710,
"y": 260,
"wires": []
},
{
"id": "7d9f24e0a78ec15c",
"type": "http request",
@ -299,32 +533,6 @@
"y": 120,
"wires": []
},
{
"id": "8ac36baa32177bd6",
"type": "http request",
"z": "ed4ea3c2bc13d1ec",
"g": "b0521ee44dc796d1",
"name": "Defiance County",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.weather.gov/alerts/active/zone/OHC039",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 300,
"y": 340,
"wires": [
[
"fc63778f17491208",
"404170ec56d4c845"
]
]
},
{
"id": "aa989a69868fc5fe",
"type": "inject",
@ -336,7 +544,13 @@
"p": "payload"
},
{
"p": "topic",
"p": "url",
"v": "https://api.weather.gov/alerts/active/zone/OHC039",
"vt": "str"
},
{
"p": "area",
"v": "defiance",
"vt": "str"
}
],
@ -348,134 +562,13 @@
"payload": "",
"payloadType": "date",
"x": 130,
"y": 340,
"wires": [
[
"8ac36baa32177bd6"
]
]
},
{
"id": "846ac653b993bbec",
"type": "mqtt out",
"z": "ed4ea3c2bc13d1ec",
"g": "b0521ee44dc796d1",
"name": "",
"topic": "weather/alerts/defiance",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "200f284a1171f0a8",
"x": 730,
"y": 280,
"wires": []
},
{
"id": "fc63778f17491208",
"type": "change",
"z": "ed4ea3c2bc13d1ec",
"g": "b0521ee44dc796d1",
"name": "",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.features",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 500,
"y": 280,
"wires": [
[
"846ac653b993bbec"
"bc210da75548aa27"
]
]
},
{
"id": "404170ec56d4c845",
"type": "function",
"z": "ed4ea3c2bc13d1ec",
"g": "b0521ee44dc796d1",
"name": "Filter",
"func": "const severeWarningEvents = [\"Severe Thunderstorm Warning\",\"Destructive Severe Thunderstorm Warning\",\"Considerable Destructive Severe Thunderstorm Warning\"]\nconst tornadoWarningEvents = [\"Tornado Warning\",\"Radar Indicated Tornado Warning\",\"Confirmed Tornado Warning\",\"Tornado Emergency\"]\nconst tornadoWatchEvents = [\"Tornado Watch\"]\nconst severeThunderstormWatchEvents = [\"Severe Thunderstorm Watch\"]\n\nlet alerts = msg.payload.features\nlet tornado_possible = false\nlet considerable_destructive = false\nlet confirmed = false\n\n// Filter for Severe Thunderstorm Warnings\n\nlet ts = alerts.filter(function(alert) {\n if (alert.properties &&\n severeWarningEvents.includes(alert.properties.event)) {\n return true\n }\n})\n\n// Filter for Severe Thunderstorm Warnings with tornado detection\n// that have a tornado possible parameter\n\nlet tstp = alerts.filter(function(alert) {\n if (alert.properties &&\n severeWarningEvents.includes(alert.properties.event) &&\n alert.properties.parameters &&\n alert.properties.parameters.tornadoDetection &&\n alert.properties.parameters.tornadoDetection.length > 0) {\n let tornadoPossible = alert.properties.parameters.tornadoDetection[0]\n return tornadoPossible === \"POSSIBLE\"\n }\n})\n\nif (tstp.length > 0) {\n tornado_possible = true\n}\n\n// Filter for considerable destructive severe thunderstorm warnings\n\nlet cdst = alerts.filter(function(alert) {\n if (alert.properties &&\n alert.properties.event === \"Considerable Destructive Severe Thunderstorm Warning\") {\n return true\n }\n})\n\nif (cdst.length > 0) {\n considerable_destructive = true\n}\n\n// Filter for Tornado Warnings\n\nlet tornado = alerts.filter(function(alert) {\n if (alert.properties &&\n tornadoWarningEvents.includes(alert.properties.event)) {\n return true\n }\n})\n\nlet confirmed_tornado = alerts.filter(function(alert) {\n if (alert.properties &&\n alert.properties.event === \"Confirmed Tornado Warning\") {\n return true\n }\n})\n\nif (confirmed_tornado.length > 0) {\n confirmed = true\n}\n\n// Filter for Tornado Watches\n\nlet tornado_watch = alerts.filter(function(alert) {\n if (alert.properties &&\n tornadoWatchEvents.includes(alert.properties.event)) {\n return true\n }\n})\n\n// Filter for Severe Thunderstorm Watches\n\nlet severe_thunderstorm_watch = alerts.filter(function(alert) {\n if (alert.properties &&\n severeThunderstormWatchEvents.includes(alert.properties.event)) {\n return true\n }\n})\n\n// If there are any alerts, return them\n\nlet tstormMsg = {\n \"payload\": {\n \"alerts\": ts,\n \"count\": ts.length,\n \"tornado_possible\": tornado_possible,\n \"considerable_destructive\": considerable_destructive\n }\n}\n\nlet tornadoWarnMsg = {\n \"payload\": {\n \"alerts\": tornado,\n \"count\": tornado.length,\n \"confirmed\": confirmed\n }\n}\n\nlet tornadoWatchMsg = {\n \"payload\": {\n \"alerts\": tornado_watch,\n \"count\": tornado_watch.length\n }\n}\n\nlet severeThunderstormWatchMsg = {\n \"payload\": {\n \"alerts\": severe_thunderstorm_watch,\n \"count\": severe_thunderstorm_watch.length\n }\n}\n\nnode.send([tstormMsg,tornadoWarnMsg,tornadoWatchMsg,severeThunderstormWatchMsg])\nnode.status({fill:'green',shape:'dot',text:'Alerts Updated'})",
"outputs": 4,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 470,
"y": 340,
"wires": [
[
"9151c0cd48bb3c45"
],
[
"ab2e9b884521285a"
],
[
"6e785299ac298ccd"
],
[
"4d8ca3ed3f302d97"
]
],
"outputLabels": [
"Severe Thunderstorm Warning",
"Tornado Warning",
null,
null
]
},
{
"id": "ab2e9b884521285a",
"type": "mqtt out",
"z": "ed4ea3c2bc13d1ec",
"g": "b0521ee44dc796d1",
"name": "",
"topic": "weather/alerts/defiance/tornado_warning",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "200f284a1171f0a8",
"x": 780,
"y": 400,
"wires": []
},
{
"id": "9151c0cd48bb3c45",
"type": "mqtt out",
"z": "ed4ea3c2bc13d1ec",
"g": "b0521ee44dc796d1",
"name": "",
"topic": "weather/alerts/defiance/severe_thunderstorm_warning",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "200f284a1171f0a8",
"x": 820,
"y": 340,
"wires": []
},
{
"id": "42b8b21e40f8b824",
"type": "link in",
@ -503,10 +596,10 @@
"b98e25d5de4ce89c"
],
"x": 185,
"y": 400,
"y": 340,
"wires": [
[
"8ac36baa32177bd6"
"bc210da75548aa27"
]
]
},
@ -565,43 +658,204 @@
"wires": []
},
{
"id": "6e785299ac298ccd",
"type": "mqtt out",
"id": "bc210da75548aa27",
"type": "subflow:0e70b91ae6570376",
"z": "ed4ea3c2bc13d1ec",
"g": "b0521ee44dc796d1",
"name": "",
"topic": "weather/alerts/defiance/tornado_watch",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "200f284a1171f0a8",
"x": 770,
"y": 460,
"x": 440,
"y": 280,
"wires": []
},
{
"id": "4d8ca3ed3f302d97",
"type": "mqtt out",
"id": "bce3a3a1210ab253",
"type": "inject",
"z": "ed4ea3c2bc13d1ec",
"g": "b0521ee44dc796d1",
"g": "56542cfc9d0c7a24",
"name": "",
"topic": "weather/alerts/defiance/severe_thunderstorm_watch",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "200f284a1171f0a8",
"x": 820,
"y": 520,
"props": [
{
"p": "payload"
},
{
"p": "url",
"v": "https://api.weather.gov/alerts/active/zone/KYC157",
"vt": "str"
},
{
"p": "area",
"v": "ky_lake",
"vt": "str"
}
],
"repeat": "30",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 130,
"y": 440,
"wires": [
[
"e8efcf839f012317"
]
]
},
{
"id": "e8efcf839f012317",
"type": "subflow:0e70b91ae6570376",
"z": "ed4ea3c2bc13d1ec",
"g": "56542cfc9d0c7a24",
"name": "",
"x": 440,
"y": 440,
"wires": []
},
{
"id": "5a0e961755fd6b45",
"type": "link in",
"z": "ed4ea3c2bc13d1ec",
"g": "56542cfc9d0c7a24",
"name": "Weather - KY Lake Alerts Trigger",
"links": [
"b98e25d5de4ce89c"
],
"x": 185,
"y": 500,
"wires": [
[
"e8efcf839f012317"
]
]
},
{
"id": "e0c88351cce4178c",
"type": "inject",
"z": "ed4ea3c2bc13d1ec",
"g": "0cd2e4517585a8c3",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "url",
"v": "https://api.weather.gov/alerts/active/zone/WIC003",
"vt": "str"
},
{
"p": "area",
"v": "ashland_co",
"vt": "str"
}
],
"repeat": "30",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 130,
"y": 600,
"wires": [
[
"ee268b5bef276f45"
]
]
},
{
"id": "ee268b5bef276f45",
"type": "subflow:0e70b91ae6570376",
"z": "ed4ea3c2bc13d1ec",
"g": "0cd2e4517585a8c3",
"name": "",
"x": 440,
"y": 600,
"wires": []
},
{
"id": "028431d8cab86f80",
"type": "link in",
"z": "ed4ea3c2bc13d1ec",
"g": "0cd2e4517585a8c3",
"name": "Weather - KY Lake Alerts Trigger",
"links": [
"b98e25d5de4ce89c"
],
"x": 185,
"y": 660,
"wires": [
[
"ee268b5bef276f45"
]
]
},
{
"id": "d2c7d572608b7d19",
"type": "inject",
"z": "ed4ea3c2bc13d1ec",
"g": "b11deb643761dfcf",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "url",
"v": "https://api.weather.gov/alerts/active/zone/WIC007",
"vt": "str"
},
{
"p": "area",
"v": "bayfield_co",
"vt": "str"
}
],
"repeat": "30",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 130,
"y": 760,
"wires": [
[
"26a089d3cbbb5ef1"
]
]
},
{
"id": "26a089d3cbbb5ef1",
"type": "subflow:0e70b91ae6570376",
"z": "ed4ea3c2bc13d1ec",
"g": "b11deb643761dfcf",
"name": "",
"x": 440,
"y": 760,
"wires": []
},
{
"id": "eed501c9777eecb5",
"type": "link in",
"z": "ed4ea3c2bc13d1ec",
"g": "b11deb643761dfcf",
"name": "Weather - KY Lake Alerts Trigger",
"links": [
"b98e25d5de4ce89c"
],
"x": 185,
"y": 820,
"wires": [
[
"26a089d3cbbb5ef1"
]
]
},
{
"id": "a1c109993f7dd396",
"type": "mqtt in",
@ -815,7 +1069,10 @@
"mode": "link",
"links": [
"42b8b21e40f8b824",
"67561d51aaa61dfa"
"5a0e961755fd6b45",
"67561d51aaa61dfa",
"028431d8cab86f80",
"eed501c9777eecb5"
],
"x": 335,
"y": 300,