UVR16x2 via CANable (candleLight) → Home Assistant (no C.M.I.) – full guide

Hi all,

I wanted to share how I connected a Technische Alternative UVR16x2 directly to Home Assistant OS using a CANable, without using a C.M.I.

This is a generic guide so it can be adapted to different installations.


Overview

Hardware

  • UVR16x2
  • existing CAN bus
  • CANable (tested with CANable 2.0)
  • Home Assistant OS (e.g. Raspberry Pi)

Software

  • Home Assistant OS
  • Mosquitto MQTT Broker
  • MQTT Integration
  • Advanced SSH & Web Terminal Add-on

Flashing CANable (mandatory)

The CANable must run candleLight firmware (gs_usb), otherwise you will not get a native CAN interface.

I used the official web flasher:

https://candlelight-fw.github.io/flash.html

Select:

  • Device: CANable
  • Firmware: candleLight
  • Mode: normal flash

After flashing, the device should appear as:

can0

instead of /dev/ttyACM0.


Architecture

UVR16x2 → CAN → CANable → Python → MQTT → Home Assistant

Important concepts

  • Uses native SocketCAN (can0)
  • UVR16x2 provides values via configured CAN outputs
  • Python script converts CAN frames → MQTT topics

Common pitfalls

BusyBox ip vs iproute2

The default Home Assistant environment uses BusyBox tools, which do not support CAN interface setup properly.

Typical error:

ip: either "dev" is duplicate, or "type" is garbage

Fix:

apk update
apk add iproute2 can-utils python3 py3-pip py3-virtualenv nano

Always use:

/sbin/ip

MQTT authentication

If MQTT is secured, credentials must be used in the Python script.


Add-on configuration is NOT YAML

The Advanced SSH & Web Terminal config UI is form-based.

  • each package = one entry
  • each command = one entry

Step 1 – Configure CAN interface

/sbin/ip link set can0 down
/sbin/ip link set can0 type can bitrate YOUR_BITRATE
/sbin/ip link set can0 up
/sbin/ip link show can0

Step 2 – Verify CAN traffic

candump -L can0

You should see continuous frames.


Step 3 – Python environment

python3 -m venv /config/uvr_venv
source /config/uvr_venv/bin/activate
pip install python-can paho-mqtt

Step 4 – CAN → MQTT script

Save as:

/config/uvr_can2mqtt.py
import can
import paho.mqtt.client as mqtt 

MQTT_HOST = "127.0.0.1"
MQTT_PORT = 1883
MQTT_USER = "YOUR_USER"
MQTT_PASS = "YOUR_PASSWORD"

bus = can.interface.Bus(channel="can0", interface="socketcan")

client = mqtt.Client()
client.username_pw_set(MQTT_USER, MQTT_PASS)
client.connect(MQTT_HOST, MQTT_PORT, 60)
client.loop_start()

def decode(data, index):
    raw = int.from_bytes(data[index:index+2], "little", signed=True)
    return round(raw / 10.0, 1)

print("UVR bridge started")

while True:
    msg = bus.recv()

    if msg is None:
        continue

    if msg.arbitration_id == 0x22C:
        t1 = decode(msg.data, 0)
        t2 = decode(msg.data, 2)
        t3 = decode(msg.data, 4)

        client.publish("uvr/sensor1", t1)
        client.publish("uvr/sensor2", t2)
        client.publish("uvr/sensor3", t3)

        print(t1, t2, t3)

Adjust CAN IDs and mapping based on your UVR configuration.


Step 5 – Test

/config/uvr_venv/bin/python /config/uvr_can2mqtt.py

Step 6 – Verify MQTT

mosquitto_sub -h 127.0.0.1 -u YOUR_USER -P YOUR_PASSWORD -t "uvr/#" -v

Step 7 – Home Assistant sensors

- platform: mqtt
  name: "Temperature 1"
  state_topic: "uvr/sensor1"

- platform: mqtt
  name: "Temperature 2"
  state_topic: "uvr/sensor2"

- platform: mqtt
  name: "Temperature 3"
  state_topic: "uvr/sensor3"

Step 8 – Autostart

Packages

  • iproute2
  • can-utils
  • python3
  • py3-pip
  • py3-virtualenv

Init Commands

  • /sbin/ip link set can0 down || true
  • /sbin/ip link set can0 type can bitrate YOUR_BITRATE || true
  • /sbin/ip link set can0 up || true
  • /config/uvr_venv/bin/python /config/uvr_can2mqtt.py > /config/uvr_can2mqtt.log 2>&1 &

Restart add-on afterwards.


Verification

ps aux | grep uvr_can2mqtt
tail -f /config/uvr_can2mqtt.log

Result

  • Automatic startup
  • CAN data in MQTT
  • Full Home Assistant integration
  • No C.M.I. needed

Notes

  • CAN IDs depend on your UVR configuration
  • values often use little-endian 16-bit scaling
  • extend mapping step by step

Hope this helps 👍