HomeAssistant Bluetooth BMS Monitoring Server Guide [ESP32]

Never Mind… The issue was that the TYPE should always be lower case.

1 Like

As using the internal Bluetooth from your server can cause issues with range and such I put together another solution.

It is very robust
Stuff needed:

ESP32 module
Lcd2004 display(optional)
Spare time

Instead of letting the server connect we use a ESP32 Arduino instead. These have Bluetooth and WiFi. So it can grab the battery data from the BMS for us over BLE and then send them over to homeassistant over WiFi.

The functionality is the same as the batmon addon, except it doesn’t use MQTT and works straight with ESPhome(.yaml at end of post)
To add something extra to it I added an LCD that shows your current battery data:





substitutions:
  name: 12s5pbattery
  device_description: "Monitor and control a Xiaoxiang Battery Management System (JBD-BMS) via BLE"
  external_components_source: github://syssi/esphome-jbd-bms@main
  mac_address: xx:xx:xx:xx:xx:xx

esphome:
  name: ${name}
  comment: ${device_description}
  project:
    name: "syssi.esphome-jbd-bms"
    version: 1.4.0

esp32:
  board: esp32dev
  framework:
    type: esp-idf

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

wifi:
  ssid: "xxxxxxxx"
  password: "xxxxxxx"
  manual_ip:
    static_ip: 192.168.1.188
    gateway: 192.168.1.1
    subnet: 255.255.255.0

api:
  encryption:
    key: "xxxxxxxxxxxxxxxxxxxx="

ota:
  password: "xxxxxxxxxxxxxxxxx"

logger:
  level: DEBUG


i2c:
  sda: GPIO16
  scl: GPIO17


display:
  - platform: lcd_pcf8574
    dimensions: 16x2
    address: 0x27
    lambda: |-
          switch (id(page)){
            case 1:
              it.printf("Total:""%.3fV", id(total_voltage).state);              
              it.printf(0, 1, "Avg:""%.3fV", id(avgcell).state);                     
              break;
            case 2:
              it.printf("Charging:""%d", id(charge).state);
              it.printf(0, 1, "Delta:""%.3fV", id(deltacell).state);                            
              break;
            case 3:
              it.printf("Current:""%.3fA", id(current).state);
              it.printf(0, 1, "Temp:""%.1fC", id(temp2).state);                  
              break;
          }

globals:
- id: page
  type: int
  initial_value: "1"


interval:
- interval: 4s
  then:
    - lambda: |-
        id(page) = (id(page) + 1);
        if (id(page) > 3) {
          id(page) = 1;
        }











esp32_ble_tracker:
  on_ble_advertise:
    then:
      - lambda: |-
          if (x.get_name().rfind("xiaoxiang", 0) == 0) {
            ESP_LOGI("ble_adv", "New JBD-BMS found");
            ESP_LOGI("ble_adv", "  Name: %s", x.get_name().c_str());
            ESP_LOGI("ble_adv", "  MAC address: %s", x.address_str().c_str());
            ESP_LOGD("ble_adv", "  Advertised service UUIDs:");
            for (auto uuid : x.get_service_uuids()) {
              ESP_LOGD("ble_adv", "    - %s", uuid.to_string().c_str());
            }
          }

ble_client:
  - id: client0
    mac_address: ${mac_address}

jbd_bms_ble:
  - id: bms0
    ble_client_id: client0
    update_interval: 30s

binary_sensor:
  - platform: jbd_bms_ble
    jbd_bms_ble_id: bms0
    balancing:
      name: "${name} balancing"
    charging:
      name: "${name} charging"
    discharging:
      name: "${name} discharging"
    online_status:
      name: "${name} online status"


sensor:
  - platform: jbd_bms_ble
    jbd_bms_ble_id: bms0
    battery_strings:
      name: "${name} battery strings"
    current:
      name: "${name} current"
      id: current
    power:
      name: "${name} power"
    charging_power:
      name: "${name} charging power"
    discharging_power:
      name: "${name} discharging power"
    state_of_charge:
      name: "${name} state of charge"
    nominal_capacity:
      name: "${name} nominal capacity"
    charging_cycles:
      name: "${name} charging cycles"
    capacity_remaining:
      name: "${name} capacity remaining"
    battery_cycle_capacity:
      name: "${name} battery cycle capacity"
    total_voltage:
      name: "${name} total voltage"
      id: total_voltage
    average_cell_voltage:
      name: "${name} average cell voltage"
      id: avgcell
    delta_cell_voltage:
      name: "${name} delta cell voltage"
      id: deltacell
    min_cell_voltage:
      name: "${name} min cell voltage"
    max_cell_voltage:
      name: "${name} max cell voltage"
    min_voltage_cell:
      name: "${name} min voltage cell"
    max_voltage_cell:
      name: "${name} max voltage cell"
    temperature_1:
      name: "${name} temperature 1"
      id: temp1
    temperature_2:
      name: "${name} temperature 2"
      id: temp2
    temperature_3:
      name: "${name} temperature 3"
    cell_voltage_1:
      name: "${name} cell voltage 1"
    cell_voltage_2:
      name: "${name} cell voltage 2"
    cell_voltage_3:
      name: "${name} cell voltage 3"
    cell_voltage_4:
      name: "${name} cell voltage 4"
    cell_voltage_5:
      name: "${name} cell voltage 5"
    cell_voltage_6:
      name: "${name} cell voltage 6"
    cell_voltage_7:
      name: "${name} cell voltage 7"
    cell_voltage_8:
      name: "${name} cell voltage 8"
    cell_voltage_9:
      name: "${name} cell voltage 9"
    cell_voltage_10:
      name: "${name} cell voltage 10"
    cell_voltage_11:
      name: "${name} cell voltage 11"
    cell_voltage_12:
      name: "${name} cell voltage 12"

    operation_status_bitmask:
      name: "${name} operation status bitmask"
    errors_bitmask:
      name: "${name} errors bitmask"
    balancer_status_bitmask:
      name: "${name} balancer status bitmask"
    software_version:
      name: "${name} software version"

text_sensor:
  - platform: jbd_bms_ble
    jbd_bms_ble_id: bms0
    errors:
      name: "${name} errors"
    operation_status:
      name: "${name} operation status"
    device_model:
      name: "${name} device model"

switch:
  - platform: ble_client
    ble_client_id: client0
    name: "${name} enable bluetooth connection"

  - platform: jbd_bms_ble
    jbd_bms_ble_id: bms0
    charging:
      name: "${name} charging"
      id: charge
    discharging:
      name: "${name} discharging"

Could be interesting for @rusins or @luastoned

1 Like

Is there a way to save all the data and put it into a spread sheet? I’ve been thinking of doing this and probably will, but it would be sweet to save everything. I know it’s not needed but I have a data addiction and like to keep as much as I can.

Yes, you can export the data from home assistant, or even use the Grafana addon.
Home assistant already makes a graph from every data point though.

Using this system now to closely monitor my drowned battery… yesterday I crashed while riding a wet road and my board ended up in a creek. :frowning:

Drying it out now while closely monitoring with hassio

After crash pic, while I was dying from pain. Just used my last adrenaline to fish up my board from the creek and open the battery box for draining