Netatmo rain information from public stations: regex or JSONata?

I am able to read netatmo weather data collected by other netatmo stations in my region and also filter them, if they contain rain data. One of them in JSON format:

{"_id":"70:ee:50:28:00:00","place":{"location":[7.71234,48.51234],"timezone":"Europe/Paris","country":"FR","altitude":111,"city":"xxx","street":"Rue des xxxx"},"mark":12,"measures":{"02:00:00:28:ae:00":{"res":{"1598026423":[36.3,56]},"type":["temperature","humidity"]},"70:ee:50:28:a7:00":{"res":{"1598026467":[1017.3]},"type":["pressure"]},"05:00:00:04:9e:00":{"rain_60min":0,"rain_24h":0,"rain_live":0,"rain_timeutc":1598026455}},"modules":["05:00:00:04:9e:00","02:00:00:28:ae:00"],"module_types":{"05:00:00:04:9e:00":"NAModule3","02:00:00:28:ae:00":"NAModule1"}}

I just want to read the following data:

rain_60min
rain_24h
rain_live

but the measures "block" ist no array.

I have managed to use a function and generate the variable name as a string:

for(var i=0; i<msg.payload.modules.length; i++)
{
if (msg.payload.modules[i].substr(0,5) === "05:00" ) 
    {
      deb.payload = "msg.payload.measures."+msg.payload.modules[i]+".rain_60min"
    }
}

= "msg.payload.measures.05:00:00:04:9e:00.rain_60min"

but how do I use this string to read the variable? I thought of a regular expression, which changes the 50:00:xx:xx:xx into a 50, so that I can use always the same variable name

msg.payload.measures.50.rain_60min

But where could I use a regular expression in Node-RED?

I tried to use a JSON node, a change node, which searches for the string 05:00:??:??:??:?? and replaces it with rain, then another JSON node to get again Javascript objects.
But it replaces only the 05:00 part with rain.

Boy, I will HAVE to learn RegEx and/or JSONata.

Does this do it for you

for (const prop in msg.payload.measures) {
    if (msg.payload.measures.hasOwnProperty(prop)) {
        if (prop.substr(0,5) === "05:00") {
            msg.payload = msg.payload.measures[prop]
            break
        }
    }
}

That ends up with msg.payload containing the object { rain_60min: 0, rain_24h: 0, rain_live: 0, rain_timeutc: 1598026455 }

1 Like

Wow! I would never have found that solution!!

In the meantime I found the right RegEx for my string: 05:00:..:..:..:..
(trial and error with this online RegEx tester: https://regex101.com/)
But with your function code I can omit both of the JSON nodes and the change node with the RegEx.

Thanks!!

This can be done very easily with jsonata in a change node, for example I read all stations in my region and get the average rain_live like:

$average(**.rain_live)

This will only read them if they exist.

This solution is also awesome!
I added a $max JSONata expression, which works, too!!
In my case, I also would like to have the country+city, but ....

(place.country&'-'&place.city&': '&**.rain_live&' (@'&**.rain_timeutc&')')

= "DE-Berlin: 0 (@1598026552)"

Argh!! It took hours to get a similar result in my first post and finally gave up. :see_no_evil:

And instead of asking if there is a way to format the timeutc in a readable format just with JSONata, I used
https://try.jsonata.org/ and some google searches:

(place.country&'-'&place.city&': '&**.rain_live&' ('&$fromMillis(**.rain_timeutc*1000,'[D01].[M01]. [H01]:[m01]','+0200')&')')

= "DE-Berlin: 0 (21.08. 18:15)"

Thank you, both!!

1 Like

There is a netatmo node (get public data) that gives the option to get all stations within a square of a given location (see api documentation as well).

To format the time, jsonata (only within node-red) has the moment.js library built-in $moment(), you can easily format dates directly with that function.

From this netatmo node I got my data.

BTW: I just managed to calculate the distance in km from my home and the public netatmo stations.
Add a change node and set a new msg.distance variable (or whatever) to this JSONata code:

( $lat1 := payload.place.location[1];	  $lon1 := payload.place.location[0];		  $lonh := 9.12345; /* Home */	  $lath := 50.12345;		  $pi := 3.1415926535897932384626;	  $product := function($a, $b) { $a * $b };	  $factorial := function($n) { $n = 0 ? 1 : $reduce([1..$n], $product) };		  $sin := function($x){ $cos($x - $pi/2)};	  $cos := function($x){ $x > $pi ? $cos($x - 2 * $pi) : $x < -$pi ? $cos($x + 2 * $pi) :	      $sum([0..12].($power(-1, $) * $power($x, 2*$) / $factorial(2*$)))	  };		$round($sqrt((111.3 * $cos(($lat1 + $lath) / 2 * 0.01745) * $abs(($lon1 - $lonh))) * (111.3 * $cos(($lat1 + $lath) / 2 * 0.01745) * $abs(($lon1 - $lonh))) + (111.3 * $abs(($lat1 - $lath))) * (111.3 * $abs(($lat1 - $lath)))),1))	

Just change $lonh := 9.12345; $lath := 50.12345; with your home longitude and latitude data
and if you use the same netatmo data leave the variables for $lat and $lon1, otherwise put your data or variable instead of xx1 and xx2:

$lat1 := xx1; $lon1 := xx2;

Maybe the calculation does not work, if you have negative lat or lon values (?). I checked it with the public netatmo stations in my region and the distances seem to be valid.

If you set the lat_ne, lon_ne,lat_sw, lon_sw you already know the distance ?

With these values I set a rectangle, where these public stations are in. But I do not know, how far away every single station is, whose values are returned.

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