This is really good Here is my first iteration on controlling it. I’m using Node-Red. Interface looks like this:
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}]