(Solved) Getting data from a large dynamic xml

I have used Node Red for some time now on my RPi and I am very happy with it!

Now I have given myself a new challenge: To grab some specific data from a xml-file in Node Red.

I have a very large xml-file (60K+ lines) containing UV-radiation data downloaded from a weather service (a small part of it is given below). The file contains radiation forecasts for many locations given as longitude and latitude in short notation. I tried to use the debug window to grab the path to the data of interest, but it seems that each time I download an updated version of the xml, the path has changed. So I get data from another location each time the xml is updated. Not very usefulā€¦

So now I believe I need to use some jsonata query to solve this. But I have very little experience with that. Played around with the try.josonata.org. This have me some new insight, but since the location elements are named latitude and longitude with a hyphen in front ('-latitude' and '-longitude') it is not that easy to work with.

If I remove the hyphens from the jsonata-file converted from xml, then this is a working query:
I have used Node Red for some time now on my RPi and I am very happy with it.

Now I have given myself a new challenge: To get xml-data to work inside Node Red.
I have a large xml-file (60K+ lines) containing UV-radiation data downloaded from a weather service. The file contains radiation forecasts for many locations given as longitude and latitude in short notation. I tried to use the debug window to grab the path to the data of interest, but it seems that each time I download an updated version of the xml, the path has changed. So I get data from another location each time the xml is updated. Not very usefulā€¦

So now I believe I need to use some jsonata query to solve this. But I have very little experience with that. Played around with my data at try.josonata.org. This have given me some new insight, but since the location elements are named latitude and longitude with a hyphen in front ('-latitude' and '-longitude') it is not that easy to work with, it seems.

If I remove the hyphens from the jsonata-file converted from xml, this is a working query:
weatherdata.product.time.location[longitude='11.00' and latitude='56.75'].iv.uvi_forecast
(this is not my actual location, so please do not fire a missileā€¦)

But since I have to deal with the hyphens, I also tried this:
weatherdata.product.time.location['longitude=11.00' and 'latitude=56.75'].iv.uvi_forecast
but that returns all uvi_forecast values in the dataset, not only for that given location.

In Node Red I use the http node to get an updated file and save that to disk (daily buffer). Then I use the xml node to convert that saved xml file to json format. This seems to work 100%.
The step I am struggling with is to grab the exact data from a specific location from that json so I can use it for mqtt, MySQL or whatever I find useful. But now I am stuck with the part getting the exact data from json ā€¦

Please help me solve this.
Thanks in advance.

Here is an example of the json data converted from xml:

{
  "weatherdata": {
    "-xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
    "product": {
      "-class": "uvforecast",
      "time": {
        "-to": "2019-07-09T12:00:00Z",
        "-from": "2019-07-09T12:00:00Z",
        "location": [
          {
            "-altitude": "0.00",
            "longitude": "11.00",
            "latitude": "56.75",
            "uv": {
              "uvi_clear": {
                "-value": "5.21",
                "-unit": "uv-index"
              },
              "uvi_partly_cloudy": {
                "-value": "4.43",
                "-unit": "uv-index"
              },
              "uvi_cloudy": {
                "-value": "1.35",
                "-unit": "uv-index"
              },
              "uvi_forecast": {
                "-value": "5.18",
                "-unit": "uv-index"
              },
              "ozon": {
                "-value": "7.755525e-03",
                "-unit": "kg/m^-2"
              },
              "snowcover": {
                "-value": "0.00",
                "-unit": "percentage"
              },
              "cloud_cover": {
                "-value": "1.00",
                "-unit": "parts of 8"
              },
              "albedo": {
                "-value": "0.05",
                "-unit": "percentage"
              },
              "solar_zenith": {
                "-value": "34.41",
                "-unit": "angle"
              }
            }
          },
          {
            "-altitude": "0.19",
            "longitude": "29.00",
            "latitude": "64.00",
            "uv": {
              "uvi_clear": {
                "-value": "4.51",
                "-unit": "uv-index"
              },
              "uvi_partly_cloudy": {
                "-value": "3.83",
                "-unit": "uv-index"
              },
              "uvi_cloudy": {
                "-value": "1.17",
                "-unit": "uv-index"
              },
              "uvi_forecast": {
                "-value": "1.17",
                "-unit": "uv-index"
              },
              "ozon": {
                "-value": "7.077940e-03",
                "-unit": "kg/m^-2"
              },
              "snowcover": {
                "-value": "0.00",
                "-unit": "percentage"
              },
              "cloud_cover": {
                "-value": "8.00",
                "-unit": "parts of 8"
              },
              "albedo": {
                "-value": "0.05",
                "-unit": "percentage"
              },
              "solar_zenith": {
                "-value": "41.66",
                "-unit": "angle"
              }
            }
          },
          {
            "-altitude": "0.32",
            "longitude": "22.25",
            "latitude": "67.75",
            "uv": {
              "uvi_clear": {
                "-value": "4.10",
                "-unit": "uv-index"
              },
              "uvi_partly_cloudy": {
                "-value": "3.49",
                "-unit": "uv-index"
              },
              "uvi_cloudy": {
                "-value": "1.07",
                "-unit": "uv-index"
              },
              "uvi_forecast": {
                "-value": "3.07",
                "-unit": "uv-index"
              },
              "ozon": {
                "-value": "6.717272e-03",
                "-unit": "kg/m^-2"
              },
              "snowcover": {
                "-value": "0.00",
                "-unit": "percentage"
              },
              "cloud_cover": {
                "-value": "5.00",
                "-unit": "parts of 8"
              },
              "albedo": {
                "-value": "0.05",
                "-unit": "percentage"
              },
              "solar_zenith": {
                "-value": "45.40",
                "-unit": "angle"
              }
            }
          }
        ]
      }
    }
  }
}

This returns 1 value for the given location:

**.location[longitude='11.00' and latitude='56.75'].**.uvi_forecast

{
    "-value": "5.18",
    "-unit": "uv-index"
}

note in your example: .iv.uvi_forecast should be .uv.uvi_forecast

Thanks Bakman2 for looking into this!

Now I see that I did at least two mistakes when publishing this topic:

  1. The one noted by Bakman2
  2. Published wrong example, the one where I had manually removed the hyphens.

So instead of editing the first post, I give here a correct sample of my data below.
How can I then modify Bakman2's query to get a single value?
(or suggest another solution. Maybe there is a node that can remove the hyphen?)

Query:
**.location[longitude='11.00' and latitude='56.75'].**.uvi_forecast

Data:

{
  "weatherdata": {
    "-xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
    "product": {
      "-class": "uvforecast",
      "time": {
        "-to": "2019-07-09T12:00:00Z",
        "-from": "2019-07-09T12:00:00Z",
        "location": [
          {
            "-altitude": "0.00",
            "-longitude": "11.00",
            "-latitude": "56.75",
            "uv": {
              "uvi_clear": {
                "-value": "5.21",
                "-unit": "uv-index"
              },
              "uvi_partly_cloudy": {
                "-value": "4.43",
                "-unit": "uv-index"
              },
              "uvi_cloudy": {
                "-value": "1.35",
                "-unit": "uv-index"
              },
              "uvi_forecast": {
                "-value": "5.18",
                "-unit": "uv-index"
              },
              "ozon": {
                "-value": "7.755525e-03",
                "-unit": "kg/m^-2"
              },
              "snowcover": {
                "-value": "0.00",
                "-unit": "percentage"
              },
              "cloud_cover": {
                "-value": "1.00",
                "-unit": "parts of 8"
              },
              "albedo": {
                "-value": "0.05",
                "-unit": "percentage"
              },
              "solar_zenith": {
                "-value": "34.41",
                "-unit": "angle"
              }
            }
          },
          {
            "-altitude": "0.19",
            "-longitude": "29.00",
            "-latitude": "64.00",
            "uv": {
              "uvi_clear": {
                "-value": "4.51",
                "-unit": "uv-index"
              },
              "uvi_partly_cloudy": {
                "-value": "3.83",
                "-unit": "uv-index"
              },
              "uvi_cloudy": {
                "-value": "1.17",
                "-unit": "uv-index"
              },
              "uvi_forecast": {
                "-value": "1.17",
                "-unit": "uv-index"
              },
              "ozon": {
                "-value": "7.077940e-03",
                "-unit": "kg/m^-2"
              },
              "snowcover": {
                "-value": "0.00",
                "-unit": "percentage"
              },
              "cloud_cover": {
                "-value": "8.00",
                "-unit": "parts of 8"
              },
              "albedo": {
                "-value": "0.05",
                "-unit": "percentage"
              },
              "solar_zenith": {
                "-value": "41.66",
                "-unit": "angle"
              }
            }
          },
          {
            "-altitude": "0.32",
            "-longitude": "22.25",
            "-latitude": "67.75",
            "uv": {
              "uvi_clear": {
                "-value": "4.10",
                "-unit": "uv-index"
              },
              "uvi_partly_cloudy": {
                "-value": "3.49",
                "-unit": "uv-index"
              },
              "uvi_cloudy": {
                "-value": "1.07",
                "-unit": "uv-index"
              },
              "uvi_forecast": {
                "-value": "3.07",
                "-unit": "uv-index"
              },
              "ozon": {
                "-value": "6.717272e-03",
                "-unit": "kg/m^-2"
              },
              "snowcover": {
                "-value": "0.00",
                "-unit": "percentage"
              },
              "cloud_cover": {
                "-value": "5.00",
                "-unit": "parts of 8"
              },
              "albedo": {
                "-value": "0.05",
                "-unit": "percentage"
              },
              "solar_zenith": {
                "-value": "45.40",
                "-unit": "angle"
              }
            }
          }
        ]
      }
    }
  }
}

Try it like this:

**.location[`-longitude`='11.00' and `-latitude`='56.75'].**.uvi_forecast
1 Like

Thank you!
That works great at try.jsonata.org.

Tried this in Node Red with a Change node using

set:
msg.filter

to:
payload.**.location[-longitude='11.00' and-latitude='56.75'].**.uvi_forecast

That returned forecast values for all locations, not only the one specified in the query.

I also tried the jsonata node using

**.location[-longitude='11.00' and-latitude='56.75'].**.uvi_forecast

as query, with the same result.

So hopefully I am (we are :grinning:) getting closer, but not quite there yet...

You forgot the backticks around the keys.

Example flow:

[{"id":"29831854.f21a78","type":"inject","z":"97f8fffc.342b1","name":"","topic":"","payload":"{   \"weatherdata\": {     \"-xmlns:xsi\": \"http://www.w3.org/2001/XMLSchema-instance\",     \"product\": {       \"-class\": \"uvforecast\",       \"time\": {         \"-to\": \"2019-07-09T12:00:00Z\",         \"-from\": \"2019-07-09T12:00:00Z\",         \"location\": [           {             \"-altitude\": \"0.00\",             \"-longitude\": \"11.00\",             \"-latitude\": \"56.75\",             \"uv\": {               \"uvi_clear\": {                 \"-value\": \"5.21\",                 \"-unit\": \"uv-index\"               },               \"uvi_partly_cloudy\": {                 \"-value\": \"4.43\",                 \"-unit\": \"uv-index\"               },               \"uvi_cloudy\": {                 \"-value\": \"1.35\",                 \"-unit\": \"uv-index\"               },               \"uvi_forecast\": {                 \"-value\": \"5.18\",                 \"-unit\": \"uv-index\"               },               \"ozon\": {                 \"-value\": \"7.755525e-03\",                 \"-unit\": \"kg/m^-2\"               },               \"snowcover\": {                 \"-value\": \"0.00\",                 \"-unit\": \"percentage\"               },               \"cloud_cover\": {                 \"-value\": \"1.00\",                 \"-unit\": \"parts of 8\"               },               \"albedo\": {                 \"-value\": \"0.05\",                 \"-unit\": \"percentage\"               },               \"solar_zenith\": {                 \"-value\": \"34.41\",                 \"-unit\": \"angle\"               }             }           },           {             \"-altitude\": \"0.19\",             \"-longitude\": \"29.00\",             \"-latitude\": \"64.00\",             \"uv\": {               \"uvi_clear\": {                 \"-value\": \"4.51\",                 \"-unit\": \"uv-index\"               },               \"uvi_partly_cloudy\": {                 \"-value\": \"3.83\",                 \"-unit\": \"uv-index\"               },               \"uvi_cloudy\": {                 \"-value\": \"1.17\",                 \"-unit\": \"uv-index\"               },               \"uvi_forecast\": {                 \"-value\": \"1.17\",                 \"-unit\": \"uv-index\"               },               \"ozon\": {                 \"-value\": \"7.077940e-03\",                 \"-unit\": \"kg/m^-2\"               },               \"snowcover\": {                 \"-value\": \"0.00\",                 \"-unit\": \"percentage\"               },               \"cloud_cover\": {                 \"-value\": \"8.00\",                 \"-unit\": \"parts of 8\"               },               \"albedo\": {                 \"-value\": \"0.05\",                 \"-unit\": \"percentage\"               },               \"solar_zenith\": {                 \"-value\": \"41.66\",                 \"-unit\": \"angle\"               }             }           },           {             \"-altitude\": \"0.32\",             \"-longitude\": \"22.25\",             \"-latitude\": \"67.75\",             \"uv\": {               \"uvi_clear\": {                 \"-value\": \"4.10\",                 \"-unit\": \"uv-index\"               },               \"uvi_partly_cloudy\": {                 \"-value\": \"3.49\",                 \"-unit\": \"uv-index\"               },               \"uvi_cloudy\": {                 \"-value\": \"1.07\",                 \"-unit\": \"uv-index\"               },               \"uvi_forecast\": {                 \"-value\": \"3.07\",                 \"-unit\": \"uv-index\"               },               \"ozon\": {                 \"-value\": \"6.717272e-03\",                 \"-unit\": \"kg/m^-2\"               },               \"snowcover\": {                 \"-value\": \"0.00\",                 \"-unit\": \"percentage\"               },               \"cloud_cover\": {                 \"-value\": \"5.00\",                 \"-unit\": \"parts of 8\"               },               \"albedo\": {                 \"-value\": \"0.05\",                 \"-unit\": \"percentage\"               },               \"solar_zenith\": {                 \"-value\": \"45.40\",                 \"-unit\": \"angle\"               }             }           }         ]       }     }   } }","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":315,"y":200,"wires":[["9d120015.e2b778"]]},{"id":"d1a1d270.68b8f","type":"debug","z":"97f8fffc.342b1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":670,"y":200,"wires":[]},{"id":"9d120015.e2b778","type":"change","z":"97f8fffc.342b1","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.**.location[`-longitude`='11.00' and `-latitude`='56.75'].**.uvi_forecast","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":200,"wires":[["d1a1d270.68b8f"]]}]

Thanks!
Now I know some more understanding of how to deal with non-standard characters in dataset/query. Nice!

But trying this query with the large data set fails for me. Maybe it is to big for Node Red to handle?

I have moved the project over to a more powerful platform for faster responses when experimenting with queries. And done a small adjustment to my flow so I got rid of the hyphen/dash. Here is my current flow. (Tried to attach the file, but the attachment button is not responding...)

[{"id":"4927d2bc.d2c2ec","type":"inject","z":"aeb8da2d.ad2ba8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":640,"wires":[["d3479451.ef7688"]]},{"id":"756bc4fe.9019ac","type":"debug","z":"aeb8da2d.ad2ba8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":730,"y":700,"wires":[]},{"id":"d80aa44d.784f98","type":"change","z":"aeb8da2d.ad2ba8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.**.location[longitude='11.00' and latitude='56.75'].**.uvi_forecast","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":540,"y":700,"wires":[["756bc4fe.9019ac"]]},{"id":"d3479451.ef7688","type":"file in","z":"aeb8da2d.ad2ba8","name":"read xml data from buffer file","filename":"\\\\192.168.0.101\\Temp\\uv1.xml","format":"utf8","chunk":false,"sendError":false,"encoding":"none","x":160,"y":700,"wires":[["da294546.e04a08"]]},{"id":"da294546.e04a08","type":"xml","z":"aeb8da2d.ad2ba8","name":"","property":"payload","attr":"","chr":"","x":370,"y":700,"wires":[["d80aa44d.784f98"]]}]

Since I don't have trouble with hyphen/dash anymore, I have therefore removed the backticks and using a more regular expression:

payload.**.location[longitude='11.00' and latitude='56.75'].**.uvi_forecast

This works for a small piece of the dataset, but using the full xml data (converted to json with xml node), I get an error in debug window saying

Invalid JSONata expression: Maximum call stack size exceeded

Have I reached some upper limit for data size...?

Here is my file in json-format.
uv1.json (2.3 MB)

And another version of my flow using attached json-file (xml to json already done before saving file):

[{"id":"7c7cba25.c144a4","type":"inject","z":"aeb8da2d.ad2ba8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":120,"y":580,"wires":[["c043808b.6ce67"]]},{"id":"44512c97.0713d4","type":"debug","z":"aeb8da2d.ad2ba8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":730,"y":620,"wires":[]},{"id":"b8ce93af.134b7","type":"change","z":"aeb8da2d.ad2ba8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.**.location[longitude='11.00' and latitude='56.75'].**.uvi_forecast","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":540,"y":620,"wires":[["44512c97.0713d4"]]},{"id":"c043808b.6ce67","type":"file in","z":"aeb8da2d.ad2ba8","name":"read xml data from buffer file","filename":"\\\\192.168.0.101\\Temp\\uv1.json","format":"utf8","chunk":false,"sendError":false,"encoding":"none","x":180,"y":620,"wires":[["b8ce93af.134b7"]]}]

I suspect there is too much recursion going on with jsonata. Try to reduce it by calling the property path directly, like
payload.weatherdata.product.time.location[....

Do you mean by specifying the index in array directly, like this:
payload.weatherdata.product.time.location[4352].uv.uvi_forecast

or removing the wildcards, like this:
payload.weatherdata.product.time.location[longitude='11.00' and latitude='56.75'].uv.uvi_forecast

or something else...?

I have tried both, and I don't get any closer.

Here is a flow getting data from a web page, converting it to json with the xml node, modified with the change node to select a location. Four debug nodes. Activate as necessary...

[{"id":"8a7851fe.4ed95","type":"tab","label":"uv_data from api.met.no","disabled":false,"info":""},{"id":"74a10f78.e4a94","type":"inject","z":"8a7851fe.4ed95","name":"get data without using a buffer file","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":120,"wires":[["4ed7fbda.c6f524"]]},{"id":"4ed7fbda.c6f524","type":"http request","z":"8a7851fe.4ed95","name":"Get data from met.no","method":"GET","ret":"txt","paytoqs":false,"url":"https://api.met.no/weatherapi/uvforecast/1.0/?time=2019-07-14T12:00:00Z&content_type=text/xml","tls":"","proxy":"","authType":"","x":140,"y":180,"wires":[["122bee70.24e212"]]},{"id":"414bf958.f439e8","type":"debug","z":"8a7851fe.4ed95","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":790,"y":140,"wires":[]},{"id":"9b4b1e84.a7f63","type":"comment","z":"8a7851fe.4ed95","name":"Test getting data directly without buffer file","info":"","x":200,"y":80,"wires":[]},{"id":"ede4264a.b076d8","type":"debug","z":"8a7851fe.4ed95","name":"complete msg","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":800,"y":180,"wires":[]},{"id":"122bee70.24e212","type":"xml","z":"8a7851fe.4ed95","name":"","property":"payload","attr":"","chr":"","x":330,"y":180,"wires":[["bf515407.cdcaa8","f59eeb5c.7c28a8","18419f2e.f07a41"]]},{"id":"bf515407.cdcaa8","type":"debug","z":"8a7851fe.4ed95","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":510,"y":80,"wires":[]},{"id":"f59eeb5c.7c28a8","type":"debug","z":"8a7851fe.4ed95","name":"complete msg","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":520,"y":120,"wires":[]},{"id":"18419f2e.f07a41","type":"change","z":"8a7851fe.4ed95","name":"select location data","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.weatherdata.product.time.location[longitude='11.00' and latitude='56.75'].uv.uvi_forecast","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":180,"wires":[["ede4264a.b076d8","414bf958.f439e8"]]}]

Does it work for you...?

The flow in my last post works if I use an index number in location:

weatherdata.product.time.location[3821].uv.uvi_forecast

or if I leave out the brackets:

weatherdata.product.time.location.uv.uvi_forecast

The first gives med an object with values corresponding to index 3821, the latter returns data for all locations. So I suspect i still need to focus on whats inside the brackets.

This variant:
weatherdata.product.time.location[longitude='11.00' and latitude='56.75'].uv.uvi_forecast

seems to destroy the payload, leaving only som header and topic in the msg.
So close, but not close enough...:sweat_smile:

The api file is too large for jsonata (not sure why their api does not support location in the request, but ok)

Using a function with a loop:

[{"id":"be829d3.1182ae","type":"inject","z":"d22d25d8.eedcf8","name":"get","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":125,"wires":[["541cabf8.503d04"]]},{"id":"541cabf8.503d04","type":"http request","z":"d22d25d8.eedcf8","name":"api.met.no","method":"GET","ret":"txt","paytoqs":false,"url":"https://api.met.no/weatherapi/uvforecast/1.0/?time=2019-07-14T12:00:00Z&content_type=text/xml","tls":"","proxy":"","authType":"","x":245,"y":125,"wires":[["b614a63f.7c0798"]]},{"id":"52d8184b.1f0e6","type":"debug","z":"d22d25d8.eedcf8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":670,"y":125,"wires":[]},{"id":"b614a63f.7c0798","type":"xml","z":"d22d25d8.eedcf8","name":"","property":"payload","attr":"","chr":"","x":400,"y":125,"wires":[["4f6df2f6.e0141c"]]},{"id":"4f6df2f6.e0141c","type":"function","z":"d22d25d8.eedcf8","name":"","func":"m = msg.payload.weatherdata.product[0].time[0].location\nt = msg.payload.weatherdata.product[0].time[0].$.from\n\nfor(x=0;x<m.length;x++){\n    \n    if(m[x].$.latitude == '56.75' && m[x].$.longitude == '11.00'){\n        \n        uvi_forecast = Number(m[x].uv[0].uvi_forecast[0].$.value)\n    \n        return {payload:{date_time:t, uvi_forecast:uvi_forecast}} \n    \n    }\n}\n","outputs":1,"noerr":0,"x":525,"y":125,"wires":[["52d8184b.1f0e6"]]}]
1 Like

Thanks again!
That works perfect for the purpose!
I have now added functionality for dynamic request url based on current date and routed the result to file for local buffering, so I don't have to ask the web server more than once a day.

I have also added mqtt client support and connection to MySQL for logging once a day.

Now I have to study your function node to understand an learn from it.
I have done some Python and C programming, so I recognize the structure, but Java has some differences. So if you know about some online resources, books etc. to recommend for learning scripting useful for Node Red, I appreciate that.

I agree that the API is not very user friendly. It should indeed be possible to select location directly. It was published back in 2008 as a free service "as is". I know they are doing some major changes in api on other services, and maybe this service will be modified too.

Thanks again for your patience! You are now my favorite Node Red forum member...

I am familiair with their API and used it a lot in the past, just not the UV part. It is the only API that is truly open.

I have done some Python and C programming, so I recognize the structure, but Java has some differences.

Java won't get you very far with node-red. Be sure to check for javascript :wink:

Yes, you are absolutely right...! :smile: