# Las herramientas, área por área

> Qué hace cada herramienta que puede llamar un agente, agrupadas por el interruptor de capacidad que la anuncia, y las herramientas de ayuda que no necesitan ninguno.

Los nombres de las herramientas son identificadores estables en snake_case. Los errores son estructurados y accionables: una llamada fallida devuelve qué salió mal más una pista que nombra la herramienta o el paso que lo arregla, para que un agente se corrija solo en vez de adivinar. El servidor indica a todos los agentes que lean la ayuda con `help_search` y `help_read` antes de contestar una pregunta sobre cómo funciona la aplicación y, cuando el área Copias de seguridad (gestión) está encendida, que creen una copia de seguridad de la configuración antes de hacer cambios de configuración. Cuál de estas listas ve de verdad un agente es [lo que abre cada área](agent-areas), más las herramientas de ayuda, que no necesitan ninguna área.

## Ayuda {#help}

Las dos herramientas de ayuda leen esta documentación tal como la lleva la instalación: los mismos artículos que abre el [panel de ayuda](app-window#contextual-help), escritos para la versión instalada en la estación. Vienen con el endpoint siempre que el interruptor general está encendido, digan lo que digan los interruptores de las áreas, porque el texto es la documentación pública y no muestra nada de la estación. Las dos siguen funcionando con el runtime detenido.

| Herramienta | Qué hace |
| --- | --- |
| `help_search` | Encuentra artículos por las palabras de una pregunta y devuelve de cada uno el slug, el título, el resumen y las secciones que tocan esas palabras, primero la mejor coincidencia (10 por defecto, hasta 50). No distingue mayúsculas ni acentos. Sin consulta, lista todos los artículos. |
| `help_read` | Lee un artículo entero por su slug como texto plano: el título, el resumen, la lista de secciones y el cuerpo, con cada sección en una línea de encabezado y las tablas a una fila por línea, más los slugs de los artículos a los que enlaza. |

Las dos leen por defecto el idioma de la interfaz de la estación, así que las páginas, los botones y los campos que nombra una respuesta son los que están en pantalla. Cualquiera de ellas acepta un `culture` que nombra otro idioma que lleve la ayuda instalada; un idioma que no lleva se rechaza con la lista de los que sí lleva, y ningún otro idioma contesta en su lugar. Una instalación cuya ayuda falta o no se puede leer contesta cada llamada con el motivo en lugar de artículos.

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

| Herramienta | Qué hace |
| --- | --- |
| `connector_browse` | Lista el árbol que dibuja la página Connector, con el estado de salud en vivo: todo controlador añadido a la estación, también uno sin nada debajo, y un controlador que tiene un dispositivo, una línea serie o un bróker siempre está añadido; Modbus RTU como controlador, línea serie, dispositivo, tag; MQTT como controlador, bróker (con el estado de su sesión), dispositivo, tag; todos los demás controladores como controlador, dispositivo, tag, con la carpeta de cada dispositivo al lado. Generic serial and TCP lista sus líneas serie como Modbus RTU y sus dispositivos de red como cualquier otro controlador, con el transporte de cada dispositivo. SCPI instruments lista del mismo modo sus líneas serie y sus demás dispositivos. Un dispositivo File lleva su carpeta, su nombre de archivo, cómo lee (un archivo o una carpeta de entrada) y su formato. Un dispositivo Database lleva su tipo de base de datos (`databaseKind`). Cada dispositivo lleva `error`, la única frase que muestra su página, en el idioma de la estación: una frase que señala su línea serie o su bróker cuando el error es de ese nivel, si no el error del propio dispositivo (no conecta, la conexión se rechaza, el controlador avisa), si no el resumen de sus tags cuya lectura se rechaza, y el motivo de cada tag es el `readFailure` de `tag_read`. Es `null` cuando el dispositivo no tiene ninguno; la frase que da `tag_read` para un tag cuyo dispositivo no está conectado lleva hasta aquí. Revela los alias de tag (`Driver.Folders….Device.Tag`) que usan `tag_read`, `tag_write` y las expresiones de Logic. Los alias son nulos mientras el Connector está detenido. |
| `tag_read` | Lee los valores en vivo de un tag por su alias: `valueRaw`, el valor del propio dispositivo antes de cualquier etapa, `value`, el valor de ingeniería tras todas las etapas de la cadena de conversión, la de Decimales incluida (un Double que el dispositivo informa como 2,718281828459 lee 2,72 con Decimales en 2), la calidad, las dos marcas de tiempo y `substitution`, que dice si el valor es un sustituto configurado en lugar de lo que informó el dispositivo: `None` (una medida, o ningún valor), `NaNReplaced` (la lectura fue NaN y el número declarado ocupó su lugar), `LastGoodHeld` (la lectura falló y se mantiene la última lectura que aterrizó, con su valor bruto y sus marcas de tiempo) o `ReadFailureReplaced` (la lectura falló y se presenta el número declarado). Un sustituto cuenta como valor, así que la calidad sigue siendo buena salvo que se produzca una falta de límite, pero nunca es una medida. `communicating` dice si el dispositivo sigue respondiendo: falso cuando la última lectura falló o todavía no se ha leído nada. Una lectura que superó el intervalo de sondeo del tag, más un pequeño margen, sin una nueva cuenta como una lectura fallida: el valor, la calidad y `substitution` responden como para una (sin valor y calidad mala por defecto, la lectura mantenida o el número declarado donde el tag lo pide), `communicating` es falso y las marcas de tiempo fechan la última lectura que aterrizó. Un valor fuera de los límites del tag no es una falta de conexión: la calidad pasa a mala mientras `communicating` sigue siendo verdadero. `readFailure` dice por qué una lectura no aterrizó, en la única frase que muestra el panel del tag, en el idioma de la estación: el motivo que dio el dispositivo o el controlador cuando se rechazó la lectura del propio tag, o una frase que señala el dispositivo del tag cuando este no está conectado. Es `null` mientras el tag lee, y cuando una lectura que no aterrizó aún no tiene motivo registrado. |
| `modbus_server_status` | Informa del [servidor Modbus](connector-modbus-server) propio de la estación: si está encendido (`enabled`), su `port`, su `status` (Off, Listening, PortInUse, Failed con las palabras del sistema en `failure`, o RuntimeStopped), los clientes conectados ahora (como mucho `maximumClients` a la vez) y cada fila del mapa de registros: su `registerClass`, el `register` contado desde 0 y el `lastRegister`, su tipo y su disposición, su `access` (ReadOnly o ReadAndWrite), su fuente (un tag o una variable, por dirección e id) y lo que un cliente lee ahí ahora, `value` y `good`, o el `gap` (NoSource, SourceRemoved, NoGoodValue, NotRepresentable) por el que un cliente recibe la excepción 04. Sigue funcionando con el runtime detenido. |
| `station_broker_status` | Informa del [bróker MQTT](connector-mqtt-broker) propio de la estación, aquel en el que publican los dispositivos, nunca uno de los brókeres que lee la estación: si está encendido (`enabled`), su `port`, su `status` (Off, Listening, PortInUse, Failed con las palabras del sistema en `failure`, o RuntimeStopped), su `authentication` (Anonymous o UsernamePassword, con `username` y `hasPassword`, nunca la contraseña), los dispositivos conectados ahora (como máximo `maximumClients` a la vez) y `thisStationEntry`, el bróker Esta estación del controlador MQTT por el que la estación lo lee. Sigue funcionando con el runtime detenido. |
| `mqtt_publish_list` | Lista lo que la estación publica en cada bróker MQTT que lee, la [tarjeta Publicar](driver-mqtt#the-publish-card) de cada uno: el `publishTopicPrefix` del bróker y si publica, y cada fila con su fuente (por dirección, `removed` cuando la fuente se eliminó), su `topic` y su mensaje (`value` o `alarm`), con los dos mensajes descritos en `payloads`. Sigue funcionando con el runtime detenido. Una fila cuyo `access` es `ReadAndWrite` acepta valores en su `writeTopic` (su tópico seguido de `/set`), que se escriben en su fuente y quedan en el diario técnico como `MQTT <nombre del bróker>`; `payloads.write` dice qué acepta ese tópico. Cada bróker dice su `publishFormat`; un bróker en Sparkplug B añade `sparkplug` (su grupo, el ID del nodo de borde de la estación y sus dispositivos), cada una de sus filas dice el dispositivo y la métrica con los que se publica, y `payloads.sparkplug` dice cómo sale el Sparkplug B ([Publicación en Sparkplug B](driver-mqtt#publishing-in-sparkplug-b)). |
| `remote_access_devices` | Informa de quién abre los sinópticos de la estación por la red: los navegadores conectados desde otro ordenador o tableta en este momento (dirección, navegador y sistema, página, usuario, desde cuándo, y el dispositivo configurado que es cada uno) y los dispositivos configurados con cómo se abre cada uno (sinóptico inicial, fijación, con quién inicia sesión, los minutos tras los que vuelve, solo lectura, y por qué se abre de otra manera cuando su usuario fijo o su sinóptico inicial cambió). Nunca lleva una clave ni su hash. Sigue funcionando con el runtime detenido. |
| `server_status` | Informa del estado de salud del [servidor OPC UA](connector-opcua-server) integrado: si está encendido (`enabled`), si está en marcha, su tiempo en marcha, la URL del endpoint y las sesiones de cliente conectadas, y el tamaño del espacio de direcciones configurado; `available` dice si el runtime del Connector lee, cosa que hace también mientras el servidor está apagado o detenido, y `serverError` por qué falló el último arranque del servidor. `list` es lo que sirve el servidor, y todo lo que sirve: una fila por tag, variable de Logic, alarma o comando de dispositivo, cada una con su `access` y el `node` con el que se configura un cliente; mientras está vacía, `servesNothing` es verdadero. |

## Connector: configuración {#connector--configure}

| Herramienta | Qué hace |
| --- | --- |
| `driver_capabilities` | Lista todos los controladores que la aplicación puede servir con los campos de conexión que necesita un dispositivo, el modelo de direccionamiento de tags (dirección de texto libre y campos tipados, o solo uno de los dos), el soporte y los parámetros del descubrimiento, los rangos de tiempos y los tipos de valor admitidos, con `defaultPort`, el puerto por el que se llama a un dispositivo que no nombra ninguno. `added` dice si el controlador está añadido a la estación, que es lo que lo dibuja en el árbol del Connector; crear un dispositivo, una línea serie o un bróker con `device_upsert`, `serial_line_upsert` o `mqtt_broker_upsert` añade su controlador. AVEVA PI y HTTP llaman al puerto del transporte que usa el dispositivo, así que dan además `defaultPortByTransport`: el 443 sobre HTTPS, que es su transporte por defecto, y el 80 sin cifrar. Generic serial and TCP añade `genericSerialTcp`: sus transportes, cómo se escriben los bytes, cómo terminan los mensajes, las sumas de verificación, los modos, filtros y extracciones de los tags, cómo se leen y escriben los valores, y dos ejemplos completos. Omron añade `omron`: sus dos protocolos con los campos de dispositivo, las formas de dirección y los tipos de dato de cada uno, los transportes y los rangos FINS, las escrituras y el descubrimiento. SCPI instruments añade `scpi`: sus transportes, si este ordenador tiene VISA (`visa.installed`), los terminadores, las confirmaciones de escritura, los comandos de preparación, cómo se escriben consultas y comandos de escritura y cómo se leen las respuestas, el descubrimiento y dos ejemplos completos. NI-DAQmx añade `niDaqmx`: para cada medida, un canal de ejemplo, la unidad, sus campos y los tipos de dato y accesos que admite. Un controlador cuyos dispositivos necesitan algo que el producto no puede incluir añade `prerequisite` (Fluke NetDAQ: el runtime de Visual C++ 2005; OPC DA: los OPC Core Components, OpcEnum y el proxy y stub de OPC DA; NI-DAQmx: el NI-DAQmx de National Instruments; SCPI: un VISA de 64 bits, NI-VISA o Keysight IO Libraries Suite, solo para sus dispositivos VISA, con las dos páginas; Database: un controlador ODBC de 64 bits o un origen de datos para un dispositivo ODBC, juzgado por dispositivo (`perDevice` true), de modo que `installed` queda en null y el error del propio dispositivo dice qué falta): si este ordenador lo tiene (`installed`, para un controlador añadido a la estación), la página oficial de descarga, el archivo, cómo instalarlo, el tropiezo conocido y qué pasa después. SNMP añade `snmp`: sus versiones y las credenciales que admite cada una, los niveles de seguridad y los protocolos SNMPv3, los tipos por clase de valor, cada objeto estándar que el controlador conoce por su nombre con su OID, cómo se comportan lecturas y escrituras, el descubrimiento y dos ejemplos completos. File añade `file`: el camino sencillo, la carpeta y el confinamiento a ella, las formas del nombre del archivo, un archivo o una carpeta de entrada, los formatos con su gramática de dirección, lo que lee un tag y sus tipos, los ajustes de texto, cómo se comportan lecturas y escrituras, el descubrimiento y tres ejemplos completos. Database añade `database`: cada base de datos con sus campos y su puerto propio, el cifrado, las dos maneras en que lee un tag y las dos en que escribe, la regla de que un valor solo entra en una instrucción como `@value` o `@now`, los tiempos de espera, el consejo sobre el usuario de la base de datos, el descubrimiento y cuatro ejemplos completos. El mapa que lee un agente antes de `device_upsert` o de `tag_upsert`. |
| `serial_line_list` | Lista todas las líneas serie guardadas, incluidas las deshabilitadas y las vacías, con su id estable y su controlador; una línea Modbus RTU además con su modo y los valores de tiempo configurados, automáticos y efectivos. |
| `serial_line_upsert` | Crea una línea serie o actualiza una por su id estable. `driver` nombra el controlador al que pertenece, `ModbusRtu` (el valor por defecto), `GenericSerialTcp`, `Scpi` u `Omron`, fijo al crearla; una línea del controlador genérico, del controlador SCPI o del controlador Omron rechaza `mode`, `responseTimeoutMs` y `minimumTransactionIntervalMs`. El nombre y el estado de habilitación cambian en cualquier momento; el intervalo mínimo entre transacciones también cambia con la línea habilitada; el puerto serie, la velocidad en baudios, el formato serie, el modo de transmisión y el tiempo de espera de respuesta solo cambian mientras la línea guardada está deshabilitada. |
| `serial_line_delete` | Elimina una línea por su id estable. Una línea que todavía contiene dispositivos se rechaza salvo que la llamada autorice de forma explícita eliminar todos los dispositivos y todos los tags hijos. |
| `mqtt_broker_list` | Lista todos los brókeres MQTT guardados, incluidos los deshabilitados y los vacíos, con su id estable, dónde responde, su transporte, su nombre de usuario, su ID de cliente, su keep-alive, su prefijo de tópico y su número de dispositivos. Dice si hay una contraseña guardada y nunca la devuelve. También muestra el formato de la publicación (`publishFormat`) y el grupo Sparkplug B (`sparkplugGroupId`). |
| `mqtt_broker_upsert` | Crea un bróker MQTT o actualiza uno por su id estable: nombre, estado de habilitación, host (una dirección `mqtt://` o `mqtts://` entera se descompone), puerto, TLS, nombre de usuario, contraseña, ID de cliente, keep-alive y el prefijo bajo el que su tarjeta Publicar propone tópicos (`publishTopicPrefix`, una cadena vacía vuelve al valor por defecto). Solo cambian los parámetros indicados; un bróker solo se habilita con host, y se rechaza un ID de cliente que use otro bróker. Un cambio guardado de la conexión reconecta la sesión que comparten todos los dispositivos del bróker. `publishFormat` (`Json` o `SparkplugB`) elige cómo sale la tarjeta Publicar, y `sparkplugGroupId` el grupo Sparkplug B del nodo de borde de la estación (una cadena vacía vuelve a `GanterLab`; un grupo con `/`, `+` o `#` se rechaza). |
| `mqtt_broker_delete` | Elimina un bróker por su id estable. Un bróker que todavía contiene dispositivos se rechaza salvo que la llamada autorice de forma explícita eliminar todos los dispositivos y todos los tags hijos. |
| `mqtt_publish_upsert` | Crea una fila de la [tarjeta Publicar](driver-mqtt#the-publish-card) de un bróker (`brokerId` y `source`: un tag, `Connector.` y su alias, una variable, `Variables.` y su ruta, o una alarma, `Alarms.` y su ruta) o edita una por `id`. `topic` es opcional: si se omite, la fila recibe el propuesto a partir del nombre de la fuente bajo el prefijo del bróker, y una cadena vacía lo vuelve a tomar. Un bróker publica una fuente una vez y un tópico una vez; un tópico no lleva + ni # y no empieza por $. Una fila nunca cambia de bróker. `access` es `ReadOnly`, el valor por defecto, o `ReadAndWrite`, que solo acepta un tag con acceso de escritura en un controlador que escribe, o una variable de memoria: la estación escribe entonces lo que se publica en el tópico de la fila seguido de `/set` ([Escritura de vuelta](driver-mqtt#writing-back)). El tópico de una fila no puede ser el tópico de otra seguido de `/set`. En un bróker en Sparkplug B la fila se publica como una métrica (`row.sparkplug`), y `ReadAndWrite` acepta los valores que le envían los comandos Sparkplug B. |
| `mqtt_publish_delete` | Elimina una fila de una tarjeta Publicar por `id`. La estación deja de publicarla; el tag, la variable o la alarma no se toca. |
| `device_upsert` | Crea o actualiza un dispositivo por controlador más nombre (el controlador es inmutable tras la creación). Solo cambian los parámetros que se le dan; los campos de conexión son propios de cada controlador; mover un dispositivo a una carpeta reescribe todas las referencias a sus direcciones de tag antiguas. Un dispositivo de Generic serial and TCP admite `transport` y los campos de sus tarjetas Mensajes y Suma de verificación, y `serialLineId` solo de una línea de su propio controlador; un dispositivo de línea rechaza host, puerto y carpeta. Un dispositivo Omron admite `omronProtocol` (`Fins` o `NjNx`) y, por FINS, los campos `fins*` de su tarjeta FINS; un dispositivo leído por nombre de tag rechaza un puerto. Un dispositivo SCPI admite `transport` (`Tcp`, `Visa`, o `SerialLine` con el `serialLineId` de una línea de su propio controlador), `visaResource`, `terminator`, `responseTimeoutMs`, `writeCheck` y `setupCommands`. Un dispositivo NI-DAQmx admite `daqmxDevice`, el nombre que NI MAX le da. Un dispositivo SNMP admite `snmpVersion`, `snmpCommunity` (SNMPv1, SNMPv2c), `username`, `password`, `snmpSecurityLevel`, `snmpAuthProtocol`, `snmpPrivacyProtocol` y `snmpPrivacyPassword` (SNMPv3), `responseTimeoutMs` y `snmpRetries`; devuelve si cada secreto está puesto, nunca el secreto. Un dispositivo File admite `fileFolder`, `fileName`, `fileMode` (`SingleFile` o `Inbox`), `fileFormat`, `fileEncoding`, `fileSeparator`, `fileDecimal`, `fileHeaderRow` y `fileWrites`, con `fileHeaderText` y `fileLineEnd` cuando la escritura está activada; devuelve `file.fileStatus`, el archivo que lee el controlador en marcha y lo que leyó de él. Un dispositivo Database admite `databaseKind`, y para un servidor `host`, `port` y `databaseName` (en SQL Server también `databaseInstance`, `databaseWindowsSignIn` y `databaseEncryption`), `databaseFile` para SQLite u `databaseOdbc` para ODBC, con `username` y `password`; devuelve `database`, la dirección y si el dispositivo aún espera su usuario, nunca la contraseña. Un puerto fuera del intervalo de 0 a 65535 se rechaza; el 0 es el puerto que usa el controlador. El cambio se concilia de inmediato en el servidor en marcha. |
| `device_delete` | Elimina un dispositivo y todos sus tags; se concilia de inmediato en el servidor en marcha. |
| `tag_upsert` | Crea o actualiza un tag de un dispositivo. El direccionamiento es propio de cada controlador (dirección de texto libre y campos tipados, o solo uno de los dos; en Generic serial and TCP, el modo de lectura, la petición, el filtro, la extracción y los campos de escritura; en SCPI instruments, la consulta como `address`, `valueField` y `writeTemplate`; en NI-DAQmx, el canal físico como `address` y los campos `daqmx*` de su medida; en SNMP, el OID como `address`, en números o por su nombre estándar; en File, la columna o la ruta como `address`, `fileSource`, `fileRow` y sus campos, `fileWriteMode` y `fileLineTemplate`, un valor de texto libre con los campos `value*` del controlador genérico, y un tag nuevo que nace de solo lectura; para Database la columna del valor como `address`, `databaseSource`, `databaseTable`, `databaseRow` y sus campos o `databaseQuery`, y cuando el tag escribe `databaseWriteMode` y `databaseCommand`, con un tag nuevo que también nace de solo lectura); la respuesta repite la dirección de bus ya compuesta y el alias para `tag_read`. Incluye las etapas de lectura no válida: la acción ante NaN en los tags numéricos, y la presentación de un fallo de lectura en todos los tags que lee la estación, donde solo `Replace` se limita a los tags numéricos y booleanos. Un `Replace` ya guardado que el nuevo tipo del tag no admite se guarda como el valor por defecto: la acción ante NaN pasa a `PassThrough` cuando el tipo deja de ser numérico, y la presentación de un fallo de lectura pasa a `ShowError` cuando el tipo es String, DateTime, Guid o ByteString. |
| `tag_delete` | Elimina un tag; se concilia de inmediato. |
| `server_start` | Enciende el servidor OPC UA integrado y lo arranca, como hace Habilitar en su fila: sirve su lista, y sigue encendido a través de los reinicios hasta `server_stop`. No hace nada cuando ya está en marcha; cuando el propio Connector no está en marcha, se arranca primero, materializando la configuración actual. |
| `server_stop` | Apaga el servidor y lo detiene con orden, como hace Deshabilitar: los clientes OPC UA se desconectan y no se publica nada hasta que `server_start` vuelva a encenderlo. El Connector sigue leyendo, y las lecturas de tag, Logic y las grabaciones siguen. |
| `server_restart` | Detener y luego arrancar solo el servidor, mientras está encendido; el Connector lee todo el tiempo. Un servidor apagado se rechaza, ya que es `server_start` lo que lo enciende. Los cambios de dispositivos y tags se aplican con `connector_refresh`. |
| `server_list_upsert` | Crea una fila de la [lista](connector-opcua-served-nodes) del servidor OPC UA, o actualiza una por su `id`. `source` nombra un tag (`Connector.` y su alias), una variable (`Variables.` y su ruta), una alarma (`Alarms.` y su ruta) o un comando de dispositivo (la dirección del dispositivo, un punto, el nombre del comando y `()`); una fuente figura una sola vez en la lista. `access` es ReadOnly, el valor por defecto de toda fila nueva, o ReadAndWrite, que solo admiten un tag con acceso de escritura o una variable de memoria; la escritura de un cliente pasa entonces por el embudo de escritura de Logic y queda en el diario técnico con la sesión del cliente. La respuesta trae la fila con su `node`. |
| `server_list_delete` | Elimina una fila de la lista por su `id`. Un cliente deja de encontrar su nodo; la fuente que servía no se toca. |
| `modbus_server_configure` | Enciende o apaga el servidor Modbus (`enabled`) o lo mueve a otro `port`, de 1 a 65535, como hace su página. Se rechazan el puerto del servidor web, del acceso de agente o del servidor OPC UA, y un puerto que retiene otro programa; el Firewall de Windows nunca se toca. Encendido, deja que cualquier equipo que llegue al puerto lea lo que sirve el mapa. Responde con el servidor entero, como `modbus_server_status`. |
| `station_broker_configure` | Enciende o apaga el bróker MQTT propio de la estación (`enabled`), lo mueve a otro `port` y cambia su `authentication`, su `username` y su `password`, como hace su página, en este orden: puerto, autenticación, y luego encendido o apagado. Se rechazan el puerto del servidor web, del acceso de agente, del servidor OPC UA o del servidor Modbus, y un puerto que ocupa otro programa; el Firewall de Windows nunca se cambia. Encendido, agrega el bróker Esta estación al controlador MQTT. Responde con el bróker entero, como `station_broker_status`. |
| `modbus_map_upsert` | Crea una fila del mapa de registros del servidor Modbus, o actualiza una por su `id`. `source` nombra un tag por su dirección (`Connector.` y su alias, como lo lista `connector_browse`) una variable (`Variables.` y su ruta) o una alarma (`Alarms.` y su ruta, siempre ReadOnly, que sirve el estado que indica `alarmValue`: Active, Acked o State); `registerClass` (HoldingRegister por defecto), `register` (desde 0), `type` (Float por defecto, Boolean en una bobina o una entrada discreta), `length` para un String, `mostSignificantByte` y `mostSignificantWord` toman los campos y las reglas de un tag Modbus. `access` es ReadOnly, el valor por defecto de toda fila nueva, o ReadAndWrite, que solo admiten un registro de retención o una bobina, con una fuente que acepte escrituras (un tag con acceso de escritura, una variable de memoria). Una fila nueva necesita su `register` y su `source`; una fila que el mapa rechaza recibe como respuesta el motivo y una pista. |
| `modbus_map_delete` | Elimina una fila del mapa de registros por su `id`. Un cliente que lee sus registros recibe la excepción 02 desde entonces; el tag o la variable que servía no se toca. |
| `remote_access_device_update` | Cambia el nombre de un dispositivo configurado, su sinóptico inicial (un panel de control por id o por nombre, o vacío para quitarlo, lo que también lo libera), la fijación, los minutos sin uso (0 para nunca) y el modo de solo lectura, como hace su fila en la página Acceso remoto. Con quién inicia sesión el dispositivo no se cambia aquí: eso requiere una persona con Gestionar los usuarios locales. Un dispositivo se configura y se olvida en la pantalla de la estación, nunca con una herramienta. Responde con el dispositivo tal como lo lista `remote_access_devices`. |

## Connector: operación {#connector--operate}

| Herramienta | Qué hace |
| --- | --- |
| `connector_refresh` | Concilia de forma incremental el servidor en marcha con los dispositivos configurados (añade, quita, recrea) sin un reinicio completo; la forma más ligera de aplicar cambios. |
| `device_discover` | Ejecuta la exploración de descubrimiento de dispositivos de un controlador y devuelve candidatos con sus tags, sin guardar nada. Solo participan los controladores cuyo protocolo admite una exploración de verdad; los candidatos que ya existen se marcan como tales. Una exploración SNMP recorre o bien `target` con `snmpCommunity`, o bien `snmpDevice`, un dispositivo configurado, que es como se explora un agente SNMPv3. Una exploración File lee o bien `fileDevice`, un dispositivo configurado, o bien `fileFolder`, `fileName`, `fileMode` y `fileFormat` escritos para la exploración. Una exploración Database lee `databaseDevice`, un dispositivo configurado, y opcionalmente `databaseTables`, un nombre de tabla o un patrón con `*`. Un `target` que la tarjeta Alcance de la exploración del controlador rechazaría, o ninguno donde la exploración lo necesita, se rechaza diciendo lo que tiene que ser. Una exploración Database, File o SNMP detenida en su límite de valores, tablas u objetos lo dice en `cut`, con lo que hay que pasar para ver el resto; una lista completa no tiene `cut`. |

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

| Herramienta | Qué hace |
| --- | --- |
| `logic_browse` | Recorre el espacio de direcciones enraizado de Logic, el mismo árbol con puntos que lee toda expresión: System, Server, Connector, Variables, Alarms, Process y Assets. Las carpetas del operador son niveles reales de la dirección; los puntos hijos incluyen su valor en vivo y su calidad, y un punto de tag de Connector lleva además `substitution` y `communicating`, tal como los informa `logic_read`. |
| `logic_read` | Lee un punto por su dirección con puntos (por ejemplo `Variables.Setpoint`) y devuelve el valor en vivo y la calidad. Un punto de tag de Connector lleva además `substitution` y `communicating`, tal como los informa `tag_read`, que es lo que distingue un sustituto, o la lectura de un dispositivo que dejó de responder, de una medida en vivo; los demás puntos no llevan ninguno de los dos. Una lectura que enmudeció se lee ahí como una lectura fallida. |

## Logic: configuración {#logic--configure}

Las altas y actualizaciones son parciales (los parámetros omitidos conservan su valor) y todo borrador combinado pasa la misma validación que aplican los editores de [Logic](logic); un borrador no válido se rechaza y no queda nada aplicado a medias.

| Herramienta | Qué hace |
| --- | --- |
| `variable_upsert` | Crea o actualiza una variable: Expresión (una sola expresión JavaScript de solo lectura sobre el espacio de direcciones) o Memoria (un valor escribible y, si se quiere, retentivo). El nombre es la clave y, saneado, la dirección; el parámetro de carpeta la archiva, reescribiendo todas las referencias a la dirección antigua. |
| `variable_delete` | Elimina una variable por su ruta, con su valor retenido incluido. Los canales vinculados a ella pierden su origen. |
| `action_upsert` | Crea o actualiza una acción: un bloque de sentencias JavaScript con exactamente dos verbos de escritura, la asignación a una variable de memoria y la escritura de ingeniería en un tag. Se valida de forma estática, nunca se ejecuta al guardar. |
| `action_delete` | Elimina una acción por su nombre. Los disparadores vinculados a ella quedan inactivos. |
| `trigger_upsert` | Crea o actualiza un disparador por intervalo: cada `intervalMs` (100 como mínimo) la acción vinculada se lanza en la vía de acciones; un tick durante una ejecución pendiente se omite. El vínculo con la acción es flojo y por nombre. |
| `trigger_delete` | Elimina un disparador; la acción vinculada no se toca. |
| `alarm_upsert` | Crea o actualiza una alarma: una expresión de condición booleana, la prioridad (Crítica, Alta, Media o Baja), los retardos a la activación y a la desactivación, si se exige reconocimiento, y el estilo del aviso. Guardar una condición o unos tiempos cambiados reinicia la máquina de estados en marcha. |
| `alarm_delete` | Elimina una alarma por su ruta; un aviso activo se cierra antes. |
| `logic_folder_upsert` | Crea, renombra o rearchiva una carpeta de organización de una sección (Variables, Alarms, Actions, Triggers; tres niveles como mucho). En Variables y en Alarms, la ruta de la carpeta es parte de la dirección, así que los cambios de nombre y los movimientos reescriben todas las expresiones, todos los scripts, todas las condiciones y todos los vínculos de panel de control que hay debajo. |
| `logic_folder_delete` | Elimina una carpeta. Nada de lo que contenía se destruye: los elementos y las subcarpetas se rearchivan un nivel más arriba y las referencias se reescriben; un choque de nombres en el destino rechaza la eliminación. |

## Logic: operación {#logic--operate}

Todas estas viajan por el mismo punto de escritura de la lógica por el que viajan las páginas y se anotan en el diario con el origen **MCP**. Una escritura sale de la lógica hacia la cola de entrega propia del dispositivo, y es la llamada de la herramienta la que espera la respuesta, así que lo que vuelve es en qué quedó el valor y no solo que se envió.

| Herramienta | Qué hace |
| --- | --- |
| `variable_write` | Escribe un valor en una variable de Memoria (convertido a su tipo de salida, y retenido cuando es retentiva). Las variables de expresión se calculan y rechazan las escrituras. |
| `tag_write` | Escribe un valor de ingeniería en un tag con escritura: se deshace por la cadena de conversión del tag, se convierte al tipo del dispositivo y se escribe en el equipo. La respuesta lleva lo que presenta el tag una vez hecha la escritura: el valor, la calidad, `substitution` y `communicating`, tal como los informa `tag_read`, así que un dispositivo que aceptó la escritura pero ha dejado de responder a las lecturas no se confunde con uno que sigue respondiendo. Los tags de solo lectura y los controladores de solo lectura se rechazan con el motivo. |
| `action_run` | Ejecuta una acción en la vía de acciones y devuelve su resultado y su duración. Una acción deshabilitada falla sin llegar a ejecutarse. |
| `alarm_ack` | Reconoce una alarma, la respuesta del operador; no hace nada cuando no hay nada pendiente. |
| `alarm_ack_all` | Reconoce todas las alarmas que esperan una respuesta, como un solo elemento de la cola de la lógica y con cada transición anotada en el diario. |

## Diario técnico: lectura {#logs--read}

| Herramienta | Qué hace |
| --- | --- |
| `logs_read` | Lee el flujo de registro en vivo de todo el programa (el mismo de la Consola de [Eventos](events)), filtrado por gravedad mínima (Debug, Information, Warning o Error; Information por defecto), por área (App, Server, Connector, Logic, Process, Dashboard, Agent o Licensing), por componente y por una subcadena de contexto; devuelve las coincidencias más nuevas (100 por defecto, 500 como mucho). Las acciones de un agente se anotan bajo el área Agent. |
| `event_history_read` | Lee la cronología permanente de eventos operativos, que sobrevive a los reinicios: transiciones de alarma, transiciones de incidencia y transiciones de enclavamiento. Se filtra por clase (Alarm, Occurrence o Interlock), por un periodo UTC inclusivo y por un nivel (prioridad de la alarma, gravedad de la incidencia o transición del enclavamiento); las más nuevas primero, 100 por defecto y 500 como mucho. Estrictamente de solo lectura: nada puede vaciar ni eliminar entradas del diario. |

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

| Herramienta | Qué hace |
| --- | --- |
| `process_models` | Lista los modelos de [Process](process) por completo: canales, grupos compartidos, unidades con su cableado resuelto y su estado en marcha, procedimientos, paneles, recetas, evaluaciones, incidencias, más la biblioteca global de plantillas de informe. El mapa que lee un agente antes de arrancar nada. |
| `process_runs` | Lista los ensayos, del más reciente al más antiguo: id, nombre, estado, veredicto, qué corrió, quién lo arrancó (Station, User, Automation o Agent), tiempos y avance de los ciclos. Se puede restringir a los ensayos activos, buscar por una parte del nombre o de cualquier valor de los metadatos (un número de serie, un lote) y acotar (50 por defecto). |
| `process_run` | Lee el registro congelado completo de un ensayo por su id: instantánea, metadatos, criterios juzgados con sus recuentos de muestras, episodios y eventos de incidencia, escrituras de receta tal como se ejecutaron, comentarios, y los artefactos congelados del informe y de la etiqueta con sus intentos de impresión. Si se le pide, calcula el número de filas del datalog y su rango de tiempo. |
| `process_samples` | Lee las muestras que grabó un ensayo, mientras graba o después de terminar. Un tramo de hasta 500 muestras llega tal como se grabó: un punto por muestra, con un valor por canal. Uno más largo llega resumido: su duración se divide en 500 intervalos iguales y cada intervalo lleva el mínimo, el máximo y la media de cada canal, de modo que un pico se conserva en el máximo. La respuesta dice cuál de los dos casos es y, si está resumida, cuánto dura cada intervalo y cuántas muestras reúne. `fromUtc` y `toUtc` acotan el tramo, y uno lo bastante estrecho vuelve tal como se grabó; `channels` lee solo los canales que nombra. |
| `unit_status` | Informa del estado en vivo de una unidad: si está en marcha (con el ensayo activo) y el valor de ingeniería actual que hay detrás de cada canal, leído sin grabar. |

## Process: configuración {#process--configure}

| Herramienta | Qué hace |
| --- | --- |
| `process_view_configure` | Configura exactamente un panel de un modelo: el icono que se dibuja a su lado y si aparece en la página View. Nada más del agregado de Process se puede escribir por MCP; el resto se edita en la página Process. |

## Process: operación {#process--operate}

Los ensayos que un agente arranca, termina o comenta anotan **Agente** como el actor, nunca el operador que casualmente tenga la sesión iniciada en el banco de pruebas.

| Herramienta | Qué hace |
| --- | --- |
| `process_snapshot` | Captura una fila de datalog en una unidad fuera de un procedimiento. Cada llamada crea un ensayo Instantáneo nuevo y ya completado en [Históricos](histories), sin evaluación (veredicto None). |
| `process_evaluate` | Captura una fila de datalog y la juzga con una evaluación; crea un ensayo Instantáneo completado y devuelve su veredicto. |
| `process_recipe_apply` | Aplica una vez una receta Instantánea a una unidad a través del punto único de escritura de Process y de los bloqueos de origen. Manda sobre el equipo; no crea ningún ensayo (las escrituras se anotan en el diario). Las recetas temporizadas se rechazan. |
| `process_start` | Arranca la ejecución de un procedimiento en una unidad, con un objeto JSON para los campos de metadatos que pide el procedimiento. Todo valor enviado queda registrado, o no arranca nada: un campo que el procedimiento no pide, un valor para un campo secuencial (la aplicación lo compone al arrancar) o un campo nombrado dos veces rechazan el arranque, igual que unos metadatos obligatorios ausentes o no válidos, una unidad que ya está en marcha o un conflicto de bloqueo de canal compartido. Devuelve el id del ensayo nuevo. |
| `process_stop` | Detiene un ensayo en marcha: bloque de finalización, instantánea de histórico congelada, veredicto calculado. |
| `process_hold` | Pausa el perfil temporizado de un ensayo en la última consigna; el datalog sigue grabando. |
| `process_resume` | Reanuda el perfil temporizado de un ensayo en pausa. |
| `process_abort` | Aborta un ensayo desde En marcha o En pausa: la finalización corre, la instantánea se escribe, el estado pasa a Abortado y el veredicto a NOK. |
| `process_comment` | Añade un comentario con marca de tiempo al archivo de un ensayo: una nota en la cronología mientras está activo, y una nota posterior al ensayo después. |
| `process_report` | Genera (o vuelve a generar) el informe PDF de un ensayo terminado y devuelve la ruta de su archivo. Una plantilla con nombre de la biblioteca global sustituye a la configurada en el procedimiento; sin ninguna de las dos, se aplica el diseño por defecto con todas las secciones. Se rechaza mientras el ensayo está activo. |
| `process_run_delete` | Elimina de forma permanente un ensayo grabado: su puntero en el índice del histórico y el archivo de base de datos de ese ensayo. Se rechaza mientras está activo; la configuración no se toca. |

## Paneles de control: configuración {#dashboard--configure}

Los nombres de rol que estas herramientas leen y devuelven están en inglés en cualquier
estación: `Not signed in`, `Viewer`, `Operator`, `Maintainer` y `Developer`, sean cuales
sean las palabras que el operador lee en la pantalla. `Admin` no se puede listar: siempre
ve todos los paneles de control. Un rol que el administrador ha renombrado lleva el nombre
que escribió.

| Herramienta | Qué hace |
| --- | --- |
| `dashboard_list` | Lista los paneles de control (o, si se nombra un modelo, los sinópticos de ese modelo): tamaño de la rejilla, carpeta, icono, bandera de arranque, visibilidad por rol y todos los componentes con su posición, su capa y su JSON de propiedades, más todas las redes de trazos guardadas. Devuelve además el catálogo de clases de componente con el tamaño por defecto y la bolsa de propiedades por defecto de cada clase. |
| `dashboard_upsert` | Crea o actualiza un panel de control por su nombre: tamaño de la rejilla (un encogimiento que dejaría huérfano a un componente se rechaza), carpeta e icono de la columna Visualización de la página View, bandera de arranque, visibilidad de la barra de estado a pantalla completa, y visibilidad por rol. Nombrar un modelo direcciona en su lugar los sinópticos de ese modelo. Las páginas de panel de control abiertas reflejan el cambio en vivo. |
| `dashboard_delete` | Elimina un panel de control y sus componentes por su nombre; nombrar un modelo elimina en su lugar el sinóptico de ese modelo. |
| `component_upsert` | Añade un componente por su clase (colocado en la primera celda libre con el tamaño por defecto de la clase, salvo que se le diga otra cosa) o actualiza uno por su id. La colocación tiene que caer dentro de la rejilla; se admite el solapamiento, y la capa z decide el orden de dibujo; el JSON de propiedades es la bolsa tipada de la clase. Nombrar un modelo direcciona en su lugar los sinópticos de ese modelo, así que un sinóptico creado allí se puede componer aquí. |
| `component_delete` | Quita un componente por su id; nombrar un modelo direcciona en su lugar los sinópticos de ese modelo. |
| `connection_upsert` | Une dos bornes de Símbolo con una red de trazos tipada, resolviendo el tipo, el papel y la orientación desde el catálogo de símbolos exactamente igual que el editor del lienzo. Los extremos que resuelven a tipos distintos fallan salvo que se permita de forma explícita un trazo indefinido; un anclaje que ya lleva un trazo se rechaza. Nombrar un modelo direcciona en su lugar los sinópticos de ese modelo. |
| `connection_delete` | Quita una red de trazos por su id y por la revisión esperada, para que una eliminación caducada se rechace en vez de pisar una edición más nueva; nombrar un modelo direcciona en su lugar los sinópticos de ese modelo. |

## Interfaz: automatización {#ui--automate}

Estas herramientas gobiernan la ventana real de la aplicación; existen para que un agente pueda verificar la interfaz que ve el operador, y no una simulación de ella. Las interacciones se despachan al shell en vivo, así que la conducta prevista es seguir cada gesto con `ui_screenshot` y observar el efecto, y las coincidencias ambiguas vuelven como listas de candidatos en lugar de como un clic adivinado.

| Herramienta | Qué hace |
| --- | --- |
| `ui_state` | Informa del estado del shell: página activa, páginas disponibles, tema, tamaño y visibilidad de la ventana, y la dirección loopback en la que esta instancia sirve su interfaz. La llamada de orientación antes que cualquier otra cosa. |
| `ui_navigate` | Activa una página del shell por su nombre estable, que está en inglés en toda estación: `View`, `Process`, `Logic`, `Connector`, `Users`, `Validation`, `Events`, `Agent`, `Settings`, `Account`. También se acepta el rótulo que la barra de navegación muestra en el idioma de la estación. |
| `ui_screenshot` | Captura la ventana tal como se ve en pantalla en un archivo PNG y devuelve su ruta absoluta; primero restaura la ventana cuando está escondida en el área de notificación. Puede capturar una región de pantalla con nombre (un área `data-doc-region` única y visible) en lugar de la ventana entera, y una región ausente, escondida o ambigua falla listando las regiones visibles, en vez de recaer en silencio en una captura completa. |
| `ui_scroll` | Desplaza la región de desplazamiento principal de la página activa al principio, al final o por páginas de la vista, devolviendo los desplazamientos para poder barrer una página larga. |
| `ui_set_theme` | Aplica el tema de la estación (Sistema, Claro u Oscuro): el tema con el que dibuja la ventana de la estación y que sigue todo navegador que no ha elegido el suyo; un navegador que eligió el suyo se queda con él. Se guarda exactamente igual que una elección hecha con las teclas de tema en la ventana de la estación, así que un agente bien educado restaura el valor original al terminar. |
| `ui_resize` | Cambia el tamaño de la ventana restaurada en unidades independientes del dispositivo, recortado al mínimo de la ventana; útil para auditar disposiciones compactas. |
| `ui_click` | Pulsa el botón, el hipervínculo, la casilla o el conmutador visible cuyo texto coincide; las casillas y los conmutadores se encuentran por la etiqueta de su campo y el resultado informa del estado en el que quedaron. La ambigüedad devuelve los candidatos en vez de elegir uno. |
| `ui_set_text` | Escribe un valor en un cuadro de texto identificado por la etiqueta de su campo, confirmando el vínculo igual que haría escribir a mano. |
| `ui_select` | Selecciona un elemento por su texto visible: una ruta separada por barras recorre un árbol, desplegándolo por el camino; un solo segmento coincide también con elementos de lista, de pestaña y de cuadro combinado y con filas de rejilla de la página actual. |

## Copias de seguridad: gestión {#backups--manage}

| Herramienta | Qué hace |
| --- | --- |
| `backup_create` | Crea una instantánea en caliente de la base de datos de configuración en la carpeta de copias de seguridad, con una nota opcional. Los ensayos grabados viven fuera de la configuración y ni la copia ni la restauración los tocan nunca. |
| `backup_list` | Lista las copias de seguridad de la configuración (nombre del archivo, fecha de creación, tamaño, nota) más cualquier restauración ya programada. |

A propósito **no hay ninguna herramienta que elimine copias de seguridad**: la retención es solo del operador, en la página [Copias de seguridad](settings-backups).

## Copias de seguridad: restauración {#backups--restore}

| Herramienta | Qué hace |
| --- | --- |
| `backup_restore` | Programa una copia de seguridad para que sustituya la configuración actual en el **siguiente** arranque de la aplicación. En la aplicación en marcha no cambia nada y la herramienta nunca la reinicia; de la configuración que se va a sustituir se hace antes una instantánea automática, y el operador puede cancelar la restauración pendiente desde Ajustes hasta el reinicio. Se rechaza mientras hay una grabación activa. |

## Ajustes: gestión {#settings--manage}

| Herramienta | Qué hace |
| --- | --- |
| `settings_read` | Lee las preferencias de presentación y de ciclo de vida de la estación: formatos de fecha, hora y número, decimales, tema, y las banderas de cerrar al área de notificación y de informes de fallo. |
| `localization_set` | Actualiza las preferencias de presentación (parcial: los parámetros omitidos se quedan). Solo presentación: el almacenamiento, la entrada y salida de los controladores y las grabaciones usan siempre el formato invariable. |
| `asset_list` | Lista los recursos de usuario (imágenes, iconos, colores) con sus ids, sus valores y sus rutas. |
| `asset_import` | Importa un PNG o un JPG desde una ruta de archivo local a la biblioteca de recursos que gobierna la aplicación y devuelve el id del recurso nuevo. Los bytes se copian, así que el archivo de origen se puede mover después. |
| `symbol_validate` | Valida contenido de símbolo en línea (SVG en bruto o un paquete v2) sin guardar nada: un ensayo en seco de la importación exacta, que devuelve errores, advertencias del saneador y un resumen de lo que se reconoció. La descripción de la herramienta lleva el [contrato completo de símbolo portátil](ganter-symbols). |
| `symbol_import` | Importa contenido de símbolo en línea como un recurso de símbolo de usuario nuevo y devuelve su id y su referencia `user:<guid>`. Siempre crea un recurso nuevo; un nombre que choca recibe un sufijo automático. |

## Avisos: redacción {#reports--draft}

| Herramienta | Qué hace |
| --- | --- |
| `report_draft` | Abre el [formulario de avisos](account-feedback#a-report-drafted-by-an-agent) en la ventana de la estación, ya rellenado con lo que escribió el agente: `kind` (`DriverRequest`, `Bug` o `Suggestion`), `summary` (una línea de 120 caracteres como mucho; una más larga se rechaza, no se recorta) y `details` (opcional). Como el botón Informar de la barra de título, primero captura la ventana y ofrece la captura con el aviso, marcada. Responde al momento que el formulario está abierto y que no se envió nada. |

La herramienta nunca envía. La persona en la estación lee el aviso, lo corrige si quiere y pulsa Enviar; el desenlace aparece en la barra de estado de la estación y no vuelve al agente. Mientras esta área está encendida, el servidor pide a cada agente que ofrezca un aviso cuando la persona necesita un controlador que Ganter Lab no tiene, cuando una llamada falla de una manera que parece un defecto del programa o cuando la persona pide una mejora, y las descripciones de `driver_capabilities`, `device_upsert` y `device_discover` dicen lo mismo.

Se niega con un `reason`, y entonces no abre ni captura nada:

| `reason` | Cuándo |
| --- | --- |
| `not_permitted` | El rol con la sesión iniciada en la estación no tiene Enviar avisos a Ganter. |
| `no_station_window` | La estación no tiene ventana propia en la que abrir el formulario: un host que sirve sus páginas solo a navegadores. |
| `no_credential` | La sesión no puede enviar: el perfil de demostración, con la sesión iniciada o no, o una sesión de la cuenta Ganter de la estación que no guarda ninguna credencial. |
| `form_busy` | El formulario de avisos está abierto en la estación, o se está capturando o enviando un aviso. |
| `draft_in_progress` | El formulario tiene un aviso que una persona está escribiendo. En cambio, un borrador anterior del agente que nadie cambió se sustituye. |

Una estación sin sesión iniciada en ninguna cuenta Ganter no se rechaza: el formulario se abre y dice
que el aviso sale sin cuenta, así que Ganter no puede responderle.

Como toda herramienta que cambia algo, responde `Runtime stopped` mientras el runtime está detenido.
