WiCAN ESP32-based open-source OBD2/OBD-II Vehicle (car or truck) CAN Bus Diagnostics to WIFi/BLE/USB adapter for Home Assistant integration?

It’s been a long time since I’ve had time to play with this. Using the MeatPi WiCAN, I’ve updated to firmware 2.80 today. It seems the lock up problem I was having a long time back on version 1.74 has been resolved. The web interface remains alive and was able to poll throughout the charge window.

Edit: As expected, it seems my 12v battery is charged while the big battery is charged. After charge complete the 12v voltage drips to normal levels (not charging) and I am not able to poll the big battery charge state anymore.


1 Like

Just throwing some support behind this project. I bought the MeatPi OBD a while back but couldn’t get it functional until this awesome feature update allowing us to bypass NodeRED and calculate/send JSON vars straight from the WiCan. Refer strongly to this HomeAssistant example.

As a lifelong sw engineer, still took me a while, and the docs aren’t super well explained, so I wanted to dump my resources for other OBD2 newbies:

  • The documentation here seems to be somewhat outdated given the release info linked above, the “V” variable is now B# referring to a zero indexed reference to the 8 length “data” array, but this part of the docs is accurate and super helpful understanding shape of the request
  • use this PID code calculator/tinker space (still have to reverse engineer some of their values) with the calculations listed on this wiki
  • Don’t go down the rabbit hole of binary or hex stuff. For PID requests, start bit & bit length can be 0 & 1 aka ignored (I think)
  • Use CarScanner and MQTT Explorer, as suggested, super helpful. Keep in mind per this info again you really just need to change the PID and the calculation, the other JSON values don’t really change
  • Remember to have HA actually consume the vars from MQTT after you’ve automated the request, as the aforementioned “HA” example doesn’t remind that, but the outdated NodeRED example explains it.

It’s basic but here’s my setup for reference (my van OBD2 doesn’t report ODO sadly but thats the equation):

Using this automation:


FuelTankLevel Payload: {"bus":"0","type":"tx","ts":37698,"frame":[{"id":417018865,"dlc":8,"rtr":false,"extd":true,"data":[2,1,47,170,170,170,170,170]}]}

And this entry to read the json formatted value back from my MQTT broker (your_value_here is the string after “WICAN_” in the wifi AP the device creates):

Sorry if this post is basic and spammy level for everyone working on the integration but I would’ve loved a post like this 3 days ago. Happy tinkering and I’d love to work with an actual integration if we make it there!

10 Likes

So sounds like its probably worth buying one… Whats the real difference between USB and ODB2? Can I just pop the USB one into a random usb port in the car or something - or should I go ODB2?

No, see the website. The USB variant is for more advanced users who want to connect their laptop directly via the terminal blocks and wires under the hood, so it is more like a USB to OBD-bus adapter (that car- developers would use to modify the engine programming) instead of a WiFi/Bluetooth to OBD2-port adapter which has limited access to diagnosics logs and read-access to some sensors.

1 Like

thats great, thanks for sharing your information. can you explain a little bit more? why do you need an extra automation? do send the payload with what you want to get for an information and then you get an answer for it? So PID 47 stand for Fuel status? and what do you get for an anwer then?
is the can to json interpreter built in to the wican? and you can use it to format your respones so you dont have to do it in HA, right? what means “B3”?

edit: ah ok, B3 seems to be bit 3 from databyte B, i would really love to see the raw answer you get, when publishing your payload.

As far as I can tell, you need something to publish a “request” to the OBD/Can.
Then the mqtt: sensor in HA constantly watches on the mqtt broker for topic “wican/id/can/rx” and reads the FuelTankLevel published.

But in order for the WiCan to publish that data, it needs to be “requested.” So my HA automation requests data from the WiCan device, and that request is defined in the Automation payload. Once requested, WiCan gathers that data from the vehicle, transforms the JSON data, and publishes the result back to the mqtt broker for HA to read.

Got it working with your help/post. but unfortunately my car (Peugeot boxer 2011) does not provide the fuel level on PID 47. It’s just zero. Any ideas here? I think it’s not possible to get this value with my car. As this was the only reason for me to use this device, I have now one to sell (coming from Germany).

Regards

If you want to sell it what price do you have in mind?

Has anybody tried this on an EV? There’s an HA integration for my car’s built-in service (Hyundai BlueLink), but the cloud API is very slow to update, sometimes to the point of being hours out of date. Since my key use case is checking charge level, door status, etc when home, I figure this could be a good replacement.

2 Likes

Yes, the WiCan works with my Hyundai Ioniq5 to get SoC (needed for feedback when level 2 charging; especially in Australia where we don’t even get Bluelink!).

Same setup as for the Ora Funky Cat

1 Like

Any change @brodykenrick that you can share your CAN to JSON settings for the IONIQ 5 because I’m fairly sure they aren’t the same as the Ora Funky Cat. This would be super helpful.

I’m trying to tx PID 154 for the SOC but what I get returned doesn’t make sense when trying to calculate it using Byte 4 and 5 as per his setup.

Sorry @timwelch - That was meant to be following the same steps to setup the Ioniq5. There are indeed a few differences.

Here is what I have setup.

configuration.yaml

#Note there is a related *_last_known trigger sensor for each of these to give continuity over a reboot
#These are hidden in the UI as those are better for use
mqtt:
  sensor:
    #An alert configiured inside WiCAN
    - name: "Electra WiCAN Aux Battery Alert"
      unique_id: "electra_wican_aux_battery_alert"
      state_topic: "Electra/aux_voltage"
      unit_of_measurement: "V"
      state_class: "measurement"
      value_template: "{{ value_json.battery_voltage }}"

    #The rest of these are triggered responses from messages sent from HA automations
    - name: "Electra WiCAN BattPackRemain"
      unique_id: "electra_wican_battpackremain"
      state_topic: "wican/XXXXXXXXXXXXXX/can/rx"
      unit_of_measurement: "%"
      state_class: "measurement"
      value_template: "{{ value_json.BattPackRemain }}"

    - name: "Electra WiCAN CumChargeEnergy"
      unique_id: "electra_wican_cumchargeenergy"
      state_topic: "wican/XXXXXXXXXXXXXX/can/rx"
      unit_of_measurement: "kWh"
      state_class: "measurement"
      value_template: "{{ value_json.CumChargeEnergy }}"

    - name: "Electra WiCAN AuxBattVoltage"
      unique_id: "electra_wican_auxbattvoltage"
      state_topic: "wican/XXXXXXXXXXXXXX/can/rx"
      unit_of_measurement: "V"
      state_class: "measurement"
      value_template: "{{ value_json.AuxBattVoltage }}"

    - name: "Electra WiCAN BattPackCurrent (Uncalculated)"
      unique_id: "electra_wican_battpackcurrent"
      state_topic: "wican/XXXXXXXXXXXXXX/can/rx"
      unit_of_measurement: "A"
      state_class: "measurement"
      value_template: "{{ (value_json.BattPackCurrent) | int(0) }}"

and

  #Only keep properly retrieved values (as WiCAN MQTT is only reported when the car is on/charging and on the home wifi and those values ar lost on a reboot)
  - trigger:
      - platform: state
        entity_id: sensor.electra_wican_battpackremain
        not_to:
          - unknown
          - unavailable
    sensor:
      - name: Electra WiCAN BattPackRemain (Last Known)
        unique_id: "electra_wican_battpackremain_last_known"
        state: '{{ trigger.to_state.state }}'
        unit_of_measurement: '%'

  - trigger:
      - platform: state
        entity_id: sensor.electra_wican_aux_battery_alert
        not_to:
          - unknown
          - unavailable
    sensor:
      - name: Electra WiCAN Aux Battery Alert (Last Known)
        unique_id: "electra_wican_aux_battery_alert_last_known"
        state: '{{ trigger.to_state.state }}'
        unit_of_measurement: 'V'

  - trigger:
      - platform: state
        entity_id: sensor.electra_wican_cumchargeenergy
        not_to:
          - unknown
          - unavailable
    sensor:
      - name: Electra WiCAN Aux CumChargeEnergy (Last Known)
        unique_id: "electra_wican_cumchargeenergy_last_known"
        state: '{{ trigger.to_state.state }}'
        unit_of_measurement: 'kWh'

  - trigger:
      - platform: state
        entity_id: sensor.electra_wican_auxbattvoltage
        not_to:
          - unknown
          - unavailable
    sensor:
      - name: Electra WiCAN AuxBattVoltage (Last Known)
        unique_id: "electra_wican_auxbattvoltage_last_known"
        state: '{{ trigger.to_state.state }}'
        unit_of_measurement: 'V'

Automation (setup in the UI) but here is the yaml

alias: OBD Request (by sending a TX) to WiCAN in Electra
description: ""
trigger:
  - platform: time_pattern
    seconds: / 30
condition: []
action:
  - alias: Send Tx CANID:2015 PID:91 (Rx BattPackRemain CANID:2028 PID:91)
    service: mqtt.publish
    metadata: {}
    data:
      topic: wican/XXXXXXXXXXXXXX/can/tx
      payload_template: >-
        {"bus":"0","type":"tx","ts":33149,"frame":[{"id":2015,"dlc":8,"rtr":false,"extd":false,"data":[2,1,91,170,170,170,170,170]}]}
      qos: "0"
  - alias: Send Tx - CANID:2020 PID:1 (To Trigger 2101)
    service: mqtt.publish
    metadata: {}
    data:
      topic: wican/XXXXXXXXXXXXXX/can/tx
      payload_template: >-
        {"bus":"0","type":"tx","ts":26517,"frame":[{"id":2020,"dlc":8,"rtr":false,"extd":false,"data":[3,34,1,1,170,170,170,170]}]}
      qos: "0"
    enabled: true
  - delay:
      hours: 0
      minutes: 0
      seconds: 0
      milliseconds: 7
  - alias: >-
      (After Receiving the ack Rx....) Send Tx - CANID:2020 PID:? (To Trigger
      "real" 2101)
    service: mqtt.publish
    metadata: {}
    data:
      topic: wican/XXXXXXXXXXXXXX/can/tx
      payload_template: >-
        {"bus":"0","type":"tx","ts":26532,"frame":[{"id":2020,"dlc":8,"rtr":false,"extd":false,"data":[48,0,0,170,170,170,170,170]}]}
      qos: "0"
    enabled: true
mode: single

Then in WiCAN the following settings:

You will mainly be interested in the BattPackRemain value which is a “normal” PID (91). My WiCAN firmware is a newer version and allows setting of a PID offset. If that index/offset is 2, like the case for the 91/BattPackRemain, then the older firmware will just use that 2 (3rd byte) by default.

The other values I am obtaining are from a two message request that is used to trigger the sending of a 2101 dataframe. I used some details that someone pulled from an OG ioniq a few years back to help me there. There were some bytes that had shifted a few places though so there was a bit of trial and error and using car scanner lots.

You can ignore the RxResponse2101 – Originally I was thinking i’d need to respond to the first message accurately. Instead a wait worked just as well for my purposes.

Hopefully that makes sense for you and is helpful. Feel free to ask any questions. I will be tidying it up in the future and also extracting a few other measures (like battery power, reamaing energy, some termperatures and accumulated quick and normal charging energy). I also hope to get the odometer reading out.

4 Likes

oh, that all looks like this on a dash:

views:
  - title: Home
    cards:
      - type: custom:apexcharts-card
        chart_type: radialBar
        header:
          show: false
          show_states: true
          colorize_states: true
        apex_config:
          legend:
            show: false
          plotOptions:
            radialBar:
              offsetY: 0
              startAngle: -108
              endAngle: 108
              dataLabels:
                total:
                  show: true
                  label: State of Charge
                  formatter: |
                    EVAL:function(w) {
                      return w.globals.seriesTotals.reduce((a, b) => {return (a*0 + b)} , 0).toFixed(1) + "%"
                      }
        series:
          - entity: sensor.electra_wican_battpackremain_last_known
            show:
              legend_value: false
      - type: entities
        entities:
          - entity: sensor.electra_wican_aux_battery_alert_last_known
          - entity: sensor.electra_wican_auxbattvoltage_last_known
          - entity: sensor.electra_wican_battpackremain_last_known
      - type: entities
        entities:
          - entity: sensor.electra_cumulative_energy
          - entity: sensor.electra_cumulative_energy_not_from_home_charger
          - entity: sensor.smappee_charging_energy_all_time
      - type: entities
        entities:
          - sensor.electra_cumulative_emissions_created_not_from_home_charger
3 Likes

Absolute gold right there! This write-up is amazing and exactly what I needed! :1st_place_medal:

2 Likes

Mine got delivered yesterday and reports V2.90, which seems to match the WiCAN release in GitHub. Is there something newer than this? Prerelease?

Yes, a pre-release adding that index feature. See above discussion (which explains lots of the special PID case).

1 Like

This might help someone :slight_smile:
My config

2 Likes

I’m wondering. Would this be a good device to buy to track the vehicle arriving so as to trigger other automations upon arrival?

I know it can do a lot of other stuff and I can probably stand to gain from some of those things as well but I first need to know if it’ll accomplish what I said.

I guess when does HA pick up that it has arrived?

Probably not ideal. It can connect to your home WiFi but it does not have power when the car is not running, so how do you know that can has left and is not just off.

Thank you. I actually meant to ask what happens when the car is powered off, as well. So that rules this out.

Really not having great luck with battery powered devices for arrival sensing, especially since it has been so cold lately and the batteries haven’t been holding up.

Back to the drawing board…