# Les outils, domaine par domaine

> Ce que fait chaque outil qu'un agent peut appeler, groupé par l'interrupteur de capacité qui l'annonce, et les outils d'aide qui n'en demandent aucun.

Les noms d'outils sont des identifiants stables en snake_case. Les erreurs sont structurées
et exploitables : un appel qui échoue renvoie ce qui n'a pas fonctionné, plus une
indication nommant l'outil ou l'étape qui corrige le problème, pour qu'un agent se corrige
au lieu de deviner. Le serveur demande à chaque agent de lire l'aide avec `help_search` et
`help_read` avant de répondre à une question sur le fonctionnement de l'application et,
quand le domaine Sauvegardes (gestion) est ouvert, de créer une sauvegarde de configuration
avant de modifier la configuration. Laquelle de ces listes un agent voit réellement, c'est
[ce que chaque domaine ouvre](agent-areas), plus les outils d'aide, qui ne demandent aucun
domaine.

## Aide {#help}

Les deux outils d'aide lisent cette documentation telle que l'installation la porte : les
mêmes articles que le [volet d'aide](app-window#contextual-help) ouvre, écrits pour la
version installée sur la station. Ils viennent avec l'endpoint dès que
l'interrupteur principal est activé, quoi que disent les interrupteurs des domaines, parce
que le texte est la documentation publique et ne montre rien de la station. Les deux
continuent de fonctionner quand le runtime est arrêté.

| Outil | Ce qu'il fait |
| --- | --- |
| `help_search` | Trouve des articles d'après les mots d'une question et renvoie pour chacun le slug, le titre, le résumé et les sections que les mots touchent, le meilleur résultat en premier (10 par défaut, jusqu'à 50). La casse et les accents sont ignorés. Sans requête, il liste tous les articles. |
| `help_read` | Lit un article entier d'après son slug, en texte brut : le titre, le résumé, la liste des sections et le corps, chaque section sur une ligne de titre et les tableaux à raison d'une rangée par ligne, plus les slugs des articles vers lesquels il renvoie. |

Les deux lisent par défaut la langue de l'interface de la station, pour que les pages,
boutons et champs qu'une réponse nomme soient ceux de l'écran. Chacun accepte un `culture`
qui nomme une autre langue que porte l'aide installée ; une langue qu'elle ne porte pas est
refusée avec la liste de celles qu'elle porte, et aucune autre langue ne répond à sa place.
Une installation dont l'aide manque ou ne peut pas être lue répond à chaque appel par la
raison au lieu d'articles.

## Connector : lecture {#connector--read}

| Outil | Ce qu'il fait |
| --- | --- |
| `connector_browse` | Liste l'arborescence que dessine la page Connector, avec l'état de santé en direct : chaque pilote ajouté à la station, y compris un pilote sans rien dessous, et un pilote qui porte un équipement, une ligne série ou un broker est toujours ajouté ; Modbus RTU sous la forme pilote, ligne série, équipement, tag ; MQTT sous la forme pilote, broker (avec l'état de sa session), équipement, tag ; tous les autres pilotes sous la forme pilote, équipement, tag, avec le dossier de chaque équipement à côté. Generic serial and TCP liste ses lignes série comme Modbus RTU et ses équipements réseau comme n'importe quel autre pilote, avec le transport de chaque équipement. SCPI instruments liste ses lignes série et ses autres équipements de la même façon. Un équipement File porte son dossier, son nom de fichier, sa façon de lire (un fichier ou un dossier d'arrivée) et son format. Un équipement Database porte son type de base de données (`databaseKind`). Chaque équipement porte `error`, l'unique phrase que montre sa page, dans la langue de la station : une phrase qui renvoie à sa ligne série ou à son broker quand l'erreur est la leur, sinon l'erreur de l'équipement lui-même (il ne se connecte pas, la connexion est refusée, le pilote avertit), sinon le résumé de ses tags dont la lecture est refusée, la raison de chaque tag étant le `readFailure` de `tag_read`. Il vaut `null` quand l'équipement n'en a aucune ; la phrase que donne `tag_read` pour un tag dont l'équipement n'est pas connecté mène ici. Révèle les alias de tag (`Driver.Folders….Device.Tag`) qu'utilisent `tag_read`, `tag_write` et les expressions Logic. Les alias sont nuls tant que le Connector est arrêté. |
| `tag_read` | Lit les valeurs en direct d'un tag par son alias : `valueRaw`, la valeur de l'équipement lui-même avant toute étape, `value`, la valeur physique après toutes les étapes de la chaîne de conversion, celle de Décimales comprise (un Double que l'équipement rapporte comme 2,718281828459 se lit 2,72 avec Décimales à 2), la qualité, les deux horodatages et `substitution`, qui dit si la valeur est une valeur de remplacement configurée plutôt que ce que l'équipement a rapporté : `None` (une mesure, ou aucune valeur), `NaNReplaced` (la lecture était NaN et le remplacement déclaré a pris sa place), `LastGoodHeld` (la lecture a échoué et la dernière lecture arrivée est maintenue, avec la valeur brute et les horodatages de cette lecture) ou `ReadFailureReplaced` (la lecture a échoué et le remplacement déclaré est présenté). Une valeur de remplacement compte comme une valeur, si bien que la qualité reste bonne sauf défaut de limite, mais ce n'est jamais une mesure. `communicating` dit si l'équipement répond toujours : `false` quand la dernière lecture a échoué ou que rien n'a encore été lu. Une lecture restée sans successeur au-delà de l'intervalle de scrutation du tag, plus une courte marge, compte comme une lecture en échec : la valeur, la qualité et `substitution` répondent comme pour celle-ci (aucune valeur et une qualité mauvaise par défaut, la lecture maintenue ou le nombre déclaré quand le tag le demande), `communicating` vaut `false`, et les horodatages datent la dernière lecture arrivée. Une valeur hors des limites du tag n'est pas une panne de connexion : la qualité devient mauvaise tandis que `communicating` reste `true`. `readFailure` dit pourquoi une lecture n'est pas arrivée, dans l'unique phrase que montre le volet du tag, dans la langue de la station : la raison donnée par l'équipement ou le pilote quand la lecture du tag lui-même a été refusée, ou une phrase qui renvoie à l'équipement du tag quand celui-ci n'est pas connecté. Il vaut `null` tant que le tag lit, et quand une lecture qui n'est pas arrivée n'a pas encore de raison enregistrée. |
| `modbus_server_status` | Rend compte du [serveur Modbus](connector-modbus-server) propre à la station : s'il est en marche (`enabled`), son `port`, son `status` (Off, Listening, PortInUse, Failed avec les mots du système dans `failure`, ou RuntimeStopped), les clients connectés en ce moment (au plus `maximumClients` à la fois), et chaque ligne de la table des registres : sa `registerClass`, le `register` compté à partir de 0 et le `lastRegister`, son type et sa disposition, son `access` (ReadOnly ou ReadAndWrite), sa source (un tag ou une variable, par adresse et identifiant) et ce qu'un client y lit en ce moment, `value` et `good`, ou le `gap` (NoSource, SourceRemoved, NoGoodValue, NotRepresentable) pour lequel un client reçoit l'exception 04. Il reste disponible pendant que le runtime est arrêté. |
| `station_broker_status` | Rapporte le [broker MQTT](connector-mqtt-broker) propre à la station, celui sur lequel les équipements publient, jamais un des brokers que la station lit : s'il est en marche (`enabled`), son `port`, son `status` (Off, Listening, PortInUse, Failed avec les mots du système dans `failure`, ou RuntimeStopped), son `authentication` (Anonymous ou UsernamePassword, avec `username` et `hasPassword`, jamais le mot de passe), les équipements connectés maintenant (au plus `maximumClients` à la fois) et `thisStationEntry`, le broker Cette station du pilote MQTT par lequel la station le lit. Il fonctionne aussi quand le runtime est arrêté. |
| `mqtt_publish_list` | Liste ce que la station publie sur chaque broker MQTT qu'elle lit, la [carte Publier](driver-mqtt#the-publish-card) de chacun : le `publishTopicPrefix` du broker et s'il publie, et chaque ligne avec sa source (par adresse, `removed` quand la source a été supprimée), son `topic` et son message (`value` ou `alarm`), les deux messages étant décrits dans `payloads`. Continue de fonctionner pendant que le runtime est arrêté. Une ligne dont l'`access` vaut `ReadAndWrite` accepte des valeurs sur son `writeTopic` (son topic suivi de `/set`), écrites dans sa source et notées au journal technique sous `MQTT <nom du broker>` ; `payloads.write` dit ce que ce topic accepte. Chaque broker dit son `publishFormat` ; un broker en Sparkplug B ajoute `sparkplug` (son groupe, l'ID du nœud de périphérie de la station et ses équipements), chacune de ses lignes dit l'équipement et la métrique sous lesquels elle est publiée, et `payloads.sparkplug` dit comment sort le Sparkplug B ([Publication en Sparkplug B](driver-mqtt#publishing-in-sparkplug-b)). |
| `remote_access_devices` | Indique qui ouvre les vues de la station par le réseau : les navigateurs connectés depuis un autre ordinateur ou une tablette en ce moment (adresse, navigateur et système, page, utilisateur, depuis quand, et l'appareil configuré qu'est chacun) et les appareils configurés avec la façon dont chacun s'ouvre (vue de départ, verrou, sous quel utilisateur il se connecte, les minutes après lesquelles il revient, lecture seule, et pourquoi il s'ouvre autrement quand son utilisateur fixe ou sa vue de départ a changé). Il ne porte jamais de clé ni son hachage. Il fonctionne toujours quand le runtime est arrêté. |
| `server_status` | Rend compte de l'état de santé du [serveur OPC UA](connector-opcua-server) intégré : s'il est en marche (`enabled`), s'il fonctionne, sa durée de fonctionnement, l'URL de l'endpoint et les sessions clientes connectées, et la taille de l'espace d'adressage configuré ; `available` dit si le runtime du Connector lit, ce qu'il fait aussi pendant que le serveur est arrêté, et `serverError` pourquoi le dernier démarrage du serveur a échoué. `list` est ce que sert le serveur, et tout ce qu'il sert : une ligne par tag, variable Logic, alarme ou commande d'équipement, chacune avec son `access` et le `node` avec lequel un client est configuré ; tant qu'elle est vide, `servesNothing` est vrai. |

## Connector : configuration {#connector--configure}

| Outil | Ce qu'il fait |
| --- | --- |
| `driver_capabilities` | Liste chaque pilote que l'application sait servir, avec les champs de connexion dont un équipement a besoin, le modèle d'adressage des tags (adresse en texte libre et/ou champs typés), la prise en charge de la découverte et ses paramètres, les plages de temporisation et les types de valeur pris en charge, avec `defaultPort`, le port sur lequel on joint un équipement qui n'en nomme aucun. `added` indique si le pilote est ajouté à la station, ce qui le dessine dans l'arborescence du Connector ; créer un équipement, une ligne série ou un broker avec `device_upsert`, `serial_line_upsert` ou `mqtt_broker_upsert` ajoute son pilote. AVEVA PI et HTTP joignent le port du transport que parle l'équipement, et donnent donc aussi `defaultPortByTransport` : 443 en HTTPS, leur transport par défaut, et 80 en clair. Generic serial and TCP ajoute `genericSerialTcp` : ses transports, la façon de saisir les octets, la fin des messages, les sommes de contrôle, les modes, filtres et extractions des tags, la lecture et l'écriture des valeurs, et deux exemples complets. Omron ajoute `omron` : ses deux protocoles avec les champs d'équipement, les formes d'adresse et les types de donnée de chacun, les transports et les plages FINS, les écritures et la découverte. SCPI instruments ajoute `scpi` : ses transports, si cet ordinateur a VISA (`visa.installed`), les terminateurs, les confirmations d'écriture, les commandes de préparation, l'écriture des requêtes et des commandes d'écriture et la lecture des réponses, la découverte, et deux exemples complets. NI-DAQmx ajoute `niDaqmx` : pour chaque mesure, une voie d'exemple, l'unité, ses champs ainsi que les types de donnée et les accès qu'elle admet. Un pilote dont les équipements ont besoin de quelque chose que le produit ne peut pas livrer ajoute `prerequisite` (Fluke NetDAQ : le runtime Visual C++ 2005 ; OPC DA : les OPC Core Components, OpcEnum et le proxy et stub d'OPC DA ; NI-DAQmx : le NI-DAQmx de National Instruments ; SCPI : un VISA 64 bits, NI-VISA ou la Keysight IO Libraries Suite, pour ses seuls équipements VISA, avec les deux pages ; Database : un pilote ODBC 64 bits ou une source de données pour un équipement ODBC, jugé équipement par équipement (`perDevice` true), si bien que `installed` reste null et que l'erreur de l'équipement dit ce qui manque) : si cet ordinateur l'a (`installed`, pour un pilote ajouté à la station), la page officielle de téléchargement, le fichier, comment l'installer, l'écueil connu et ce qui se passe ensuite. SNMP ajoute `snmp` : ses versions et les identifiants que prend chacune, les niveaux de sécurité et les protocoles SNMPv3, les types par genre de valeur, chaque objet standard que le pilote connaît par son nom avec son OID, le comportement des lectures et des écritures, la découverte, et deux exemples complets. File ajoute `file` : le chemin simple, le dossier et le confinement à ce dossier, les formes du nom du fichier, un fichier ou un dossier d'arrivée, les formats avec leur grammaire d'adresse, ce qu'un tag lit et ses types, les réglages de texte, le comportement des lectures et des écritures, la découverte, et trois exemples complets. Database ajoute `database` : chaque base de données avec ses champs et son port propre, le chiffrement, les deux façons dont un tag lit et les deux dont il écrit, la règle selon laquelle une valeur n'entre dans une instruction que comme `@value` ou `@now`, les délais, le conseil sur l'utilisateur de la base de données, la découverte et quatre exemples complets. La carte qu'un agent lit avant `device_upsert` ou `tag_upsert`. |
| `serial_line_list` | Liste chaque ligne série enregistrée, y compris celles qui sont désactivées ou vides, avec son identifiant stable et son pilote ; une ligne Modbus RTU aussi avec son mode et ses temporisations configurée, automatique et effective. |
| `serial_line_upsert` | Crée une ligne série ou en met une à jour par son identifiant stable. `driver` nomme le pilote auquel elle appartient, `ModbusRtu` (par défaut), `GenericSerialTcp`, `Scpi` ou `Omron`, fixé à la création ; une ligne du pilote générique, du pilote SCPI ou du pilote Omron refuse `mode`, `responseTimeoutMs` et `minimumTransactionIntervalMs`. Le nom et l'état d'activation changent à tout moment ; l'intervalle minimal entre transactions change lui aussi pendant que la ligne est activée ; le port série, la vitesse, le format série, le mode de transmission et le délai de réponse ne changent que pendant que la ligne enregistrée est désactivée. |
| `serial_line_delete` | Supprime une ligne par son identifiant stable. Une ligne qui contient encore des équipements est refusée, sauf si l'appel autorise explicitement la suppression de tous les équipements et tags qu'elle porte. |
| `mqtt_broker_list` | Liste tous les brokers MQTT enregistrés, désactivés et vides compris, avec leur identifiant stable, l'endroit où ils répondent, leur transport, leur nom d'utilisateur, leur ID client, leur maintien de session, leur préfixe de topic et leur nombre d'équipements. Dit si un mot de passe est enregistré et ne le renvoie jamais. Montre aussi le format de la publication (`publishFormat`) et le groupe Sparkplug B (`sparkplugGroupId`). |
| `mqtt_broker_upsert` | Crée un broker MQTT ou en met un à jour par son identifiant stable : nom, état d'activation, hôte (une adresse `mqtt://` ou `mqtts://` entière est décomposée), port, TLS, nom d'utilisateur, mot de passe, ID client, maintien de session et le préfixe sous lequel sa carte Publier propose les topics (`publishTopicPrefix`, une chaîne vide ramène la valeur par défaut). Seuls les paramètres fournis changent ; un broker n'est activé qu'avec un hôte, et un ID client qu'utilise un autre broker est refusé. Une modification enregistrée de la connexion reconnecte la session que partagent tous les équipements du broker. `publishFormat` (`Json` ou `SparkplugB`) choisit comment sort la carte Publier, et `sparkplugGroupId` le groupe Sparkplug B du nœud de périphérie de la station (une chaîne vide revient à `GanterLab` ; un groupe qui contient `/`, `+` ou `#` est refusé). |
| `mqtt_broker_delete` | Supprime un broker par son identifiant stable. Un broker qui contient encore des équipements est refusé, sauf si l'appel autorise explicitement la suppression de tous les équipements et tags qu'il porte. |
| `mqtt_publish_upsert` | Crée une ligne de la [carte Publier](driver-mqtt#the-publish-card) d'un broker (`brokerId` et `source` : un tag, `Connector.` et son alias, une variable, `Variables.` et son chemin, ou une alarme, `Alarms.` et son chemin) ou en modifie une par `id`. `topic` est facultatif : absent, la ligne prend celui proposé d'après le nom de la source sous le préfixe du broker, et une chaîne vide le reprend. Un broker publie une source une fois et un topic une fois ; un topic ne contient ni + ni # et ne commence pas par $. Une ligne ne change jamais de broker. `access` vaut `ReadOnly`, la valeur par défaut, ou `ReadAndWrite`, que seuls un tag accessible en écriture sur un pilote qui écrit, ou une variable mémoire, acceptent : la station écrit alors ce qui est publié sur le topic de la ligne suivi de `/set` ([Écriture en retour](driver-mqtt#writing-back)). Le topic d'une ligne ne peut pas être le topic d'une autre suivi de `/set`. Sur un broker en Sparkplug B, la ligne est publiée comme une métrique (`row.sparkplug`), et `ReadAndWrite` accepte les valeurs que lui envoient les commandes Sparkplug B. |
| `mqtt_publish_delete` | Supprime une ligne d'une carte Publier par `id`. La station cesse de la publier ; le tag, la variable ou l'alarme n'est pas touché. |
| `device_upsert` | Crée ou met à jour un équipement par pilote et nom (le pilote est immuable après la création). Seuls les paramètres fournis changent ; les champs de connexion dépendent du pilote ; déplacer un équipement dans un dossier réécrit chaque référence à ses anciennes adresses de tag. Un équipement de Generic serial and TCP prend `transport` et les champs de ses cartes Messages reçus et Somme de contrôle, et `serialLineId` seulement pour une ligne de son propre pilote ; un équipement sur une ligne refuse l'hôte, le port et le dossier. Un équipement Omron accepte `omronProtocol` (`Fins` ou `NjNx`) et, en FINS, les champs `fins*` de sa carte FINS ; un équipement lu par nom de tag refuse un port. Un équipement SCPI accepte `transport` (`Tcp`, `Visa`, ou `SerialLine` avec le `serialLineId` d'une ligne de son propre pilote), `visaResource`, `terminator`, `responseTimeoutMs`, `writeCheck` et `setupCommands`. Un équipement NI-DAQmx accepte `daqmxDevice`, le nom que NI MAX lui donne. Un équipement SNMP accepte `snmpVersion`, `snmpCommunity` (SNMPv1, SNMPv2c), `username`, `password`, `snmpSecurityLevel`, `snmpAuthProtocol`, `snmpPrivacyProtocol` et `snmpPrivacyPassword` (SNMPv3), `responseTimeoutMs` et `snmpRetries` ; il renvoie si chaque secret est défini, jamais le secret. Un équipement File prend `fileFolder`, `fileName`, `fileMode` (`SingleFile` ou `Inbox`), `fileFormat`, `fileEncoding`, `fileSeparator`, `fileDecimal`, `fileHeaderRow` et `fileWrites`, avec `fileHeaderText` et `fileLineEnd` une fois l'écriture activée ; il renvoie `file.fileStatus`, le fichier que lit le pilote en marche et ce qu'il y a lu. Un équipement Database accepte `databaseKind`, et pour un serveur `host`, `port` et `databaseName` (sur SQL Server aussi `databaseInstance`, `databaseWindowsSignIn` et `databaseEncryption`), `databaseFile` pour SQLite ou `databaseOdbc` pour ODBC, avec `username` et `password` ; il renvoie `database`, l'adresse et le fait que l'équipement attend encore ou non son utilisateur, jamais le mot de passe. Un port hors de la plage de 0 à 65535 est refusé ; 0 désigne le port que le pilote joint. Le changement est appliqué au serveur en cours d'exécution immédiatement. |
| `device_delete` | Supprime un équipement et tous ses tags ; appliqué au serveur en cours d'exécution immédiatement. |
| `tag_upsert` | Crée ou met à jour un tag sur un équipement. L'adressage dépend du pilote (adresse en texte libre et/ou champs typés ; pour Generic serial and TCP, le mode de lecture, la requête, le filtre, l'extraction et les champs d'écriture ; pour SCPI instruments, la requête en `address`, `valueField` et `writeTemplate` ; pour NI-DAQmx, la voie physique en `address` et les champs `daqmx*` de sa mesure ; pour SNMP, l'OID en `address`, en chiffres ou par son nom standard ; pour File, la colonne ou le chemin en `address`, `fileSource`, `fileRow` et ses champs, `fileWriteMode` et `fileLineTemplate`, une valeur de texte libre prenant les champs `value*` du pilote générique, et un nouveau tag naissant en lecture seule ; pour Database la colonne de la valeur comme `address`, `databaseSource`, `databaseTable`, `databaseRow` et ses champs ou `databaseQuery`, et une fois que le tag écrit `databaseWriteMode` et `databaseCommand`, un nouveau tag naissant là aussi en lecture seule) ; la réponse renvoie l'adresse de bus assemblée et l'alias pour `tag_read`. Comprend les étapes de lecture invalide : l'action sur NaN pour les tags numériques, et la présentation d'un échec de lecture pour tout tag que la station lit, dont seul `Replace` est réservé aux tags numériques et booléens. Un `Replace` déjà enregistré que le nouveau type du tag ne peut pas porter est enregistré comme la valeur par défaut à sa place : l'action sur NaN devient `PassThrough` dès que le type n'est plus numérique, et la présentation d'un échec de lecture devient `ShowError` dès que le type est String, DateTime, Guid ou ByteString. |
| `tag_delete` | Supprime un tag ; appliqué immédiatement. |
| `server_start` | Met le serveur OPC UA intégré en marche et le démarre, comme le fait Activer sur sa ligne : il sert sa liste, et reste en marche d'un redémarrage à l'autre jusqu'à `server_stop`. Sans effet s'il fonctionne déjà ; quand le Connector lui-même ne tourne pas, il est démarré d'abord, en matérialisant la configuration courante. |
| `server_stop` | Arrête proprement le serveur, comme le fait Désactiver : les clients OPC UA sont déconnectés et plus rien n'est publié jusqu'à ce que `server_start` le remette en marche. Le Connector continue de lire, et la lecture des tags, Logic et les enregistrements continuent. |
| `server_restart` | Arrêt puis démarrage du serveur seul, tant qu'il est en marche ; le Connector lit tout du long. Un serveur arrêté est refusé, puisque c'est `server_start` qui le met en marche. Les modifications d'équipements et de tags s'appliquent avec `connector_refresh`. |
| `server_list_upsert` | Crée une ligne de la [liste](connector-opcua-served-nodes) du serveur OPC UA, ou en met une à jour par son `id`. `source` nomme un tag (`Connector.` et son alias), une variable (`Variables.` et son chemin), une alarme (`Alarms.` et son chemin) ou une commande d'équipement (l'adresse de l'équipement, un point, le nom de la commande et `()`) ; une source figure une seule fois dans la liste. `access` vaut ReadOnly, le défaut de toute nouvelle ligne, ou ReadAndWrite, que seuls un tag accessible en écriture ou une variable mémoire acceptent ; l'écriture d'un client passe alors par l'entonnoir d'écriture de Logic et est consignée au journal technique avec la session du client. La réponse porte la ligne avec son `node`. |
| `server_list_delete` | Supprime une ligne de la liste par son `id`. Un client ne trouve plus son nœud ; la source qu'elle servait n'est pas touchée. |
| `modbus_server_configure` | Met le serveur Modbus en marche ou l'arrête (`enabled`), ou le déplace sur un autre `port`, de 1 à 65535, comme le fait sa page. Le port du serveur web, de l'accès agent ou du serveur OPC UA, et un port qu'un autre programme retient, sont refusés ; le pare-feu Windows n'est jamais modifié. En marche, il laisse toute machine qui atteint le port lire ce que la table sert. Répond avec le serveur entier, comme `modbus_server_status`. |
| `station_broker_configure` | Met en marche ou arrête le broker MQTT propre à la station (`enabled`), le déplace sur un autre `port` et change son `authentication`, son `username` et son `password`, comme le fait sa page, dans cet ordre : port, authentification, puis marche ou arrêt. Le port du serveur web, de l'accès agent, du serveur OPC UA ou du serveur Modbus, et un port qu'un autre programme occupe, sont refusés ; le pare-feu Windows n'est jamais modifié. En marche, il ajoute le broker Cette station au pilote MQTT. Répond avec le broker entier, comme `station_broker_status`. |
| `modbus_map_upsert` | Crée une ligne de la table des registres du serveur Modbus, ou en met une à jour par son `id`. `source` nomme un tag par son adresse (`Connector.` et son alias, tel que `connector_browse` le liste) une variable (`Variables.` et son chemin) ou une alarme (`Alarms.` et son chemin, toujours ReadOnly, qui sert l'état que désigne `alarmValue` : Active, Acked ou State) ; `registerClass` (HoldingRegister par défaut), `register` (base 0), `type` (Float par défaut, Boolean dans une bobine ou une entrée discrète), `length` pour un String, `mostSignificantByte` et `mostSignificantWord` reprennent les champs et les règles d'un tag Modbus. `access` vaut ReadOnly, le défaut de toute nouvelle ligne, ou ReadAndWrite, que seuls un registre de maintien ou une bobine acceptent, avec une source qui accepte les écritures (un tag accessible en écriture, une variable mémoire). Une nouvelle ligne a besoin de son `register` et de sa `source` ; une ligne que la table refuse reçoit la raison et une indication. |
| `modbus_map_delete` | Supprime une ligne de la table des registres par son `id`. Un client qui lit ses registres reçoit l'exception 02 à partir de là ; le tag ou la variable qu'elle servait n'est pas touché. |
| `remote_access_device_update` | Modifie le nom d'un appareil configuré, sa vue de départ (un tableau de bord par id ou par nom, ou vide pour la retirer, ce qui le déverrouille aussi), le verrou, les minutes sans contact (0 pour jamais) et la lecture seule, comme le fait sa ligne sur la page Accès à distance. Sous quel utilisateur l'appareil se connecte ne se change pas ici : il faut une personne qui détient Gérer les utilisateurs locaux. Un appareil se configure et s'oublie sur l'écran de la station, jamais par un outil. Répond avec l'appareil tel que `remote_access_devices` le liste. |

## Connector : pilotage {#connector--operate}

| Outil | Ce qu'il fait |
| --- | --- |
| `connector_refresh` | Réconcilie de façon incrémentale le serveur en cours d'exécution avec les équipements configurés (ajouts, retraits, recréations) sans redémarrage complet ; la façon la plus légère d'appliquer des modifications. |
| `device_discover` | Lance le balayage de découverte d'équipements d'un pilote et renvoie les candidats avec leurs tags, sans rien enregistrer. Seuls les pilotes dont le protocole permet un vrai balayage y participent ; les candidats qui existent déjà sont signalés comme tels. Un balayage SNMP parcourt soit `target` avec `snmpCommunity`, soit `snmpDevice`, un équipement configuré, ce qui est la façon de balayer un agent SNMPv3. Un balayage File lit soit `fileDevice`, un équipement configuré, soit `fileFolder`, `fileName`, `fileMode` et `fileFormat` saisis pour le balayage. Un balayage Database lit `databaseDevice`, un équipement configuré, et facultativement `databaseTables`, un nom de table ou un motif avec `*`. Un `target` que la carte Portée du balayage du pilote refuserait, ou aucun là où le balayage en demande un, est refusé avec ce qu'il doit être. Un balayage Database, File ou SNMP arrêté à sa limite de valeurs, de tables ou d'objets le dit dans `cut`, avec ce qu'il faut passer pour voir le reste ; une liste complète n'a pas de `cut`. |

## Logic : lecture {#logic--read}

| Outil | Ce qu'il fait |
| --- | --- |
| `logic_browse` | Parcourt l'espace d'adressage Logic depuis sa racine, le même arbre à points que lit chaque expression : System, Server, Connector, Variables, Alarms, Process et Assets. Les dossiers de l'opérateur sont de vrais niveaux d'adresse ; les points enfants portent leur valeur en direct et leur qualité, et un point de tag du Connector porte aussi `substitution` et `communicating`, tels que `logic_read` les rapporte. |
| `logic_read` | Lit un point par son adresse à points (par exemple `Variables.Setpoint`) et renvoie la valeur en direct et la qualité. Un point de tag du Connector porte aussi `substitution` et `communicating`, tels que `tag_read` les rapporte, et c'est ce qui distingue une valeur de remplacement, ou la lecture d'un équipement qui a cessé de répondre, d'une mesure en direct ; les autres points ne portent ni l'un ni l'autre. Une lecture qui s'est tue s'y lit comme une lecture en échec. |

## Logic : configuration {#logic--configure}

Les upserts sont partiels (un paramètre omis garde sa valeur) et chaque brouillon fusionné
passe la validation qu'appliquent les éditeurs de [Logic](logic) ; un brouillon invalide est
rejeté et rien n'est appliqué à moitié.

| Outil | Ce qu'il fait |
| --- | --- |
| `variable_upsert` | Crée ou met à jour une variable : Expression (une seule expression JavaScript en lecture seule sur l'espace d'adressage) ou Memory (une valeur modifiable, rémanente si vous le demandez). Le nom est la clé et, une fois assaini, l'adresse ; le paramètre de dossier la classe, en réécrivant chaque référence à l'ancienne adresse. |
| `variable_delete` | Supprime une variable par son chemin, y compris sa valeur rémanente. Les voies qui y étaient liées perdent leur source. |
| `action_upsert` | Crée ou met à jour une action : un bloc d'instructions JavaScript comportant exactement deux verbes d'écriture, l'affectation d'une variable mémoire et l'écriture d'un tag en valeur physique. Validée statiquement, jamais exécutée à l'enregistrement. |
| `action_delete` | Supprime une action par son nom. Les déclencheurs qui y étaient liés restent inactifs. |
| `trigger_upsert` | Crée ou met à jour un déclencheur périodique : toutes les `intervalMs` (100 au minimum) l'action liée part sur la voie des actions ; un top qui tombe pendant une exécution en cours est sauté. Le lien vers l'action est souple et se fait par nom. |
| `trigger_delete` | Supprime un déclencheur ; l'action liée n'est pas touchée. |
| `alarm_upsert` | Crée ou met à jour une alarme : une expression de condition booléenne, une priorité (Critical/High/Medium/Low), des retards d'apparition et de disparition, l'obligation ou non d'un acquittement, et le style de signalisation. Enregistrer une condition ou une temporisation modifiée réinitialise la machine d'état en cours. |
| `alarm_delete` | Supprime une alarme par son chemin ; une signalisation active est d'abord effacée. |
| `logic_folder_upsert` | Crée, renomme ou reclasse un dossier d'organisation d'une section (Variables, Alarms, Actions, Triggers ; trois niveaux au maximum). Pour Variables et Alarms le chemin du dossier fait partie de l'adresse : un renommage ou un déplacement réécrit donc chaque expression, script, condition et liaison de tableau de bord situés en dessous. |
| `logic_folder_delete` | Supprime un dossier. Rien de ce qu'il contenait n'est détruit : les éléments et les sous-dossiers remontent d'un niveau et les références sont réécrites ; une collision de nom à destination fait refuser la suppression. |

## Logic : pilotage {#logic--operate}

Toutes ces opérations empruntent le même entonnoir d'écriture de la Logique que les pages et
sont journalisées avec l'origine **MCP**. Une écriture quitte la Logique pour la file de
livraison de l'équipement concerné, et c'est l'appel de l'outil qui attend la réponse : ce
qui revient dit ce qu'est devenue la valeur, et pas seulement qu'elle est partie.

| Outil | Ce qu'il fait |
| --- | --- |
| `variable_write` | Écrit une valeur dans une variable Memory (convertie vers son type de sortie, conservée si elle est rémanente). Les variables Expression sont calculées et refusent l'écriture. |
| `tag_write` | Écrit une valeur physique dans un tag accessible en écriture : elle remonte à l'envers la chaîne de conversion du tag, est convertie vers le type de l'équipement, puis écrite sur l'équipement. La réponse porte ce que le tag présente une fois l'écriture passée : la valeur, la qualité, `substitution` et `communicating`, tels que `tag_read` les rapporte, si bien qu'un équipement qui a accepté l'écriture mais a cessé de répondre aux lectures ne se confond pas avec un équipement qui répond toujours. Les tags en lecture seule et les pilotes en lecture seule sont refusés avec la raison. |
| `action_run` | Exécute une action sur la voie des actions et renvoie son résultat et sa durée. Une action désactivée échoue sans s'exécuter. |
| `alarm_ack` | Acquitte une alarme, la réponse de l'opérateur ; sans effet quand rien n'est en attente. |
| `alarm_ack_all` | Acquitte toutes les alarmes qui attendent un acquittement, en un seul élément de la file de la logique, chaque transition étant journalisée. |

## Journaux : lecture {#logs--read}

| Outil | Ce qu'il fait |
| --- | --- |
| `logs_read` | Lit le flux de journal en direct de tout le programme (celui de la console de la page [Événements](events)), filtré par gravité minimale (Debug/Information/Warning/Error, Information par défaut), par domaine (App/Server/Connector/Logic/Process/Dashboard/Agent/Licensing), par composant et par une sous-chaîne de contexte ; renvoie les correspondances les plus récentes (100 par défaut, 500 au maximum). Les actions d'un agent sont journalisées dans le domaine Agent. |
| `event_history_read` | Lit la chronologie persistante des événements d'exploitation, celle qui survit aux redémarrages : transitions d'alarme, transitions d'occurrence et transitions de verrouillage. Filtre par nature (Alarm/Occurrence/Interlock), par période UTC bornes comprises et par niveau (priorité d'alarme, gravité d'occurrence ou transition de verrouillage) ; les plus récentes d'abord, 100 par défaut, 500 au maximum. Strictement en lecture seule : rien ne peut vider ni supprimer une entrée du journal. |

## Process : lecture {#process--read}

| Outil | Ce qu'il fait |
| --- | --- |
| `process_models` | Liste les modèles du [Process](process) en entier : voies, groupes partagés, unités avec leur câblage résolu et leur état de fonctionnement, procédures, volets, recettes, évaluations, occurrences, plus la bibliothèque globale de modèles de rapport. La carte qu'un agent lit avant de démarrer quoi que ce soit. |
| `process_runs` | Liste les essais, du plus récent au plus ancien : identifiant, nom, état, verdict, ce qui s'est exécuté, qui l'a démarré (Station/User/Automation/Agent), temps et avancement des cycles. Peut être restreinte aux essais en cours, filtrée par une partie du nom ou de n'importe quelle valeur des métadonnées (un numéro de série, un lot) et plafonnée (50 par défaut). |
| `process_run` | Lit le dossier figé complet d'un essai par son identifiant : instantané, métadonnées, critères jugés avec le nombre d'échantillons, épisodes et événements d'occurrence, écritures de recette telles qu'exécutées, commentaires, et les artefacts figés du rapport et de l'étiquette avec leurs tentatives d'impression. Calcule au besoin le nombre de lignes du datalog et sa plage de temps. |
| `process_samples` | Lit les échantillons qu'un essai a enregistrés, pendant qu'il enregistre ou après sa fin. Une plage d'au plus 500 échantillons arrive telle qu'enregistrée : un point par échantillon, avec une valeur par voie. Une plage plus longue arrive résumée : sa durée est divisée en 500 intervalles égaux, et chaque intervalle porte le minimum, le maximum et la moyenne de chaque voie, si bien qu'un pic survit dans le maximum. La réponse dit lequel des deux cas s'applique et, résumée, combien de temps dure chaque intervalle et combien d'échantillons il regroupe. `fromUtc` et `toUtc` resserrent la plage, et une plage assez étroite revient telle qu'enregistrée ; `channels` ne lit que les voies qu'il nomme. |
| `unit_status` | Rend compte de l'état en direct d'une unité : si elle fonctionne (avec l'essai en cours) et la valeur physique actuelle derrière chaque voie, lue sans enregistrement. |

## Process : configuration {#process--configure}

| Outil | Ce qu'il fait |
| --- | --- |
| `process_view_configure` | Configure exactement un volet d'un modèle : l'icône dessinée à côté de lui et sa présence ou non sur la page View. Rien d'autre de l'agrégat Process n'est modifiable par MCP ; le reste s'édite sur la page Process. |

## Process : pilotage {#process--operate}

Les essais démarrés, terminés ou commentés par un agent enregistrent **Agent logiciel** comme auteur,
jamais l'opérateur qui se trouve connecté au poste.

| Outil | Ce qu'il fait |
| --- | --- |
| `process_snapshot` | Capture une ligne de datalog sur une unité en dehors d'une procédure. Chaque appel crée un nouvel essai Instant, déjà terminé, dans les [Historiques](histories), sans évaluation (verdict None). |
| `process_evaluate` | Capture une ligne de datalog et la juge avec une évaluation ; crée un essai Instant terminé et renvoie son verdict. |
| `process_recipe_apply` | Applique une fois une recette Instant à une unité, par le canal d'écriture du Process et ses verrous de source. Commande l'équipement ; ne crée aucun essai (les écritures sont journalisées). Les recettes Temporal sont refusées. |
| `process_start` | Démarre l'essai d'une procédure sur une unité, avec un objet JSON pour les champs de métadonnées que la procédure demande. Chaque valeur transmise est enregistrée, ou rien ne démarre : un champ que la procédure ne demande pas, une valeur pour un champ séquentiel (l'application le compose au démarrage) ou un champ nommé deux fois font refuser le démarrage, tout comme une métadonnée obligatoire absente ou invalide, une unité déjà en fonctionnement ou un conflit de verrou sur une voie partagée. Renvoie l'identifiant du nouvel essai. |
| `process_stop` | Arrête un essai en cours : bloc de finalisation, instantané figé dans l'historique, verdict calculé. |
| `process_hold` | Suspend le profil temporel d'un essai à la dernière consigne ; le datalog continue d'enregistrer. |
| `process_resume` | Reprend le profil temporel d'un essai suspendu. |
| `process_abort` | Interrompt un essai depuis l'état Running ou Held : la finalisation s'exécute, l'instantané est écrit, l'état devient Aborted et le verdict NOK. |
| `process_comment` | Ajoute un commentaire horodaté dans le fichier d'un essai : une note dans la chronologie pendant l'essai, une note après coup ensuite. |
| `process_report` | Génère (ou régénère) le rapport PDF d'un essai terminé et renvoie le chemin de son fichier. Un modèle de document nommé, pris dans la bibliothèque globale, l'emporte sur celui que la procédure a configuré ; sans l'un ni l'autre, la mise en page par défaut avec toutes les sections s'applique. Refusé tant que l'essai est en cours. |
| `process_run_delete` | Supprime définitivement un essai enregistré : son pointeur dans l'index des historiques et le fichier de base de données de l'essai. Refusé tant qu'il est en cours ; la configuration n'est pas touchée. |

## Tableaux de bord : configuration {#dashboard--configure}

Les noms de rôle que ces outils lisent et renvoient sont en anglais sur toute station :
`Not signed in`, `Viewer`, `Operator`, `Maintainer` et `Developer`, quels que soient les
mots que l'opérateur lit à l'écran. `Admin` ne figure pas dans la liste : ce rôle voit
toujours tous les tableaux de bord. Un rôle renommé par l'administrateur porte le nom qu'il
a saisi.

| Outil | Ce qu'il fait |
| --- | --- |
| `dashboard_list` | Liste les tableaux de bord (ou, si vous nommez un modèle, les vues de ce modèle) : taille de la grille, dossier, icône, indicateur de démarrage, visibilité par rôle et chaque composant avec sa position, sa couche et son JSON de propriétés, plus chaque réseau de tracés enregistré. Renvoie aussi le catalogue des natures de composant, avec la taille et le jeu de propriétés par défaut de chacune. |
| `dashboard_upsert` | Crée ou met à jour un tableau de bord par son nom : taille de la grille (un rétrécissement qui laisserait un composant orphelin est rejeté), dossier et icône dans la colonne Visualisation de la page View, indicateur de démarrage, visibilité de la barre d'état en plein écran, et visibilité par rôle. Nommer un modèle adresse les vues de ce modèle à la place. Les pages de tableau de bord ouvertes reflètent le changement en direct. |
| `dashboard_delete` | Supprime un tableau de bord et ses composants par leur nom ; nommer un modèle supprime la vue de ce modèle à la place. |
| `component_upsert` | Ajoute un composant par sa nature (placé sur la première cellule libre à la taille par défaut de sa nature, sauf indication contraire) ou en met un à jour par son identifiant. Le placement doit tenir dans la grille ; le chevauchement est autorisé, la couche z décidant l'ordre de dessin ; le JSON de propriétés est le jeu typé de cette nature. Nommer un modèle adresse les vues de ce modèle à la place, donc une vue créée là-bas se met en page ici. |
| `component_delete` | Retire un composant par son identifiant ; nommer un modèle adresse les vues de ce modèle à la place. |
| `connection_upsert` | Relie deux bornes de Symbol par un réseau de tracés typé, en résolvant le type, le rôle et le sens depuis le catalogue de symboles exactement comme le fait l'éditeur du plan de travail. Deux extrémités qui se résolvent en types différents échouent, sauf si un tracé indéfini est explicitement autorisé ; un ancrage qui porte déjà un tracé est rejeté. Nommer un modèle adresse les vues de ce modèle à la place. |
| `connection_delete` | Retire un réseau de tracés par son identifiant et la révision attendue, pour qu'une suppression périmée soit rejetée au lieu d'écraser une modification plus récente ; nommer un modèle adresse les vues de ce modèle à la place. |

## Interface : automatisation {#ui--automate}

Ces outils pilotent la vraie fenêtre de l'application ; ils existent pour qu'un agent
vérifie l'interface que voit l'opérateur, et non une simulation de celle-ci. Les
interactions sont envoyées à la fenêtre en direct : la conduite attendue est donc de faire
suivre chaque geste d'un `ui_screenshot` et d'en observer l'effet, et une correspondance
ambiguë revient sous forme de liste de candidats plutôt qu'en clic deviné.

| Outil | Ce qu'il fait |
| --- | --- |
| `ui_state` | Rend compte de l'état de la fenêtre : page active, pages disponibles, thème, taille et visibilité de la fenêtre, et adresse de boucle locale sur laquelle cette instance sert son interface. L'appel d'orientation, avant tout le reste. |
| `ui_navigate` | Active une page de l'application par son nom stable, qui est en anglais sur toute station : `View`, `Process`, `Logic`, `Connector`, `Users`, `Validation`, `Events`, `Agent`, `Settings`, `Account`. Le libellé que la barre de navigation affiche dans la langue de la station est accepté également. |
| `ui_screenshot` | Capture la fenêtre telle qu'elle est affichée dans un fichier PNG et renvoie son chemin absolu ; restaure d'abord la fenêtre si elle est masquée dans la zone de notification. Peut capturer une seule région nommée (une zone `data-doc-region` unique et visible) au lieu de la fenêtre entière ; une région absente, masquée ou ambiguë échoue en listant les régions visibles, au lieu de retomber silencieusement sur une capture complète. |
| `ui_scroll` | Fait défiler la zone de défilement principale de la page active vers le haut, vers le bas ou d'un écran à la fois, en renvoyant les décalages pour qu'une longue page puisse être balayée. |
| `ui_set_theme` | Applique le thème de la station (System, Light ou Dark) : celui dans lequel la fenêtre de la station se dessine et que suit chaque navigateur qui n'a pas choisi le sien ; un navigateur qui a choisi le sien le garde. Le choix est conservé exactement comme celui des touches de thème dans la fenêtre de la station : un agent bien élevé rétablit donc la valeur d'origine quand il a fini. |
| `ui_resize` | Redimensionne la fenêtre restaurée en unités indépendantes du périphérique, bornées au minimum de la fenêtre ; utile pour auditer les mises en page étroites. |
| `ui_click` | Clique le bouton, le lien, la case à cocher ou l'interrupteur visible dont le texte correspond ; les cases et les interrupteurs se trouvent par le libellé de leur champ et le résultat indique l'état atteint. Une ambiguïté renvoie les candidats au lieu d'en choisir un. |
| `ui_set_text` | Écrit une valeur dans une zone de texte identifiée par le libellé de son champ, en validant la liaison comme le ferait une saisie. |
| `ui_select` | Sélectionne un élément par son texte visible : un chemin séparé par des barres obliques parcourt un arbre en le dépliant au passage ; un segment unique correspond aussi aux éléments d'une liste, d'un onglet, d'une liste déroulante et aux lignes de grille de la page courante. |

## Sauvegardes : gestion {#backups--manage}

| Outil | Ce qu'il fait |
| --- | --- |
| `backup_create` | Crée un instantané en ligne de la base de données de configuration dans le dossier des sauvegardes, avec une note facultative. Les essais enregistrés vivent hors de la configuration et ne sont jamais touchés par une sauvegarde ni par une restauration. |
| `backup_list` | Liste les sauvegardes de configuration (nom de fichier, date de création, taille, note) ainsi que toute restauration déjà programmée. |

Il n'existe délibérément **aucun outil de suppression de sauvegarde** : la rétention
appartient à l'opérateur seul, sur la page [Sauvegardes](settings-backups).

## Sauvegardes : restauration {#backups--restore}

| Outil | Ce qu'il fait |
| --- | --- |
| `backup_restore` | Programme une sauvegarde pour remplacer la configuration courante au **prochain** démarrage de l'application. Rien ne change dans l'application en cours d'exécution et l'outil ne la redémarre jamais ; la configuration remplacée fait d'abord l'objet d'un instantané automatique, et l'opérateur peut annuler la restauration en attente depuis les Paramètres jusqu'au redémarrage. Refusé pendant qu'un enregistrement est en cours. |

## Paramètres : gestion {#settings--manage}

| Outil | Ce qu'il fait |
| --- | --- |
| `settings_read` | Lit les préférences d'affichage et de cycle de vie de la station : formats de date, d'heure et de nombre, nombre de décimales, thème, indicateurs de fermeture dans la zone de notification et de rapport d'incident. |
| `localization_set` | Met à jour les préférences d'affichage (partiel : un paramètre omis reste). Affichage seulement : le stockage, les entrées et sorties des pilotes et les enregistrements utilisent toujours le format invariant. |
| `asset_list` | Liste les ressources de l'utilisateur (images, icônes, couleurs) avec leurs identifiants, leurs valeurs et leurs chemins. |
| `asset_import` | Importe un PNG ou un JPG depuis un chemin de fichier local dans la bibliothèque de ressources détenue par l'application et renvoie l'identifiant de la nouvelle ressource. Les octets sont copiés, donc le fichier source peut être déplacé ensuite. |
| `symbol_validate` | Valide un contenu de symbole en ligne (SVG brut ou paquet v2) sans rien enregistrer : une simulation de l'import réel, qui renvoie les erreurs, les avertissements du nettoyage et un résumé de ce qui a été reconnu. La description de l'outil porte le [contrat de symbole portable](ganter-symbols) au complet. |
| `symbol_import` | Importe un contenu de symbole en ligne comme nouvelle ressource de symbole utilisateur et renvoie son identifiant et sa référence `user:<guid>`. Crée toujours une ressource ; un nom en collision reçoit automatiquement un suffixe. |

## Signalements : rédaction {#reports--draft}

| Outil | Ce qu'il fait |
| --- | --- |
| `report_draft` | Ouvre le [formulaire de signalement](account-feedback#a-report-drafted-by-an-agent) dans la fenêtre de la station, déjà rempli de ce que l'agent a écrit : `kind` (`DriverRequest`, `Bug` ou `Suggestion`), `summary` (une ligne de 120 caractères au plus ; plus longue, elle est refusée, pas coupée) et `details` (facultatif). Comme le bouton Signaler de la barre de titre, il capture d'abord la fenêtre et propose la capture avec le signalement, cochée. Il répond aussitôt que le formulaire est ouvert et que rien n'est parti. |

L'outil n'envoie jamais. La personne à la station lit le signalement, le corrige si elle veut et appuie sur Envoyer ; le résultat s'affiche dans la barre d'état de la station et ne revient pas à l'agent. Tant que ce domaine est activé, le serveur demande à chaque agent de proposer un signalement quand la personne a besoin d'un pilote que Ganter Lab n'a pas, quand un appel échoue d'une façon qui ressemble à un défaut du programme, ou quand la personne demande une amélioration, et les descriptions de `driver_capabilities`, `device_upsert` et `device_discover` disent la même chose.

Il refuse avec un `reason`, et alors n'ouvre ni ne capture rien :

| `reason` | Quand |
| --- | --- |
| `not_permitted` | Le rôle connecté à la station n'a pas Envoyer des signalements à Ganter. |
| `no_station_window` | La station n'a pas de fenêtre à elle où ouvrir le formulaire : un hôte qui ne sert ses pages qu'aux navigateurs. |
| `no_credential` | La session ne peut pas envoyer : le profil de démonstration, connecté ou non, ou une connexion au compte Ganter de la station qui ne garde aucun identifiant. |
| `form_busy` | Le formulaire de signalement est ouvert à la station, ou un signalement est en cours de capture ou d'envoi. |
| `draft_in_progress` | Le formulaire contient un signalement qu'une personne est en train d'écrire. Un brouillon précédent de l'agent que personne n'a modifié est remplacé, lui. |

Une station qui n'est connectée à aucun compte Ganter n'est pas refusée : le formulaire s'ouvre et dit
que le signalement part sans compte, et que Ganter ne peut donc pas y répondre.

Comme tout outil qui modifie quelque chose, il répond `Runtime stopped` tant que le runtime est arrêté.
