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

Maybe make the name a bit more interesting than sunspec as it becomes the prefix to all your sensors:

Choose all read models available and 5-10s scan interval for faster updating

I tried to do it all in YAML but I struggled with getting all the syntax correct. NodeRed has been a godsend.

We have the same setup except I have an extra 5kW inverter. You could copy and paste it across and delete all the secondary inverter controls and get going pretty quick !! Will be interesting to see what you can tweak and improve!

As long as we are on the same starting point - Modbus setup on inverter via technician controls, FLOAT, etc I go through it step by step on my blog just to make sure we’re all on the same page.

1 Like

I’m reading your blog post now. I don’t understand why you set a limit on export in the Fronius GUI though?

And also, I’m on INT+SF. You’re on Float right? That means I have to change your addresses by -10?

Ohh sorry I’ll make that clearer, we turn on limiting on the inverter and make it the default state of the inverter. Combined with a smart meter the inverter will do the heavy lifting of export limiting calculations. This is especially useful during negative feed in tariff times.

We then use Modbus control to adjust output power output from 1-100% when we aren’t in export limiting mode.

The naming WMaxLimEna isn’t the most intuitive but I think of it as turn this on, to enter manual power adjusting mode.

And correct if you are INT+FLOAT, just minus 10 from all the register addresses from mine.

1 Like

So basically; default is to not export. Because AFAIK the smart meter isn’t very smart and won’t allow exporting anything if not set by the owner (me and you).

Also, my situation regarding electricity are not fixed tariffs, it’s per hour. So a day could look like the above post in price (elpris_kwh_total = the price in SEK, Elnät drawn effekt = Fronius integration and the RAW value from the smart meter power).

My goal with this whole setup is to avoid peaks, and be smart about when to use the battery or not. For example if the price is low one hour, CHARGE, then hold until a new peak and then DISCHARGE. Typically that means that the battery will CHARGE during night between 00-05 AM - “but wait there’s more” :wink: - there can also be very low price during the day, and some times for whole weekends. That extra important now especially in the winter since prices may vary around 1-2 SEK / kWH during lows and highs.

Above that I also have two car batteries that needs charging during the night, and my total house power is 20A. The example above shows more or less when I maxed out on everything: both cars were charging, battery charged 2000W, dishwasher on, and me tinkering. :slight_smile: I use an “Equalizer” for the cars, which limits the power based on the main fuse - but I’ve seen occasions where it peaked at around 28A just for some second - that would also be good to avoid.

Up until now I don’t have the hourly price for electricity, but November 13 it will become a reality, and then this HAVE to work, otherwise I’ll be ruined. :slight_smile:

Just downloaded Node RED, now the endeavor begins!

So basically; default is to not export. Because AFAIK the smart meter isn’t very smart and won’t allow exporting anything if not set by the owner (me and you).

Yes - default is to NOT export. When the feed in tariff is negative, turn OFF Modbus control (WMaxLimEna = 0) to put back into inverter managed state of export limitin.

When feed in tariff is positive, enable Modbus control WMaxLimEna = 1 and max power WMaxLimEna 10000.

Also, my situation regarding electricity are not fixed tariffs, it’s per hour. So a day could look like the above post in price (elpris_kwh_total = the price in SEK, Elnät drawn effekt = Fronius integration and the RAW value from the smart meter power).

Yes my implementation is based on Amber Electric which are based on 5 minute price changes. Similar to yours.

My goal with this whole setup is to avoid peaks, and be smart about when to use the battery or not. For example if the price is low one hour, CHARGE, then hold until a new peak and then DISCHARGE. Typically that means that the battery will CHARGE during night between 00-05 AM - “but wait there’s more” :wink: - there can also be very low price during the day, and some times for whole weekends. That extra important now especially in the winter since prices may vary around 1-2 SEK / kWH during lows and highs.

When you want to hold the battery - you can set your battery to not discharge InWRte = 0, OutWRte = 0
When your SEK is only above a certain SEK - force maximum discharge InWRte = -55536, OutWRte = 10000
When your SEK is under a certain threshold - force max charge InWRte = 10000 OutWRte = -55536

Above that I also have two car batteries that needs charging during the night, and my total house power is 20A. The example above shows more or less when I maxed out on everything: both cars were charging, battery charged 2000W, dishwasher on, and me tinkering. :slight_smile: I use an “Equalizer” for the cars, which limits the power based on the main fuse - but I’ve seen occasions where it peaked at around 28A just for some second - that would also be good to avoid.

Overnight - you can hold your battery until you start drawing from the grid above 8000W. Have your battery to discharge power to match any power increase above 8000W. But you’ll need to use sunspec integration for fast power measurement of your smart meter.

Hopefully there is an integration for your energy provider and home assistant, if so it will make your life easier!! Good luck!!

1 Like

@heyyitsal OK, so running this as a test now:

[{"id":"091ca0116b29db01","type":"function","z":"2460b7dd22fc0358","g":"6993516a32a59b71","name":"WMaxLim_Ena = 0","func":"msg.payload = { \n    'value': 0,\n    'fc': 6,\n    'unitid': 1,\n    'address': 40236,\n    'quantity': 1\n} \n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1510,"y":780,"wires":[["d4b4a54cb4aa17bb","95cb0b89c5be0909"]]}]

It haven’t triggered yet afaik, and to my understanding it should remove the export limit if the price is above 1?

This only sets the export limit, right?

This was also super helpful! Though I’m a bit unsure why I get this message when trying to force charge?

msg : error
"Error: Modbus exception 3: Illegal data value (value cannot be written to this register)"

msg.StorCtl_Mod = "3"
msg.OutWRte = "60536"
msg.InWRte = 5000

msg.newstate = "forcechargeonly"

return msg
var values = [msg.StorCtl_Mod, (65535), (700), (10000), (65535), (65535), (5), (msg.OutWRte), (msg.InWRte)]

msg.payload = {
    'value': values,
    'fc': 16,
    'unitid': 1,
    'address': 40358,
    'quantity': 9
}

return msg

EDIT: Some more debuggning:

Running a test now trying to force charge, and will build something upon that.

Thanks again, this have been super helpful!

Me again :wave:

Now looking at the documentation and trying to set this:

Example 5: Charging in the range of 50% to 75% of the nominal power
This behavior can be achieved by limiting the maximum charge capacity to 75%
and the maximum discharge capacity to -50%
=> results in window [1650 W, 2475 W]
- InWRte = 75% (set charge limit of WchaMax to 75%)
- OutWRte = -50% (set discharge limit of WchaMax to -50%)
- StorCtl_Mod = 3 (activate both limit values, bit pattern: 11)
- Battery status in Fronius Solar.web will change to Forced Recharge

With this:

msg.StorCtl_Mod = "3"
msg.OutWRte = "60536"
msg.InWRte = 5000

msg.newstate = "forcechargeonly"

return msg
var values = [msg.StorCtl_Mod, (65535), (700), (8000), (65535), (65535), (5), (msg.OutWRte), (msg.InWRte)]

msg.payload = {
    'value': values,
    'fc': 16,
    'unitid': 1,
    'address': 40355,
    'quantity': 9
}

return msg

I get the "Error: Modbus exception 3: Illegal data value (value cannot be written to this register)" But its doesn’t make sense to me… Have I missed some setting somewhere?

I read above that sensor.gen24_storage_inoutwrte_rvrttms needs to be set to 0, so I did that. But to I also need to do some kind of calculation of how large the battery is to be allowed within a ceratin limit or something?

These are my current settings for the battery right now:

And I’m debugging with this:

THANK YOU again, just want to get this up and running and your help is super valuable! cc @steffanlm @heyyitsal

EDIT: SOLVED!

The issue was that the StorCtl_Mod was set to 3 and not 2 in your example @heyyitsal, when changed that one to 2, and also did the math 65536−50(%)=65485 (not sure if that’s correct), and BAM the inverter booted and started charging.

image

Example 7: Charging with 50% to 100% of the nominal power
This behavior can be achieved by limiting the maximum discharge capacity to
-50% => results in window [1650 W, 3300 W]
- OutWRte = -50% (set discharge limit of WchaMax to -50%)
- StorCtl_Mod = 2 (activates discharge limit, bit pattern: 10)
- InWRte is not relevant in this case
- Battery status in Fronius Solar.web will change to Forced Recharge

Here’s what I used:

var values = [msg.StorCtl_Mod, (65535), (700), (10000), (65535), (65535), (5), (msg.OutWRte), (msg.InWRte)]

msg.payload = {
    'value': values,
    'fc': 16,
    'unitid': 1,
    // INT+SF = -10
    'address': 40348,
    'quantity': 9
}

return msg
msg.StorCtl_Mod = "2"
msg.OutWRte = "60486"
msg.InWRte = 5000

msg.newstate = "forcechargeonly"

return msg

Still not figured out what this means though…

var values = [msg.StorCtl_Mod, (65535), (700), (10000), (65535), (65535), (5), (msg.OutWRte), (msg.InWRte)]

Is that just the msg.payload - in other words for debugging purposes?

I also realize that what I did doesn’t match with the documentation since I use msg.InWrte which doesn’t matter when you are charging at 100% power…

I hope I didn’t do something stupid now. :slight_smile:

EDIT 2:

OK, so some more tinkering, this is what I have so far…

[{"id":"d4ddcb9085ea730f","type":"group","z":"effce8e2e8a9f43c","name":"Write changes!","style":{"label":true},"nodes":["180989e6b6be69e1","beceba7f58b3cb02","8257c587efbab683","128a17e0b4b42529","6e1b23a96a0be05e","cb1a63e7561cc549"],"x":994,"y":19,"w":692,"h":162},{"id":"180989e6b6be69e1","type":"modbus-response","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"","registerShowMax":20,"x":1470,"y":120,"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":1280,"y":100,"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":1510,"y":80,"wires":[]},{"id":"128a17e0b4b42529","type":"debug","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"Inverter MODBUS Response","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1150,"y":60,"wires":[]},{"id":"6e1b23a96a0be05e","type":"modbus-response","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"","registerShowMax":20,"x":1110,"y":140,"wires":[]},{"id":"cb1a63e7561cc549","type":"function","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"InWRte","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":1080,"y":100,"wires":[["beceba7f58b3cb02","6e1b23a96a0be05e","128a17e0b4b42529"]]},{"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}]

Plan is to charge on cheap hours, and only when the cars is not charging. Haven’t got my head around the car charging part yet, but I’ll get there.

Also, what do you think is the best way to resetting to normal mode when the price is high again?

Final picture before bed (current state):

I get the “Error: Modbus exception 3: Illegal data value (value cannot be written to this register)” But its doesn’t make sense to me… Have I missed some setting somewhere?

I think you fixed it by changing your address value from 40355 to 40348. Battery control and inverter control uses different register values so be careful!

It haven’t triggered yet afaik, and to my understanding it should remove the export limit if the price is above 1?

WMaxLim_Ena = 0 - turns off Modbus control - giving the inverter full control again to export limit

WMaxLim_Ena = 1 - turns on Modbus control - giving us control to do whatever you want!

Ignore the naming of the register - they should name it like Modbus_Control = 0 or 1…

Still not figured out what this means though…
var values = [msg.StorCtl_Mod, (65535), (700), (10000), (65535), (65535), (5), (msg.OutWRte), (msg.InWRte)]
Is that just the msg.payload - in other words for debugging purposes?

It’s just a template before I pass it into the payload from when I first started writing to multiple messages. Probably could make a nicer implementation though.

var values = [msg.StorCtl_Mod, VAChaMax, MinRsvPct, ChaState,StorAval , InBatV, ChaSt, (msg.OutWRte), (msg.InWRte)]

I think you already can tell registers you can write to and what are read only.

msg.StorCtl_Mod - RW
VAChaMax - R - 65535 - Read Only
MinRsvPct - RW - Minimum Battery % (700 = 7%, you can change this if you want save more battery for later)
ChaState - R - 10000 (I just copied what the register default was and put it back into this message, but it’s READ ONLY anyway)
StorAval - R - 65535 - Read Only
InBatV -R - 65535 - Read Only
ChaSt - R - 65535 - Read Only (Sorry I put 5, that was what the inverter gave me before)
(msg.OutWRte) - RW
(msg.InWRte) - RW

OK, so some more tinkering, this is what I have so far…

Nice one!!! Another one joins the fold! Thanks to the pioneers earlier in this thread!!

image

You could probably delete this Modbus Response.

But more importantly:

InWRte (sorry probably should’ve fixed the name, I’ll change it to Modbus Msg Template)
Is your template before you send it off to the Inverter.
All the ForceCharge/Normal Op/50%kw Discharge/Hold are where you build your messages which you can send to your Modbus Msg Template, then that goes into the inverter.

I also realize that what I did doesn’t match with the documentation since I use msg.InWrte which doesn’t matter when you are charging at 100% power…

A good visualisation I got was from here:

Here is a quick reference table:

I think what you’ve done with

msg.StorCtl_Mod = "2"
msg.OutWRte = "60486"
msg.InWRte = 5000

msg.newstate = "forcechargeonly"

With StorCtl_Mod = 2, you’ve set your battery to “Charge Only”.
If you had set OutWrte = 0, you would’ve set your charging range between 0 - Maximum. Maximum being, whatever available extra solar capacity you’ve had.

But because you’ve set OutWRte = “60486” or “-5050”, you’ve set the minimum charging rate to 5,171W (50.5% of 10,240W).
But the maximum BYD HVM 11.0 is only rated to 4500W. So the battery is forced to charge at 4500W.

And on the flip side,with StorCtl_Mod = 1, if you set a negative number into the InWrte Charging register you turn it into a minimum discharging value.

Also I’ll post my updated battery control

Export your whole flow if you can, you’ve just exported the Write Changes section haha.

Good luck!

1 Like

Seriously, super helpful! I’m so grateful that I got this up and running now (soon)! I started out two weeks ago from nothing, and now I control my cars, heat pump, solar and battery through home assistant. I had this in the back of my head for like a year now, but finally came around to actually do something about it.

I’m looking forward to getting this perfect (ok, it will never be hehe), and this feels like a good base to stand on.

We’ll see, maybe I’ll keep Node RED or convert it into HAOS automations, we’ll see what’s easiest… Do you know btw if you can make enteties of node flows? If I for example would like a button or switch to quickly turn on or off charging…?

I’ll post the full export tomorrow. Have to sleep now.

Thanks again! :1st_place_medal:

EDIT: Or btw, here you go:

[{"id":"effce8e2e8a9f43c","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"76ab0c3aad64c668","type":"tab","label":"Fronius Export Control Updated","disabled":true,"info":"","env":[]},{"id":"82d61b2ddb027662","type":"tab","label":"Flow 2","disabled":true,"info":"","env":[]},{"id":"67faeae86ef585a8","type":"group","z":"76ab0c3aad64c668","name":"Check 1 Minute Intervals","style":{"label":true},"nodes":["200bacc074df8cbe","cc52d431205212f2","4db51c0c85952ba4","045582548c036ebb","a3c52370e1e3c91b"],"x":14,"y":99},{"id":"d49b298a20da4cb3","type":"group","z":"76ab0c3aad64c668","name":"Check Battery Discharge - If Yes - Max Output","style":{"label":true},"nodes":["d18a063fdcace0ab","093e86667a226569","45fd82b96452fd59"],"x":14,"y":439},{"id":"dd1ae8afab7bd989","type":"group","z":"76ab0c3aad64c668","name":"Primary Inverter with Smart Meter","style":{"label":true},"nodes":["bf545c79efb5be6e","5b9f73ad2d28291f","d61e75648cf03aa5","942cab0954a58820","0ad6a47eabf863af","5dd4a83230f373cf","ec76d9ae41bde168","bc3862a711b0445e","92b3c15ead4a275d"],"x":614,"y":39},{"id":"67f3f6554cd2fe41","type":"group","z":"82d61b2ddb027662","name":"Main Inverter Connected to Smart Meter","style":{"label":true},"nodes":["2c660a19252258df","678adc0348f546d3","ed79a132110622ab"],"x":114,"y":299},{"id":"d4ddcb9085ea730f","type":"group","z":"effce8e2e8a9f43c","name":"Write changes!","style":{"label":true},"nodes":["180989e6b6be69e1","beceba7f58b3cb02","8257c587efbab683","128a17e0b4b42529","6e1b23a96a0be05e","cb1a63e7561cc549"],"x":994,"y":19,"w":692,"h":162},{"id":"9d13313687e3f017","type":"group","z":"effce8e2e8a9f43c","name":"Normal state","style":{"label":true},"nodes":["134bc56b2d93918d","cf500d91417561eb","2468d8245a765d21"],"x":674,"y":359,"w":532,"h":122},{"id":"ceea0bd0f56e5cbe","type":"group","z":"effce8e2e8a9f43c","name":"Force charge","style":{"label":true},"nodes":["8bf3fd6bab97b524","d19deebddbe58f74","f3095d184f17834f","0548b4b7a9faec3d","f79b4f746a482239","ab188204ffe303ef"],"x":674,"y":219,"w":652,"h":122},{"id":"32f8524788c52a9d","type":"group","z":"effce8e2e8a9f43c","name":"Force Discharge","style":{"label":true},"nodes":["f941ac38c439226e","d804b22ae3be2b4e","127b84a81d7204e8"],"x":674,"y":499,"w":532,"h":122},{"id":"f84e3a88a392756e","type":"group","z":"effce8e2e8a9f43c","name":"HOLD (No charge or discharge) - NOT TESTED","style":{"label":true},"nodes":["23b92e3a92162b4a","9c1a5de4d5079aa4","4be156af80f1d0d2"],"x":674,"y":659,"w":612,"h":122},{"id":"0ad6a47eabf863af","type":"group","z":"76ab0c3aad64c668","g":"dd1ae8afab7bd989","name":"Enable Modbus Control - Max Output","style":{"label":true},"nodes":["57f9336fd070e990","38741f73b2283ba3","d14dcad7cd72383f","168c0e4cad193ff9","737229fe2974e0cf"],"x":1234,"y":99},{"id":"5dd4a83230f373cf","type":"group","z":"76ab0c3aad64c668","g":"dd1ae8afab7bd989","name":"Disable Modbus Control - Limit Exports","style":{"label":true},"nodes":["9677eb7418f50bfe","7acb279b01b8b86e","c15edc748f63bdd9","ad601a7bb224da80","2734f7c6cd704d7c"],"x":1234,"y":299},{"id":"ec76d9ae41bde168","type":"group","z":"76ab0c3aad64c668","g":"dd1ae8afab7bd989","name":"Main Inverter Connected to Smart Meter","style":{"label":true},"nodes":["ba19a0ef37ef7dca","c337fcf0fac93eae","f8e3e969561ea1f7","c40101ee33f5a5fd"],"x":1954,"y":219},{"id":"bc3862a711b0445e","type":"group","z":"76ab0c3aad64c668","g":"dd1ae8afab7bd989","name":"Check Current WMaxLimEna","style":{"label":true},"nodes":["b8453a1af1eac10d","817a3ac03ce24936","8c568a8ffe7f8f39"],"x":654,"y":119},{"id":"92b3c15ead4a275d","type":"group","z":"76ab0c3aad64c668","g":"dd1ae8afab7bd989","name":"Check Current WMaxLimEna","style":{"label":true},"nodes":["108881d15cc05277","e98e8be8c28e9b7d","9cabe321855fbdb2"],"x":654,"y":319},{"id":"7ba45c1373d6db9c","type":"group","z":"effce8e2e8a9f43c","name":"Check current price/kWh","style":{"label":true},"nodes":["d5351cdc453ee22e","3b6d2b1103a7ee5c","dd104017de06fd0b"],"x":14,"y":39,"w":452,"h":162},{"id":"0548b4b7a9faec3d","type":"junction","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","x":700,"y":280,"wires":[[]]},{"id":"f79b4f746a482239","type":"junction","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","x":700,"y":280,"wires":[[]]},{"id":"ab188204ffe303ef","type":"junction","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","x":700,"y":280,"wires":[[]]},{"id":"168c0e4cad193ff9","type":"junction","z":"76ab0c3aad64c668","g":"0ad6a47eabf863af","x":1280,"y":200,"wires":[["38741f73b2283ba3"]]},{"id":"c40101ee33f5a5fd","type":"junction","z":"76ab0c3aad64c668","g":"ec76d9ae41bde168","x":1980,"y":300,"wires":[["f8e3e969561ea1f7"]]},{"id":"737229fe2974e0cf","type":"junction","z":"76ab0c3aad64c668","g":"0ad6a47eabf863af","x":1780,"y":200,"wires":[["c40101ee33f5a5fd"]]},{"id":"ad601a7bb224da80","type":"junction","z":"76ab0c3aad64c668","g":"5dd4a83230f373cf","x":1300,"y":340,"wires":[["7acb279b01b8b86e"]]},{"id":"2734f7c6cd704d7c","type":"junction","z":"76ab0c3aad64c668","g":"5dd4a83230f373cf","x":1802.592529296875,"y":342.66656494140625,"wires":[["c40101ee33f5a5fd"]]},{"id":"045582548c036ebb","type":"junction","z":"76ab0c3aad64c668","g":"67faeae86ef585a8","x":380,"y":260,"wires":[["b8453a1af1eac10d"]]},{"id":"a3c52370e1e3c91b","type":"junction","z":"76ab0c3aad64c668","g":"67faeae86ef585a8","x":380,"y":300,"wires":[["108881d15cc05277","d18a063fdcace0ab"]]},{"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},{"id":"180989e6b6be69e1","type":"modbus-response","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"","registerShowMax":20,"x":1470,"y":120,"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":1280,"y":100,"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":1510,"y":80,"wires":[]},{"id":"8bf3fd6bab97b524","type":"function","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","name":"Force Charge @ 4.8kW, No Discharge","func":"msg.StorCtl_Mod = \"2\"\n// 0%\nmsg.OutWRte = \"65535\"\n\nmsg.newstate = \"forcechargeonly\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":280,"wires":[["d19deebddbe58f74","f3095d184f17834f"]],"info":"Example 7: Charging with 50% to 100% of the nominal power\nThis behavior can be achieved by limiting the maximum discharge capacity to\n-50% => results in window [1650 W, 3300 W]\n- OutWRte = -50% (set discharge limit of WchaMax to -50%)\n- StorCtl_Mod = 2 (activates discharge limit, bit pattern: 10)\n- InWRte is not relevant in this case\n- Battery status in Fronius Solar.web will change to Forced Recharge"},{"id":"f941ac38c439226e","type":"function","z":"effce8e2e8a9f43c","g":"32f8524788c52a9d","name":"50% kW discharge","func":"\nmsg.StorCtl_Mod = \"3\"\n// + 50%\nmsg.OutWRte = 5000\n// -50%\nmsg.InWRte = \"65485\"\n\nmsg.newstate = \"1kWdischarge\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":790,"y":560,"wires":[["d804b22ae3be2b4e","127b84a81d7204e8"]],"info":"Example 6: Discharging with 50% of the nominal power\nThis behavior can be achieved by limiting the maximum charge capacity to -50%\nand the maximum discharge capacity to 50%\n=> results in window [-1650 W, -1650 W]\n- InWRte = -50% (set charge limit of WchaMax to -50%)\n- OutWRte = 50% (set discharge limit of WchaMax to 50%)\n- StorCtl_Mod = 3 (activate both limit values, bit pattern: 11)"},{"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":790,"y":420,"wires":[["134bc56b2d93918d","cf500d91417561eb"]],"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":"GreenelyPrice","server":"afa7e6c.89d5e18","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.greenely_prices","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":140,"y":160,"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":340,"y":160,"wires":[["cb1a63e7561cc549"],["8bf3fd6bab97b524"]]},{"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":130,"y":80,"wires":[["d5351cdc453ee22e"]]},{"id":"d19deebddbe58f74","type":"debug","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","name":"Inverter MODBUS Response","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1150,"y":260,"wires":[]},{"id":"f3095d184f17834f","type":"modbus-response","z":"effce8e2e8a9f43c","g":"ceea0bd0f56e5cbe","name":"","registerShowMax":20,"x":1110,"y":300,"wires":[]},{"id":"128a17e0b4b42529","type":"debug","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"Inverter MODBUS Response","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1150,"y":60,"wires":[]},{"id":"6e1b23a96a0be05e","type":"modbus-response","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"","registerShowMax":20,"x":1110,"y":140,"wires":[]},{"id":"cb1a63e7561cc549","type":"function","z":"effce8e2e8a9f43c","g":"d4ddcb9085ea730f","name":"InWRte","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":1080,"y":100,"wires":[["beceba7f58b3cb02","6e1b23a96a0be05e","128a17e0b4b42529"]]},{"id":"134bc56b2d93918d","type":"modbus-response","z":"effce8e2e8a9f43c","g":"9d13313687e3f017","name":"","registerShowMax":20,"x":990,"y":440,"wires":[]},{"id":"cf500d91417561eb","type":"debug","z":"effce8e2e8a9f43c","g":"9d13313687e3f017","name":"Inverter MODBUS Response","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1030,"y":400,"wires":[]},{"id":"d804b22ae3be2b4e","type":"debug","z":"effce8e2e8a9f43c","g":"32f8524788c52a9d","name":"Inverter MODBUS Response","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1030,"y":540,"wires":[]},{"id":"127b84a81d7204e8","type":"modbus-response","z":"effce8e2e8a9f43c","g":"32f8524788c52a9d","name":"","registerShowMax":20,"x":990,"y":580,"wires":[]},{"id":"23b92e3a92162b4a","type":"modbus-response","z":"effce8e2e8a9f43c","g":"f84e3a88a392756e","name":"","registerShowMax":20,"x":1070,"y":740,"wires":[]},{"id":"9c1a5de4d5079aa4","type":"debug","z":"effce8e2e8a9f43c","g":"f84e3a88a392756e","name":"Inverter MODBUS Response","active":true,"tosidebar":true,"console":true,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1110,"y":700,"wires":[]},{"id":"4be156af80f1d0d2","type":"function","z":"effce8e2e8a9f43c","g":"f84e3a88a392756e","name":"HOLD (no charge or discharge)","func":"\nmsg.StorCtl_Mod = \"0\"\nmsg.OutWRte = 65535\nmsg.InWRte = 65535\n\nmsg.newstate = \"HOLD state\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":830,"y":720,"wires":[["23b92e3a92162b4a","9c1a5de4d5079aa4","cb1a63e7561cc549"]],"info":"This puts the battery in normal operation.\nMeaningn that it will both charge and discharge to\nits set limits at 100%,\n"},{"id":"0f7bddac0d6e47e9","type":"poll-state","z":"effce8e2e8a9f43c","name":"Volkswagen status","server":"afa7e6c.89d5e18","version":3,"exposeAsEntityConfig":"","updateInterval":"60","updateIntervalType":"num","updateIntervalUnits":"seconds","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":280,"wires":[["afd38d704e49105d"]]},{"id":"34930c36e0d50c0c","type":"poll-state","z":"effce8e2e8a9f43c","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":190,"y":340,"wires":[["afd38d704e49105d"]]},{"id":"afd38d704e49105d","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":390,"y":320,"wires":[["dd104017de06fd0b"],["4be156af80f1d0d2"]]},{"id":"ba19a0ef37ef7dca","type":"debug","z":"76ab0c3aad64c668","g":"ec76d9ae41bde168","name":"GEN24: Inverter Set","active":false,"tosidebar":true,"console":true,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":2340,"y":320,"wires":[]},{"id":"57f9336fd070e990","type":"inject","z":"76ab0c3aad64c668","g":"0ad6a47eabf863af","name":"ExportLimitOFF","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","payload":"","payloadType":"str","x":1360,"y":140,"wires":[["38741f73b2283ba3"]]},{"id":"38741f73b2283ba3","type":"function","z":"76ab0c3aad64c668","g":"0ad6a47eabf863af","name":"100% Max Power","func":"var values = [(10000),(0),(0),(0),(1)];\n\nmsg.payload = { \n    'value': values,\n    'fc': 16,\n    'unitid': 1,\n    'address': 40232,\n    'quantity': 5\n} \n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1510,"y":220,"wires":[["d14dcad7cd72383f","737229fe2974e0cf"]]},{"id":"d14dcad7cd72383f","type":"debug","z":"76ab0c3aad64c668","g":"0ad6a47eabf863af","name":"GEN24: MAX POWA SET","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1670,"y":140,"wires":[]},{"id":"c337fcf0fac93eae","type":"modbus-response","z":"76ab0c3aad64c668","g":"ec76d9ae41bde168","name":"","registerShowMax":20,"x":2330,"y":260,"wires":[]},{"id":"f8e3e969561ea1f7","type":"modbus-flex-write","z":"76ab0c3aad64c668","g":"ec76d9ae41bde168","name":"Fronius-Storage","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"ecd41b68db8d4254","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"10","x":2100,"y":300,"wires":[["c337fcf0fac93eae","ba19a0ef37ef7dca"],["ba19a0ef37ef7dca"]]},{"id":"9677eb7418f50bfe","type":"inject","z":"76ab0c3aad64c668","g":"5dd4a83230f373cf","name":"ExportLimitOn","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","payload":"","payloadType":"str","x":1350,"y":420,"wires":[["7acb279b01b8b86e"]]},{"id":"7acb279b01b8b86e","type":"function","z":"76ab0c3aad64c668","g":"5dd4a83230f373cf","name":"WMaxLim_Ena = 0","func":"msg.payload = { \n    'value': 0,\n    'fc': 6,\n    'unitid': 1,\n    'address': 40236,\n    'quantity': 1\n} \n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1510,"y":340,"wires":[["c15edc748f63bdd9","2734f7c6cd704d7c"]]},{"id":"c15edc748f63bdd9","type":"debug","z":"76ab0c3aad64c668","g":"5dd4a83230f373cf","name":"GEN24: Set Export Limit","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1710,"y":420,"wires":[]},{"id":"bf545c79efb5be6e","type":"comment","z":"76ab0c3aad64c668","g":"dd1ae8afab7bd989","name":"When Positive Feed In - Max Output","info":"","x":1380,"y":80,"wires":[]},{"id":"5b9f73ad2d28291f","type":"comment","z":"76ab0c3aad64c668","g":"dd1ae8afab7bd989","name":"When Negative Feed In - Limit Exports to 0","info":"","x":1400,"y":480,"wires":[]},{"id":"b8453a1af1eac10d","type":"modbus-getter","z":"76ab0c3aad64c668","g":"bc3862a711b0445e","name":"Read_WMaxLimEna","showStatusActivities":false,"showErrors":false,"showWarnings":false,"logIOActivities":false,"unitid":"1","dataType":"HoldingRegister","adr":"40236","quantity":"1","server":"ecd41b68db8d4254","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"","x":780,"y":160,"wires":[["817a3ac03ce24936"],[]]},{"id":"817a3ac03ce24936","type":"switch","z":"76ab0c3aad64c668","g":"bc3862a711b0445e","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"eq","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":990,"y":160,"wires":[["168c0e4cad193ff9"],["8c568a8ffe7f8f39"]]},{"id":"108881d15cc05277","type":"modbus-getter","z":"76ab0c3aad64c668","g":"92b3c15ead4a275d","name":"Read_WMaxLimEna","showStatusActivities":false,"showErrors":false,"showWarnings":false,"logIOActivities":false,"unitid":"1","dataType":"HoldingRegister","adr":"40236","quantity":"1","server":"ecd41b68db8d4254","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"","x":780,"y":360,"wires":[["e98e8be8c28e9b7d"],[]]},{"id":"e98e8be8c28e9b7d","type":"switch","z":"76ab0c3aad64c668","g":"92b3c15ead4a275d","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"num"},{"t":"eq","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":970,"y":360,"wires":[["ad601a7bb224da80"],["9cabe321855fbdb2"]]},{"id":"8c568a8ffe7f8f39","type":"debug","z":"76ab0c3aad64c668","g":"bc3862a711b0445e","name":"GEN24: Already Max","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1040,"y":220,"wires":[]},{"id":"9cabe321855fbdb2","type":"debug","z":"76ab0c3aad64c668","g":"92b3c15ead4a275d","name":"GEN24: Already Limit","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1040,"y":420,"wires":[]},{"id":"d61e75648cf03aa5","type":"comment","z":"76ab0c3aad64c668","g":"dd1ae8afab7bd989","name":"If WMaxLimEna is 0, set it to 1, if 1, then do nothing","info":"","x":850,"y":80,"wires":[]},{"id":"942cab0954a58820","type":"comment","z":"76ab0c3aad64c668","g":"dd1ae8afab7bd989","name":"If WMaxLimEna is 1, set it to 0, if 0, then do nothing","info":"","x":830,"y":480,"wires":[]},{"id":"200bacc074df8cbe","type":"api-current-state","z":"76ab0c3aad64c668","g":"67faeae86ef585a8","name":"GreenelyPrice","server":"afa7e6c.89d5e18","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.greenely_prices","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":180,"y":220,"wires":[["cc52d431205212f2"]]},{"id":"cc52d431205212f2","type":"switch","z":"76ab0c3aad64c668","g":"67faeae86ef585a8","name":"Above 0, or Less Equal to 0","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"0","vt":"num"},{"t":"lte","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":240,"y":280,"wires":[["045582548c036ebb"],["a3c52370e1e3c91b"]]},{"id":"d18a063fdcace0ab","type":"api-current-state","z":"76ab0c3aad64c668","g":"d49b298a20da4cb3","name":"BatteryDischarge","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"500","halt_if_type":"num","halt_if_compare":"gt","entity_id":"sensor.gen24_mppt_module_3_dc_power","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"topic","propertyType":"msg","value":"discharge","valueType":"str"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":130,"y":480,"wires":[[],["093e86667a226569"]]},{"id":"093e86667a226569","type":"api-current-state","z":"76ab0c3aad64c668","g":"d49b298a20da4cb3","name":"Battery Charge Rate Less Than 4500","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"4500","halt_if_type":"num","halt_if_compare":"lt","entity_id":"sensor.gen24_mppt_module_2_dc_power","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":190,"y":560,"wires":[["45fd82b96452fd59"],[]]},{"id":"45fd82b96452fd59","type":"api-current-state","z":"76ab0c3aad64c668","g":"d49b298a20da4cb3","name":"Battery Not Full","server":"afa7e6c.89d5e18","version":3,"outputs":2,"halt_if":"100","halt_if_type":"num","halt_if_compare":"lt","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":420,"y":500,"wires":[[],[]]},{"id":"4db51c0c85952ba4","type":"cronplus","z":"76ab0c3aad64c668","g":"67faeae86ef585a8","name":"1 Min Interval","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output1","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"30 * 5-20 * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":140,"y":140,"wires":[["200bacc074df8cbe"]]},{"id":"479a9cbc4a8364f1","type":"debug","z":"82d61b2ddb027662","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":760,"y":100,"wires":[]},{"id":"6c0bec9257e8a35c","type":"modbus-response","z":"82d61b2ddb027662","name":"","registerShowMax":20,"x":790,"y":40,"wires":[]},{"id":"0f3f8144fdb342a6","type":"cronplus","z":"82d61b2ddb027662","name":"1 Min Interval","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"30 * 5-23 * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":160,"y":80,"wires":[["7b66a52b51a5a4ac"]]},{"id":"2c660a19252258df","type":"debug","z":"82d61b2ddb027662","g":"67f3f6554cd2fe41","name":"GEN24: Inverter Set","active":false,"tosidebar":true,"console":true,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":460,"y":400,"wires":[]},{"id":"678adc0348f546d3","type":"modbus-response","z":"82d61b2ddb027662","g":"67f3f6554cd2fe41","name":"","registerShowMax":20,"x":450,"y":340,"wires":[]},{"id":"ed79a132110622ab","type":"modbus-flex-write","z":"82d61b2ddb027662","g":"67f3f6554cd2fe41","name":"Fronius-Storage","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"ecd41b68db8d4254","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"10","x":220,"y":380,"wires":[["678adc0348f546d3","2c660a19252258df"],["2c660a19252258df"]]},{"id":"7b66a52b51a5a4ac","type":"function","z":"82d61b2ddb027662","name":"Force Charge @ Max, No Discharge","func":"msg.StorCtl_Mod = \"2\"\nmsg.OutWRte = \"60486\"\nmsg.InWRte = 5000\n\nmsg.newstate = \"forcechargeonly\"\n\nreturn msg","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":470,"y":80,"wires":[["7c1c7d833e308cbc","6c0bec9257e8a35c","479a9cbc4a8364f1"]]},{"id":"7c1c7d833e308cbc","type":"function","z":"82d61b2ddb027662","name":"InWRte","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":380,"y":140,"wires":[["ed79a132110622ab","c06cf8115a809b2b","1c418f6f8269ddcd"]]},{"id":"1c418f6f8269ddcd","type":"debug","z":"82d61b2ddb027662","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":760,"y":220,"wires":[]},{"id":"c06cf8115a809b2b","type":"modbus-response","z":"82d61b2ddb027662","name":"","registerShowMax":20,"x":790,"y":160,"wires":[]}]
1 Like

Since it didn’t fit this thread, I have started a new one here which my remaining tasks with this whole setup:

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