Battery SOC Forecaster

Hello - I am wondering what people are using, or approaches people may have tried/used around forecasting battery level. I am referring to a configuration where:

  • A smart meter/inverter is reporting total (load) usage to home-assistant. In my instance I utilise the Sungrow-SHx-Inverter-Modbus-Home-Assistant with my SH10RT - 3 Phase system
  • A battery reporting current state of charge to home-assistant. In my instance again using the Sungrow integration with a 25.6kWh battery.
  • A solar system and a solar forecasting system (I use the HA Solcast Solar integration).

My system of monitoring is working well, my solar forecast is sensible, my battery and inverter are integrating into home-assistant, but to scratch that itch further, I’m interesting in forecasting not just solar - but simulating how my battery might discharge overnight and recharging during the following day(s). The use case for this is to potentially delay or make decisions around whether to say use my washing machine today, or air-conditioner early, knowing that my battery might not recharge fully tomorrow, it would help me better understand the system and down the line would potentially be used to set/limit forced discharge when the feed-in-tariff is high.

To date, I have been playing with a custom Python script that:

  • Reads in the previous 7-days of energy usage, groups the usage into 30-minute intervals (as this is the interval Solcast produces), and then calculates the mean and standard-deviation for each time-interval.
  • Similarly, while making some (not statistically valid) assumptions using Solcasts 10th, 50th (assumed) and 90th percentile forecasts, estimating a statistical distribution for power at each time-interval.
  • Because generation and consumption are independent, I thought sampling each distribution 10,000 times and then determining 10,000 potential net energy values (10,000 produced solar estimates less 10,000 consumed energy estimates). These 10,000 net energy values could then be analysed to extract say the 10th / 50th / 90th percentiles for each time-interval and therefore be used to simulate a battery…(?)
  • Currently this pushes a forecast (similar to solcast using a date-stamped attribute with values) to home-assistant through a push/http request, but I am looking to transition this to MQQT(?) or another format so that the output is cached/saved in case HASS Restarts (push requests don’t seem to have saved history/states).
  • The python script simply executes on my raspberry pi every hour using cron.

Using this forecast, I then have a sensor inside home-assistant via a template that:

  • Reads the current battery state of charge in kWh
  • Calculates for the next 30-minute, the potential battery level based on the 10th/50th/90th net energy values.
  • Loops forward over the next 30-minute interval using the previously predicted 10th/50th/90th battery level.
  • Builds a time-series/forecast of state of charge

The python script and sensor seems to be functioning, e.g,:
Daily cumulative solar forecast actuals vs forecast (10th/90th bands) as an output from the python code (not Solcast)

  • Additional graphs in comment, new user limitation… *

Some things i’m thinking about:

  • Statistics isn’t my strong suit, but by say, using the 10th percentile net energy to calculate the 10th percentile battery level, then iterating that always using the 10th (or the 90th…), is a compounding assumption. There must be a better way to handle this in selecting an appropriate distribution to sample.
  • Is this better done not in python externally, so that the 10,000 sample approach could be done for the battery?
  • What is the most logical way to process the daily data and resample the generation, at the moment I am calculating the energy step every 30minutes and doing the statistics on that - ensemble statistics. Is there a more robust way to do the statistics on the daily cumulative and then process it back to intervals?
  • It would be cool to be able to use this to forecast export (or import) as well, so that a power chart (like below - could be adapted to include the power distribution forecast. Once all the kinks and statistics are ironed out.

Anyway - hoping to hear what others have tried or some thoughts and suggestions on this. I’m new to python but happy to share code or sensors etc., if that’s of interest to anyone! Cheers!

Daily cumulative energy forecast actuals vs forecast (10th/90th bands) with historical 7d values in grey. I have a daylight saving time error on my daily data so ignore the 1-hour offset. Also a very low energy day!

Here’s the output, application for the battery simulator, showing the historical/current state of charge and then the forecasted levels for today through and tomorrow. The red-dash is the best estimate (50th) and the bars indicate the range using the other percentiles. Grey lines indicate the previous 7-days. (We had a longer solar day than the previous few days coupled with low usage, so the battery went into the evening higher than normal)

… and here’s the power card to add the forecast to:

This is interesting — you’ve basically described one of the reasons I started developing AION EMS Zeus for Home Assistant. :slightly_smiling_face:

Your approach of combining historical household demand, solar forecast uncertainty and current battery SOC to project a range of possible future SOC trajectories makes a lot of sense to me.

One thing I’ve found while developing Zeus is that the difficult part isn’t producing a battery forecast — it’s knowing whether that forecast was actually any good.

Zeus now works around a similar loop:

Observe → Learn → Predict → Recommend → Verify → Improve

It learns household demand from Recorder history, uses solar/weather forecast evidence, knows usable battery capacity, SOC and real charge/discharge limits, accounts for learned battery round-trip efficiency and tariffs, and produces an advisory future battery plan.

We recently added a Forecast Explorer specifically to compare the forecast with what actually happened afterward, including forecast error/uncertainty. Zeus deliberately keeps the original prediction so it can be evaluated later rather than quietly replacing yesterday’s forecast with today’s knowledge.

Your 10th/50th/90th percentile idea is particularly interesting. I’ve been moving Zeus in the same direction of showing an expected result together with an uncertainty range rather than pretending a single SOC prediction is certain.

At the moment Zeus keeps battery planning recommendation-only — it doesn’t automatically force-charge/discharge the inverter — because I want the prediction/verification evidence to mature before allowing that intelligence to control hardware.

If you feel like experimenting, have a look at AION EMS Zeus. Your Sungrow SH10RT + 25.6 kWh battery + Solcast setup would actually be a very interesting system to test it against, especially because a battery that size makes multi-day SOC forecasting genuinely useful.

And I’d be interested to compare Zeus’s learned demand/forecast behaviour against the Monte Carlo approach you’ve already built. That’s exactly the kind of real-world comparison that can improve the project.