Jerarquía de variables

Proyecto UWS (5)

Esta entrada es continuación de Proyecto UWS (4).
Hora de cambiarlo todo. Era necesario para que UWS avanzase en las líneas que expuse hace poco. Las principales novedades son:

  • Se vuelca todo el peso en la clase Tag, y se eliminan mapeos de memoria de controladores. Por supuesto, debe seguir habiendo referencias a direcciones, pero a partir de ahora las memorias se gestionan como un diccionario de variables. ¿Cómo se determinan las tramas de un PLC Modbus, por buscar una pega? Sencillo, las memorias pueden ser de dos tipos: ordenadas y no ordenadas. En las primeras, el índice es numérico, y las tramas de lectura se pueden resolver con facilidad a partir de sus valores. Pero el objeto PLC no copia toda la memoria del controlador, sólo contiene las variables que se necesitan.
    Una de las consecuencias de esta decisión es que se eliminan los direccionamientos absolutos. Desde el interfaz ya no se puede acceder a áreas aleatorias de la memoria, lo cual podía ser un foco de inseguridades. A partir de ahora, las referencias sólo podrán hacerse a las variables dadas de alta en el motor.
  • Se eliminan los escaneos para actualizar valores. En vez de ello, cada variable mantiene una lista de suscriptores que son avisados ante sus cambios de valor. Un suscriptor es cualquier objeto derivado de la clase Subscriptor, y debe poseer un método update. Esto mejora la eficiencia y hace que las actualizaciones sean todo lo ágiles que se puede. Cada cambio de valor se notifica inmediatamente a todos los elementos que de ella dependen: alarmas, históricos, interfaz, cálculos… Por otro lado, muchos protocolos de comunicación con controladores funcionan de este modo, así que era una transición inevitable.
  • La interfaz es un suscriptor más de una lista de variables. Esto demanda poderosamente introducir los websockets de HTML5. La interfaz ahora usa dos puertos: uno para solicitar ficheros y otro nuevo para establecer una conexión bidireccional para el envío y recepción de información. Como antes, se gana en eficicencia, velocidad y se reduce el ancho de banda consumido por las comunicaciones.

Aunque hay algún cambio más, me voy a centrar en describir estos puntos. Respecto al primero, mi intención es que todo lo que contenga un valor derive de la clase Tag. Se me ocurre en un primer momento esta jerarquía de clases:

Jerarquía de variables
Jerarquía de variables

En bordes punteados se marcan las clases que todavía no están definidas. La intención es que existan al menos estos tipos de variables:

  • IOTag. Se lee de un controlador, y por tanto contiene una referencia a dicho equipo, el área de memoria donde se ubica y su dirección. La principal particularidad es que redefine el método set para enviar por comunicaciones los cambios de valor.
  • MemoryTag. Se aloja en memoria. Lo adecuado sería establecer un mecanismo para que algunas de estas variables preserven su valor en cada arranque de la aplicación.
  • Expression. Como he comentado, se trata como variable cualquier elemento que arroje un valor, dotado de una lista de suscriptores para advertirlos de su modificación. De acuerdo a este criterio, una expresión debe ser considerada un tipo de variable. La clase Expression permite definir un cálculo dependiente de otras variables. Tiene herencia múltiple por tanto, de Tag y Subscriptor. Por el momento sólo contempla expresiones básicas: suma, resta, multiplicación, división, negación, igualdad, inferioridad, superioridad y anidamientos mediante paréntesis.
  • Alarm. Definida como una expresión, una alarma debería llevar a cabo ciertas acciones de notificación cuando se activa: almacenarse en un fichero, mostrarse en los HMI, enviar un correo…
  • TrendTag. Nuevamente, es una expresión (aunque su contenido puede ser una variable pura) cuyo valor se almacena periódicamente en base de datos o archivos.

En lo que toca al desarrollo web, se mantiene la misma estructura del fichero html y la página tiene las idénticas funcionalidades. Sin embargo, al usar websockets, se elimina el método de refresco periódico de los valores, y se minimiza el tiempo de actualización de la información. Por comentar brevemente el código en Javascript: cuando el documento está listo, tras asociar los eventos a la página, se instancia un websocket y se le asocian eventos.

El primero, onopen, registra (se suscribe) a las variables contenidas en la página. Como decíamos en entradas previas, el nombre de la variable se indica en el atributo data-dir. La suscripción se lleva a cabo enviando un JSON que especifica la acción (subscribe) y el listado de variables:

UWS responderá con un mensaje (que se gestiona con el evento onmessage) que contiene los valores de dichas variables:

Por último, los envíos de consignas u operaciones se hacen mediante el método send de websocket, también codificados en JSON:

En próximas entradas avanzaremos en las alarmas e históricos, e incluiré algún driver más de comunicaciones.
Esta entrada continúa en Proyecto UWS (6).
Recursos asociados:
SCADA UWS (versión 1.2) y código de ejemplo.

Facebooktwitterlinkedin