Releases: Soundistor/ha-eveus
Release list
v0.4.5
A maintenance release. Everything here comes from measurements on live stations: a reboot makes the charger serve a frame of readings it does not mean, and those readings were reaching Home Assistant's long-term statistics.
Fixed
- A lifetime counter that steps backwards is no longer believed on the first frame. For about a minute after a reboot the station reports
totalEnergyas0, before the counter is read back from flash. A single poll landing in that window used to reset the daily energy baseline and make the day report the whole lifetime counter — 134 kWh in one day on a 4.2 kW station, measured. Such a frame is now held back; a value still low on the next poll is accepted, so a genuine reset, or energy the station really lost, is not hidden forever.totalEnergy,IEM1andIEM2are guarded. - A charging current below what the station accepts is no longer published. The same reboot frame can carry a
currentSetthe station cannot legally have been set to. It is dropped until a second poll, a full poll interval later, confirms it — and a confirmed low value is then taken as the new normal, so a station genuinely running below the minimum is reported rather than hidden. - The daily energy sensor no longer rolls over on a frame that carries no reading. Crossing midnight on such a frame opened the new day already holding the previous day's total.
- A charger that is offline when Home Assistant starts no longer erases the stored firmware version. The device page kept showing the version before this; now it does again.
Changed
-
total_energyis now reported as atotalstatistic instead oftotal_increasing. The station loses the kWh it has not yet flushed to flash when it reboots, so the counter is not strictly increasing — Home Assistant was logging astate class total_increasing, but its state is not strictly increasingwarning and pointing users at this repository for a bug that is not one. The trip metersiem1andiem2deliberately staytotal_increasing: those are reset on purpose, andtotal_increasingis what preserves their accumulated sum across a reset.Note for existing installations: historical data for
total_energyis not rewritten by this release, and the change is not expected to raise a repair issue — Home Assistant raises those when a state class is removed or a unit changes, neither of which happens here. Measured on the maintainer's own instance after upgrading: none appeared.
Added
- A device row left behind by an upgrade can now be deleted. Before 0.4.0 the device was keyed by IP address; upgrading created a new row and left the old one in place with no entities and no way to remove it from the UI. Such a row can now be deleted from its own device page. The row the configuration entry currently owns stays undeletable — remove the entry itself for that.
v0.4.4
The first stable release since 0.4.3. Most of it comes from reading the station's own firmware and from live measurements on both generations, which is why several long-standing values turned out to be wrong rather than merely imprecise.
If you have automations or dashboards referring to this integration, read the breaking changes — several of them fail silently: the trigger simply stops matching and nothing appears in the log.
⚠️ Breaking changes
V1: sensor.*_state reports different values. The state table inherited from the project this was forked from came from a V2-generation station and agreed with V1 only on two codes. Two everyday states were reported wrongly: a plugged car that is waiting (code 9) read as no_ground, and an unplugged one (code 12) read as overcurrent. Any automation written against the observed behaviour triggers on exactly those two values and stops firing after the update.
| code | was | is now |
|---|---|---|
9 |
no_ground |
waiting |
12 |
overcurrent |
ready |
13 |
overvoltage |
delayed_start |
14 |
undervoltage |
overcurrent |
15 |
limited_by_time |
overvoltage |
16 |
limited_by_energy |
current_leak |
17 |
limited_by_money |
station_error |
18 |
limited_by_schedule1 |
overheat |
19 |
limited_by_schedule2 |
locked |
20 |
disabled_by_user |
no_ground |
21 |
relay_stuck |
overheat_plug |
22 |
limited_by_ai_mode |
undervoltage |
0 (no_data) and 6 (charging) are unchanged. Codes 1–5, 7, 8, 10 and 11 do not exist on V1 at all, so the values the old table produced for them never arrived.
V1: the charging switch is gone. This firmware has no remote stop: sending evseEnabled=0 mid-session was tested on a live station and the charger kept charging while still reporting itself enabled. The switch could not be honoured, so it is no longer created. End a session by unplugging, or let a time/energy limit expire.
binary_sensor.*_ground is unknown while the station's protective-earth monitoring is off (groundCtrl != 1). The ground field reads 1 whether monitoring is on or off, so reporting "safe" on a SAFETY sensor was a claim we cannot make. On V1 this is a permanent state, not a window at startup — the fix is to enable ground monitoring on the station itself. Automations testing state: 'off' on this sensor stop matching; test explicitly for what you mean.
switch.*_charging reports unknown when the frame carries no evseEnabled instead of claiming "off".
eveus_session_ended now also fires for a session cut short by a power cut. A charger that loses power boots straight back into charging, so its state never changes and the interrupted session used to vanish. Two consequences if you filter on this event: ended_state may now carry an active state such as charging, which it never did before; and ended_at is the moment of detection, not of the session's death — after a long outage the two differ by hours. eveus_charging_started fires for the new session in the same case, so started/ended stay paired. This covers the charger losing power, not an outage that also takes Home Assistant down.
Renamed and re-typed sensors. leak_current is now leak_channel_raw and has lost its mA unit and its state_class: the channel's scale is unknown, and long-term statistics over a guess only lent it authority. aiVoltage lost its state_class too — it is stored configuration, not a measurement. On V2, substate 9 is now external_limit instead of waiting_for_activation.
Long-term statistics. Because of those metadata changes, Home Assistant will raise Repairs (state_class_removed, units_changed) on installations that already collected statistics. This is the recorder reacting to a deliberate change, not a fault. Home Assistant offers to drop the collected statistics or keep the old metadata — that choice is yours.
Added
- V1: firmware version on the device page, and a Sync time button.
- Adaptive current sensor, reported only while adaptive mode is actually on — with it off the station keeps serving a stale figure.
- Diagnostics download, with device identifiers and credentials redacted.
Fixed
Reliability
- The entry now loads even when the charger is unreachable; setup no longer waits for a station that is powered only while a car is plugged in.
- Every request to the station is serialised. The firmware accepts one connection at a time and closes the existing one to make room, which was behind a long tail of timeouts and dropped connections — including whenever anyone had the station's own web page open.
- Writes are read back correctly: the station's acknowledgement was being misread, so accepted writes on V1 looked like failures, and the post-write refresh is now deferred instead of reading stale cached values.
- Daily energy and session-time accumulators survive restarts and unavailability.
- A garbage value in a single field no longer fails the whole poll with a repair issue; that sensor reads
unknowninstead. - V1: numeric fields with an absent or unparseable value now read
unknownrather than a confident0.
Correctness
systemTimeon V2 is the station's local clock, not a UTC epoch, andtimeMsg == 1means the clock is invalid rather than a real reading; on V1 it is localised to Home Assistant's timezone, not the host's.- A temperature below −50 is the firmware's "no sensor" sentinel, not a reading.
number.current_settakes its minimum from the station rather than a hardcoded constant, and is capped at 12 A on a 110 V grid.- Ground-fault confirmation is now truthful in both directions: a fault the station declares is reported immediately, and one inferred from the field alone needs three consecutive polls, so a missed poll no longer confirms a fault on stale data.
- Adaptive mode is set by posting the mode alone instead of a junk parameter pair.
- V1: a failed firmware-version read is no longer silent — it logs once when its retries run out, and its cause appears in diagnostics.
Configuration
- Credentials are validated against a handler that actually checks them; a wrong password used to be accepted silently and simply left the firmware version blank.
- Choosing the wrong generation (V1/V2) is rejected instead of producing a half-working entry.
- Reconfigure no longer fails, and no longer wipes the stored password.
v0.4.4-rc6
Pre-release for live testing on production. Not the final 0.4.4.
Fixed
binary_sensor.*_groundno longer claims "safe" without grounds. While the charger's PE
monitoring is disabled (groundCtrl != 1), the sensor reportsunknowninstead ofoff. On
V1/EnergyStar chargers PE monitoring is off in every frame observed so far, so the sensor stays
unknownthere until ground control is enabled on the charger itself. Breaking for
automations matchingstate: 'off'on this sensor — replace with an explicit check.- Ground-fault confirmation is now truthful in both directions. A fault reported by the charger
(state/subState= no ground / grounding error) raises the sensor immediately, where before it
could never raise whileground = 1. A fault inferred only from thegroundfield now needs
three consecutive polls — a missed poll restarts the counter, so the debounce no longer fires
on a stale frame. switch.*_chargingreportsunknowninstead of "off" when a poll carries noevseEnabled
field. No trigger for this has been observed live; this is a contract change, not a fix for a
seen failure.- A garbage (non-numeric) value in
state,subStateoraiStatusnow yieldsunknownfor
that one sensor instead of failing the entire poll and raising a repair issue. - Firmware version now reaches the device page after Home Assistant starts while the charger is
offline, without reloading the integration.
v0.4.4-rc5 (pre-release)
Release candidate. Closes 22 findings from the 2026-08-13 code review, plus the first live measurements of the station's write behaviour.
Fixed
- Reconfigure no longer fails, and no longer wipes the stored password. Changing the charger's IP after a DHCP change submitted an empty password field, which failed the credential check with
invalid_auth— and on success would have cleared the saved password. An empty password field now means "keep the one I already have". Regression introduced by the credential check in the rc series. - Last Session Energy / Duration survive a restart while the charger is offline. They were restored from the entity's last state, which is
unavailablewhenever HA shuts down with the charger unreachable — the normal case for this device. They now persist independently of availability, like the daily counters already did. - Daily Energy no longer freezes at zero. Two ways in, both fixed: resetting the lifetime counter from the station's own web UI (which also zeroes
totalEnergy) used to clamp the daily figure to 0 until midnight, and a missed baseline left the sensor dead for the rest of the day. The accumulated day is preserved across both. - A ground fault now trips the safety sensor immediately.
grounding_error(V2) andno_ground(V1) were missing from the set of firmware faults that bypass debounce, so the one fault the ground sensor exists for was the slowest to confirm — up to three polls, about three minutes. - Clock drift over 12 hours is reported truthfully on V2. The midnight wrap-around, which is correct for V1's
HH:MM:SSclock, was also applied to V2's absolute timestamp and folded a genuine 13-hour drift into "11 hours behind". - Firmware version on V1 is retried. A single failed read left the device page with no firmware version until the next reload — and that read fails exactly when the station has only just come back up.
- Entities that do not need the charger stay available while it is offline. Daily Energy, Daily Session Time, Last Session Energy/Duration and the Force Refresh button serve their own values or act locally; going unavailable with the station also wiped their attributes.
- The charging switch no longer springs back. It now holds the state you set until a poll actually agrees with it, instead of dropping it on the first poll that follows.
- A corrupted stored value no longer stops the Daily Session Time sensor from loading.
eveus.set_ai_moderejects a mode the connected generation does not have (V1 has two, V2 four) instead of sending it to the station.
Changed — please read before updating
- The leak sensor loses its unit and its long-term statistics, and is renamed to "Leak channel (raw)". The value is the station's raw earth-leakage channel; the "mA" label came from the vendor's UI and does not match the firmware's own trip thresholds, so it was most likely wrong. State history is kept, but long-term statistics for this sensor stop. New installations get the entity id
sensor.<prefix>_leak_channel_raw; existing installations keep their current entity id. - A password can no longer be cleared through Reconfigure. An empty field means "keep the stored password". Remove and re-add the charger if you need to drop credentials entirely.
- Some entities no longer become
unavailablewhen the charger is offline (see above). Automations that trigger on those entities becoming unavailable will need adjusting.
Internal
- Test suite grown from 148 to 229 tests: new coverage for the switch, select and button platforms, all five deferred-write paths, diagnostics redaction (a missing password redaction used to leave every test green), the V2 state maps, and the device registry.
- Firmware knowledge base updated with the first live measurements of
/mainkey stability and the post-write settle window. Two constants that had been derived from a comment in the vendor's JavaScript are now backed by measurement.
v0.4.4-rc4 (pre-release)
Pre-release for prod verification of the 2026-08-13 offline-recovery batch.
The charger coming back online is picked up on its own
Setup no longer waits for the first poll to succeed. Previously an HA restart while the charger was offline left the config entry in SETUP_RETRY with no entities at all, and the core's retry backoff doubles to a 600 s ceiling — so a charger that rejoined the network could stay invisible for up to 10 minutes, which looked like the integration being permanently dead until it was reloaded by hand. The entry now loads regardless: entities register as unavailable and become available on the next poll, within about a minute.
Daily counters survive an offline restart
Daily Energy could restart the day at zero after an HA restart. HA writes no attributes for an unavailable entity, so the stored state carried neither the date nor the baseline, and the sensor re-anchored itself to the station's current total. The three restore-based sensors now persist their values independently of availability, with a one-time migration so no baseline is lost on upgrade.
A wrong password is now detected when adding a charger (V2)
The /main endpoint answers successfully whatever the password is — POST handlers on this firmware check no credentials at all — so the config flow accepted any password. V2 credentials are now probed against the one handler that does check them. V1 is deliberately left unverified: its auth path has never been measured, and a probe that rejected a valid password would make the station impossible to add.
Smaller fixes
- The current-setting entity used a deprecated Home Assistant method and only worked through a fallback path; HA logged a warning about it on every setup.
- Removed the coordinator's unreachable
401 → re-authbranch. Had it ever fired, polling would have stopped for good. - Stale repair issues from older versions (
cannot_connect, unsuffixeddevice_error) are deleted at setup — one of them had been sitting in storage since June.
v0.4.4-rc3 (pre-release)
Pre-release for live testing. Everything here concerns V1 (EnergyStar) chargers; V2 behaviour is unchanged except for two shared improvements at the end.
This round is based on the V1 charger's own web interface plus live probes of a real station, so the claims below are measured rather than inferred.
Breaking
- V1 chargers no longer get a
chargingswitch. That firmware has no remote-stop command at all: its own web interface offers none, and a stop written straight to the device is ignored. ItsevseEnabledflag also reads "enabled" at all times, so the toggle was misleading in both directions. Whether a session is running is shown by thestatesensor; ending one means unplugging the car or letting a limit expire. Automations referencing the switch on a V1 charger will need updating. - V1 state names changed. The previous mapping was inherited from an older project whose configuration had been written against a V2-generation station. It matched a real V1 only for "no data" and "charging" — a plugged-in car was reported as No Ground and an unplugged one as Overcurrent. The state sensor now uses the enum the charger itself renders (verified live: unplugged = Ready, plugged and idle = Waiting). Codes that do not exist on V1 report Unknown instead of an invented meaning. Historical states recorded under the old names stay in the database; those readings were wrong, not the new mapping.
Fixed
- Every write to a V1 charger failed with an error since 0.4.4-rc1, even though the charger had applied the command. V1 answers writes with an empty body, which the new response check read as a rejection. The expected acknowledgement is now per firmware generation.
- Turning charging off on V1 silently did nothing. It now reports the limitation instead of pretending to succeed.
- The AI mode selector sent a junk parameter (
pageevent=evseEnabled&aiMode=…). It now sendsaiModealone, as the charger's own interface does. - Out-of-range charging currents were truncated by the charger rather than refused — a request for 999 A was stored as 231 A. Values outside 0–255 are now rejected before they are sent.
- A value could jump back after being changed. The charger keeps serving cached data for a few seconds after a write, so the confirming poll is now deliberately delayed instead of issued immediately. Affects both generations.
Added
- Sync Time works on V1. The write format differs from V2: this firmware stores exactly the timestamp it is given and applies no timezone of its own, so local wall-clock time is sent.
- Firmware version for V1 chargers. V1 reports no version over the API, so it is read once at setup from the page the charger serves.
- Adaptive Current sensor (both generations) — the current the adaptive algorithm is actually allowing, next to the requested setpoint. Reports nothing while adaptive mode is off, where the underlying field keeps a stale figure.
v0.4.4-rc2 (pre-release)
Pre-release for live verification only — not a general update. Builds on v0.4.4-rc1 (already smoke-tested: write path, request serialization, V2 clock offset) and adds the remaining ten fixes from the 2026-07-27 API analysis.
New in this rc
timeMsg == 1(station clock invalid, typically a dead RTC backup battery) now blankssystemTimeinstead of publishing a garbage reading.number.current_setminimum now comes from the station'sminCurrentinstead of a hardcoded constant that no longer matched the device after a firmware update.- Absent temperature sensor (
< -50 °Csentinel) now readsunknowninstead of a permanent-60 °C. - V2 substate 9 renamed
waiting_for_activation→external_limit— it actually means the current is under external/OCPP control, the opposite of what the old name implied. aiVoltage(a stored threshold, not a live measurement) moved to Diagnostics and no longer collects statistics.- Diagnostics now redacts
stationIdandSTA_IP_Addresin addition to the serial numbers already redacted. sw_versionno longer carries the firmware's trailing space.- Debounce now applies only to safety sensors —
groundCtrl(a config flag) reacts on the first poll instead of being delayed by up to three. - Config flow now rejects a mismatched V1/V2 model choice instead of silently corrupting every measurement.
- Current ceiling capped at 12 A when the station reports a 110 V grid (
gridRange == 1) — latent on our own 230 V hardware, added for correctness.
Rollback
HACS → Eveus Charger → ⋮ → Redownload → v0.4.3.
v0.4.4-rc1 (pre-release)
Pre-release for live verification only — not a general update. It carries the three critical fixes from the 2026-07-27 API analysis so they can be confirmed on real hardware before 0.4.4 ships.
Fixes
Every write raised an error after the charger had already applied it. /pageEvent never answers JSON — a successful write returns the plain text OK, and a refusal returns plain text too, always with HTTP 200. The response was parsed as JSON, so setting the current, toggling charging, changing the AI mode and syncing the clock all showed "Failed to perform the action" with a traceback even though the charger had accepted the command. The exception also aborted the follow-up refresh, so the new value only appeared with the next scheduled poll. Present since v0.2.0.
(Note: this tag replaces an earlier v0.4.4-rc1 that checked for the wrong success body — static firmware analysis suggested mainPost successfully, but a live test on real hardware showed the station actually replies OK. If you installed the previous rc1, please update again — it still raised on every write.)
Requests to the charger are now serialized. The station serves exactly one connection: a second one is not queued or refused, it closes the session already in use. A poll overlapping a write therefore broke both, and any other client (the charger's own web UI polls once a second) could kill a pooled socket and take the next request down with it. All reads and writes now pass through a single lock.
V2 clock offset. systemTime is the station's local wall clock encoded as an epoch (UTC + timeZone*3600), not an absolute UTC epoch. Decoding it as UTC made the time-drift sensor report a permanent offset equal to the configured timezone on a perfectly healthy clock. The write direction was already correct and is unchanged. Confirmed live: Time Drift reads 0.00s.
Rollback
HACS → Eveus Charger → ⋮ → Redownload → v0.4.3.
v0.4.3
Fixed
- Repair issues are now per-charger and name the device — in a multi-charger setup, one charger recovering no longer clears another charger's error notification.
- Re-authentication now distinguishes a wrong username/password (prompts you to re-enter credentials) from a charger that is simply unreachable.
- The "session ended" event and the Last Session sensors are no longer lost when a charging session ends during a brief network hiccup, and a stale event is no longer replayed after a long offline period.
Changed
- The charging-current control's maximum now follows the charger's reported hardware limit instead of a fixed 32 A.
- Session Energy statistics keep their reset point across Home Assistant restarts.
- Logs and the update coordinator now carry the device name, making multi-charger setups easier to read.
Under the hood
- The integration now uses Home Assistant's shared HTTP session, shares a single entity base class across all platforms, and stores its runtime data on the config entry (modern typed pattern).
- Added a full automated test suite (coordinator, config flow, sensors, golden/snapshot) and ruff linting to CI.
v0.4.2
Added
- Session lifecycle events — the integration now fires
eveus_charging_startedandeveus_session_endedon the Home Assistant event bus, so automations (notifications, energy logging, etc.) can trigger on charging start/finish without polling.eveus_session_endedcarries the session's finalenergy_kwh,duration_s,ended_state, andended_at. Filter byentry_id/device_nameif you run more than one charger. - Last Session sensors —
last_session_energy(kWh) andlast_session_duration(s) freeze the previous completed session's final figures and keep them until the next session ends. They survive Home Assistant restarts. The charger clears its live session counters the moment the next session begins, so these sensors preserve numbers that would otherwise disappear.
Fixed
- Dynamic polling now actually speeds up while charging — a state-string case mismatch meant the coordinator always polled at 60 s; it now correctly polls every 30 s during an active charging session and 60 s otherwise.
Documentation
- README now links the external HTTP API reference, Soundistor/eveus-api-doc.
- README (English + Ukrainian) documents the new events and Last Session sensors.