# La cadena de conversión

> La conversión tipada que comparte cada tag, de la lectura bruta al valor de ingeniería, las dos políticas de lectura no válida, las acciones de fuera de rango, las transformaciones de Boolean y String, y cómo una escritura deshace las etapas.

Todos los tags comparten una misma cadena de conversión tipada que convierte la lectura bruta en el valor de ingeniería. La cadena vive en el tag mismo: la tarjeta Conversión de la página [Tags](connector-tags#the-conversion-card) y la cuadrícula del dispositivo muestran las mismas etapas, y el valor que aterriza en Logic, en los paneles de control, en el registrador y en lo que publica la estación es el que sale de la última etapa. El nodo público de OPC UA lleva el valor bruto.

## Primero el valor bruto {#raw-first}

La cadena arranca del **valor bruto** forzado al tipo de dato del tag, no del objeto propio del driver: un driver que entrega 3.7 a un tag Int32 lee 4 en lo alto de la tarjeta, y todas las etapas continúan a partir de ese 4. Una lectura que el tipo declarado no puede contener en absoluto (texto donde se declara un número) es una lectura vacía, nunca un cero sustituto. Las etapas calculan con números reales, y en el otro extremo el valor de ingeniería toma su tipo:

| Tag | Valor de ingeniería |
| --- | --- |
| Tipo de dato entero, Escala y Calibración apagadas, o activadas con factor 1 y desplazamiento 0 (como nace todo tag) | El número entero mismo, en el tipo de dato del tag. |
| Tipo de dato entero, Escala o Calibración que cambian el valor | Un número real (Double), redondeado por la etapa Decimales: un tag Int16 que guarda una temperatura multiplicada por diez lee 235 en el dispositivo y 23.5 con escala 0.1. |
| Float o Double | El tipo de dato del tag, así que un tag Float redondea a lo que un float puede representar. |

El tipo de dato sigue siendo el que llevan el dispositivo y el nodo público de OPC UA. Activar o apagar Escala o Calibración cambia el tipo del valor de ingeniería a partir de ese momento: lo que el registrador ya registró se queda como se registró, y un canal conserva el tipo que declara, así que un canal Entero registra el valor redondeado al entero más cercano y un canal Número decimal conserva los decimales. La tarjeta Conversión cierra con el valor entregado y avisa cuando un tipo entero que Escala y Calibración dejan como está pierde al redondear los decimales de un límite al que Límites recorta el valor.

## Las etapas {#the-stages}

Para los tipos numéricos la cadena es una sucesión de etapas, cada una con su propia casilla; una etapa desactivada deja pasar su entrada, y la tarjeta muestra el valor en curso al final de cada etapa para que usted siga una lectura en vivo a lo largo de las matemáticas:

| Etapa | Valor inicial | Qué hace |
| --- | --- | --- |
| **Escala** | encendida | `escalado = bruto × Angular + Lineal`. El coeficiente angular arranca en 1 y el lineal en 0. Un coeficiente angular de 0 se rechaza ahí mismo donde se escribe ("Un factor de escala de 0 pondría a cero todas las lecturas. Ingrese el factor por el que multiplicar (1 mantiene el valor)."), porque pondría a cero todas las lecturas y la vista previa y la cadena guardada nunca deben contradecirse. |
| **Calibración** | apagada | Un segundo par lineal aplicado al valor escalado: `calibrado = escalado × Angular + Lineal`. Se mantiene aparte de Escala para que un ajuste de estado inicial y final no perturbe las matemáticas del rango, y está gobernada por su propio permiso; vea [Calibración](connector-calibration). Un coeficiente angular de 0 se rechaza igual. |
| **Lectura no válida** | siempre visible | Dos políticas para las lecturas que no traen ningún número utilizable (más abajo). No es una casilla: su "apagado" es una de las respuestas. |
| **Límites** | apagada | Juzga el valor contra **Mín** (0 al inicio) y **Máx** (100 al inicio) y aplica la acción de fuera de rango elegida (más abajo). Las cotas se normalizan, así que un Mín por encima del Máx nunca falla: la menor de las dos es el piso. |
| **Decimales** | encendida | Redondea a **Decimales** posiciones, 2 al inicio, aceptadas de 0 a 15. |

Las dos etapas lineales llevan un asistente de **Dos puntos** que calcula el par a partir de dos puntos de referencia; se describe paso a paso en [Calibración](connector-calibration#the-two-point-assistant).

## El dispositivo respondió sin un número {#the-device-answered-without-a-number}

Un termopar abierto, un canal sin sensor: la lectura llegó, el equipo está hablando, pero la medición es NaN. Solo tags numéricos, y la calidad se mantiene buena en cualquiera de los dos casos:

| Política | Efecto |
| --- | --- |
| **Dejarlo pasar** (al inicio) | El NaN viaja intacto y se salta la etapa Límites por completo, sea cual sea la acción que lleve esa etapa: los límites juzgan números, y aquí no hay ninguno. El infinito no es NaN y sigue saturando contra el rango. |
| **Reemplazar por un valor** | El número declarado hace de sustituto de esta etapa en adelante y entra en Límites, en Decimales y en el forzado final como cualquier lectura. |

## El dispositivo no respondió {#the-device-did-not-answer}

Un tiempo de espera agotado, un cable cortado, un equipo apagado, una excepción del driver. Todos los
tipos, aunque a un tag que lee texto, una marca de tiempo, un identificador o un bloque de bytes solo
se le ofrecen las dos primeras políticas: un sustituto declarado es un número, y una lectura de esos
tipos no es uno.

| Política | Efecto |
| --- | --- |
| **Mostrar el error** (al inicio) | El tag se lee vacío y su calidad se vuelve mala, así que la falla sale a la vista en todas partes a la vez. |
| **Mantener el último valor bueno** | La última lectura que aterrizó se queda en pantalla, sin vencimiento, hasta que el equipo vuelva a responder. Las marcas de tiempo siguen apuntando a esa lectura, porque fue cuando se midió el número. Nada se mantiene antes de que aterrice la primera lectura; el tag se lee vacío entonces. |
| **Reemplazar por un valor** | El número declarado se presenta tal como se declaró: no hay ninguna lectura que recorra las etapas, así que no se escala, ni se calibra, ni se redondea, solo se fuerza al tipo del valor de ingeniería. Se ofrece en los tipos numéricos y en el Booleano, cuya lectura puede salir de un número; no en String, DateTime, Guid ni ByteString. |

Un sustituto nunca es silencioso: la tarjeta Valor en vivo imprime por qué ("Último valor bueno, mantenido mientras el dispositivo no responde."), el punto en vivo se pone ámbar, el servidor OPC UA integrado publica el valor con un estado de sustituto en lugar de un Good a secas, y un agente que lee el tag con `tag_read` sabe qué sustituto es (`substitution`). Se queda publicado mientras la política lo pida: un dispositivo que sigue sin responder no hace que un cliente externo alterne entre el sustituto y una lectura fallida, así que lo que lee ese cliente es lo que muestra el panel. La lectura misma recupera el punto en cuanto el dispositivo responde, y lo mismo hace apagar el sustituto. Elegir un sustituto es elegir disponibilidad, así que las alarmas y las expresiones siguen juzgando el punto como si tuviera un valor; lo que eso cuesta se paga a la vista, porque el diario técnico sigue registrando la lectura fallida y el estado de salud sigue reportando el dispositivo sin conexión. Un sustituto responde "qué debería mostrar este punto", nunca "si el equipo está ahí". Un reemplazo declarado fuera de los límites activados se advierte ahí mismo donde se escribe: "Fuera de los límites (de 0 a 100): el valor que reemplaza una lectura fallida."

Una lectura que enmudece cuenta como una lectura fallida. Cuando no llega ninguna lectura nueva durante el intervalo de sondeo del tag más 10 segundos, como cuando un dispositivo acepta la conexión y luego deja de responder, la política de arriba se aplica como si la lectura hubiera fallado, para todo lo que lee el tag: las expresiones de Logic, los paneles de control, lo que se registra y los agentes. Con **Mostrar el error** el tag se lee vacío y su calidad se vuelve mala, mientras el servidor OPC UA integrado conserva en el nodo el último valor del dispositivo con `UncertainLastUsableValue` en lugar de Good, así un cliente externo ve el número que tenía y sabe que nada lo renueva; con un sustituto, el sustituto se presenta y se publica como arriba. Las alarmas mantienen su estado mientras la calidad es mala, como siempre. La tarjeta Valor en vivo dice por qué ("No ha llegado ninguna lectura nueva desde la marca de tiempo de la aplicación. El tag lo cuenta como una lectura fallida."), las marcas de tiempo siguen fechando la última lectura que llegó, y la siguiente lectura que llegue devuelve el tag.

Un tag de Solo escritura no tiene ninguna de estas políticas. La estación nunca lo lee, así que ninguna lectura suya puede fallar: hasta que la estación escribe en él, el tag no tiene valor y lo dice, sin sustituto, sin punto ámbar y sin nada publicado en su lugar por OPC UA, y el panel no dibuja esta fila para él. Una política elegida mientras el tag se leía se queda guardada y se ignora mientras el tag sea de Solo escritura; vuelve a aplicarse en cuanto el acceso sea Solo lectura o Lectura y escritura.

## Los valores fuera de rango {#out-of-range-values}

Las acciones de **Límites** para un valor fuera de Mín y Máx:

| Acción | El valor se vuelve | Calidad |
| --- | --- | --- |
| **Nulo** | Un hueco (sin valor). | buena |
| **Recorte** (al inicio) | La cota más cercana. | buena |
| **Error y nulo** | Un hueco. | mala (falla de límite) |
| **Error y recorte** | La cota más cercana. | mala (falla de límite) |
| **NaN** | NaN. | buena. Se ofrece solo en los tags Float y Double, cuyo tipo lo puede representar; le permite a un canal de Process clasificar el valor no válido. Una acción NaN dejada en un tag entero por una escritura de agente o por una copia de seguridad restaurada degrada al hueco de Nulo. |

Una falla de límite se pliega dentro de la calidad efectiva del tag, así que el punto en vivo, las expresiones de propiedad y las alarmas ven todos el valor fuera de límites como malo sin ningún cableado extra, y la tarjeta Conversión imprime "El valor 130 está fuera de los límites (de 0 a 100)." Sigue siendo una condición de proceso y no un problema de conexión, y el [estado de salud del dispositivo](connector-health) no cuenta al dispositivo como sin conexión por ella.

## Boolean, String y los demás tipos {#boolean-string-and-other-types}

Los tipos no numéricos tienen sus propias transformaciones en la misma tarjeta Conversión:

- **Booleano**: **Invertir** reporta la negación lógica del valor bruto.
- **String**: **Inicio de la subcadena** (desde 0) y **Longitud (en blanco = hasta el final)** recortan una ventana de la cadena bruta; una longitud en blanco llega hasta el final, y las cotas fuera de rango se recortan en lugar de fallar.
- Todos los demás tipos (DateTime, Guid, ByteString) pasan sin cambios. Su tarjeta Conversión trae solo la etapa Lectura no válida, con la política para el dispositivo que no respondió, y un tag de Solo escritura de esos tipos no muestra tarjeta.

Mostrar el error y mantener el último valor bueno valen para todos los tipos; reemplazar por un valor
se ofrece solo en los tags numéricos y booleanos, así que un tag String, DateTime, Guid o ByteString
no lo lista. Un reemplazo ya guardado en un tag de uno de esos tipos, como podía guardarlo una
versión anterior, se obedece como mostrar el error, y la siguiente vez que se guarda el tag, desde el
panel o por un agente, se guarda mostrar el error en su lugar. La política de NaN vale solo para los
tags numéricos.

## Una escritura deshace la cadena {#writes-reverse-the-pipeline}

El campo de escritura de la tarjeta Valor en vivo toma un valor de ingeniería y deshace en orden las etapas activadas que son invertibles: recorta a Mín y Máx cuando Límites está activada (una escritura siempre se recorta, nunca se descarta, sea cual sea la acción de límite), descalibra (`(valor − Lineal) ÷ Angular`), desescala de la misma manera, y luego fuerza al tipo del tag. Un tag entero cuya Escala o Calibración cambia el valor acepta una fracción: 123.4 en un tag Int16 con escala 0.1 escribe 1234. Sin una etapa así, una fracción escrita en un tag entero se redondea al número entero más cercano, y las mitades van lejos de cero (2.5 escribe 3). El redondeo pierde información y no se deshace. Una entrada booleana vuelve a aplicar Invertir. Una subcadena de String es solo de presentación, así que una escritura de texto envía el valor entero tal cual; DateTime, Guid y ByteString pasan sin cambios. Un valor escrito por un cliente OPC UA externo sobre el nodo público ya es bruto y no cruza nada de esto.
