Growatt Inverter Mode Switch

That could be good. Although I also like the idea of giving it a failsafe that it controls itself. The API doesn’t always seem to respond first time, so im going to look at processing the response codes. It may be useful to supply a command status / retry routine if it keeps failing.

Firstly: Its my first dab in this area. I have made all my automation and logic in node-red, so I’m trying to find my way here.

I got appdeamon running and your scripts copied in:
2022-05-26 19:32:28.331612 INFO AppDaemon: App 'set_discharge_rate' added 2022-05-26 19:32:28.333537 INFO AppDaemon: App 'set_charge_rate' added 2022-05-26 19:32:28.334757 INFO AppDaemon: App 'get_discharge_rate' added

A couple of warnings:
2022-05-26 19:32:30.360612 WARNING AppDaemon: No app description found for: /config/appdaemon/apps/growattServer.py - ignoring
2022-05-26 19:32:30.375042 WARNING set_discharge_rate: set_discharge_rate: Entity input_button.house_battery_set_discharge_rate_button not found in namespace default
2022-05-26 19:32:30.377569 WARNING set_charge_rate: set_charge_rate: Entity input_button.house_battery_set_charge_rate_button not found in namespace default
2022-05-26 19:32:30.380032 WARNING get_discharge_rate: get_discharge_rate: Entity input_button.house_battery_get_discharge_rate_button not found in namespace default

Seems Im missing the entity input_button.house_battery_get_discharge_rate_button. Is that a helper or part of some yaml you have created in home-assistant?

My biggest problem is that I don’t know how to access the functionality in the scripts. Im guessing that the scripts can be called from home-assistant with an argument and execute the command on the server and return some sort of status.

How have you integrated the functionality in home-assistant?

I added three helper buttons:

  • house_battery_set_discharge_rate_button
  • house_battery_set_charge_rate_button
  • house_battery_get_discharge_rate_button

And appdeamon starts without errors :smile:
So far so good - now off to figure out how to get the apps to execute. Any pointer?

When I get I running, I will do a little write up to ease the process for others.

Great work!

I’ll write some of this up on GitHub this weekend too! Finally my working week is done!

So, how I’ve got the code to run is for AD to have a listener within the initialize function to watch for the change of state of a button entity in HA. I chose to do this via an input button helper. I’ve got three of these, as I’ve been playing with different ways of doing a UI for it. I’m not sure all of these will stick.

This bit of the code is the listener. Also note that self.get_inverter_settings is what’s triggered when the button is pressed.

def initialize(self):
    self.listen_state(self.get_inverter_settings, "input_button.house_battery_get_discharge_rate_button")

Similarly in reverse, when data comes back to self.response i’ve used a template to pull out the value and put it into a sensor state. If I remember correctly, these sensors are created by AD, so they will not exist until they’re filled with data. I should probably convert these to normal sensors / helpers and set the state of those instead.

self.set_state("sensor.battery_charge_time1_start", state = self.response['obj']['mixBean']['forcedChargeTimeStart1'], attributes = {"friendly_name": "Charge Time 1 Start"})

It took me a while to find the right way to find the right template for the JSON, but it helped to call the code from a python3 prompt in bash and see the raw output. The more basic examples on the original server code were helpful on this :slight_smile:

This is the type of UI I’ve been thinking about.

  1. List of sensors that HA knows about
  2. Easy time adjustment (maybe need a reset button to get back to my overnight rate). These are desired times and different to those mentioned in 1.
  3. Get settings toggle button to pull the latest data from the growatt server
  4. Push settings, will set new charge settings according to the desired time. I’m hoping to eventually toggle the enabled/disabled value every time push settings is pressed.
  5. A toggle for Max SoC charge, which changes by 10% (from 60-100%) every time it’s pressed.

Great work! Thanks a lot!!!

I got it working after adding the missing helpers:

Helper datetime:
growatt_start_time

Helper dropdown
input_select.growatt_charge_final_soc
(add relevant charge percentages)

Helper boolean
growatt_force_charge_on

My plan is to create some logic that evaluates the estimated solar production and energy price and charge based on that. eg: If solar < XX kwHr AND energy price < YY THEN charge. This will need a bit of thought to work well.
I have a sensor that picks up prices from NordPool by the hour. This would then run full auto once every hour.

This is really good :smile: Here is my first iteration on controlling it. I’m using Node-Red. Interface looks like this:
image

Grid charge enabled is just to monitor the state on the server - updated when state is changed.
Charge_Battery is a manual switch and also an indicator of the state. When switched it calls “growatt_force_charge_on” waits 5 sec and then calls “house_battery_get_discharge_rate_button”.
Charge Time 1 Start = 00:00
Charge Time 1 Stop = 23:59
This allows node-red and home-assistant to run the timer logic and I only need to call “growatt_force_charge_on” to start charging.

Charge_timer_on_off turns the timer automation on and off
Start and Stop sliders are used to set time on a simple hour basis. Electricity prices are set per hour on the NordPool Exchange and the sliders are the fastest way.

Charge automation will be used to turn on/off automatic charge control based on the lowest day price - but I’m not there yet.

To work it needs the following helpers in HA:
Charge_end_time - number, slider
Charge_start_time - number, slider
charge_timer_on_off - toggle
charge_automation_on_off - toggle

Flow from node-red:

[{"id":"a8b6b9981e2da679","type":"tab","label":"Charger","disabled":false,"info":"","env":[]},{"id":"d6182880cb2b7ae9","type":"comment","z":"a8b6b9981e2da679","name":"Turning Growatt AC chage on/off","info":"","x":130,"y":40,"wires":[]},{"id":"f4e21e20c9ebca29","type":"inject","z":"a8b6b9981e2da679","name":"Inject time","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":false,"onceDelay":"","topic":"CurrentTime","payloadType":"date","x":130,"y":320,"wires":[["90d13b8b5340cee0"]]},{"id":"fa09d576d633a447","type":"switch","z":"a8b6b9981e2da679","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"start_charge_time","vt":"global"},{"t":"eq","v":"stop_charge_time","vt":"global"}],"checkall":"true","repair":false,"outputs":2,"x":730,"y":320,"wires":[["87319ace7b99bdee"],["a420c3f4803b23dc"]]},{"id":"90d13b8b5340cee0","type":"moment","z":"a8b6b9981e2da679","name":"","topic":"","input":"","inputType":"msg","inTz":"Europe/Copenhagen","adjAmount":0,"adjType":"days","adjDir":"add","format":"HH","locale":"C","output":"","outputType":"msg","outTz":"Europe/Copenhagen","x":360,"y":320,"wires":[["96ea7351eddf8dac"]]},{"id":"d62edeaeb38c7ca8","type":"server-state-changed","z":"a8b6b9981e2da679","name":"læs starttid fra ui","server":"785585e5.21e4ec","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_number.charge_start_time","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":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":120,"y":140,"wires":[["3bb55aeb5ebc2696"]]},{"id":"e8982f41a2133138","type":"server-state-changed","z":"a8b6b9981e2da679","name":"læs sluttid fra ui","server":"785585e5.21e4ec","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_number.charge_end_time","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":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":120,"y":200,"wires":[["c23ad9a67ba7e56d"]]},{"id":"6c7915f3c4e7f614","type":"debug","z":"a8b6b9981e2da679","name":"1","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":510,"y":940,"wires":[]},{"id":"a14e4f8dba1a205b","type":"change","z":"a8b6b9981e2da679","name":"","rules":[{"t":"set","p":"stop_charge_time","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":620,"y":200,"wires":[[]]},{"id":"dd64ebc25c40287d","type":"change","z":"a8b6b9981e2da679","name":"","rules":[{"t":"set","p":"start_charge_time","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":620,"y":140,"wires":[[]]},{"id":"96ea7351eddf8dac","type":"api-current-state","z":"a8b6b9981e2da679","name":"Is timer on?","server":"785585e5.21e4ec","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_boolean.charge_timer_on_off","state_type":"str","blockInputOverrides":false,"outputProperties":[],"for":0,"forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":570,"y":320,"wires":[["fa09d576d633a447"],[]]},{"id":"e9de28bfaa953647","type":"debug","z":"a8b6b9981e2da679","name":"3","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":690,"y":1000,"wires":[]},{"id":"6b4758c88b69ce4d","type":"debug","z":"a8b6b9981e2da679","name":"4","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":490,"y":1000,"wires":[]},{"id":"81d97675c4bf33df","type":"api-call-service","z":"a8b6b9981e2da679","name":"","server":"785585e5.21e4ec","version":5,"debugenabled":false,"domain":"input_button","service":"press","areaId":[],"deviceId":[],"entityId":["input_button.house_battery_set_charge_rate_button"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":830,"y":480,"wires":[["11121fb5668172ad"]]},{"id":"2c7185e6a72d2cc5","type":"delay","z":"a8b6b9981e2da679","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":660,"y":480,"wires":[["81d97675c4bf33df"]]},{"id":"3e6fecfa13e474f0","type":"api-call-service","z":"a8b6b9981e2da679","name":"","server":"785585e5.21e4ec","version":5,"debugenabled":false,"domain":"input_boolean","service":"turn_on","areaId":[],"deviceId":[],"entityId":["input_boolean.growatt_force_charge_on"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":420,"y":440,"wires":[["2c7185e6a72d2cc5"]]},{"id":"d628ed899738498e","type":"api-call-service","z":"a8b6b9981e2da679","name":"","server":"785585e5.21e4ec","version":5,"debugenabled":false,"domain":"input_boolean","service":"turn_off","areaId":[],"deviceId":[],"entityId":["input_boolean.growatt_force_charge_on"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":420,"y":500,"wires":[["2c7185e6a72d2cc5"]]},{"id":"3bb55aeb5ebc2696","type":"function","z":"a8b6b9981e2da679","name":"afrunding","func":"msg.payload = msg.payload >> 0\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":140,"wires":[["dd64ebc25c40287d"]]},{"id":"c23ad9a67ba7e56d","type":"function","z":"a8b6b9981e2da679","name":"afrunding","func":"msg.payload = msg.payload >> 0\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":200,"wires":[["a14e4f8dba1a205b"]]},{"id":"1d099ff23d9c61c0","type":"api-call-service","z":"a8b6b9981e2da679","name":"Update status","server":"785585e5.21e4ec","version":5,"debugenabled":false,"domain":"input_button","service":"press","areaId":[],"deviceId":[],"entityId":["input_button.house_battery_get_discharge_rate_button"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1160,"y":480,"wires":[[]]},{"id":"11121fb5668172ad","type":"delay","z":"a8b6b9981e2da679","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":1000,"y":480,"wires":[["1d099ff23d9c61c0"]]},{"id":"4493dbd66a8e0d12","type":"ha-entity","z":"a8b6b9981e2da679","name":"Charge_Battery","server":"785585e5.21e4ec","version":2,"debugenabled":false,"outputs":2,"entityType":"switch","config":[{"property":"name","value":"Charge_Battery"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:battery-charging-100"},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"payload","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":true,"outputPayload":"","outputPayloadType":"jsonata","x":180,"y":460,"wires":[["3e6fecfa13e474f0"],["d628ed899738498e"]]},{"id":"87319ace7b99bdee","type":"api-call-service","z":"a8b6b9981e2da679","name":"","server":"785585e5.21e4ec","version":5,"debugenabled":false,"domain":"switch","service":"turn_on","areaId":[],"deviceId":[],"entityId":["switch.charge_battery"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":940,"y":300,"wires":[[]]},{"id":"a420c3f4803b23dc","type":"api-call-service","z":"a8b6b9981e2da679","name":"","server":"785585e5.21e4ec","version":5,"debugenabled":false,"domain":"switch","service":"turn_off","areaId":[],"deviceId":[],"entityId":["switch.charge_battery"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":940,"y":340,"wires":[[]]},{"id":"e3159f9d7f5a6481","type":"comment","z":"a8b6b9981e2da679","name":"Timer - read from UI using helpers","info":"","x":180,"y":100,"wires":[]},{"id":"6ff6e2a9a06da8a5","type":"comment","z":"a8b6b9981e2da679","name":"Timer automation - checks every minut","info":"","x":190,"y":280,"wires":[]},{"id":"925b1977f3f9d746","type":"comment","z":"a8b6b9981e2da679","name":"Switch - manual and called from timer","info":"","x":190,"y":400,"wires":[]},{"id":"a9642f818802c937","type":"comment","z":"a8b6b9981e2da679","name":"Automatic charging logic (in progress)","info":"","x":190,"y":680,"wires":[]},{"id":"2a24649745724576","type":"inject","z":"a8b6b9981e2da679","name":"Inject time","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":false,"onceDelay":"","topic":"CurrentTime","payloadType":"date","x":150,"y":780,"wires":[["c59586f817628d23"]]},{"id":"c59586f817628d23","type":"api-current-state","z":"a8b6b9981e2da679","name":"Is charge automation on?","server":"785585e5.21e4ec","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_boolean.charge_automation_on_off","state_type":"str","blockInputOverrides":false,"outputProperties":[],"for":0,"forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":370,"y":780,"wires":[["fe9c3ea0432642f3"],[]]},{"id":"fe9c3ea0432642f3","type":"api-current-state","z":"a8b6b9981e2da679","name":"Todays solar < 10 kwh","server":"785585e5.21e4ec","version":3,"outputs":2,"halt_if":"10","halt_if_type":"num","halt_if_compare":"lte","entity_id":"sensor.energy_production_today","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":620,"y":780,"wires":[[],[]]},{"id":"fe800241f1368faa","type":"comment","z":"a8b6b9981e2da679","name":"To be:logic for picking low price time","info":"","x":960,"y":780,"wires":[]},{"id":"74477df3f7b1be7d","type":"comment","z":"a8b6b9981e2da679","name":"Calls Charge_Battery in next line","info":"","x":1170,"y":320,"wires":[]},{"id":"e47ed72ef7f5e02c","type":"debug","z":"a8b6b9981e2da679","name":"2","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":690,"y":940,"wires":[]},{"id":"785585e5.21e4ec","type":"server","name":"Home Assistant","version":1,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false,"cacheJson":true}]

An addition to the interface and function: Show energy prices and control charging based on price. Charge automation has to be on for price based charging to start.

.

It seems the new growatt status is not always returned, even with a 5 sec delay. Im considering a loop that checks that status and press update if it seems wrong.

1 Like

Hello
How did you integrated te inverter mode switch in HA? Is there a link to the documentation or description?
This is really the solution I’ve been looking for for 6 months.
I can get into a pilot project with dynamic pricing and this piece was still missing.
Thanks

Functionality is certainly possible, however it is somewhat more complicated than a nice integration would provide. It also needs a bit more thought than a simple switch (i.e. time periods need to be included). It also doesn’t work when the Growatt server is down.

If you have a read of above, Kasper and I have set out some hints, however there is some coding involved to meet your own needs.

This is great!

Just started to work with my hybrid inverter+battery and Home Assistant and this is close to what i want.

Did a few templates to check if current hour has lowest (or second, third,… lowest) price Nordpool.
Also to see if the difference between lowest<>highest price is big enough to charge and discharge based on this data.

But i have no integration to execute the Growatt schedule, maby this can help me. I will give it a try if there is no HA integration to use straight off?

And, do you have a complete example of how you did that UI in HA? I now can run python scripts, but that’s where it stop :slight_smile:

Hi Kasper

How did you get the data from the data from Growatt → AppDeamon → Home Assistant?

I use the Growatt integration in HA to get data on load, battery state of charge etc.

Data on charge status and changing charge status (telling the inverter to charge) is through app deamon.

I don’t have a description of the UI. I use node-red (image and code above) to control when to start and stop charging.
The entities used in node-red are then displayed and controlled from the UI in HA.

1 Like

Hi, @KasperEdw , would it be possible for you to offer a how to? Im a novice (literally installed Home assistant today)

I have the HA running and installed Growatt extension but thats as far as ive got. I would love to be able to set to bat first for example. I was even hoping to somehow trigger from the wholesale price of elec API.

thanks in advance

Hi there,

First of all - credits to @mjdyson, @KasperEdw, @muppet3000 and @indykoning for providing all the important pieces of the actual code. I too wanted to automate the charging of my Growatt battery, and without their work I wouldn’t be able to achieve that.

For the benefits of others in a similar situation, this is how I combined the different pieces together for my nightly routine (I am using HA running in Docker on Synology NAS):

  1. Installed AppDaemon and configured so it listens to my HA instance. I run AppDaemon in Docker, alongside my HA instance. AppDaemon with Docker — AppDaemon 4.2.1 documentation

  2. Deployed growattServer.py and set_charge_rate.py from mjdyson/ad-growatt (github.com) into …\appdaemon\conf\apps.

  3. Made sure that growattServer.py is referring to the right server URL; Growatt seems to have been switching between https://server.growatt.com/ and https://server-api.growatt.com/ recently.

  4. Next I modified the set_charge_rate.py module, so it better suited my needs (I wanted to call the set_charge_rate routine as a service from HA, only setting the Stop charging SoC %):

import growattServer
import appdaemon.plugins.hass.hassapi as hass

SET_CHARGE_RATE = 'SET_CHARGE_RATE'


class HouseBatteryCharge(hass.Hass):

  def initialize(self):
    self.listen_event(self.set_charge_rate, SET_CHARGE_RATE)


  def set_charge_rate(self, event, data, kwargs):

    stop_battery_soc = str(data['stop_battery_soc'])
...

Plus I added logging in various places of the ‘set_charge_rate’ function and made the #Stop charging SoC % the only variable in self.schedule_settings. I didn’t need any other variables, my charging time window is fixed by the cheaper night tariff provided by my energy supplier.

  1. The final piece of AppDaemon config was adding this entry into …\appdaemon\conf\apps\apps.yaml
set_charge_rate:
  module: set_charge_rate
  class: HouseBatteryCharge
  1. Then I configured HA to call my AppDaemon app - this 3-part blog was absolutely essential to understand how to do that: AppDaemon, next level home automation | Medium

  2. As a result, I added this entry into my HA scripts.yaml:

set_charge_rate:
  alias: Growatt Battery - Set Charge Rate
  sequence:
    - event: SET_CHARGE_RATE
      event_data:
        stop_battery_soc: "{{ stop_battery_soc }}"    
  1. Finally, in HA I configured a nightly automation which looks at the solar energy production forecast and then calls the script service (and passes the Stop charging SoC % as a variable), which then triggers the event, which AppDaemon is listening to and which then finally runs the set_charge_rate app. How to call the service and pass the variable:
- service: script.set_charge_rate
  data:
  stop_battery_soc: 70

Because the Growatt servers have been somewhat unreliable recently (even in the ShinePhone app I often get ‘Network Error’ and have to try several times to get the actual status), the automation makes the call twice (could be more frequently, if it runs OK it completes within 5 seconds). For ref, the complete automation logic:

alias: Set solar battery charging rate
description: ""
trigger:
  - platform: time
    at: "20:00:00"
condition: []
action:
  - repeat:
      count: 2
      sequence:
        - if:
            - type: is_energy
              condition: device
              device_id: 5c6093279048b524c3282a0040c49398
              entity_id: sensor.energy_production_tomorrow
              domain: sensor
              below: 10
              above: 0
          then:
            - service: script.set_charge_rate
              data:
                stop_battery_soc: 100
        - if:
            - type: is_energy
              condition: device
              device_id: 5c6093279048b524c3282a0040c49398
              entity_id: sensor.energy_production_tomorrow
              domain: sensor
              below: 20
              above: 10
          then:
            - service: script.set_charge_rate
              data:
                stop_battery_soc: 70
        - if:
            - type: is_energy
              condition: device
              device_id: 5c6093279048b524c3282a0040c49398
              entity_id: sensor.energy_production_tomorrow
              domain: sensor
              below: 30
              above: 20
          then:
            - service: script.set_charge_rate
              data:
                stop_battery_soc: 60
        - if:
            - type: is_energy
              condition: device
              device_id: 5c6093279048b524c3282a0040c49398
              entity_id: sensor.energy_production_tomorrow
              domain: sensor
              above: 30
          then:
            - service: script.set_charge_rate
              data:
                stop_battery_soc: 30
        - delay:
            hours: 0
            minutes: 1
            seconds: 0
            milliseconds: 0
mode: single

The sensor.energy_production_tomorrow is from Forecast.Solar integration.

Hope it helps!

PS I also run my own Grott instance, so have been wondering if it wouldn’t be more reliable to run the set_charge_rate against that. Not sure though whether is also listening to calls, or just forwarding calls from the inverter to growatt servers. I reckon it should be the former, but not sure.

1 Like

Thanks for sharing, this is really cool, especially as a HA integration.
I completely forgot this forum/chain existed for feature requests for Growatt.

I actually implemented some very similar functionality myself which you can find here: GitHub - muppet3000/growatt-weather-based-charger: A tool for configuring overnight charging (i.e. during off-peak periods) for Growatt inverters that have storage capacity (batteries) based on the predicted solar generation for the day it’s also available as a docker image that can be run as well.

My implementation took into account the maximum charging rate of the batteries as well i.e. if you can only fill them at 3kw, then the rest will be shoved out the door etc. etc.

Either way, it’s all really cool, just wanted to share my implementation (even if it sits completely outside of the home-assistant domain).

1 Like

Thanks for sharing too. I have something similar in mind (with two EVs in the mix), so thanks for the inspiration!

Hi guys

I am very interested in being able to switch my growatt SPH 3600 inverter on/off in HA and also be able to automate when the battery is charging from the grid.

I tried to follow the guide from @martinm, but unfortunately I cant make it work.

I’m not very skilled at all this, can anyone help me out with a more “simple” guide for newbies?

Thank you very much and great job!

Hi @kassand, how far did you get?