fix: Update du readme

This commit is contained in:
2026-01-09 16:09:47 +00:00
parent fce468cf76
commit d9eda4746a

413
README.md
View File

@@ -1,28 +1,27 @@
# Pont Bascule Connector (Raspberry Pi) — FastAPI + Serial + Tailscale # Pont Bascule Connector (Raspberry Pi) — FastAPI + Serial + Tailscale
API HTTP (FastAPI) qui pilote un pont bascule connecté en USB (port série) sur Raspberry Pi. API HTTP (FastAPI) qui pilote un pont bascule connecté en USB (port série) sur Raspberry Pi.
Objectif : permettre à une application/serveur distant dinterroger le pont bascule via réseau (Tailscale),
avec une contrainte stricte : **1 requête série à la fois**. **Objectif :** permettre à une application/serveur distant d'interroger le pont bascule via réseau (Tailscale), avec une contrainte stricte : **1 requête série à la fois**.
--- ---
## Fonctionnement global ## Fonctionnement global
```
Client (PC / serveur / app) --HTTP--> Raspberry Pi (FastAPI) Client (PC / serveur / app) --HTTP--> Raspberry Pi (FastAPI)
| |
| 1 appel à la fois (lock) | 1 appel à la fois (lock)
v v
Port série (/dev/ttyUSB0) Port série (/dev/ttyUSB0)
| |
v v
Pont bascule Pont bascule
```
yaml **Accès distant :**
Copier le code
Accès distant :
- via IP Tailscale `100.x.x.x` (VPN mesh) - via IP Tailscale `100.x.x.x` (VPN mesh)
- optionnellement via `tailscale serve` pour exposer lAPI sur le port 80 sans `:8000` - optionnellement via `tailscale serve` pour exposer l'API sur le port 80 sans `:8000`
--- ---
@@ -42,92 +41,108 @@ Accès distant :
## Installation (Raspberry Pi) ## Installation (Raspberry Pi)
### 1) Récupérer le projet ### 1) Récupérer le projet
```bash ```bash
cd ~ cd ~
git clone <URL_DE_TON_REPO> pont-bascule-connector git clone <URL_DE_TON_REPO> pont-bascule-connector
cd pont-bascule-connector cd pont-bascule-connector
2) Environnement Python ```
### 2) Environnement Python
Deux options : Deux options :
Option A : venv global (recommandé si déjà en place) #### Option A : venv global (recommandé si déjà en place)
bash ```bash
Copier le code
python3 -m venv /home/malio/venv python3 -m venv /home/malio/venv
source /home/malio/venv/bin/activate source /home/malio/venv/bin/activate
pip install --upgrade pip pip install --upgrade pip
pip install -r requirements.txt pip install -r requirements.txt
Option B : venv dans le projet ```
bash #### Option B : venv dans le projet
Copier le code
```bash
python3 -m venv ./venv python3 -m venv ./venv
source ./venv/bin/activate source ./venv/bin/activate
pip install --upgrade pip pip install --upgrade pip
pip install -r requirements.txt pip install -r requirements.txt
Configuration série (.env) ```
Créer un fichier .env à la racine du projet :
bash ### 3) Configuration série (.env)
Copier le code
Créer un fichier `.env` à la racine du projet :
```bash
cd ~/pont-bascule-connector cd ~/pont-bascule-connector
nano .env nano .env
```
Exemple : Exemple :
env ```env
Copier le code
SERIAL_PORT=/dev/ttyUSB0 SERIAL_PORT=/dev/ttyUSB0
SERIAL_BAUDRATE=9600 SERIAL_BAUDRATE=9600
SERIAL_TIMEOUT_S=1.0 SERIAL_TIMEOUT_S=1.0
SERIAL_OPEN_DELAY_S=2.0 SERIAL_OPEN_DELAY_S=2.0
SERIAL_POST_WRITE_DELAY_S=0.5 SERIAL_POST_WRITE_DELAY_S=0.5
Notes importantes ```
SERIAL_OPEN_DELAY_S=2.0 et SERIAL_POST_WRITE_DELAY_S=0.5 reproduisent le comportement du script Tkinter historique :
attente 2s après ouverture du port **Notes importantes :**
envoi trame - `SERIAL_OPEN_DELAY_S=2.0` et `SERIAL_POST_WRITE_DELAY_S=0.5` reproduisent le comportement du script Tkinter historique :
- attente 2s après ouverture du port
- envoi trame
- attente 0.5s
- lecture une seule fois de `in_waiting`
- Si ton port est `/dev/ttyACM0`, adapte `SERIAL_PORT`
attente 0.5s ### 4) Droits port série (dialout)
lecture une seule fois de in_waiting
Si ton port est /dev/ttyACM0, adapte SERIAL_PORT.
Droits port série (dialout)
Vérifier les devices : Vérifier les devices :
bash ```bash
Copier le code
ls /dev/ttyUSB* 2>/dev/null || true ls /dev/ttyUSB* 2>/dev/null || true
ls /dev/ttyACM* 2>/dev/null || true ls /dev/ttyACM* 2>/dev/null || true
dmesg | tail -n 30 dmesg | tail -n 30
Ajouter lutilisateur au groupe dialout : ```
bash Ajouter l'utilisateur au groupe `dialout` :
Copier le code
```bash
sudo usermod -aG dialout malio sudo usermod -aG dialout malio
sudo reboot sudo reboot
Lancer lAPI (mode manuel) ```
bash
Copier le code ---
## Lancer l'API (mode manuel)
```bash
source /home/malio/venv/bin/activate # ou ./venv/bin/activate source /home/malio/venv/bin/activate # ou ./venv/bin/activate
uvicorn app.main:app --host 0.0.0.0 --port 8000 uvicorn app.main:app --host 0.0.0.0 --port 8000
```
Test local : Test local :
bash ```bash
Copier le code
curl http://127.0.0.1:8000/health curl http://127.0.0.1:8000/health
Lancer lAPI au démarrage (systemd) ```
Créer le service :
bash ---
Copier le code
## Lancer l'API au démarrage (systemd)
### 1) Créer le service
```bash
sudo nano /etc/systemd/system/pont-bascule-api.service sudo nano /etc/systemd/system/pont-bascule-api.service
```
Contenu (adapter les chemins si nécessaire) : Contenu (adapter les chemins si nécessaire) :
ini ```ini
Copier le code
[Unit] [Unit]
Description=Pont bascule API (FastAPI) Description=Pont bascule API (FastAPI)
After=network-online.target tailscaled.service After=network-online.target tailscaled.service
@@ -143,65 +158,78 @@ RestartSec=2
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
Activer et démarrer : ```
bash ### 2) Activer et démarrer
Copier le code
```bash
sudo systemctl daemon-reload sudo systemctl daemon-reload
sudo systemctl enable --now pont-bascule-api sudo systemctl enable --now pont-bascule-api
sudo systemctl status pont-bascule-api --no-pager sudo systemctl status pont-bascule-api --no-pager
Logs : ```
bash ### 3) Logs
Copier le code
```bash
journalctl -u pont-bascule-api -f journalctl -u pont-bascule-api -f
API — Endpoints ```
Santé
GET /health ---
## API — Endpoints
### Santé
**GET** `/health`
Exemple : Exemple :
bash ```bash
Copier le code
curl http://127.0.0.1:8000/health curl http://127.0.0.1:8000/health
Dernière réponse (debug) ```
GET /last
Envoi trame “Esclave” ### Dernière réponse (debug)
POST /send/esclave
bash **GET** `/last`
Copier le code
### Envoi trame "Esclave"
**POST** `/send/esclave`
```bash
curl -X POST http://127.0.0.1:8000/send/esclave curl -X POST http://127.0.0.1:8000/send/esclave
Envoi trame “DSD” ```
POST /send/dsd
bash ### Envoi trame "DSD"
Copier le code
**POST** `/send/dsd`
```bash
curl -X POST http://127.0.0.1:8000/send/dsd curl -X POST http://127.0.0.1:8000/send/dsd
Envoi trame custom (hex) ```
POST /send/custom
bash ### Envoi trame custom (hex)
Copier le code
**POST** `/send/custom`
```bash
curl -X POST http://127.0.0.1:8000/send/custom \ curl -X POST http://127.0.0.1:8000/send/custom \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{"hex":"01 0D 0A"}' -d '{"hex":"01 0D 0A"}'
Format de réponse ```
### Format de réponse
La réponse renvoie : La réponse renvoie :
response_ascii : texte décodé ASCII (souvent le poids + infos) - `response_ascii` : texte décodé ASCII (souvent le poids + infos)
- `response_hex` : trame brute
response_hex : trame brute - `duration_ms` : durée de l'opération
- `error` : message d'erreur si problème
duration_ms : durée de lopération
error : message derreur si problème
Exemple (indicatif) : Exemple (indicatif) :
json ```json
Copier le code
{ {
"ok": true, "ok": true,
"mode": "serial", "mode": "serial",
@@ -213,105 +241,130 @@ Copier le code
"duration_ms": 2600, "duration_ms": 2600,
"error": null "error": null
} }
Contrainte “1 appel à la fois” (important) ```
Le port série ne doit pas être utilisé en concurrence.
Si une requête est déjà en cours, lAPI renvoie :
HTTP 409
message BUSY
Accès à distance via Tailscale
1) Vérifier Tailscale
Sur le Raspberry :
bash
Copier le code
tailscale status
tailscale ip -4
Exemple : IP Tailscale du Pi 100.122.43.54.
2) Appeler lAPI via Tailscale (simple)
bash
Copier le code
curl http://100.122.43.54:8000/health
curl -X POST http://100.122.43.54:8000/send/esclave
3) Option recommandé : exposer sans port avec tailscale serve
Sur le Raspberry :
bash
Copier le code
sudo tailscale serve --http=80 localhost:8000
sudo tailscale serve status
Ensuite :
bash
Copier le code
curl http://100.122.43.54/health
curl -X POST http://100.122.43.54/send/esclave
4) SSH via Tailscale
bash
Copier le code
tailscale ssh malio@raspberrypi
Dépannage rapide
API down
bash
Copier le code
sudo systemctl status pont-bascule-api --no-pager
journalctl -u pont-bascule-api -n 100 --no-pager
Port série introuvable
bash
Copier le code
ls /dev/ttyUSB* /dev/ttyACM* 2>/dev/null
dmesg | tail -n 50
Permission refusée
bash
Copier le code
groups
# dialout doit apparaître
Pas de réponse
vérifier le baudrate
vérifier le port /dev/ttyUSB0 vs /dev/ttyACM0
augmenter SERIAL_POST_WRITE_DELAY_S (ex: 1.0) si la réponse arrive lentement
Sécurité recommandée (à faire)
Exposer lAPI uniquement via Tailscale :
faire écouter uvicorn en local seulement (--host 127.0.0.1)
utiliser tailscale serve comme reverse proxy
Ajouter un token API si besoin (header Authorization)
Ajouter une route /weight qui parse la chaîne response_ascii et renvoie weight + unit + ticket proprement.
yaml
Copier le code
--- ---
## 3) Autres choses que je te recommande (vraiment utiles) ## Contrainte "1 appel à la fois" (important)
1) **Sécuriser lAPI** Le port série ne doit pas être utilisé en concurrence.
Aujourdhui tu exposes `0.0.0.0:8000` → accessible depuis le LAN.
Si tu veux “Tailscale only” (recommandé) : Si une requête est déjà en cours, l'API renvoie :
- **HTTP 409**
- message **BUSY**
---
## Accès à distance via Tailscale
### 1) Vérifier Tailscale
Sur le Raspberry :
```bash
tailscale status
tailscale ip -4
```
Exemple : IP Tailscale du Pi `100.122.43.54`.
### 2) Appeler l'API via Tailscale (simple)
```bash
curl http://100.122.43.54:8000/health
curl -X POST http://100.122.43.54:8000/send/esclave
```
### 3) Option recommandée : exposer sans port avec `tailscale serve`
Sur le Raspberry :
```bash
sudo tailscale serve --http=80 localhost:8000
sudo tailscale serve status
```
Ensuite :
```bash
curl http://100.122.43.54/health
curl -X POST http://100.122.43.54/send/esclave
```
### 4) SSH via Tailscale
```bash
tailscale ssh malio@raspberrypi
```
---
## Dépannage rapide
### API down
```bash
sudo systemctl status pont-bascule-api --no-pager
journalctl -u pont-bascule-api -n 100 --no-pager
```
### Port série introuvable
```bash
ls /dev/ttyUSB* /dev/ttyACM* 2>/dev/null
dmesg | tail -n 50
```
### Permission refusée
```bash
groups
# dialout doit apparaître
```
### Pas de réponse
- vérifier le baudrate
- vérifier le port `/dev/ttyUSB0` vs `/dev/ttyACM0`
- augmenter `SERIAL_POST_WRITE_DELAY_S` (ex: 1.0) si la réponse arrive lentement
---
## Sécurité recommandée (à faire)
1. **Exposer l'API uniquement via Tailscale :**
- faire écouter uvicorn en local seulement (`--host 127.0.0.1`)
- utiliser `tailscale serve` comme reverse proxy
2. **Ajouter un token API** si besoin (header `Authorization`)
3. **Ajouter une route `/weight`** qui parse la chaîne `response_ascii` et renvoie `weight` + `unit` + `ticket` proprement.
---
## Autres recommandations (vraiment utiles)
### 1) Sécuriser l'API
Aujourd'hui tu exposes `0.0.0.0:8000` → accessible depuis le LAN.
Si tu veux "Tailscale only" (recommandé) :
- Dans systemd : `--host 127.0.0.1` - Dans systemd : `--host 127.0.0.1`
- Et tu actives `tailscale serve --http=80 localhost:8000` - Et tu actives `tailscale serve --http=80 localhost:8000`
2) **Ajouter une route `/weight`** ### 2) Ajouter une route `/weight`
Tu menvoies 1 exemple de `response_ascii` (exact) et je te code un parseur robuste qui sort :
Tu m'envoies 1 exemple de `response_ascii` (exact) et je te code un parseur robuste qui sort :
```json ```json
{"weight": 12.34, "unit": "kg", "ticket": "000123", "raw": "..."} {
Port série stable (udev) "weight": 12.34,
Si ton port passe parfois de /dev/ttyUSB0 à /dev/ttyUSB1, on peut créer une règle udev pour avoir un nom fixe, genre /dev/pontbascule. "unit": "kg",
"ticket": "000123",
"raw": "..."
}
```
Healthcheck matériel ### 3) Port série stable (udev)
Ajouter une route GET /serial/info qui vérifie :
port existe Si ton port passe parfois de `/dev/ttyUSB0` à `/dev/ttyUSB1`, on peut créer une règle udev pour avoir un nom fixe, genre `/dev/pontbascule`.
user a accès
bridge non-busy