Exploitez une station ou une centaine : les décisions d'architecture prises à 10 stations déterminent votre succès à 100. Ce guide présente les changements nécessaires à chaque seuil de montée en charge.
Défis de montée en charge par étape
| Stations | Ce qui casse | Cause racine |
|---|---|---|
| 1 | Rien | Tout va bien |
| 5-10 | Dérive de configuration | Configuration manuelle par station |
| 10-25 | Désynchronisation des versions de scripts | Absence de pipeline de déploiement |
| 25-50 | Perte de visibilité pour le débogage | Pas de journalisation centralisée |
| 50-100 | Saturation réseau | Toutes les stations contactent le cloud simultanément |
| 100+ | Collision d'identifiants | Noms de stations non uniques |
Architecture à chaque échelle
1 station
Une seule machine exécutant votre script de test. Aucune infrastructure particulière n'est nécessaire.
[DUT] -> [Station de test] -> [TofuPilot Cloud]
10 stations
À 10 stations, le goulot d'étranglement est la configuration. Il vous faut une source de configuration partagée, un nommage cohérent et un moyen de déployer les mises à jour de scripts.
[10 DUTs] -> [10 stations de test] -> [TofuPilot Cloud]
|
[Dépôt Git pour les scripts]
100 stations
À 100 stations, vous avez besoin d'un pipeline de déploiement, d'une surveillance centralisée et d'un échelonnement des envois.
[100 DUTs] -> [100 stations de test] -> [TofuPilot Cloud]
| |
[Pipeline CI/CD] [Tableau de bord de santé]
[Serveur de configuration]
Nommage et enregistrement des stations
Les stations sont identifiées par leur nom. Une collision corrompt les analyses par station.
{site}-{ligne}-{numéro_station}
# Exemples :
taipei-line1-001
munich-eol-001
Définissez le nom de la station comme variable d'environnement :
TOFUPILOT_STATION_ID=taipei-line1-001TOFUPILOT_API_KEY=tp_live_xxxxxxxxxxxxChoisissez le schéma avant l'existence de la deuxième station. Renommer plus tard scinde l'historique d'une station en deux identités, et les anciennes exécutions gardent l'ancien nom pour toujours.
Distribution des scripts de test
Option 1 : Git Pull (1-20 stations)
0 6 * * * testuser cd /opt/testscripts && git pull origin mainAvantages : Simple. Inconvénients : Nécessite un accès réseau à l'hébergeur Git. Échoue silencieusement.
Cet échec silencieux est le vrai coût. Une station qui a raté le pull continue de tester avec les anciennes limites sans rien signaler d'anormal : vous l'apprenez par la divergence de rendement, pas par une erreur.
Option 2 : Binaire PyInstaller (20-50 stations)
#!/bin/bashpyinstaller --onefile test_main.py --name test_runnerfor station in taipei-line1-{001..020}; do rsync -az dist/test_runner "${station}:/opt/testscripts/test_runner_new" ssh "${station}" "mv /opt/testscripts/test_runner_new /opt/testscripts/test_runner"doneAvantages : Pas de Python sur les stations. Inconvénients : Itération plus lente, binaire plus volumineux.
Notez l'écriture puis le renommage : copier directement sur le chemin en cours d'exécution peut laisser une station avec un binaire à moitié écrit. La boucle n'a pas non plus de gestion d'erreur, donc une station hors ligne est sautée sans commentaire. Vérifiez le code de retour par station si vous utilisez ceci.
Option 3 : Docker (50-100 stations)
FROM python:3.11-slimWORKDIR /appCOPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txtCOPY test_main.py .CMD ["python", "test_main.py"]version: "3.9"services: test_runner: image: your-registry/test-runner:latest restart: unless-stopped environment: - TOFUPILOT_STATION_ID - TOFUPILOT_API_KEY devices: - /dev/ttyUSB0:/dev/ttyUSB0Mettre à jour toutes les stations :
#!/bin/bashparallel-ssh -h stations.txt "docker compose pull && docker compose up -d"Épinglez un tag d'image explicite plutôt que latest dès que vous dépassez quelques stations. Avec latest, deux stations ayant tiré à des jours différents exécutent du code différent et rien n'enregistre lequel.
Comparaison des méthodes de distribution
| Méthode | Stations | Python sur la station | Vitesse de mise à jour | Retour arrière |
|---|---|---|---|---|
| Git pull | 1-20 | Oui | Rapide | git revert |
| PyInstaller | 20-50 | Non | Moyenne | Remplacement du binaire |
| Docker | 50-100 | Non | Rapide | Tag d'image précédent |
Si vous déployez vos procédures depuis un push Git, ce tableau devient largement caduc : le build produit un artefact immuable par commit, chaque station liée le récupère, et le rollback consiste à sélectionner un déploiement précédent.
Configuration centralisée
Ne codez jamais en dur les valeurs qui varient par station ou par produit.
| Niveau de configuration | Portée | Exemple |
|---|---|---|
| Variable d'environnement | Par station | TOFUPILOT_STATION_ID, TOFUPILOT_API_KEY |
| Fichier de configuration | Par produit | Limites de tension, seuils de temporisation |
| Script de test | Par phase de test | Logique de phase OpenHTF |
voltage_rail_3v3: min: 3.2 max: 3.4voltage_rail_5v: min: 4.8 max: 5.2boot_time_ms: min: 0 max: 3000test_main.py32 lines
import yamlimport openhtf as htffrom openhtf.util import unitsfrom tofupilot.openhtf import uploadwith open("config/product_v2.yaml") as f: cfg = yaml.safe_load(f)@htf.measures( htf.Measurement("voltage_3v3").in_range( cfg["voltage_rail_3v3"]["min"], cfg["voltage_rail_3v3"]["max"] ).with_units(units.VOLT))def phase_power_check(test): voltage = read_voltage_rail("3v3") test.measurements.voltage_3v3 = voltagedef main(): test = htf.Test( phase_power_check, procedure_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", # UUID de procédure du dashboard part_number="PCBA-100", ) test.add_output_callbacks(upload()) test.execute(lambda: input("Scanner le numéro de série : "))if __name__ == "__main__": main()Versionnez le fichier de configuration avec le script. Des limites qui changent sans marqueur de version rendent silencieusement incomparables les résultats d'avant et d'après.
Topologie réseau
Les stations communiquent uniquement en sortie. Aucun port entrant n'est requis.
| Destination | Port | Objectif |
|---|---|---|
tofupilot.app | 443 | Envoi des résultats de test |
| Votre hébergeur Git | 443 | Mises à jour des scripts |
| Votre registre de conteneurs | 443 | Téléchargement des images |
À 100 stations, échelonnez les envois pour éviter l'effet de troupeau :
import timeimport randomdef upload_with_jitter(upload_fn, max_jitter_seconds=10): time.sleep(random.uniform(0, max_jitter_seconds)) upload_fn()Le jitter coûte du temps de cycle sur chaque unité : ne l'utilisez que si vous constatez réellement de la contention. Les exécutions se mettent en file localement et se synchronisent au retour du réseau, ce qui absorbe la plupart des pics sans aide.
Surveillance de la santé des stations
Le rendement, le débit et la durée des tests par station sont suivis automatiquement. Filtrez les analyses par station pour détecter les dégradations.
La requête la plus utile à grande échelle est le taux d'échec groupé par station. Si une station est à 12 % quand les autres sont à 2 %, le problème vient de son montage ou de son instrument, pas de votre produit.
Liste de contrôle de santé des stations
| Vérification | Intervalle | Action en cas de défaillance |
|---|---|---|
| Signal de vie | 1 min | Alerter l'astreinte, vérifier le réseau |
| Version du script de test | Au démarrage | Mise à jour automatique via le pipeline |
| Espace disque | 1 heure | Archiver les anciens journaux, alerter si inférieur à 5 Go |
| Connectivité USB de la fixture | Avant chaque test | Échouer le test avec une erreur explicite |
Script d'initialisation de station
bootstrap.sh28 lines
#!/bin/bashset -eSTATION_ID=$1API_KEY=$2if [ -z "$STATION_ID" ] || [ -z "$API_KEY" ]; then echo "Usage: bootstrap.sh <station-id> <api-key>" exit 1fiecho "TOFUPILOT_STATION_ID=${STATION_ID}" >> /etc/environmentecho "TOFUPILOT_API_KEY=${API_KEY}" >> /etc/environmentcurl -fsSL https://get.docker.com | shmkdir -p /opt/testrunnercat > /opt/testrunner/docker-compose.yml << EOFversion: "3.9"services: test_runner: image: your-registry/test-runner:latest restart: unless-stopped env_file: /etc/environmentEOFdocker compose -f /opt/testrunner/docker-compose.yml up -decho "La station ${STATION_ID} est en cours d'exécution."sudo bash bootstrap.sh taipei-line1-042 tp_live_xxxxxxxxxxxxDeux points à resserrer avant d'utiliser ceci sur un vrai atelier. La clé API est passée en argument de ligne de commande, ce qui la place dans l'historique du shell et dans la liste des processus ; lisez-la depuis un fichier ou une invite. Et l'ajout dans /etc/environment duplique les entrées à chaque réexécution au lieu de les remplacer.
