# Generic serial and TCP

> Des équipements qui parlent un protocole à eux, fait de texte ou d'octets, comme les indicateurs de pesage et les lecteurs de codes-barres, sur une ligne série, en TCP ou en UDP : comment leurs messages se terminent et sont vérifiés, et comment chaque tag en tire sa valeur.

Le pilote Generic serial and TCP lit et écrit des équipements qui parlent un protocole à eux, fait
de texte ou d'octets simples, là où aucun protocole standard ne s'applique : un indicateur de pesage,
un lecteur de codes-barres ou RFID, un instrument ancien, une imprimante d'étiquettes. On ne peut pas
demander à un tel équipement ce qu'il est, donc rien n'est découvert. Vous dites à l'équipement
comment se termine un message qu'il envoie et comment sa somme de contrôle se vérifie, et vous dites
à chaque tag comment il obtient sa valeur, quels messages sont les siens et quels caractères du
message forment la valeur.

Un équipement atteint son matériel de l'une de trois façons, choisie à sa création :

| Transport | Comment l'équipement est atteint | Ce que ses tags peuvent faire |
| --- | --- | --- |
| Sur une ligne série | Une ligne série de ce pilote, partagée avec les autres équipements qu'elle porte, une requête à la fois. | Requête et réponse, écoute, écritures. |
| **Client TCP** | Sa propre connexion à l'hôte et au port du matériel. | Requête et réponse, écoute, écritures. |
| **Écoute UDP** | Un port de cette station vers lequel le matériel envoie des datagrammes. La station n'envoie rien. | Écoute seulement, lecture seule. |

Un équipement sur une ligne série est rangé sous sa ligne, si bien que cette partie de
l'arborescence se lit **Pilote → Ligne → Équipement → Tag**, comme sous [Modbus RTU](driver-modbus-rtu).
Un équipement réseau se trouve sous le pilote et peut être classé dans des dossiers comme l'équipement
de n'importe quel autre pilote, **Pilote → Dossier → Équipement → Tag**. Un équipement reste du côté
où il a été créé : TCP et UDP s'échangent, mais un équipement ne passe jamais d'une ligne au réseau
ni du réseau à une ligne.

## La page du pilote {#the-drivers-page}

La phrase sous l'en-tête dit « Les lignes série portent les instruments qui partagent un bus, et les équipements réseau se trouvent sous le pilote. Ajoutez une ligne ou un équipement, puis ouvrez-le pour décrire ses messages. »
et la page porte deux tableaux, l'un sous l'autre :

| Tableau | Ce qui le fait grandir | Ce qu'il liste |
| --- | --- | --- |
| **Lignes série** | **Ajouter une ligne**, à droite de son titre. | Les lignes du pilote : **Ligne**, **Réglages physiques** (port · débit · format, sans délai, puisqu'une ligne de ce pilote n'en a pas), **Équipements**, **État**, et les actions Ouvrir, Activer, Désactiver et Supprimer. Vide, il indique « Aucune ligne série pour l'instant. » |
| **Équipements** | **Ajouter un équipement**, à droite de son titre. Il crée un équipement réseau, un **Client TCP**. | Tous les équipements du pilote, ceux d'une ligne compris, avec les colonnes du [tableau des équipements](connector-drivers#the-device-table) de n'importe quel pilote. Vide, il indique « Aucun équipement pour l'instant. » |

L'en-tête compte les équipements entre parenthèses, et la ligne du pilote dans l'arborescence compte
les deux niveaux dès qu'une ligne existe (« 1 ligne · 2 équipements »). La barre du pilote n'a pas de
Découvrir. Le clic droit sur la ligne du pilote propose **Ajouter un équipement**, **Ajouter une ligne**, **Nouveau dossier** et **Actualiser**,
puis, après un séparateur, **Retirer le pilote** ; dans le menu Nouveau… de la colonne, l'entrée du
pilote propose **Nouvel équipement**, **Nouvelle ligne série** et **Nouveau dossier**, puis ses lignes, ses
dossiers et ses équipements. Une fois ajouté, le pilote se range sous le dossier Pilotes de l'arborescence,
avec ou sans ligne ni équipement.

## Ligne série {#serial-line}

Une ligne de ce pilote est la ligne décrite dans [Lignes série](connector-lines), avec moins de
champs. Sa page dit « Un bus série physique : les réglages de port que partagent ses instruments, une requête à la fois. »
et sa carte Ligne physique porte :

| Champ | Sens | Par défaut |
| --- | --- | --- |
| **Nom** | Le nom convivial du bus, affiché dans l'arborescence et sur chaque équipement qu'il porte. | « Nouvelle ligne » |
| **Port série** | Le port COM de Windows, physique, virtuel ou redirigé, saisi ou choisi parmi les ports que Windows rapporte (**Actualiser** les relit). Un port appartient à une ligne, quel que soit le pilote de la ligne. | le premier port libre |
| **Débit (bauds)** | La vitesse du bus, partagée par chaque équipement de la ligne. | 9600 |
| **Format série** | Bits de données, parité et bits d'arrêt : `8N1`, `8N2`, `8E1`, `8E2`, `8O1`, `8O2`, `7N2`, `7E1`, `7E2` ou `7O1`. Les dix sont proposés, parce que ce pilote n'a pas besoin de 8 bits de données. | `8E1` |

Une ligne créée ici démarre désactivée, pour que les réglages du port soient saisis avant que le port
s'ouvre. Le port, le débit et le format ne changent que ligne désactivée ; le nom change à tout
moment. Une ligne de ce pilote n'a ni mode de transmission, ni délai de réponse, ni intervalle minimal
entre transactions, ni silence automatique : chaque équipement qu'elle porte indique dans son propre
panneau comment se terminent ses messages et combien de temps il attend une réponse, comme le dit la
carte Équipements sous la ligne : « Tous les équipements de cette ligne partagent ses réglages de port. Chacun indique dans son propre panneau comment se terminent ses messages et combien de temps il attend une réponse. »
Elle n'a pas de carte Découvrir les unités et son tableau Équipements n'a pas de colonne ID d'unité,
parce qu'un instrument se distingue par ce que disent ses requêtes, pas par une adresse.

**Ajouter un équipement** sur la ligne, ou dans son menu du clic droit, crée un équipement de ce
pilote sur cette ligne. Une ligne appartient pour de bon au pilote sous lequel elle a été créée : un
équipement Modbus RTU et un équipement de ce pilote ne partagent jamais une ligne, et un agent qui
rattache un équipement à une ligne de l'autre pilote est refusé. Les états de la ligne (Arrêt, Au
repos, Connexion…, En ligne, Défaut de port) sont ceux de toute ligne série, dans
[Activation et état de santé](connector-health#serial-line-states).

Sur la ligne, le pilote ouvre le port une fois pour tous les équipements qu'elle porte et envoie une
requête à la fois, en attendant sa réponse avant la suivante. Entre les requêtes, ce qui arrive est
proposé à chaque équipement de la ligne, chacun le découpant en messages selon ses propres règles. Un
port qui échoue est rouvert par la ligne pour tous ses équipements, avec une attente qui s'allonge
entre les tentatives tant qu'il continue d'échouer.

## Équipement {#device}

### Connexion {#connection}

| Champ | Sens | Par défaut |
| --- | --- | --- |
| **Transport réseau** | Équipement réseau seulement. **Client TCP** : « La station se connecte à l'hôte et au port de l'équipement. » **Écoute UDP** : « La station écoute sur un port local ce que l'équipement envoie, et n'envoie rien. » Les deux s'échangent ; un équipement sur une ligne montre sa ligne à la place. | **Client TCP** |
| **Hôte** | TCP : le nom d'hôte ou l'adresse IP du matériel. Une adresse entière peut être collée, avec `tcp://` devant et le port après l'hôte. | vide |
| **Port** | TCP : le port sur lequel le matériel répond, de 1 à 65535. Aucun port n'est standard pour ce genre de matériel, donc un nouvel équipement n'en a pas. | vide |
| **Accepter de** | UDP, à la place de l'hôte : « Seuls les datagrammes de cette adresse sont lus. Vide : n'importe quel expéditeur. » | vide |
| **Port local** | UDP, à la place du port : « Le port de cette station vers lequel l'équipement envoie. Le pare-feu Windows doit le laisser passer. » | vide |
| **Ligne série · fixe** | Un équipement sur une ligne : le nom de la ligne au-dessus de son port, de son débit et de son format, en lecture seule. | la ligne sous laquelle il est ajouté |

Un nouvel équipement TCP affiche « Hôte pas encore saisi » et n'est pas connecté tant qu'il n'a pas
un hôte et un port. Un équipement avec un hôte et sans port, et un équipement UDP sans son port
local, ne peuvent pas être enregistrés : « Indiquez le port : celui de l'équipement en TCP, le port local d'écoute en UDP. »
Un équipement sur une ligne n'a ni hôte, ni port, ni dossier, ni ID d'unité.

La Base URI qu'affiche l'en-tête est l'adresse d'exécution : `generic://tcp/<host>:<port>`,
`generic://udp/<local port>` (avec `from=<sender>` quand Accepter de est rempli) ou
`generic://serial/<line id>/<port>/<baud>/<format>`, suivie de la façon dont les messages se
terminent et se vérifient (`end`, `start`, `terminator`, `length`, `gap`, `timeout`, `checksum` et
le reste). Les octets qu'elle porte sont des octets, jamais la notation dans laquelle l'équipement
est saisi. La copie d'un équipement sur une ligne reste sur cette ligne ; la copie d'un équipement
réseau va au niveau du pilote lui-même.

### La carte Messages reçus {#the-messages-card}

Sous la carte Connexion, la carte **Messages reçus** dit comment les octets sont saisis et comment
un message se termine.

| Champ | Sens | Par défaut |
| --- | --- | --- |
| **Saisi en** | Comment s'écrivent le marqueur de début, le terminateur et, pour chaque tag, la requête, le filtre, le séparateur, le message d'écriture et la réponse attendue. **Texte avec échappements** : les caractères imprimables tels quels, `\r`, `\n`, `\t`, `\\` et `\xNN` pour tout autre octet. **Octets en hexadécimal** : deux chiffres par octet, par exemple `02 30 31 0D`. Changer réécrit chaque champ d'octets de l'équipement et de ses tags, pour que chacun continue d'envoyer les mêmes octets ; tant que l'un d'eux n'est pas fait d'octets valides, le changement est refusé : « La notation n'a pas été changée : un champ d'octets de cet équipement ou de ses tags n'est pas valide dans la notation en cours. Corrigez-le d'abord. » | **Texte avec échappements** |
| **Fin du message** | **Terminateur**, **Longueur fixe** ou **Silence sur la ligne**. En UDP chaque datagramme est un message, quoi que dise ce champ. | **Terminateur** |
| **Terminateur** | Avec Terminateur : les octets qui ferment chaque message. Ils ne font pas partie de ce que lisent les tags. | `\r\n` |
| **Longueur du message (octets)** | Avec Longueur fixe, de 1 à 1024 : « Chaque message compte ce nombre d'octets, marqueur de début et somme de contrôle compris. » | |
| **Silence sur la ligne (ms)** | Avec Silence sur la ligne, de 5 à 10000 : « Un message se termine quand rien n'arrive pendant cette durée. » | 50 |
| **Marqueur de début** | Facultatif. Les octets par lesquels commence chaque message, par exemple `\x02`. Les octets qui le précèdent sont écartés, ce qui remet aussi en phase un flux pris au milieu d'un message, et il compte comme les premiers caractères du message. | vide |
| **Délai de réponse (ms)** | De 50 à 60000 : « Combien de temps une requête attend sa réponse, et une écriture sa réponse attendue. » | 1000 |
| **Durée maximale sans message (s)** | De 0 à 86400, 0 voulant dire jamais : « Les tags en écoute ne comptent plus comme lectures quand rien n'arrive pendant cette durée. 0 : jamais, pour un équipement qui n'envoie que de temps en temps, comme un lecteur de codes-barres. Réglez-la pour un équipement qui envoie en continu, comme une balance. » | 0 |

Un champ que la fin choisie ne lit pas n'est pas affiché et garde sa valeur pour le moment où cette
fin revient. Une valeur dont l'équipement ne peut rien faire n'est pas enregistrée, et le journal des actions dit pourquoi, par exemple « Indiquez le terminateur qui clôt les messages, par exemple \r\n. » ou « La longueur du message doit être comprise entre 1 et 1024 octets. »

### La carte Somme de contrôle {#the-checksum-card}

| Champ | Sens | Par défaut |
| --- | --- | --- |
| **Algorithme** | La somme de contrôle que porte chaque message : **Aucun**, **Somme (8 bits)**, **Complément à deux de la somme (LRC)**, **Complément à deux de la somme sur 7 bits (Toledo)**, **XOR (8 bits)**, **CRC-16/MODBUS** ou **CRC-16/CCITT**. « Un message dont la somme de contrôle ne correspond pas est écarté et compté dans le journal technique, jamais lu comme une valeur. » | **Aucun** |
| **Écrite en** | **Texte hexadécimal**, la somme écrite en chiffres hexadécimaux, ou **Octets bruts**, les octets mêmes de la somme. | **Texte hexadécimal** |
| **Emplacement** | **Avant la fin** : les derniers octets avant le terminateur, ou les derniers octets du message. **Après le terminateur** : juste après lui, qu'elle couvre alors ; proposé seulement quand les messages se terminent par un terminateur. | **Avant la fin** |
| **Octets exclus au début** | De 0 à 255 : « Octets du début du message que la somme de contrôle ne couvre pas, par exemple un STX ou un $. » | 0 |
| **Octets exclus juste avant** | De 0 à 255 : « Octets placés juste avant la somme de contrôle qu'elle ne couvre pas, par exemple le * d'une phrase NMEA. Les tags ne les lisent pas non plus. » | 0 |

Tous les champs sauf l'algorithme n'apparaissent qu'une fois une somme de contrôle choisie. La somme
couvre le message de son premier octet à l'octet qui précède la somme, moins les octets exclus. Un
message dont la somme ne correspond pas n'est jamais lu comme une valeur : il est écarté, et le
journal technique le signale sous l'équipement au plus une fois par minute. La somme est seulement
vérifiée : les requêtes et les écritures partent exactement telles que saisies, si bien qu'une
requête qui a besoin d'une somme de contrôle la porte dans ses propres octets.

| Algorithme | Usage courant |
| --- | --- |
| Somme (8 bits) | Indicateurs. |
| Complément à deux de la somme (LRC) | Indicateurs, trames dans le style de Modbus ASCII. |
| Complément à deux de la somme sur 7 bits (Toledo) | La sortie continue d'un indicateur Toledo, en octet brut après le CR. |
| XOR (8 bits) | Phrases NMEA 0183 (`$…*hh`), indicateurs, lecteurs RFID. |
| CRC-16/MODBUS | Trames binaires ; l'octet de poids faible d'abord en octets bruts. |
| CRC-16/CCITT | Trames binaires (la variante CCITT-FALSE) ; l'octet de poids fort d'abord en octets bruts. |

## Adressage du tag {#tag-addressing}

Un tag de ce pilote n'a pas d'adresse à saisir : sa carte **Source de la valeur** demande comment il
obtient sa valeur, dans les champs ci-dessous. Les octets sont saisis dans la notation de l'équipement.

| Champ | Sens | Par défaut |
| --- | --- | --- |
| **Mode de lecture** | **Requête et réponse** : « La station envoie la requête à l'intervalle de scrutation du tag et lit la valeur dans la réponse. » **Écoute** : « L'équipement envoie de lui-même, et le tag garde le dernier message que son filtre accepte. » Un équipement UDP ne propose qu'Écoute : « Cet équipement écoute en UDP et n'envoie rien : ses tags sont seulement en écoute et en lecture seule. » | **Requête et réponse** |
| **Requête** | En requête et réponse seulement : « Ce que la station envoie à l'intervalle de scrutation du tag, saisi comme l'équipement l'indique. Le premier message que le filtre accepte dans le délai de réponse est la réponse. » | obligatoire |
| **Filtre des messages** | Quels messages appartiennent au tag : **Tous les messages**, **Commence par** (les octets par lesquels ils commencent) ou **Correspond à une expression régulière** (l'**Expression régulière** à laquelle ils correspondent). Pour une requête, « Le message qui répond à la requête. Les autres vont aux tags en écoute. » | **Tous les messages** |
| **La valeur est** | Comment la valeur est découpée dans le message : **Le message entier**, **Position fixe** (**Premier caractère** et **Longueur**), **Champ entre séparateurs** (**Séparateur** et **Numéro du champ**) ou **Groupe de capture d'un motif** (**Motif**). « Les positions et les champs se comptent à partir de 1. Le motif doit avoir exactement un groupe de capture, la valeur. Les nombres se lisent avec un point décimal. » | **Le message entier** |
| **L'équipement écrit une virgule comme séparateur décimal** | Tags Float et Double seulement. La virgule est le séparateur décimal en lecture comme en écriture. | décoché |
| **Message d'écriture** | Tags écrits, pas en UDP : « Ce qu'envoie une écriture, avec {value} là où va la valeur, par exemple SP {value}\r, ou {value:0.00} pour la mettre en forme. Sur un tag Boolean, un message d'écriture sans {value} est une commande, envoyée quand on écrit true. » | vide |
| **Réponse attendue** | « Facultatif. Ce par quoi commence la réponse de l'équipement à une écriture. L'écriture ne réussit que si cette réponse arrive dans le délai de réponse. » | vide |

Les caractères se comptent depuis le début du message, marqueur de début compris ; le terminateur, la
somme de contrôle et les octets qu'elle exclut juste avant elle ne font pas partie de ce que lit un
tag. Un motif est une expression régulière .NET, et un message qu'il met plus de 250 ms à lire n'est
pas lu. Un tag en écriture seule n'a ni champ de requête, ni filtre, ni champ de valeur ; un tag sans
message d'écriture est en lecture seule.

Les types de données sont Boolean, Int32, Int64, Float, Double et String. Le texte découpé est lu
dans le type du tag avant que les étapes propres au tag le convertissent, comme pour tout pilote
(voir [La chaîne de conversion](connector-value-pipeline)) : un Boolean lit `1`, `true`, `on` ou
`yes` et `0`, `false`, `off` ou `no` ; un entier lit un nombre entier (`12.0` se lit 12, `12.5` est
refusé) ; un Float ou un Double lit un nombre décimal ; un String prend les caractères tels quels. Les
espaces autour d'un nombre, et entre son signe et ses chiffres, sont ignorés, parce que les
indicateurs complètent leurs nombres par des espaces. Un tag dont les champs ne peuvent pas
fonctionner n'est pas enregistré, et la page du tag dit ce qui lui manque, par exemple « Indiquez la requête que ce tag envoie. » ou « Le motif doit avoir exactement un groupe de capture, autour de la valeur. »

L'aperçu en lecture seule de l'adresse de bus affiche `ask` ou `listen` suivi de ce qui s'applique,
par exemple `listen?extract=position&start=5&length=6`, ou `ask?send=01RD%0D&extract=field&separator=,&field=3`
pour un tag qui envoie `01RD` et un CR et lit le troisième champ séparé par des virgules de la réponse.

## Lecture {#reading}

| Situation | Tag en requête et réponse | Tag en écoute |
| --- | --- | --- |
| La valeur | Tirée du premier message vérifié que le filtre accepte dans le délai de réponse après la requête. | Tirée du dernier message vérifié que le filtre accepte, daté de son arrivée. |
| Quand il est lu | À l'intervalle de scrutation du tag. | Chaque fois que le matériel envoie ; le tag affiche le dernier message à son intervalle de scrutation. |
| Avant le premier message | Sans objet. | Le tag attend : pas de valeur et pas d'erreur, comme tout tag avant sa première réponse. |
| Pas de réponse, ou un matériel muet | Aucune réponse dans le délai de réponse est une lecture en échec, et la règle du tag pour [un équipement qui n'a pas répondu](connector-value-pipeline#the-device-did-not-answer) décide de ce qu'il affiche. | Passé la **Durée maximale sans message (s)** de l'équipement, chaque tag en écoute échoue sa lecture et sa règle décide de ce qu'il affiche. Une connexion TCP qui tombe les fait échouer quoi que dise cette durée. |
| Un message que le tag ne peut pas lire | Une lecture en échec, avec la raison : un champ manquant, la valeur qui dépasse la fin du message, ou un texte que le type ne peut pas contenir. | Pareil. |

Les messages qui ne répondent à aucune requête vont aux tags en écoute du même équipement, si bien
qu'un équipement peut avoir les deux sortes de tags. Les tags en écoute qui ont le même filtre
partagent ce qui a été entendu, et peuvent tirer des champs différents du même message.

## Écriture {#writing}

Une écriture passe par le même entonnoir que celle de n'importe quel autre pilote : la case
d'écriture prend la valeur physique, et les étapes de conversion sont inversées avant que la valeur
brute soit envoyée (voir [Connector](connector)).

| Message d'écriture | Ce qui est envoyé | Ce que l'écriture rapporte |
| --- | --- | --- |
| Avec `{value}` | Les octets saisis, avec la valeur là où se trouve `{value}` : un nombre en culture invariante (avec une virgule comme séparateur décimal quand le tag le dit), ou mis en forme par `{value:FORMAT}` selon un format numérique .NET (`W{value:000.0}\r` envoie 12,5 sous la forme `W012.5` et un CR) ; un Boolean sous la forme `1` ou `0` ; un texte tel quel. | Faite dès l'envoi. Avec une **Réponse attendue**, faite seulement quand une réponse qui commence par elle arrive dans le délai de réponse ; une autre réponse refuse l'écriture avec cette réponse comme raison, et le silence est une absence de réponse. |
| Sans `{value}`, sur un tag Boolean | Une commande, comme une tare ou une impression : écrire true l'envoie, écrire false est refusé. | Pareil. |
| Aucun | Rien : le tag est en lecture seule. | |

Les écritures attendent leur tour dans la file de l'équipement comme celles de tout pilote : sur une
ligne, elles partagent la requête à la fois de la ligne, en TCP la connexion propre de l'équipement.
Un équipement UDP n'envoie rien, donc ses tags ne peuvent pas être écrits.

## Exemple : un indicateur de pesage en RS-232 {#example-a-weighing-indicator-on-rs-232}

Un indicateur dans le style de la sortie continue de Toledo envoie, plusieurs fois par seconde, un
STX, trois octets d'état, six chiffres de poids, six de tare, un CR et un octet de somme de contrôle.
Sur la station :

1. **Ajouter une ligne** sur la page du pilote ; nommez-la `Scale line`, choisissez `COM3`, gardez
   **Débit (bauds)** à 9600 et choisissez `7E1` comme **Format série**, puis **Activer** la ligne.
2. **Ajouter un équipement** sur la ligne ; nommez-le `Scale`. Sur la carte **Messages reçus**
   gardez **Texte avec échappements** et **Terminateur**, mettez le **Terminateur** à `\r`, le
   **Marqueur de début** à `\x02` et la **Durée maximale sans message (s)** à 10, pour qu'un câble
   débranché se voie comme une communication perdue.
3. Sur la carte **Somme de contrôle** choisissez
   **Complément à deux de la somme sur 7 bits (Toledo)**, **Octets bruts** et
   **Après le terminateur**, avec les deux nombres d'octets exclus à 0.
4. **Ajouter un tag** ; nommez-le `Weight`, Double, en lecture seule. Sur la carte
   **Source de la valeur** choisissez **Écoute**, **Tous les messages** et **Position fixe**, avec
   **Premier caractère** 5 et **Longueur** 6 : le STX est le caractère 1, les trois octets d'état
   vont de 2 à 4, le poids de 5 à 10.
5. Les chiffres ne portent pas de point décimal, donc l'étape Mise à l'échelle du tag le place, par
   exemple un facteur de 0,01 pour un indicateur réglé sur deux décimales.

Un agent fait la même chose en trois appels d'outil :

```
serial_line_upsert driver=GenericSerialTcp name="Scale line" serialPort=COM3 baudRate=9600 serialFormat=7E1
device_upsert driver=GenericSerialTcp name=Scale transport=SerialLine serialLineId=<id> messageEnd=Terminator terminator=\r startMarker=\x02 checksum=SumTwosComplement7Bit checksumFormat=Raw checksumPlacement=AfterEnd silenceTimeoutSeconds=10
tag_upsert device=Scale name=Weight opcUaType=Double tagMode=Listen valueExtraction=FixedPosition valueStart=5 valueLength=6
```

## Exemple : un lecteur de codes-barres en TCP {#example-a-barcode-reader-on-tcp}

Un lecteur de codes-barres doté d'un port Ethernet envoie un code par ligne, et seulement quand il en
lit un :

1. **Ajouter un équipement** sur la page du pilote ; nommez-le `Reader`, gardez **Client TCP**, et
   saisissez **Hôte** 192.168.0.40 et **Port** 2001.
2. Sur la carte **Messages reçus** gardez **Texte avec échappements**, **Terminateur** `\r\n` et
   **Durée maximale sans message (s)** à 0 : un lecteur qui n'envoie rien pendant une heure n'est pas
   en panne. Gardez **Aucun** sur la carte **Somme de contrôle**.
3. **Ajouter un tag** ; nommez-le `Code`, String, en lecture seule. Sur la carte
   **Source de la valeur** choisissez **Écoute**, **Tous les messages** et **Le message entier**.

La même chose avec les outils de l'agent :

```
device_upsert driver=GenericSerialTcp name=Reader transport=TcpClient host=192.168.0.40 port=2001 messageEnd=Terminator terminator=\r\n
tag_upsert device=Reader name=Code opcUaType=String tagMode=Listen valueExtraction=WholeMessage
```

`driver_capabilities` décrit ce pilote sous `genericSerialTcp`, avec ces deux exemples, et
`serial_line_upsert` crée une ligne de ce pilote avec `driver=GenericSerialTcp` ; les autres outils
sont dans [Les outils, domaine par domaine](agent-tools).

## Limites à connaître {#limits-worth-knowing}

- Rien n'est découvert : il n'y a pas de protocole pour demander à un tel équipement ce qu'il est ou
  ce qu'il contient.
- Une trame binaire qui annonce sa propre longueur dans un en-tête n'est pas lue ; un message se
  termine par un terminateur, une longueur fixe, un silence ou un datagramme.
- La somme de contrôle est seulement vérifiée : aucune somme n'est ajoutée à ce que la station envoie.
- Un tag tire une valeur d'un message, sous forme de texte lu dans son type ; les nombres codés en
  entiers ou en flottants binaires dans le message ne sont pas décodés.
- Un équipement UDP ne fait qu'écouter : il n'envoie pas de requête et n'accepte pas d'écriture.
- Un équipement ne peut pas être déplacé entre une ligne série et le réseau, ni vers une autre
  ligne : créez-le là où il doit être et supprimez l'ancien.
