Custom component Nissan Leaf via LeLink 2 (ELM327) BLE

Hello - I need the hive minds help.
I am trying to build a simple component to monitor the battery state of a Nissan Leaf when the car initially returns home.

Essentials:

  • Nissan Leaf
  • Lelink2 BLE OBD2 dongle (ELM327)
  • GL-S10 ESPHome Bluetooth gateway

Using the built in BLE stack, I am part of the way there:

ble_client:
  - mac_address: B4:99:XX:XX:XX:XX
    id: lelink
    name: LELink BLE OBDII
    on_connect:
      then:
        - lambda: |-
            ESP_LOGI("ble_client_lambda", "Connected to lelink");
    on_disconnect:
      then:
        - lambda: |-
            ESP_LOGI("ble_client_lambda", "Disconnected from lelink");

text_sensor:
  - platform: ble_client
    ble_client_id: lelink
    internal: True
    notify: True
    name: "lelink leaf response"
    id: lelink_leaf_response_text
    service_uuid: "0000ffe0-0000-1000-8000-00805f9b34fb"
    characteristic_uuid: "ffe1"
    on_notify: 
      then:
        - lambda: |-
            ESP_LOGI("ble_client_lambda", "notify from lelink_leaf");

interval:
  - interval: 30s 
    then:
      - logger.log:
          level: INFO
          format: "Sending ATZ"
      - ble_client.ble_write:
            id: lelink
            service_uuid: 0000ffe0-0000-1000-8000-00805f9b34fb
            characteristic_uuid: ffe1
            # List of bytes to write.
            value: [0x41, 0x54, 0x5A, 0x0D, 0x0A] #ATZ\r\n

I have tested the approach via a couple of BLE tools on an iphone, and sending ATZ(cr)(lf) as a ascii byte array works and returns 0d,0d,4f,42,44,49,49,20,20,76,31,2E,35,0d,0d,3e (via a notify)


OBDII

v1-5

>

But I am not getting this consistently with the built in tools.

[15:53:44][I][main:171]: Sending ATZ
[15:53:44][D][ble_client.automation:026]: Write type: ESP_GATT_WRITE_TYPE_RSP
>'
[15:53:45][I][ble_client_lambda:140]: notify from lelink
[15:53:46][D][text_sensor:067]: 'lelink response': Sending state 'A'
[15:54:14][I][main:171]: Sending ATZ
[15:54:14][D][ble_client.automation:026]: Write type: ESP_GATT_WRITE_TYPE_RSP
'
[15:54:14][I][ble_client_lambda:140]: notify from lelink
OBDII  v1.'
[15:54:15][I][ble_client_lambda:140]: notify from lelink
>'
[15:54:15][I][ble_client_lambda:140]: notify from lelink
[15:54:44][I][main:171]: Sending ATZ
[15:54:44][D][ble_client.automation:026]: Write type: ESP_GATT_WRITE_TYPE_RSP
[15:54:44][D][text_sensor:067]: 'lelink response': Sending state 'AT'
[15:54:44][I][ble_client_lambda:140]: notify from lelink
'
[15:54:44][I][ble_client_lambda:140]: notify from lelink
>'
[15:54:45][I][ble_client_lambda:140]: notify from lelink
[15:54:46][D][text_sensor:067]: 'lelink response': Sending state 'A'
[15:55:14][I][main:171]: Sending ATZ
[15:55:14][D][ble_client.automation:026]: Write type: ESP_GATT_WRITE_TYPE_RSP
[15:55:14][D][text_sensor:067]: 'lelink response': Sending state 'AT'
[15:55:14][I][ble_client_lambda:140]: notify from lelink
'
[15:55:14][I][ble_client_lambda:140]: notify from lelink
>'
[15:55:15][I][ble_client_lambda:140]: notify from lelink

I am investigating a custom C++ component, but what is the best approach?

1 Like

Sorry to revive this, I understand you might have sold your Nissan since then :slight_smile:

I was looking into doing something similar using a ESP8266 combined with a canbus MCP2515 that plugs directly. I like your approach as well, did you ever succeed?

Thanx.

No - it is 2018 Leaf but bought in 2023 :grinning:
I have got to the point where the LeLink should be streaming notifications via BLE, but it isn’t.

Not sure if it is an issue with the BLE client in ESPHome?

Found this open feature-request for esphome to support ELM327+BLE.

Someone in that PR mentions this WiCAN device that can publish message to a MQTT server over WiFi but it says it also supports BLE. More info here@github. Currently the device’s price is 42$ US + shipping.

Anyone had any more luck with this…. It really bugs me that I cannot integrate our 2018 Leaf into home assistant :weary:

I need to look into it again.

I am considering writing a native Bluetooth integration for home assistant, using an ESPHome Bluetooth proxy, vs trying to use Bluetooth on the ESPhome device, as that seems much more constrained in how you can use Bluetooth…

But I need to set up a HomeAssistant dev environment.

1 Like

Just found this.
Well, I have a similar “problem” i’d like to get some data out of my Renault Kangoo Z.E. from 2013 (22kWh). I would be glad to finde a way to geht my SOC of my car, to start / stop chargeing with homeassistant.

I found this GitHub: GitHub - sanchosk/ZoeELM2MQTT: Translation tool from ELM bluetooth dongle connected to OBD2 port in the car to MQTT server for HomeAssistant

But I would prefere a ESPHome solution. If it’s just some other AT commands, I still can do some testing…

Hi, I’m after the same. I was told that he car switches most/all it’s CAN off afer the car itself is swiched off, to prevent the 12v battery depleting. BUT, if you come in close proximity, you may have enough time to capture the SOC before the car is switched off. I leave my BT dongle always pluged in the ODB2 port. I can remotely start my EVSE, so some part of the CAN should come on, and keep you informed again on its SOC. My EVSE and car are 50mtr from the house, but I can install a BT/ESP/Arduino module inside the EVSE. I ran a power cable and SFTP from evse to the house. I’m willing to participate in the project.

edit: don’t know much abot CAN yet, but I think there are some basic addresses on the bus for particular messages. SOC is a very basic and common message since all fast chargers use that info.

Well, I got the ZoeELM2MQTT running.
I get SOC and range reported while charging. My esp32 is in the house, my car 5m away from it.

The CAN interface is not that easy. Environmental stuff is the same for every car maker: On-board diagnostics - Wikipedia

But every car manufacturer has it’s own “coding”. You can encode for every single bit in a byte a state of the car or use 2 or 4 bits just the like. Without a manual how to decode, you almost have any chance to get the data you like.

For some car’s there are these informations available. Mostly extracted from workshop tester…

So there are 2 basic “problems”

  • get ELM327 connected e.g. using bluetooth proxy
  • get the OBD / CAN data decoded (every car have it’s own encoding)

I think you are on the right track here. A while back I wanted to reverse engineer the BLE comms for my swimming pool controller. I started down the path of making a ESPHome client, but after taking on some advice from the bluetooth home assistant gurus on Discord, I switched to using a BLE proxy, and doing it all in a custom integration directly in HA (sucessfully).

Now I have a 2021 Nissan Leaf, and a LELink dongle. Surely it must be possible to pull off the same trick. OVMS is too expensive for my tastes.

Let me know if you have made any progress, or if you have any useful material. I’m interested in progressing this. Is the BLE protocol documented somewhere? I also have a BLE sniffer, but it’s a deep rabbit hole to go down…

1 Like

Hi Paul, I’d be really interested to know if you get this working.

OK, so I’ve starting to try and get this working:

So far I’ve built a python module that wraps a bleak client (Home Assistant uses bleak) to have an interface similar to pySerial (LeLink tunnels the ELM327 over BLE GATT). Then I’ve adapted python-OBD to use my ble-serial module (since it was using pySerial).

This should handle most of the ISO 15765-4 CAN (11 bit ID,500 Kbaud) protocol with flow control, framing etc. Currently testing this.

Next step is to write the commands and decoders for the Leaf messages.

And then, write a home assistant custom component to wrap in into HA. I’m hoping this part will be fairly straightforward since I’ve done it once before (GitHub - pbutterworth/astralpool_chlorinator: Home Assistant custom component to interface with Astra Pool Viron Equilibrium pool chlorinators). There will no doubt be some head scratchers here since the peripheral device (car) will only be sparsely available and HA doesn’t like unavailable entities. But anything is possible.

Any assistance is vastly appreciated.

1 Like

Update: can now fetch SoC from the car:

[obd.obd] Sending command: b'79703221304': Power switch status
power_switch decoder messages: [<obd.protocols.protocol.Message object at 0x126a25f50>]
Power switch: True
[obd.obd] Sending command: b'79703221103': 12V battery voltage
bat_12v_voltage decoder messages: [<obd.protocols.protocol.Message object at 0x126a91a50>]
12V battery voltage: 12.16
[obd.obd] Sending command: b'79B022101': State of charge
state_of_charge decoder messages: [<obd.protocols.protocol.Message object at 0x126a91ed0>]
78.2224
3 Likes

That’s awesome, unfortunately I don’t have the skills to assist but I’m watching with keen interest. We currently have an old phone (on a power bank) in the car running leaf spy (reporting back to HA) but it tends to run out of power if the car is not used often.

Update: still working on this, hopefully about a week away from pushing something (rough) to Github.

1 Like

Slow and steady wins the race…

So far:
HA will discover an advertising LeLink OBD dongle. If you add the integration, it will then connect and populate these sensors. I’ve got it polling every 10 seconds at the moment. Car needs to be on to get this info.

1 Like

This looks great, awesome!

Nice! Having the odometer could also be useful for monitoring RUC.

1 Like

Fantastic. Did you finally do it on ESPHOME?
I have in mind to create a screen to see the instant consumption in Opel Ampera