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

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…

It is detectable on arrival.

It does depend on your use case and how quickly you want it to be detected.

Mine is detected within 30 second of arrival (coming in to range of my wifi). All of my car stats get updated whenever the car gets back home.

I could make that check more frequently and get that down to 10 seconds.

As it is just wifi, you could also just check if your router has a connection to that IP (of your router supports that in HA).

Or you could just try to open the web page. If you get a 200 OK then you know the car is back.

Now, when the car is off you can tell the WiCAN to not go to sleep. So you could have constant details of the car being present. That will drain your 12v battery some though. No worries for an EV that auto-tops up the 12v battery but a problem for an ICE car.

The device’s sleep mode is still pretty good for tracking presence though. It wakes up every hour and does some checks. That will show as present on the network. It will also send an mqtt message if certain conditions are met.

You could ask for the developer to add a shorter sleep period for your use case also (like 15 mins) or do a custom esp32 firmware yourself.

I think you can make it work pretty well. A very nifty little device.

Oh and you can probably do some logic on a “departure check” pretty easily.

If you had the WiCAN send back details from the car like speed then you could transition a state from at home to “not home” if the device comes on and has speed zero and then has a real speed and dropped off your network.

If you do write such an automation then please consider making it into a sharable Blueprint available on Home Assistant’s Blueprints exchange.

Regardless it would be nice to see all types of WiCAN related Blueprint automations on Home Assistant’s Blueprints exchange.

Thanks!
So as I understand it I should be able to configure the CAN to JSON filters and then any time I send an MQTT tx with the correct PID request the WiCAN should respond with a formatted JSON response, correct?

I seem to be able to get the BattPackRemain with PID 91 but the other two never show up in MQTT. Any ideas as to what I might be doing wrong?

That is correct for a normal PID (which is a simple request/response like the 91 PID).

That is my automation/request task named “Send Tx CANID:2015 PID:91” which you have already gotten working.

The more challenging ones are the multi request with multiple frame response. Essentially, if you properly trigger that request you get a large number of responses sequentially.

Those are my automation with names “Send Tx - CANID:2020 PID:1” and “(After Receiving the ack Rx…) Send Tx…”.

Now that second message is meant to come after you get a response to the first one. However I just added a sleep and that seems fine for faking receiving the response.

The “real” 2101 response is sent over about 10 responses. These each start with an index/PID. That is why I check on index 0 for that PID. Then the bytes coming back are part of a byte stream that makes up the values.

Another way of putting it is this is a mechanism to trigger a response of a large number of values in one go (rather than one at time).

The WiCAN users that requested the index change explain this over in the WiCAN forum in more precise detail than I have done here.

The map of the 2101 byte stream from an original Ioniq is also in that thread. That is a rough map for what the ioniq5 sends as some bytes are moved around a little.

Does that make sense?

If you really want to get a feel for it though get “car scanner” for your phone and “MQTT explorer” on a computer and set the WiCAN to the elm to mqtt logging mode and you can see it in real time. Details on that are in the WiCAN forum/examples.

Let me know if you have any more questions. It is certainly a pretty weird format and spec and took me a while to get my head around it (especially as the basic PID is so straightforward).

1 Like

I work in IT and it’s the weirdest comms I’ve ever dealt with.

Cheers for the assistance.

2 Likes