À propos du projet
## Aperçu
plexus-python est le SDK Python léger de la plateforme Plexus. Plexus fournit aux équipes matérielles un stockage de séries temporelles et des tableaux de bord : diffusez en flux les données de drones, robots et appareils IoT vers Plexus Time Series, ou connectez une base existante, pour obtenir tableaux de bord et alertes en temps réel. Ce paquet se charge uniquement d'envoyer les données à la passerelle Plexus ; stockage, tableaux de bord, alertes et gestion de flotte restent côté plateforme.
## Démarrage rapide
```bash
pip install plexus-python
```
```python
from plexus import Plexus
px = Plexus(api_key="plx_xxx", source_id="device-001")
px.send("temperature", 72.5)
```
La clé API s'obtient sur app.plexus.company/api, ou via `plexus init` pour autoriser la machine dans le navigateur.
## Identification des appareils
Chaque appareil a besoin d'un `source_id` unique. Le script d'amorçage est recommandé ; il exige d'abord un nom d'appareil :
```bash
curl -sL https://app.plexus.company/setup | bash -s -- \
--key plx_xxx --name drone-01
```
Le nom devient le `source_id`, qui doit correspondre à `^[a-z0-9][a-z0-9._-]*$` (256 caractères max). Sans `--name` ni `source_id=...` dans le code, le SDK génère au premier lancement un id aléatoire (ex. `source-1a2b3c4d`) enregistré dans `~/.plexus/config.json`. N'utilisez pas le nom d'hôte : les images SD clonées démarrent toutes en `raspberrypi` et les télémétries fusionneraient dans la même source. Les noms ne sont pas dédupliqués automatiquement ; la passerelle renvoie tel quel le `source_id` déclaré, donc deux appareils de même nom écrivent dans la même source.
## Méthodes principales
### send(metric, value)
La méthode la plus utilisée, à appeler à chaque nouvelle mesure. `metric` est une chaîne à namespace pointé (ex. `"motor.rpm"`), `value` accepte tout type sérialisable en JSON : float/int (mesures, compteurs), str (machines à états, codes d'erreur), bool (indicateurs binaires), dict (vecteurs, mesures structurées), list (formes d'onde, angles d'articulation). Paramètres optionnels : `tags={"motor_id": "A1"}` pour le filtrage des tableaux de bord, `timestamp=t` pour un horodatage Unix en secondes.
### send_batch(points)
Envoie plusieurs mesures en un appel réseau, avec horodatage partagé. `points` est une liste de tuples `(metric, value)`, ou `(metric, value, timestamp)` pour un horodatage par point.
### batch()
À utiliser au-delà de quelques mesures par seconde. Chaque `send()` est un message WebSocket ; la passerelle limite le nombre de messages, pas de points (2 000/s par connexion). 25 canaux à 100 Hz en envoi individuel font 2 500 messages/s ; le surplus est rejeté avant stockage.
```python
with px.batch(interval_ms=50) as b:
while running:
b.send("att.pos_x", att.x)
```
Un thread d'arrière-plan vide la file toutes les `interval_ms`, et le reste est vidé à la sortie du bloc ; les mesures gardent leur horodatage d'acquisition. Si la passerelle rejette des trames, elle signale `RATE_LIMITED` ; le SDK compte dans `px.rate_limited_frames` et lève `RateLimitedError` à l'envoi suivant.
### run(name)
Un run est une fenêtre temporelle nommée sur une source, consultable dans `/runs`, comparable par alignement T+0 et vérifiable selon des critères à la clôture. Quitter le bloc marque le run `completed` ; une exception le marque `aborted` et la relance. On peut aussi utiliser `px.start_run()` / `px.end_run()` séparément ; `end_run()` renvoie le run avec `test_result`.
### event(name, data)
Pour consigner ce qui se produit plutôt qu'une grandeur mesurée : pannes, changements d'état, actions opérateur, entrées de journal. La plateforme affiche les événements comme marqueurs sur les graphiques, pas comme lignes temporelles. Limites par événement : valeur chaîne 256 octets, valeur dict/list 4 096 octets JSON, 16 tags max.
### Journaux
Ce paquet n'envoie pas de fichiers de log et ne fournit pas de `logging.Handler`. Pour transmettre des lignes importantes à Plexus, utilisez un événement : `px.event("log", {"level": "error", "msg": "..."})`. Ne transférez que les lignes utiles à la chronologie (erreurs, avertissements, changements d'état), pas chaque log de débogage.
## Flux vidéo
La vidéo nécessite un plan payant : les trames passent par WebSocket et la passerelle les refuse en plan gratuit. Les trames sont transmises en temps réel aux spectateurs et stockées uniquement si l'on appuie sur Record dans l'application ; un enregistrement dure 4 heures max.
- `send_video_frame(frame, camera_id)` : quand vous gérez vous-même la boucle de capture (callback picamera2, boucle OpenCV VideoCapture, pipeline FFmpeg personnel). Accepte un ndarray numpy (nécessite opencv-python), des octets JPEG (transmis tels quels), d'autres octets d'image (décodés via Pillow puis réencodés en JPEG, nécessite `pip install plexus-python[video]`).
- `stream_camera(url, camera_id)` : quand vous avez un flux RTSP ou un fichier vidéo sans vouloir gérer la capture ; le SDK lance FFmpeg en interne (FFmpeg requis dans `$PATH`). Renvoie un `threading.Event` ; appelez `.set()` pour arrêter, l'exécution se fait dans un thread d'arrière-plan.
## Apportez votre protocole
Ce paquet ne contient ni adaptateur, ni détection automatique, ni démon : seulement un client. Faites entrer les valeurs dans `px.send()` avec les bibliothèques que vous utilisez déjà ; le README donne des exemples MAVLink (pymavlink), CAN (python-can), MQTT (paho-mqtt), capteurs I2C (Adafruit CircuitPython), avec des versions exécutables dans `examples/`.
## Fiabilité
Chaque envoi est d'abord mis en tampon local puis transmis, avec retry à backoff exponentiel, préservant les données lors des coupures réseau. Le tampon est par défaut sur disque (SQLite), résistant aux redémarrages et coupures d'alimentation ; `persistent_buffer=False` le garde en mémoire. Utilisez `px.buffer_size()` et `px.flush_buffer()` pour consulter et vider.
## Horodatage et correction d'horloge
Par défaut, le SDK choisit l'heure. En WebSocket, chaque connexion se synchronise avec l'horloge de la passerelle, donc même avec une horloge système imprécise (premier démarrage sans NTP, RTC expirée, image système neuve), les données se placent correctement sur la chronologie. Avec une source de temps externe fiable (GPS, RTC de confiance, NTP hôte) ou pour rejouer des données historiques à horodatage connu, passez explicitement `timestamp`. Limites connues : la synchronisation se rafraîchit à chaque reconnexion WebSocket, donc un appareil connecté longtemps avec une RTC dérivante accumule une dérive non corrigée entre reconnexions ; le repli HTTP ne reçoit pas de synchronisation d'horloge ; `send_batch()` partage un horodatage par défaut.
## Transport
Par défaut, connexion WebSocket à `/ws/device` de la passerelle, pour un flux de télémétrie à plus faible latence et un canal portant les actions déclenchées par les tableaux de bord. Si le socket est indisponible, repli transparent vers `POST /ingest`, sans perte de données. Il n'y a pas de sélecteur de transport : le SDK privilégie toujours WebSocket. En plan gratuit, la passerelle refuse le WebSocket appareil (`streaming_requires_plan`) et le SDK bascule seul en HTTP ; `send()`, `send_batch()`, `batch()`, `event()` restent disponibles ; le streaming temps réel et la vidéo exigent un plan payant, le plan gratuit étant limité à 3 appareils et 7 jours d'historique.
## Commandes
Vous pouvez déclarer les commandes acceptées par le code, avant le premier `send()` (la déclaration est envoyée avec la trame d'authentification). Décorez les gestionnaires avec `@px.command(...)` ; les paramètres acceptent string (maxLength, enum), integer/number (minimum, maximum, unit), boolean, plus title, description, default, required, 16 au maximum, à plat sans imbrication. `danger` vaut normal/dangerous/critical ; `idempotent` vrai ne rejoue qu'après déconnexion ; `expires_in` va de 5 à 3600 secondes ; `concurrency` accepte accept/reject. Le gestionnaire est appelé `handler(run, **params)`, paramètres validés et convertis ; la valeur de retour devient le résultat du run, une exception le fait passer à `failed`. Une clé API avec la permission Receive commands est requise. Le SDK accuse réception de chaque run, n'exécute pas deux fois le même run id, juge l'expiration à l'horloge monotone et rejoue l'état non acquitté après reconnexion. `px.on_command()` est obsolète mais fonctionne encore avec l'ancienne signature.
## Variables d'environnement
`PLEXUS_API_KEY` (requis), `PLEXUS_GATEWAY_URL` (défaut `https://gateway.plexus.company`), `PLEXUS_GATEWAY_WS_URL` (défaut `wss://gateway.plexus.company`).
## Agent skills
Le paquet inclut trois skills pour apprendre aux agents de codage à utiliser l'API Plexus (endpoints, streaming temps réel, erreurs courantes causant des 400 silencieux). `plexus skills install` installe dans `~/.claude/skills` ; avec `--project`, dans `./.claude/skills` pour suivre le dépôt. Markdown pur, sans installation ni identifiants.
## Architecture
```
Your code ── px.send() ── WebSocket /ws/device (ou HTTP POST /ingest) ──> plexus-gateway ──> ClickHouse + Dashboard
```
Un chemin léger, sans agent, sans démon, sans adaptateur. La plateforme HardwareOps complète (tableaux de bord, alertes, RCA, vue de flotte) est dans l'interface web app.plexus.company.
## Licence
Apache 2.0.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.