syssi / esphome-jk-bms

ESPHome component to monitor and control a Jikong Battery Management System (JK-BMS) via UART-TTL or BLE
Apache License 2.0
482 stars 161 forks source link

Add BLE support #5

Closed syssi closed 2 years ago

syssi commented 3 years ago

https://forum.drbacke.de/viewtopic.php?f=8&t=982&start=10

# service
0xffe0
# characteristic
0xffe1

# request device info
{0xaa, 0x55, 0x90, 0xeb, 0x97, 0x00, 0xdf, 0x52, 0x88, 0x67, 0x9d, 0x0a, 0x09, 0x6b, 0x9a, 0xf6, 0x70, 0x9a, 0x17, 0xfd}

# request status
{0xaa, 0x55, 0x90, 0xeb, 0x96, 0x00, 0x79, 0x62, 0x96, 0xed, 0xe3, 0xd0, 0x82, 0xa1, 0x9b, 0x5b, 0x3c, 0x9c, 0x4b, 0x5d}

# data response
{0x55, 0xAA, 0xEB, 0x90, 0x02, ...}
syssi commented 3 years ago
[ble_client:161]: Service UUID: 0x1800
[ble_client:162]:   start_handle: 0x1  end_handle: 0x9
[ble_client:341]:  characteristic 0x2A00, handle 0x3, properties 0xa
[ble_client:341]:  characteristic 0x2A01, handle 0x5, properties 0xa
[ble_client:341]:  characteristic 0x2A02, handle 0x7, properties 0x2
[ble_client:341]:  characteristic 0x2A04, handle 0x9, properties 0x2
[ble_client:161]: Service UUID: 0x1801
[ble_client:162]:   start_handle: 0xa  end_handle: 0xd
[ble_client:341]:  characteristic 0x2A05, handle 0xc, properties 0x22
[ble_client:161]: Service UUID: 0xFFE0
[ble_client:162]:   start_handle: 0xe  end_handle: 0x13
[ble_client:341]:  characteristic 0xFFE2, handle 0x10, properties 0x4
[ble_client:341]:  characteristic 0xFFE1, handle 0x12, properties 0x1c
[ble_client:161]: Service UUID: 0x180A
[ble_client:162]:   start_handle: 0x14  end_handle: 0x26
[ble_client:341]:  characteristic 0x2A29, handle 0x16, properties 0x2
[ble_client:341]:  characteristic 0x2A24, handle 0x18, properties 0x2
[ble_client:341]:  characteristic 0x2A25, handle 0x1a, properties 0x2
[ble_client:341]:  characteristic 0x2A27, handle 0x1c, properties 0x2
[ble_client:341]:  characteristic 0x2A26, handle 0x1e, properties 0x2
[ble_client:341]:  characteristic 0x2A28, handle 0x20, properties 0x2
[ble_client:341]:  characteristic 0x2A23, handle 0x22, properties 0x2
[ble_client:341]:  characteristic 0x2A2A, handle 0x24, properties 0x2
[ble_client:341]:  characteristic 0x2A50, handle 0x26, properties 0x2
[ble_client:161]: Service UUID: 0x180F
[ble_client:162]:   start_handle: 0x27  end_handle: 0x2a
[ble_client:341]:  characteristic 0x2A19, handle 0x29, properties 0x12
[ble_client:161]: Service UUID: F000FFC0-0451-4000-B000-000000000000
[ble_client:162]:   start_handle: 0x2b  end_handle: 0x33
[ble_client:341]:  characteristic F000FFC1-0451-4000-B000-000000000000, handle 0x2d, properties 0x1c
[ble_client:341]:  characteristic F000FFC2-0451-4000-B000-000000000000, handle 0x31, properties 0x1c
syssi commented 3 years ago

https://medium.com/@charlie.d.anderson/how-to-get-the-bluetooth-host-controller-interface-logs-from-a-modern-android-phone-d23bde00b9fa

syssi commented 2 years ago

Todos:

syssi commented 2 years ago

https://github.com/jblance/mpp-solar/issues/170#issuecomment-1050503970

JohnGalt1717 commented 2 years ago

It would be really awesome if you could pull data from multiple over BLE in home assistant. I have 4 and really don't want to have 4 esp32s or something running. I'd love to be able to do all 4 in one shot. Obviously I could use a rs484 breakout chip, but not sure that that is supported with ESPhome yet.

Alternatively CanBus would be awesome with the ability to read multiples.

syssi commented 2 years ago

@JohnGalt1717 The modbus interface / firmware of the JK-BMS doesn't support device addresses. In other words: You cannot attach multiple devices to the same (mod)bus. A ESP32 has 3 hardware UARTs so you can attach 3 BMS to 1 ESP without much effort.

In feature I will improve/add this BLE support so you will be able to query the data without connecting any cables.

supiiik commented 2 years ago

In feature I will improve/add this BLE support so you will be able to query the data without connecting any cables.

It would be great. At the moment I afraid (little bit) to connect BMS by wire because of the potential to destroy the board (https://github.com/syssi/esphome-jk-bms/issues/28). The BLE connection should be totally safe from this perspective.

syssi commented 2 years ago

To be careful is a good idea but don't be too scared the RS485 (TTL) port is read-only if we can trust the seller.

supiiik commented 2 years ago

Is it possible to connect only GND and RX (on ESP) to read data? Will this work? Or the ESP is sending data requests to BMS over TX?

syssi commented 2 years ago

This doesn't work because the status frame must be requested.

JohnGalt1717 commented 2 years ago

FYI, one of the esp32 uarts is read only so you’ll get only 2 per esp32. Hence why it would be nice to use Canbus because surely since can natively does daisy chaining you can find all of them ….

JohnGalt1717 commented 2 years ago

But it seems that as long as you can use 9600 baud you can have as many software uarts as pins…

https://esphome.io/components/uart.html

Does this work here to control many units?

syssi commented 2 years ago

You are mixing things up here. The ESP32 has 3 hardware UARTs and a GPIO matrix. Because of the GPIO matrix you can use any GPIO as RX/TX pin (if the GPIO supports input and output). In summary: You can connect 3 BMS to the 3 hardware UARTs. The JK-BMS uses 115200 baud (in general). Some old versions use slower baudrates.

If you want to use a ESP8266 there is just one accessible hardware UART and no GPIO matrix. You must use GPIO1 and GPIO3 if you want to use the hardware UART. The ESPHome platforms provides a software serial implementation (ESP8266 only!). So you can use any GPIO as software UART but please be careful: Software serial and high baudrates aren't recommended.

Long story short: BLE is your best bet. ;-)

syssi commented 2 years ago

The BLE support (read-only for now) is ready. Please give it a try:

  1. Download this example config https://raw.githubusercontent.com/syssi/esphome-jk-bms/main/esp32-ble-example.yaml
  2. Change the mac_address to the MAC address of your BMS
  3. Compile and flash: esphome run esp32-ble-example.yaml
JohnGalt1717 commented 2 years ago

Thanks!

What's the best/easiest way to get the mac addresses required for this?

syssi commented 2 years ago

@JohnGalt1717 Flash the yaml with some random address, start the ESP32 and take a look at the logs. The BLE tracker will report every device in the air. You should find the mac address next to the name of your BMS here.

syssi commented 2 years ago

It looks like this:

[14:24:01][D][esp32_ble_tracker:723]: Found device C8:47:8C:F2:7E:03 RSSI=-90
[14:24:01][D][esp32_ble_tracker:744]:   Address Type: PUBLIC
[14:24:01][D][esp32_ble_tracker:746]:   Name: 'JK-BD6A17S6P'
JohnGalt1717 commented 2 years ago

Ok, I got it working with 1 and 2 BMSes. But as soon as you add a 3rd which should be supported (BLE uses the Uarts underneath so you'll get 3 max) it errors on compilation. 2 works fine...

syssi commented 2 years ago

Could you provide the exact error message?

JohnGalt1717 commented 2 years ago

(yes that's it)

There's some warnings above that of a possible fall through a switch statement, but with 2 instead of 3 it compiles fine.

syssi commented 2 years ago

Could you try to reduce the number of sensors just for testing. Try somehting like this:

substitutions:
  name: jk-bms
  external_components_source: github://syssi/esphome-jk-bms@main
  mac_address0: C8:47:FF:FF:FF:FF
  mac_address1: C8:47:FF:FF:FF:FF
  mac_address2: C8:47:FF:FF:FF:FF

esphome:
  name: ${name}

esp32:
  board: wemos_d1_mini32
  framework:
    type: esp-idf
    version: latest

external_components:
  - source: ${external_components_source}
    refresh: 0s

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

ota:
logger:

api:

esp32_ble_tracker:

ble_client:
  - mac_address: ${mac_address0}
    id: client0
  - mac_address: ${mac_address1}
    id: client1
  - mac_address: ${mac_address2}
    id: client2

jk_bms_ble:
  - ble_client_id: client0
    throttle: 5s
    id: bms0
  - ble_client_id: client1
    throttle: 5s
    id: bms1
  - ble_client_id: client2
    throttle: 5s
    id: bms2

sensor:
  - platform: jk_bms_ble
    jk_bms_ble_id: bms0
    min_cell_voltage:
      name: "${name} min cell voltage"
    max_cell_voltage:
      name: "${name} max cell voltage"
    min_voltage_cell:

  - platform: jk_bms_ble
    jk_bms_ble_id: bms1
    min_cell_voltage:
      name: "${name} min cell voltage"
    max_cell_voltage:
      name: "${name} max cell voltage"
    min_voltage_cell:

    - platform: jk_bms_ble
    jk_bms_ble_id: bms2
    min_cell_voltage:
      name: "${name} min cell voltage"
    max_cell_voltage:
      name: "${name} max cell voltage"
    min_voltage_cell:

I don't think the number of BLE connections is limited by the number of hardware UARTs. I think your ESP32 crashs because of a stack overflow. If the "reduced sensor example" works for you I would provide some instructions how to increase the stack size to have room for a lot of sensors.

JohnGalt1717 commented 2 years ago

I have things hooked in home assistant and didn't want it to go nuts so I manually updated the stack size, and it seems to have solved it.

If you try and add a 4th ble_client it will error and not let you compile. My understanding is that the underlying ble_client is actually using BLE Serial which uses UARTs so limited to 3 on esp32.

On another note, the Balancing Enabled switch doesn't appear to be working with BLE.

syssi commented 2 years ago

You are right about the balancing_enabled switch. There a some unknowns at the (cell info) frame/payload. I'm not sure the balancing enabled bit is part of the frame. If you are able to identify some status/error bits I would be happy about your support/analysis.

JohnGalt1717 commented 2 years ago

I can't find anything in any of the docs floating around about where these values should be pulled from BLE, so I'm mystified that you even figured it out ! If you have any docs that might point me in the right direction, I'd be happy to have a go.

syssi commented 2 years ago

I don't have any docs about the BLE traffic. I've used a traffic capture (btsnoop) to reverse engineer the communication plus some existing code from different open source projects (f.e. mpp-solar).

JohnGalt1717 commented 2 years ago

Ok, I'll see what I can come up with.

syssi commented 2 years ago

Please monitor the "Unknown" messages at the log. Stop the ESP, change a setting via the App, close the app and let the ESP reconnect. Check the "Unknown" log lines again. May be you can identify some status bits or bytes.

JohnGalt1717 commented 2 years ago

The trick is that with ble you can't use the app at the same time... and I have multiple but the logs don't seem to dump which is which so it's hard to track. If I had to guess it's Unknown 12 and 13 based on the info. (Unknown 15 also changes when you enable and disable active balancing)

syssi commented 2 years ago

@JohnGalt1717 I've pushed a breaking change. Please adapt your configuration yaml:

https://github.com/syssi/esphome-jk-bms/pull/83

  1. Remove the balancing_switch.
  2. Rename charging_switch to charging
  3. Rename discharging_switch to discharging
  4. Add the binary_sensor balancing

All binary sensors are indicators of the current status of the BMS. They don't represent switch states.

JohnGalt1717 commented 2 years ago

Seemed to work!

There's a bunch of items I'd love to be able to change if changing is possible (then I wouldn't need to ever use the app)

  1. OVCP (over voltage cell protection) (i.e. 3.65 or 3.55 etc.)
  2. OVCR (over voltage cell recovery) (i.e. 3.6 or 3.5 or whatever it falls back to before turning charge on again automatically)
  3. UVDP (under voltage discharge protection)
  4. UVCP (under voltage discharge recovery)
  5. Enable/Disable Charging, Balancing and Discharging.
  6. Delta for Cell Balancing
  7. Min Cell Voltage for Cell Balancing

Not sure if this is possible. Maybe an option to pass in the pass code in the yaml configuration and then be able to setup switches for No. 5 and then text fields for the rest?

syssi commented 2 years ago

Please subscribe #73 to track the progress of the mentioned features. Control the BMS via BLE is on my roadmap.

JohnGalt1717 commented 2 years ago

Awesome! Thanks!

tssparky commented 3 months ago

Hello, I’ve been trying to use BLE to get data from jk BMS for days, I didn’t want to use esphome as I want to just print to screen or serial for now. so I used the logic and methods of this code to connect and get data but. System finds bms, connects, gets a bit of info from FF01, and it’s just jk model, user password (hmm not so good probably) and software version. If I try to connect to 180F or 180A, it won’t connect, can’t find service. at one point I thought I got it going and was just a parsing issue but the data appears static. has the data structure changed? Since this esphome version was created? I can post my code if there is anyone here to read it and hopefully point me in the right direction. any advice will be appreciated Cheers Nick

Been using VScode with esp32-s3 / arduino ide.

syssi commented 3 months ago

Please create a new issue. Please keep in mind ESPHome is very flexible. If you remove the wifi section and the other components requiring network access (ota f.e.) you can also reach your goal without writing a second implementation.