Solar Energy Management (SEM) — Smart solar + EV + battery orchestration

Thanks — and both of these are good catches, one of which was a documentation failure on my side.

1. Hiding what you don’t have. You’re right that this is worse than it should be. select.sem_battery_mode = Off means “SEM keeps its hands off” — it doesn’t mean “this install has no battery”, and there’s currently no way to say the second thing. So you get entities and a dashboard tab for hardware you don’t own, plus exactly the EV-battery-vs-home-battery ambiguity you describe.

I’ve opened #857 for it. The shape I want is derived, not another switch: an install with no battery source configured shouldn’t create battery entities or a Battery tab at all, same for the heat pump — while the Configuration tab keeps everything, always, because that’s where you’d go to say “I have one now”. Adding a “hide it” toggle to reduce the option surface would be self-defeating.

In the meantime you can disable individual entities in Settings → Devices & Services → Entities (filter sem_battery), and remove the tab from the dashboard — SEM won’t fight you on either.

One thing already fixed: the 5 kWh minimum on battery capacity was a bug — the same setting was declared twice with different ranges. In 2.0 it’s 1–100 kWh.

2. The missing charge mode — this one is my fault for not documenting it. Solar + cheapest hours is hidden unless a dynamic tariff is configured. It’s deliberate: without live prices the mode has no cheap hours to find and would quietly behave like Solar only, so SEM doesn’t offer an option it can’t honour. Set Configuration → Tariff → Dynamic with a price entity and it appears. The other four modes are always there.

That rule existed in the code and nowhere in the docs. The USER_GUIDE now explains it.
switch.sem_night_charging and switch.sem_smart_night_charging are genuinely gone — removed in v1.6.3. Night charging is now carried by the Charge mode itself (select.sem_charger_<id>_charge_mode), and the “smart” part — the SOC/forecast/temperature checks before committing to an overnight charge — is implied by the Solar + cheapest hours and Min + Solar modes rather than being a separate toggle. The guide mentions the removal, but clearly not prominently enough if you went looking for the switches; I’ve made that more explicit too.

You’re on 1.7.5 — 2.0 is worth the upgrade for the settings work alone (every setting now has an explanation, and the ranges are declared once so the 5 kWh class of bug can’t recur).

1 Like

Thanks for the detail — that’s enough to say what’s happening.

Why it wasn’t detected. SEM recognises a go-eCharger through the integration that publishes the entities, not by guessing from entity names. It knows two: the HACS goecharger_mqtt integration (syssi/homeassistant-goecharger-mqtt) and goecharger_api2. For either, detection is automatic — it picks up the plug sensor, the power sensor, the amp number for current control and the frc select for start/stop.

If your go-e entities come from plain HA MQTT instead (manual MQTT config or MQTT discovery), their integration is mqtt — which is a transport, not a brand. SEM deliberately doesn’t guess a brand from it, because “this install has MQTT” says nothing about what’s on the other end. That’s almost certainly your case, and it also explains the dryer: with no charger recognised, SEM fell back to the Energy Dashboard’s individual devices and took the largest energy meter it found.

Two ways to fix it, both fine.

Option A — install the HACS go-eCharger MQTT integration (syssi’s, linked above), point it at your broker, then reload SEM. Detection then finds the charger by itself, including the start/stop select, which is the piece manual setup most often misses.

Option B — tell SEM directly. Configuration tab → EV charger (or Settings → Devices & Services → SEM → Configure → EV charger) and set:

  • Charging power sensor → your go-e power sensor (W)
  • Connected sensor → the plug/cable binary sensor
  • Current control entity → the go-e number.* that sets the charging current (usually amp)
  • optionally Charging sensor → the “car is charging” binary sensor

Current control is the important one: with a number entity SEM can modulate the charge to your surplus. Without it SEM can only watch.

And remove the dryer — Configuration → device list, or unset it as the EV charger — otherwise SEM will keep managing your dryer as if it were the car. Sorry about that one; it’s a fallback doing exactly what it was told, badly.

In 2.1 this gets less mysterious: detection now reads Home Assistant’s registry rather than pattern-matching entity names, and the Configuration tab shows what SEM found, what it nearly matched, and which installed integrations look energy-related but weren’t recognised. Your MQTT charger would appear in that last list — so instead of silence you’d get a line telling you SEM saw something it couldn’t identify.

If Option B still doesn’t take, post the entity IDs of your go-e power sensor and current number and I’ll tell you exactly which fields they belong in.

SEM 2.0 — Trustworthy — is out :tada:

2.0 adds almost nothing you have to learn. It makes what SEM already did believable: the same decisions, no longer changing their mind for reasons nobody can see.

That was the whole milestone. Six weeks, 21 betas, 48 issues closed, and most of them spent on SEM saying what it will do, doing that and nothing else, and admitting what it doesn’t know.

:muted_speaker: SEM stops shouting in your log and your database. Its recorder footprint fell from 25% to 6.1% of Home Assistant’s state writes — SEM was a quarter of everything your database recorded. At the default log level it’s quiet now.

:electric_plug: The charger does what you told it. The last stretch was one question: does SEM’s “stop” actually stop the car? It didn’t always. On a KEBA, SEM’s stop used to enable the box with a 1 kWh energy target so it would charge into a stop — putting roughly 1 kWh into the car on every plug-in even with the daily target at 0. Setting a device to Mode = Off could switch off a load you had running. Both fixed, plus the box is now parked when the car leaves so the next plug-in can’t auto-start behind SEM’s back.

:abacus: The numbers reconcile. The energy diagram balances, per-device breakdowns agree with the fleet total, and the Costs tab’s year and months agree. An estimate is never recorded as a measurement — exported battery energy is attributed and paid once, and a bought kWh doesn’t become free by sitting in the battery.

:compass: Setup tells the truth. Every setting has an explanation, ranges are declared once (so “minimum 5 kWh” on a 3 kWh battery can’t happen again), and the first-run welcome describes your install. Repairs link either the exact troubleshooting section or a pre-filled bug report.

:sun_behind_small_cloud: Forecast. Multiple solar forecasts — one per PV string — are added together instead of read as one, you can see the forecast per string, and choosing your forecast source now sticks.

Upgrade notes

  • Nothing switches on silently. A fresh install no longer wakes up observing.
  • EV 1↔3-phase switching is off by default while that model is reworked — it paused chargers that never resumed on some brands. Enable per charger if you want it.
  • Battery → grid arbitrage stays off on every default. Check your grid connection agreement before enabling.
  • switch.sem_overnight_actuation is now switch.sem_energy_plan_actuation.
  • Requires Home Assistant 2026.2.0 or newer.

Thank you

Genuinely: this release was shaped by people in this thread and on GitHub reporting things that were wrong, then testing the fixes on their own hardware. Fronius, GoodWe, Growatt, SMA, SolarEdge, Deye, Sessy, Enphase, FENECON and Huawei installs, Zaptec / Wallbox / KEBA / Easee / go-e chargers — the supported hardware table marks what’s been proven on someone’s real system, and links the thread it was proven in. That table is short in the :white_check_mark: column only because I refuse to write :white_check_mark: without evidence.

Full notes: CHANGELOG · install via HACS.

Bug reports and “this is confusing” reports are equally welcome — several of the setup fixes in 2.0 came from the second kind.

1 Like

I have now been able to successfully connect the go-eCharger in version 1.7.6. I will continue testing now.

Hi, thanks for the great integration and nice dashboard , impressive !

I’ve got a home battery (Izypower TITAN, no EV charger) and I’m trying to replicate a “smart meter” style behavior: discharge the battery to cover household grid import whenever it’s cost-effective or when exceeding solar injection, independent of any specific appliance (I’ve got a Shelly Pro 3 EM but it doesn’t works with the TITAN, hence trying to do that with HA.

From what I can see in the docs, battery discharge is currently scoped to two contexts:

  1. EV charging assist (SOC Zone 3/4)
  2. “Finish overnight from → Battery” on an individual load’s runtime goal (Load Management section)

On top of that, I can’t see anything to tell the integration how to charge or discharge the battery.

Is there a way to have SEM discharge the battery to offset general home consumption (grid import) that I’m missing? Or is that on the roadmap? Happy to test if there’s something in beta.

Thanks

Thanks! The behaviour you want — battery covers household import — is your inverter’s own self-consumption mode, and SEM deliberately doesn’t re-implement that loop: it reacts locally in milliseconds, and an HA-side poller would only do it worse. SEM is not an EMS with its own drivers (that’s evcc’s model) — it connects hardware that is already integrated in Home Assistant, so it can only command what your TITAN’s HA integration exposes as writable entities. If it exposes a discharge/mode control, SEM can drive it today (discharge control entity + protection floors), and the 2.1 betas add exactly your “when it’s cost-effective” half: a forecast-led spendable-battery budget. Paste which integration brings the TITAN into HA and its number/select/switch entities, and I’ll tell you precisely what SEM can do with it — if it’s read-only in HA, no HA tool can command it and the ask belongs upstream. Happy to have you on the beta channel for the spendable-battery testing.

Here’s the entity list you asked for (integration is khirale/izypower_titan, MR1/local mode):

  • number.baie_technique_izypower_titan_max_discharge_power : writable, min: 100, max: 800, step: 50 (W). This is the one currently set as SEM’s battery_discharge_control_entity.
  • number.baie_technique_izypower_titan_charge_discharge_power : writable, same range, sets the power setpoint but doesn’t trigger anything on its own.
  • button.baie_technique_izypower_titan_start_discharge / start_charge / standby : these actually trigger the action.
  • Underlying services (not exposed as entities): izypower_titan.charge / .discharge / .stop, both taking power (W) and soc_limit (%).

So to be clear about what SEM can already do vs. what it can’t: max_discharge_power is a ceiling, not a trigger. It limits discharge power if discharge is already happening, but doesn’t start one. The actual start/stop is either a press button press or the charge/discharge/stop service call.

Does SEM’s discharge control entity handling call the button/service to initiate discharge, or does it only ever adjust the ceiling number?

That’s the part I can’t tell from my side, and it’s the crux of whether the 2.1 spendable-battery budget will actually cover my use case or just cap an already-running discharge that nothing else triggers.

Hi Loic,
you’re not missing anything. SEM’s “hold the battery back” logic today only fires for the EV or for grid-funded loads, so on an install with no charger there’s no path to it. Real gap.

Worth splitting though: your TITAN’s own self-consumption loop already covers the house in milliseconds and I won’t re-implement that badly on a polling cycle. What’s genuinely missing is deciding when it’s worth it — holding the pack through a cheap hour so it’s there for an expensive one. That half is SEM’s job, and the 2.1 budget that works out how much of your pack is spare already exists; it just can’t spend it on the house yet.

I’ve written it up as #879 — let’s continue there rather than in the thread, so it stays findable and I can track it properly.

Hi, as first-time test of the app, I’ve had a rough first-experience due to the ‘Load Management’ feature - that resulted in almost all the power to my house being shut off in the middle of the night.

First, while I realize Load Management defaults to ‘off’, I somehow inadvertently turned it on, perhaps by making an adjustment to something elsewhere, or maybe just accidentally flipping the switch.

Second, I didn’t notice that SEM had automatically identified many switches that existed in my HA instance - the Span panel that controlled all the electric circuits for the house, and the Pila battery (via an HA MQTT integration) that backed up my Internet and networking system.

I purposely hadn’t added the EV control, as I wanted to understand more about SEM before enabling it to control things. The EV was separately (outside of HA) set to begin charging at midnight, to take advantage of lower electric tariffs.

So midnight rolls around, the EV starts charging, and SEM goes into critical overload identification against the default 5kW limit, and proceeded to shut down almost all of the circuits in my house - including the output circuit from the Pila battery that was supposed to be a backup for my Internet router and the device running my HA instance itself!

So, I was eventually able to figure out how to turn things back on manually without Internet. But, the aggressiveness of the default load management, and the way SEM had automatically identified switches controlling loads, was too much. Until I can figure out a more fail-safe way to protect access to electrical load switches, I’m quite wary of using SEM again - or for that matter any third-party automation.

Happy to provide logs or config details if it’s useful for any changes you might want to consider for the app.

Hello,

Thank you for this great software & all the effort you put into this.

I recently started using this integration after using EVCC for a while, but I was looking to a more integrated solution.

My setup :

car charger : ABB terra

solar : Huawei Sun 2000 + luna 2000 and 1 plugin solar panel system

P1 port grid power meter

For the car charger I had to create 2 helpers in Home assistant as the charger status was combined in 1 sensor, and SEM needed a charging & a plugged in sensor.

Control of the charger is working, it can start & stop & limit power when needed.

When the home battery is close to or at 100 %, and select.sem_charger_ev_charger_charge_mode is set to solar, the power for the car charger is adapted so only solar power is used. → working as expected.

![|643x468](file:///tmp/lu64121bzn5.tmp/lu64121bzy2_tmp_64d78587.gif)

However when the battery is not yet at 100 % the charger will switch on, but the battery charging power will not be adapted, so the car is charged from the grid & the battery received all the power from the solar panels.

![|643x363](file:///tmp/lu64121bzn5.tmp/lu64121bzy2_tmp_16e61ede.gif)

Is there a setting in the Huawei inverter or in SEM I missed?

Also I noticed the battery_maximum_discharging_power from the sun2000 is always updating, not sure why this is done, possibly this is a mis-match in the parameters?

Example :

stability: delta guard — holding 7A — solar_only: surplus=1500W (bare=0W + redirect=1500W) → 6A (solar=3800W, home=1100W, batt_chg=2700W)→stability: delta guard — holding 7A — solar_only: surplus=1500W (bare=0W + redirect=1500W) → 6A (solar=3700W, home=900W, batt_chg=2700W)

Thank you for the detailed report, that was three real bugs on my side, and all three are fixed in 2.1.0-beta.6:

  • #897, you did not turn it on. Load management was on by default at a 5 kW ceiling while the User Guide said off, and the arm switch was hidden behind Advanced. It is now off on a fresh install, with the toggle and the target limit side by side in the default Config view. Existing installs keep whatever value they have, so please check yours after updating.
  • #895, auto-discovered devices are supposed to be monitor-only until you say otherwise. That default reached the surplus side but not the shedder, so your Span circuits and the backup battery were fair game the moment they were discovered. One resolver answers it everywhere now.
  • #896, the shedder had no cap, no floor and no futility guard. It now sheds only what the overshoot needs, one load per pass, judged against the live meter; and before the first switch it checks whether shedding everything it may shed would even reach the target — if the peak belongs to a load SEM doesn’t control (your EV), it sheds nothing and files a Repair naming those kilowatts. Every shed episode also raises a notification now, and what SEM switched off it switches back on.

Nothing SEM controls should ever have included the circuit feeding HA itself, sorry about the manual recovery.

Both of your observations were bugs, both fixed in 2.1.0-beta.6:

  • #899, the redirect=1500W in your log. SEM credited a share of the battery’s charge power to the car assuming the inverter would yield it; the LUNA kept charging, so the grid funded those amps. A commanded pack now keeps its watts, and the redirect only counts while the meter agrees — three cycles of sustained import with a redirect in the budget veto it for the rest of the plug-in.
  • #900, battery_maximum_discharging_power was SEM, rewriting the limit every 10 s to chase the live house load. It now follows the load’s trend instead of the sample, and no writer re-sends a value the entity already holds. The options wizard also lets you pick the huawei adapter explicitly now (it was silently pinning Huawei installs to the generic one, a pinned install gets a Repair saying so).

If you get a solar day on beta.6, I’d like to hear whether the car still touches the grid while the pack is filling, that’s the one confirmation still open on #899.

Straight answer to his question: only the ceiling. battery_discharge_control_entity is the protection clamp, SEM writes a limit, never a trigger. The entity that initiates is a different one (battery_force_discharge_control_entity, a signed power setpoint), and where an inverter needs a mode change first, SEM flips a select (battery_strategy_control_entity). It has no path that presses a button or calls a vendor service. So on the TITAN, SEM would write charge_discharge_power and nothing would start.

Hey Guido and everyone,
first things first: Thanks for a very cool piece of software! I’m trying to get it running with my setup at home:

Inverter: Huawei Sun 2000
Wallbox: Huawei Scharger 22-KT

I have the inverter attached via the northbound API (this integration) and the Wallbox via OCPP and parts of the setup seem to be working. What’s odd is this: I noticed, that the current calculated consumption of my house seemed to be off in the Graphical overview. By looking deeper into the power graphs I noticed that my grid import is jumping in ten second windows. You can see it in the picture below. There is a smart meter at my final grid connection point (I have multiple smart meters, one for my house and then cascading behind it one for the house + heat-pump) that delivers live values (yellow line in the chart below, purple is delivered by the Fusion Solar Integration). That one is delivering the expected values.

So as far as I can see, there is no actual import happening. Do you have any clue how the jumping in the “Netzwerkimport”-Chart is happening?

Hi @symon — thanks for the detailed screenshot, it answered the question.

The jumping line is SEM’s own sensor, not FusionSolar: sensor.sem_grid_import_power flips between ~850 W and 0 W on SEM’s 10-second cycle while your meters stay flat. Your house figure looks wrong because SEM calculates it from the balance, so every phantom cycle lands in it.

The cause is your feed: FusionSolar’s northbound API is a cloud connection that updates every few minutes, and SEM has never learned that integration’s entities, so it’s guessing which of your sensors is the grid — and deciding every 10 seconds on numbers that are minutes old. That’s not something I can fix as a bug; supporting slow cloud feeds properly is an enhancement, and I’ve opened #947 for it.

If you can, use the local huawei_solar Modbus integration instead — that’s the Huawei path SEM is built and tested against, and it updates every few seconds.

Your SCharger over OCPP should work: SEM knows that integration and controls charging through its maximum_current number. It has never been confirmed on real hardware though, so I’d be glad to hear whether it holds up.