OBD Solutions / Home Assistant
OBDLink MX+ e Home Assistant: la guida completa, incluse le app che non funzionano
Il percorso reale per portare i dati di OBDLink MX+ su Home Assistant in tempo reale mentre guidi: le app scartate e perché, la soluzione Tasker + plugin Bluetooth seriale, e l'alternativa Raspberry Pi per chi parcheggia sempre vicino a casa.

Cos'è OBDLink MX+
OBDLink MX+ è un adattatore Bluetooth per la porta OBD-II prodotto da OBD Solutions LLC (marchio ScanTool.net), con chipset proprietario STN2255. Il Bluetooth è di tipo classico (profilo SPP), certificato MFi per iOS: per un'analisi completa del prodotto, delle sue funzioni e dei suoi limiti vedi la nostra recensione dedicata. Questa guida si concentra solo su un obiettivo specifico: portare i dati dell'auto, in tempo reale, dentro Home Assistant.
Prima di iniziare
- OBDLink MX+ già configurato e abbinato via Bluetooth con l'app ufficiale (vedi la recensione linkata sopra per i dettagli del primo abbinamento).
- Un'istanza Home Assistant raggiungibile da internet tramite un indirizzo HTTPS pubblico (ad esempio via Cloudflare Tunnel), con un broker MQTT già collegato.
- Uno smartphone Android con Tasker (app a pagamento, circa 4,69€) e Bluetooth attivo.
- Accesso amministratore a Home Assistant per creare un'automazione con trigger webhook.
Il problema: Bluetooth classico e nessuna integrazione nativa
OBDLink MX+ comunica in Bluetooth classico (profilo SPP), non in Bluetooth Low Energy: per questo motivo non esiste e non può esistere un'integrazione nativa in Home Assistant per collegarlo direttamente. Il percorso deve sempre passare da un dispositivo intermedio che sappia parlare SPP e che possa inoltrare i dati a Home Assistant.
La soluzione "da manuale" è un piccolo computer Linux (Raspberry Pi) sempre acceso e vicino all'auto, che legge i dati con python-OBD e li pubblica su MQTT: la trovi più sotto in questa guida. Ma se l'auto non è sempre parcheggiata a portata di Bluetooth di un dispositivo di casa — il nostro caso: garage quattro piani sotto l'appartamento — quella strada semplicemente non funziona, perché il Bluetooth ha una portata di pochi metri. Serve un dispositivo che sia sempre vicino all'auto per definizione: il telefono di chi guida.
Le strade scartate (e perché)
Prima di arrivare alla soluzione che funziona, abbiamo verificato concretamente diverse app "facili", scartandole tutte per motivi specifici, non per sentito dire:
- Torque Pro: non compatibile con la versione Android recente del telefono usato nella prova.
- App ufficiale OBDLink, Car Scanner ELM OBD2: ottime per la diagnosi e il cruscotto live (vedi la recensione), ma non hanno alcuna funzione di esportazione dati in tempo reale verso MQTT o un webhook: fanno solo log locali.
- RealDash: usa solo un protocollo proprietario TCP/UDP, non compatibile con un collegamento HTTP verso un tunnel come Cloudflare.
- AndrOBD + plugin Home Assistant (progetto open source su GitHub): nessun APK pronto all'uso, solo codice sorgente da compilare.
- AndrOBD + MQTTPublisher (plugin ufficiale del progetto AndrOBD, su F-Droid, supporta connessioni
wss://): installato e configurato correttamente, ma l'app si è bloccata ripetutamente durante il test in modalità Demo sul telefono usato nella prova — scartata per inaffidabilità concreta, non solo teorica. - MacroDroid e Automate (LlamaLab): confermato anche da un intervento pubblico dello sviluppatore di Automate che Android non espone il profilo Bluetooth seriale (SPP) alle app di automazione generiche: nessuna delle due può parlare con OBDLink MX+ in questo modo, indipendentemente da come si prova a configurarle.
La soluzione che funziona: Tasker + BluetoothSerialForTasker
L'unica app di automazione Android in grado di aprire una connessione Bluetooth seriale (SPP) reale con OBDLink MX+ è Tasker, abbinato al plugin open source BluetoothSerialForTasker (sviluppato da Mollayo, non disponibile sul Play Store).
Passo 1: installa Tasker e il plugin
- Installa Tasker dal Play Store (a pagamento).
- Scarica il file APK del plugin da GitHub:
github.com/Mollayo/BluetoothSerialForTasker→ cartellaapp/app-release.apk. Scaricalo come file vero (non copiare/incollare il contenuto tradotto della pagina, altrimenti il file XML risulta corrotto). - Attiva "Installa da questa origine" quando richiesto e installa l'APK.
- Apri il plugin una volta per concedere i permessi Bluetooth e posizione richiesti da Android.
Passo 2: trova l'indirizzo MAC di OBDLink MX+
Con OBDLink MX+ già abbinato via Bluetooth nelle impostazioni di sistema del telefono (non nell'app ufficiale: nelle Impostazioni Bluetooth di Android), annota l'indirizzo MAC del dispositivo — lo trovi anche dentro un'azione "Bluetooth Serial" di Tasker premendo "SHOW ALL PAIRED DEVICES".
Passo 3: crea il profilo che riceve i dati
Crea un nuovo Profilo Tasker collegato all'evento plugin "BT Serial" (BluetoothSerialForTasker → evento, non azione), e una nuova Attività collegata a quel profilo con una sola operazione: Imposta Variabile con Nome una variabile GLOBALE tutta maiuscola (es. %SERIAL_DATA) e valore %serial_data1, con la casella "Aggiungi" spuntata (vedi il riquadro sotto sul perché).
Questo passaggio è più importante di quanto sembri: le variabili del plugin come %serial_data1 sono locali all'Attività collegata direttamente all'evento e non sono leggibili da nessun'altra parte di Tasker. Copiarle subito in una variabile globale tutta maiuscola è l'unico modo per poterle riusare in un'altra Attività.
Passo 4: crea l'Attività che interroga l'auto
Crea un'Attività (ad esempio "Leggi OBD") con questa sequenza di azioni, ripetuta per ogni PID che vuoi leggere:
- Bluetooth Serial → Connect al MAC di OBDLink MX+.
- Bluetooth Serial → Send:
ATZ(CRLF attivo) per inizializzare l'adattatore. - Bluetooth Serial → Send:
ATE0(CRLF attivo) per disattivare l'eco dei comandi (in pratica l'eco spesso resta comunque visibile nei dati ricevuti: non è un problema, la formula lato Home Assistant lo ignora). - Aspetta 1 secondo.
- Per ogni PID che vuoi leggere: Cancella Variabile
%SERIAL_DATA(per ripulirla dal comando precedente) → Bluetooth Serial → Send il PID (dispositivo OBDLink selezionato, CRLF attivo) → Aspetta 2 secondi → Imposta Variabile per copiare il contenuto accumulato (es.%rpm_raw=%SERIAL_DATA) in una variabile dedicata a quel PID. Ripeti questo blocco di 4 azioni una volta per ogni riga della tabella qui sotto. - Un'ultima azione HTTP Request (metodo GET) verso il webhook di Home Assistant, con tutti i dati grezzi come parametri della query string (vedi il link completo più sotto).
Il punto "Cancella Variabile prima di ogni Send" è quello che rende affidabile l'accumulo del passo 3: senza, i pezzi di un comando si mescolerebbero con quelli del comando successivo.
I 15 PID usati in questa guida (comandi + variabili + formula)
Questa è la tabella completa con cui abbiamo costruito e testato con dati reali il sistema descritto in questa guida. I primi 3 sono i valori base; gli altri 12 sono opzionali, aggiungili solo se ti interessano.
| Comando da inviare | Nome variabile in Tasker | Cosa misura | Formula (calcolata da Home Assistant) | Unità |
|---|---|---|---|---|
010C | %rpm_raw | Giri motore | (A×256+B)/4 | rpm |
010D | %speed_raw | Velocità | A | km/h |
0105 | %coolant_raw | Temperatura liquido raffreddamento | A-40 | °C |
0104 | %engine_load_raw | Carico motore | A×100/255 | % |
010A | %fuel_pressure_raw | Pressione carburante | A×3 | kPa |
010B | %intake_pressure_raw | Pressione collettore aspirazione | A | kPa |
010E | %timing_advance_raw | Anticipo accensione | A/2-64 | ° |
010F | %intake_temp_raw | Temperatura aria aspirata | A-40 | °C |
0110 | %maf_raw | Portata aria (MAF) | (A×256+B)/100 | g/s |
0111 | %throttle_raw | Posizione farfalla | A×100/255 | % |
012F | %fuel_level_raw | Livello carburante | A×100/255 | % |
0142 | %battery_voltage_raw | Tensione impianto elettrico | (A×256+B)/1000 | V |
0146 | %ambient_temp_raw | Temperatura ambiente | A-40 | °C |
015E | %fuel_rate_raw | Consumo istantaneo | (A×256+B)/20 | L/h |
0121 | %mil_distance_raw | Km percorsi con spia motore accesa | A×256+B | km |
Dove "A" e "B" sono, in ordine, il primo e il secondo byte di dati della risposta (dopo i due byte iniziali "41 PID" che l'adattatore ripete sempre all'inizio) convertiti da esadecimale a decimale.
L'azione HTTP Request finale, con tutti e 15 i parametri
Nel campo URL dell'ultima azione (Metodo GET), incolla questo indirizzo sostituendo il-tuo-dominio.it e IL-TUO-WEBHOOK-ID con i tuoi valori reali (li trovi nel trigger Webhook dell'automazione che crei nel passo successivo):
https://il-tuo-dominio.it/api/webhook/IL-TUO-WEBHOOK-ID?rpm_raw=%rpm_raw&speed_raw=%speed_raw&coolant_raw=%coolant_raw&engine_load_raw=%engine_load_raw&fuel_pressure_raw=%fuel_pressure_raw&intake_pressure_raw=%intake_pressure_raw&timing_advance_raw=%timing_advance_raw&intake_temp_raw=%intake_temp_raw&maf_raw=%maf_raw&throttle_raw=%throttle_raw&fuel_level_raw=%fuel_level_raw&battery_voltage_raw=%battery_voltage_raw&ambient_temp_raw=%ambient_temp_raw&fuel_rate_raw=%fuel_rate_raw&mil_distance_raw=%mil_distance_raw
Se vuoi leggere solo i 3 valori base, usa la stessa URL ma con solo i primi tre parametri (rpm_raw, speed_raw, coolant_raw) e costruisci in Tasker solo i primi 3 blocchi della tabella sopra.

Nota: ogni singola azione "Bluetooth Serial" (non solo la prima Connect) richiede anche il dispositivo OBDLink selezionato al suo interno, non solo il comando da inviare — è un altro errore facile da fare copiando le azioni.
Perché conviene far calcolare i valori a Home Assistant, non a Tasker
Un PID OBD-II risponde in esadecimale (ad esempio 41 0C 1A F8 per i giri motore) e va convertito in un numero reale con una formula specifica per ogni parametro (per i giri motore: (A×256+B)/4). Fare questo calcolo dentro Tasker richiede diverse azioni aggiuntive per ogni singolo PID (separare i byte, convertirli da esadecimale, applicare la formula con il flag "Calcola").
È molto più semplice e affidabile far inviare a Tasker il dato grezzo così com'è ricevuto (compreso l'eventuale eco del comando che lo precede) e far fare il calcolo a Home Assistant, dentro l'automazione che riceve il webhook, con un template che usa un'espressione regolare per trovare ed estrarre i byte di risposta ovunque si trovino nella stringa. Questo riduce drasticamente il numero di azioni da costruire a mano su Tasker (un errore facile da introdurre premendo il pulsante sbagliato) e concentra tutta la logica di calcolo in un unico posto, più semplice da correggere se serve.
L'automazione webhook su Home Assistant
Crea una nuova automazione con trigger Webhook (metodo GET e POST entrambi accettati, non riservato solo alla rete locale). Per ogni parametro grezzo ricevuto nella query string, l'automazione:
- Pubblica una sola volta (all'avvio) la configurazione MQTT Discovery per ciascun sensore, così Home Assistant crea le entità in automatico senza YAML manuale per le entità stesse.
- Per ogni parametro
_rawpresente nella richiesta, con una condizione "if" che verificatrigger.query.get('nome_raw') is not none, estrae i byte di risposta con un'espressione regolare (es.41\s*0C\s*([0-9A-Fa-f]{2})\s*([0-9A-Fa-f]{2})per i giri motore) e pubblica il valore calcolato sul topic di stato del sensore.
Il vantaggio pratico: se in futuro noti che un valore non torna, correggi la formula in un solo punto (il template dell'automazione), senza dover rifare le azioni su Tasker.
Esempio completo: l'azione per i giri motore
Ecco esattamente come si scrive, in formato azione dell'automazione (aggiungila tramite l'editor YAML dell'automazione, azione "Azione", scegliendo "Modifica in YAML"):
- if:
- condition: template
value_template: "{{ trigger.query.get('rpm_raw') is not none }}"
then:
- action: mqtt.publish
data:
topic: obdlink_mxplus/rpm/state
payload: >-
{% set raw = trigger.query.get('rpm_raw') %}
{% set m = raw | regex_findall('41\s*0C\s*([0-9A-Fa-f]{2})\s*([0-9A-Fa-f]{2})') %}
{% if m %}{{ (((m[0][0]|int(0,16))*256 + (m[0][1]|int(0,16))) / 4) | round(0) | int }}{% else %}unknown{% endif %}
Ripeti la stessa struttura per ogni PID, cambiando solo il nome del parametro (rpm_raw), il topic MQTT e l'espressione regolare/formula secondo la tabella qui sotto.
Espressione regolare e formula per ciascun PID
| Parametro webhook | Espressione regolare | Formula nel template |
|---|---|---|
rpm_raw | 41\s*0C\s*([0-9A-Fa-f]{2})\s*([0-9A-Fa-f]{2}) | (((A)*256+(B))/4) |
speed_raw | 41\s*0D\s*([0-9A-Fa-f]{2}) | (A) |
coolant_raw | 41\s*05\s*([0-9A-Fa-f]{2}) | (A-40) |
engine_load_raw | 41\s*04\s*([0-9A-Fa-f]{2}) | (A*100/255) |
fuel_pressure_raw | 41\s*0A\s*([0-9A-Fa-f]{2}) | (A*3) |
intake_pressure_raw | 41\s*0B\s*([0-9A-Fa-f]{2}) | (A) |
timing_advance_raw | 41\s*0E\s*([0-9A-Fa-f]{2}) | (A/2-64) |
intake_temp_raw | 41\s*0F\s*([0-9A-Fa-f]{2}) | (A-40) |
maf_raw | 41\s*10\s*([0-9A-Fa-f]{2})\s*([0-9A-Fa-f]{2}) | ((A*256+B)/100) |
throttle_raw | 41\s*11\s*([0-9A-Fa-f]{2}) | (A*100/255) |
fuel_level_raw | 41\s*2F\s*([0-9A-Fa-f]{2}) | (A*100/255) |
battery_voltage_raw | 41\s*42\s*([0-9A-Fa-f]{2})\s*([0-9A-Fa-f]{2}) | ((A*256+B)/1000) |
ambient_temp_raw | 41\s*46\s*([0-9A-Fa-f]{2}) | (A-40) |
fuel_rate_raw | 41\s*5E\s*([0-9A-Fa-f]{2})\s*([0-9A-Fa-f]{2}) | ((A*256+B)/20) |
mil_distance_raw | 41\s*21\s*([0-9A-Fa-f]{2})\s*([0-9A-Fa-f]{2}) | (A*256+B) |
Renderlo automatico, senza aprire mai l'app
Il primo istinto sarebbe agganciare l'avvio automatico a un Profilo Tasker "Bluetooth Connesso": sembra logico, ma non funziona, ed è utile capire perché. Quel tipo di Profilo diventa attivo solo quando il telefono risulta già collegato via Bluetooth all'adattatore — ma quella connessione la apre solo l'azione "Connect" della tua stessa Attività di lettura. È un cane che si morde la coda: il Profilo che dovrebbe avviare tutto in automatico dipende da una connessione che parte solo se qualcosa ha già avviato l'Attività. Senza un primo innesco indipendente, non scatta mai da solo.
La soluzione che funziona davvero è più semplice: un Profilo Tempo, che ripete il tentativo ogni 10-15 minuti, collegato direttamente all'Attività di lettura. Se l'adattatore non è raggiungibile il tentativo fallisce in un istante (grazie a "Continua dopo un errore" su ogni azione, vedi sopra) senza alcun effetto collaterale; se lo è, la lettura parte da sola. Un intervallo troppo breve (es. ogni 1-2 minuti) non offre vantaggi pratici e consuma batteria inutilmente per tutto il resto della giornata quando l'auto è ferma.

Un sensore che ti dice sempre cosa è arrivato davvero
Quando qualcosa non funziona, la domanda più difficile a cui rispondere è: il telefono ha anche solo provato a chiamare il webhook? È utile aggiungere all'automazione un'azione diagnostica che pubblica ogni singola chiamata ricevuta, con tutti i suoi parametri così come sono arrivati, indipendentemente dal fatto che corrispondano o meno a un sensore riconosciuto:
- action: mqtt.publish
data:
topic: obdlink_mxplus/debug_last_call/state
payload: "{{ now().strftime('%d/%m %H:%M:%S') }}"
- action: mqtt.publish
data:
topic: obdlink_mxplus/debug_last_call/attributes
payload: "{{ {'query_raw': (trigger.query.items() | list)} | tojson }}"
Abbinata a un sensore MQTT con json_attributes_topic puntato al secondo topic, questa coppia di azioni crea un'entità che mostra sempre data/ora dell'ultima chiamata e il contenuto esatto ricevuto, anche quando è vuoto, sbagliato o non corrisponde a nessun sensore. È il modo più veloce per capire se il problema è "Tasker non ha mai chiamato Home Assistant" oppure "Tasker ha chiamato ma con dati diversi da quelli attesi" — due problemi molto diversi da risolvere, che altrimenti sono indistinguibili guardando solo i sensori principali.
La dashboard "Auto OBD"
Con i sensori creati dall'automazione, costruisci una vista dedicata con indicatori a lancetta per i tre valori principali, un grafico storico e due riquadri con tutti gli altri parametri. Non serve scrivere a mano l'intero dashboard: si aggiunge una card alla volta, incollando il relativo codice YAML nell'editor manuale di ogni singola card.
Passo 1: crea la nuova vista
- Apri il tuo dashboard, tocca la matita in alto a destra per entrare in modalità modifica.
- Tocca il + accanto alle schede/tab in alto per aggiungere una nuova vista.
- Nel campo "Titolo" scrivi
Auto OBDe salva: si apre una vista vuota, pronta per le card.
Passo 2: aggiungi i tre indicatori principali
Tocca + Aggiungi scheda, scorri in fondo alla lista dei tipi di card e scegli "Modifica manualmente" (l'editor YAML della singola card): questo ti permette di incollare direttamente il codice invece di configurare i campi uno per uno. Incolla questo blocco per i giri motore:
type: gauge
entity: sensor.obdlink_mx_auto_rpm
name: Giri motore
min: 0
max: 8000
severity:
green: 0
yellow: 4000
red: 6000
Salva, poi ripeti (di nuovo "+ Aggiungi scheda" → "Modifica manualmente") per la velocità:
type: gauge
entity: sensor.obdlink_mx_auto_speed
name: Velocità
min: 0
max: 220
severity:
green: 0
yellow: 130
red: 180
E per la temperatura del liquido di raffreddamento:
type: gauge
entity: sensor.obdlink_mx_auto_coolant_temp
name: Temperatura liquido
min: 0
max: 130
severity:
green: 0
yellow: 100
red: 115
Passo 3: aggiungi il grafico storico
Stessa procedura ("+ Aggiungi scheda" → "Modifica manualmente"):
type: history-graph
title: Storico ultimo tragitto
hours_to_show: 3
entities:
- entity: sensor.obdlink_mx_auto_rpm
- entity: sensor.obdlink_mx_auto_speed
- entity: sensor.obdlink_mx_auto_coolant_temp
Passo 4: aggiungi gli altri parametri (se hai attivato i 12 PID extra)
Se hai seguito anche la sezione sui parametri aggiuntivi più sopra, aggiungi due card "Entità" per raggrupparli in modo leggibile:
type: entities
title: Motore e aspirazione
entities:
- entity: sensor.obdlink_mx_auto_carico_motore
name: Carico motore
- entity: sensor.obdlink_mx_auto_pressione_aspirazione
name: Pressione aspirazione
- entity: sensor.obdlink_mx_auto_pressione_carburante
name: Pressione carburante
- entity: sensor.obdlink_mx_auto_anticipo_accensione
name: Anticipo accensione
- entity: sensor.obdlink_mx_auto_temperatura_aria_aspirata
name: Temperatura aria aspirata
- entity: sensor.obdlink_mx_auto_portata_aria_maf
name: Portata aria (MAF)
- entity: sensor.obdlink_mx_auto_posizione_farfalla
name: Posizione farfalla
type: entities
title: Carburante e impianto elettrico
entities:
- entity: sensor.obdlink_mx_auto_livello_carburante
name: Livello carburante
- entity: sensor.obdlink_mx_auto_consumo_istantaneo
name: Consumo istantaneo
- entity: sensor.obdlink_mx_auto_tensione_impianto
name: Tensione impianto
- entity: sensor.obdlink_mx_auto_temperatura_ambiente
name: Temperatura ambiente
- entity: sensor.obdlink_mx_auto_km_spia_motore_accesa
name: Km con spia motore accesa

Lo sportellino del vano OBD-II non si chiude
Su parecchie auto, con OBDLink MX+ inserito, lo sportellino o il pannello che copre la presa OBD-II non torna a chiudersi: il connettore sporge troppo. Non è un difetto di OBDLink MX+, che anzi è tra gli adattatori più compatti in circolazione: è che, anno dopo anno, i produttori auto continuano a disegnare quel vano come se nessuno dovesse mai lasciarci qualcosa collegato in pianta stabile.
La soluzione più semplice è un cavo di prolunga OBD-II piatto: si collega alla presa originale, esce dal vano con uno spessore minimo che permette allo sportellino di richiudersi (o quasi) sul cavo stesso, e sposta il connettore vero e proprio in un punto più comodo. Verifica lo spazio libero sulla tua auto prima di comprarlo, perché la profondità del vano cambia da modello a modello. Su Amazon si trova cercando «prolunga OBD2 piatta».
L'alternativa Raspberry Pi (se l'auto resta vicino a casa)
Se la tua auto è sempre parcheggiata a portata di Bluetooth di casa (garage annesso, box privato accanto all'ingresso), un Raspberry Pi sempre acceso è un'alternativa più solida al telefono, perché non dipende dall'aprire un'app ogni volta: legge i dati con la libreria python-OBD e li pubblica su MQTT con lo stesso meccanismo di discovery.
Passo 1: abbina l'adattatore al Raspberry Pi
sudo bluetoothctl
power on
agent on
default-agent
scan on
# individua l'adattatore (nome tipo "OBDLink" o "OBDII"), annota il MAC AA:BB:CC:DD:EE:FF
pair AA:BB:CC:DD:EE:FF
trust AA:BB:CC:DD:EE:FF
quitPasso 2: crea la porta seriale virtuale
sudo rfcomm bind 0 AA:BB:CC:DD:EE:FF
ls -l /dev/rfcomm0Il collegamento creato con rfcomm bind non sopravvive al riavvio (il vecchio file /etc/bluetooth/rfcomm.conf non è più letto dalle versioni attuali di BlueZ): il servizio del passo 5 lo ricrea automaticamente a ogni avvio.
Passo 3: installa python-OBD e il client MQTT
python3 -m venv ~/obd2mqtt
source ~/obd2mqtt/bin/activate
pip install obd paho-mqttPasso 4: script di pubblicazione con discovery
Salva lo script come /home/pi/obd2mqtt.py (è il percorso usato dal servizio del passo 5) e sostituisci indirizzo e credenziali con quelli del tuo broker MQTT.
import time, json, obd
import paho.mqtt.client as mqtt
MQTT_HOST = "192.168.1.10"
MQTT_USER = "homeassistant"
MQTT_PASS = "la-tua-password"
DEVICE_ID = "obdlink_mxplus"
PIDS = {
"rpm": (obd.commands.RPM, "rpm"),
"speed": (obd.commands.SPEED, "km/h"),
"coolant_temp": (obd.commands.COOLANT_TEMP, "°C"),
}
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2) # evita l'avviso di deprecazione di paho-mqtt 2.x
client.username_pw_set(MQTT_USER, MQTT_PASS)
client.connect(MQTT_HOST, 1883, 60)
client.loop_start()
def publish_discovery():
for key, (_, unit) in PIDS.items():
topic = f"homeassistant/sensor/{DEVICE_ID}/{key}/config"
payload = {
"name": f"Auto {key}", "state_topic": f"{DEVICE_ID}/{key}/state",
"unit_of_measurement": unit, "unique_id": f"{DEVICE_ID}_{key}", "state_class": "measurement",
"device": {"identifiers": [DEVICE_ID], "name": "OBDLink MX+", "manufacturer": "OBD Solutions"},
}
client.publish(topic, json.dumps(payload), retain=True)
connection = obd.OBD("/dev/rfcomm0")
publish_discovery()
while True:
if connection.is_connected():
for key, (command, _) in PIDS.items():
response = connection.query(command)
if not response.is_null():
client.publish(f"{DEVICE_ID}/{key}/state", str(response.value.magnitude))
time.sleep(5)Passo 5: avvio automatico con systemd
sudo tee /etc/systemd/system/obd2mqtt.service <<'EOF'
[Unit]
Description=OBDLink MX+ to MQTT bridge
After=bluetooth.target network-online.target
[Service]
ExecStartPre=-+/usr/bin/rfcomm bind 0 AA:BB:CC:DD:EE:FF
ExecStart=/home/pi/obd2mqtt/bin/python /home/pi/obd2mqtt.py
Restart=always
RestartSec=10
User=pi
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now obd2mqtt.serviceVerifica e troubleshooting
Il Bluetooth Serial di Tasker dà "Errore: 2" al Connect
Quasi sempre è un problema di raggiungibilità: il quadro dell'auto è spento (a motore spento l'adattatore entra in modalità sleep), il telefono è troppo lontano, oppure un'altra app (tipica l'app ufficiale OBDLink rimasta aperta in background) tiene già occupata la connessione Bluetooth con l'adattatore — un adattatore seriale può stare connesso a una sola app alla volta. Chiudi le altre app OBD e riprova.
La variabile con il dato ricevuto risulta sempre vuota
Controlla per primo che il nome della variabile scritta dall'Attività collegata all'evento "BT Serial" corrisponda esattamente al nome letto dall'Attività che interroga l'auto: è facile che restino disallineati (es. una scrive %SERIAL_DATA e l'altra legge %LASTDATA) dopo qualche modifica. Usa il registro di Tasker (menu → Avvia Registro) per vedere il nome esatto usato in ogni azione, invece di fidarti della memoria.
Il sensore su Home Assistant resta su "unknown" dopo la prima chiamata
È una normale condizione di corsa tra la creazione del sensore (MQTT Discovery) e la pubblicazione del suo primo valore: si risolve da sola dalla seconda chiamata del webhook in poi.
Dopo un riavvio di Home Assistant, i sensori smettono di aggiornarsi anche se tutto il resto funziona
Capita raramente ma è particolarmente subdolo, perché non produce nessun errore visibile: dopo un riavvio (aggiornamento, riavvio pianificato o imprevisto), un'entità creata da MQTT Discovery può restare "orfana" — visibile, non disabilitata, con la configurazione ancora corretta, ma non più realmente in ascolto sul suo topic di stato. Il sintomo è che il webhook risulta chiamato correttamente (verificalo con il sensore diagnostico) e il valore giusto arriva persino al broker MQTT, ma il sensore resta fermo al vecchio valore. Un semplice ricaricamento dell'integrazione MQTT non basta a risolverlo.
La soluzione è ricreare l'entità da zero: dalle Impostazioni di Home Assistant, elimina l'entità del sensore interessato, poi forza una nuova pubblicazione della sua configurazione di discovery (rilanciando l'automazione o riavviando il servizio/script che la pubblica). Dopo la ricreazione, il sensore torna ad aggiornarsi normalmente.
Nessun dato arriva mai, nemmeno provando più volte
Prima di sospettare Bluetooth o rete, verifica con il sensore diagnostico (vedi sopra) se il webhook viene anche solo chiamato. Se il sensore diagnostico non si aggiorna mai, il problema è tutto lato Tasker, quasi sempre uno di questi due: l'Attività non ha davvero un'azione "Richiesta HTTP" in fondo (capita di prepararla e non salvarla, o di aggiungerla a un'Attività diversa da quella che gira per sbaglio), oppure una delle azioni Bluetooth Serial intermedie non ha "Continua dopo un errore" attivo e interrompe tutto prima di arrivarci (vedi il registro: una riga "ExitErr" invece di "ExitOK" conferma questo caso).
Il valore ricevuto è una scritta ripetuta centinaia di volte (es. "%SERIAL_DATA%SERIAL_DATA...")
La casella "Aggiungi" sull'azione "Imposta Variabile" del passo 3 deve restare spuntata (serve ad accumulare i pezzi di una stessa risposta, vedi sopra) — il problema qui è che manca l'azione "Cancella Variabile" prima di ogni Send descritta al passo 4: senza quel reset, i pezzi si accumulano non solo dentro una risposta ma anche tra un tentativo e l'altro, per ore se hai un controllo automatico periodico. Aggiungi il "Cancella Variabile" mancante prima di ogni Send, poi cancella manualmente la variabile dalla scheda VARS una volta per ripulire il residuo già accumulato.
Il valore ricevuto è letteralmente il testo "%serial_data" (senza numero)
Nel campo "A" dell'azione "Imposta Variabile" del profilo che riceve i dati (passo 3) manca il numero alla fine: deve essere %serial_data1, non %serial_data. È un errore facile da non notare perché non produce nessun errore visibile in Tasker, solo un dato finale sempre sbagliato. Dopo averlo corretto, cancella la variabile globale dalla scheda VARS prima di ritestare, altrimenti per un po' vedrai ancora il vecchio valore sporco.
rfcomm bind restituisce un errore (percorso Raspberry Pi)
Controlla che l'adattatore sia ancora abbinato ("trust" attivo in bluetoothctl) e che nessun altro processo occupi già /dev/rfcomm0; rilascia il binding con sudo rfcomm release 0 e ripeti.
Uso quotidiano e manutenzione
Lascia l'adattatore collegato solo quando ti serve un monitoraggio attivo: la modalità sleep di OBDLink MX+ riduce il consumo, ma su un'auto ferma a lungo un piccolo assorbimento costante può comunque incidere sulla batteria a 12V.
Dove comprarlo
Trovi OBDLink MX+ tramite il collegamento Amazon nella scheda prodotto di questa guida; per approfondire il prodotto in sé vedi la nostra recensione dedicata.
Fonti e ultima verifica
Verifica specifiche e documentazione: settembre 2026. Percorso testato direttamente dalla redazione, incluse le app scartate durante la prova. Il comportamento dei PID può variare da veicolo a veicolo: verifica sempre quali parametri risponde la tua centralina prima di costruire automazioni che dipendono da questi dati.
