Retrieve Dynamic value in object

Hi all,

I receive from the API "forecast.solar" (see also post Ideas about solar production forecasting) a message as shown in the picture below:

I would like to retrieve the date and time or even better to compare the date and time with the current date and time and in case they are equal retrieve the value.
I have been looking already to various JSONata expressions, but so far without any positive result.

Thanks for any hint in advance.

Hello @FireWizard52

Can you send as the msg.payload as code instead of a screenshot so it would be easier to create an example flow ? by the way .. that data is from July

Just to crarify .. you want the watts value that is nearest to the current time ?

This in a Change node using Jsonata and $moment should round down the current datetime and theoretically give you the matching watts.

image

here is an example of retriving the closest to current date time. msg.payload[0] will contain the closest

[{"id":"85120793.18262","type":"inject","z":"1fc07194.1c283e","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"2021-08-06 22:15:00\":10,\"2021-08-06 22:20:00\":20,\"2021-08-06 21:15:00\":30}","payloadType":"jsonata","x":454.33331298828125,"y":718.6666259765625,"wires":[["5e1ef649.b69d78"]]},{"id":"5e1ef649.b69d78","type":"change","z":"1fc07194.1c283e","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$each($$.payload, function($v,$k){\t    {\"time\":$k,\"value\":$v, \"dif\":\t    $abs($toMillis($join($split($k, \" \"),\"T\")) - $millis())}\t})^(dif)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":720,"wires":[["a2f86242.9c488"]]},{"id":"a2f86242.9c488","type":"debug","z":"1fc07194.1c283e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":910,"y":720,"wires":[]}]

[edit]
Or if you want the closest, but not in the future try

$each($$.payload, function($v,$k){
    ($diff := $toMillis($join($split($k, " "),"T")) - $millis();
    {"time":$k,"value":$v, "dif": $abs($round($diff/1000)), "pos": $diff > 0 ? 1 : 0})
})^(pos, dif)

you can mess with $diff > 0 making 0 positive or negative in milliseconds to bring dates that are with in the limit to the front of the array.

1 Like

very clever solution @E1cid :+1:
my approach was totaly wrong since i later noticed that not all datetimes were rounded to the hour

in moment there is a method diff for date subtractions that may make the jsonata a bit more readable without the split and joins

$each(
   $$.payload.result.watts,
   function($v,$k){
       {
           "time":$k,
           "value":$v,
           "dif":
    $abs(
               ($moment().diff($moment($k), 'minutes'))
           )
       }
}
)^(dif)

I thought of using moments, but it is not available in earlier node-red versions. The in built $millis() etc worked, so for backward compatibility i choice to keep it at $millis().

My edit allows you to get the future or past nearest to.

1 Like

Thank you @UnborN and @E1cid for your quick response.

To answer @UnborN questions first.

Please find below the code that generates an output as shown above.
It is a http request in order to get the solar forecast for a particular location.
It uses: https://forecast.solar/
Be aware that the "Public" API only uses estimate ( See: api:estimate [Forecast.Solar]) You can do 12 request/hour per IP Address (See: account_models [Forecast.Solar])

The lat/lon co-ordinates are the Central Railway Station in Amsterdam.
I do not live there :grinning:

[{"id":"f062ea34411c9575","type":"function","z":"b3872b85ab49c693","name":"Prepare Solar Forecast","func":"var url = \"https://api.forecast.solar/\";\nvar lat = 52.379189;\nvar lon = 4.899431;\nvar dec = 10;\nvar az = -14;\nvar kwp = 2.4;\nmsg.url = url + \"estimate/\" + lat + \"/\" + lon + \"/\" + dec + \"/\" + az + \"/\" + kwp;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":660,"wires":[["4b61faf70b1e3548"]]},{"id":"4b61faf70b1e3548","type":"http request","z":"b3872b85ab49c693","name":"Solar Forecast http request","method":"GET","ret":"obj","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"","x":940,"y":660,"wires":[["c3345b9b2799640e"]]},{"id":"c3345b9b2799640e","type":"debug","z":"b3872b85ab49c693","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1190,"y":660,"wires":[]},{"id":"a57e5a379ffc8781","type":"inject","z":"b3872b85ab49c693","name":"Inject timestamp","props":[{"p":"payload","v":"","vt":"date"},{"p":"topic","v":"","vt":"string"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":660,"wires":[["45c4b344b9bbe227"]]},{"id":"45c4b344b9bbe227","type":"time-switch","z":"b3872b85ab49c693","name":"Day Time switch","lat":"52.379189","lon":"4.899431","startTime":"sunrise","endTime":"sunset","startOffset":"-30","endOffset":"+30","x":400,"y":660,"wires":[["f062ea34411c9575"],[]]}]

I know that the picture indicated data from July. I actually used the screeenshot I made for the post, as indicated in the link above.

I tested the JSONata expression in the "Change" node. It gave an error. When I changed the time indication from HH:00:00 into hh: 00:00 it worked, but it gave me the rounded current time.

@E1cid flow worked , but not with the received flow from forecast.solar.
I have to look how to use it in the received flow.

To use moments is not an issue for me. I have used it before

Just change $$payload at beginning to the path to the object. as you did not supply a copyable example I made my own. I think it would be $$.payload.result.watts

What Unborn asked was for a copyable example, it's not his job to supply it. You can easily copy to clip board from the debug panel, just hover mouse over the copy value icon, it will appear to the right of the object name.

@E1cid

I think that did the trick. Thanks. I have to look into it.

I know that, but I thought that it was easier to have the flow, so far and that's why I supplied the complete flow, so he can test it, with his own values, etc.

People on this forum help without any cost. It would be helpful to them to supply all info and not make them go and get it, or load a flow that they may not have all the nodes installed. If I was asking for help I would not expect others to go out and find info that I have at hand. I hope in future when asking for help you would post the flow and any input that is not in the flow, or flow retrieves plus the expected output, in a copyable form.

Please do not take offence, I am just pointing out you could have made life easier on people helping

@E1cid,

I understand and I agree with it.
Sorry that I did not provide the necessary info this time, but will keep it in my mind that it is better to provide the copy-able values, instead of the flow.

Nevertheless I appreciate your support.
Thank you and have a nice weekend.

Regards

1 Like

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