What's the issue?
Two DC-only B2500 (HMJ-2): only one registers as consumer, and both BMS SoC counters collapse to 0% in auto mode
Setup
- AstraMeter Home Assistant add-on v2.2.4
- 2× Marstek B2500-D (HMJ-2), identical firmware
- LEFT
18cedf9aaaaa @ 192.168.178.71
- RIGHT
6824994aaaaa @ 192.168.178.72
- Per battery: 2 PV panels (450 W each), one feeding each of the battery's two PV inputs — so both PV inputs are in use on both batteries.
- Per battery: one dedicated Marstek HMI-1 micro-inverter (MST-MI0600W), driven from both battery outputs (both outputs in use, so the commanded setpoint applies in full — not halved).
- LEFT battery → inverter
98a14a3aaaaa
- RIGHT battery → inverter
98a14a3bbbbb
- Strictly DC-coupled: panels → battery → inverter. No panel is wired directly to an inverter.
- Two separate, independent PV strings — the batteries share no panels and no inverter. AC-side, they sit on different phases (L1 and L3).
- Grid meter: EasyMeter Q3AA1174 via Tasmota IR head, pushed to HA every 5 s. Meter is netting across all three phases.
power_input_alias = sensor.strom_leistung_l1,sensor.strom_leistung_l2,sensor.strom_leistung_l3
device_types = ct002, min_dc_output = 20, fair_distribution = true, throttle_interval = 1.0
- Both batteries set to Self-Adaptation in the Marstek app, both bound to the emulated CT002. The inverters run in standard mode.
Issue 1 — Only one of two batteries is registered as a consumer
The two batteries poll AstraMeter in different roles, consistently, over thousands of requests:
LEFT (192.168.178.71): phase='0' → "inspection mode", never becomes a consumer
RIGHT (192.168.178.72): phase='A' → the only registered consumer
Counted over one log window: 917/917 requests from LEFT with phase='0', 967/967 from RIGHT with phase='A'. Never a single switch.
Result: sensor.astrameter_consumer_count = 1. Fair distribution has nothing to distribute — there is only one consumer in the fleet. HA exposes consumer entities only for the RIGHT battery.
Both batteries are the same model with the same firmware, both configured identically in the Marstek app. I have not found any app setting that controls this.
Issue 2 — The single consumer gets trapped at min_dc_output (active control)
With active_control = true, the registered battery ended up in a self-sustaining trap:
reported_power = 0 — even though the battery was physically outputting 109 W (confirmed via hm2mqtt: micro_inverter_power = 109)
- Because it reports 0, AstraMeter scores it
saturation = 100%
- Being "saturated", it gets capped at
min_dc_output → target_l1 = 20 W
- A DC-coupled B2500 cannot run its inverter below ~80 W, so 20 W means the output collapses to 0
- Output 0 → still reports 0 → saturation stays at 100% → capped again
Log evidence: over 967 consecutive responses, the RIGHT battery received only ever this:
fields=['HME-4', '02b2500aaaaa', 'HMJ-2', '6824994aaaaa',
'20', '0', '0', '20', '1', '0', '0', '0', '-50', ...]
while LEFT (inspection mode) received the real phase values:
fields=['HME-4', '02b2500aaaaa', 'HMJ-2', '18cedf9aaaaa',
'1349', '71', '-618', '802', '1', '1', '1', '0', '-50', ...]
Switching active_control = false (relay mode) breaks the trap immediately: saturation drops to 0%, target_l1 rises to 299 W, and both batteries start receiving identical real phase values.
Possible root cause: for DC-coupled batteries, reported_power appears unreliable (always 0 here). Using it as the saturation input creates a deadlock that min_dc_output cannot escape, because the floor it enforces (20 W) is below the inverter's minimum operating power (~80 W).
Issue 3 — steer_to_zero fires on tiny surpluses (related to #359)
Even on v2.2.4, this appears repeatedly:
CT002: 1 W surplus but no AC-chargeable battery reporting — nothing here can absorb it. Reporting device_types: ['HMJ-2']
CT002: 3 W surplus but no AC-chargeable battery reporting — ...
CT002: 7 W surplus but no AC-chargeable battery reporting — ...
CT002: 9 W surplus but no AC-chargeable battery reporting — ...
Fires at 1 W / 3 W / 7 W / 9 W. Setting deadband = 30 suppresses these, but it looks like the #359 fix does not fully cover the near-zero-crossing case.
Issue 4 — Cross-talk fields stay zero (batteries never learn about each other)
In every response — active control and relay mode — the cross-talk fields (*_chrg_power / *_dchrg_power) are all zeros:
'-877', '363', '137', '-377', '1', '0', '0', '0', '-50', '141', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
So neither battery knows what the other is doing. Both regulate independently against the same grid value.
Observation — BMS SoC collapse correlates with auto mode
This is the part I cannot explain, and I want to flag it carefully — I am not claiming AstraMeter causes it, only that the correlation is hard to ignore:
- 2 days in Manual mode (fixed 150 W per battery): completely stable. Both batteries tracked each other closely, SoC and pack voltage nearly identical.
- Switched to Self-Adaptation + AstraMeter. Within one hour, both batteries collapsed:
- RIGHT at 21:22 → SoC 0%, output 0 W,
discharging: off, charging: off
- LEFT at 21:49 → SoC 0%, output 0 W, same state
- Real pack voltages at that moment: 46.52 V and 46.62 V — i.e. both packs are essentially full
This is a BMS coulomb-counter drift, not a hardware fault. Marstek's own FAQ documents the fix (charge to 100% without discharging, then discharge to 0% without charging).
My working hypothesis: with cross-talk fields at zero (Issue 4), both batteries hunt independently around the zero-crossing, constantly reversing between charge and discharge. That repeated direction reversal is what drifts the coulomb counter. In manual mode there is no hunting, and no drift.
Historical HA data supports the drift pattern — SoC readings jumping like 17 → 61 → 17 and 0 → 60 → 0 within a minute, while pack voltage stayed steady.
Additional context that may matter
Parallel hm2mqtt connection. Both batteries are simultaneously connected to hm2mqtt (v1.8.1, MQTT proxy enabled) alongside AstraMeter's UDP CT002 session. This is how I could see that reported_power = 0 was wrong: hm2mqtt reported micro_inverter_power = 109 W for the same battery at the same moment. If a parallel MQTT session can affect what the battery reports over UDP, that would be worth knowing.
Prior custom controller. Before AstraMeter, I ran a custom HA automation for months that wrote time_period_1_output_value directly via hm2mqtt (60 s cycle, 20 W write deadband). It is possible one battery is left in a different internal state than the other as a result — which might explain why they now take different CT002 roles. I have no way to inspect or reset that state.
Timeline of the BMS collapse (relay mode did not prevent the second one):
- ~20:45 — both batteries physically outputting (LEFT 172 W, RIGHT 109 W), grid at −19 W
- 21:22 — RIGHT collapses: SoC 0%, output 0 W (still in
active_control = true, capped at 20 W)
- 21:26 — I switch to
active_control = false (relay mode). Saturation trap clears, target_l1 jumps 20 W → 299 W, both batteries now receive identical real phase values
- 21:49 — LEFT collapses too: SoC 0%, output 0 W — 23 minutes after the relay switch
- 21:52 — both at SoC 0%, pack voltages 46.52 V / 46.62 V (full), grid +273 W
So relay mode fixed the balancer trap but did not prevent the second battery from going down. Whatever drives the BMS drift is not (only) the saturation logic.
Questions
- Is
phase='0' (inspection mode) expected for a B2500 in Self-Adaptation, or does it indicate the battery declined to participate? Is there anything on the AstraMeter side that influences which role a battery takes? Could the fact that the two batteries sit on different AC phases (L1 / L3) be related?
- Should
reported_power be trusted as the saturation input for DC-coupled batteries at all? Here it is always 0 despite real output.
- Should
min_dc_output be floored at the inverter's minimum operating power (~80 W for B2500) rather than allowing 20 W, which for DC batteries effectively means "off"?
- Are the cross-talk fields expected to be populated with two DC batteries, and does relay mode change that?
What I can provide: full DEBUG logs for any window, HA history for SoC / pack voltage / inverter power / grid power at 1 min resolution going back ~10 days, and I can reproduce on demand — though I would rather not, given it takes a full charge/discharge calibration cycle to recover the packs afterwards.
Version
2.2.4
Installation method
Home Assistant add-on
If "Other", which?
No response
Configuration
[GENERAL]
DEVICE_TYPE = ct002
THROTTLE_INTERVAL = 1.0
WAIT_FOR_NEXT_MESSAGE = false
LOG_LEVEL = debug
DEADBAND = 30
HAMPEL_WINDOW = 7
HAMPEL_N_SIGMA = 3.0
HAMPEL_MIN_THRESHOLD = 50
[HOMEASSISTANT]
POWER_INPUT_ALIAS = sensor.strom_leistung_l1,sensor.strom_leistung_l2,sensor.strom_leistung_l3
[CT002]
ACTIVE_CONTROL = false
MIN_DC_OUTPUT = 20.0
MIN_EFFICIENT_POWER = 0
EFFICIENCY_ROTATION_INTERVAL = 900
GRID_PREDICT_TRUST = 0.5
FAIR_DISTRIBUTION = true
BALANCE_GAIN = 0.3
BALANCE_DEADBAND = 25
CONCENTRATE_DEADBAND = 60.0
IMPORT_TRIM_W = 15.0
MARSTEK_AUTO_REGISTER_CT_DEVICE = false
CLOUD_REPORTING = false
Logs
2026-07-12 19:51:48 DEBUG:astrameter:CT002 parsed fields from ('192.168.178.71', 10000): meter_dev_type=HMJ-2 meter_mac=18cedf984748 ct_type=HME-4 ct_mac=02b2500516f7 phase='0' power=0 consumer_id=18cedf984748 in inspection mode
2026-07-12 19:51:48 DEBUG:astrameter:CT002 parsed fields from ('192.168.178.72', 10000): meter_dev_type=HMJ-2 meter_mac=68249943636a ct_type=HME-4 ct_mac=02b2500516f7 phase='A' power=0 consumer_id=68249943636a
2026-07-12 19:51:48 DEBUG:astrameter:CT002 response to ('192.168.178.71', 10000): fields=['HME-4', '02b2500516f7', 'HMJ-2', '18cedf984748', '1349', '71', '-618', '802', '1', '1', '1', '0', '-50', '4', '0', '0', '0', '0', '0', '0', '20', '0', '0', '0']
2026-07-12 19:51:48 DEBUG:astrameter:CT002 response to ('192.168.178.72', 10000): fields=['HME-4', '02b2500516f7', 'HMJ-2', '68249943636a', '20', '0', '0', '20', '1', '0', '0', '0', '-50', '5', '0', '0', '0', '0', '0', '0', '20', '0', '0', '0']
2026-07-12 20:11:06 INFO:astrameter:CT002 consumer 68249943636a phase detected: A
2026-07-12 20:13:42 INFO:astrameter:CT002: 1 W surplus but no AC-chargeable battery reporting — nothing here can absorb it. Reporting device_types: ['HMJ-2']
2026-07-12 20:09:21 INFO:astrameter:CT002: 3 W surplus but no AC-chargeable battery reporting — nothing here can absorb it. Reporting device_types: ['HMJ-2']
2026-07-12 20:11:50 INFO:astrameter:CT002: 7 W surplus but no AC-chargeable battery reporting — nothing here can absorb it. Reporting device_types: ['HMJ-2']
2026-07-12 20:21:50 INFO:astrameter:CT002: 9 W surplus but no AC-chargeable battery reporting — nothing here can absorb it. Reporting device_types: ['HMJ-2']
--- After switching ACTIVE_CONTROL = false at 21:26:50 ---
2026-07-12 21:28:xx DEBUG:astrameter:CT002 response to ('192.168.178.71', 10000): fields=['HME-4', '02b2500516f7', 'HMJ-2', '18cedf984748', '-877', '363', '137', '-377', '1', '0', '0', '0', '-50', '141', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
2026-07-12 21:28:xx DEBUG:astrameter:CT002 response to ('192.168.178.72', 10000): fields=['HME-4', '02b2500516f7', 'HMJ-2', '68249943636a', '-877', '363', '137', '-377', '1', '0', '0', '0', '-50', '145', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
Note: LEFT sent phase='0' in 917/917 requests, RIGHT sent phase='A' in 967/967 requests. RIGHT received '20','0','0','20' in 967/967 responses under active control.
What's the issue?
Two DC-only B2500 (HMJ-2): only one registers as consumer, and both BMS SoC counters collapse to 0% in auto mode
Setup
18cedf9aaaaa@ 192.168.178.716824994aaaaa@ 192.168.178.7298a14a3aaaaa98a14a3bbbbbpower_input_alias = sensor.strom_leistung_l1,sensor.strom_leistung_l2,sensor.strom_leistung_l3device_types = ct002,min_dc_output = 20,fair_distribution = true,throttle_interval = 1.0Issue 1 — Only one of two batteries is registered as a consumer
The two batteries poll AstraMeter in different roles, consistently, over thousands of requests:
Counted over one log window: 917/917 requests from LEFT with
phase='0', 967/967 from RIGHT withphase='A'. Never a single switch.Result:
sensor.astrameter_consumer_count = 1. Fair distribution has nothing to distribute — there is only one consumer in the fleet. HA exposes consumer entities only for the RIGHT battery.Both batteries are the same model with the same firmware, both configured identically in the Marstek app. I have not found any app setting that controls this.
Issue 2 — The single consumer gets trapped at
min_dc_output(active control)With
active_control = true, the registered battery ended up in a self-sustaining trap:reported_power = 0— even though the battery was physically outputting 109 W (confirmed via hm2mqtt:micro_inverter_power = 109)saturation = 100%min_dc_output→target_l1 = 20 WLog evidence: over 967 consecutive responses, the RIGHT battery received only ever this:
while LEFT (inspection mode) received the real phase values:
Switching
active_control = false(relay mode) breaks the trap immediately: saturation drops to 0%,target_l1rises to 299 W, and both batteries start receiving identical real phase values.Possible root cause: for DC-coupled batteries,
reported_powerappears unreliable (always 0 here). Using it as the saturation input creates a deadlock thatmin_dc_outputcannot escape, because the floor it enforces (20 W) is below the inverter's minimum operating power (~80 W).Issue 3 —
steer_to_zerofires on tiny surpluses (related to #359)Even on v2.2.4, this appears repeatedly:
Fires at 1 W / 3 W / 7 W / 9 W. Setting
deadband = 30suppresses these, but it looks like the #359 fix does not fully cover the near-zero-crossing case.Issue 4 — Cross-talk fields stay zero (batteries never learn about each other)
In every response — active control and relay mode — the cross-talk fields (
*_chrg_power/*_dchrg_power) are all zeros:So neither battery knows what the other is doing. Both regulate independently against the same grid value.
Observation — BMS SoC collapse correlates with auto mode
This is the part I cannot explain, and I want to flag it carefully — I am not claiming AstraMeter causes it, only that the correlation is hard to ignore:
discharging: off,charging: offThis is a BMS coulomb-counter drift, not a hardware fault. Marstek's own FAQ documents the fix (charge to 100% without discharging, then discharge to 0% without charging).
My working hypothesis: with cross-talk fields at zero (Issue 4), both batteries hunt independently around the zero-crossing, constantly reversing between charge and discharge. That repeated direction reversal is what drifts the coulomb counter. In manual mode there is no hunting, and no drift.
Historical HA data supports the drift pattern — SoC readings jumping like
17 → 61 → 17and0 → 60 → 0within a minute, while pack voltage stayed steady.Additional context that may matter
Parallel hm2mqtt connection. Both batteries are simultaneously connected to hm2mqtt (v1.8.1, MQTT proxy enabled) alongside AstraMeter's UDP CT002 session. This is how I could see that
reported_power = 0was wrong: hm2mqtt reportedmicro_inverter_power = 109 Wfor the same battery at the same moment. If a parallel MQTT session can affect what the battery reports over UDP, that would be worth knowing.Prior custom controller. Before AstraMeter, I ran a custom HA automation for months that wrote
time_period_1_output_valuedirectly via hm2mqtt (60 s cycle, 20 W write deadband). It is possible one battery is left in a different internal state than the other as a result — which might explain why they now take different CT002 roles. I have no way to inspect or reset that state.Timeline of the BMS collapse (relay mode did not prevent the second one):
active_control = true, capped at 20 W)active_control = false(relay mode). Saturation trap clears,target_l1jumps 20 W → 299 W, both batteries now receive identical real phase valuesSo relay mode fixed the balancer trap but did not prevent the second battery from going down. Whatever drives the BMS drift is not (only) the saturation logic.
Questions
phase='0'(inspection mode) expected for a B2500 in Self-Adaptation, or does it indicate the battery declined to participate? Is there anything on the AstraMeter side that influences which role a battery takes? Could the fact that the two batteries sit on different AC phases (L1 / L3) be related?reported_powerbe trusted as the saturation input for DC-coupled batteries at all? Here it is always 0 despite real output.min_dc_outputbe floored at the inverter's minimum operating power (~80 W for B2500) rather than allowing 20 W, which for DC batteries effectively means "off"?What I can provide: full DEBUG logs for any window, HA history for SoC / pack voltage / inverter power / grid power at 1 min resolution going back ~10 days, and I can reproduce on demand — though I would rather not, given it takes a full charge/discharge calibration cycle to recover the packs afterwards.
Version
2.2.4
Installation method
Home Assistant add-on
If "Other", which?
No response
Configuration
Logs