From 1258e35d09016c18fe5d91922afc0c56fcdc931d Mon Sep 17 00:00:00 2001 From: Alex Ebeling-Hoppe Date: Sat, 23 Mar 2024 20:38:35 +0100 Subject: [PATCH] works with new JBD BMS with internal BT tested with 16S AP21S002P21200A --- jbdbt.py | 57 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/jbdbt.py b/jbdbt.py index 2bb0d95..0ab7503 100644 --- a/jbdbt.py +++ b/jbdbt.py @@ -10,7 +10,7 @@ import atexit import os -# 0 disabled, or set the number of seconds to detect BT hang, and reboot. +# 0 disabled, or set the number of seconds to detect BT hang, and reboot. BT_WATCHDOG_TIMER=300 @@ -64,6 +64,7 @@ def __init__(self, address): self.cellData = None self.cellDataTotalLen = 0 self.cellDataRemainingLen = 0 + self.last_state = "0000" self.generalDataCallback = None self.generalData = None @@ -95,14 +96,14 @@ def run(self): continue try: - if self.bt.waitForNotifications(0.5): + if self.bt.waitForNotifications(2): continue if (time.monotonic() - timer) > self.interval: timer = time.monotonic() result = self.bt.writeCharacteristic(0x15, b'\xdd\xa5\x03\x00\xff\xfd\x77', True) # write x03 (general info) #time.sleep(1) # Need time between writes? - while self.bt.waitForNotifications(0.5): + while self.bt.waitForNotifications(1): continue result = self.bt.writeCharacteristic(0x15, b'\xdd\xa5\x04\x00\xff\xfc\x77', True) # write x04 (cell voltages) @@ -128,8 +129,9 @@ def addGeneralDataCallback(self, func): def handleNotification(self, cHandle, data): hex_data = binascii.hexlify(data) - hex_string = hex_data.decode('utf-8') - #print(hex_string) + hex_string = hex_data.decode('utf-8') + logger.info("new Hex_String(" +str(len(data))+"): " + str(hex_string)) + HEADER_LEN = 4 #[Start Code][Command][Status][Length] FOOTER_LEN = 3 #[16bit Checksum][Stop Code] @@ -138,36 +140,40 @@ def handleNotification(self, cHandle, data): # Cell Data if hex_string.find('dd04') != -1: + self.last_state = "dd04" # Because of small MTU size, the BMS data may not be transmitted in a single packet. # We use the 4th byte defined as "data len" in the BMS protocol to calculate the remaining bytes - # that will be transmitted in the second packet + # that will be transmitted in the second packet self.cellDataTotalLen = data[3] + HEADER_LEN + FOOTER_LEN self.cellDataRemainingLen = self.cellDataTotalLen - len(data) + logger.info("cellDataTotalLen: " + str(int(self.cellDataTotalLen))) + logger.info("cellDataRemainingLen: " + str(int(self.cellDataRemainingLen))) self.cellData = data - elif hex_string.find('77') != -1 and len(data) == self.cellDataRemainingLen: # Look for the stop code, and check if the len matches P2Len (i.e. the remaining bytes) + elif self.last_state == "dd04" and hex_string.find('dd04') == -1 and hex_string.find('dd03') == -1: self.cellData = self.cellData + data + self.cellDataCallback(self.cellData) + logger.info("Final Length cellData(" + str(len(self.cellData))+ "): " + str(binascii.hexlify(self.cellData).decode('utf-8'))) + # General Data elif hex_string.find('dd03') != -1: + self.last_state = "dd03" self.generalDataTotalLen = data[3] + HEADER_LEN + FOOTER_LEN self.generalDataRemainingLen = self.generalDataTotalLen - len(data) + logger.info("generalDataTotalLen: " + str(int(self.generalDataTotalLen))) + logger.info("generalDataRemainingLen: " + str(int(self.generalDataRemainingLen))) self.generalData = data - elif hex_string.find('77') != -1 and len(data) == self.generalDataRemainingLen: - self.generalData = self.generalData + data - - # Hack - elif len(data) == 20: - self.cellData = self.cellData + data - self.cellDataRemainingLen = self.cellDataRemainingLen - len(data) + elif self.last_state == "dd03" and hex_string.find('dd04') == -1 and hex_string.find('dd03') == -1: + self.generalData = self.generalData + data + self.generalDataCallback(self.generalData) + logger.info("Final Length generalData(" + str(len(self.generalData)) + "): " + str(binascii.hexlify(self.generalData).decode('utf-8'))) - if self.cellData and len(self.cellData) == self.cellDataTotalLen: - self.cellDataCallback(self.cellData) + if self.last_state == "dd04" and self.cellData and len(self.cellData) == self.cellDataTotalLen: + self.last_state == "0000" self.cellData = None - if self.generalData and len(self.generalData) == self.generalDataTotalLen: - self.generalDataCallback(self.generalData) + if self.last_state == "dd03" and self.generalData and len(self.generalData) == self.generalDataTotalLen: + self.last_state == "0000" self.generalData = None - - class JbdBt(Battery): def __init__(self, address): @@ -348,7 +354,7 @@ def generalDataCB(self, data): self.mutex.release() def checkTS(self, ts): - elapsed = 0 + elapsed = 0 if ts: elapsed = time.monotonic() - ts @@ -359,7 +365,7 @@ def checkTS(self, ts): return if elapsed > BT_WATCHDOG_TIMER: - logger.info('Watchdog timer expired. BT chipset might be locked up. Rebooting') + logger.info('Watchdog timer expired. BT chipset might be locked up. Rebooting') os.system('reboot') @@ -373,21 +379,14 @@ def checkTS(self, ts): #batt = JbdBt( "70:3e:97:08:00:62" ) #batt = JbdBt( "a4:c1:37:40:89:5e" ) #batt = JbdBt( "a4:c1:37:00:25:91" ) - batt.get_settings() while True: batt.refresh_data() - print("Cells " + str(batt.cell_count) ) - for c in range(batt.cell_count): print( str(batt.cells[c].voltage) + "v", end=" " ) - print("") - - time.sleep(5) -