V
Visla Hardware
Portal R&D
🔐 Backend Visla — onboarding tracker

Registrare un device tracker (MQTT + DB)

Cosa serve perché un nuovo tracker (firmware MQTTS) si autentichi al broker e appaia in app. Procedura usata per i banchi LilyGO/XIAO.

Un tracker che pubblica via MQTTS (visla/<IMEI>/pos) ha bisogno di 2 registrazioni indipendenti: una credenziale sul broker (mosquitto, per autenticarsi) e un device nell'app (Cloud SQL, per associare le posizioni a un utente). Mancando una delle due: o il modem non si connette, o si connette ma i dati non appaiono.

🧭 Com'è fatto il broker

  • mosquitto gira come sidecar nel pod decoder-0 (namespace visla), accanto al container decoder.
  • Listener 8883 TLS (cert mosquitto-tls) per i device · 1883 plain interno. allow_anonymous false.
  • Auth: password_file + acl_file, montati dal ConfigMap mosquitto-config (chiavi passwords, acl, mosquitto.conf).
  • ⚠️ I file in /mosquitto/config sono un symlink read-only (montati dal ConfigMap) → non si editano nel pod: si aggiorna il ConfigMap e si riavvia il pod.
  • ACL a pattern → nessuna modifica per-device:
user visla-bridge          # il bridge legge tutto e scrive i cmd downlink
topic read  visla/#
topic write visla/+/cmd

pattern write visla/%u/pos     # ogni device (username=IMEI) scrive SOLO il proprio topic
pattern write visla/%u/status
pattern read  visla/%u/cmd

→ Aggiungere un device = solo aggiungere IMEI:hash al file passwords. L'ACL è già coperto dal pattern %u.

1️⃣ Credenziale MQTT (broker)

Username = IMEI del modem · password = segreto per-device (anche random). Genera l'hash con mosquitto_passwd (presente nel container), aggiungilo al ConfigMap, riavvia.

# 1. genera l'hash (nel container mosquitto, file temporaneo)
kubectl exec -n visla decoder-0 -c mosquitto -- sh -c '
  cp /mosquitto/config/passwords /tmp/pw &&
  mosquitto_passwd -b /tmp/pw <IMEI> <PASSWORD> &&
  cat /tmp/pw'        # copia l'output (tutte le righe IMEI:hash)

# 2. incolla il contenuto aggiornato nella chiave "passwords" del ConfigMap
kubectl edit configmap mosquitto-config -n visla
#   (oppure: kubectl create configmap mosquitto-config --from-file=... --dry-run -o yaml | kubectl apply -f -)

# 3. riavvia il pod per ricaricare i file montati
kubectl rollout restart statefulset decoder -n visla   # o: kubectl delete pod decoder-0 -n visla

# verifica: l'utente compare
kubectl exec -n visla decoder-0 -c mosquitto -- cut -d: -f1 /mosquitto/config/passwords

⚠️ Mai committare le password per-device nel firmware in prod. Per il banco vanno bene hardcoded.

2️⃣ Device nell'app (Cloud SQL)

Perché le posizioni si associno a un utente e appaiano in app, il device deve esistere in tabella devices ed essere claimato da un utente (banco: user 11). Accesso al DB via cloud-sql-proxy (psycopg v3).

-- INSERT device (IMEI = identità MQTT/topic) + claim utente 11
INSERT INTO devices (imei, model, protocol_id, hw_version, created_at)
VALUES ('<IMEI>', 'visla-bench', <protocol_id>, 'bench', now())
RETURNING id;

-- claim: lega il device all'utente (banco = user 11)
INSERT INTO user_device_associations (user_id, device_id, ...)
VALUES (11, <device_id>, ...);

Banchi registrati: 7080 = id177, 7070 = id179. Schema esatto colonne/claim: vedi i microservizi visla-devices.

3️⃣ Firmware

  • Broker: mqtt.vislagps.com:8883 (TLS). CA = Let's Encrypt ISRG Root X1 caricata nel modem (A76xx: AT+CCERTDOWN, righe con \n non \r\n).
  • username = IMEI, password = quella registrata allo step 1, clientid = visla-<IMEI>.
  • Publish su visla/<IMEI>/pos (JSON: lat, lon, spd, sats, hdop, valid, ts, battery, volt, rssi) · status = online retain.
  • Stack nativo modem AT+CMQTT* su A76xx Cat-1 (NON TinyGsmClientSecure). Vedi progetto A7670.

📋 Device bench registrati

idIMEI / protocol_id DevicePathStato
185862608083899168Visla XIAO+A7670E · MQTTMQTTS Cat-1free · token XIAOA767
182860016049553337Visla 7080G S3 · MQTTMQTTS NB-IoTfree
171862771076818239Visla A7670E · Cat-1H02/TCP + MQTTclaimed
179867684071283868Visla 7070G · Cat-MH02/TCP + MQTTclaimed
1777777777777Visla 7080G · NB-IoTH02/TCPclaimed

Owner bench = user 11. is_test=true. Per MQTT il bridge matcha per imei(=protocol_id).

✅ Checklist & troubleshooting

  • CMQTTCONNECT non dà 0,0 → IMEI non nel passwords, password sbagliata, o CA non caricata. Verifica l'username nel file.
  • Connette ma niente in app → device non in devices / non claimato.
  • Isola broker vs modem: mosquitto_pub -h mqtt.vislagps.com -p 8883 --cafile isrgrootx1.pem -u <IMEI> -P <pass> -t visla/<IMEI>/pos -m test.
  • URC +CMQTTPUB:0,0 su QoS0 è inaffidabile → tratta l'OK come successo.
  • Log broker: kubectl logs -n visla decoder-0 -c mosquitto -f (mostra connessioni/ACL deny).