# MQTT scanner ⇆ cloud — lista della spesa

Configurazione **meccanica** del canale. Copia-incolla dall'alto in basso.
Dettagli e *perché* in [DEPLOY-baremetal.md](DEPLOY-baremetal.md) (prod) e
[TEST-LAB.md](TEST-LAB.md) (macchina di test). Qui solo i passi.

Due lati:
- **CLOUD** = il broker centrale (`my.c4rgo.cloud` in prod, il PC di test in LAN).
- **SCANNER** = ogni Raspberry, che apre un *bridge* uscente verso il cloud.

Un solo strumento per vedere se va tutto: **`./c4rgo-mqtt-status.sh`** (§ Verifica).

---

## A. CLOUD — una volta sola per broker

Serve `ca.crt` + `ca.key` della **C4rgo-CA** (la stessa che firma i device).

| | **TEST** (PC in LAN, es. 192.168.0.80) | **PRODUZIONE** (my.c4rgo.cloud) |
|---|---|---|
| 1. installa broker | `sudo EXTRA_SAN=IP:192.168.0.80 ./install-broker-baremetal.sh ca.crt ca.key` | `sudo ./install-broker-baremetal.sh ca.crt ca.key` |
| 2. annota | la password `r_server` che lo script stampa | idem |
| 3. cancella la chiave CA | `shred -u ca.key` | `shred -u ca.key` |
| 4. porta 8883 nel firewall | `sudo ufw allow 8883/tcp` | idem (o già aperta) |

> **L'unica differenza test/prod è `EXTRA_SAN`.** Aggiunge l'IP alle SAN del cert
> così il bridge può puntare all'IP *tenendo la verifica TLS accesa*. In prod si
> omette. Se la 1883 è già occupata sul PC di test: `LOCAL_PORT=1884` davanti al
> comando (poi `SCANNER_MQTT_PORT=1884` in `.env.local`).

Poi, **un utente broker per ogni scanner** (username = device_id):
```bash
sudo mosquitto_passwd -b /etc/mosquitto/c4rgo-scanner.passwd kiosk_36b94b28 '<password-scanner>'
sudo systemctl reload mosquitto
```

E l'**app di test** (`.env.local` nel progetto c4rgocloud):
```dotenv
SCANNER_MQTT_HOST=127.0.0.1
SCANNER_MQTT_PORT=1883          # o 1884 se hai usato LOCAL_PORT
SCANNER_MQTT_PASSWORD=<password r_server del passo 2>
```

**Verifica il broker:**
```bash
./c4rgo-mqtt-status.sh doctor          # tutto verde? il broker è pronto
```

---

## B. CLOUD — il worker (legge i topic e scrive nel DB)

In test conviene tenerlo in primo piano (si legge tutto):
```bash
php bin/console cache:clear
php bin/console app:scanner:listener -vv
```
Quando funziona, installalo come servizio (come in prod, toglie anche i warning dev).
La unit ha 3 segnaposto da sostituire — **utente**, **path progetto**, **php**:
```bash
sed -e "s#__DEPLOY_PATH__#/var/www/c4rgocloud#g" \
    -e "s#__PHP_BIN__#/usr/bin/php#g" \
    -e "s#__RUN_USER__#www-data#g" \
    c4rgo-scanner-listener.service | sudo tee /etc/systemd/system/c4rgo-scanner-listener.service >/dev/null
sudo -u www-data /usr/bin/php /var/www/c4rgocloud/bin/console cache:clear --env=prod
sudo systemctl daemon-reload && sudo systemctl enable --now c4rgo-scanner-listener
sudo systemctl status c4rgo-scanner-listener
```
(adatta i 3 valori alla macchina; dettagli in [DEPLOY-baremetal.md](DEPLOY-baremetal.md) § 5.)

---

## C. SCANNER — una volta per Raspberry

1. **Copia** `docker/mqtt/device-bridge.conf.example` sul device come
   `c4rgo-cloud-bridge.conf` e personalizza:
   - `connection`, `remote_username`, `remote_clientid` → il **device_id**
   - `remote_password` → la password creata al passo A
   - le righe `topic ... c4rgo/<device_id>/...` → il **device_id**
   - `notification_topic c4rgo/<device_id>/status/bridge` → il **device_id**
     (è il segnale di presenza online/offline; vedi § D)
   - `address` → **IP del PC di test** (in prod: `my.c4rgo.cloud:8883`)

   ⚠️ **mosquitto non ha commenti a fine riga.** Un `# ...` in coda a
   `remote_password` entra *nella password* e il bridge fallisce con *not
   authorised*. Tieni i commenti su righe proprie.

2. **Installa** (permessi 600: contiene la password):
   ```bash
   sudo install -m 600 -o root -g root c4rgo-cloud-bridge.conf /etc/mosquitto/conf.d/
   sudo systemctl restart mosquitto
   ```

3. **Verifica il bridge:**
   ```bash
   sudo ./c4rgo-mqtt-status.sh doctor     # deve dire: bridge CONNESSO al cloud
   ```

> Un solo file bridge in `conf.d/` alla volta. Per passare test→prod si **modifica**
> questo file (§ E), non se ne aggiunge un secondo.

---

## D. Verifica — un comando, colpo d'occhio

Lo strumento **`c4rgo-mqtt-status.sh`** capisce da solo se gira sul cloud o su uno
scanner. Password `r_server`: la legge da `.env.local`, oppure `-P <pass>`.

**Sul CLOUD — chi c'è e chi è vivo adesso:**
```bash
./c4rgo-mqtt-status.sh                  # elenco scanner
```
```
  DEVICE                 STATO    #TOP  SERVIZI (retained)
  kiosk_36b94b28         online   3     modem,status
  kiosk_a1b2             OFFLINE  2     modem,status
  sim7600                ?        2     data,status
```
- **online / OFFLINE** = presenza del bridge sul cloud, retained e istantanea:
  `1` alla connessione, `0` (will del broker) su crash/stop/mancanza corrente.
  Indipendente dal link (ethernet/wifi/modem) — non dipende dal modem.
- **?** = device senza topic di presenza: legacy o bridge senza `notification_topic`.
- **#TOP / SERVIZI** = quanti topic e quali sottosistemi pubblica (a colpo
  d'occhio se manca `modem`, `gps`, ecc.).

**Guardare un device da vicino:**
```bash
./c4rgo-mqtt-status.sh watch kiosk_36b94b28    # tail live di tutti i suoi topic
```

**Check di configurazione** (auto broker/scanner, verde = ok, giallo = attenzione):
```bash
./c4rgo-mqtt-status.sh doctor           # sul cloud: broker+cert+auth; sullo scanner: bridge
```

**Se qualcosa è rosso**, il messaggio dice già cosa guardare. Diagnosi grezza:
```bash
sudo journalctl -u mosquitto -n 30 --no-pager      # errori broker/bridge
sudo ss -lntp | grep -E ':(8883|1883|1884)\b'      # i listener sono su?
```

---

## E. Passaggio TEST → PRODUZIONE

Sul Raspberry, in `/etc/mosquitto/conf.d/c4rgo-cloud-bridge.conf`, **due righe**:
```diff
-address 192.168.0.80:8883
+address my.c4rgo.cloud:8883
-remote_password <password-di-test>
+remote_password <password-di-produzione>
```
```bash
sudo systemctl restart mosquitto
sudo ./c4rgo-mqtt-status.sh doctor      # deve tornare verde
```
Nient'altro cambia lato device. Sul cloud di produzione: stesso
`install-broker-baremetal.sh` **senza** `EXTRA_SAN`.
