Solcast, tuning discontinued, using two sites with summed forecasts?

Hello,

I have never really done anything with Node Red, I only used used the great Solcast flow found here to get the forecast for one Solcast site and add the data to an InfluxDB: Power Forecasts and Data-Tuning for Solar Installations (Node-Red / solcast-API / InfluxDB / Grafana)

I just found out that tuning of Solcast sites will be discontinued. So as I have a solar setup with 15 kWp facing east and 11 kWp facing west, I will have to use two Solcast sites to get somewhat reliable data.

Has anyone rewritten the above flow to look at two Solcast sites and add the two forecasts together somehow? I might try to implement that myself, but if someone already did that, that would make it much easier :slight_smile:

...tuning feature has been discontinued quite some time ago. However, a already tuned site will stay tuned. If you were registered at that time, you were able to activate a second site for free.
Using two free accounts for the same split site would violate the terms&conditions, I believe.

The best you could do in that case is - as your site is oriented towards east and west, to configure the site towards south, ir with uneven capacity installed, more towards the orientation with larger capacity.

....that said, even with several accounts, each single site should be captured individually...hence, simply duplicate the flows and set influx topics accordingly.
This will enable your installations to be more flexible (I'd use one flow per inverter, so if one goes down, the remaining data will still be processed). Then add values of sites by queries frim the influxDB.

Thanks, I will duplicate the flow. I guess I then have to tell Grafana to add both forecast values when displaying the graph.

Unfortunately, my system was just installed (or rather I had a much bigger system installed), and I therefore haven't tuned the system.

...using grafana will only collect and calculate values for displaying.
You could as well create a small, extra fluw where you can feed the output of each site flow via a join-nide (make it wait for 2 messages) then combine/sum-up these two into a third data stream and store this in influx as well.
This way you have the individual sites and the sum stored.

Yea, that would be great, but I'm too much of a Node-RED noob to make that happen at the moment :slight_smile:

I was able to duplicate the flow and I now have both sites storing the forecasts in InfluxDB. I am able to somewhat add the two values in Grafana as well (using a Transformation), but it's tricky as somehow my other graphs in that panel then only displays dots for each value and doesn't connect those anymore. Not sure, why.

Ok, nevermind, I had to migrate from Grafanas old graph type to the new one, now it seems to be working:

Ok, now that you have this working, you could experiment with a third flow, to create sum-values.

I am without access to my NR, as I am vacation atm so cannot help much.

There a link-in and link-out nodes, that would allow you to link between flows.
You can easily link the messages that are going to the influxdb node to the third flow, too.
There you can experiment with the values.
As said, use a join-node to join every two messages (coming from flow 1 and flow 2 of your sites) and start learning.

You can then export the flow here and ask for detailed help...maybe someone else will chime in.

1 Like

Hi again,

I didn't work on this thing for a while now, but would like to start again, somehow joining the messages for my east and my west Solcast forecasts. Somehow I still haven't been able to get used to Node-RED, might need some practice...

I did set up a third flow to start, and I also added "link out" and "link in" nodes to the two Solcast flows and my new "solcast join" flow. But I'm stuck then.

This is what my join flow looks like right now. But then I don't know if that's even the correct node to use, and also what to do with it and how to configure it.

Any help would be greatly appreciated. :slight_smile:

Edit:

Here a screenshot how one of the other flows looks like, only the part where the message gets sent to the database.

I think I might be able to somehow sometime get there myself. I now got the join node to combine the two arrays into one payload. Now I'm in the process of building a Function node that will add the two values for east/west and put that into a new array, which then will be put as the payload for the message that will then go to InfluxDB. Of course I am completely new to NodeRED and there might be an easier way, but it's good to learn this way, I guess :slight_smile:

Edit: Ok, might not be that "easy" after all. I do get combined messages that contain arrays with Solcast values for both sides, but they don't necessarily have the same timestamp... which sucks.

Basically that is the way to go and you are on the right track.

Solcast will provide forecasts with time-slots on PTS30mins intervals.
If the location for east/west site is the same, the timestamps should be the same.
Check each array before the join....even check the array that is the output of each API call.

As a side note, you should use the same, single trigger event to trigger the flows that fetch the results for each site, in order to have the values for each PTS30min element "aligned".

If the timeslots do differ, your function node that does the math is maybe not working correctly.
Maybe you are allocating the content of "now" when performaing that action but you should use the time-slot given in each array element.

Second side note: you can do the math/combination even before the sub-flow that produces the influx output...use the output of each API call and join these, then do the math.

1 Like

Thank you for your help!

I'm still struggling. I did put everything in one Flow (which looks like a mess now). I basically copied all of the nodes from the API call onwards (there is probably a way to not have every node twice, but I was just trying to test it out). I do use a single inject node to trigger the flow. This is what the API call and joining of the messages looks like right now:

Unfortunately, it looks like timestamps are not the same. Do you have a tip for me on how to get that sorted?

Here you can see that the timestamps are, at least in those cases, half an hour apart.

Sometimes they are identical though:

image

Edit: I'm not even sure if the joined messages even always contain both east and west, or if there are some combined arrays where both first and second forecast are for either east or west. At least the watt data somewhat looks like that.

This is how the join node is configured:

image

Could that join node trigger by for example two messages from east or two messages from west?

as a side-note, using screenshots to show your flow is not optimal. You can use the export feature in NR, copy/export the flow to clipboard and then paste it here between "formatted text" block (the </> item in the editor :wink: )
Edit: but be aware that in this case your solcast credentials (rooftop-ID and API-Token) will be presented to the world...remove this part of the config before exporting the flow!!

Seeing your picture of the flow, I'd suggest to place the join right after "switch" node, where the original messages from the API calls arrive. Where it is now, each stream is split and is fed individual timestamps/values originated to influx.

....and, yes, because of where you placed the join node, the two streams could mix differently - depending on performance of your platform.

Right after the switch there is still one message for each API call. So setting the join node to wait for two messages in a row will join one from east and one from west (as long as the API calls are triggered simultaneously there is a low risk that - i.e. when one API call, like one for east, would fail and the other would not - two from east or west will not be joined fine).

Here is another tip: As you might already being limited by the number of solcast API calls allowed per day, you should maybe introduce a way to store the last result and make it able to being sent/forwarded again.
There is a NR library called "node-red-contrib-mock" for this.
image

[{"id":"31996918.cd7766","type":"tab","label":"mock store","disabled":false,"info":""},{"id":"6585c767.83a528","type":"mock","z":"31996918.cd7766","name":"mockstore","x":380,"y":240,"wires":[["37f14a35.4054b6","a63e69af.f5b238"]]},{"id":"e7a04f34.9c0c2","type":"link in","z":"31996918.cd7766","name":"to mock-store","links":["cee31b2e.18f158","337db7b6.382498"],"x":160,"y":180,"wires":[["6585c767.83a528"]]},{"id":"37f14a35.4054b6","type":"link out","z":"31996918.cd7766","name":"from mock-store","links":["7a18231.adc1cdc","8d5624e1.507db8","bdbf41b.bd0dbc"],"x":580,"y":180,"wires":[]},{"id":"a63e69af.f5b238","type":"debug","z":"31996918.cd7766","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":580,"y":300,"wires":[]}]

...add that mock node to your flow, i.e. after the API response/the switch and you will be able to forward the last object stored as often as you wish, for testing. I am using it in an extras flow, linking the input to the API result messages and the output to test-flows as need be.

1 Like

Awesome, thank you. That mock node is just what I needed, I was running out of API calls for today. :slight_smile:

I also added the join node just after the switch node and I am now getting one message with two forecast arrays. I guess I can then use a Function node or something to actually add the values together. Might have to check each time if the timestamp is the same and if not just ignore it or something.

image

...yes, you can.
Before the join node, i'd rather change the name/move the object "forecasts" into a destinct name, like "east" & "west". Then after the join, maybe copy the first one into a third, with name like "sum".
Payload is then made an array of three objects (east, west, sum).
Then you can iterate over the first inner array of 336 elements (i.e. "east"), fetch the value from "east[i] & west[i], calc the sum of these two and store it in the same index in array "sum[i]".

Actually, not as each array of 336 objects should carry the same timestamps in the same order (if the API calls have been triggered simultaneously and the call did not fail).

Sounds like a plan.

I wonder what would happen if, for example, one of the two API calls fails. Then only one message reaches the join node. When then the flow gets triggered, either east or west data might get to the join node first, which then gets triggered by that new message and the old message that was already waiting there?

Yes, basically you are right. But this is a Risk based assessment.
Remember that my flows did cater for a retry of API calls.
As long as a subsequent call/retry finishes in time before the next scheduled event, you should be fine as long as the number of allowed calls is not exceeded (I noticed, that even a failed call counted against the allowance, but I did not have a failed call the last 18 months).

You could also introduce a countermeasure by using a DSM node, as an example. You could configure it (its rules), to only forward both messages when they are a "matched tuple" of east & west from the same trigger event (triggered time) and discard an unmatched pair otherwise.

BTW. here is another little flow, I did help with for another User, who actually had an island PV/battery system and needed the forecasts for a week in display. You'll also need the UI dashboard library for this...might give you some more info/ideas on how to play with the data arrays:

[{"id":"57a878b4.0b4b98","type":"tab","label":"PV Forcasts","disabled":false,"info":"Display PC Forcasts in a UI table\n\nThe UI gets updated with each solcast API call, that needs to be fed into this flow.\n\nThe Forcasts spread excatly, as per solcast specs, 7 days.\nHence the forcasts of \"today\" is the PV Energy for the remaining rest of day, after when the APi has been called.\nThe same holds true for the last of the seven days, counting only the PV energy up to the time of todays clock/api call."},{"id":"8d5624e1.507db8","type":"link in","z":"57a878b4.0b4b98","name":"","links":["37f14a35.4054b6"],"x":75,"y":40,"wires":[["9ebcdc17.57104"]]},{"id":"cf308c55.df1c6","type":"debug","z":"57a878b4.0b4b98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":690,"y":160,"wires":[]},{"id":"4d910fe4.9c659","type":"split","z":"57a878b4.0b4b98","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":520,"y":40,"wires":[["77e32bb1.366dc4"]]},{"id":"e2255bce.5a71a8","type":"join","z":"57a878b4.0b4b98","name":"","mode":"auto","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":930,"y":40,"wires":[["8f55025b.6ab52"]]},{"id":"77e32bb1.366dc4","type":"change","z":"57a878b4.0b4b98","name":"values PTS30min and day","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t\"value\": $.payload.pv_estimate,\t\"day\": $moment($toMillis($.payload.period_end) - 1800000).locale('Sv_se').format(\"YYYY-MM-DD\")\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":730,"y":40,"wires":[["e2255bce.5a71a8"]]},{"id":"9ebcdc17.57104","type":"change","z":"57a878b4.0b4b98","name":"","rules":[{"t":"move","p":"payload.forecasts","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":290,"y":40,"wires":[["4d910fe4.9c659","e7a3af3a.4a2e2"]]},{"id":"8f55025b.6ab52","type":"change","z":"57a878b4.0b4b98","name":"sum per day","rules":[{"t":"set","p":"payload","pt":"msg","to":"$spread($.payload{day: $formatNumber($sum(value)/2, '#0.0')})","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":250,"y":140,"wires":[["40071d1c.445e74"]]},{"id":"40071d1c.445e74","type":"function","z":"57a878b4.0b4b98","name":"split array of objects","func":"for (let i = 0; i < msg.payload.length; i++) {\n    const el = msg.payload[i];\n    const entries = Object.entries(el).map(([topic, payload]) => ({ topic, payload, row: (i+1) }));\n    node.send([entries]);\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","x":220,"y":281,"wires":[["1fc0bc30.248144"]]},{"id":"f3445bea.b68348","type":"switch","z":"57a878b4.0b4b98","name":"split into day #1 to day #8","property":"row","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"num"},{"t":"eq","v":"2","vt":"num"},{"t":"eq","v":"3","vt":"num"},{"t":"eq","v":"4","vt":"num"},{"t":"eq","v":"5","vt":"num"},{"t":"eq","v":"6","vt":"num"},{"t":"eq","v":"7","vt":"num"},{"t":"eq","v":"8","vt":"num"}],"checkall":"false","repair":false,"outputs":8,"x":730,"y":280,"wires":[["5b8ab87b.1304a8"],["bc14d4b3.0ec688"],["9bc31eef.91302"],["f1f97c78.34e09"],["303e24fe.bc753c"],["332cbe48.948842"],["16ff402c.c4b6e"],["a4c16502.805198"]]},{"id":"5b8ab87b.1304a8","type":"ui_text","z":"57a878b4.0b4b98","group":"2ae5a11e.8cceae","order":2,"width":"0","height":"0","name":"today","label":"{{msg.topic}}","format":"{{msg.payload}} kWh","layout":"row-spread","x":1010,"y":160,"wires":[]},{"id":"bc14d4b3.0ec688","type":"ui_text","z":"57a878b4.0b4b98","group":"2ae5a11e.8cceae","order":3,"width":"0","height":"0","name":"tomorrow","label":"{{msg.topic}}","format":"{{msg.payload}} kWh","layout":"row-spread","x":1020,"y":200,"wires":[]},{"id":"9bc31eef.91302","type":"ui_text","z":"57a878b4.0b4b98","group":"2ae5a11e.8cceae","order":4,"width":"0","height":"0","name":"day after tomorrow","label":"{{msg.topic}}","format":"{{msg.payload}} kWh","layout":"row-spread","x":1050,"y":240,"wires":[]},{"id":"f1f97c78.34e09","type":"ui_text","z":"57a878b4.0b4b98","group":"2ae5a11e.8cceae","order":5,"width":"0","height":"0","name":"day #4","label":"{{msg.topic}}","format":"{{msg.payload}} kWh","layout":"row-spread","x":1010,"y":280,"wires":[]},{"id":"303e24fe.bc753c","type":"ui_text","z":"57a878b4.0b4b98","group":"2ae5a11e.8cceae","order":6,"width":"0","height":"0","name":"day #5","label":"{{msg.topic}}","format":"{{msg.payload}} kWh","layout":"row-spread","x":1010,"y":320,"wires":[]},{"id":"332cbe48.948842","type":"ui_text","z":"57a878b4.0b4b98","group":"2ae5a11e.8cceae","order":7,"width":"0","height":"0","name":"day #6","label":"{{msg.topic}}","format":"{{msg.payload}} kWh","layout":"row-spread","x":1010,"y":360,"wires":[]},{"id":"16ff402c.c4b6e","type":"ui_text","z":"57a878b4.0b4b98","group":"2ae5a11e.8cceae","order":8,"width":"0","height":"0","name":"day #7","label":"{{msg.topic}}","format":"{{msg.payload}} kWh","layout":"row-spread","x":1010,"y":400,"wires":[]},{"id":"a4c16502.805198","type":"ui_text","z":"57a878b4.0b4b98","group":"2ae5a11e.8cceae","order":9,"width":"0","height":"0","name":"day #8","label":"{{msg.topic}}","format":"{{msg.payload}} kWh","layout":"row-spread","x":1010,"y":440,"wires":[]},{"id":"1fc0bc30.248144","type":"change","z":"57a878b4.0b4b98","name":"set topic to name (day)","rules":[{"t":"set","p":"topic","pt":"msg","to":"$moment($.topic).locale('de_de').format(\"DD.MM - dddd\")","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":281,"wires":[["cf308c55.df1c6","f3445bea.b68348"]]},{"id":"e7a3af3a.4a2e2","type":"change","z":"57a878b4.0b4b98","name":"NOW","rules":[{"t":"set","p":"ts","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":120,"wires":[["4bec1643.c947a8"]]},{"id":"4bec1643.c947a8","type":"change","z":"57a878b4.0b4b98","name":"moment(now)","rules":[{"t":"set","p":"payload","pt":"msg","to":"$moment($.ts).locale('de_de').format(\"DD.MMMM - HH:mm\")","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":120,"wires":[["39e79959.f4ced6"]]},{"id":"39e79959.f4ced6","type":"ui_text","z":"57a878b4.0b4b98","group":"2ae5a11e.8cceae","order":1,"width":"0","height":"0","name":"NOW","label":"Vorschau vom: ","format":"{{msg.payload}}","layout":"row-center","x":1010,"y":120,"wires":[]},{"id":"2ae5a11e.8cceae","type":"ui_group","name":"PV Forecasts","tab":"322ae12.c23f41e","order":2,"disp":true,"width":"6","collapse":false},{"id":"322ae12.c23f41e","type":"ui_tab","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]

...looks like this:

That's cool. I am mostly using Grafana for visualisation, but good to know that NR can do stuff like that as well.

I am still struggling. :smiley: I did set up those mock nodes and they do seem to work, but not sure what I did but now when I actually do the API call I do get two arrays that were actually renamed to forecasts_east and _west, but whenever I then use the mock nodes to send the same messages again, all I get is two empty arrays? So it's working when not using the mock nodes. Unfortunately, I only have two API calls left :wink:

Here is my current flow, still a long long way to go. Not sure if that's the correct way to rename the arrays. I also wasn't able to actually copy one of the arrays to a new third array, but I guess I will manage to get that to work once I am able to reliably resend messages with the mock nodes. Do you know what I could be doing wrong here?

[
    {
        "id": "a5cb0f26a080725b",
        "type": "http request",
        "z": "457f9988695be7c4",
        "name": "Solcast API - get Live+Forecast JSON EAST",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "https://api.solcast.com.au/rooftop_sites/XXXXXXXXXXXX",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "basic",
        "senderr": false,
        "x": 630,
        "y": 460,
        "wires": [
            [
                "786e5f423ffa7593"
            ]
        ]
    },
    {
        "id": "c0e0319e8b59c5ca",
        "type": "debug",
        "z": "457f9988695be7c4",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1210,
        "y": 740,
        "wires": []
    },
    {
        "id": "5cc54dd022077d84",
        "type": "http request",
        "z": "457f9988695be7c4",
        "name": "Solcast API - get Past + Estimated Actuals EAST",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "https://api.solcast.com.au/rooftop_sites/XXXXXXXXXXXXXX",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "basic",
        "senderr": false,
        "x": 640,
        "y": 420,
        "wires": [
            [
                "786e5f423ffa7593"
            ]
        ]
    },
    {
        "id": "786e5f423ffa7593",
        "type": "switch",
        "z": "457f9988695be7c4",
        "name": "StatusCode",
        "property": "statusCode",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "200",
                "vt": "num"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 950,
        "y": 380,
        "wires": [
            [
                "78d8d2fbb49c79ab"
            ],
            [
                "c0e0319e8b59c5ca",
                "43c89b64564876f0"
            ]
        ]
    },
    {
        "id": "43c89b64564876f0",
        "type": "change",
        "z": "457f9988695be7c4",
        "name": "timestamp",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "",
                "tot": "date"
            },
            {
                "t": "delete",
                "p": "statusCode",
                "pt": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1170,
        "y": 380,
        "wires": [
            [
                "e132cc1dd6f953de"
            ]
        ]
    },
    {
        "id": "e132cc1dd6f953de",
        "type": "delay",
        "z": "457f9988695be7c4",
        "name": "",
        "pauseType": "delay",
        "timeout": "3",
        "timeoutUnits": "minutes",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "outputs": 1,
        "x": 1380,
        "y": 380,
        "wires": [
            []
        ]
    },
    {
        "id": "5783efa521601e69",
        "type": "inject",
        "z": "457f9988695be7c4",
        "name": "forecasts",
        "props": [
            {
                "p": "payload",
                "v": "",
                "vt": "date"
            },
            {
                "p": "topic",
                "v": "forecasts",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "forecasts",
        "payload": "",
        "payloadType": "date",
        "x": 106,
        "y": 1015,
        "wires": [
            [
                "cbda7ba3f1b5dd8c"
            ]
        ]
    },
    {
        "id": "6fba0be572ad1fcc",
        "type": "change",
        "z": "457f9988695be7c4",
        "name": "reset counter",
        "rules": [
            {
                "t": "set",
                "p": "reset",
                "pt": "msg",
                "to": "true",
                "tot": "bool"
            },
            {
                "t": "set",
                "p": "topic.reset",
                "pt": "msg",
                "to": "reset",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 450,
        "y": 899,
        "wires": [
            [
                "cbda7ba3f1b5dd8c"
            ]
        ]
    },
    {
        "id": "647d5a3b47463e70",
        "type": "switch",
        "z": "457f9988695be7c4",
        "name": "counter",
        "property": "count",
        "propertyType": "msg",
        "rules": [
            {
                "t": "btwn",
                "v": "1",
                "vt": "num",
                "v2": "50",
                "v2t": "num"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 969,
        "y": 739,
        "wires": [
            [
                "2dc5dceec8bc5fe5"
            ],
            [
                "c0e0319e8b59c5ca"
            ]
        ]
    },
    {
        "id": "c8a0bcb16c3e26a7",
        "type": "change",
        "z": "457f9988695be7c4",
        "name": "",
        "rules": [
            {
                "t": "delete",
                "p": "reset",
                "pt": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 907,
        "y": 899,
        "wires": [
            [
                "647d5a3b47463e70"
            ]
        ]
    },
    {
        "id": "78d8d2fbb49c79ab",
        "type": "switch",
        "z": "457f9988695be7c4",
        "name": "",
        "property": "topic",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "estimated_actuals",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "forecasts",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 1150,
        "y": 200,
        "wires": [
            [],
            [
                "5b41b7be8a1ce405"
            ]
        ]
    },
    {
        "id": "6c397fa8917f9a86",
        "type": "inject",
        "z": "457f9988695be7c4",
        "name": "tägl. 02:00Uhr",
        "props": [
            {
                "p": "payload",
                "v": "",
                "vt": "date"
            },
            {
                "p": "topic",
                "v": "Counter_Reset",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "00 02 * * *",
        "once": false,
        "onceDelay": 0.1,
        "topic": "Counter_Reset",
        "payload": "",
        "payloadType": "date",
        "x": 127,
        "y": 861,
        "wires": [
            [
                "ec6877f94fdbf330"
            ]
        ]
    },
    {
        "id": "2dc5dceec8bc5fe5",
        "type": "switch",
        "z": "457f9988695be7c4",
        "name": "topic",
        "property": "topic",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "estimated_actuals",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "forecasts",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 350,
        "y": 480,
        "wires": [
            [
                "5cc54dd022077d84",
                "23605978e56b965d"
            ],
            [
                "a5cb0f26a080725b",
                "62e234f625a2a02a"
            ]
        ]
    },
    {
        "id": "b1f52ecbb1c743c5",
        "type": "inject",
        "z": "457f9988695be7c4",
        "name": "estimated_actuals",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "estimated_actuals",
        "payload": "",
        "payloadType": "date",
        "x": 135,
        "y": 1073,
        "wires": [
            []
        ]
    },
    {
        "id": "39febf8dd840c45e",
        "type": "comment",
        "z": "457f9988695be7c4",
        "name": "Manuelle Abfragen",
        "info": "",
        "x": 126,
        "y": 975,
        "wires": []
    },
    {
        "id": "58231316133afbbb",
        "type": "comment",
        "z": "457f9988695be7c4",
        "name": "Zeitgesteuerte Abfragen",
        "info": "",
        "x": 120,
        "y": 300,
        "wires": []
    },
    {
        "id": "3e4d03c3c94e9d0d",
        "type": "comment",
        "z": "457f9988695be7c4",
        "name": "API abfragen",
        "info": "",
        "x": 590,
        "y": 380,
        "wires": []
    },
    {
        "id": "b1a608779bbca9bf",
        "type": "comment",
        "z": "457f9988695be7c4",
        "name": "50 API-Calls pro Tag möglich",
        "info": "",
        "x": 865,
        "y": 860,
        "wires": []
    },
    {
        "id": "2e79f304435b99b2",
        "type": "comment",
        "z": "457f9988695be7c4",
        "name": "Reset counter",
        "info": "",
        "x": 110,
        "y": 820,
        "wires": []
    },
    {
        "id": "817124037088499e",
        "type": "inject",
        "z": "457f9988695be7c4",
        "name": "Counter_Reset",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "Counter_Reset",
        "payload": "",
        "payloadType": "date",
        "x": 126,
        "y": 898,
        "wires": [
            [
                "6fba0be572ad1fcc"
            ]
        ]
    },
    {
        "id": "4feaa555ebe704cb",
        "type": "debug",
        "z": "457f9988695be7c4",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": true,
        "complete": "count",
        "targetType": "msg",
        "statusVal": "count",
        "statusType": "auto",
        "x": 880,
        "y": 960,
        "wires": []
    },
    {
        "id": "cbda7ba3f1b5dd8c",
        "type": "counter",
        "z": "457f9988695be7c4",
        "name": "Counter",
        "init": "0",
        "step": "1",
        "lower": null,
        "upper": null,
        "mode": "increment",
        "outputs": "1",
        "x": 719,
        "y": 899,
        "wires": [
            [
                "c8a0bcb16c3e26a7",
                "4feaa555ebe704cb"
            ]
        ]
    },
    {
        "id": "69982da8785adefe",
        "type": "time-inject",
        "z": "457f9988695be7c4",
        "name": "forecasts",
        "nameInt": "Sonnenaufgang Beginn↶ - Sonnenuntergang Ende↷ =... ↻150min",
        "positionConfig": "8c7609ce.dd5798",
        "props": [
            {
                "p": "",
                "pt": "msgPayload",
                "v": "",
                "vt": "date",
                "o": "1",
                "oT": "none",
                "oM": "60000",
                "f": 0,
                "fS": 0,
                "fT": "Millisekunden UNIX-Zeit",
                "fI": "0",
                "next": true,
                "days": "*",
                "months": "*",
                "onlyOddDays": false,
                "onlyEvenDays": false,
                "onlyOddWeeks": false,
                "onlyEvenWeeks": false
            },
            {
                "p": "",
                "pt": "msgTopic",
                "v": "forecasts",
                "vt": "str",
                "o": "1",
                "oT": "none",
                "oM": "60000",
                "f": 0,
                "fS": 0,
                "fT": "Millisekunden UNIX-Zeit",
                "fI": "0",
                "next": false,
                "days": "*",
                "months": "*",
                "onlyOddDays": false,
                "onlyEvenDays": false,
                "onlyOddWeeks": false,
                "onlyEvenWeeks": false
            }
        ],
        "injectTypeSelect": "interval-time",
        "intervalCount": "150",
        "intervalCountType": "num",
        "intervalCountMultiplier": 60000,
        "time": "sunriseStart",
        "timeType": "pdsTime",
        "offset": "-15",
        "offsetType": "num",
        "offsetMultiplier": 60000,
        "timeEnd": "sunsetEnd",
        "timeEndType": "pdsTime",
        "timeEndOffset": "15",
        "timeEndOffsetType": "num",
        "timeEndOffsetMultiplier": 60000,
        "timeDays": "*",
        "timeOnlyOddDays": false,
        "timeOnlyEvenDays": false,
        "timeOnlyOddWeeks": false,
        "timeOnlyEvenWeeks": false,
        "timeMonths": "*",
        "timedatestart": "",
        "timedateend": "",
        "property": "",
        "propertyType": "none",
        "propertyCompare": "true",
        "propertyThreshold": "",
        "propertyThresholdType": "num",
        "timeAlt": "",
        "timeAltType": "entered",
        "timeAltDays": "*",
        "timeAltOnlyOddDays": false,
        "timeAltOnlyEvenDays": false,
        "timeAltOnlyOddWeeks": false,
        "timeAltOnlyEvenWeeks": false,
        "timeAltMonths": "*",
        "timeAltOffset": 0,
        "timeAltOffsetType": "none",
        "timeAltOffsetMultiplier": 60000,
        "once": false,
        "onceDelay": 0.1,
        "recalcTime": 2,
        "x": 100,
        "y": 380,
        "wires": [
            []
        ]
    },
    {
        "id": "a6859388b3b826d8",
        "type": "time-inject",
        "z": "457f9988695be7c4",
        "name": "estimated_actuals",
        "nameInt": "Sonnenaufgang Beginn↷ - Sonnenuntergang Ende↷ =... ↻4h",
        "positionConfig": "8c7609ce.dd5798",
        "props": [
            {
                "p": "",
                "pt": "msgPayload",
                "v": "",
                "vt": "date",
                "o": "1",
                "oT": "none",
                "oM": "60000",
                "f": 0,
                "fS": 0,
                "fT": "Millisekunden UNIX-Zeit",
                "fI": "0",
                "next": true,
                "days": "*",
                "months": "*",
                "onlyOddDays": false,
                "onlyEvenDays": false,
                "onlyOddWeeks": false,
                "onlyEvenWeeks": false
            },
            {
                "p": "",
                "pt": "msgTopic",
                "v": "estimated_actuals",
                "vt": "str",
                "o": "1",
                "oT": "none",
                "oM": "60000",
                "f": 0,
                "fS": 0,
                "fT": "Millisekunden UNIX-Zeit",
                "fI": "0",
                "next": false,
                "days": "*",
                "months": "*",
                "onlyOddDays": false,
                "onlyEvenDays": false,
                "onlyOddWeeks": false,
                "onlyEvenWeeks": false
            }
        ],
        "injectTypeSelect": "interval-time",
        "intervalCount": "4",
        "intervalCountType": "num",
        "intervalCountMultiplier": 3600000,
        "time": "sunriseStart",
        "timeType": "pdsTime",
        "offset": "90",
        "offsetType": "num",
        "offsetMultiplier": 60000,
        "timeEnd": "sunsetEnd",
        "timeEndType": "pdsTime",
        "timeEndOffset": "60",
        "timeEndOffsetType": "num",
        "timeEndOffsetMultiplier": 60000,
        "timeDays": "*",
        "timeOnlyOddDays": false,
        "timeOnlyEvenDays": false,
        "timeOnlyOddWeeks": false,
        "timeOnlyEvenWeeks": false,
        "timeMonths": "*",
        "timedatestart": "",
        "timedateend": "",
        "property": "",
        "propertyType": "none",
        "propertyCompare": "true",
        "propertyThreshold": "",
        "propertyThresholdType": "num",
        "timeAlt": "",
        "timeAltType": "entered",
        "timeAltDays": "*",
        "timeAltOnlyOddDays": false,
        "timeAltOnlyEvenDays": false,
        "timeAltOnlyOddWeeks": false,
        "timeAltOnlyEvenWeeks": false,
        "timeAltMonths": "*",
        "timeAltOffset": 0,
        "timeAltOffsetType": "none",
        "timeAltOffsetMultiplier": 60000,
        "once": false,
        "onceDelay": 0.1,
        "recalcTime": 2,
        "x": 130,
        "y": 344,
        "wires": [
            []
        ]
    },
    {
        "id": "ec6877f94fdbf330",
        "type": "within-time-switch",
        "z": "457f9988695be7c4",
        "name": "neuer Tag?",
        "nameInt": "",
        "positionConfig": "8c7609ce.dd5798",
        "startTime": "sunriseStart",
        "startTimeType": "pdsTime",
        "startOffset": "-15",
        "startOffsetType": "num",
        "startOffsetMultiplier": 60000,
        "endTime": "sunsetEnd",
        "endTimeType": "pdsTime",
        "endOffset": "60",
        "endOffsetType": "num",
        "endOffsetMultiplier": 60000,
        "timeRestrictions": "",
        "timeRestrictionsType": "none",
        "timeDays": "*",
        "timeOnlyOddDays": false,
        "timeOnlyEvenDays": false,
        "timeOnlyOddWeeks": false,
        "timeOnlyEvenWeeks": false,
        "timeMonths": "*",
        "timedatestart": "",
        "timedateend": "",
        "propertyStart": "",
        "propertyStartType": "none",
        "propertyStartCompare": "true",
        "propertyStartThreshold": "",
        "propertyStartThresholdType": "num",
        "startTimeAlt": "",
        "startTimeAltType": "entered",
        "startOffsetAlt": 0,
        "startOffsetAltType": "none",
        "startOffsetAltMultiplier": 60000,
        "propertyEnd": "",
        "propertyEndType": "none",
        "propertyEndCompare": "true",
        "propertyEndThreshold": "",
        "propertyEndThresholdType": "num",
        "endTimeAlt": "",
        "endTimeAltType": "entered",
        "endOffsetAlt": 0,
        "endOffsetAltType": "none",
        "endOffsetAltMultiplier": 60000,
        "withinTimeValue": "",
        "withinTimeValueType": "msgInput",
        "outOfTimeValue": "",
        "outOfTimeValueType": "msgInput",
        "tsCompare": "0",
        "x": 310,
        "y": 760,
        "wires": [
            [
                "cbda7ba3f1b5dd8c"
            ],
            [
                "6fba0be572ad1fcc"
            ]
        ]
    },
    {
        "id": "62e234f625a2a02a",
        "type": "http request",
        "z": "457f9988695be7c4",
        "name": "Solcast API - get Live+Forecast JSON WEST",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "https://api.solcast.com.au/rooftop_sites/XXXXXXXXXXXXXXX",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "basic",
        "senderr": false,
        "x": 630,
        "y": 540,
        "wires": [
            [
                "50f9f1260a2a3cab"
            ]
        ]
    },
    {
        "id": "23605978e56b965d",
        "type": "http request",
        "z": "457f9988695be7c4",
        "name": "Solcast API - get Past + Estimated Actuals WEST",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "https://api.solcast.com.au/rooftop_sites/XXXXXXXXXX",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "basic",
        "senderr": false,
        "x": 650,
        "y": 500,
        "wires": [
            [
                "50f9f1260a2a3cab"
            ]
        ]
    },
    {
        "id": "50f9f1260a2a3cab",
        "type": "switch",
        "z": "457f9988695be7c4",
        "name": "StatusCode",
        "property": "statusCode",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "200",
                "vt": "num"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 970,
        "y": 560,
        "wires": [
            [
                "080fa57b694d22f0"
            ],
            [
                "96fb7138c35bd826",
                "c0e0319e8b59c5ca"
            ]
        ]
    },
    {
        "id": "96fb7138c35bd826",
        "type": "change",
        "z": "457f9988695be7c4",
        "name": "timestamp",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "",
                "tot": "date"
            },
            {
                "t": "delete",
                "p": "statusCode",
                "pt": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1230,
        "y": 640,
        "wires": [
            [
                "5e61daf7a3b261cc"
            ]
        ]
    },
    {
        "id": "5e61daf7a3b261cc",
        "type": "delay",
        "z": "457f9988695be7c4",
        "name": "",
        "pauseType": "delay",
        "timeout": "3",
        "timeoutUnits": "minutes",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "outputs": 1,
        "x": 1440,
        "y": 640,
        "wires": [
            []
        ]
    },
    {
        "id": "080fa57b694d22f0",
        "type": "switch",
        "z": "457f9988695be7c4",
        "name": "",
        "property": "topic",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "estimated_actuals",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "forecasts",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 1190,
        "y": 500,
        "wires": [
            [],
            [
                "18b30938e9b171ea"
            ]
        ]
    },
    {
        "id": "d546ea9a582551d0",
        "type": "join",
        "z": "457f9988695be7c4",
        "name": "",
        "mode": "custom",
        "build": "array",
        "property": "payload",
        "propertyType": "msg",
        "key": "topic",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "2",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "",
        "reduceFixup": "",
        "x": 1870,
        "y": 340,
        "wires": [
            [
                "458232a4a5ef55e4"
            ]
        ]
    },
    {
        "id": "458232a4a5ef55e4",
        "type": "debug",
        "z": "457f9988695be7c4",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 2350,
        "y": 340,
        "wires": []
    },
    {
        "id": "18b30938e9b171ea",
        "type": "mock",
        "z": "457f9988695be7c4",
        "name": "",
        "x": 1370,
        "y": 500,
        "wires": [
            [
                "3a5f9fe881377a01"
            ]
        ]
    },
    {
        "id": "5b41b7be8a1ce405",
        "type": "mock",
        "z": "457f9988695be7c4",
        "name": "",
        "x": 1350,
        "y": 200,
        "wires": [
            [
                "4eae59afbaad4281"
            ]
        ]
    },
    {
        "id": "4eae59afbaad4281",
        "type": "change",
        "z": "457f9988695be7c4",
        "name": "rename forecasts array (east)",
        "rules": [
            {
                "t": "move",
                "p": "payload.forecasts",
                "pt": "msg",
                "to": "payload.forecasts_east",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1630,
        "y": 200,
        "wires": [
            [
                "d546ea9a582551d0"
            ]
        ]
    },
    {
        "id": "3a5f9fe881377a01",
        "type": "change",
        "z": "457f9988695be7c4",
        "name": "rename forecasts array (west)",
        "rules": [
            {
                "t": "move",
                "p": "payload.forecasts",
                "pt": "msg",
                "to": "payload.forecasts_west",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1630,
        "y": 500,
        "wires": [
            [
                "d546ea9a582551d0"
            ]
        ]
    },
    {
        "id": "8c7609ce.dd5798",
        "type": "position-config",
        "name": "DACH-1",
        "isValide": "true",
        "longitude": "0",
        "latitude": "0",
        "angleType": "deg",
        "timeZoneOffset": 99,
        "timeZoneDST": 0,
        "stateTimeFormat": "3",
        "stateDateFormat": "12",
        "contextStore": ""
    }
]

Edit: Just connected the mock nodes to the debug node, and it looks like the payload is empty. Not sure why?

image

...try/look at this part:

[{"id":"4148e45e.9f396c","type":"change","z":"cfcb4279.2fe54","name":"move forecasts to east","rules":[{"t":"move","p":"payload.forecasts","pt":"msg","to":"payload.east","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":240,"y":160,"wires":[["f58bd530.3fa968","3ea6000a.5511e"]]},{"id":"f58bd530.3fa968","type":"join","z":"cfcb4279.2fe54","name":"","mode":"custom","build":"merged","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"3","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":530,"y":200,"wires":[["3ff6ee38.472862"]]},{"id":"997fb560.63c828","type":"change","z":"cfcb4279.2fe54","name":"move forecasts to west","rules":[{"t":"move","p":"payload.forecasts","pt":"msg","to":"payload.west","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":240,"y":240,"wires":[["f58bd530.3fa968"]]},{"id":"3ff6ee38.472862","type":"debug","z":"cfcb4279.2fe54","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":810,"y":200,"wires":[]},{"id":"3ea6000a.5511e","type":"change","z":"cfcb4279.2fe54","name":"copy east to sum","rules":[{"t":"set","p":"payload.sum","pt":"msg","to":"payload.east","tot":"msg"},{"t":"delete","p":"payload.east","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":320,"wires":[["f58bd530.3fa968"]]}]

remember, the sum object still contains the values from east...you will need to create the function node to actually add the values from east and west and store them in sum at the same index and object.

I currently on the road and cannot help much better.

look at the methods used for deploying a flow in NR.
Once you deploy a complete flow, the nodes get restarted and the mock node will be empty until a new api call comes in. Change NR to deploy only changed nodes and the stored message will survive in the mock node (provides you did not change the mock node - including connections and position)