Integration of a Fronius Symo Gen 24 plus Inverter via Modbus TCP

Hi again - have been offline for the past 2 evenings, but can see the thread has evolved tremendously. And some of my points might have been said already - but just trying to help out a tad more and hopefully clarify some more.

Just a quick note from my side - the values for the R(ead) only registers, can just be nothing

Can be stated:

Or you could just write out with variables, with null values, so keep a nice track of what you provide to the Modbus Flex node.

Regarding the WMaxLim_Ena = 0 or 1 has nothing to do with Modbus enable/disable, but to enforce a inverter limit at all time - regarding both solar and battery output, which can be required in some areas, that i needs to be limited - or if the energy prices is negative - to limit the expenses to sell energy. The inverter limit is higher ranked in the control structure than then storage control settings.
I use that register along with WMaxLimPct, to ensure battery isn’t providing energy to charging my car if my car needs to be emergency charged in peak hours. Haven’t tweaked it for cost optimization during hours from 17-21 yet - but soon to come, if potential is great enough :slight_smile:

Regarding the Sunspec integration - it’s the exact same readings as you do from the Modbus registers. It just does the calculations and serves it all nice and smooth in Home Assistant :slight_smile:
My Sunspec integration in Home Assistant is somehow broken, and haven’t bothered to open a ticket at Github. (Some of the readings are unavailable within Home Assistant (MPPT2 Energy is unavailabe and MPPT1 Voltage are non existant). Have done all calculations in NodeRED from register values to real values (took some good time and headaches, but a fun and time consuming proces to especially hit the 32 bit (double registers) values correct.)

Using the Modbus integration directly in Node-RED enables you to control how often you read out the inverter registers, including smart meter information (afaik the inverter receives values every 5 seconds from the Smart Meter - atleast don’t expect to do anything sub 10 seconds from reading out something to command another thing and see the changes)

Have just read your Blogpost heyyuitsal, would have loved reading that a year ago, when I started my journey - good work!

Happy to be able to help out on this matter and to see it’s appreciated - thank you enoch85

1 Like

I actually tried to set that now, but it resulted in forced 1 W charge… I must have done something wrong.

I could actually force it to charge at 4800W with that setting. :slight_smile: What I ended up with is this anyway for 4500W forced charge:

msg.StorCtl_Mod = "2"
// 4500W (65536-4500)
msg.OutWRte = "61036"

msg.newstate = "forcecharge4500w"

return msg

Issues now though:

  1. I want to set a HOLD setting, but this doesn’t work:
msg.StorCtl_Mod = "0"
msg.OutWRte = "0"
msg.InWRte = "0"

msg.newstate = "hold_state"

return msg
  1. What happens when the battery is full, then I want it to go back to normal state, but I don’t want to write every minute to the NVRAM. Right now I have this:

image

So when the battery is <= 50% then do this or that. My thought of the flow right now is:

a) Is the cars charging? (because if they do it means the price is low)
b) Start charging the home battery at forced 1500W(because I don’t want to discharge to handle the car battery charging)
c) Loop every hour to check if the car charging status has changed
d) When car charging stopped, we can assume that the price is high(er), then go back to HOLD/NORMAL.

That’s at least a start.

  1. My next plan is to check the coming electricity price, and based on that use the home battery for the peaks. If no extra ordinary peak is coming within 12 hours, then just put it to normal state. If a peak is coming, get the time for that peak and HOLD the home battery until that peak happens (and put it in normal state (allowing 100% discharge).

  2. Also, I haven’t got my head around when the sun is shining (not now, but in 6 months) - what will happen if the battery is in forced charge mode? Will it charge both from the sun, and the grid, or only from the grid?

  3. And last but not least. Let’s assume I start a forced charge when battery is at 80%. It will then be pretty quick to reach 100%. Will it just keep trying to charge, or what will happen? Preferably I would like for the state to change to normal again once the battery reached it max charge state. But the loop for that…?

Sorry, I’m a bit tired. I’m sitting with this when everyone a sleep, and the past weeks has been not so much of sleep for me to get this sorted in time before our new agreement with the energy provider.

I forgot it affected battery output as well. Thanks for that.
It just so happens that when I was wanting to discharge and export my battery on my battery flow - the feed in price is always positive - which sets the inverter to WMax_LimEna = 1, WMaxPct = 10000. Which allowed the battery to export at full power.
So I didn’t expect it to affect my battery. Thankyou for the correction. I’ll update my messaging!

WMaxLim_Ena = 0 - Export Limits as set in our Inverter Page - In our case 0W power exports.
This is the combination sum of BOTH battery and solar production. I.E your battery won’t discharge to grid.

So even setting battery to discharge at maximum - if WMaxLim_Ena = 0, it still will ensure there is still no power exported - reducing solar production as well.

WMaxLim_Ena = 1 - We enable our Modbus Settings to take priority over inverter settings. Thats why I still think of it as “enabling Modbus”, at least in my head it works that way…

I use that register along with WMaxLimPct, to ensure battery isn’t providing energy to charging my car if my car needs to be emergency charged in peak hours.

Wouldn’t you use the battery discharge/charge registers to limit battery power when your car is being charged?

Have just read your Blogpost heyyuitsal, would have loved reading that a year ago, when I started my journey - good work!

Thanks but it’s all credit to all the pioneers in this thread who’ve done most of the hard yards! Yourself included! I think everyone here has done an amazing job experimenting and figuring things out. Your flows look really awesome - almost as if you’ve done some systems engineering!

Yours works too!!

Mine is the same except enabling both registers - can force maximum rate charge with this.

msg.StorCtl_Mod = "3"
msg.OutWRte = "55536"
msg.InWRte = 10000

You force to charge in a range of minimum rate charge 2kW (pull from grid if required) - 4kW (if theres solar capacity) with

msg.StorCtl_Mod = "3"
msg.OutWRte = "63536"
msg.InWRte = 3906

My current updated flows.

[{"id":"9b9533b87828c99b","type":"group","z":"be58659390631944","name":"Battery Operation Modes","style":{"label":true},"nodes":["7ff5756845dcf22d","666215979b6ea1a6","331227502da4f67e","8802eb71790aac17","395b3ce33097daec","2b2f509c6e71e307","0ad541c97dedf319","5f400be0b926d17a","ea5af7fc8aa15b79","eafa1ba459601f9e","8804c16885a4555b","50a99136d006a8be","a07b8cf15cb62ab9","7fa9e8ceb8aad8a9","69c6b6daa43aee78","4b4c1ed678c12752","762b2c03d7a184cb"],"x":1474,"y":779,"w":992,"h":422},{"id":"7ff5756845dcf22d","type":"function","z":"be58659390631944","g":"9b9533b87828c99b","name":"Force Max Discharge","func":"\nmsg.StorCtl_Mod = \"3\"\nmsg.OutWRte = 10000\nmsg.InWRte = \"55536\"\n\nmsg.newstate = \"dischargemax\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1900,"y":1020,"wires":[["0ad541c97dedf319"]]},{"id":"666215979b6ea1a6","type":"switch","z":"be58659390631944","g":"9b9533b87828c99b","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"normal","vt":"str"},{"t":"eq","v":"chargemax","vt":"str"},{"t":"eq","v":"stop","vt":"str"},{"t":"eq","v":"dischargemax","vt":"str"},{"t":"eq","v":"1kwdischarge","vt":"str"}],"checkall":"true","repair":false,"outputs":5,"x":1610,"y":920,"wires":[["331227502da4f67e"],["8802eb71790aac17"],["395b3ce33097daec"],["7ff5756845dcf22d"],["2b2f509c6e71e307"]]},{"id":"331227502da4f67e","type":"function","z":"be58659390631944","g":"9b9533b87828c99b","name":"Normal Operation","func":"\nmsg.StorCtl_Mod = \"0\"\nmsg.OutWRte = 10000\nmsg.InWRte = 10000\n\nmsg.newstate = \"normal\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1890,"y":880,"wires":[["0ad541c97dedf319"]]},{"id":"8802eb71790aac17","type":"function","z":"be58659390631944","g":"9b9533b87828c99b","name":"Force Max Charge","func":"msg.StorCtl_Mod = \"3\"\nmsg.OutWRte = \"55536\"\nmsg.InWRte = 10000\n\nmsg.newstate = \"forcechargeonly\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1890,"y":920,"wires":[["0ad541c97dedf319"]]},{"id":"395b3ce33097daec","type":"function","z":"be58659390631944","g":"9b9533b87828c99b","name":"Stop Operation","func":"\nmsg.StorCtl_Mod = \"3\"\nmsg.OutWRte = 0\nmsg.InWRte = 0\n\nmsg.newstate = \"stop\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1880,"y":960,"wires":[["0ad541c97dedf319"]]},{"id":"2b2f509c6e71e307","type":"function","z":"be58659390631944","g":"9b9533b87828c99b","name":"1kW discharge","func":"\nmsg.StorCtl_Mod = \"3\"\nmsg.OutWRte = 1000\nmsg.InWRte = \"64536\"\n\nmsg.topic = \"1kwdischarge\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1880,"y":1060,"wires":[["0ad541c97dedf319"]]},{"id":"0ad541c97dedf319","type":"junction","z":"be58659390631944","g":"9b9533b87828c99b","x":2080,"y":900,"wires":[["5f400be0b926d17a"]]},{"id":"5f400be0b926d17a","type":"function","z":"be58659390631944","g":"9b9533b87828c99b","name":"Modbus Msg Template","func":"var values = [msg.StorCtl_Mod, (65535), (700), (10000), (65535), (65535), (5), (msg.OutWRte), (msg.InWRte)]\n\nmsg.payload = {\n    'value': values,\n    'fc': 16,\n    'unitid': 1,\n    'address': 40358,\n    'quantity': 9\n}\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2240,"y":900,"wires":[["ea5af7fc8aa15b79"]]},{"id":"ea5af7fc8aa15b79","type":"junction","z":"be58659390631944","g":"9b9533b87828c99b","x":2440,"y":900,"wires":[["eafa1ba459601f9e","7f9957a41ca84419"]]},{"id":"eafa1ba459601f9e","type":"debug","z":"be58659390631944","g":"9b9533b87828c99b","name":"debug 170","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":2330,"y":820,"wires":[]},{"id":"8804c16885a4555b","type":"junction","z":"be58659390631944","g":"9b9533b87828c99b","x":1500,"y":920,"wires":[["666215979b6ea1a6"]]},{"id":"50a99136d006a8be","type":"inject","z":"be58659390631944","g":"9b9533b87828c99b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1600,"y":1080,"wires":[["395b3ce33097daec"]]},{"id":"a07b8cf15cb62ab9","type":"inject","z":"be58659390631944","g":"9b9533b87828c99b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1600,"y":1000,"wires":[["331227502da4f67e"]]},{"id":"7fa9e8ceb8aad8a9","type":"inject","z":"be58659390631944","g":"9b9533b87828c99b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1600,"y":1120,"wires":[["7ff5756845dcf22d"]]},{"id":"69c6b6daa43aee78","type":"inject","z":"be58659390631944","g":"9b9533b87828c99b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1600,"y":1040,"wires":[["8802eb71790aac17"]]},{"id":"4b4c1ed678c12752","type":"inject","z":"be58659390631944","g":"9b9533b87828c99b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1600,"y":1160,"wires":[["2b2f509c6e71e307"]]},{"id":"762b2c03d7a184cb","type":"comment","z":"be58659390631944","g":"9b9533b87828c99b","name":"Ensure inverters are NOT in export limit mode","info":"","x":2190,"y":1040,"wires":[]}]
  1. I want to set a HOLD setting, but this doesn’t work:

StorCtl_Mod = 0 - disables register use of OutWRte and InWRte
You need to set StorCtl_Mod = 3 enables both register values

  1. What happens when the battery is full, then I want it to go back to normal state, but I don’t want to write every minute to the NVRAM. Right now I have this:

You’ll need state control - to determine what you’re doing with the batteries.
You can check the register values of the batteries and just see if the register values are the same as what you’re sending in.

C) Loop every hour to check if the car charging status has changed

Have a look at “State Changed Node” - it’ll only fire when something changes - better than waiting until the next scheduled hour.
image

d) When car charging stopped, we can assume that the price is high(er), then go back to HOLD/NORMAL.

Never assume hahah! Always check and confirm!

My next plan

I would love to do more optimization strategies but our variable pricing is really predictable so I haven’t had the will to really squeeze out optimisation…

  1. Also, I haven’t got my head around when the sun is shining (not now, but in 6 months) - what will happen if the battery is in forced charge mode? Will it charge both from the sun, and the grid, or only from the grid?

You have no sun during Winter? I’m so sorry… :cold_face:
Forced charged mode - will charge the battery at your required rate no matter sun shining or cloudy crap weather or at night. If theres not enough solar to cover your house loads + battery rate requirements, it’ll draw from the grid. Which I’m testing and confirming now during our cloudy weather.

And last but not least. Let’s assume I start a forced charge when battery is at 80%. It will then be pretty quick to reach 100%. Will it just keep trying to charge, or what will happen? Preferably I would like for the state to change to normal again once the battery reached it max charge state. But the loop for that…?

80% to 100% will be quick at 4.5kW. After 100% it will stay at whatever your last command was, you’ll need to set it back to normal once you’ve verified the battery is full.

Here is my forced battery charging - between 10am-2pm, I need the batteries full by 2pm.

  1. Check how long left until 2pm : timeleft
  2. Check how long it will take to charge from current battery state → full state : timerequired
  3. If timeleft is more than time required → auto mode
  4. If time left is less than time required → start charging max rate.
    My NodeRed skills aren’t very good so I just coded it… :sweat_smile:
[{"id":"646c23ede785858a","type":"group","z":"be58659390631944","name":"10AM-2PM","style":{"label":true},"nodes":["aacc5fb7a1da412e","18c4eb668adefd13"],"x":894,"y":553,"w":798,"h":194},{"id":"aacc5fb7a1da412e","type":"time-of-day","z":"be58659390631944","g":"646c23ede785858a","name":"","startTime":"10:00:00","endTime":"14:00:00","outputs":1,"x":990,"y":660,"wires":[["2a5ced916e8ec277"]]},{"id":"18c4eb668adefd13","type":"group","z":"be58659390631944","g":"646c23ede785858a","name":"Get Batteries Full Before 2PM","style":{"label":true},"nodes":["2a5ced916e8ec277","61a81939027f7503","7b998478c9684c74"],"x":1074,"y":579,"w":592,"h":142},{"id":"2a5ced916e8ec277","type":"api-current-state","z":"be58659390631944","g":"18c4eb668adefd13","name":"battery charge remaining","server":"61d027bd.371248","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.kw10_storage_chastate","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1210,"y":620,"wires":[["61a81939027f7503"]]},{"id":"61a81939027f7503","type":"function","z":"be58659390631944","g":"18c4eb668adefd13","name":"Charge Normal/Max - Time Left","func":"//Date and Time calculator\n//Time left til 2PM\nvar d = new Date();\nvar end_time = d.setHours(14, 0, 0, 0);\n\nvar d = new Date();\nvar start_time = d.getTime();\n\nvar difference = end_time - start_time;\n\nvar time_left = difference / 1000 / 3600;\n\n//Calculate Time to Refill at Max Charge Rate\nvar max_capacity = 11.06;\nvar max_rate = 4.5;\n\nvar batt_remain = msg.payload / 100 * max_capacity;\n\nvar energy_to_fill = max_capacity - batt_remain;\n\nvar time_to_fill = energy_to_fill / max_rate;\n\nmsg.timerequired = time_to_fill;\nmsg.timeleft = time_left;\n\n\nif (time_left < 0) {\n    msg.topic = \"normal\"\n} else {\n    if (time_left > time_to_fill) {\n        msg.topic = \"normal\";\n    } else {\n        msg.topic = \"chargemax\";\n    }\n}\n\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1250,"y":680,"wires":[["8804c16885a4555b","7b998478c9684c74"]]},{"id":"7b998478c9684c74","type":"debug","z":"be58659390631944","g":"18c4eb668adefd13","name":"Charging State Before 2PM","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1500,"y":620,"wires":[]},{"id":"61d027bd.371248","type":"server","name":"Home Assistant HOME","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false,"cacheJson":true,"heartbeat":true,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]

I’m still working on my flows as we’ve just put on a electric hot water system with a shelly, so it’s still a work in progress. Hope it helps you on your journey!

1 Like

To tired to answer your postings now, but this is what I got so far.

  1. Is car battery charging? (we expect it to be a low price using the function from the smart ev integration)
  2. If ON, then CHARGE 1500W
  3. If OFF, set to NORMAL
  4. To avoid writing to NVRAM, check if the value is already set.

Problem is that I get NaN values from the checks which results in a write every time… I must be thinking wrong about this…

[{"id":"effce8e2e8a9f43c","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"d4ddcb9085ea730f","type":"group","z":"effce8e2e8a9f43c","name":"Write changes!","style":{"label":true},"nodes":["180989e6b6be69e1","beceba7f58b3cb02","8257c587efbab683"],"x":1974,"y":339,"w":512,"h":122},{"id":"9d13313687e3f017","type":"group","z":"effce8e2e8a9f43c","name":"NORMAL","style":{"label":true},"nodes":["2468d8245a765d21"],"x":1294,"y":59,"w":232,"h":82},{"id":"ceea0bd0f56e5cbe","type":"group","z":"effce8e2e8a9f43c","name":"FORCED CHARGE","style":{"label":true},"nodes":["8bf3fd6bab97b524","0548b4b7a9faec3d","f79b4f746a482239","ab188204ffe303ef"],"x":1294,"y":239,"w":232,"h":82},{"id":"32f8524788c52a9d","type":"group","z":"effce8e2e8a9f43c","name":"FORCED CHARGE","style":{"label":true},"nodes":["f941ac38c439226e"],"x":1294,"y":419,"w":232,"h":82},{"id":"f84e3a88a392756e","type":"group","z":"effce8e2e8a9f43c","name":"HOLD (No charge or discharge) - NOT TESTED","style":{"label":true},"nodes":["4be156af80f1d0d2"],"x":1294,"y":599,"w":312,"h":82},{"id":"7ba45c1373d6db9c","type":"group","z":"effce8e2e8a9f43c","name":"Check current price/kWh","style":{"label":true},"nodes":["d5351cdc453ee22e","3b6d2b1103a7ee5c","dd104017de06fd0b"],"x":54,"y":819,"w":432,"h":162},{"id":"9164e2cf469fbb1a","type":"group","z":"effce8e2e8a9f43c","name":"Payload","style":{"label":true},"nodes":["4a3bc7d5caa41672"],"x":1654,"y":359,"w":292,"h":82},{"id":"a2d0a27e96764e53","type":"group","z":"effce8e2e8a9f43c","name":"Check if car is charging","style":{"label":true},"nodes":["0f7bddac0d6e47e9","34930c36e0d50c0c","afd38d704e49105d"],"x":54,"y":659,"w":432,"h":142},{"id":"8eeab12e1db7ba76","type":"group","z":"effce8e2e8a9f43c","name":"Check Current WMaxLimEna","style":{"label":true},"nodes":["191990f99428e9c3","b5a3efe24c74646b","6a41961a653255de"],"x":674,"y":239,"w":592,"h":142},{"id":"7b9956d7639218f4","type":"group","z":"effce8e2e8a9f43c","name":"Check Current WMaxLimEna","style":{"label":true},"nodes":["512f5707d5fea406","596b905436fc0fcf","a791f1a6ee243bde"],"x":674,"y":59,"w":592,"h":142},{"id":"90fbe2b3b17d1864","type":"group","z":"effce8e2e8a9f43c","name":"Check Current WMaxLimEna","style":{"label":true},"nodes":["a6a08c44832cad29","08c33679d09a331c","7ceb7b856da89642"],"x":674,"y":419,"w":592,"h":142},{"id":"0b5ccab872320c67","type":"group","z":"effce8e2e8a9f43c","name":"Check Current WMaxLimEna","style":{"label":true},"nodes":["ca52f40b1c58a4f3","5b1d8f3f25c95293","cb112be787b31a3b"],"x":674,"y":599,"w":592,"h":142},{"id":"0548b4b7a9faec3d","type":"junction","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","x":1320,"y":280,"wires":[[]]},{"id":"f79b4f746a482239","type":"junction","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","x":1320,"y":280,"wires":[[]]},{"id":"ab188204ffe303ef","type":"junction","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","x":1320,"y":280,"wires":[[]]},{"id":"180989e6b6be69e1","type":"modbus-response","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"","registerShowMax":20,"x":2270,"y":420,"wires":[]},{"id":"beceba7f58b3cb02","type":"modbus-flex-write","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"Fronius Storage","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"ecd41b68db8d4254","emptyMsgOnFail":true,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":2080,"y":400,"wires":[["180989e6b6be69e1","8257c587efbab683"],[]]},{"id":"8257c587efbab683","type":"debug","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"Inverter MODBUS Response","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":2310,"y":380,"wires":[]},{"id":"8bf3fd6bab97b524","type":"function","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","name":"4800W CHARGE","func":"msg.StorCtl_Mod = \"2\"\n// 4500W (65536-4500)\nmsg.OutWRte = \"61036\"\n\nmsg.newstate = \"forcecharge4500w\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1410,"y":280,"wires":[["4a3bc7d5caa41672"]],"info":"Example 1: Only permit energy storage charging\nThis behavior can be achieved by limiting the maximum discharge capacity to 0%\n=> results in window [-3300 W, 0 W]\n- OutWRte = 0% (set discharge limit of WchaMax to 0%)\n- StorCtl_Mod = 2 (activates discharge limit, bit pattern: 10)\n- InWRte is not relevant in this case"},{"id":"f941ac38c439226e","type":"function","z":"effce8e2e8a9f43c","g":"32f8524788c52a9d","name":"1500W CHARGE","func":"msg.StorCtl_Mod = \"2\"\n// 4500W (65536-1500)\nmsg.OutWRte = \"64036\"\n\nmsg.newstate = \"forcecharge1500w\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1410,"y":460,"wires":[["4a3bc7d5caa41672"]],"info":"Example 5: Charging in the range of 50% to 75% of the nominal power\nThis behavior can be achieved by limiting the maximum charge capacity to 75%\nand the maximum discharge capacity to -50%\n=> results in window [1650 W, 2475 W]\n- InWRte = 75% (set charge limit of WchaMax to 75%)\n- OutWRte = -50% (set discharge limit of WchaMax to -50%)\n- StorCtl_Mod = 3 (activate both limit values, bit pattern: 11)\n- Battery status in Fronius Solar.web will change to Forced Recharge"},{"id":"2468d8245a765d21","type":"function","z":"effce8e2e8a9f43c","g":"9d13313687e3f017","name":"Normal Operation","func":"\nmsg.StorCtl_Mod = \"0\"\nmsg.OutWRte = \"10000\"\nmsg.InWRte = \"10000\"\n\nmsg.newstate = \"normal\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1410,"y":100,"wires":[["4a3bc7d5caa41672"]],"info":"This puts the battery in normal operation.\nMeaningn that it will both charge and discharge to\nits set limits at 100%,\n"},{"id":"d5351cdc453ee22e","type":"api-current-state","z":"effce8e2e8a9f43c","g":"7ba45c1373d6db9c","name":"Spotpris","server":"afa7e6c.89d5e18","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.energi_data_service","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":160,"y":940,"wires":[["3b6d2b1103a7ee5c"]]},{"id":"3b6d2b1103a7ee5c","type":"switch","z":"effce8e2e8a9f43c","g":"7ba45c1373d6db9c","name":"> 50 öre or < 50 öre","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"0.5","vt":"num"},{"t":"lt","v":"0.5","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":360,"y":940,"wires":[[],[]]},{"id":"dd104017de06fd0b","type":"cronplus","z":"effce8e2e8a9f43c","g":"7ba45c1373d6db9c","name":"Every hour","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"0 0 * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":170,"y":860,"wires":[["d5351cdc453ee22e"]]},{"id":"4be156af80f1d0d2","type":"function","z":"effce8e2e8a9f43c","g":"f84e3a88a392756e","name":"HOLD (no charge or discharge)","func":"msg.StorCtl_Mod = \"0\"\nmsg.OutWRte = \"00000\"\nmsg.InWRte = \"00000\"\n\nmsg.newstate = \"hold_state\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1450,"y":640,"wires":[["4a3bc7d5caa41672"]],"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":"0f7bddac0d6e47e9","type":"poll-state","z":"effce8e2e8a9f43c","g":"a2d0a27e96764e53","name":"Volkswagen status","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","updateInterval":"1","updateIntervalType":"num","updateIntervalUnits":"minutes","outputInitially":false,"outputOnChanged":false,"entityId":"sensor.ev_smart_charging_volkswagen_charging","stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputs":1,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":170,"y":700,"wires":[["afd38d704e49105d"]]},{"id":"34930c36e0d50c0c","type":"poll-state","z":"effce8e2e8a9f43c","g":"a2d0a27e96764e53","name":"Tesla status","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","updateInterval":"60","updateIntervalType":"num","updateIntervalUnits":"seconds","outputInitially":false,"outputOnChanged":false,"entityId":"sensor.ev_smart_charging_charging","stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputs":1,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":150,"y":760,"wires":[["afd38d704e49105d"]]},{"id":"afd38d704e49105d","type":"switch","z":"effce8e2e8a9f43c","g":"a2d0a27e96764e53","name":"Charging or not?","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"off","vt":"num"},{"t":"lt","v":"running","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":370,"y":740,"wires":[[],[]]},{"id":"4a3bc7d5caa41672","type":"function","z":"effce8e2e8a9f43c","g":"9164e2cf469fbb1a","name":"Modbus Payload Template","func":"var values = [msg.StorCtl_Mod, (65535), (700), (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': 40348,\n    'quantity': 9\n}\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1800,"y":400,"wires":[["beceba7f58b3cb02"]]},{"id":"fbd62beaf41b9d25","type":"switch","z":"effce8e2e8a9f43c","name":"Charging or not?","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"off","vt":"num"},{"t":"lt","v":"running","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":430,"y":1020,"wires":[[],[]]},{"id":"299b741395ca0109","type":"api-current-state","z":"effce8e2e8a9f43c","name":"Battery less than 50%","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"16","halt_if_type":"num","halt_if_compare":"lte","entity_id":"sensor.gen24_storage_chastate","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":960,"y":820,"wires":[[],[]]},{"id":"7b9e92a1033c5dc5","type":"cronplus","z":"effce8e2e8a9f43c","name":"Every minute","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"0 * * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":870,"y":960,"wires":[["299b741395ca0109"]]},{"id":"563e1f08cb0b355b","type":"api-current-state","z":"effce8e2e8a9f43c","name":"","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"15","halt_if_type":"num","halt_if_compare":"lt","entity_id":"sensor.gen24_storage_inwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":710,"y":1020,"wires":[[],[]]},{"id":"191990f99428e9c3","type":"switch","z":"effce8e2e8a9f43c","g":"8eeab12e1db7ba76","name":"","property":"payload","propertyType":"msg","rules":[{"t":"neq","v":"-45","vt":"str"},{"t":"eq","v":"-45","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":1010,"y":280,"wires":[["8bf3fd6bab97b524"],["b5a3efe24c74646b"]]},{"id":"b5a3efe24c74646b","type":"debug","z":"effce8e2e8a9f43c","g":"8eeab12e1db7ba76","name":"Already set to 4500W","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1110,"y":340,"wires":[]},{"id":"512f5707d5fea406","type":"switch","z":"effce8e2e8a9f43c","g":"7b9956d7639218f4","name":"","property":"payload","propertyType":"msg","rules":[{"t":"neq","v":"100","vt":"str"},{"t":"eq","v":"100","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":1010,"y":100,"wires":[["2468d8245a765d21"],["596b905436fc0fcf"]]},{"id":"596b905436fc0fcf","type":"debug","z":"effce8e2e8a9f43c","g":"7b9956d7639218f4","name":"Already set to Normal","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1110,"y":160,"wires":[]},{"id":"a791f1a6ee243bde","type":"api-current-state","z":"effce8e2e8a9f43c","g":"7b9956d7639218f4","name":"OutWRte = 100?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"100","halt_if_type":"num","halt_if_compare":"gt","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":790,"y":140,"wires":[[],["512f5707d5fea406"]]},{"id":"a6a08c44832cad29","type":"switch","z":"effce8e2e8a9f43c","g":"90fbe2b3b17d1864","name":"","property":"payload","propertyType":"msg","rules":[{"t":"neq","v":"-15","vt":"num"},{"t":"eq","v":"-15","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":1010,"y":460,"wires":[["f941ac38c439226e"],["08c33679d09a331c"]]},{"id":"08c33679d09a331c","type":"debug","z":"effce8e2e8a9f43c","g":"90fbe2b3b17d1864","name":"Already set to 1500W","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1110,"y":520,"wires":[]},{"id":"7ceb7b856da89642","type":"api-current-state","z":"effce8e2e8a9f43c","g":"90fbe2b3b17d1864","name":"OutWRte less than -15?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"-15","halt_if_type":"num","halt_if_compare":"lt","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":810,"y":500,"wires":[[],["a6a08c44832cad29"]]},{"id":"ca52f40b1c58a4f3","type":"switch","z":"effce8e2e8a9f43c","g":"0b5ccab872320c67","name":"","property":"payload","propertyType":"msg","rules":[{"t":"neq","v":"0","vt":"str"},{"t":"eq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":1010,"y":640,"wires":[["4be156af80f1d0d2"],["5b1d8f3f25c95293"]]},{"id":"5b1d8f3f25c95293","type":"debug","z":"effce8e2e8a9f43c","g":"0b5ccab872320c67","name":"Already set to HOLD","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1110,"y":700,"wires":[]},{"id":"cb112be787b31a3b","type":"api-current-state","z":"effce8e2e8a9f43c","g":"0b5ccab872320c67","name":"OutWRte less than 0?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"0","halt_if_type":"num","halt_if_compare":"gt","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":800,"y":680,"wires":[[],["ca52f40b1c58a4f3"]]},{"id":"6a41961a653255de","type":"api-current-state","z":"effce8e2e8a9f43c","g":"8eeab12e1db7ba76","name":"OutWRte less than -45?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"-45","halt_if_type":"num","halt_if_compare":"gt","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":810,"y":320,"wires":[[],["191990f99428e9c3"]]},{"id":"da0cf52b3512077c","type":"api-current-state","z":"effce8e2e8a9f43c","name":"Volkswagen status","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.ev_smart_charging_volkswagen_charging","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":390,"y":320,"wires":[["7ceb7b856da89642"],["a791f1a6ee243bde"]]},{"id":"acac173176451675","type":"cronplus","z":"effce8e2e8a9f43c","name":"Every second","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"* * * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":620,"y":920,"wires":[[]]},{"id":"b7e215e05bd12da5","type":"cronplus","z":"effce8e2e8a9f43c","name":"Every second","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"* * * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":620,"y":860,"wires":[[]]},{"id":"a9f90b19dad3d01b","type":"cronplus","z":"effce8e2e8a9f43c","name":"Every minute","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"0 * * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":170,"y":340,"wires":[["da0cf52b3512077c"]]},{"id":"ecd41b68db8d4254","type":"modbus-client","name":"Fronius Gen24","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":true,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"10.10.10.4","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":1,"commandDelay":1,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true},{"id":"afa7e6c.89d5e18","type":"server","name":"Home Assistant","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":true,"heartbeatInterval":"30","statusSeparator":"","enableGlobalContextStore":false}]

OK, so I took the easy route for now, just to have something to build upon. This is considered a “base” at least:

[{"id":"4d8bb11523950e4c","type":"server-state-changed","z":"effce8e2e8a9f43c","name":"State Check Volkswagen charging?","server":"afa7e6c.89d5e18","version":5,"outputs":2,"exposeAsEntityConfig":"","entityId":"sensor.ev_smart_charging_volkswagen_charging","entityIdType":"exact","outputInitially":true,"stateType":"habool","ifState":"true","ifStateType":"bool","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":160,"y":240,"wires":[["83ab376c9f575823","c81b595f086bd847"],["c045f1aba2908960","2468d8245a765d21"]]},{"id":"c045f1aba2908960","type":"debug","z":"effce8e2e8a9f43c","name":"Car is NOT charging","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":420,"y":300,"wires":[]},{"id":"83ab376c9f575823","type":"debug","z":"effce8e2e8a9f43c","name":"Car is charging","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":410,"y":160,"wires":[]},{"id":"c81b595f086bd847","type":"api-current-state","z":"effce8e2e8a9f43c","name":"GRID LOAD less than 5 kW?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"5000","halt_if_type":"num","halt_if_compare":"lte","entity_id":"sensor.gen24_ac_meter_watts","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":720,"y":240,"wires":[["8bf3fd6bab97b524","6e51d92aabfb5884"],["f941ac38c439226e","2cb4fe8a59835f21"]]},{"id":"2cb4fe8a59835f21","type":"debug","z":"effce8e2e8a9f43c","name":"LESS THAN","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":920,"y":320,"wires":[]},{"id":"6e51d92aabfb5884","type":"debug","z":"effce8e2e8a9f43c","name":"MORE THAN","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":920,"y":100,"wires":[]},{"id":"d4ddcb9085ea730f","type":"group","z":"effce8e2e8a9f43c","name":"Write changes!","style":{"label":true},"nodes":["180989e6b6be69e1","beceba7f58b3cb02","8257c587efbab683"],"x":1994,"y":159,"w":512,"h":122},{"id":"180989e6b6be69e1","type":"modbus-response","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"","registerShowMax":20,"x":2290,"y":240,"wires":[]},{"id":"beceba7f58b3cb02","type":"modbus-flex-write","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"Fronius Storage","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"ecd41b68db8d4254","emptyMsgOnFail":true,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":2100,"y":220,"wires":[["180989e6b6be69e1","8257c587efbab683"],[]]},{"id":"8257c587efbab683","type":"debug","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"Inverter MODBUS Response","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":2330,"y":200,"wires":[]},{"id":"ecd41b68db8d4254","type":"modbus-client","name":"Fronius Gen24","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":true,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"10.10.10.4","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":1,"commandDelay":1,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true},{"id":"9164e2cf469fbb1a","type":"group","z":"effce8e2e8a9f43c","name":"Payload","style":{"label":true},"nodes":["4a3bc7d5caa41672"],"x":1674,"y":179,"w":292,"h":82},{"id":"4a3bc7d5caa41672","type":"function","z":"effce8e2e8a9f43c","g":"9164e2cf469fbb1a","name":"Modbus Payload Template","func":"var values = [msg.StorCtl_Mod, (65535), (700), (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': 40348,\n    'quantity': 9\n}\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1820,"y":220,"wires":[["beceba7f58b3cb02"]]},{"id":"e76b6d3638319a77","type":"group","z":"effce8e2e8a9f43c","name":"BATTERY INSTRUCTIONS","style":{"label":true},"nodes":["9d13313687e3f017","ceea0bd0f56e5cbe","32f8524788c52a9d","f84e3a88a392756e"],"x":1308,"y":13,"w":284,"h":434},{"id":"9d13313687e3f017","type":"group","z":"effce8e2e8a9f43c","g":"e76b6d3638319a77","name":"NORMAL","style":{"label":true},"nodes":["2468d8245a765d21"],"x":1334,"y":39,"w":172,"h":82},{"id":"2468d8245a765d21","type":"function","z":"effce8e2e8a9f43c","g":"9d13313687e3f017","name":"NORMAL","func":"\nmsg.StorCtl_Mod = \"0\"\nmsg.OutWRte = \"10000\"\nmsg.InWRte = \"10000\"\n\nmsg.newstate = \"normal\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1420,"y":80,"wires":[["4a3bc7d5caa41672"]],"info":"This puts the battery in normal operation.\nMeaningn that it will both charge and discharge to\nits set limits at 100%,\n"},{"id":"ceea0bd0f56e5cbe","type":"group","z":"effce8e2e8a9f43c","g":"e76b6d3638319a77","name":"FORCED CHARGE","style":{"label":true},"nodes":["8bf3fd6bab97b524","0548b4b7a9faec3d","f79b4f746a482239","ab188204ffe303ef"],"x":1334,"y":139,"w":232,"h":82},{"id":"8bf3fd6bab97b524","type":"function","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","name":"4500W CHARGE","func":"msg.StorCtl_Mod = \"2\"\n// 4500W (65536-4500)\nmsg.OutWRte = \"61036\"\n\nmsg.newstate = \"forcecharge4500w\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1450,"y":180,"wires":[["4a3bc7d5caa41672"]],"info":"Example 1: Only permit energy storage charging\nThis behavior can be achieved by limiting the maximum discharge capacity to 0%\n=> results in window [-3300 W, 0 W]\n- OutWRte = 0% (set discharge limit of WchaMax to 0%)\n- StorCtl_Mod = 2 (activates discharge limit, bit pattern: 10)\n- InWRte is not relevant in this case"},{"id":"0548b4b7a9faec3d","type":"junction","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","x":1360,"y":180,"wires":[[]]},{"id":"f79b4f746a482239","type":"junction","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","x":1360,"y":180,"wires":[[]]},{"id":"ab188204ffe303ef","type":"junction","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","x":1360,"y":180,"wires":[[]]},{"id":"32f8524788c52a9d","type":"group","z":"effce8e2e8a9f43c","g":"e76b6d3638319a77","name":"FORCED CHARGE","style":{"label":true},"nodes":["f941ac38c439226e"],"x":1334,"y":239,"w":232,"h":82},{"id":"f941ac38c439226e","type":"function","z":"effce8e2e8a9f43c","g":"32f8524788c52a9d","name":"1500W CHARGE","func":"msg.StorCtl_Mod = \"2\"\n// 4500W (65536-1500)\nmsg.OutWRte = \"64036\"\n\nmsg.newstate = \"forcecharge1500w\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1450,"y":280,"wires":[["4a3bc7d5caa41672"]],"info":"Example 5: Charging in the range of 50% to 75% of the nominal power\nThis behavior can be achieved by limiting the maximum charge capacity to 75%\nand the maximum discharge capacity to -50%\n=> results in window [1650 W, 2475 W]\n- InWRte = 75% (set charge limit of WchaMax to 75%)\n- OutWRte = -50% (set discharge limit of WchaMax to -50%)\n- StorCtl_Mod = 3 (activate both limit values, bit pattern: 11)\n- Battery status in Fronius Solar.web will change to Forced Recharge"},{"id":"f84e3a88a392756e","type":"group","z":"effce8e2e8a9f43c","g":"e76b6d3638319a77","name":"HOLD (No charge or discharge)","style":{"label":true},"nodes":["4be156af80f1d0d2"],"x":1334,"y":339,"w":205,"h":82},{"id":"4be156af80f1d0d2","type":"function","z":"effce8e2e8a9f43c","g":"f84e3a88a392756e","name":"HOLD","func":"msg.StorCtl_Mod = \"3\"\nmsg.OutWRte = \"0\"\nmsg.InWRte = \"0\"\n\nmsg.newstate = \"hold_state\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1410,"y":380,"wires":[["4a3bc7d5caa41672"]],"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":"afa7e6c.89d5e18","type":"server","name":"Home Assistant","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":true,"heartbeatInterval":"30","statusSeparator":"","enableGlobalContextStore":false}]

Everything started to come togeheter when I added the “State Changed Node”. That changed everything and I could remove all my condition checks as it would only trigger when the state was changed which is 2 times per 24 hours. I’m still not pleased with that it writes to the Modbus device on every “Deploy” though. Is there any way to come around that? Also, would it be possible to change the NVRAM if it goes south?

I also got what I need in terms of time for the start and stop event. Here and here. So my idea is to start charging the home battery 1 hour before the car chargin starts, since it tends to start in the end of the allowed range. It’s not optimal since it could trigger a charge on “the wrong” hour, but I’ve never seen a peak in the middle of the night before.

As mentioned, I now have a base to stand on that at least works - and my goal is to tweak it further so that it checks for more conditions than just house load and if the car is charging. Another factor could be if the price differs more than 1 SEK from today’s and tomorrows price…

Anyway after about 3 hours sleep today I decided to just let it sit for while now to see how it behaves. I’ve added a check for the house total consumption to not blow any fuses, ideas of improvement here are welcome!

Somewhat prioritized tasks left:

  1. Be smart about ChaState and put it back to NORMAL or HOLD when a certain % is reached, help is welcome! This should also consider the next day price, or the average price during a certain time frame to be able to decide if it’s worth DISCHARGE or not… I think this might help.
  2. Do I actually use the correct sensor to check the house load? sensor.gen24_ac_meter_watts. I noticed a race-condition yesterday where it discharged from the battery and thus thought the power from grid only was 13W, and then put it into max force charge, which in turn stopped one of the cars from charging… I want a sensor for total consumed from battery, grid, and everything.
  3. Implement the start and stop times as template sensors so that I can choose when to start and stop in Node RED.
  4. Try to avoid writing to the NVRAM by adding even more checks before a write happens
  5. Etc…

Well, almost. Sun comes up around 8:00-9:00 and sets at around 15:00 - and 90% of the days are cloudy. In the north of Sweden, the sun never rises during winter. :slight_smile:

Thanks again! You made it so much easier for me down this path.

Current state:

#################################################################

Btw @heyyitsal, would you be able to send this Excel to me? It would be easier to keep track of all the numbers since we have different batteries:

OK I admit, I couldn’t keep my hands off… It ended up in this:

(Updated at 02:07 AM)

[{"id":"effce8e2e8a9f43c","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"62fbd666c7c7b20d","type":"group","z":"effce8e2e8a9f43c","name":"BATTERY INSTRUCTIONS","style":{"label":true},"nodes":["7b45bdf5d2c774a4","d93cd01b0135c571","7a2e734eead34d16","d324d8010fa062da"],"x":1668,"y":193,"w":304,"h":594},{"id":"f155037011aa0d79","type":"group","z":"effce8e2e8a9f43c","name":"Write changes!","style":{"label":true},"nodes":["0cc39af6d8b8dc0f","9f84293f8db8abd4","e0414ba507e24b27"],"x":2574,"y":419,"w":512,"h":122},{"id":"fbe0abfb3ee0e088","type":"group","z":"effce8e2e8a9f43c","name":"Payload","style":{"label":true},"nodes":["fad803646bcd93ee"],"x":2194,"y":439,"w":292,"h":82},{"id":"7a697ccd23e6b3cb","type":"group","z":"effce8e2e8a9f43c","name":"START CHARGE 1H BEFORE CAR START BASED ON SPOT PRICE - IF BATTERY LESS THAN 50%","style":{"label":true,"stroke":"#92d04f","color":"#000000"},"nodes":["1bdbeec9beec4666","f69e7949f24db159","2a001bec87d1bcf1","7ba45c1373d6db9c","299b741395ca0109"],"x":14,"y":59,"w":1012,"h":242},{"id":"e209b9134d0bb2d2","type":"group","z":"effce8e2e8a9f43c","name":"DISCHARGE ON THE MOST EXPENSIVE HOURS","style":{"label":true,"color":"#000000","stroke":"#ff0000"},"nodes":["9e6981eae0813a2e","adbc3aa9cf52d50f","b613f0683c528e72","02b26ef1b0a8b08d","7f4903812faedc8c","d02c29a8f72609bd"],"x":14,"y":619,"w":1012,"h":342},{"id":"0bd67f9e3d7f071c","type":"group","z":"effce8e2e8a9f43c","name":"SCHELUDED CAR CHARHING","style":{"label":true,"color":"#000000","stroke":"#ffC000"},"nodes":["1c8a755bac3130a0","f049899799f7f431","19a007dca869d5ac"],"x":194,"y":339,"w":852,"h":142},{"id":"72b918efda5f705f","type":"group","z":"effce8e2e8a9f43c","name":"DO SOMETHING WHEN BATTERY IS FULL","style":{"stroke":"#000000","label":true,"color":"#000000"},"nodes":["213549e7b854d62a","b6852c6123b496b0"],"x":1034,"y":59,"w":532,"h":82},{"id":"fe7e3d938efd615b","type":"group","z":"effce8e2e8a9f43c","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["cef42ad4b8be9134","67565807754a25b8","0f486b541cabd4ee","97397f6c4fe48c4a","9f6169b8654f08cb"],"x":1274,"y":219,"w":292,"h":562},{"id":"7ba45c1373d6db9c","type":"group","z":"effce8e2e8a9f43c","g":"7a697ccd23e6b3cb","name":"Check current price/kWh","style":{"label":true},"nodes":["d5351cdc453ee22e","3b6d2b1103a7ee5c"],"x":314,"y":139,"w":412,"h":82},{"id":"7b45bdf5d2c774a4","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"NORMAL","style":{"label":true},"nodes":["7a60a2b45d28626d"],"x":1694,"y":219,"w":172,"h":82},{"id":"d93cd01b0135c571","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"FORCED CHARGE","style":{"label":true},"nodes":["66d147c4d9a586f8","4695b75a3e4dcf76","d040c0fa03cffab1","ad02180332549efa","62364dcb3387db2b"],"x":1694,"y":379,"w":232,"h":142},{"id":"7a2e734eead34d16","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"HOLD (No charge or discharge)","style":{"label":true},"nodes":["5d370aec7b2aa1ce"],"x":1694,"y":579,"w":206,"h":82},{"id":"02b26ef1b0a8b08d","type":"group","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"Check current price/kWh","style":{"label":true},"nodes":["0cc692ab6f439fdf","f032a97315254445"],"x":514,"y":739,"w":412,"h":82},{"id":"d324d8010fa062da","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"FORCED DISCHARGE","style":{"label":true},"nodes":["a78bef469323ace0"],"x":1694,"y":679,"w":252,"h":82},{"id":"4695b75a3e4dcf76","type":"junction","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","x":1720,"y":420,"wires":[[]]},{"id":"d040c0fa03cffab1","type":"junction","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","x":1720,"y":420,"wires":[[]]},{"id":"ad02180332549efa","type":"junction","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","x":1720,"y":420,"wires":[[]]},{"id":"d5351cdc453ee22e","type":"api-current-state","z":"effce8e2e8a9f43c","g":"7ba45c1373d6db9c","name":"Spotpris","server":"afa7e6c.89d5e18","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.energi_data_service","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":400,"y":180,"wires":[["3b6d2b1103a7ee5c"]]},{"id":"3b6d2b1103a7ee5c","type":"switch","z":"effce8e2e8a9f43c","g":"7ba45c1373d6db9c","name":"MORE / LESS 50 öre","property":"payload","propertyType":"msg","rules":[{"t":"lte","v":"50","vt":"num"},{"t":"gte","v":"50","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":600,"y":180,"wires":[["299b741395ca0109","2a001bec87d1bcf1"],["f69e7949f24db159"]]},{"id":"299b741395ca0109","type":"api-current-state","z":"effce8e2e8a9f43c","g":"7a697ccd23e6b3cb","name":"Battery less than 50%","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"50","halt_if_type":"num","halt_if_compare":"lte","entity_id":"sensor.gen24_storage_chastate","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":900,"y":180,"wires":[["67565807754a25b8"],[]]},{"id":"1bdbeec9beec4666","type":"ha-time","z":"effce8e2e8a9f43c","g":"7a697ccd23e6b3cb","name":"TESLA START OFFSET -1H","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","entityId":"sensor.tesla_start_charging_time","property":"","offset":"-119","offsetType":"num","offsetUnits":"minutes","randomOffset":false,"repeatDaily":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"sunday":true,"monday":true,"tuesday":true,"wednesday":true,"thursday":true,"friday":true,"saturday":true,"x":160,"y":180,"wires":[["d5351cdc453ee22e"]]},{"id":"1c8a755bac3130a0","type":"ha-time","z":"effce8e2e8a9f43c","g":"0bd67f9e3d7f071c","name":"TESLA STOP (NOW)","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","entityId":"sensor.tesla_stop_charging_time","property":"","offset":"0","offsetType":"num","offsetUnits":"hours","randomOffset":false,"repeatDaily":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"sunday":true,"monday":true,"tuesday":true,"wednesday":true,"thursday":true,"friday":true,"saturday":true,"x":320,"y":440,"wires":[["cef42ad4b8be9134"]]},{"id":"7a60a2b45d28626d","type":"function","z":"effce8e2e8a9f43c","g":"7b45bdf5d2c774a4","name":"NORMAL","func":"\nmsg.StorCtl_Mod = \"0\"\nmsg.OutWRte = \"10000\"\nmsg.InWRte = \"10000\"\n\nmsg.newstate = \"normal\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1780,"y":260,"wires":[["fad803646bcd93ee"]],"info":"This puts the battery in normal operation.\nMeaningn that it will both charge and discharge to\nits set limits at 100%,\n"},{"id":"66d147c4d9a586f8","type":"function","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","name":"4500W CHARGE","func":"msg.StorCtl_Mod = \"2\"\n// 4500W (65536-4500)\nmsg.OutWRte = \"61036\"\n\nmsg.newstate = \"forcecharge4500w\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1810,"y":420,"wires":[["fad803646bcd93ee"]],"info":"Example 1: Only permit energy storage charging\nThis behavior can be achieved by limiting the maximum discharge capacity to 0%\n=> results in window [-3300 W, 0 W]\n- OutWRte = 0% (set discharge limit of WchaMax to 0%)\n- StorCtl_Mod = 2 (activates discharge limit, bit pattern: 10)\n- InWRte is not relevant in this case"},{"id":"5d370aec7b2aa1ce","type":"function","z":"effce8e2e8a9f43c","g":"7a2e734eead34d16","name":"HOLD","func":"msg.StorCtl_Mod = \"3\"\nmsg.OutWRte = \"0\"\nmsg.InWRte = \"0\"\n\nmsg.newstate = \"hold_state\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1770,"y":620,"wires":[["fad803646bcd93ee"]],"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":"0cc39af6d8b8dc0f","type":"modbus-response","z":"effce8e2e8a9f43c","g":"f155037011aa0d79","name":"","registerShowMax":20,"x":2870,"y":500,"wires":[]},{"id":"9f84293f8db8abd4","type":"modbus-flex-write","z":"effce8e2e8a9f43c","g":"f155037011aa0d79","name":"Fronius Storage","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"ecd41b68db8d4254","emptyMsgOnFail":true,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":2680,"y":480,"wires":[["0cc39af6d8b8dc0f","e0414ba507e24b27"],[]]},{"id":"e0414ba507e24b27","type":"debug","z":"effce8e2e8a9f43c","g":"f155037011aa0d79","name":"Inverter MODBUS Response","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":2910,"y":460,"wires":[]},{"id":"fad803646bcd93ee","type":"function","z":"effce8e2e8a9f43c","g":"fbe0abfb3ee0e088","name":"Modbus Payload Template","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': 40348,\n    'quantity': 9\n}\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2340,"y":480,"wires":[["9f84293f8db8abd4"]]},{"id":"f69e7949f24db159","type":"debug","z":"effce8e2e8a9f43c","g":"7a697ccd23e6b3cb","name":"MORE THAN","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":800,"y":260,"wires":[]},{"id":"2a001bec87d1bcf1","type":"debug","z":"effce8e2e8a9f43c","g":"7a697ccd23e6b3cb","name":"LESS THAN","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":800,"y":100,"wires":[]},{"id":"f049899799f7f431","type":"ha-time","z":"effce8e2e8a9f43c","g":"0bd67f9e3d7f071c","name":"TESLA START (NOW)","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","entityId":"sensor.tesla_start_charging_time","property":"","offset":"","offsetType":"num","offsetUnits":"hours","randomOffset":false,"repeatDaily":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"sunday":true,"monday":true,"tuesday":true,"wednesday":true,"thursday":true,"friday":true,"saturday":true,"x":320,"y":380,"wires":[["19a007dca869d5ac"]]},{"id":"9e6981eae0813a2e","type":"cronplus","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"Every hour","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"30 0 * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":130,"y":780,"wires":[["7f4903812faedc8c","d02c29a8f72609bd"]]},{"id":"adbc3aa9cf52d50f","type":"debug","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"MORE THAN","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":900,"y":920,"wires":[]},{"id":"b613f0683c528e72","type":"debug","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"LESS THAN","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":900,"y":660,"wires":[]},{"id":"0cc692ab6f439fdf","type":"api-current-state","z":"effce8e2e8a9f43c","g":"02b26ef1b0a8b08d","name":"Spotpris","server":"afa7e6c.89d5e18","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.energi_data_service","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":600,"y":780,"wires":[["f032a97315254445"]]},{"id":"f032a97315254445","type":"switch","z":"effce8e2e8a9f43c","g":"02b26ef1b0a8b08d","name":"MORE / LESS 150 öre","property":"payload","propertyType":"msg","rules":[{"t":"lte","v":"150","vt":"num"},{"t":"gte","v":"150","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":800,"y":780,"wires":[["b613f0683c528e72","cef42ad4b8be9134"],["adbc3aa9cf52d50f","97397f6c4fe48c4a"]]},{"id":"7f4903812faedc8c","type":"time-of-day","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"","startTime":"17:00:00","endTime":"19:00:00","outputs":1,"x":390,"y":820,"wires":[["0cc692ab6f439fdf"]]},{"id":"d02c29a8f72609bd","type":"time-of-day","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"","startTime":"06:00:00","endTime":"08:00:00","outputs":1,"x":390,"y":740,"wires":[["0cc692ab6f439fdf"]]},{"id":"a78bef469323ace0","type":"function","z":"effce8e2e8a9f43c","g":"d324d8010fa062da","name":"1000W DISCHARGE","func":"\nmsg.StorCtl_Mod = \"3\"\nmsg.OutWRte = 1000\n// 65536 - 1000\nmsg.InWRte = \"64536\"\n\nmsg.newstate = \"1kWdischarge\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1820,"y":720,"wires":[["fad803646bcd93ee"]]},{"id":"19a007dca869d5ac","type":"api-current-state","z":"effce8e2e8a9f43c","g":"0bd67f9e3d7f071c","name":"GRID LOAD less than 5500W?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"5500","halt_if_type":"num","halt_if_compare":"lte","entity_id":"sensor.gen24_ac_meter_watts","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":890,"y":380,"wires":[["67565807754a25b8"],["0f486b541cabd4ee"]]},{"id":"62364dcb3387db2b","type":"function","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","name":"1500W CHARGE","func":"msg.StorCtl_Mod = \"2\"\n// 4500W (65536-1500)\nmsg.OutWRte = \"64036\"\n\nmsg.newstate = \"forcecharge1500w\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1810,"y":480,"wires":[["fad803646bcd93ee"]],"info":"Example 5: Charging in the range of 50% to 75% of the nominal power\nThis behavior can be achieved by limiting the maximum charge capacity to 75%\nand the maximum discharge capacity to -50%\n=> results in window [1650 W, 2475 W]\n- InWRte = 75% (set charge limit of WchaMax to 75%)\n- OutWRte = -50% (set discharge limit of WchaMax to -50%)\n- StorCtl_Mod = 3 (activate both limit values, bit pattern: 11)\n- Battery status in Fronius Solar.web will change to Forced Recharge"},{"id":"213549e7b854d62a","type":"server-state-changed","z":"effce8e2e8a9f43c","g":"72b918efda5f705f","name":"State Check Battery MORE THAN 90%","server":"afa7e6c.89d5e18","version":5,"outputs":2,"exposeAsEntityConfig":"","entityId":"sensor.gen24_storage_chastate","entityIdType":"exact","outputInitially":true,"stateType":"num","ifState":"90","ifStateType":"num","ifStateOperator":"gt","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":1210,"y":100,"wires":[["b6852c6123b496b0"],[]]},{"id":"b6852c6123b496b0","type":"time-of-day","z":"effce8e2e8a9f43c","g":"72b918efda5f705f","name":"","startTime":"08:00:00","endTime":"17:00:00","outputs":1,"x":1470,"y":100,"wires":[["9f6169b8654f08cb"]]},{"id":"1aa259781a6e2913","type":"debug","z":"effce8e2e8a9f43c","name":"IS SOMETHING WRITTEN?","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":2630,"y":660,"wires":[]},{"id":"6f57fd58660bf7dc","type":"inject","z":"effce8e2e8a9f43c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":2400,"y":660,"wires":[["1aa259781a6e2913"]]},{"id":"cef42ad4b8be9134","type":"api-current-state","z":"effce8e2e8a9f43c","g":"fe7e3d938efd615b","name":"ChaSt already HOLDING?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"HOLDING","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.gen24_storage_chast","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1420,"y":660,"wires":[[],["5d370aec7b2aa1ce"]]},{"id":"67565807754a25b8","type":"api-current-state","z":"effce8e2e8a9f43c","g":"fe7e3d938efd615b","name":"OutWRt already -45?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"-45","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1400,"y":400,"wires":[[],["66d147c4d9a586f8"]]},{"id":"0f486b541cabd4ee","type":"api-current-state","z":"effce8e2e8a9f43c","g":"fe7e3d938efd615b","name":"OutWRt already -15?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"-15","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1400,"y":460,"wires":[[],["62364dcb3387db2b"]]},{"id":"97397f6c4fe48c4a","type":"api-current-state","z":"effce8e2e8a9f43c","g":"fe7e3d938efd615b","name":"OutWRt already 10?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"10","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1400,"y":740,"wires":[[],["a78bef469323ace0"]]},{"id":"9f6169b8654f08cb","type":"api-current-state","z":"effce8e2e8a9f43c","g":"fe7e3d938efd615b","name":"OutWRt already 100?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"100","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1400,"y":260,"wires":[[],["7a60a2b45d28626d"]]},{"id":"cb05b2a950f8de3d","type":"cronplus","z":"effce8e2e8a9f43c","name":"Every second","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"* * * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":1440,"y":1000,"wires":[[]]},{"id":"950594b9ea04a2ed","type":"cronplus","z":"effce8e2e8a9f43c","name":"Every minute","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"0 * * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":1170,"y":1000,"wires":[[]]},{"id":"afa7e6c.89d5e18","type":"server","name":"Home Assistant","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":true,"heartbeatInterval":"30","statusSeparator":"","enableGlobalContextStore":false},{"id":"ecd41b68db8d4254","type":"modbus-client","name":"Fronius Gen24","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":true,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"10.10.10.4","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":1,"commandDelay":1,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true}]

  • 1H before car charging starts AND price/kWH are LESS than 50 öre (cent) AND battery level below 50% —> FORCE CHARGE 4500W

  • WHEN car START charging THEN check if house grid load is less than 5000W:
    a) IF MORE THAN 5kW —> FORCE CHARGE 1500W (to disallow discharge)
    b) IF LESS THAN 5kW —> FORCE CHARGE 4500W (to disallow discharge)

  • WHEN car STOP charging —> HOLD

  • DISCHARGE between 06:00 - 08:00 OR 17:00 - 19:00 AND price/kWH are:
    a) MORE than 150 öre —> DISCHARGE 1000W
    b) LESS than 150 öre —> HOLD

  • WHEN battery is more than 90% AND time is 08:00 -17:00 —> NORMAL

So basically:

  1. Cars are allowed to charge between 19:00 and 05:00 (but only on the cheapest rate which usually occurs at between 00:00 and 04:00.
  2. 1H before the cars are scheluded to start charging, then add full power to the home battery on the condition that price is below a certain point
  3. When car charging starts, then check the house power, and decide which charge mode based on that
  4. When car charging stops, then always put the battery in HOLD, might add a factor for sunrise there as well now wen thinking about it…
  5. Between the most expensive times during the day, discharge if the price /kWh is 100 öre (1 SEK) more than what we force charged with earlier (1H before that car started charging).

In amount of commands per 24 hours that could be something like:

  1. Force charge starts 1 hour before the car starts charging, new command
  2. Car starts charging, new command
  3. Car stop charging, new command
  4. Time is between the given times, 2 new commands in the morning, and 2 new commands in the evening (since the trigger for each hour (want to make this one comand, any ideas?)
  5. When battery is above 90% between 08:00 - 17:00, new command

TOTAL: ~8 commands per 24 hours if all the commands are carried out. Is that too much?

Also, I haven’t figured out how to check BOTH cars… Right now everything depends on if one car needs charging or not.

EDIT:

OK, so I came up with a solution to lessen the writes to Modbus. Do you have something better in mind?

Btw @heyyitsal, would you be able to send this Excel to me? It would be easier to keep track of all the numbers since we have different batteries:

Don’t we have BYD HVM 11.0?

You’ve significantly minimised the amount of commands sent! But without any documentation about what is “too much” - its hard to say. All you can do is not send a command if you don’t need to and it looks like you have definitely done that! I have my own implementation but still a work in progress.

Overall you’ve done a great job and if your commands work then the rest is up to you to play around and experiment :smiley:

NodeRed is like Lego, so fun to figure out what each node can do and it’s so satisfying when you can get it working hahaha

1 Like

Good to get some confirmation! :+1:t3:

It ran now last night, and battery is currently at 82% HOLDING. Prices today are still low and now I’m waiting for the time span to occur for it to DISCHARGE.

I already have a few improvements in mind, but that would mean more writes to the NVRAM - like CHARGE everytime the battery is X and price is X, and do the same for DISCHARGE, and NORMAL.

One thing also, if sun would be shining now (it doesn’t), and the battery wasn’t min 90%, HOLDING the battery would mean I would export excessive energy instead of pushing to battery… Preferably I’d like for the battery to be CHARGED instead of HOLDING. I guess that would mean a setting of 3, and DISCHARGE to minus 100 and CHARGE to 0?

And yes, I also have the BYD 11.0 HVM. :slight_smile:

Will be interesting to exchange ideas in the future. I’m curious about your switch @heyitsal… It seemed smart. :slight_smile:

Some updated battery modes:

[{"id":"62fbd666c7c7b20d","type":"group","z":"effce8e2e8a9f43c","name":"BATTERY INSTRUCTIONS","style":{"label":true},"nodes":["7b45bdf5d2c774a4","d93cd01b0135c571","7a2e734eead34d16","b9ef723c9e5d6e8c"],"x":1428,"y":233,"w":544,"h":554},{"id":"7b45bdf5d2c774a4","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"NORMAL","style":{"label":true},"nodes":["7a60a2b45d28626d","8c9613cac1965ae9"],"x":1454,"y":259,"w":492,"h":82},{"id":"7a60a2b45d28626d","type":"function","z":"effce8e2e8a9f43c","g":"7b45bdf5d2c774a4","name":"NORMAL","func":"\nmsg.StorCtl_Mod = \"0\"\nmsg.OutWRte = \"10000\"\nmsg.InWRte = \"10000\"\n\nmsg.newstate = \"normal\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1860,"y":300,"wires":[["fad803646bcd93ee"]],"info":"This puts the battery in normal operation.\nMeaningn that it will both charge and discharge to\nits set limits at 100%,\n"},{"id":"8c9613cac1965ae9","type":"api-current-state","z":"effce8e2e8a9f43c","g":"7b45bdf5d2c774a4","name":"OutWRt already 100?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"100","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1580,"y":300,"wires":[[],["7a60a2b45d28626d"]]},{"id":"afa7e6c.89d5e18","type":"server","name":"Home Assistant","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":true,"heartbeatInterval":"30","statusSeparator":"","enableGlobalContextStore":false},{"id":"d93cd01b0135c571","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"FORCED CHARGE","style":{"label":true},"nodes":["66d147c4d9a586f8","62364dcb3387db2b","96365e785c02b8ce","21da80d2a0e2aa42"],"x":1454,"y":359,"w":492,"h":142},{"id":"66d147c4d9a586f8","type":"function","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","name":"4500W CHARGE","func":"msg.StorCtl_Mod = \"2\"\n// 4500W (65536-4500)\nmsg.OutWRte = \"61036\"\n\nmsg.newstate = \"forcecharge4500w\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1830,"y":400,"wires":[["fad803646bcd93ee"]],"info":"Example 1: Only permit energy storage charging\nThis behavior can be achieved by limiting the maximum discharge capacity to 0%\n=> results in window [-3300 W, 0 W]\n- OutWRte = 0% (set discharge limit of WchaMax to 0%)\n- StorCtl_Mod = 2 (activates discharge limit, bit pattern: 10)\n- InWRte is not relevant in this case"},{"id":"62364dcb3387db2b","type":"function","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","name":"1500W CHARGE","func":"msg.StorCtl_Mod = \"2\"\n// 4500W (65536-1500)\nmsg.OutWRte = \"64036\"\n\nmsg.newstate = \"forcecharge1500w\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1830,"y":460,"wires":[["fad803646bcd93ee"]],"info":"Example 5: Charging in the range of 50% to 75% of the nominal power\nThis behavior can be achieved by limiting the maximum charge capacity to 75%\nand the maximum discharge capacity to -50%\n=> results in window [1650 W, 2475 W]\n- InWRte = 75% (set charge limit of WchaMax to 75%)\n- OutWRte = -50% (set discharge limit of WchaMax to -50%)\n- StorCtl_Mod = 3 (activate both limit values, bit pattern: 11)\n- Battery status in Fronius Solar.web will change to Forced Recharge"},{"id":"96365e785c02b8ce","type":"api-current-state","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","name":"OutWRt already -15?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"-15","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1580,"y":460,"wires":[[],["62364dcb3387db2b"]]},{"id":"21da80d2a0e2aa42","type":"api-current-state","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","name":"OutWRt already -45?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"-45","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1580,"y":400,"wires":[[],["66d147c4d9a586f8"]]},{"id":"7a2e734eead34d16","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"HOLD (No charge or discharge)","style":{"label":true},"nodes":["5d370aec7b2aa1ce","f888ef1ef01b3e83"],"x":1454,"y":519,"w":492,"h":82},{"id":"5d370aec7b2aa1ce","type":"function","z":"effce8e2e8a9f43c","g":"7a2e734eead34d16","name":"HOLD","func":"msg.StorCtl_Mod = \"3\"\nmsg.OutWRte = \"0\"\nmsg.InWRte = \"0\"\n\nmsg.newstate = \"hold_state\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1870,"y":560,"wires":[["fad803646bcd93ee"]],"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":"f888ef1ef01b3e83","type":"api-current-state","z":"effce8e2e8a9f43c","g":"7a2e734eead34d16","name":"ChaSt already HOLDING?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"HOLDING","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.gen24_storage_chast","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1600,"y":560,"wires":[[],["5d370aec7b2aa1ce"]]},{"id":"b9ef723c9e5d6e8c","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"FORCED DISCHARGE","style":{"label":true},"nodes":["f52c691bee1e0932","3fccdd784ca45eca","bc399a85c5ad3281","7b05462e688a5afd"],"x":1454,"y":619,"w":492,"h":142},{"id":"f52c691bee1e0932","type":"function","z":"effce8e2e8a9f43c","g":"b9ef723c9e5d6e8c","name":"1500W DISCHARGE","func":"\nmsg.StorCtl_Mod = \"3\"\nmsg.OutWRte = 1000\n// 65536 - 1500\nmsg.InWRte = \"64536\"\n\nmsg.newstate = \"1kWdischarge\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1820,"y":660,"wires":[["fad803646bcd93ee"]]},{"id":"3fccdd784ca45eca","type":"api-current-state","z":"effce8e2e8a9f43c","g":"b9ef723c9e5d6e8c","name":"OutWRt already 10?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"10","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1580,"y":660,"wires":[[],["f52c691bee1e0932"]]},{"id":"bc399a85c5ad3281","type":"function","z":"effce8e2e8a9f43c","g":"b9ef723c9e5d6e8c","name":"3000W DISCHARGE","func":"\nmsg.StorCtl_Mod = \"3\"\nmsg.OutWRte = 1000\n// 65536 - 3000\nmsg.InWRte = \"64536\"\n\nmsg.newstate = \"3kWdischarge\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1820,"y":720,"wires":[["fad803646bcd93ee"]]},{"id":"7b05462e688a5afd","type":"api-current-state","z":"effce8e2e8a9f43c","g":"b9ef723c9e5d6e8c","name":"OutWRt already 30?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"30","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1580,"y":720,"wires":[[],["bc399a85c5ad3281"]]}]

image

The solutions for the cars became like this:

If they should start at the same time I’ve set an offset on either one or the other state, since it takes a few seconds for the Modbus to write and update.

I’ve also optimized the DISCHARGE a bit. Depending on the price, it now discharges at different power. The loading cost for CHARGING is always below 40 öre (cent), that means either 1 or 2 SEK profit / kwh.

EDIT:
Btw @steffanlm Just implemented your “Rate limit” before writing to Modbus, nice addition!

I’m a bit more cautious and decided to go with 1 message every 5 seconds. NVRAM wear… :slight_smile:

If you meant Discharge to -100% :

StorCTL_Mod = 3
Discharge = 55536
InWRte = 0

Then you would be force charging at 100%.

If you want
No Discharge - Only Charge with Excess Solar
Either:

StorCtl_MOD = 2
OutWRte = 0

Same thing can be done with this (but redundant in this case)

StorCtl_Mod = 3 (enables both OutWRte and InWRte registers)
OutWRte = 0
InWRte = 10000 (allow charging up to max rate)

The solutions for the cars became like this:

Wow you’ve done so much already! Keep it up!!

Will definitely post my battery/inverter control up soon - trying to efficientise it further… maybe it’s a never ending goal??

Haha, true dat!

I think this is just what I needed, thanks! Will set that as the normal throughout the day.

This one is also very interesting, I can now extract the time of the day when the price is at it’s highest, and if that price is above a hard limit set, then go bananas on the export (discharge):

image

[{"id":"d3317acef2826bb6","type":"ha-time","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"MAX DISCHARGE @ PEAK","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","entityId":"sensor.peak_48_hours_time","property":"","offset":"2","offsetType":"num","offsetUnits":"minutes","randomOffset":false,"repeatDaily":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"sunday":true,"monday":true,"tuesday":true,"wednesday":true,"thursday":true,"friday":true,"saturday":true,"x":920,"y":920,"wires":[["f8111ebed4317fd9"]]},{"id":"f8111ebed4317fd9","type":"api-current-state","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"PEAK PRICE","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"150","halt_if_type":"num","halt_if_compare":"gt","entity_id":"sensor.peak_48_hours_price","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1160,"y":920,"wires":[["7b05462e688a5afd"],[]]},{"id":"afa7e6c.89d5e18","type":"server","name":"Home Assistant","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":true,"heartbeatInterval":"30","statusSeparator":"","enableGlobalContextStore":false}]

Still experimenting, but after today’s run I’ve learned a few things:

  1. HOLD is only good if you actually know a big peak is coming, it’s better to set StorCtl 3 and let it charge from sun.
  2. Always try to diff at least 1 SEK (0.1 EUR) between charge and discharge. I sold pretty cheap today, and bought it expensive.
  3. There’s always room for improvement. The hardest parts are the hard limit - where should it be set? It can differ from day to day. But I think I settled on selling from battery storage if the price differs more than 1 SEK for now.
1 Like

OK, so I think this is close to the final result:

[{"id":"effce8e2e8a9f43c","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"62fbd666c7c7b20d","type":"group","z":"effce8e2e8a9f43c","name":"BATTERY INSTRUCTIONS","style":{"label":true},"nodes":["7b45bdf5d2c774a4","d93cd01b0135c571","7a2e734eead34d16","b9ef723c9e5d6e8c","f1579354c1921264"],"x":1728,"y":233,"w":564,"h":714},{"id":"f155037011aa0d79","type":"group","z":"effce8e2e8a9f43c","name":"Write changes!","style":{"label":true},"nodes":["0cc39af6d8b8dc0f","9f84293f8db8abd4","e0414ba507e24b27","3bffd91c351286ee"],"x":2734,"y":459,"w":672,"h":122},{"id":"fbe0abfb3ee0e088","type":"group","z":"effce8e2e8a9f43c","name":"Payload","style":{"label":true},"nodes":["fad803646bcd93ee"],"x":2414,"y":479,"w":292,"h":82},{"id":"7a697ccd23e6b3cb","type":"group","z":"effce8e2e8a9f43c","name":"START CHARGE 1H BEFORE CAR START BASED ON SPOT PRICE - CHEAP HOURS","style":{"label":true,"stroke":"#92d04f","color":"#000000"},"nodes":["1bdbeec9beec4666","7ba45c1373d6db9c","ec6756e96722cebb","ee12a627340871cc"],"x":14,"y":53,"w":1092,"h":148},{"id":"e209b9134d0bb2d2","type":"group","z":"effce8e2e8a9f43c","name":"DISCHARGE ON THE MOST EXPENSIVE HOURS","style":{"label":true,"color":"#000000","stroke":"#ff0000"},"nodes":["adbc3aa9cf52d50f","02b26ef1b0a8b08d","7f4903812faedc8c","d02c29a8f72609bd","c8e0d9aa9ca9caeb","34990cd67c990907","d3317acef2826bb6","1af0741d36ec6e93","f8111ebed4317fd9","fee34c327c9cea95","1aab75cc0f069305","2b9f4c9abc1148dd","de05bf4c517ce32a","7f55b776f0b34a54"],"x":14,"y":639,"w":1092,"h":382},{"id":"0bd67f9e3d7f071c","type":"group","z":"effce8e2e8a9f43c","name":"SCHELUDED CAR CHARGING","style":{"label":true,"color":"#000000","stroke":"#ffC000"},"nodes":["1c8a755bac3130a0","f049899799f7f431","19a007dca869d5ac","2f6678d42b0de023","906228c962c8c1e3","e47b6a6830c96cef"],"x":14,"y":239,"w":852,"h":282},{"id":"72b918efda5f705f","type":"group","z":"effce8e2e8a9f43c","name":"DO SOMETHING WHEN BATTERY IS FULL","style":{"stroke":"#000000","label":true,"color":"#000000"},"nodes":["213549e7b854d62a","b6852c6123b496b0","f27f1ab3f8eb58bf"],"x":1214,"y":19,"w":432,"h":162},{"id":"7ba45c1373d6db9c","type":"group","z":"effce8e2e8a9f43c","g":"7a697ccd23e6b3cb","name":"Check current price/kWh","style":{"label":true},"nodes":["d5351cdc453ee22e","3b6d2b1103a7ee5c"],"x":334,"y":79,"w":472,"h":82},{"id":"7b45bdf5d2c774a4","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"NORMAL","style":{"label":true},"nodes":["7a60a2b45d28626d","8c9613cac1965ae9"],"x":1774,"y":419,"w":492,"h":82},{"id":"d93cd01b0135c571","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"FORCED CHARGE","style":{"label":true},"nodes":["66d147c4d9a586f8","62364dcb3387db2b","96365e785c02b8ce","21da80d2a0e2aa42"],"x":1774,"y":519,"w":492,"h":142},{"id":"7a2e734eead34d16","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"HOLD (No charge or discharge)","style":{"label":true},"nodes":["5d370aec7b2aa1ce","f888ef1ef01b3e83"],"x":1774,"y":679,"w":492,"h":82},{"id":"02b26ef1b0a8b08d","type":"group","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"Check current price/kWh","style":{"label":true},"nodes":["0cc692ab6f439fdf","f032a97315254445"],"x":234,"y":724,"w":432,"h":112},{"id":"b9ef723c9e5d6e8c","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"FORCED DISCHARGE","style":{"label":true},"nodes":["f52c691bee1e0932","3fccdd784ca45eca","bc399a85c5ad3281","7b05462e688a5afd"],"x":1774,"y":779,"w":492,"h":142},{"id":"f1579354c1921264","type":"group","z":"effce8e2e8a9f43c","g":"62fbd666c7c7b20d","name":"POWER FROM SUN","style":{"label":true},"nodes":["79428347ba72398e","b77df5e20a3eff97","b30d06bcfe2e62de"],"x":1754,"y":259,"w":512,"h":142},{"id":"fee34c327c9cea95","type":"junction","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","x":1080,"y":720,"wires":[["3fccdd784ca45eca"]]},{"id":"1af0741d36ec6e93","type":"junction","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","x":1080,"y":680,"wires":[["7b05462e688a5afd"]]},{"id":"e47b6a6830c96cef","type":"junction","z":"effce8e2e8a9f43c","g":"0bd67f9e3d7f071c","x":580,"y":440,"wires":[["f888ef1ef01b3e83"]]},{"id":"de05bf4c517ce32a","type":"junction","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","x":1080,"y":800,"wires":[["b77df5e20a3eff97"]]},{"id":"7f55b776f0b34a54","type":"junction","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","x":1080,"y":740,"wires":[["8c9613cac1965ae9"]]},{"id":"d5351cdc453ee22e","type":"api-current-state","z":"effce8e2e8a9f43c","g":"7ba45c1373d6db9c","name":"Spotpris","server":"afa7e6c.89d5e18","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.energi_data_service","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":420,"y":120,"wires":[["3b6d2b1103a7ee5c"]]},{"id":"3b6d2b1103a7ee5c","type":"switch","z":"effce8e2e8a9f43c","g":"7ba45c1373d6db9c","name":"LESS than $LOWPEAKPRICE","property":"payload","propertyType":"msg","rules":[{"t":"lte","v":"LOWPEAKPRICE","vt":"env"}],"checkall":"true","repair":false,"outputs":1,"x":650,"y":120,"wires":[["ec6756e96722cebb"]]},{"id":"1bdbeec9beec4666","type":"ha-time","z":"effce8e2e8a9f43c","g":"7a697ccd23e6b3cb","name":"TESLA START OFFSET -1H","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","entityId":"sensor.tesla_start_charging_time","property":"","offset":"-3580","offsetType":"num","offsetUnits":"seconds","randomOffset":false,"repeatDaily":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"sunday":true,"monday":true,"tuesday":true,"wednesday":true,"thursday":true,"friday":true,"saturday":true,"x":160,"y":100,"wires":[["d5351cdc453ee22e"]]},{"id":"1c8a755bac3130a0","type":"ha-time","z":"effce8e2e8a9f43c","g":"0bd67f9e3d7f071c","name":"TESLA STOP (NOW)","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","entityId":"sensor.tesla_stop_charging_time","property":"","offset":"0","offsetType":"num","offsetUnits":"hours","randomOffset":false,"repeatDaily":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"sunday":true,"monday":true,"tuesday":true,"wednesday":true,"thursday":true,"friday":true,"saturday":true,"x":140,"y":420,"wires":[["e47b6a6830c96cef"]]},{"id":"7a60a2b45d28626d","type":"function","z":"effce8e2e8a9f43c","g":"7b45bdf5d2c774a4","name":"NORMAL","func":"\nmsg.StorCtl_Mod = \"0\"\nmsg.OutWRte = \"10000\"\nmsg.InWRte = \"10000\"\n\nmsg.newstate = \"normal\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2180,"y":460,"wires":[["fad803646bcd93ee"]],"info":"This puts the battery in normal operation.\nMeaningn that it will both charge and discharge to\nits set limits at 100%,\n"},{"id":"66d147c4d9a586f8","type":"function","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","name":"4500W CHARGE","func":"msg.StorCtl_Mod = \"2\"\n// 4500W (65536-4500)\nmsg.OutWRte = \"61036\"\n\nmsg.newstate = \"forcecharge4500w\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2150,"y":560,"wires":[["fad803646bcd93ee"]],"info":"Example 1: Only permit energy storage charging\nThis behavior can be achieved by limiting the maximum discharge capacity to 0%\n=> results in window [-3300 W, 0 W]\n- OutWRte = 0% (set discharge limit of WchaMax to 0%)\n- StorCtl_Mod = 2 (activates discharge limit, bit pattern: 10)\n- InWRte is not relevant in this case"},{"id":"5d370aec7b2aa1ce","type":"function","z":"effce8e2e8a9f43c","g":"7a2e734eead34d16","name":"HOLD","func":"msg.StorCtl_Mod = \"3\"\nmsg.OutWRte = \"0\"\nmsg.InWRte = \"0\"\n\nmsg.newstate = \"hold_state\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2190,"y":720,"wires":[["fad803646bcd93ee"]],"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":"0cc39af6d8b8dc0f","type":"modbus-response","z":"effce8e2e8a9f43c","g":"f155037011aa0d79","name":"","registerShowMax":20,"x":3190,"y":540,"wires":[]},{"id":"9f84293f8db8abd4","type":"modbus-flex-write","z":"effce8e2e8a9f43c","g":"f155037011aa0d79","name":"Fronius Storage","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"ecd41b68db8d4254","emptyMsgOnFail":true,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"10","x":3000,"y":520,"wires":[["0cc39af6d8b8dc0f","e0414ba507e24b27"],[]]},{"id":"e0414ba507e24b27","type":"debug","z":"effce8e2e8a9f43c","g":"f155037011aa0d79","name":"Inverter MODBUS Response","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":3230,"y":500,"wires":[]},{"id":"fad803646bcd93ee","type":"function","z":"effce8e2e8a9f43c","g":"fbe0abfb3ee0e088","name":"Modbus Payload Template","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': 40348,\n    'quantity': 9\n}\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2560,"y":520,"wires":[["3bffd91c351286ee"]]},{"id":"f049899799f7f431","type":"ha-time","z":"effce8e2e8a9f43c","g":"0bd67f9e3d7f071c","name":"TESLA START (NOW)","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","entityId":"sensor.tesla_start_charging_time","property":"","offset":"","offsetType":"num","offsetUnits":"hours","randomOffset":false,"repeatDaily":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"sunday":true,"monday":true,"tuesday":true,"wednesday":true,"thursday":true,"friday":true,"saturday":true,"x":140,"y":280,"wires":[["19a007dca869d5ac"]]},{"id":"adbc3aa9cf52d50f","type":"debug","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"MORE THAN 240","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":700,"y":680,"wires":[]},{"id":"0cc692ab6f439fdf","type":"api-current-state","z":"effce8e2e8a9f43c","g":"02b26ef1b0a8b08d","name":"Spotpris","server":"afa7e6c.89d5e18","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.energi_data_service","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":320,"y":780,"wires":[["f032a97315254445"]]},{"id":"f032a97315254445","type":"switch","z":"effce8e2e8a9f43c","g":"02b26ef1b0a8b08d","name":"Price switch","property":"payload","propertyType":"msg","rules":[{"t":"gte","v":"240","vt":"num"},{"t":"gte","v":"MAXPEAKPRICE","vt":"env"},{"t":"lte","v":"MAXPEAKPRICE","vt":"env"},{"t":"lte","v":"100","vt":"env"}],"checkall":"false","repair":false,"outputs":4,"x":570,"y":780,"wires":[["1af0741d36ec6e93","adbc3aa9cf52d50f"],["fee34c327c9cea95","c8e0d9aa9ca9caeb"],["34990cd67c990907","7f55b776f0b34a54"],["2b9f4c9abc1148dd","de05bf4c517ce32a"]]},{"id":"7f4903812faedc8c","type":"time-of-day","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"","startTime":"16:00:00","endTime":"20:01:00","outputs":1,"x":130,"y":800,"wires":[["0cc692ab6f439fdf"]]},{"id":"d02c29a8f72609bd","type":"time-of-day","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"","startTime":"06:00:00","endTime":"09:01:00","outputs":1,"x":130,"y":740,"wires":[["0cc692ab6f439fdf"]]},{"id":"19a007dca869d5ac","type":"api-current-state","z":"effce8e2e8a9f43c","g":"0bd67f9e3d7f071c","name":"GRID LOAD less than 5500W?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"5500","halt_if_type":"num","halt_if_compare":"lte","entity_id":"sensor.gen24_ac_meter_watts","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":710,"y":340,"wires":[["21da80d2a0e2aa42"],["96365e785c02b8ce"]]},{"id":"62364dcb3387db2b","type":"function","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","name":"1500W CHARGE","func":"msg.StorCtl_Mod = \"2\"\n// 4500W (65536-1500)\nmsg.OutWRte = \"64036\"\n\nmsg.newstate = \"forcecharge1500w\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2150,"y":620,"wires":[["fad803646bcd93ee"]],"info":"Example 5: Charging in the range of 50% to 75% of the nominal power\nThis behavior can be achieved by limiting the maximum charge capacity to 75%\nand the maximum discharge capacity to -50%\n=> results in window [1650 W, 2475 W]\n- InWRte = 75% (set charge limit of WchaMax to 75%)\n- OutWRte = -50% (set discharge limit of WchaMax to -50%)\n- StorCtl_Mod = 3 (activate both limit values, bit pattern: 11)\n- Battery status in Fronius Solar.web will change to Forced Recharge"},{"id":"213549e7b854d62a","type":"server-state-changed","z":"effce8e2e8a9f43c","g":"72b918efda5f705f","name":"State Check Battery MORE THAN 60%","server":"afa7e6c.89d5e18","version":5,"outputs":2,"exposeAsEntityConfig":"","entityId":"sensor.gen24_storage_chastate","entityIdType":"exact","outputInitially":true,"stateType":"num","ifState":"60","ifStateType":"num","ifStateOperator":"gt","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":1390,"y":60,"wires":[["b6852c6123b496b0"],["f27f1ab3f8eb58bf"]]},{"id":"b6852c6123b496b0","type":"time-of-day","z":"effce8e2e8a9f43c","g":"72b918efda5f705f","name":"","startTime":"09:01:00","endTime":"16:01:00","outputs":1,"x":1330,"y":140,"wires":[["8c9613cac1965ae9"]]},{"id":"1aa259781a6e2913","type":"debug","z":"effce8e2e8a9f43c","name":"IS SOMETHING WRITTEN?","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":3070,"y":640,"wires":[]},{"id":"6f57fd58660bf7dc","type":"inject","z":"effce8e2e8a9f43c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":2840,"y":640,"wires":[["1aa259781a6e2913"]]},{"id":"cb05b2a950f8de3d","type":"cronplus","z":"effce8e2e8a9f43c","name":"Every second","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"* * * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":540,"y":560,"wires":[[]]},{"id":"c8e0d9aa9ca9caeb","type":"debug","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"MORE THAN $MAXPEAKPRICE","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":900,"y":820,"wires":[]},{"id":"34990cd67c990907","type":"debug","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"LESS THAN $MAXPEAKPRICE","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":880,"y":880,"wires":[]},{"id":"f52c691bee1e0932","type":"function","z":"effce8e2e8a9f43c","g":"b9ef723c9e5d6e8c","name":"1500W DISCHARGE","func":"msg.StorCtl_Mod = \"1\"\n// 65536 - 1500\nmsg.InWRte = \"64036\"\n\nmsg.newstate = \"1kWdischarge\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2140,"y":820,"wires":[["fad803646bcd93ee"]]},{"id":"3fccdd784ca45eca","type":"api-current-state","z":"effce8e2e8a9f43c","g":"b9ef723c9e5d6e8c","name":"InWRte already -15?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"-15","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_inwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1900,"y":820,"wires":[[],["f52c691bee1e0932"]]},{"id":"f888ef1ef01b3e83","type":"api-current-state","z":"effce8e2e8a9f43c","g":"7a2e734eead34d16","name":"ChaSt already HOLDING?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"HOLDING","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.gen24_storage_chast","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1920,"y":720,"wires":[[],["5d370aec7b2aa1ce"]]},{"id":"96365e785c02b8ce","type":"api-current-state","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","name":"OutWRte already -15?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"-15","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1900,"y":620,"wires":[[],["62364dcb3387db2b"]]},{"id":"21da80d2a0e2aa42","type":"api-current-state","z":"effce8e2e8a9f43c","g":"d93cd01b0135c571","name":"OutWRte already -45?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"-45","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1900,"y":560,"wires":[[],["66d147c4d9a586f8"]]},{"id":"8c9613cac1965ae9","type":"api-current-state","z":"effce8e2e8a9f43c","g":"7b45bdf5d2c774a4","name":"OutWRte already 100?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"100","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_outwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1900,"y":460,"wires":[[],["7a60a2b45d28626d"]]},{"id":"bc399a85c5ad3281","type":"function","z":"effce8e2e8a9f43c","g":"b9ef723c9e5d6e8c","name":"4500W DISCHARGE","func":"\nmsg.StorCtl_Mod = \"1\"\n// 65536 - 4500\nmsg.InWRte = \"61036\"\n\nmsg.newstate = \"3kWdischarge\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2140,"y":880,"wires":[["fad803646bcd93ee"]]},{"id":"7b05462e688a5afd","type":"api-current-state","z":"effce8e2e8a9f43c","g":"b9ef723c9e5d6e8c","name":"InWRte already -45?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"-45","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_inwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1900,"y":880,"wires":[[],["bc399a85c5ad3281"]]},{"id":"ec6756e96722cebb","type":"api-current-state","z":"effce8e2e8a9f43c","g":"7a697ccd23e6b3cb","name":"GRID LOAD less than 5500W?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"5500","halt_if_type":"num","halt_if_compare":"lte","entity_id":"sensor.gen24_ac_meter_watts","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":950,"y":140,"wires":[["21da80d2a0e2aa42"],["96365e785c02b8ce"]]},{"id":"2f6678d42b0de023","type":"ha-time","z":"effce8e2e8a9f43c","g":"0bd67f9e3d7f071c","name":"VW START (NOW)","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","entityId":"sensor.volkswagen_start_charging_time","property":"","offset":"30","offsetType":"num","offsetUnits":"seconds","randomOffset":false,"repeatDaily":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"sunday":true,"monday":true,"tuesday":true,"wednesday":true,"thursday":true,"friday":true,"saturday":true,"x":130,"y":340,"wires":[["19a007dca869d5ac"]]},{"id":"906228c962c8c1e3","type":"ha-time","z":"effce8e2e8a9f43c","g":"0bd67f9e3d7f071c","name":"VW STOP (NOW)","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","entityId":"sensor.volkswagen_stop_charging_time","property":"","offset":"30","offsetType":"num","offsetUnits":"seconds","randomOffset":false,"repeatDaily":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"sunday":true,"monday":true,"tuesday":true,"wednesday":true,"thursday":true,"friday":true,"saturday":true,"x":130,"y":480,"wires":[["e47b6a6830c96cef"]]},{"id":"ee12a627340871cc","type":"ha-time","z":"effce8e2e8a9f43c","g":"7a697ccd23e6b3cb","name":"VW START OFFSET -1H","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","entityId":"sensor.volkswagen_start_charging_time","property":"","offset":"-3570","offsetType":"num","offsetUnits":"seconds","randomOffset":false,"repeatDaily":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"sunday":true,"monday":true,"tuesday":true,"wednesday":true,"thursday":true,"friday":true,"saturday":true,"x":150,"y":160,"wires":[["d5351cdc453ee22e"]]},{"id":"3bffd91c351286ee","type":"delay","z":"effce8e2e8a9f43c","g":"f155037011aa0d79","name":"Rate limit","pauseType":"rate","timeout":"500","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"10","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":2820,"y":520,"wires":[["9f84293f8db8abd4"]]},{"id":"79428347ba72398e","type":"function","z":"effce8e2e8a9f43c","g":"f1579354c1921264","name":"ALLOW SUN CHARGE","func":"msg.StorCtl_Mod = \"3\"\nmsg.OutWRte = \"65536\"\nmsg.InWRte = \"10000\"\n\nmsg.newstate = \"allow_suncharge\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":2130,"y":360,"wires":[["fad803646bcd93ee"]],"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":"f27f1ab3f8eb58bf","type":"time-of-day","z":"effce8e2e8a9f43c","g":"72b918efda5f705f","name":"","startTime":"09:01:00","endTime":"16:01:00","outputs":1,"x":1550,"y":140,"wires":[["b77df5e20a3eff97"]]},{"id":"d3317acef2826bb6","type":"ha-time","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"MAX DISCHARGE @ PEAK","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","entityId":"sensor.peak_48_hours_time","property":"","offset":"2","offsetType":"num","offsetUnits":"minutes","randomOffset":false,"repeatDaily":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"sunday":true,"monday":true,"tuesday":true,"wednesday":true,"thursday":true,"friday":true,"saturday":true,"x":160,"y":940,"wires":[["f8111ebed4317fd9"]]},{"id":"f8111ebed4317fd9","type":"api-current-state","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"PEAK PRICE (170)","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"170","halt_if_type":"num","halt_if_compare":"gt","entity_id":"sensor.peak_48_hours_price","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":410,"y":940,"wires":[["7b05462e688a5afd"],["f032a97315254445"]]},{"id":"b77df5e20a3eff97","type":"api-current-state","z":"effce8e2e8a9f43c","g":"f1579354c1921264","name":"InWRte already 100?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"100","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.gen24_storage_inwrte","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1880,"y":300,"wires":[[],["b30d06bcfe2e62de"]]},{"id":"1aab75cc0f069305","type":"cronplus","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"Every hour","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"15 0 * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":130,"y":680,"wires":[["d02c29a8f72609bd","7f4903812faedc8c"]]},{"id":"8306b11f2939be75","type":"cronplus","z":"effce8e2e8a9f43c","name":"Every minute","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"0 * * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":810,"y":560,"wires":[[]]},{"id":"b30d06bcfe2e62de","type":"api-current-state","z":"effce8e2e8a9f43c","g":"f1579354c1921264","name":"ChaSt already HOLDING?","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"HOLDING","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.gen24_storage_chast","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":2120,"y":300,"wires":[[],["79428347ba72398e"]]},{"id":"2b9f4c9abc1148dd","type":"debug","z":"effce8e2e8a9f43c","g":"e209b9134d0bb2d2","name":"LESS THAN 100","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":790,"y":980,"wires":[]},{"id":"afa7e6c.89d5e18","type":"server","name":"Home Assistant","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":true,"heartbeatInterval":"30","statusSeparator":"","enableGlobalContextStore":false},{"id":"ecd41b68db8d4254","type":"modbus-client","name":"Fronius Gen24","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":true,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"10.10.10.4","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":1,"commandDelay":1,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true}]

Any suggestions of improvments?

1 Like

How does it go after 9 days?

I’m working through my solution - finding edge cases I should’ve thought about.

Max discharge of battery at 4.5kW - reduces solar panel production due to maximum AC output of the inverter. So have had to dynamically adjust battery output instead of forcing max discharge.

Wish I could start doing forecasting but still need to get the basics down first…

My loong answer got lost due to read-only…

Basically yes - it works OK, but I’m starting to question if it’s worth it in the end when importing electricity from GRID is so expensive.

OK, so now I want to change Fronius to Sunspec in my Energy dashboard, but I’m not sure which entities to use in my templates.

Does anyone have a clue?

Hope you figure out an optimal charging strategy!!

Energy Dashboard:

From smart meter - Sunspec integration:
Smartmeter Energy Real Consumption:
_total_watt_hours_imported

Smatermeter Energy Real Produced:
_total_watt_hours_exported

Total Photovoltaics Energy:
You’ll need to make your own template sensor - you can use if you have 2 strings - 1 on each input:
kw10_mppt_module_0_lifetime_energy + kw10_mppt_module_1_lifetime_energy

  - name: "Power Photovoltaics 10kw"
    unique_id: "power_photovoltaics_10kw"
    unit_of_measurement: W
    device_class: power
    state: "{{ states('sensor.kw10_mppt_module_0_dc_power') | float(default=0) 
    + states('sensor.kw10_mppt_module_1_dc_power') | float(default=0)}}"

And then integration sensor:

- platform: integration
  source: sensor.total_power_photovoltaics
  name: "Total Photovoltaics Energy"
  unit_prefix: k
  method: left

And Total Battery Energy Charge/Discharge
Same thing - you’ll need your own integration sensor for that based on:

kw10_mppt_module_3_dc_power
kw10_mppt_module_2_dc_power

- platform: integration
  source: sensor.kw10_mppt_module_2_dc_power
  name: "Total Battery Energy Charged"
  unit_prefix: k
  method: left

- platform: integration
  source: sensor.kw10_mppt_module_3_dc_power
  name: "Total Battery Energy Discharged"
  unit_prefix: k
  method: left

Something like that…

1 Like

Thanks!

For feed in effect (Fronius), I have this today:

{{ max(0, 0 - states('sensor.gen24_ac_meter_watts') | float) }}

And for ‘drawn effect’ (Fronius) I have this:

{{ max(0, states('sensor.gen24_ac_meter_watts') | float) }}

Is that wrong?