JSON Api weather data

Hello.

I want to filter out some of the weather data from this api.
https://api.met.no/weatherapi/locationforecast/2.0/complete?altitude=70&lat=59.023441&lon=6.041370

I am new to node red, and i dont know where to start. So im hoping soneone here could help me in the right direction

Thanks

What is your level of programming knowledge? Do you know any JavaScript or similar?

THere are 2 main ways to extract data from JSON data. JSONata and a function node. Which is best depends on your knowledge and preference. JSONata is great for certain things but will suddenly get impossible difficult whereas a function node is just JavaScript code that gets the incoming msg (there's a bit more to it than that but that's the basics).

If you dump the JSON to a debug node, you will see it's structure which is a great help to begin to understand how to get data out of it. The debug node even lets you copy the "path" to a specific property so that you can include it in your code.

Hi and welcome.

You will need to do a http request to get the return JSON. The site requires that user-agent is set in the headers so you may want to read this info from the docs.

here is a simple example, the header is set in th inject node just for this example. You can also use a change node or function. The http request node is set to return a JSON object. so you may also want to read about about mssages and how they work

[{"id":"e6c446cf.b7e26","type":"http request","z":"8d22ae29.7df6d","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.met.no/weatherapi/locationforecast/2.0/complete?altitude=70&lat=59.023441&lon=6.041370","tls":"","persist":false,"proxy":"","authType":"","x":340,"y":2620,"wires":[["eaeada19.7042a"]]},{"id":"676fa2c6.4727ac","type":"inject","z":"8d22ae29.7df6d","name":"","props":[{"p":"headers","v":"{\"User-Agent\":\"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0\"}","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":190,"y":2620,"wires":[["e6c446cf.b7e26"]]},{"id":"eaeada19.7042a","type":"debug","z":"8d22ae29.7df6d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":500,"y":2620,"wires":[]}]

Hope this helps you get started

Thanks you both @E1cid and @TotallyInformation . I am not much into javascript. I have been programming PLCs, and the most comparable PLC language would be ST.

I have briefly read the links, which i will read more tonight. But I have testet with the code embedded below.

I can see the data coming in, and i manage to filter out one datapoint for testing :slight_smile:

Any suggestion for improving this code? Or any comments?

[{"id":"8d1d8f1c.dd3a4","type":"tab","label":"Værdata","disabled":false,"info":""},{"id":"32dab920.d5dbf6","type":"http request","z":"8d1d8f1c.dd3a4","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.met.no/weatherapi/locationforecast/2.0/complete?altitude=70&lat=59.023441&lon=6.041370","tls":"","persist":false,"proxy":"","authType":"","x":290,"y":220,"wires":[["ac4dd9e8.571d78","74983ee6.88a54"]]},{"id":"f2673a9b.4e3f58","type":"inject","z":"8d1d8f1c.dd3a4","name":"","props":[{"p":"headers","v":"{\"User-Agent\":\"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0\"}","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":140,"y":220,"wires":[["32dab920.d5dbf6"]]},{"id":"ac4dd9e8.571d78","type":"function","z":"8d1d8f1c.dd3a4","name":"","func":"var temperature;\n\ntemperature = msg.payload.properties.timeseries[44].data.instant.details.air_temperature;\n\n\nmsg.payload = {\n    \"AirTemp\": temperature};\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":520,"y":220,"wires":[["1a46b956.1dc3d7"]]},{"id":"74983ee6.88a54","type":"debug","z":"8d1d8f1c.dd3a4","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":140,"wires":[]},{"id":"1a46b956.1dc3d7","type":"change","z":"8d1d8f1c.dd3a4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.AirTemp","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":740,"y":220,"wires":[["471a1a77.6ed304","38fd9095.b7a69"]]},{"id":"471a1a77.6ed304","type":"debug","z":"8d1d8f1c.dd3a4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":950,"y":140,"wires":[]},{"id":"38fd9095.b7a69","type":"ui_gauge","z":"8d1d8f1c.dd3a4","name":"","group":"f9386359.1b288","order":1,"width":0,"height":0,"gtype":"gage","title":"Temperature","label":"units","format":"{{value}}","min":0,"max":"15","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":950,"y":220,"wires":[]},{"id":"f9386359.1b288","type":"ui_group","z":"","name":"Default","tab":"f4280269.47236","order":1,"disp":true,"width":"6","collapse":false},{"id":"f4280269.47236","type":"ui_tab","z":"","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]

You seem to be getting the idea,. One thing, you can access the info directly in the change node, no need for the function as well.

[{"id":"33149722.b071e","type":"inject","z":"eafbaccc.fc1738","name":"","props":[{"p":"headers","v":"{\"User-Agent\":\"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0\"}","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":220,"wires":[["d938a3b2.68497"]]},{"id":"d938a3b2.68497","type":"http request","z":"eafbaccc.fc1738","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.met.no/weatherapi/locationforecast/2.0/complete?altitude=70&lat=59.023441&lon=6.041370","tls":"","persist":false,"proxy":"","authType":"","x":290,"y":220,"wires":[["42b1fdc0.8b85a4","4be9ab90.dc0c24"]]},{"id":"42b1fdc0.8b85a4","type":"debug","z":"eafbaccc.fc1738","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":430,"y":160,"wires":[]},{"id":"4be9ab90.dc0c24","type":"change","z":"eafbaccc.fc1738","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.properties.timeseries[44].data.instant.details.air_temperature","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":220,"wires":[["e9454cc6.831e98","d6d1aaab.1d1948"]]},{"id":"e9454cc6.831e98","type":"debug","z":"eafbaccc.fc1738","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":690,"y":140,"wires":[]},{"id":"d6d1aaab.1d1948","type":"ui_gauge","z":"eafbaccc.fc1738","name":"","group":"6fb38b74.e2bd74","order":1,"width":0,"height":0,"gtype":"gage","title":"Temperature","label":"units","format":"{{value}}","min":0,"max":"15","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":750,"y":220,"wires":[]},{"id":"6fb38b74.e2bd74","type":"ui_group","z":"","name":"Default","tab":"fcb45faf.6e90c","order":1,"disp":true,"width":"6","collapse":false},{"id":"fcb45faf.6e90c","type":"ui_tab","z":"","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]

Thank you @E1cid , thats easier for 1 variable. Next step is to filter out the air temperature each hours the next 7 days. So 168 variables.

I think an array would be easiest. Not quite sure how to declare the array. And after I want to publish this array to OPCUA.

Am i onto something here?

Thanks again for all help :slight_smile:

Most things in JavaScript have multiple ways of doing things. In this case, the easiest way to declare an empty array is const myarray = [] Note that you can declare an array or an object as a const but still make changes to it, you just can't replace the whole thing with something like myarray = [1,2,3]

For what you want, it would be easier to do:

const times = msg.payload.properties.timeseries
const temperature = [
    times[0].data.xxxx
    ....
]

msg.payload = temperature
return msg

You can also use delete to get rid of things out of an object. However, remember that all variables and arguments are passed by reference in JavaScript, not by value. It is easy to accidentally delete something from a variable and only later realise that it does, of course, also delete from the original not just the reference. :unamused:

Something like this maybe?

[{"id":"f7d259d.03d7ca8","type":"inject","z":"8d22ae29.7df6d","name":"","props":[{"p":"headers","v":"{\"User-Agent\":\"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0\"}","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":180,"y":2460,"wires":[["89fa7892.ced66"]]},{"id":"89fa7892.ced66","type":"http request","z":"8d22ae29.7df6d","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.met.no/weatherapi/locationforecast/2.0/complete?altitude=70&lat=59.023441&lon=6.041370","tls":"","persist":false,"proxy":"","authType":"","x":330,"y":2460,"wires":[["d3a7e4db.cd5818"]]},{"id":"d3a7e4db.cd5818","type":"change","z":"8d22ae29.7df6d","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"airtemps\":payload.properties.timeseries[*].data.instant.details.air_temperature}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":2460,"wires":[["4e8067ed.73c6a"]]},{"id":"4e8067ed.73c6a","type":"debug","z":"8d22ae29.7df6d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":610,"y":2400,"wires":[]}]

Thanks again both of you @TotallyInformation and @E1cid :slight_smile:

Both ways works fine. I also managed to publish this array to my OPCUA server, which is a Wago PLC.

If you have any improvement to this I am thankful :slight_smile:

I also want to use a variable to trigger the http request. And i also want to set up a Gauge to display ex array[17]. Any ideas how to do this? :slight_smile:

And I was thinking it would be smart to use a for loop to get the data info the array. I tried like this, but i only get 1 datapoint.
image

And is there a way to get rid of all this red text showing up in de debug window?

Thanks in advance :slight_smile:

And here is the code so far:

[{"id":"8d1d8f1c.dd3a4","type":"tab","label":"Værdata","disabled":false,"info":""},{"id":"c5c068bb.040ca8","type":"debug","z":"8d1d8f1c.dd3a4","name":"Data fra api.met.no","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":590,"y":260,"wires":[]},{"id":"3d1ac866.952508","type":"OpcUa-Client","z":"8d1d8f1c.dd3a4","endpoint":"d66a982f.e2c078","action":"write","deadbandtype":"a","deadbandvalue":1,"time":10,"timeUnit":"s","certificate":"n","localfile":"","securitymode":"None","securitypolicy":"None","name":"","x":1240,"y":320,"wires":[[]]},{"id":"344fd399.f5ce6c","type":"debug","z":"8d1d8f1c.dd3a4","name":"Temperatur Array","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":910,"y":260,"wires":[]},{"id":"b5399af0.72ebd8","type":"http request","z":"8d1d8f1c.dd3a4","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.met.no/weatherapi/locationforecast/2.0/complete?altitude=70&lat=59.023441&lon=6.041370","tls":"","persist":false,"proxy":"","authType":"","x":390,"y":320,"wires":[["86f7bed4.dec77","c5c068bb.040ca8","c7c09a0b.fc9918"]]},{"id":"86f7bed4.dec77","type":"function","z":"8d1d8f1c.dd3a4","name":"Temperatur","func":"const times = msg.payload.properties.timeseries\n\n\nconst rAirtemps = [\ntimes[0].data.instant.details.air_temperature,\ntimes[1].data.instant.details.air_temperature,\ntimes[2].data.instant.details.air_temperature,\ntimes[3].data.instant.details.air_temperature,\ntimes[4].data.instant.details.air_temperature,\ntimes[5].data.instant.details.air_temperature,\ntimes[6].data.instant.details.air_temperature,\ntimes[7].data.instant.details.air_temperature,\ntimes[8].data.instant.details.air_temperature,\ntimes[9].data.instant.details.air_temperature,\ntimes[10].data.instant.details.air_temperature,\ntimes[11].data.instant.details.air_temperature,\ntimes[12].data.instant.details.air_temperature,\ntimes[13].data.instant.details.air_temperature,\ntimes[14].data.instant.details.air_temperature,\ntimes[15].data.instant.details.air_temperature,\ntimes[16].data.instant.details.air_temperature,\ntimes[17].data.instant.details.air_temperature,\ntimes[18].data.instant.details.air_temperature,\ntimes[19].data.instant.details.air_temperature,\ntimes[20].data.instant.details.air_temperature,\ntimes[21].data.instant.details.air_temperature,\ntimes[22].data.instant.details.air_temperature,\ntimes[23].data.instant.details.air_temperature,\ntimes[24].data.instant.details.air_temperature,\ntimes[25].data.instant.details.air_temperature,\ntimes[26].data.instant.details.air_temperature,\ntimes[27].data.instant.details.air_temperature,\ntimes[28].data.instant.details.air_temperature,\ntimes[29].data.instant.details.air_temperature,\ntimes[30].data.instant.details.air_temperature,\ntimes[31].data.instant.details.air_temperature,\ntimes[32].data.instant.details.air_temperature,\ntimes[33].data.instant.details.air_temperature,\ntimes[34].data.instant.details.air_temperature,\ntimes[35].data.instant.details.air_temperature,\ntimes[36].data.instant.details.air_temperature,\ntimes[37].data.instant.details.air_temperature,\ntimes[38].data.instant.details.air_temperature,\ntimes[39].data.instant.details.air_temperature,\ntimes[40].data.instant.details.air_temperature,\ntimes[41].data.instant.details.air_temperature,\ntimes[42].data.instant.details.air_temperature,\ntimes[43].data.instant.details.air_temperature,\ntimes[44].data.instant.details.air_temperature,\ntimes[45].data.instant.details.air_temperature,\ntimes[46].data.instant.details.air_temperature,\ntimes[47].data.instant.details.air_temperature,\ntimes[48].data.instant.details.air_temperature,\ntimes[49].data.instant.details.air_temperature,\ntimes[50].data.instant.details.air_temperature,\n\n]\n\nmsg.payload = rAirtemps\nreturn msg\n\n\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":730,"y":320,"wires":[["e23bffa4.09488","344fd399.f5ce6c"]]},{"id":"e23bffa4.09488","type":"OpcUa-Item","z":"8d1d8f1c.dd3a4","item":"ns=4;s=|var|WAGO 750-8212 PFC200 G2 2ETH RS.Application.gvl_OpcUA.rAirtemps","datatype":"Float Array","value":"","name":"Temperatur OPC ","x":970,"y":320,"wires":[["3d1ac866.952508"]]},{"id":"c17d1b4b.a153a8","type":"inject","z":"8d1d8f1c.dd3a4","name":"","props":[{"p":"headers","v":"{\"User-Agent\":\"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0\"}","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":150,"y":320,"wires":[["b5399af0.72ebd8"]]},{"id":"c7c09a0b.fc9918","type":"function","z":"8d1d8f1c.dd3a4","name":"Nedbør","func":"const times = msg.payload.properties.timeseries\n\n\nconst rPrecipitation = [\ntimes[0].data.next_1_hours.details.precipitation_amount,\ntimes[1].data.next_1_hours.details.precipitation_amount,\ntimes[2].data.next_1_hours.details.precipitation_amount,\ntimes[3].data.next_1_hours.details.precipitation_amount,\ntimes[4].data.next_1_hours.details.precipitation_amount,\ntimes[5].data.next_1_hours.details.precipitation_amount,\ntimes[6].data.next_1_hours.details.precipitation_amount,\ntimes[7].data.next_1_hours.details.precipitation_amount,\ntimes[8].data.next_1_hours.details.precipitation_amount,\ntimes[9].data.next_1_hours.details.precipitation_amount,\ntimes[10].data.next_1_hours.details.precipitation_amount,\ntimes[11].data.next_1_hours.details.precipitation_amount,\ntimes[12].data.next_1_hours.details.precipitation_amount,\ntimes[13].data.next_1_hours.details.precipitation_amount,\ntimes[14].data.next_1_hours.details.precipitation_amount,\ntimes[15].data.next_1_hours.details.precipitation_amount,\ntimes[16].data.next_1_hours.details.precipitation_amount,\ntimes[17].data.next_1_hours.details.precipitation_amount,\ntimes[18].data.next_1_hours.details.precipitation_amount,\ntimes[19].data.next_1_hours.details.precipitation_amount,\ntimes[20].data.next_1_hours.details.precipitation_amount,\ntimes[21].data.next_1_hours.details.precipitation_amount,\ntimes[22].data.next_1_hours.details.precipitation_amount,\ntimes[23].data.next_1_hours.details.precipitation_amount,\ntimes[24].data.next_1_hours.details.precipitation_amount,\ntimes[25].data.next_1_hours.details.precipitation_amount,\ntimes[26].data.next_1_hours.details.precipitation_amount,\ntimes[27].data.next_1_hours.details.precipitation_amount,\ntimes[28].data.next_1_hours.details.precipitation_amount,\ntimes[29].data.next_1_hours.details.precipitation_amount,\ntimes[30].data.next_1_hours.details.precipitation_amount,\ntimes[31].data.next_1_hours.details.precipitation_amount,\ntimes[32].data.next_1_hours.details.precipitation_amount,\ntimes[33].data.next_1_hours.details.precipitation_amount,\ntimes[34].data.next_1_hours.details.precipitation_amount,\ntimes[35].data.next_1_hours.details.precipitation_amount,\ntimes[36].data.next_1_hours.details.precipitation_amount,\ntimes[37].data.next_1_hours.details.precipitation_amount,\ntimes[38].data.next_1_hours.details.precipitation_amount,\ntimes[39].data.next_1_hours.details.precipitation_amount,\ntimes[40].data.next_1_hours.details.precipitation_amount,\ntimes[41].data.next_1_hours.details.precipitation_amount,\ntimes[42].data.next_1_hours.details.precipitation_amount,\ntimes[43].data.next_1_hours.details.precipitation_amount,\ntimes[44].data.next_1_hours.details.precipitation_amount,\ntimes[45].data.next_1_hours.details.precipitation_amount,\ntimes[46].data.next_1_hours.details.precipitation_amount,\ntimes[47].data.next_1_hours.details.precipitation_amount,\ntimes[48].data.next_1_hours.details.precipitation_amount,\ntimes[49].data.next_1_hours.details.precipitation_amount,\ntimes[50].data.next_1_hours.details.precipitation_amount,\n]\n\nmsg.payload = rPrecipitation\nreturn msg\n\n\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":720,"y":380,"wires":[["ca3d45e4.b20d78","9841c0f.05a664"]]},{"id":"ca3d45e4.b20d78","type":"OpcUa-Item","z":"8d1d8f1c.dd3a4","item":"ns=4;s=|var|WAGO 750-8212 PFC200 G2 2ETH RS.Application.gvl_OpcUA.rPrecipitation","datatype":"Float Array","value":"","name":"Nedbør OPC","x":950,"y":380,"wires":[["3d1ac866.952508"]]},{"id":"9841c0f.05a664","type":"debug","z":"8d1d8f1c.dd3a4","name":"Nedbør Array","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":890,"y":440,"wires":[]},{"id":"d66a982f.e2c078","type":"OpcUa-Endpoint","z":"","endpoint":"opc.tcp://10.0.0.15:4840","secpol":"None","secmode":"None","login":false}]

It is much easier if you paste code into your posts as code because then we can reference it. Saves a lot of time.

In Javascript there are many ways to process arrays. Have a look at the Array.prototype.forEach() function which is why I normally use. Much quicker (in coding terms) and less error prone than trying to use a for loop.

const rAirtemps = []
times.forEach( (item, idx) => {
    // `item` now contains each element, 
    // idx contains the current index (miss that off if you don't need it) 
    // so ...
    rAirtemps.push(item.data.instant.details.air_temperature)
} )

To add entries to an array, you have to push it.

Thank you so much. Works very well for air temperature:

const times = msg.payload.properties.timeseries

const rTemperature = []
times.forEach( (item, idx) => {
    rTemperature.push(item.data.instant.details.air_temperature)
} )

msg.payload = rTemperature
return msg

But its not working for precipitation:

const times = msg.payload.properties.timeseries

const rPrecipitation = []
times.forEach( (item, idx) => {
   rPrecipitation.push(item.data.next_1_hours.details.precipitation_amount)
} )

msg.payload = rPrecipitation
return msg

Any ideas?

Couple of things. First, when sharing example flows, best to avoid including non-core nodes if you can as it can be painful for people trying to deploy your example.

Secondly, best to avoid repeating triggers, especially for calls to external API's as most of them have limits that you will soon exceed and again, anyone trying out the example could also end up blocked as well.

The reason your second example fails is because not all of the timeseries arry objects actually contain the data.next_1_hours.details.precipitation_amount property. There are 84 entries with temperature but only 56 with precipitation.

Here is a safer version of the function node:

const times = msg.payload.properties.timeseries

const rTemperature = [], rPrecipitation = []

times.forEach( item => {
    try{
        rTemperature.push(item.data.instant.details.air_temperature)
    } catch (e) {}
    try{
        rPrecipitation.push(item.data.next_1_hours.details.precipitation_amount)
    } catch (e) {}
} )

msg.payload = {
    'precipitation': rPrecipitation,
    'temperature': rTemperature,
    'full': msg.payload
}

return msg

I didn't bother to work out whether it was the precipitation missing or some higher-level property. Node-RED does also provide some utility functions for safely accessing deep property objects.

By the way, I have a few other weather services that I've tested:

There is also a thread somewhere on the forum where I produced a comparison table of the various features.

Thank you :slight_smile:

I will look into that thread!

But i need the temperature, precipitation etc in different nodes when publishing to OPCUA. Would you seperate the last code you send into 3 functions then?

EDIT:
@TotallyInformation i read that i need to identify myself when using this service. How can i do that?

EDIT 2:
Now i get this error for some reason. What causes this?
image
image

Personally, I would do it all in 1 function node with 3 outputs. Then you only need to walk through the array once. But it isn't really enough of an overhead to worry about even if you do it in multiple functions.

For Norway MET? No, I just use this API: https://api.met.no/weatherapi/locationforecast/2.0/complete.json and give it my location.

I did mention limits didn't I? I think that you've hit them and it has blocked you for a while. Try again tomorrow maybe and don't keep hitting their API. Look at how often they update their forecasts and what limits they apply. Do you really need to check a forecast every minute? I think not. They are, after all, providing that service for free. I would never check a forecast more than once an hour, maybe as little as twice a day. Depends on the API.

Thanks again @TotallyInformation. You have really been helping me out here.

I think you are right, that I have been hitting their API way to often. And ofc i dont need to update that often. Hope that they let me get data from them tomorrow, and i can set the update to every 6hours or something.

I would very much like to have all three in one function. But I dont know how to output it to my OPCUA client. As you see below, I need to set an unique node-id for each array. If you have any idea how I can set the ID for each, and still use only one function I would be happy :slight_smile:

image

Complete code:

[{"id":"eb41f62a.95ba98","type":"tab","label":"Flow 2","disabled":false,"info":""},{"id":"ec96248a.501ff8","type":"inject","z":"eb41f62a.95ba98","name":"","props":[{"p":"headers","v":"{\"User-Agent\":\"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0\"}","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"str","x":230,"y":260,"wires":[["540deca8.606db4"]]},{"id":"540deca8.606db4","type":"http request","z":"eb41f62a.95ba98","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.met.no/weatherapi/locationforecast/2.0/complete?altitude=75&lat=59.0234&lon=6.0413","tls":"","persist":false,"proxy":"","authType":"","x":430,"y":260,"wires":[["80425272.3349b","f6d39a76.0babf8","52a029d4.745de8"]]},{"id":"80425272.3349b","type":"function","z":"eb41f62a.95ba98","name":"Temperature","func":"const times = msg.payload.properties.timeseries\n\nconst rTemperature = []\n\ntimes.forEach( item => {\n    try{\n        rTemperature.push(item.data.instant.details.air_temperature)\n    } catch (e) {}\n} )\n\nmsg.payload = {\n    'rTemperature': rTemperature,\n}\n\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","x":710,"y":200,"wires":[["4d909134.70fb3"]]},{"id":"4d909134.70fb3","type":"OpcUa-Item","z":"eb41f62a.95ba98","item":"ns=4;s=|var|WAGO 750-8212 PFC200 G2 2ETH RS.Application.gvl_OpcUA.rTemperature","datatype":"Float Array","value":"","name":"OPC","x":890,"y":200,"wires":[["75755866.201688"]]},{"id":"f6d39a76.0babf8","type":"function","z":"eb41f62a.95ba98","name":"Precipitation","func":"const times = msg.payload.properties.timeseries\n\nconst rPrecipitation = []\n\ntimes.forEach( item => {\n    try{\n        rPrecipitation.push(item.data.next_1_hours.details.precipitation_amount)\n    } catch (e) {}\n} )\n\nmsg.payload = {\n    'rPrecipitation': rPrecipitation,\n}\n\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","x":710,"y":260,"wires":[["8ca64652.1ea968"]]},{"id":"52a029d4.745de8","type":"function","z":"eb41f62a.95ba98","name":"Probability","func":"const times = msg.payload.properties.timeseries\n\nconst rProbability = []\n\ntimes.forEach( item => {\n    try{\n        rProbability.push(item.data.next_1_hours.details.probability_of_precipitation)\n    } catch (e) {}\n} )\n\nmsg.payload = {\n    \n    'rProbability': rProbability\n}\n\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","x":710,"y":320,"wires":[["cb19f82a.74d718"]]},{"id":"8ca64652.1ea968","type":"OpcUa-Item","z":"eb41f62a.95ba98","item":"ns=4;s=|var|WAGO 750-8212 PFC200 G2 2ETH RS.Application.gvl_OpcUA.rPrecipitation","datatype":"Float Array","value":"","name":"OPC","x":890,"y":260,"wires":[["75755866.201688"]]},{"id":"cb19f82a.74d718","type":"OpcUa-Item","z":"eb41f62a.95ba98","item":"ns=4;s=|var|WAGO 750-8212 PFC200 G2 2ETH RS.Application.gvl_OpcUA.rProbability","datatype":"Float Array","value":"","name":"OPC","x":890,"y":320,"wires":[["75755866.201688"]]},{"id":"75755866.201688","type":"OpcUa-Client","z":"eb41f62a.95ba98","endpoint":"38f7b58f.008a3a","action":"write","deadbandtype":"a","deadbandvalue":1,"time":10,"timeUnit":"s","certificate":"n","localfile":"","securitymode":"None","securitypolicy":"None","name":"","x":1160,"y":260,"wires":[[]]},{"id":"38f7b58f.008a3a","type":"OpcUa-Endpoint","z":"","endpoint":"opc.tcp://10.0.0.15:4840","secpol":"None","secmode":"None","login":false}]

I don't use OpcUa so I can't really help there. but the following single function node gives you 3 different outputs and should give you the starting point.

[{"id":"528413a1.1e001c","type":"debug","z":"d915a360.b8766","name":"Temperatur Array","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":670,"y":1400,"wires":[]},{"id":"7eaaffa4.60769","type":"http request","z":"d915a360.b8766","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.met.no/weatherapi/locationforecast/2.0/complete?altitude=70&lat=59.023441&lon=6.041370","tls":"","persist":false,"proxy":"","authType":"","x":290,"y":1440,"wires":[["d776f5f6.d8a8f8"]]},{"id":"d776f5f6.d8a8f8","type":"function","z":"d915a360.b8766","name":"Combined","func":"const times = msg.payload.properties.timeseries\n\nconst rTemperature = [], rPrecipitation = []\n\ntimes.forEach( item => {\n    rTemperature.push(item.data.instant.details.air_temperature)\n    try{\n    rPrecipitation.push(item.data.next_1_hours.details.precipitation_amount)\n    } catch (e) {\n        console.warn(item)\n    }\n} )\n\n// msg.payload = {\n//     'precipitation': rPrecipitation,\n//     'temperature': rTemperature,\n//     'full': msg.payload\n// }\n\nreturn [\n    {\n        topic: msg.topic,\n        temp: rTemperature,\n    },\n    {\n        topic: msg.topic,\n        temp: rPrecipitation,\n    },\n    {\n        topic: msg.topic,\n        full: msg.payload,\n    },\n]","outputs":3,"noerr":0,"initialize":"","finalize":"","x":470,"y":1440,"wires":[["528413a1.1e001c"],["7838d859.eb7b68"],["f3224afc.dbac18"]]},{"id":"f8a93ca2.f21b1","type":"inject","z":"d915a360.b8766","name":"","props":[{"p":"headers","v":"{\"User-Agent\":\"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0\"}","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":150,"y":1440,"wires":[["7eaaffa4.60769"]]},{"id":"fc1bf5a7.8c3a48","type":"comment","z":"d915a360.b8766","name":"met.no","info":"","x":160,"y":1380,"wires":[]},{"id":"7838d859.eb7b68","type":"debug","z":"d915a360.b8766","name":"Precip Array","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":650,"y":1440,"wires":[]},{"id":"f3224afc.dbac18","type":"debug","z":"d915a360.b8766","name":"full","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":630,"y":1480,"wires":[]}]

Armed with what you've learned now, you might want to go through the Node-RED docs again so that the concepts bed in. It can take a few times before some of the things gel, I know.

Thank you @TotallyInformation. Thats perfect!

I will for sure read trough the docs again, and do alot of testing. Im starting to getting into node-red, thanks to you. I really want to learn more :slight_smile:

What if I only want 20 lines? I tested with if statement, but this didnt work well...

var rTemperature;
var Reading = 0;

if (Reading < 20){
    Reading = Reading+1;
}
if  (Reading == 20){
    Reading = 0;
}

rTemperature = msg.payload.properties.timeseries[Reading].data.instant.details.air_temperature;

msg.payload = {
    "rTemperature": rTemperature};

return msg;

Or even worse, if I want data from line 20 to 60?

I will try to read more about this, but if you want to help i appreciate it :slight_smile:

You could replace the hard coded 0 and 20 with a msg properties and make the function dynamic.

Thank you @Steve-Mcl :slight_smile: But first i need the function to work. In this case the Reading is stuck at 0, and it wont run from 0 to 20 and put it all in the array.

That would be because of ...

TBH, I have zero idea what you are attempting to achieve.

If you can articulate that and provide example flow and example data I will show you how to get on.

You can populate an array in many ways, here is one such example...

var originalArray = msg.payload.properties.timeseries;
var newArray = originalArray.slice(0,20);//get items 0 ~ 20
var anotherArray = originalArray.slice(20,60);//get items 20 ~ 60

Just search google - "javascript copy part of an array"