mpp-solar: Cannot connect to JK BMS/Active Balancer
Tried both JK02/04. I am sure its something simple I am missing here. Using RPI4 4gb
jkbms -p C8:47:8C:F3:75:92 -P JK02 -D
2021-10-23 17:17:55,859:INFO:__init__:main@195: Solar Device Command Utility, version: 0.7.83, add missing libs
MqttBroker(name='localhost', port=1883, username=None, password=None, results_topic='jkbms')
2021-10-23 17:17:55,859:INFO:__init__:main@299: Creating device "unnamed" (type: "jkbms") on port "C8:47:8C:F3:75:92 (porttype=None)" using protocol "JK02"
2021-10-23 17:17:55,867:DEBUG:__init__:main@302: device_class <class 'mppsolar.devices.jkbms.jkbms'>
2021-10-23 17:17:55,867:DEBUG:device:__init__@31: __init__ args ()
2021-10-23 17:17:55,867:DEBUG:device:__init__@32: __init__ kwargs {'name': 'unnamed', 'port': 'C8:47:8C:F3:75:92', 'protocol': 'JK02', 'baud': 2400, 'porttype': None, 'mqtt_broker': MqttBroker(name='localhost', port=1883, username=None, password=None, results_topic='jkbms')}
2021-10-23 17:17:55,868:DEBUG:device:get_port_type@71: port matches jkble ':'
2021-10-23 17:17:55,868:INFO:device:set_port@154: Using jkbleio for communications
2021-10-23 17:17:55,902:DEBUG:device:set_protocol@96: Protocol JK02
2021-10-23 17:17:55,923:DEBUG:device:__init__@36: __init__ name unnamed, port <mppsolar.io.jkbleio.JkBleIO object at 0xb5d945b0>, protocol <mppsolar.protocols.jk02.jk02 object at 0xb5d7be70>
2021-10-23 17:17:55,923:DEBUG:__init__:main@349: Commands [(<mppsolar.devices.jkbms.jkbms object at 0xb5d7bed0>, '', '', 'screen', None, None)]
2021-10-23 17:17:55,923:INFO:__init__:main@354: Looping 1 commands
2021-10-23 17:17:55,924:INFO:__init__:main@365: Getting results from device: jkbms device - name: unnamed, port: <mppsolar.io.jkbleio.JkBleIO object at 0xb5d945b0>, protocol: <mppsolar.protocols.jk02.jk02 object at 0xb5d7be70> for command: , tag: , outputs: screen
2021-10-23 17:17:55,924:INFO:device:run_command@268: Running command
2021-10-23 17:17:55,924:INFO:jkabstractprotocol:get_full_command@71: Using protocol b'JK02' with 3 commands
2021-10-23 17:17:55,924:DEBUG:jkabstractprotocol:get_command_defn@102: get_command_defn for: getCellData
2021-10-23 17:17:55,924:DEBUG:abstractprotocol:get_command_defn@43: Processing command 'getCellData'
2021-10-23 17:17:55,924:DEBUG:abstractprotocol:get_command_defn@45: Found command getCellData in protocol b'JK02'
2021-10-23 17:17:55,924:DEBUG:jkabstractprotocol:get_full_command@76: self._command = getCellData
2021-10-23 17:17:55,924:DEBUG:jkabstractprotocol:get_full_command@87: cmd with SOR: bytearray(b'\xaaU\x90\xeb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
2021-10-23 17:17:55,925:DEBUG:jkabstractprotocol:get_full_command@95: cmd with command code: bytearray(b'\xaaU\x90\xeb\x96\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
2021-10-23 17:17:55,925:DEBUG:jkabstractprotocol:get_full_command@97: cmd with crc: bytearray(b'\xaaU\x90\xeb\x96\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10')
2021-10-23 17:17:55,925:INFO:device:run_command@294: full command bytearray(b'\xaaU\x90\xeb\x96\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10') for command getCellData
2021-10-23 17:17:55,925:DEBUG:jkabstractprotocol:get_command_defn@102: get_command_defn for: getCellData
2021-10-23 17:17:55,925:DEBUG:abstractprotocol:get_command_defn@43: Processing command 'getCellData'
2021-10-23 17:17:55,925:DEBUG:abstractprotocol:get_command_defn@45: Found command getCellData in protocol b'JK02'
2021-10-23 17:17:55,925:INFO:jkabstractprotocol:get_full_command@71: Using protocol b'JK02' with 3 commands
2021-10-23 17:17:55,925:DEBUG:jkabstractprotocol:get_command_defn@102: get_command_defn for: getCellData
2021-10-23 17:17:55,926:DEBUG:abstractprotocol:get_command_defn@43: Processing command 'getCellData'
2021-10-23 17:17:55,926:DEBUG:abstractprotocol:get_command_defn@45: Found command getCellData in protocol b'JK02'
2021-10-23 17:17:55,926:DEBUG:jkabstractprotocol:get_full_command@76: self._command = getCellData
2021-10-23 17:17:55,926:DEBUG:jkabstractprotocol:get_full_command@87: cmd with SOR: bytearray(b'\xaaU\x90\xeb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
2021-10-23 17:17:55,926:DEBUG:jkabstractprotocol:get_full_command@95: cmd with command code: bytearray(b'\xaaU\x90\xeb\x96\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
2021-10-23 17:17:55,926:DEBUG:jkabstractprotocol:get_full_command@97: cmd with crc: bytearray(b'\xaaU\x90\xeb\x96\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10')
2021-10-23 17:17:55,926:INFO:jkbleio:send_and_receive@26: full command bytearray(b'\xaaU\x90\xeb\x96\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10') for command getCellData
2021-10-23 17:17:55,926:DEBUG:jkabstractprotocol:get_command_defn@102: get_command_defn for: getCellData
2021-10-23 17:17:55,927:DEBUG:abstractprotocol:get_command_defn@43: Processing command 'getCellData'
2021-10-23 17:17:55,927:DEBUG:abstractprotocol:get_command_defn@45: Found command getCellData in protocol b'JK02'
2021-10-23 17:17:55,927:DEBUG:jkbleio:send_and_receive@30: expected record type 2 for command getCellData
2021-10-23 17:17:55,927:INFO:jkbleio:ble_connect@54: Attempting to connect to C8:47:8C:F3:75:92
2021-10-23 17:17:57,123:INFO:jkbleio:ble_get_data@82: Connected to b''
Traceback (most recent call last):
File "/usr/local/bin/jkbms", line 33, in <module>
sys.exit(load_entry_point('mppsolar', 'console_scripts', 'jkbms')())
File "/home/pi/Python-3.6.9/src/mpp-solar/mppsolar/__init__.py", line 367, in main
results = _device.run_command(command=_command)
File "/home/pi/Python-3.6.9/src/mpp-solar/mppsolar/devices/device.py", line 311, in run_command
command_defn=self._protocol.get_command_defn(command),
File "/home/pi/Python-3.6.9/src/mpp-solar/mppsolar/io/jkbleio.py", line 34, in send_and_receive
response = self.ble_get_data(full_command)
File "/home/pi/Python-3.6.9/src/mpp-solar/mppsolar/io/jkbleio.py", line 91, in ble_get_data
characteristicRead = serviceNotify.getCharacteristics(characteristicReadUuid)[0]
IndexError: list index out of range
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 40 (12 by maintainers)
Commits related to this issue
- Add another bluetooth capture https://github.com/jblance/mpp-solar/issues/170#issuecomment-952375557 — committed to syssi/esphome-jk-bms by syssi 3 years ago
Thanks syssi. I got it to work by removing the ord() function from the line crc = ord(record[299])
I implemented a JKBMS Emulator based on a JDY-23 BLE module. The commands to change values are always based on a 20 byte frame with following format: Set Command:
The register addresses (AD) are as follows:
Btw, the first response on CMDINFO is a record type 0x01 that contains all setup data, then JKBMS continues periodically with record type 0x02 (Cell data). Based on this information one is able cover almost the whole functionality as the JKBMS App. Here the record structure (record type 0x01) with real data from my LiPoFe4 battery block:
I could also find some more useful data in the Cell info frame (record type 0x02). At position 0x88 the possible 16 different System Alarms are shown and at 0x3E/3F the actual min and max cell number is distributed. Here the screenshot of the grammar:
Finally the data analysis function I am using to convert the data on an ESP32: DATA_ANALYSIS.ino.zip
@bullar Do you like to share the code of your JK-BMS emulator? There is a new BMS model (B2A8S20P, hardware version 11) and some registers has been changed.
@LMMKnight This checksum should work for your device:
The checksum is always at position 300 even if the frame is 320 bytes long.
To get things working on HW Ver 8.x and Software Ver 8.20G
I had to switch to a Raspberry Pi 4 with bluetooth 5.0 and change the following code:
def ble_connect(self, mac=None, protocol=None, record_type=0x02): “”" Connect to a BLE device with ‘mac’ address “”" self._device = None # Intialise BLE device self._device = btle.Peripheral(None) self._device.withDelegate(jkBleDelegate(self, protocol, record_type)) # Connect to BLE Device connected = False attempts = 0 log.info(f"Attempting to connect to {mac}“) while not connected: attempts += 1 if attempts > self.maxConnectionAttempts: log.warning(f"Cannot connect to mac {mac} - exceeded {attempts - 1} attempts”) return connected try: self._device.connect(mac) self._device.setMTU(244) #this must be added to receive more than 20 bytes in a single message 120, 120, 64 = 320 total connected = True except Exception: continue return connected
I also had to tweak the FFE3 to FFE1 and here’s the new format for the info:
SOR = bytes.fromhex(“55aaeb90”)
COMMANDS = { “getInfo”: { “name”: “getInfo”, “command_code”: “97”, “record_type”: “3”, “description”: “BLE Device Information inquiry”, “help”: " – queries the ble device information", “type”: “QUERY”, “response_type”: “POSITIONAL”, “response”: [ [“Hex2Str”, 4, “Header”, “”], [“Hex2Str”, 1, “Record Type”, “”], [“Hex2Int”, 1, “Record Counter”, “”], [“Hex2Ascii”, 12, “Device Model”, “”], [“Hex2Ascii”, 10, “Hardware Version”, “”], [“Hex2Ascii”, 10, “Software Version”, “”], [“uptime”, 3, “Up Time”, “”], [“Hex2Str”, 2, “Power-on Times”, “”], [“Hex2Ascii”, 13, “Device Name”, “”], [“Hex2Ascii”, 22, “Device Passcode”, “”], [“Hex2Ascii”, 6, “Manufacturing Date”, “”], [“Hex2Ascii”, 12, “Serial Number”, “”], [“discard”, 5, “”, “”], [“Hex2Ascii”, 17, “User Data”, “”], [“Hex2Ascii”, 16, “Settings Passcode?”, “”], [“discard”, 672, “unknown”, “”], ], “test_responses”: [ bytes.fromhex( “55aaeb9003f14a4b2d42324132345300000000000000332e300000000000332e322e330000000876450004000000506f7765722057616c6c203100000000313233340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c2” ), bytes.fromhex( “55aaeb9003b54a4b2d42443641323053313050000000342e300000000000342e312e37000000541d1600040000004e6f7468696e67204a4b31000000000031323334000000000000000000000000323030373038000032303036323834303735000000000000496e707574205573657264617461000031323334353600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c4” ), ], }, }
Also the crc is broken so I skipped those lines. log.debug(f"Record Length:{len(record)}“) if len(record) == 300 or len(record) == 320: # check the crc/checksum is correct for the record data crc = ord(record[-1:]) calcCrc = crc8(record[:-1]) log.debug(f"crc {crc} calcCrc {calcCrc}”)# print (crc, calcCrc) return True if crc == calcCrc: log.debug(“Record CRC is valid”) return True return False
Another implementation using
FFE0and charFFE1: https://github.com/syssi/esphome-jk-bms/pull/10/files