Automate Fronius Soft Limit

pkuhn have you got this dual inverter configuration setup working effectively?

I have two Primo GEN24ā€™s, one with two strings, and one with one string and connected to a battery. The inverters are running independently given there is no way to connect these models in any type of master/slave connection. I know other models of Fronius do support that but these Primo GEN24ā€™s do not. If anyone knows to the contrary and how please let me know.

So trying to implement the soft limit in this scenario seems impossible. From my trial and error observations activating the soft limit in the manner described on this thread (Export Limiting Power Switched on with FeedIn set to zero, then activated via Modbus) on both inverters results in instability in both inverters ramping up and down in conflict with each other. It seems to particular favour agressive ramp down and very slow ramp up (several minutes).
I thought to try and run the limit only on the one inverter (the one not connected to the battery) but again the very slow ramp up means that the inverter with the battery never ā€œseesā€ the excess power available to increase battery charging and the system stays very highly throttled and never ramps up.

A few other thoughts and questions.
The Export Limitation menu mentions the Mode as ā€œLimit Entire Systemā€. If the inverters do not talk to each other there is no mechanism where the ā€œentire systemā€ can be limited. Is this just a hangover from previous models where it was possible?
Does the setting ā€œTotal DC power of the Entire Systemā€ have any impact at all. I think it only is important if you use a percentage for the maximum feedin power.

A thanks to all on this thread, Iā€™ve got to a point where I can set controls on everything but stuck now on this dual inverter setup.

If the inverters are linked by DATCOM - then you only need the IP address of the lead inverter and you configure it as per drjmzā€™s post

I have the original Primos which are linked via DATCOM in a master / slave arrangement. Do

As for independent inverters - that soundā€™s trickier if they canā€™t see each other or if there isnā€™t a Fronius consumption meter reading both outputs.

Are both inverters the same size or different. This article from Fronius may help? [Fronius Symo GEN24 6 - 10 kW / 6 - 10 kW Plus Operating Instructions]
Dynamic power regulation with several inverters (Fronius Symo GEN24 6 - 10 kW / 6 - 10 kW Plus Operating Instructions)

Thanks for link Phil, interesting.

In Example 1 Iā€™m guessing you could only throttle the GEN24 down to zero leaving you with a min. feedin limited by the maximum of the SnapIN

In Example 2a I have actually managed to connect my Power Meter to both of my inverters by connecting the Modbus connection in parallel (not sure why you would need a second one to provide the same data). Both inverters see the power readings effectively. I had the settings pretty much identical to this setup today and it just wouldnā€™t ramp up.
Iā€™ve found this though in the System, Information menu under Ramp Rates :

Which goes to @pete.AUS previous posts to slow ramp up rates. Iā€™m not sure if fixing this will provide a solution for me but Iā€™ll get it fixed first. Does anyone have a hack to get into the Access Code Country Setup on the GEN24 so I can fix this?? I donā€™t know how hard or long it is going to take to get my installer back to get this changed.

OK Iā€™ve just seen this on another forum. Hopefully this is the answer.

I thought Iā€™d quickly post my experience of testing this today. Bottom line it is not working well for me in more ways than one.

Firstly looking at the video it is self evident that the Master is controlling the slave via Modbus TCP. Critically, while monitoring the ā€œImmediate Controlā€ registers you can see it dynamically adjusting WMaxLimPct as the throttle mechanism on both Master and Slave Inverters. This is interesting as any previous throttle mechanism for export limit was not visible in this register. Unfortunately though it appears as a result you are locked out of making any changes yourself to those registers meaning I doubt there is an easy way to effectively switch on and off the export limit unless you can work with some sort of http based control on the web interface. Secondly it seems every 5 or so minutes stats go missing, I suspect there is some contention issue on the Modbus control.
Lastly throttling balance to battery charge didnā€™t seem to be prioritised at all, meaning the panel power was throttled back to the export limit with no prioritisation to bring the power back up and send it to the battery, one of the key aspects I thought this feature would bring (this could still be the ramp up issue, I havenā€™t got that changed yet).
I still want to play around with some settings a bit more but first experience not so good.

Thank you @juande and @tux43. I was completely stuck on the idea that I need to turn on dynamic power reduction.

But instead itā€™s turning off production limit of 100%, which falls back to next in priority which is dynamic power reduction :smiley: Just genius

Also, Fronius, what the hell - Modbus, Solar API and still nothing for making use of your smart meter.

Sorry just seen this

For the Snap Primo inverters is the same, for the Gen24 its device spacific that only the installer can change.

Its due to the country code in use for some reason Fronius set stupid ramp rates for Australia.

Man, sorry for theā€¦well annual reply cycleā€¦

I got mine working initially just using modbus from in home assistant but like 5 days ago I got the installer to let me set a new service password.

I sent them my intentions (cos they were understandably reluctant) and a screenshot I have form a draft energex proposal that is implementing a reverse demand for solar where they do the same process for demand but charge you for exports between certain times.

The inverter is much more efficient at managing it but Iā€™m still tweaking tolerances cos sometimes the battery (ac coupled) just sits there not charging because the fronuis steps down (basically have to tell it to always allow 100 watts export minimum)

I also have tried contacting about another matter, but without any response too. However, it still seems to be working for me ā€¦? (Fronius Primo firmware 3.31.1-5)

That is good of you, the only thing is that the fronius-auth-proxy allows you to modify many of the areas in the web UI (whereas yours seems to just be the export limit setting?). I am using fronius-auth-proxy mainly to control load management settings.

yours seems to just be the export limit setting

Correctā€¦ but seeing as thatā€™s all I need, thatā€™s all I cared about :stuck_out_tongue:

Iā€™m by no means against the idea of people adding additional functionality to this project as they require it though.

Anyone wanting to do this (enable/disable export limits) in script form: enjoy:

#!/bin/bash

# Input parameters
USERNAME="service"
PASSWORD="***"
URL="http://***/config/exportlimit/?method=save"
DATA_ON=' {"powerLimits":{"exportLimits":{"activePower":{"hardLimit":{"enabled":false,"powerLimit":0},"mode":"entireSystem","softLimit":{"enabled":true, "powerLimit":0}},"failSafeModeEnabled":false},"visualization":{"exportLimits":{"activePower":{"displayModeHardLimit":"absolute","displayModeSoftLimit":"absolute"}},"wattPeakReferenceValue":0}}}'
DATA_OFF='{"powerLimits":{"exportLimits":{"activePower":{"hardLimit":{"enabled":false,"powerLimit":0},"mode":"off",         "softLimit":{"enabled":false,"powerLimit":0}},"failSafeModeEnabled":false},"visualization":{"exportLimits":{"activePower":{"displayModeHardLimit":"absolute","displayModeSoftLimit":"absolute"}},"wattPeakReferenceValue":0}}}'
METHOD="POST"

# Convert argument to uppercase to match variable names
ACTION=$(echo "$1" | tr '[:lower:]' '[:upper:]')

# Use indirect variable referencing to get the DATA
DATA_VAR="DATA_$ACTION"
DATA="${!DATA_VAR}"

# Check if argument is provided
if [ -z "$1" ]; then
  echo "Usage: $0 [ON|OFF]"
  exit 1
fi

# Step 1: Get the authentication challenge (x-www-authenticate header)
AUTH_CHALLENGE=$(curl -s -D - "$URL" -o /dev/null | grep -i 'x-www-authenticate:' | sed 's/x-www-authenticate: //I' | tr -d '\r')

# Check if AUTH_CHALLENGE is empty
if [ -z "$AUTH_CHALLENGE" ]; then
    echo "Failed to get authentication challenge from server."
    exit 1
fi

# Step 2: Parse the challenge parameters
realm=$(echo "$AUTH_CHALLENGE" | sed -n 's/.*realm="\([^"]*\)".*/\1/p')
nonce=$(echo "$AUTH_CHALLENGE" | sed -n 's/.*nonce="\([^"]*\)".*/\1/p')
qop=$(echo "$AUTH_CHALLENGE" | sed -n 's/.*qop="\([^"]*\)".*/\1/p')

# If qop is empty, default to 'auth'
if [ -z "$qop" ]; then
    qop="auth"
fi

# Other parameters
uri="/config/exportlimit/?method=save"
nc="00000001"
cnonce="abcdef0123456789"

# Step 3: Compute HA1, HA2, and Response using OpenSSL
# HA1 = MD5(username:realm:password)
ha1=$(printf "%s:%s:%s" "$USERNAME" "$realm" "$PASSWORD" | openssl md5 | awk '{print $2}')

# HA2 = MD5(method:uri)
ha2=$(printf "%s:%s" "$METHOD" "$uri" | openssl md5 | awk '{print $2}')

# Response = MD5(HA1:nonce:nc:cnonce:qop:HA2)
response=$(printf "%s:%s:%s:%s:%s:%s" "$ha1" "$nonce" "$nc" "$cnonce" "$qop" "$ha2" | openssl md5 | awk '{print $2}')

# Build the Authorization header
AUTH_HEADER="Digest username=\"$USERNAME\", realm=\"$realm\", nonce=\"$nonce\", uri=\"$uri\", algorithm=MD5, response=\"$response\", qop=$qop, nc=$nc, cnonce=\"$cnonce\""

# Step 4: Make the authenticated request
curl -X "$METHOD" "$URL" \
  -H "Content-Type: application/json;charset=utf-8" \
  -H "Authorization: $AUTH_HEADER" \
  -d "$DATA"
1 Like

Iā€™m going to add one other thing to the conversation. Iā€™m running unifi dream machine router with 3 access points. With the fronius primo and symo in master slave arrangement connected by wifi HA would occasionally lose capability to control via modbus, and the fronius integration wouldnt load correctly.

I ended up running a cat cable from the router to the inverter and no more issues, and it seems to be far quicker in responding to modbus commands.

1 Like

Has anbody had the issue since setting this up - for not feeding in during negative feed in this all works fine, however when I have negative draw from the grid (getting paid to take from the grid).

If the house is drawing above 5KW then it draws from my battery aswell - say if my house is pulling 9KW with the A/C going it will take 5KW from the grid then the other 4KW from my battery.

Is this an issue with my fronius configuration/ modbus or is something else going on here?

Cheers!

When grid price is negative, isnā€™t your automation setup to limit itā€™s output to 0? Iā€™d imagine WMaxLimPct controls all inverter output i.e. solar & battery. Donā€™t have a battery to test. Thereā€™s also a register called ChaGriSet which could be limiting you?

that is correct - when feed in price is negative, however sometimes to draw from the grid is negative ( you get paid to take from the grid) in that case my solar turns off and I draw entirely from the grid - however anything over 5KW and it draws from my battery and not the grid - so rather than filling up the battery and powering the house - I am powering the house and depleting my battery.

*edits cause itā€™s been a long day

Yeah thatā€™s strange. Donā€™t have a battery myself to test unfortunatley.

With Node-Red I was able to create a nice tariff based controller for my GEN24 10kW. Maybe the Node Red code is usefull inspiration :slight_smile:

The whole register setting is some what unlogical to me but I managed to figure it out.

[{"id":"ffb07c75f3edf808","type":"group","z":"082d1a6d7f9f4ee6","name":"Write changes to Gen24 inverter (1Hz)","style":{"fill":"#c8e7a7","label":true},"nodes":["acc53a6f4ee7fcc1","042d68470832006d","612e3990e9a32c1d","313d603e6a147c48","e23254938653df68"],"x":1414,"y":559,"w":992,"h":142},{"id":"acc53a6f4ee7fcc1","type":"function","z":"082d1a6d7f9f4ee6","g":"ffb07c75f3edf808","name":"Modbus Payload Packet","func":"var values = [msg.storctl_mod, (65535), (500), (10000), (65535), (65535), (5), (msg.outwrte), (msg.inwrte)]\n\nmsg.payload = {\n    'value': values,\n    'fc': 16,\n    'unitid': 1,\n    // INT+SF = -10\n    'address': 40358,\n    'quantity': 9\n}\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1550,"y":640,"wires":[["e23254938653df68"]]},{"id":"042d68470832006d","type":"modbus-response","z":"082d1a6d7f9f4ee6","g":"ffb07c75f3edf808","name":"","registerShowMax":20,"x":2210,"y":600,"wires":[]},{"id":"612e3990e9a32c1d","type":"modbus-flex-write","z":"082d1a6d7f9f4ee6","g":"ffb07c75f3edf808","name":"Fronius Storage","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"bcc4229c.180ac","emptyMsgOnFail":true,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":1980,"y":640,"wires":[["042d68470832006d","313d603e6a147c48"],[]]},{"id":"313d603e6a147c48","type":"debug","z":"082d1a6d7f9f4ee6","g":"ffb07c75f3edf808","name":"Inverter MODBUS Response","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":2240,"y":660,"wires":[]},{"id":"e23254938653df68","type":"delay","z":"082d1a6d7f9f4ee6","g":"ffb07c75f3edf808","name":"Rate limit (1Hz)","pauseType":"rate","timeout":"500","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":1780,"y":640,"wires":[["612e3990e9a32c1d"]]},{"id":"bcc4229c.180ac","type":"modbus-client","name":"Fronius","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":false,"tcpHost":"192.168.x.x","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"","unit_id":200,"commandDelay":1,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true},{"id":"e71396201ab31ab6","type":"group","z":"082d1a6d7f9f4ee6","name":"SOC charge/discharge manager","style":{"fill":"#c8e7a7","label":true},"nodes":["ab44b5cb2df49b31","c888c99eccf91d8c","9578ea3068d442bf"],"x":594,"y":499,"w":652,"h":122},{"id":"ab44b5cb2df49b31","type":"api-current-state","z":"082d1a6d7f9f4ee6","g":"e71396201ab31ab6","name":"Battery SOC lower than 20%, stop discharge","server":"aa39721f.3c9dc","version":3,"outputs":2,"halt_if":"20","halt_if_type":"num","halt_if_compare":"lte","entity_id":"sensor.tesla_battery_state_of_charge","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"status","propertyType":"msg","value":"SOC < 20%","valueType":"str"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1030,"y":540,"wires":[["e39ad0b0a923904a"],[]]},{"id":"c888c99eccf91d8c","type":"api-current-state","z":"082d1a6d7f9f4ee6","g":"e71396201ab31ab6","name":"Battery SOC higher than 30%, normal operation","server":"aa39721f.3c9dc","version":3,"outputs":2,"halt_if":"25","halt_if_type":"num","halt_if_compare":"gt","entity_id":"sensor.tesla_battery_state_of_charge","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"status","propertyType":"msg","value":"SOC > 30%","valueType":"str"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1040,"y":580,"wires":[["7219cc5524b6201c"],[]]},{"id":"9578ea3068d442bf","type":"ha-switch","z":"082d1a6d7f9f4ee6","g":"e71396201ab31ab6","name":"SOC manager On/Off","version":0,"debugenabled":false,"inputs":1,"outputs":2,"entityConfig":"2f29503ca621eacd","enableInput":true,"outputOnStateChange":false,"outputProperties":[{"property":"outputType","propertyType":"msg","value":"state change","valueType":"str"},{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"x":720,"y":560,"wires":[["ab44b5cb2df49b31","c888c99eccf91d8c"],[]]},{"id":"aa39721f.3c9dc","type":"server","name":"Home Assistant 1","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","statusSeparator":"","enableGlobalContextStore":false},{"id":"2f29503ca621eacd","type":"ha-entity-config","server":"aa39721f.3c9dc","deviceConfig":"","name":"SOC manager On/Off","version":"6","entityType":"switch","haConfig":[{"property":"name","value":"SOC manager On/Off"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""}],"resend":false,"debugEnabled":false},{"id":"c927b6a863acb390","type":"group","z":"082d1a6d7f9f4ee6","name":"Every minute and protections","style":{"label":true,"fill":"#dbcbe7"},"nodes":["f571da0891d8ce43","d26c1cd22f597dab","93e59122d814ce01"],"x":14,"y":439,"w":532,"h":182},{"id":"f571da0891d8ce43","type":"cronplus","z":"082d1a6d7f9f4ee6","g":"c927b6a863acb390","name":"every 2 seconds","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"0/2 * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":140,"y":580,"wires":[["93e59122d814ce01","http-request-node"]]},{"id":"d26c1cd22f597dab","type":"api-current-state","z":"082d1a6d7f9f4ee6","g":"c927b6a863acb390","name":"Above backup energy level","server":"aa39721f.3c9dc","version":3,"outputs":2,"halt_if":"10","halt_if_type":"num","halt_if_compare":"gte","entity_id":"sensor.tesla_battery_state_of_charge","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"status","propertyType":"msg","value":"SOC  >= min%","valueType":"str"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":320,"y":480,"wires":[["98275a63d7578b29"],["11a3663361be0176"]]},{"id":"93e59122d814ce01","type":"ha-switch","z":"082d1a6d7f9f4ee6","g":"c927b6a863acb390","name":"Auto battery management","version":0,"debugenabled":false,"inputs":1,"outputs":2,"entityConfig":"8c13c83e43673f66","enableInput":true,"outputOnStateChange":false,"outputProperties":[{"property":"outputType","propertyType":"msg","value":"state change","valueType":"str"},{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"x":410,"y":580,"wires":[["d26c1cd22f597dab"],["9578ea3068d442bf"]]},{"id":"8c13c83e43673f66","type":"ha-entity-config","server":"aa39721f.3c9dc","deviceConfig":"","name":"Auto battery management","version":"6","entityType":"switch","haConfig":[{"property":"name","value":"Auto battery management"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""}],"resend":false,"debugEnabled":false},{"id":"972413b3b474c04e","type":"group","z":"082d1a6d7f9f4ee6","name":"Energy selling and buying","style":{"label":true,"stroke":"#a4a4a4","fill":"#bfdbef","fill-opacity":"0.47"},"nodes":["166f102fe8044a4d","fd2ffb49be6386f4","9eb0e0e8a944a8ab","4da31527a79ba2bb","d154056291b873bc","8934403241c202e6"],"x":28,"y":13,"w":1424,"h":408},{"id":"166f102fe8044a4d","type":"junction","z":"082d1a6d7f9f4ee6","g":"972413b3b474c04e","x":1340,"y":360,"wires":[["7219cc5524b6201c"]]},{"id":"fd2ffb49be6386f4","type":"api-call-service","z":"082d1a6d7f9f4ee6","g":"972413b3b474c04e","name":"Update Normal Price State","server":"aa39721f.3c9dc","version":7,"debugenabled":false,"action":"input_text.set_value","floorId":[],"areaId":[],"deviceId":[],"entityId":["input_text.price_select_state"],"labelId":[],"data":"{\"value\":\"normal\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"input_text","service":"set_value","x":880,"y":380,"wires":[[]]},{"id":"9eb0e0e8a944a8ab","type":"group","z":"082d1a6d7f9f4ee6","g":"972413b3b474c04e","name":"Low price","style":{"stroke":"#a4a4a4","label":true,"fill":"#e3f3d3"},"nodes":["b659660eddbff070","d122f965b4cc06c2","7f64baa7b4233a58"],"x":754,"y":39,"w":292,"h":142},{"id":"b659660eddbff070","type":"api-call-service","z":"082d1a6d7f9f4ee6","g":"9eb0e0e8a944a8ab","name":"Update Low Price State","server":"aa39721f.3c9dc","version":7,"debugenabled":false,"action":"input_text.set_value","floorId":[],"areaId":[],"deviceId":[],"entityId":["input_text.price_select_state"],"labelId":[],"data":"{\"value\":\"low\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"input_text","service":"set_value","x":910,"y":80,"wires":[[]]},{"id":"d122f965b4cc06c2","type":"ha-switch","z":"082d1a6d7f9f4ee6","g":"9eb0e0e8a944a8ab","name":"Energy buying","version":0,"debugenabled":false,"inputs":1,"outputs":2,"entityConfig":"7e0478382e6245ea","enableInput":true,"outputOnStateChange":false,"outputProperties":[{"property":"outputType","propertyType":"msg","value":"state change","valueType":"str"},{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"x":870,"y":140,"wires":[["11a3663361be0176"],["166f102fe8044a4d"]]},{"id":"7f64baa7b4233a58","type":"junction","z":"082d1a6d7f9f4ee6","g":"9eb0e0e8a944a8ab","x":780,"y":140,"wires":[["b659660eddbff070","d122f965b4cc06c2"]]},{"id":"7e0478382e6245ea","type":"ha-entity-config","server":"aa39721f.3c9dc","deviceConfig":"","name":"Energy buying","version":"6","entityType":"switch","haConfig":[{"property":"name","value":"Energy buying"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""}],"resend":false,"debugEnabled":false},{"id":"4da31527a79ba2bb","type":"group","z":"082d1a6d7f9f4ee6","g":"972413b3b474c04e","name":"High price","style":{"fill":"#ffbfbf","label":true},"nodes":["b31e815209d2c646","9b6a8f9c6e184f7f","0afdd7a9f3168964","ae318f7d467ec754"],"x":754,"y":199,"w":672,"h":142},{"id":"b31e815209d2c646","type":"api-call-service","z":"082d1a6d7f9f4ee6","g":"4da31527a79ba2bb","name":"Update High Price State","server":"aa39721f.3c9dc","version":7,"debugenabled":false,"action":"input_text.set_value","floorId":[],"areaId":[],"deviceId":[],"entityId":["input_text.price_select_state"],"labelId":[],"data":"{\"value\":\"high\"}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"input_text","service":"set_value","x":910,"y":240,"wires":[[]]},{"id":"9b6a8f9c6e184f7f","type":"ha-switch","z":"082d1a6d7f9f4ee6","g":"4da31527a79ba2bb","name":"Energy selling","version":0,"debugenabled":false,"inputs":1,"outputs":2,"entityConfig":"6806eaeffeb00bc4","enableInput":true,"outputOnStateChange":false,"outputProperties":[{"property":"outputType","propertyType":"msg","value":"state change","valueType":"str"},{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"x":870,"y":300,"wires":[["ae318f7d467ec754"],["166f102fe8044a4d"]]},{"id":"0afdd7a9f3168964","type":"junction","z":"082d1a6d7f9f4ee6","g":"4da31527a79ba2bb","x":780,"y":280,"wires":[["b31e815209d2c646","9b6a8f9c6e184f7f"]]},{"id":"ae318f7d467ec754","type":"api-current-state","z":"082d1a6d7f9f4ee6","g":"4da31527a79ba2bb","name":"Battery SOC >= than 10%, discharge","server":"aa39721f.3c9dc","version":3,"outputs":2,"halt_if":"10","halt_if_type":"num","halt_if_compare":"gte","entity_id":"sensor.tesla_battery_state_of_charge","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"status","propertyType":"msg","value":"SOC >= 10%","valueType":"str"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1250,"y":280,"wires":[["0d8023037a7d1b5a"],["166f102fe8044a4d"]]},{"id":"6806eaeffeb00bc4","type":"ha-entity-config","server":"aa39721f.3c9dc","deviceConfig":"","name":"Energy selling","version":"6","entityType":"switch","haConfig":[{"property":"name","value":"Energy selling"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""}],"resend":false,"debugEnabled":false},{"id":"d154056291b873bc","type":"group","z":"082d1a6d7f9f4ee6","g":"972413b3b474c04e","name":"Selector","style":{"label":true,"stroke":"#9363b7","stroke-opacity":"0.55"},"nodes":["3bdd4e2662f4b4a4","98275a63d7578b29","fd320becde60c34c","d319fc7d7512279e","94137adeb2ba33eb","de8324abdcf0b2cf"],"x":54,"y":179,"w":632,"h":202},{"id":"3bdd4e2662f4b4a4","type":"api-current-state","z":"082d1a6d7f9f4ee6","g":"d154056291b873bc","name":"Get spot price","server":"aa39721f.3c9dc","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.epex_spot_data_net_price","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"price","propertyType":"msg","value":"","valueType":"entityState"},{"property":"topic","propertyType":"msg","value":"price","valueType":"str"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":200,"y":220,"wires":[["94137adeb2ba33eb"]]},{"id":"98275a63d7578b29","type":"junction","z":"082d1a6d7f9f4ee6","g":"d154056291b873bc","x":80,"y":280,"wires":[["3bdd4e2662f4b4a4","fd320becde60c34c","d319fc7d7512279e"]]},{"id":"fd320becde60c34c","type":"api-current-state","z":"082d1a6d7f9f4ee6","g":"d154056291b873bc","name":"Get low price threshold","server":"aa39721f.3c9dc","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_number.low_price_threshold","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"lowThreshold","propertyType":"msg","value":"","valueType":"entityState"},{"property":"topic","propertyType":"msg","value":"lowThreshold","valueType":"str"}],"for":0,"forType":"num","forUnits":"minutes","x":230,"y":280,"wires":[["94137adeb2ba33eb"]]},{"id":"d319fc7d7512279e","type":"api-current-state","z":"082d1a6d7f9f4ee6","g":"d154056291b873bc","name":"Get high price threshold","server":"aa39721f.3c9dc","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_number.high_price_threshold","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"highThreshold","propertyType":"msg","value":"","valueType":"entityState"},{"property":"topic","propertyType":"msg","value":"highThreshold","valueType":"str"}],"for":0,"forType":"num","forUnits":"minutes","x":230,"y":340,"wires":[["94137adeb2ba33eb"]]},{"id":"94137adeb2ba33eb","type":"join","z":"082d1a6d7f9f4ee6","g":"d154056291b873bc","name":"","mode":"custom","build":"object","property":"","propertyType":"full","key":"topic","joiner":"\\n","joinerType":"str","useparts":false,"accumulate":false,"timeout":"","count":"3","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":450,"y":260,"wires":[["de8324abdcf0b2cf"]]},{"id":"de8324abdcf0b2cf","type":"switch","z":"082d1a6d7f9f4ee6","g":"d154056291b873bc","name":"Price select (ct)","property":"price","propertyType":"msg","rules":[{"t":"lte","v":"lowThreshold","vt":"msg"},{"t":"gte","v":"highThreshold","vt":"msg"},{"t":"else"}],"checkall":"false","repair":false,"outputs":3,"x":580,"y":320,"wires":[["7f64baa7b4233a58"],["0afdd7a9f3168964"],["166f102fe8044a4d","fd2ffb49be6386f4"]]},{"id":"8934403241c202e6","type":"comment","z":"082d1a6d7f9f4ee6","g":"972413b3b474c04e","name":"10% SOC backup buffer","info":"De inverter is ingesteld op dat minimaal \n10% soc beschikbaar blijft voor backup-power\n\n% in te stellen op de locale GEN24 pagina:\nDevice configuration > FuncĀ­tions and I/Os","x":470,"y":100,"wires":[]},{"id":"6f28ef0306b0dbd9","type":"group","z":"082d1a6d7f9f4ee6","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["7219cc5524b6201c","0d8023037a7d1b5a","e39ad0b0a923904a","8b9fdfe7e1821416"],"x":1474,"y":299,"w":552,"h":202},{"id":"7219cc5524b6201c","type":"function","z":"082d1a6d7f9f4ee6","g":"6f28ef0306b0dbd9","name":"Normal operation","func":"msg.storctl_mod = \"0\"\n\nmsg.newstate = \"normal\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1590,"y":460,"wires":[["8b9fdfe7e1821416"]],"info":"Example 3: Do not permit charging or discharging\nThis behavior can be achieved by limiting the maximum charge capacity to 0%\nand the maximum discharge capacity to 0%\n=> results in window [0 W, 0 W]\n- InWRte = 0% (set charge limit of WchaMax to 0%)\n- OutWRte = 0% (set discharge limit of WchaMax to 0%)\n- StorCtl_Mod = 3 (activate both limit values, bit pattern: 11)"},{"id":"0d8023037a7d1b5a","type":"function","z":"082d1a6d7f9f4ee6","g":"6f28ef0306b0dbd9","name":"Max discharge","func":"msg.storctl_mod = \"1\"\nmsg.outwrte = \"0\"\nmsg.inwrte = \"60933\"\n\nmsg.newstate = \"Max discharge\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1580,"y":340,"wires":[["8b9fdfe7e1821416"]],"info":"Example 3: Do not permit charging or discharging\nThis behavior can be achieved by limiting the maximum charge capacity to 0%\nand the maximum discharge capacity to 0%\n=> results in window [0 W, 0 W]\n- InWRte = 0% (set charge limit of WchaMax to 0%)\n- OutWRte = 0% (set discharge limit of WchaMax to 0%)\n- StorCtl_Mod = 3 (activate both limit values, bit pattern: 11)"},{"id":"e39ad0b0a923904a","type":"function","z":"082d1a6d7f9f4ee6","g":"6f28ef0306b0dbd9","name":"No discharge, allow solar charge","func":"msg.storctl_mod = \"3\"\nmsg.outwrte = \"0\"\nmsg.inwrte = \"2439\"\n\nmsg.newstate = \"No discharge, allow solar charge\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1640,"y":400,"wires":[["8b9fdfe7e1821416"]],"info":"Example 3: Do not permit charging or discharging\nThis behavior can be achieved by limiting the maximum charge capacity to 0%\nand the maximum discharge capacity to 0%\n=> results in window [0 W, 0 W]\n- InWRte = 0% (set charge limit of WchaMax to 0%)\n- OutWRte = 0% (set discharge limit of WchaMax to 0%)\n- StorCtl_Mod = 3 (activate both limit values, bit pattern: 11)"},{"id":"8b9fdfe7e1821416","type":"junction","z":"082d1a6d7f9f4ee6","g":"6f28ef0306b0dbd9","x":2000,"y":400,"wires":[["acc53a6f4ee7fcc1"]]},{"id":"336421b5a0497c39","type":"group","z":"082d1a6d7f9f4ee6","name":"Charge + Main fuse over current limiter for Home battery charger","style":{"fill":"#ffC000","fill-opacity":"0.78","label":true},"nodes":["987e5486ddb6e3cb","7072c1b693b72fe8","11a3663361be0176"],"x":1474,"y":199,"w":552,"h":82},{"id":"987e5486ddb6e3cb","type":"comment","z":"082d1a6d7f9f4ee6","g":"336421b5a0497c39","name":"TODO!","info":"Make some signalling on Home Assistant\ndashboard.","x":1950,"y":240,"wires":[]},{"id":"7072c1b693b72fe8","type":"function","z":"082d1a6d7f9f4ee6","g":"336421b5a0497c39","name":"Calculate amount of charge power","func":"// Retrieve the stored smart meter data from the flow context\nconst meterData = flow.get('smartMeterData');\n\nif (!meterData || !meterData.Body || !meterData.Body.Data) {\n    node.error(\"No valid data from the smart meter\");\n    return null;\n}\n\n// Extract data from the smart meter response\nconst phase1Current = meterData.Body.Data.Current_AC_Phase_1 || 0; // Phase 1 current in Amps\nconst phase2Current = meterData.Body.Data.Current_AC_Phase_2 || 0; // Phase 2 current in Amps\nconst phase3Current = meterData.Body.Data.Current_AC_Phase_3 || 0; // Phase 3 current in Amps\n\n// Constants for calculations\nconst fuseValue = 25; // Maximum allowable current in amps\nconst registerStart = 65291; // Maximum register value\nconst registerEnd = 63296; // Minimum register value\nconst extraStepUp = 200; // Extra step size for sudden overload\nconst stepUp = 50; // Step size to increase register value\nconst stepDown = 50; // Step size to decrease register value\n\n// Current register value and previous max current from context\nconst currentRegisterValue = context.get('currentRegisterValue') || registerStart;\nconst previousMaxCurrent = context.get('previousMaxCurrent') || 0;\n\n// Calculate maximum current across phases\nconst maxCurrent = Math.max(phase1Current, phase2Current, phase3Current);\n\n// Determine if the maximum current exceeds the fuse value\nconst availableMargin = fuseValue - maxCurrent;\nconst suddenOverload = maxCurrent > fuseValue + 5;\n\n// Adjust the register value based on conditions\nlet updatedRegisterValue = currentRegisterValue;\n\nif (suddenOverload) {\n    // Increase register value due to sudden overload\n    updatedRegisterValue = Math.min(currentRegisterValue + extraStepUp, registerStart);\n    node.warn(\"Sudden overload detected. Increased register value.\");\n} else if (availableMargin <= 0) {\n    // Increase register value due to overload\n    updatedRegisterValue = Math.min(currentRegisterValue + stepUp, registerStart);\n    node.warn(\"Overload detected. Increased register value.\");\n} else {\n    // Decrease register value within safe margin\n    updatedRegisterValue = Math.max(currentRegisterValue - stepDown, registerEnd);\n    node.warn(\"Safe margin detected. Decreased register value.\");\n}\n\n// Store the updated register value and current in the context\ncontext.set('currentRegisterValue', updatedRegisterValue);\ncontext.set('previousMaxCurrent', maxCurrent);\n\nnode.warn(`Max current: ${maxCurrent}`);\nnode.warn(`Available margin: ${availableMargin}`);\nnode.warn(`Register value: ${currentRegisterValue}`);\n\n// Prepare the output message\nmsg.storctl_mod = \"2\";\nmsg.outwrte = updatedRegisterValue;\nmsg.inwrte = \"0\";\nmsg.newstate = \"charge power updated\";\nmsg.maxCurrent = maxCurrent;\n\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1720,"y":240,"wires":[["8b9fdfe7e1821416"]]},{"id":"11a3663361be0176","type":"junction","z":"082d1a6d7f9f4ee6","g":"336421b5a0497c39","x":1500,"y":240,"wires":[["7072c1b693b72fe8"]]},{"id":"ee426500a61afdd4","type":"group","z":"082d1a6d7f9f4ee6","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["http-request-node","storeSmartMeterData"],"x":234,"y":659,"w":512,"h":82},{"id":"http-request-node","type":"http request","z":"082d1a6d7f9f4ee6","g":"ee426500a61afdd4","name":"Get Smart Meter Data","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://192.168.x.x/solar_api/v1/GetMeterRealtimeData.cgi?Scope=Device&DeviceId=0","tls":"","persist":false,"proxy":"","authType":"","x":360,"y":700,"wires":[["storeSmartMeterData"]]},{"id":"storeSmartMeterData","type":"change","z":"082d1a6d7f9f4ee6","g":"ee426500a61afdd4","name":"Store Smart Meter Data","rules":[{"t":"set","p":"smartMeterData","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":700,"wires":[[]]}]

Where did you find the modbus addresses?
Thanks.

Grab them here https://www.smartmotion.life/wp-content/uploads/2023/09/Fronius_Inverter_Register_Map_with_IntegerSF_Inverter_Model.xlsx