Math & Expressions

When the WiCAN Pro requests a PID from your vehicle, the ECU responds with a payload of raw hexadecimal bytes. To convert this raw data into useful information (like RPM, Voltage, or Temperature), you must provide a math Expression.

The WiCAN Pro features a highly optimized, onboard C-based expression parser. It evaluates your formulas in real-time before sending the data to your Dashboard or MQTT broker.


1. Accessing Data Bytes

The vehicle's response is treated as an array of bytes, starting at index 0. You extract data by referencing these bytes.

Unsigned Bytes (B)

Use the B prefix to read a byte as an unsigned integer (0 to 255).

  • B0: Reads the 1st byte of the payload.
  • B3: Reads the 4th byte of the payload.

Signed Bytes (S)

Use the S prefix to read a byte as a signed 8-bit integer (-128 to +127). This is useful for temperatures or battery current that can flow in two directions.

  • S0: Reads the 1st byte, where 0xFF equals -1.
  • S2: Reads the 3rd byte as a signed number.

Single Bit Extraction (:)

You can isolate a specific bit from a byte (resulting in a 0 or 1). Bits are zero-indexed from right to left (0 is the Least Significant Bit, 7 is the Most Significant Bit).

  • B0:0: Gets the 1st bit of the 1st byte.
  • B4:7: Gets the 8th bit of the 5th byte. (This is extremely useful for reading ON/OFF toggles like "Brake Pedal Pressed" or "Clutch Engaged").

2. Multi-Byte Ranges (Big-Endian)

Many vehicle parameters are larger than 8 bits. Instead of manually shifting and adding bytes together, the WiCAN parser supports bracketed range syntax.

  • Unsigned Range [B<start>:B<end>]: Combines the bytes into a 16-bit, 32-bit, or 64-bit unsigned integer.
    • Example: [B0:B1] combines byte 0 and byte 1. (Equivalent to B0 * 256 + B1).
  • Signed Range [S<start>:S<end>]: Combines the bytes and evaluates the final result as a signed integer.
    • Example: [S2:S3] combines bytes 2 and 3, treating the MSB as a sign bit.

!NOTE The WiCAN parser uses Big-Endian ordering for ranges. The first byte in the brackets is treated as the Most Significant Byte (MSB).


3. Device Variables

The parser also has access to internal WiCAN Pro hardware variables:

  • V: Represents the current supply voltage measured at the WiCAN's OBD2 pins (e.g., 13.5).
    • Example formula: V + 0.5

4. Supported Operators

You can build complex formulas using standard mathematical and bitwise operators. The parser respects standard order of operations (PEMDAS), and you can use parentheses ( ) to force precedence.

TypeOperatorDescription
Arithmetic+ - * /Add, Subtract, Multiply, Divide
Bitwise&Bitwise AND
Bitwise|Bitwise OR
Bitwise^Bitwise XOR
Bit Shift<< >>Left Shift, Right Shift

5. Real-World Formula Examples

Here are common ways to use the parser based on standard SAE J1979 OBD2 formulas:

1. Engine RPM The ECU reports RPM across two bytes. The formula is (A * 256 + B) / 4.

  • Using standard math: (B0 * 256 + B1) / 4
  • Using ranges (Better): [B0:B1] / 4

2. Coolant Temperature Reported as a single byte offset by -40 degrees Celsius.

  • Formula: B0 - 40

3. Bitwise Flags If you want to mask out the lower 4 bits of a byte:

  • Formula: B2 & 15

4. Complex Multi-Byte Math

  • Formula: ([B3:B6] >> 8) * 0.1

6. Special Expression Types

For advanced users or specific data formats, you can bypass the math parser entirely by entering one of these exact words into the Expression field:

RAW

If you type exactly RAW in the expression field, the WiCAN skips mathematical evaluation. Instead, it captures the entire multi-frame payload and outputs it as one continuous, unbroken Hexadecimal string.

  • Why use this? This is vital for massive, repeating data sets—such as an EV reporting 96 different battery cell voltages in a single UDS response. You can send this massive RAW hex string to Home Assistant and use HA's powerful templating engine to slice it apart, rather than creating 96 individual PID cards on the WiCAN.

!NOTE If you use RAW, do not use a 7 digit PID which has a trailing "1". A PID with a trailing "1", tells the CAN bus that there will only be one frame response.

DTC_RAW

If you type exactly DTC_RAW, the WiCAN engages a specialized internal parser designed exclusively for reading Diagnostic Trouble Codes (e.g., P0104). It properly formats the ECU's error memory response so it can be parsed as active vehicle faults.

7. Pro-Tip: Bitfields and Home Assistant

When dealing with a vehicle PID that contains multiple status flags packed into a single byte or two (a "bitfield"), you can use the WiCAN's single-bit extraction syntax (e.g., B4:0, B4:1) to create separate fields.

However, it is much more efficient to send the entire byte or word to Home Assistant and let Home Assistant decode the individual bits.

Why do this?

  • Saves WiCAN Resources: The device evaluates and transmits one expression (e.g., B4) instead of processing up to eight separate expressions.
  • Reduces MQTT Traffic: Instead of sending a massive JSON payload with multiple individual true/false states, you send a single, compact integer.

How to configure it:

  1. On the WiCAN, create a single extraction field for your PID.
  2. Set the Expression to the full byte (e.g., B4) or word (e.g., [B4:B5]).
  3. Route this value to your MQTT broker.

Home Assistant YAML Example

In Home Assistant, use the bitwise_and filter in your value_template to unpack the states from that single integer.

Here is an example extracting the Parking Lights (Bit 0) and Low Beams (Bit 1) from a single raw byte sent by the WiCAN:

    # --- BIT 0: Parking Lights (Bitwise Value: 1) ---
    - name: "Fusion Parking Lights"
      default_entity_id: "binary_sensor.fusion_lights_parking"
      state_topic: "homeassistant/wican/fusion/lights_raw"
      value_template: >
        {% set raw_val = value_json["lights raw byte"] if value_json is defined else value %}
        {{ 'ON' if (raw_val | int(0) | bitwise_and(1)) > 0 else 'OFF' }}
      unique_id: "fusion_lights_parking"
      device_class: light
      icon: mdi:car-parking-lights
      device: *fusion_device

    # --- BIT 1: Low Beams (Bitwise Value: 2) ---
    - name: "Fusion Low Beams"
      default_entity_id: "binary_sensor.fusion_lights_low_beam"
      state_topic: "homeassistant/wican/fusion/lights_raw"
      value_template: >
        {% set raw_val = value_json["lights raw byte"] if value_json is defined else value %}
        {{ 'ON' if (raw_val | int(0) | bitwise_and(2)) > 0 else 'OFF' }}
      unique_id: "fusion_lights_low_beam"
      device_class: light
      icon: mdi:car-light-dimmed
      device: *fusion_device