Sunday, November 16, 2025

FoxESS and Octopus Energy in Home Assistant without Modbus

I have Octopus Intelligent Go for my electicity tariff, which has a cheap rate at night, but can also have a variable rate during the day if it deems that certain times are good for charging your EV car. I have a FoxESS solar generation system with batteries. However there are times when charging my car that it drains these batteries and I wanted to ensure the car charging came from the grid instead.

I found Home Assistant and got an instance setup in a VirtualBox VM on an Intel NUC. I won't go through all of the details of that, but there are integrations for Octopus and for FoxESS. However, most of the advice involves installing a modbus device on your inverter. That isn't really practical for my outdoor inverter (I couldn't run a huge cable, and had no power nearby to install a wifi dongle).

However, the Open API from FoxESS allows for setting the battery min soc.

And I have just now found a way to use curl from a shell command within Home Assistant to set the SOC, and then create some automations based on Octopus Energy's Intelligent Go rates. As a Home Assistant n00b, I'll call out the steps I went through (prettier printing of the code here):

1) In the File Editor addon, create the shell script below.

I put mine in a new folder: /shell_scripts/foxess_set_soc.sh.

Be sure to replace the APIKEY and SN values with your own.

Note that this needs to go in the config folder, which is wherever your configuration.yaml is, which for me in File Editor is /homeassistant/.

#!/bin/bash # Usage: ./foxess_set_soc.sh <min_soc> <min_soc_on_grid> # Example: ./foxess_set_soc.sh 20 10 if [ $# -ne 2 ]; then echo "Usage: $0 <min_soc> <min_soc_on_grid>" echo "Example: $0 20 10" exit 1 fi MIN_SOC="$1" MIN_SOC_GRID="$2" APIKEY="YOUR KEY HERE FROM FOXESS CLOUD" URL_PATH="/op/v0/device/battery/soc/set" BASE_URL="https://www.foxesscloud.com" SN="YOUR INVERTER ID" # Correct millisecond timestamp (Python guarantees correctness) TIMESTAMP=$(python3 - <<EOF import time print(int(time.time() * 1000)) EOF ) # Signature uses *literal* \r\n (not actual CRLF) SIGN_STRING="${URL_PATH}\\r\\n${APIKEY}\\r\\n${TIMESTAMP}" # MD5 of literal text SIGNATURE=$(printf "%s" "$SIGN_STRING" | md5sum | awk '{print $1}') echo "DEBUG:" echo " TIMESTAMP: $TIMESTAMP" echo " SIGN_STRING literal: [$SIGN_STRING]" echo " SIGNATURE: $SIGNATURE" echo "" # JSON Body JSON_BODY=$(cat <<EOF { "sn": "${SN}", "minSoc": ${MIN_SOC}, "minSocOnGrid": ${MIN_SOC_GRID} } EOF ) echo "Sending request..." curl -X POST "${BASE_URL}${URL_PATH}" \ -H "Content-Type: application/json" \ -H "token: ${APIKEY}" \ -H "signature: ${SIGNATURE}" \ -H "timestamp: ${TIMESTAMP}" \ -H "lang: en" \ -d "$JSON_BODY" -v echo "Request completed."

2) Using the Advanced SSH & Web Terminal addon you need to do a few things:

  • Disable protected mode in the addon's settings
  • Type this at the terminal prompt so we can test the script: docker exec -it homeassistant bash
  • Then navigate to the shell_scripts folder and make the script executable (once): chmod -x foxess_set_soc.sh
  • Then any time you paste in code in File Editor, run this in terminal to fix the line endings: dos2unix foxess_set_soc.sh
  • Then you can run it to test it: ./foxess_set_soc.sh 100 100
  • You can verify in the FoxESSCloud app or website that the battery reserve capacity and system min soc were changed to 100. You can run the script again to change the numbers back again.

3) In File Editor, add this shell command to your configuration.yaml:

# Custom shell command script to call FoxESS via web to set min soc of batteries shell_command: foxess_set_soc: bash /shell_scripts/foxess_set_soc.sh {{ soc }} {{ soc_on_grid }}

4) In the Home Assistant UI (Settings > Automations > Scripts), create two scripts:

To start charging:

data: soc: 100 soc_on_grid: 100 action: shell_command.foxess_set_soc

To stop charging:

data: soc: 20 soc_on_grid: 10 action: shell_command.foxess_set_soc

5) Create an automation to call the script, e.g. when electricity rate is cheap

For example, I use Octopus Intelligent Go, so using the current rate electricity entity as the trigger, when is is <0.15 I have an action to call my 'start charging' script above. And then another automation when >0.15 to call 'stop charging'.

I'm sure there are some others I could add for free sessions too, but I've not got that far.

6) Restart Home Assistant

You're done! This all relies on FoxCloud, but avoids the need for a modbus to be installed.