Flow Details
- Upload the icons to your Awtrix.
There 2 configuration nodes:
- First, set your desired latitude and longitude in second configuration node, run it once, you will see output from console panel telling you the WFO and gridX, gridY you need.
- Second given the above information, change the first configuration node to match your desired settings.
- You may ignore authorization_header if no credentials are needed.
[
{
"id": "7efaf915ca5b7337",
"type": "tab",
"label": "Awtrix weather by api.weather.gov",
"disabled": false,
"info": "",
"env": []
},
{
"id": "97e239f3b23160ca",
"type": "group",
"z": "7efaf915ca5b7337",
"name": "Awtrix weather by api.weather.gov",
"style": {
"label": true
},
"nodes": [
"514be84e6537b208",
"a89bf6bc9b4ee6cd",
"43c8034f31d87da1",
"c3731eefae02dcb4",
"ef31a5c5cd4dbcfc",
"82f57ae3116cc75d",
"0654e5b8038248e8",
"d5cf1dbca661bcb3",
"515b12b72d5e63dc",
"8c1e5672f66cc334",
"52931d15a219febb",
"eb9f1cfe4f036184",
"7071c05bfb9d9ac7",
"97fb33089ff4fd73",
"ece47f29798a9a1f",
"eae9209dd318913e",
"9e4bcd38a1a73d39",
"95f76795e13faa31",
"6824085062f5947f",
"2ea88619e5304433",
"a849b46631023e92",
"b7d85c4da0f239fb"
],
"x": 214,
"y": 119,
"w": 2092,
"h": 482
},
{
"id": "514be84e6537b208",
"type": "http request",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "make weather request",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": true,
"headers": [],
"x": 1000,
"y": 200,
"wires": [
[
"43c8034f31d87da1",
"515b12b72d5e63dc"
]
]
},
{
"id": "a89bf6bc9b4ee6cd",
"type": "inject",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "check",
"props": [
{
"p": "payload"
}
],
"repeat": "900",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 330,
"y": 200,
"wires": [
[
"d5cf1dbca661bcb3"
]
]
},
{
"id": "43c8034f31d87da1",
"type": "debug",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "debug weather response",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1250,
"y": 380,
"wires": []
},
{
"id": "c3731eefae02dcb4",
"type": "change",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "generate weather request",
"rules": [
{
"t": "set",
"p": "url",
"pt": "msg",
"to": "https://api.weather.gov/gridpoints/{wfo}/{x,y}/forecast/hourly",
"tot": "str"
},
{
"t": "change",
"p": "url",
"pt": "msg",
"from": "{wfo}",
"fromt": "str",
"to": "wfo",
"tot": "flow"
},
{
"t": "change",
"p": "url",
"pt": "msg",
"from": "{x,y}",
"fromt": "str",
"to": "x,y",
"tot": "flow"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 750,
"y": 200,
"wires": [
[
"514be84e6537b208"
]
]
},
{
"id": "ef31a5c5cd4dbcfc",
"type": "catch",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "",
"scope": null,
"uncaught": false,
"x": 580,
"y": 560,
"wires": [
[
"82f57ae3116cc75d"
]
]
},
{
"id": "82f57ae3116cc75d",
"type": "debug",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "debug errors",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 790,
"y": 560,
"wires": []
},
{
"id": "0654e5b8038248e8",
"type": "comment",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "Change configuration in this node",
"info": "",
"x": 540,
"y": 160,
"wires": []
},
{
"id": "d5cf1dbca661bcb3",
"type": "change",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "configuration",
"rules": [
{
"t": "set",
"p": "wfo",
"pt": "flow",
"to": "OKX",
"tot": "str"
},
{
"t": "set",
"p": "x,y",
"pt": "flow",
"to": "36,36",
"tot": "str"
},
{
"t": "set",
"p": "use_fahrenheit",
"pt": "flow",
"to": "true",
"tot": "bool"
},
{
"t": "set",
"p": "awtrix_ip",
"pt": "flow",
"to": "192.168.1.101",
"tot": "str"
},
{
"t": "set",
"p": "awtrix_app_name",
"pt": "flow",
"to": "weather",
"tot": "str"
},
{
"t": "set",
"p": "authorization_header",
"pt": "flow",
"to": "Basic ZXhhbXBsZTpwYXNzd29yZA==",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 510,
"y": 200,
"wires": [
[
"c3731eefae02dcb4"
]
]
},
{
"id": "515b12b72d5e63dc",
"type": "function",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "frames generator",
"func": "const LIFETIME = '3600';\nconst PUSH_ICON = '0';\nconst REPEAT = '2';\nconst DURATION = '';\n// Look ahead 30 mins\nconst TIME_OFFSET_IN_MS = 30 * 60 * 1000;\nconst USE_FAHRENHEIT = flow.get('use_fahrenheit');\n\n// Match keyword case insensitive from top to bottom\n// Put \"cloudy\" before \"mostly cloudy\" will cause latter one never matches\nconst KEYWORD_TO_ICON_DICT = {\n 'storm': 'stormy',\n 'foggy': 'foggy',\n 'snow': 'snowy',\n 'rain': 'rainy',\n 'partly cloudy': 'partly_cloudy',\n 'cloudy': 'mostly_cloudy',\n 'clear': 'moon',\n 'sunny': 'sunny',\n '': 'weather_fallback',\n};\n\nconst createFrameWithTextAndIcon = (text, icon) => ({\n text,\n icon,\n lifetime: LIFETIME,\n pushIcon: PUSH_ICON,\n repeat: REPEAT,\n duration: DURATION,\n});\n\nconst mapShortForecastToIcon = (shortForecast) => {\n for (const keyword of Object.keys(KEYWORD_TO_ICON_DICT)) {\n if (shortForecast?.toLowerCase().includes(keyword?.toLowerCase())) {\n return KEYWORD_TO_ICON_DICT[keyword];\n }\n }\n};\n\nconst findPeriodNow = (periods, timeOffsetInMs = TIME_OFFSET_IN_MS) => {\n if (!Array.isArray(periods)) {\n throw new Error('periods should be array');\n }\n const timestampInEpoch = Date.now() + TIME_OFFSET_IN_MS;\n const found = periods.find(period => (new Date(period?.startTime)).valueOf() > timestampInEpoch);\n if (!found) {\n throw new Error(`unable to find period after ${timestampInEpoch}`);\n }\n return found;\n};\n\nconst FToC = (f, optionalDecimalPoints = 1) => Math.round((f - 32) * 5 / 9 * Math.pow(10, optionalDecimalPoints)) / Math.pow(10, optionalDecimalPoints);\n\nconst handleMessage = (message) => {\n const periods = message?.payload?.properties?.periods;\n if (!Array.isArray(periods)) {\n throw new Error('unable to parse msessage');\n }\n const frames = [];\n const currentPeriod = findPeriodNow(periods);\n const temperatureText = USE_FAHRENHEIT ? `${currentPeriod?.temperature}°F` : `${FToC(currentPeriod?.temperature)}°C`;\n frames.push(createFrameWithTextAndIcon(\n temperatureText,\n mapShortForecastToIcon(currentPeriod?.shortForecast),\n ));\n frames.push(createFrameWithTextAndIcon(\n currentPeriod?.shortForecast,\n mapShortForecastToIcon(currentPeriod?.shortForecast),\n ));\n frames.push(createFrameWithTextAndIcon(\n `${currentPeriod?.probabilityOfPrecipitation?.value}%`,\n 'umbrella',\n ));\n frames.push(createFrameWithTextAndIcon(\n // `${currentPeriod?.windSpeed} ${currentPeriod?.windDirection}`,\n currentPeriod?.windSpeed,\n 'wind',\n ));\n frames.push(createFrameWithTextAndIcon(\n `${currentPeriod?.relativeHumidity?.value}%`,\n 'humidity',\n ));\n message.payload.frames = frames;\n return message;\n};\n\nreturn handleMessage(msg);",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1250,
"y": 200,
"wires": [
[
"8c1e5672f66cc334",
"52931d15a219febb"
]
]
},
{
"id": "8c1e5672f66cc334",
"type": "debug",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "debug frames generator",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1530,
"y": 380,
"wires": []
},
{
"id": "52931d15a219febb",
"type": "change",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "generate awtrix request",
"rules": [
{
"t": "set",
"p": "method",
"pt": "msg",
"to": "POST",
"tot": "str"
},
{
"t": "set",
"p": "url",
"pt": "msg",
"to": "http://{awtrix_ip}/api/custom?name={awtrix_app_name}",
"tot": "str"
},
{
"t": "change",
"p": "url",
"pt": "msg",
"from": "{awtrix_ip}",
"fromt": "str",
"to": "awtrix_ip",
"tot": "flow"
},
{
"t": "change",
"p": "url",
"pt": "msg",
"from": "{awtrix_app_name}",
"fromt": "str",
"to": "awtrix_app_name",
"tot": "flow"
},
{
"t": "move",
"p": "headers",
"pt": "msg",
"to": "original_headers",
"tot": "msg"
},
{
"t": "move",
"p": "payload",
"pt": "msg",
"to": "original_payload",
"tot": "msg"
},
{
"t": "set",
"p": "headers.Authorization",
"pt": "msg",
"to": "authorization_header",
"tot": "flow"
},
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "original_payload.frames",
"tot": "msg",
"dc": true
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1510,
"y": 200,
"wires": [
[
"eb9f1cfe4f036184",
"7071c05bfb9d9ac7"
]
]
},
{
"id": "eb9f1cfe4f036184",
"type": "debug",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "debug awtrix request",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1820,
"y": 380,
"wires": []
},
{
"id": "7071c05bfb9d9ac7",
"type": "http request",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "make awtrix request",
"method": "use",
"ret": "txt",
"paytoqs": "body",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [
{
"keyType": "Content-Type",
"keyValue": "",
"valueType": "application/json",
"valueValue": ""
}
],
"x": 1860,
"y": 200,
"wires": [
[
"97fb33089ff4fd73"
]
]
},
{
"id": "97fb33089ff4fd73",
"type": "debug",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "debug awtrix response",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 2160,
"y": 380,
"wires": []
},
{
"id": "ece47f29798a9a1f",
"type": "inject",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "get WFO and gridX, gridY",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 370,
"y": 440,
"wires": [
[
"eae9209dd318913e"
]
]
},
{
"id": "eae9209dd318913e",
"type": "change",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "configuration",
"rules": [
{
"t": "set",
"p": "latitude",
"pt": "msg",
"to": "40.730610",
"tot": "str"
},
{
"t": "set",
"p": "longitude",
"pt": "msg",
"to": "-73.935242",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 590,
"y": 440,
"wires": [
[
"9e4bcd38a1a73d39"
]
]
},
{
"id": "9e4bcd38a1a73d39",
"type": "change",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "generate grid lookup request",
"rules": [
{
"t": "set",
"p": "url",
"pt": "msg",
"to": "https://api.weather.gov/points/{latitude},{longitude}",
"tot": "str"
},
{
"t": "change",
"p": "url",
"pt": "msg",
"from": "{latitude}",
"fromt": "str",
"to": "latitude",
"tot": "msg"
},
{
"t": "change",
"p": "url",
"pt": "msg",
"from": "{longitude}",
"fromt": "str",
"to": "longitude",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 840,
"y": 440,
"wires": [
[
"95f76795e13faa31"
]
]
},
{
"id": "95f76795e13faa31",
"type": "http request",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "make grid lookup request",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": true,
"headers": [],
"x": 1110,
"y": 440,
"wires": [
[
"6824085062f5947f",
"2ea88619e5304433"
]
]
},
{
"id": "6824085062f5947f",
"type": "debug",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "debug grid lookup response",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1380,
"y": 540,
"wires": []
},
{
"id": "2ea88619e5304433",
"type": "template",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "NWS Weather Forecast Office (WFO):\n{{payload.properties.gridId}}\nLocation gridX:\n{{payload.properties.gridX}}\nLocation gridY:\n{{payload.properties.gridY}}",
"output": "str",
"x": 1380,
"y": 440,
"wires": [
[
"a849b46631023e92"
]
]
},
{
"id": "a849b46631023e92",
"type": "debug",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "printout WFO and gridX, gridY",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1630,
"y": 440,
"wires": []
},
{
"id": "b7d85c4da0f239fb",
"type": "comment",
"z": "7efaf915ca5b7337",
"g": "97e239f3b23160ca",
"name": "Change configuration in this node to get WFO and gridX, gridY needed for configuration above",
"info": "",
"x": 640,
"y": 380,
"wires": []
}
]
-- Flow first published on February 15, 2024.