Skip to content

JBD: support reliable MOS control and extended diagnostics - #419

Merged
fl4p merged 2 commits into
fl4p:masterfrom
tednv:feature/jbd-mos-control
Oct 17, 2026
Merged

fl4p merged 2 commits into
fl4p:masterfrom
tednv:feature/jbd-mos-control

Conversation

@tednv

@tednv tednv commented Oct 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • use the complete JBD factory-mode transaction for charge/discharge MOS commands
  • reconnect when keep_alive is disabled, preserve the other MOS state, ignore already-satisfied retained commands, and verify each write
  • expose read-only JBD identity, firmware, capacity, protection, balance, voltage-curve, and configuration registers through MQTT discovery
  • support display_name and comma-separated temperature_names without changing MQTT topics or entity unique IDs

On supported JBD firmware, this can re-enable charging when an undervoltage event has left the charge MOS disabled, including states where standard app controls are unavailable. Active protection conditions are not bypassed.

Scope

Extended JBD settings are read-only. Existing charge and discharge switches remain the only settings this change writes.

Validation

  • tested through Home Assistant with a JBD 14S BMS running firmware version 3.2
  • verified the MOS-control sequence and state readback against the physical BMS
  • 23 JBD tests passed
  • 5 MQTT discovery and sampling tests passed
  • Python compilation and git diff --check passed

Closes #418

@fl4p
fl4p merged commit 92f3421 into fl4p:master Oct 17, 2026
6 checks passed
fl4p added a commit that referenced this pull request Oct 17, 2026
…y type (#419 follow-up)

- fetch_device_info exited factory mode with 28 28, which also saves to
  EEPROM (dbus-serialbattery lltjbd), on every add-on start. Now 00 00.
- Settings registers time out after 2 s and the read stops after 3
  unanswered in a row; at 16 s each a clone could stay in factory mode for
  ~15 minutes before the first sample.
- A BMS that refuses factory mode still returns basic info, so the
  sampler doesn't re-enter it every discovery period.
- Register 0x16 is no longer DeviceInfo.sn: sn is the HA device identifier,
  and clones sharing a factory serial would merge into one device.
- display_name and temperature_names apply to every type via discovery;
  extra values carry their own topic prefix instead of a hardcoded jbd/.
- Changelog entries within the 30-word gate.
fl4p added a commit that referenced this pull request Oct 17, 2026
…o EEPROM rewrite loop

Review findings on the #419 switch path:
- MQTT switch commands run in the background loop, concurrently with the
  sampler: its disconnect (keep_alive off) could cut the factory-mode
  sequence after 56 78, leaving the BMS in factory mode, and both could
  wait on future 0x03 at once. Register I/O and __aexit__ now share a lock,
  and a command that arrives disconnected is applied by the next fetch
  instead of a connect outside ConnectLock.
- The algorithm's switch call raised on a verification failure and lost
  the sample; the calibration branch asks every sample while a protection
  holds charge off, so each poll was a factory-mode write + EEPROM save.
  The sampler now logs the failure, and a written state is not rewritten
  for 10 minutes.
- "Already in that state" skipped a command a protection was forcing, so
  the FET came back when it cleared; the skip now needs problem_code 0.
- The other FET's bit comes from the last command, not from a protection.
- A refused reply (status != 0) reaches the waiter instead of a 16 s
  timeout; the status is checked after the checksum.
- fetch_device_info sends 00 00 even if the enter ack was lost.
@fl4p

fl4p commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Thanks, merged and released in 2.25. I changed a few things on top (63c3df7, e46a566, ef589fe):

  • Settings read leaves factory mode with 00 00. 28 28 also saves to EEPROM (dbus-serialbattery lltjbd.py), and that ran on every add-on start. Switch writes still exit with 28 28, as you tested.
  • Settings registers time out after 2 s, and the read stops after 3 unanswered in a row. At 16 s each, a clone could sit in factory mode for ~15 min before the first sample.
  • Register 0x16 is no longer the HA device identifier. Clones share factory serials and would merge into one device.
  • display_name / temperature_names work for every BMS type, not only jbd.
  • Switch commands from MQTT run concurrently with the sampler. Its disconnect could cut the sequence between 56 78 and the exit, leaving the BMS in factory mode. Register I/O, disconnect and the periodic reconnect now share a lock. With keep_alive: false, a command is applied at the next poll instead of opening its own connection.
  • A refused write no longer drops the sample when the algorithm made it. Under an active protection, the same state isn't rewritten for 10 min (each write is an EEPROM save).
  • A command a protection is forcing is still written once, so the FET stays there after the protection clears. The other FET keeps its last commanded state, not the one a protection set.
  • A status != 0 reply raises right away instead of a 16 s timeout.

If you can, please check 2.25 on your 14S: switch charge off/on from HA, and once with keep_alive: false.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JBD charge MOS recovery and extended read-only diagnostics

2 participants