Parsing Weather.gov API

Weather.gov provides an API for US weather, partly documented here:
API Web Service

The following example pulls localized weather data
https://api.weather.gov/gridpoints/ILM/89,69

So, to grab the temperature at for a specific period I'd do something like:

let period=msg.payload.properties.temperature.values[n].validTime
let period_temp=msg.payload.properties.temperature.values[n].value

where n is an array representing some period in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format

Any suggestion on the best approach to parsing this data in Node Red?

As an example, I'd like to get the temp/weather forecast for some arbitrary future time (say 6 hours from now). My first thought is to write a function node with a forEach loop, comparing Now to the validTime. I can see myself going deep down a rabbit hole trying to figure out the best approach. Posting some example flows for weather.gov seems to me would be useful to a lot of people.

You can use the find() method of javascript to find the first match of the data
with some Jsonata in a Change node you can manipulate the Date format to match the API date format
(as an example i created a Date based on todays date and time but rounded to the hour)

[{"id":"af724c25d3f6de5f","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":150,"y":1420,"wires":[["71cf2282698b9b75"]]},{"id":"ab33310b81de87f4","type":"http request","z":"54efb553244c241f","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.weather.gov/gridpoints/ILM/89,69","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":530,"y":1420,"wires":[["38b783ee3fe21080"]]},{"id":"df27ee4e1d2497d4","type":"debug","z":"54efb553244c241f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":1420,"wires":[]},{"id":"38b783ee3fe21080","type":"function","z":"54efb553244c241f","name":"","func":"let values = msg.payload.properties.temperature.values\nlet selectTime = msg.selectTime\n\nmsg.payload = values.find(el => el.validTime.startsWith(selectTime))\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":700,"y":1420,"wires":[["df27ee4e1d2497d4"]]},{"id":"71cf2282698b9b75","type":"change","z":"54efb553244c241f","name":"","rules":[{"t":"set","p":"selectTime","pt":"msg","to":"$moment().format('YYYY-MM-DDTHH:00:00')","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":1420,"wires":[["ab33310b81de87f4","90c4ec6922dd358d"]]},{"id":"90c4ec6922dd358d","type":"debug","z":"54efb553244c241f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":510,"y":1340,"wires":[]}]

[EDIT]

Here is another example with the Moment library loaded in the Function node ( functionExternalModules )
utilizing its isBetween method to filter data for a range of datetimes

image

[{"id":"af724c25d3f6de5f","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":150,"y":1420,"wires":[["ab33310b81de87f4"]]},{"id":"ab33310b81de87f4","type":"http request","z":"54efb553244c241f","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.weather.gov/gridpoints/ILM/89,69","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":350,"y":1420,"wires":[["90c4ec6922dd358d","38b783ee3fe21080"]]},{"id":"df27ee4e1d2497d4","type":"debug","z":"54efb553244c241f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":770,"y":1420,"wires":[]},{"id":"38b783ee3fe21080","type":"function","z":"54efb553244c241f","name":"","func":"let values = msg.payload.properties.temperature.values\nlet startTime = moment().utc()\nlet endTime = moment().utc().add(6, 'hours')\nnode.warn({ startTime, endTime })\n\nmsg.payload = values.filter(el => moment(el.validTime.split(\"/\")[0]).isBetween(startTime, endTime))\n       \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"moment","module":"moment"}],"x":560,"y":1420,"wires":[["df27ee4e1d2497d4"]]},{"id":"90c4ec6922dd358d","type":"debug","z":"54efb553244c241f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":490,"y":1340,"wires":[]}]

The forecast are in hourly sequence so array 0 will be 1 hour forecast, and 5 should be 6 hour forecast
eg.

[{"id":"487bb69.cdeb548","type":"inject","z":"c791cbc0.84f648","name":"","props":[{"p":"payload"},{"p":"forecast","v":"5","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":190,"y":220,"wires":[["62b6106c.8a6c1"]]},{"id":"62b6106c.8a6c1","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"https://api.weather.gov/points/39.7456,-97.0892","tot":"str"},{"t":"set","p":"headers.user-agent","pt":"msg","to":"my_user_agent","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":240,"wires":[["c6c4a080.408b3"]]},{"id":"c6c4a080.408b3","type":"http request","z":"c791cbc0.84f648","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":570,"y":240,"wires":[["5c510ec6.b300b8"]]},{"id":"5c510ec6.b300b8","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"payload.properties.forecastHourly","tot":"msg"},{"t":"delete","p":"headers","pt":"msg"},{"t":"set","p":"headers.user-agent","pt":"msg","to":"my_user_agent","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":280,"wires":[["5f27466d.75f038"]]},{"id":"5f27466d.75f038","type":"http request","z":"c791cbc0.84f648","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":280,"wires":[["4467f7ce.e212a8"]]},{"id":"4467f7ce.e212a8","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.properties.periods[$$.forecast]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1010,"y":280,"wires":[["dab1571e.83d498"]]},{"id":"dab1571e.83d498","type":"debug","z":"c791cbc0.84f648","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1030,"y":200,"wires":[]}]

The data takes two requests, one to retrieve url for the grid reference of your coordinates, then one to retrieve the forecast json.

[edit] When first saw the results it looked like the forecast array was starting at the current time, due to timezone. But it appears they are not.
so the in built Jsonata time fuctions should get you the result you require.
e.g

[{"id":"487bb69.cdeb548","type":"inject","z":"c791cbc0.84f648","name":"","props":[{"p":"payload"},{"p":"forecast","v":"6","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":190,"y":220,"wires":[["62b6106c.8a6c1"]]},{"id":"62b6106c.8a6c1","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"https://api.weather.gov/points/39.7456,-97.0892","tot":"str"},{"t":"set","p":"headers.user-agent","pt":"msg","to":"my_user_agent","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":240,"wires":[["c6c4a080.408b3"]]},{"id":"c6c4a080.408b3","type":"http request","z":"c791cbc0.84f648","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":570,"y":240,"wires":[["5c510ec6.b300b8"]]},{"id":"5c510ec6.b300b8","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"payload.properties.forecastHourly","tot":"msg"},{"t":"delete","p":"headers","pt":"msg"},{"t":"set","p":"headers.user-agent","pt":"msg","to":"my_user_agent","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":280,"wires":[["5f27466d.75f038"]]},{"id":"5f27466d.75f038","type":"http request","z":"c791cbc0.84f648","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":790,"y":280,"wires":[["bdb1705b.6db87"]]},{"id":"bdb1705b.6db87","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.properties.periods[$toMillis(startTime) > $millis()+(3600000 * $$.forecast)][0]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1020,"y":280,"wires":[["dab1571e.83d498"]]},{"id":"dab1571e.83d498","type":"debug","z":"c791cbc0.84f648","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1030,"y":200,"wires":[]}]

I guess I'm drawn to doing things the hardway, lol! Though, some data I'm looking for isn't in that feed.

Do you know if there is a database of responses for weather.gov? For eample, there seems to be several variations for its "snowing" in the shortForecast property.

API Web Services
If you click specification on that page then you can expand all GET requests and see the responses, and further down the page are the schema's.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.