# Pont Bascule Connector — FastAPI + Serial + (optionnel) Tailscale API HTTP (FastAPI) qui pilote un pont bascule connecté en USB (port série) sur Raspberry Pi ou Linux. **Objectif :** permettre à une application/serveur distant d'interroger le pont bascule via réseau, avec une contrainte stricte : **1 requête série à la fois**. --- ## Fonctionnement global ``` Client (PC / serveur / app) --HTTP--> Machine (FastAPI) | | 1 appel à la fois (lock) v Port série (/dev/ttyUSB0) | v Pont bascule ``` **Accès distant (optionnel) :** - via IP Tailscale `100.x.x.x` (VPN mesh) - ou autre VPN / reverse-proxy selon votre infra --- ## Prérequis ### Matériel - Pont bascule branché en USB (ou via adaptateur USB↔RS232/RS485 selon le matériel) ### Système - Raspberry Pi OS / Debian / Ubuntu (autres Linux OK) - Python 3.9+ recommandé - Accès SSH - (optionnel) Tailscale installé et connecté --- ## Installation ### 1) Récupérer le projet ```bash cd ~ git clone gitea@gitea.malio.fr:MALIO-DEV/pont-bascule-connector.git cd pont-bascule-connector ``` ### 2) Installer les dépendances système (Debian/Ubuntu/Raspberry Pi OS) ```bash sudo apt update sudo apt install -y python3 python3-venv python3-pip git ``` Si vous êtes sur un autre OS, installez Python 3 + pip + venv via votre gestionnaire de paquets. ### 3) Installer les dépendances Python ```bash python3 -m venv ./.venv source ./.venv/bin/activate pip install --upgrade pip pip install -r requirements.txt ``` --- ## Hook git (commit-msg) Le repo contient un hook pour valider le format des messages de commit. Activation : ```bash git config core.hooksPath .githooks ``` Format attendu : ```text () : ``` Types autorisés : `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, `test`. --- ## Configuration série (.env) Le fichier `.env` est chargé automatiquement au démarrage (via `python-dotenv`). Créer un fichier `.env` à la racine du projet : ```bash cd ~/pont-bascule-connector nano .env ``` Exemple (mode reel / port serie) : ```env APP_MODE=serial APP_HOST=0.0.0.0 APP_PORT=8000 SERIAL_PORT=/dev/ttyUSB0 SERIAL_BAUDRATE=9600 SERIAL_TIMEOUT_S=1.0 SERIAL_OPEN_DELAY_S=2.0 SERIAL_POST_WRITE_DELAY_S=0.5 ``` Exemple (mode mock pour dev, sans port serie) : ```env APP_MODE=mock APP_HOST=0.0.0.0 APP_PORT=8000 ``` **Notes importantes :** - `APP_MODE=serial` (defaut) utilise le port serie ; `APP_MODE=mock` simule les reponses pour le dev. - `APP_HOST` et `APP_PORT` permettent de changer l'interface d'ecoute et le port HTTP. - `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 votre port est `/dev/ttyACM0`, adaptez `SERIAL_PORT` --- ## Droits port série (dialout) Vérifier les devices : ```bash ls /dev/ttyUSB* 2>/dev/null || true ls /dev/ttyACM* 2>/dev/null || true dmesg | tail -n 30 ``` Ajouter l'utilisateur courant au groupe `dialout` : ```bash sudo usermod -aG dialout "$USER" newgrp dialout ``` Si besoin, reconnectez-vous (ou redémarrez) pour que les droits prennent effet. --- ## Lancer l'API (mode manuel) ```bash source ./.venv/bin/activate uvicorn app.main:app --host 0.0.0.0 --port 8000 ``` Test local : ```bash curl http://127.0.0.1:8000/health ``` --- ## Lancer l'API au démarrage (systemd) ### 1) Créer le service ```bash sudo nano /etc/systemd/system/pont-bascule-api.service ``` Contenu (adapter les chemins et l'utilisateur) : ```ini [Unit] Description=Pont bascule API (FastAPI) After=network-online.target Wants=network-online.target [Service] User= WorkingDirectory=/home//pont-bascule-connector EnvironmentFile=/home//pont-bascule-connector/.env ExecStart=/home//pont-bascule-connector/.venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000 Restart=always RestartSec=2 [Install] WantedBy=multi-user.target ``` ### 2) Activer et démarrer ```bash sudo systemctl daemon-reload sudo systemctl enable --now pont-bascule-api sudo systemctl status pont-bascule-api --no-pager ``` ### 3) Logs ```bash journalctl -u pont-bascule-api -f ``` --- ## API — Endpoints ### Santé **GET** `/health` Exemple : ```bash curl http://127.0.0.1:8000/health ``` ### Dernière réponse (debug) **GET** `/last` ### Envoi trame "Esclave" **POST** `/send/esclave` ```bash curl -X POST http://127.0.0.1:8000/send/esclave ``` ### Envoi trame "DSD" **POST** `/send/dsd` ```bash curl -X POST http://127.0.0.1:8000/send/dsd ``` ### Envoi trame custom (hex) **POST** `/send/custom` ```bash curl -X POST http://127.0.0.1:8000/send/custom \ -H "Content-Type: application/json" \ -d '{"hex":"01 0D 0A"}' ``` ### Format de réponse La réponse renvoie : - `response_ascii` : texte décodé ASCII (souvent le poids + infos) - `response_hex` : trame brute - `duration_ms` : durée de l'opération - `error` : message d'erreur si problème Exemple (indicatif) : ```json { "ok": true, "mode": "serial", "port": "/dev/ttyUSB0", "baudrate": 9600, "request_hex": "01 0D 0A", "response_hex": "30 30 31 32 2E 33 34 20 6B 67", "response_ascii": "0012.34 kg", "duration_ms": 2600, "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, l'API renvoie : - **HTTP 409** - message **BUSY** --- ## Accès à distance via Tailscale (optionnel) ### 1) Vérifier Tailscale Sur la machine : ```bash tailscale status tailscale ip -4 ``` Exemple : IP Tailscale `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 la machine : ```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 ``` --- ## 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 (optionnel) 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. --- ## Recommandations utiles ### Port série stable (udev) Si votre port passe parfois de `/dev/ttyUSB0` à `/dev/ttyUSB1`, on peut créer une règle udev pour avoir un nom fixe (ex: `/dev/pontbascule`).