Expresiones

El único lenguaje de expresiones detrás de las variables y de las condiciones de alarma, qué puede referenciar, la superficie de lectura de cada clase de punto, las reglas que impone el evaluador, los mensajes que da la validación, y cómo funcionan el editor de scripts y su selector Examinar…

Ver como Markdown

Un solo lenguaje de expresiones sirve a dos lugares de la página Logic: lo que calcula una variable de expresión y la condición que vigila una alarma. Las dos son una sola expresión JavaScript evaluada en modo estricto dentro de un aislamiento sin acceso a la máquina, y las dos se editan en el mismo editor de scripts. Los scripts de acción usan el mismo vocabulario, pero son bloques de sentencias; sus diferencias están en Acciones.

Qué es una expresión

Una expresión es exactamente una expresión JavaScript: literales, aritmética, comparaciones, operadores lógicos, el condicional a ? b : c, operaciones de texto, cadenas de plantilla y llamadas a los objetos integrados de JavaScript Math, Date y JSON. Las sentencias (let, if, los bucles) pertenecen a las acciones: una segunda sentencia se rechaza con "Una variable contiene una sola expresión. Las sentencias pertenecen a las acciones." Las asignaciones y los ++/-- en cualquier parte de una expresión se rechazan con "Las expresiones son de solo lectura. Las escrituras pertenecen a las acciones."

La expresión referencia los puntos por su dirección con raíz. Lo que le entrega cada raíz a la expresión:

Raíz Qué cruza hacia la expresión
Los tags de Connector, Variables, Alarms, los Channels de una unidad de Process Un objeto en vivo con la superficie de lectura tipada de abajo. Una referencia pelona (Connector.Simulated.Pump.Flow sola) se evalúa al valor del punto; una alarma pelona a su IsActive.
System, Server, Assets, y el estado de la corrida, la productividad, los comandos y la preparación de una unidad de Process El valor actual mismo: un número, un texto, un booleano o un instante. Úselo directamente; no hay ningún miembro que agregar.

System.Now es el instante de la evaluación: todas las referencias a él dentro de una misma evaluación leen la misma hora. Cruza como un Date de JavaScript, igual que toda marca de tiempo, así que los instantes se comparan y se restan con naturalidad: (System.Now - Connector.Simulated.Pump.Run.SourceTimeStamp()) / 1000 son segundos.

Una variable de expresión puede referenciar tags, variables de memoria, alarmas, puntos de Process, puntos de Assets y los diagnósticos de System y de Server, pero nunca a otra variable de expresión: el editor lo rechaza ("'Variables.X' es una variable de expresión. Las expresiones no pueden hacer referencia a otras variables de expresión; referencie variables de memoria o los puntos de base en su lugar.") para que los resultados nunca dependan del orden de evaluación. Una condición de alarma puede referenciar todo menos Alarms.* ("Las condiciones de alarma no pueden hacer referencia a otras alarmas.") y tiene que producir un booleano.

La superficie de lectura de un punto

Un tag en vivo ofrece:

Miembro Devuelve Significado
.Value valor tipado El valor de ingeniería, después de toda la cadena de conversión del tag
.ValueRaw valor tipado El valor bruto normalizado al tipo declarado del tag, antes del escalado
.ValueObject cualquier cosa El valor exactamente como lo produjo el driver
.ValueScaled, .ValueCalibrated, .ValueLimited, .ValueRounded número El valor después de las etapas Escala, Calibración, Límites y Decimales
.ValueToBool(), .ValueToInteger(), .ValueToReal(), .ValueToString(), .ValueToDateTime() valor convertido El valor de ingeniería convertido a esa categoría; sin valor sigue siendo sin valor
.State() booleano La calidad: verdadero mientras la lectura es buena
.SourceTimeStamp() Date Cuándo produjo el dispositivo la lectura
.ApplicationTimeStamp() Date Cuándo la recibió el servidor integrado
.Name, .EngineeringUnit texto El nombre y la unidad del tag

Una variable ofrece .Value, las cinco conversiones .ValueTo*(), .State(), .ApplicationTimeStamp(), .Name y .EngineeringUnit. Una alarma ofrece .IsActive, .IsAcked, .CurrentState, .State() (si su condición se pudo evaluar en el último ciclo), .ActiveSince(), .LastTransitionAt() y .Name. Un canal de Process ofrece la superficie del tag cuando está vinculado a un tag y la superficie de la variable cuando está vinculado a una variable; un canal sin vínculo no ofrece nada. Nada más de un objeto en vivo es alcanzable: un miembro fuera de esta superficie se lee como indefinido, y llamarlo falla en la validación. El selector Examinar… lista esos mismos miembros bajo cada punto, así que ninguno hay que escribirlo de memoria.

Las reglas que impone el evaluador

Tanto en el editor conforme usted escribe como otra vez en cada ciclo de 100 ms:

  • La compuerta de calidad. Antes de evaluar, todos los puntos referenciados se resuelven y se refrescan. Cualquier punto que falte, que sea malo o que no contenga ningún valor vuelve el resultado un hueco de mala calidad sin correr la expresión, así que un tag sin conexión nunca puede fabricar una muestra y null nunca llega al motor para convertirse en 0.
  • Los resultados no finitos son huecos. NaN o infinito (una división entre cero, una aritmética indefinida) nunca se vuelve una muestra.
  • Protección contra desbocamiento. Una evaluación se aborta pasados 250 ms, 5,000 sentencias o 4 MB de memoria de script, y cuenta como un hueco de mala calidad. Se conserva un motor por texto de expresión, así que nada se filtra de otra expresión.
  • El forzado. Un resultado exitoso se fuerza al tipo de salida de la variable; una condición de alarma se fuerza a booleano, y un resultado que no se puede convertir mantiene el estado de la alarma.
  • Los errores son huecos, no excepciones. Un error de ejecución en el momento del ciclo da un hueco y una entrada en el diario técnico (la primera falla, resúmenes mientras se repite, y una línea cuando se recupera); el ciclo sigue con la variable siguiente.

Lo que rechaza la validación

El editor valida el borrador cada medio segundo y muestra el primer problema debajo del valor o de la condición:

Mensaje Causa
Se necesita una expresión. / Se necesita una condición. El editor está vacío.
Error de expresión: … El texto no se puede interpretar.
Una variable contiene una sola expresión. Las sentencias pertenecen a las acciones. Más de una sentencia, o una sentencia que no es una expresión.
Las expresiones son de solo lectura. Las escrituras pertenecen a las acciones. Una asignación o un ++/--.
Las direcciones deben ser estáticas: se accede a 'Root' con un segmento calculado. Variables[nombre] o cualquier segmento que no sea literal.
Dirección incompleta 'Connector.Simulated'. Una cadena demasiado corta para nombrar un punto bajo su raíz.
No se encontró 'X'. La dirección no resuelve a nada.
'X' es una variable de expresión. … Una referencia a otra variable de expresión.
Las condiciones de alarma no pueden hacer referencia a otras alarmas. Una referencia a Alarms.* dentro de una condición.
La condición debe evaluarse como Bool, pero produjo 'x'. La evaluación de prueba de una condición produjo un valor presente que no se convierte a booleano.
Error de expresión: aquí no se puede usar un punto en vivo directamente. Léalo por su miembro .Value (por ejemplo, Connector.Driver.Device.Tag.Value). Un objeto en vivo usado donde hace falta un primitivo (Tag + 1).
Error de expresión: <mensaje del motor> La evaluación de prueba lanzó un error: un identificador desconocido, un miembro bloqueado llamado como función.

La evaluación de prueba corre con los valores actuales sin importar la calidad, así que un mensaje refleja la expresión y no una entrada mala; una entrada mala se muestra en la tarjeta PUNTOS REFERENCIADOS.

El editor de scripts

Todas las expresiones, las condiciones y los scripts de la página se editan en la misma tarjeta: un título pequeño (EXPRESIÓN, CONDICIÓN o SCRIPT), un botón Examinar…, el editor, una pista y el mensaje de validación. El editor es CodeMirror con resaltado de JavaScript, un historial para deshacer, y autocompletado de los tokens de dirección: los nombres de raíz para un token pelón, y luego los hijos de la ruta escrita hasta ahí, con los miembros incluidos en cuanto el token nombra un punto (capturar una dirección). El texto se manda al borrador con amortiguación y se guarda solo. Las cajas de expresión y de condición miden 56 px de alto como mínimo, y la caja del script de una acción 160 px. Cuando el motor del editor no puede arrancar, la caja degrada a un área de texto simple que sigue leyendo y escribiendo, sin resaltado, sin completado y sin historial; Examinar… agrega entonces la dirección elegida al final en lugar de en el cursor.

Examinar… abre un diálogo ("Examinar: insertar en EXPRESIÓN") con el árbol a nivel de miembro de todo el espacio de direcciones; seleccione una fila y presione Insertar, o haga doble clic en ella, para poner su dirección en el cursor. Cada editor es dueño de su propio diálogo, así que dos editores de una misma página nunca comparten una selección.

Lo que las expresiones no hacen

No escriben nada, no llaman a los comandos de corrida de Process, no guardan estado entre evaluaciones, no pueden definir funciones compartidas entre expresiones, y no se evalúan a solicitud: el ciclo las publica cada 100 ms y el editor muestra de antemano el borrador dos veces por segundo.