Skip to content

Commit

Permalink
works with new JBD BMS with internal BT tested with 16S AP21S002P21200A
Browse files Browse the repository at this point in the history
  • Loading branch information
AEHluis committed Mar 23, 2024
1 parent 26f2793 commit 1258e35
Showing 1 changed file with 28 additions and 29 deletions.
57 changes: 28 additions & 29 deletions jbdbt.py
Expand Up @@ -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


Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand All @@ -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]
Expand All @@ -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):
Expand Down Expand Up @@ -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

Expand All @@ -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')


Expand All @@ -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)



0 comments on commit 1258e35

Please sign in to comment.