Test Station Setup

Gérer la certification des opérateurs

Suivez la formation, le statut de certification et l'autorisation de test en enregistrant qui a exécuté chaque test et en conditionnant l'accès.

JJulien Buteau
intermediate9 min de lecture14 mars 2026

Un nouvel opérateur exécute un test de travers et met au rebut trois cartes avant que quiconque ne s'en aperçoive. Cela arrive plus souvent qu'il ne le faudrait. La plupart des équipes suivent la certification des opérateurs dans des tableurs qui deviennent obsolètes le jour même de leur création.

Lier l'identité de l'opérateur à chaque exécution est ce qui rend le reste possible : contrôles de certification, analyse du rendement par opérateur, et une piste d'audit qui survit à une revue réglementaire.

Pourquoi le suivi des opérateurs est important

Les industries réglementées l'exigent. L'ISO 13485 (dispositifs médicaux), l'AS9100 (aérospatiale) et l'IATF 16949 (automobile) imposent toutes que les opérateurs soient formés et qualifiés pour les tâches qu'ils effectuent. Mais même sans pression réglementaire, savoir qui a exécuté quel test est important quand vous investiguez une baisse de rendement.

Prérequis

  • Un compte TofuPilot
  • Python 3.9+ avec pip install "tofupilot[openhtf]"
  • Une méthode d'authentification des opérateurs (scan de badge, connexion ou code-barres)

Étape 1 : Enregistrer l'opérateur sur chaque exécution

operated_by est le champ qui lie une exécution à une personne. Un e-mail correspondant à un membre de votre organisation lie l'exécution à ce compte ; toute autre valeur est enregistrée telle quelle comme nom d'opérateur déclaré.

operator_tracking.py
22 lines
import openhtf as htffrom tofupilot.openhtf import uploadPROCEDURE_ID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"  # UUID de procédure du dashboarddef main():    operator_id = input("Scannez le badge opérateur : ")    test = htf.Test(        functional_tests,        power_tests,        procedure_id=PROCEDURE_ID,        part_number="PCB-100-R4",        operated_by=operator_id,    )    test.add_output_callbacks(upload())    test.execute(lambda: input("Scannez le numéro de série du DUT : "))if __name__ == "__main__":    main()

Préférez l'e-mail professionnel de l'opérateur quand il a un compte : cela lie l'exécution à un membre réel plutôt que d'enregistrer une chaîne de badge que personne ne pourra résoudre plus tard.

Étape 2 : Construire une vérification de certification

Les données de certification vivent dans votre propre système, pas dans la plateforme de test. Un fichier JSON convient à une petite équipe ; une API RH ou une base de données a la même forme.

certification_check.py
27 lines
import jsonfrom pathlib import PathCERT_FILE = Path("operator_certs.json")def load_certifications() -> dict:    """Charge les registres de certification des opérateurs."""    if CERT_FILE.exists():        return json.loads(CERT_FILE.read_text())    return {}def is_certified(operator_id: str, procedure_name: str) -> bool:    """Vérifie si l'opérateur est certifié pour une procédure de test spécifique."""    certs = load_certifications()    operator = certs.get(operator_id, {})    return procedure_name in operator.get("certified_procedures", [])def require_certification(operator_id: str, procedure_name: str) -> None:    """Bloque l'exécution du test si l'opérateur n'est pas certifié."""    if not is_certified(operator_id, procedure_name):        raise PermissionError(            f"L'opérateur {operator_id} n'est pas certifié pour {procedure_name}. "            f"Contactez votre responsable de ligne."        )

Exemple de fichier de certification :

operator_certs.json
{  "OP-001": {    "name": "Jane Chen",    "certified_procedures": ["pcba-fct-v2", "motor-fct", "burn-in-48h"],    "certification_date": "2026-01-15",    "expiry_date": "2027-01-15"  },  "OP-002": {    "name": "Mike Torres",    "certified_procedures": ["pcba-fct-v2"],    "certification_date": "2026-02-01",    "expiry_date": "2027-02-01"  }}

Étape 3 : Conditionner le test à la certification

Exécutez la vérification avant le démarrage du test, pour qu'un opérateur non certifié n'atteigne jamais la première phase.

certified_test.py
26 lines
import openhtf as htffrom tofupilot.openhtf import uploadfrom certification_check import require_certificationPROCEDURE_ID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"PROCEDURE_NAME = "pcba-fct-v2"def main():    operator_id = input("Scannez le badge opérateur : ")    require_certification(operator_id, PROCEDURE_NAME)  # lève si non certifié    test = htf.Test(        functional_tests,        power_tests,        procedure_id=PROCEDURE_ID,        part_number="PCB-100-R4",        operated_by=operator_id,    )    test.add_output_callbacks(upload())    test.execute(lambda: input("Scannez le numéro de série du DUT : "))if __name__ == "__main__":    main()

Vérifier avant htf.Test(...) signifie qu'une tentative non certifiée ne produit aucune exécution. Si vous préférez enregistrer la tentative, déplacez la vérification dans une première phase et retournez htf.PhaseResult.STOP.

Soyons clairs sur la nature de ce contrôle : c'est une mesure procédurale, pas une frontière de sécurité. Quiconque peut modifier le script de test peut la contourner. Elle satisfait l'exigence d'audit qu'une vérification existe et soit enregistrée ; elle n'arrête pas une personne déterminée.

Étape 4 : Suivre l'expiration des certifications

Les certifications expirent. Avertir avant, bloquer après.

cert_expiry.py
31 lines
from datetime import datefrom certification_check import load_certificationsdef check_certification_status(operator_id: str, procedure_name: str) -> bool:    """Vérifie la validité de la certification avec avertissement anticipé."""    certs = load_certifications()    operator = certs.get(operator_id)    if not operator:        raise PermissionError(f"Opérateur inconnu : {operator_id}")    if procedure_name not in operator.get("certified_procedures", []):        raise PermissionError(            f"{operator['name']} n'est pas certifié pour {procedure_name}"        )    expiry = date.fromisoformat(operator["expiry_date"])    today = date.today()    if today > expiry:        raise PermissionError(            f"Certification expirée le {expiry}. Recertification requise."        )    days_remaining = (expiry - today).days    if days_remaining < 30:        print(f"ATTENTION : La certification expire dans {days_remaining} jours")    return True

Étape 5 : Analyser les performances des opérateurs

Avec un opérateur sur chaque exécution, vous pouvez répondre aux questions importantes :

  • Rendement par opérateur : Un opérateur est-il systématiquement plus bas ? Il a peut-être besoin d'une formation complémentaire.
  • Durée de test par opérateur : Les opérateurs plus lents suivent peut-être les procédures plus soigneusement, ou ont des difficultés avec l'équipement.
  • Modes de défaillance par opérateur : Si un opérateur rencontre davantage un type de défaillance spécifique, vérifiez sa technique.

Le tableau de bord regroupe les exécutions par opérateur directement. Pour le calculer vous-même, interrogez un opérateur à la fois avec le filtre operated_by_names et comptez les verdicts :

operator_analysis.py
35 lines
import osfrom tofupilot.v2 import TofuPilotPROCEDURE_ID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"OPERATORS = ["OP-001", "OP-002"]def count_outcomes(client, operator: str) -> dict:    counts = {"pass": 0, "fail": 0}    cursor = None    while True:        result = client.runs.list(            procedure_ids=[PROCEDURE_ID],            operated_by_names=[operator],            limit=100,            cursor=cursor,        )        for run in result.data:            counts["pass" if run.outcome == "PASS" else "fail"] += 1        if not result.meta.has_more:            break        cursor = result.meta.next_cursor    return countswith TofuPilot(api_key=os.getenv("TOFUPILOT_API_KEY")) as client:    for operator in OPERATORS:        stats = count_outcomes(client, operator)        total = stats["pass"] + stats["fail"]        if not total:            print(f"Opérateur {operator} : aucune exécution")            continue        print(f"Opérateur {operator} : {stats['pass'] / total * 100:.1f}% ({total} exécutions)")

Utilisez operated_by_ids quand vos opérateurs sont des membres liés de l'organisation plutôt que des noms déclarés.

Deux réserves sur le chiffre. Il compte chaque exécution : une unité échouée puis retestée est comptée deux fois ; pour un vrai rendement au premier passage, prenez la première exécution par numéro de série. Et un chiffre bas pour un opérateur invite à regarder, pas à conclure : les opérateurs testent rarement le même mix de produits ni ne travaillent les mêmes postes.

Notes de conformité réglementaire

NormeExigenceCorrespondance
ISO 13485Registres de formation documentés, évaluation des compétencesOpérateur sur chaque exécution, vérification avant test
AS9100Personnel qualifié pour les tâches assignéesPorte de certification avant le test
IATF 16949Efficacité de la formation évaluéeAnalyse du rendement par opérateur
FDA 21 CFR 820Formation du personnel documentéePiste d'audit complète avec identité de l'opérateur

Les registres de certification eux-mêmes restent dans votre système de référence. Ce que la plateforme de test apporte, c'est le lien immuable entre chaque exécution et la personne qui l'a exécutée.

Plus de guides

Mettez ce guide en pratique