mpp-solar icon indicating copy to clipboard operation
mpp-solar copied to clipboard

implement extra commands for JK02 (set commands)

Open jblance opened this issue 4 years ago • 7 comments

But what wasn't obvious to me anymore is how protocols/jk02.py is structured...nor can i find any documentation on the jk02 protocol.... After comparing the commands in jk02 and my wireshark capture from earlier, I can confirm that command 0x96 was indeed being sent from my capture: 1621269103580 although as opposed to being followed by 0x00's until the last crc8 byte, there's a bunch of numbers there that, don't seem to correlate to anything?

In any case, I looked further to see my other commands, and can confirm the following: Command Code 0x04 0x04 - parameter 0x42 0x0E (3650 in decimal) This sets Cell OVP to 3.65 Volt 1621269242512

Command Code 0x05 0x04 - parameter 0x3D 0x0E (3645 in decimal) This sets Cell OVPR to 3.645 Volts 1621269307837

Command Code 0x03 0x04 - parameter 0xC5 0x09 (2501 in decimal) This sets Cell UVPR to 2.501 Volts 1621269471734

Command Code 0x02 0x04 - parameter 0xC4 0x09 (2500 in decimal) This sets Cell UVP to 2.5 Volts 1621269628394 Command Code 0x0b 0x04 - parameter 0x60 0x09 (2400in decimal) This sets Power Off Vol. to 2.400 Volts 1621269710971

Command Code 0x26 0x04 - parameter 0xc4 0x09 (2500 decimal) This sets Start Balance Volt to 2.500 Volts 1621269781245

Command Code 0x13 0x04 - parameter 0xd0 0x07 (2000 in decimal) This sets Max Balance Cur. to 2.000 Amps 1621269898372

That's kinda where I stopped logging my BLE since I wasn't even sure if my android was even capturing the packets.. those were the configs under the Advance Settings section. Are you able to implement those for JK02 please so I can use your py code as a template to implement the rest of the commands after I run more captures and grab the rest of them???

Thanks heaps in advance! Cheers, lonertic

jblance avatar May 18 '21 23:05 jblance

more from lonertic

  • under the JK02 protocol, there were a few unknowns and discards... having the benefit of 3 identical BMS's I can query them and cross-reference them to the screenshot of the app to check these. Mainly...

  • found battery_power and charge_current ..I don't think you have a decoder for a signed Int32?? Closest I found was 4ByteHex1000... but charge current is basically a signed int32 divide by 1000 to get the amps... so the number itself is in units of milliamps. Same as Battery_power, that's also int32 divide by 1000 to get watts... It does mean the "current_charge and current_discharge" values further down the definition, appears to be wrong... on the app at least, that's a single number.. and the values returned by current_charge/current_discharge doesnt correlate to the actual charge/discharge current of the BMS's...so it's worth considering removing those.

  • And the other one I found was cycle_count, which was previously unknown10... it's another int32... safe to assume it's actually a uint32 since it's not possible to have a negative cycle count.

  • Whilst I've also verified Percent_remain value is correct, it was actually easier (and more precise) for me to simply calculate it on the fly using capacity_remain / nominal_capacity... so perhaps you could look into that too?

1622384257446

jblance avatar Jun 14 '21 23:06 jblance

Command Code 0x0b 0x04 - parameter 0x60 0x09 (2400in decimal) This sets Power Off Vol. to 2.400 Volts /> Does this mean I might be able to set this to below 2V in the future??? I run lead carbon batteries and have to use an AAA battery in series to B1 to wake it up, then whenever it goes below 2V it has a chance of shutting down until I notice...

bobwho69 avatar Sep 15 '21 11:09 bobwho69

I guess the main thing missing here is to figure out what the last 10 bytes of the command mean? Presumably some kind of crc and maybe frame numbers?

It would be good to do a capture of 2 things:

  • same command with the same value multiple times
  • same command, but different values, with some examples of single bit changes e.g. 3650 and 3651

I also got the disassembly from the APK of the section, which I believe is the construction of the command (at least it contains the reference to the magic 4 bytes). Happy to provide the full disassembly if anyone has time to make sense out of it. sendCommand.c.txt

trixing avatar Sep 17 '21 09:09 trixing

On further investigation this investment is probably not necessary. I'm able to replay the commands and change the values in the BMS. I tried this with the balancer start voltage:

# original bytes
setBalanceStart2500 = [0xAA, 0x55, 0x90, 0xEB, 0x26, 0x04, 0xc4, 0x09, 0x00, 0x00, 0x23, 0xB2, 0xCD, 0x31, 0x2D, 0x28, 0xF2, 0x6B, 0x04, 0xFA]
# modify value
x = setBalanceStart2500.copy()
x[7] = int(2501 / 256)
x[6] = 2501 % 256
# re-calculate checksum
x[-1] = sum(x[0:-1])%256

And then (incomplete, but hacked into jkbleio.py, ble_get_data)

characteristicWriteUuid = "ffe1"
chars = serviceNotify.getCharacteristics(characteristicWriteUuid)
characteristicRead = chars[0]
handleRead = characteristicRead.getHandle()
self._device.writeCharacteristic(handleRead, command)

When I read the value again (via RS485 actually, where I can't get the write support to work), it's set to 2501.

If this is true for other commands, it should be relatively straight forward to generalize.

trixing avatar Sep 17 '21 11:09 trixing

Attached is the proof of concept to set the balancer start voltage:

jkbleio_write_cmd.py.txt

trixing avatar Sep 17 '21 11:09 trixing