Fix BullTron discharge display and disconnect

This commit is contained in:
2026-07-11 12:07:09 +02:00
parent 2addde3dbc
commit bff0af18c0
2 changed files with 85 additions and 7 deletions
+46 -2
View File
@@ -42,7 +42,7 @@ class BullTronParserTest(unittest.TestCase):
self.assertTrue(state.telemetry.charge_mos)
self.assertTrue(state.telemetry.discharge_mos)
self.assertEqual(state.telemetry.cell_count, 4)
self.assertEqual(state.telemetry.time_value, "9 h 21 m")
self.assertEqual(state.telemetry.time_value, "14 h 20 m")
def test_charging_time_uses_soc_fraction_and_rated_capacity(self):
state = DeviceState(rated_capacity_ah=160)
@@ -51,7 +51,7 @@ class BullTronParserTest(unittest.TestCase):
words[41] = 30152
words[42] = 450
words[47] = 1
words[48] = 72
words[48] = 720
payload = b"".join(word.to_bytes(2, "big") for word in words)
body = bytes([0xD2, 0x03, len(payload)]) + payload
from bulltron_gui import crc16_modbus_swapped
@@ -64,6 +64,50 @@ class BullTronParserTest(unittest.TestCase):
self.assertEqual(state.telemetry.time_label, "Time till full")
self.assertEqual(state.telemetry.time_value, "5 h 47 m")
def test_current_direction_uses_signed_current_for_display(self):
state = DeviceState(rated_capacity_ah=160)
words = [0] * 62
words[40] = 128
words[41] = 29922
words[42] = 490
words[47] = 1
words[48] = 784
payload = b"".join(word.to_bytes(2, "big") for word in words)
body = bytes([0xD2, 0x03, len(payload)]) + payload
from bulltron_gui import crc16_modbus_swapped
frame = body + crc16_modbus_swapped(body).to_bytes(2, "big")
decode_response(frame, state)
self.assertAlmostEqual(state.telemetry.current, -7.8)
self.assertAlmostEqual(state.telemetry.discharge_current, 7.8)
self.assertAlmostEqual(state.telemetry.discharge_power_w, 99.84)
self.assertAlmostEqual(state.telemetry.charge_current, 0.0)
self.assertEqual(state.telemetry.time_label, "Time till empty")
self.assertEqual(state.telemetry.time_value, "10 h 03 m")
def test_bms_residue_time_register_overrides_estimate(self):
state = DeviceState(rated_capacity_ah=160)
residue_payload = (6 * 60 + 30).to_bytes(2, "big")
residue_body = bytes([0xD2, 0x03, len(residue_payload)]) + residue_payload
from bulltron_gui import crc16_modbus_swapped
residue_frame = residue_body + crc16_modbus_swapped(residue_body).to_bytes(2, "big")
decode_response(residue_frame, state)
words = [0] * 62
words[40] = 128
words[41] = 29999
words[42] = 490
words[47] = 2
words[48] = 784
payload = b"".join(word.to_bytes(2, "big") for word in words)
body = bytes([0xD2, 0x03, len(payload)]) + payload
live_frame = body + crc16_modbus_swapped(body).to_bytes(2, "big")
decode_response(live_frame, state)
self.assertEqual(state.telemetry.time_label, "Time till empty")
self.assertEqual(state.telemetry.time_value, "6 h 30 m")
def test_settings_capacity_uses_app_word_zero(self):
state = DeviceState()
words = [1600, 3750, 42] + [0] * 38