Proyecto UWS (6)

publicado en: OPC, Programación | 0

Esta entrada es continuación de Proyecto UWS (5).

UWS con alarmero e histórico
UWS con alarmero e histórico

El anidamiento de clases en Python no tiene otra función que la de organizar el código. ¡Pero el orden es importante! En la última versión de UWS he reestructurado el código para darle una estructura menos difusa. También he renombrado algunos métodos para hacer la nomenclatura más coherente. En lo que toca a funcionalidad, hay muchas posibilidades nuevas: alarmas, driver OPC, registro en ficheros, base de datos, etc. Voy a ir comentando de forma resumida:

  • La clase Tag ya no está aislada, sino dentro de la clase Memory, que a su vez está en PLC. Por supuesto, se puede crear una variable sin asociarla a un controlador (de hecho, las alarmas van a tener ese tratamiento), pero creo que esta estructura es más natural. Este cambio organizativo afecta varios aspectos. En primer lugar, se funden los módulos PLCModule con TagModule dentro del último. Los diferentes drivers, en módulos independientes, se expresan como derivados de la clase PLC, y redefinen si es preciso los atributos y métodos de Memory y Tag. En segundo lugar, desaparece la clase IOTag. Bien pensado no tenía mucho sentido: todas las variables se pueden escribir y leer, ¿por qué habría que hablar de variables de entrada/salida? Si es preciso, como se ha dicho, se derivará la clase Tag en el correspondiente módulo del driver.
  • Aunque no tengo espacio para detenerme a comentar todas las clases, creo que Tag merece cierta atención por su relevancia. Cada variable tiene un identificador, que debe ser único dentro del Ensemble. Puede pertenecer a un controlador, en cuyo caso formará parte de una memoria, dentro de la cual tendrá una dirección; o estar disociada. También posee una descripción, útil para ciertos registros, que comentaré más adelante. El valor de una variable se lee con get() y se modifica con set(). Al principio comencé usando métodos mágicos de Python (__get__(), __set__(), __getitem__(), __setitem__()…), pero lo he abandonado, porque interfieren con el uso de listas o diccionarios. Por poner un ejemplo, si hacemos listadetag[“tag1”]=5, posiblemente estamos deseando llamar al método __set()__ de la variable listadetag[“tag1”], pero en realidad lo que hacemos es asignar un 5 al elemento “tag1” de la lista, lo que es un destrozo mayúsculo. Para evitar confusiones, me he desecho de casi todos los métodos mágicos. Sólo he guardado una excepción con la asignación de controladores al Ensemble, donde no cabe solapamiento. Hecho este largo inciso, comentar que la clase Tag tiene también un método update(), de uso interno para los drivers. Así, una clase derivada puede redefinir set(), y llamar posteriormente a update() para las obligadas gestiones, como advertir a todos los objetos suscritos de los cambios de valores. ¿Qué es una suscripción? Lo comento en el siguiente punto.
  • Cuando queremos lanzar una serie de acciones ante los cambios de una variable, creamos un objeto derivado de la clase Subscriptor, se lo pasamos a la variable mediante Tag.subscribe() y redefinimos el método Subscriptor.update() para programar dichas acciones. El sistema es rápido, eficiente y enormemente versátil. Tanto que todo el SCADA se ha redefinido para funcionar de esta guisa. Las actualizaciones de la interfaz gráfica se hacen por suscripción; también las alarmas, las expresiones calculadas, los registros… Vayamos por partes.
  • Como comenté en la pasada entrada, una expresión es una evaluación de operaciones sobre variables; por ejemplo (nivel<5)+(nivel>90)+boya_minimo+boya_maximo. La clase Expression aprovecha la herencia múltiple para derivar tanto de Subscriptor como Tag. Esto quiere decir que será advertida de la modificación de los valores que la conforman, pero que también, al constituir una variable en sí misma, puede advertir a otros elementos de sus cambios. En concreto, el ejemplo anterior sería una alarma; pero también podríamos configurar escalados, fórmulas complejas, históricos, etc. En la inicialización de la expresión hay que pasarle un diccionario de variables, que puede cambiar a posteriori, pero que debe estar completo en el momento de llamar a su método analyze(), que es el que lanza las suscripciones.
  • Una alarma (clase Alarm) es un tipo de expresión (y por tanto, también tiene funciones de variable). Idealmente, debería asociarse a un grupo de alarmas (AlarmGroup), que contiene una lista de salidas o registros de sus cambios. Estos registros son derivados de la clase Output, que define cómo deben ser gestionados. Igual que se añadió al Ensemble un método import_tags() para importar las variables de un csv, se le ha incorporado un import_alarms() para importar las alarmas. Éste es un ejemplo de definición de alarmas:

    CSV de alarmas
    CSV de alarmas
  • La clase Output está definida en el módulo OutputModule. Su función es registrar expresiones de cualquier tipo, no necesariamente alarmas. Su método transform hace algunas sustituciones automáticas. Por ejemplo, {n.description} en el texto de la expresión es reemplazado por la descripción de la variable n, {n.value} se sustituye por su valor… Para dar un poco de juego, he incorporado varias clases derivadas que pueden ser de utilidad: LogOutput envía los cambios a la depuración de Python, SimpleFileOutput lleva a cabo el registro en un fichero y DataBaseOutput los escribe en base de datos.

    Log
    Log
  • El driver Modbus TCP se simplifica. Al instanciarlo se crean automáticamente sus diferentes memorias, y conforme se le van agregando variables, se redefinen automáticamente sus áreas de escaneo. ¡Ah, lo había olvidado! He jubilado las clases para gestionar áreas y grupos de escaneo. Que cada driver maneje sus comunicaciones como mejor convenga. MBPLC lanza una hebra independiente con ese fin. Consecuencia de ello, el método deploy() del Ensemble ha quedado reducido al análisis de expresiones y la conexión con los controladores.
  • El nuevo driver OPCPLC permite la comunicación con un servidor OPC UA. El encapsulado hace que tenga poco que contar de su funcionamiento. Tan solo en lo tocante al direccionamiento de las variables, que ataca a los nodos del protocolo, y describe la ruta a partir del nodo de objetos usando el carácter \ como separador. Como los nodos también se diferencian por tipo, es preciso anteponerles su identificador correspondiente, separado por :. Así, por ejemplo, una dirección válida puede ser 2:Data\2:Static\2:Scalar\2:DateTimeValue. Para ayudar a determinar el direccionamiento he incluido el método print_tree(), que imprime la estructura completa de un servidor OPC una vez que el driver se ha conectado.

    Driver OPC UA
    Driver OPC UA
  • Toda la gestión de alarmas que se ha definido clamaba con ansia dos elementos nuevos en la interfaz. El primero es un visualizador de alarmas. Se hace de una forma tan sencilla como insertar una tabla con el atributo data-alarmgroup=”nombre_del_grupo_de_alarmas”. El código en Javascript se encarga solo de asociarle los eventos correspondientes para ir mostrando en todo momento las alarmas presentes, con aspecto definido en la hoja de estilos. El segundo elemento es un histórico de alarmas. Su definición es idéntica, salvo que añade el atributo data-historical. A continuación se muestra cómo se insertan estos dos nuevos objetos en la interfaz:

Para mostrar cómo se levanta un proyecto con los nuevos cambios, a continuación muestro el código necesario para definir un Ensemble con un PLC Modbus y un servidor OPC, importar sus variables y alarmas, registrar estas últimas en un fichero, en el depurador de Python y en una base de datos MySQL, y por último lanzar la interfaz web:

Esta entrada continúa en Proyecto UWS (7).
Recursos asociados:
SCADA UWS (versión 1.3) y código de ejemplo.

Novedades 20151102

La noche del 24 al 25 de octubre, en la mayoría de los países europeos, entre ellos España, tuvo fin el horario de verano. Aproveché para avisar de que, en todas aquellas instalaciones que tienen programaciones horarias y no se haya contemplado dicho cambio, es necesario actualizar la hora de los controladores. Lo ideal es habilitar donde se pueda el servicio de horario con esta característica y mantenerlo actualizado por NTP.
El estándar IEEE 802.3at-2009 describe la alimentación eléctrica a través de la red Ethernet (PoE). Los fabricantes no siempre se acogen a esta norma, por cierto. Anja Adling, de Siemens, comenta las cuatro clasificaciones de dispositivos en el nivel físico según sus requerimientos, y la clasificación a nivel de enlace. También el mecanismo de apagado por prioridad, y el ahorro que se puede conseguir con la gestión PoE.
En un par de ocasiones me han planteado monitorizar instalaciones desde el aire, por medio de drones. La tarea es mucho más compleja de lo que puede parecer, y requiere fuertemente de la inteligencia artificial para asistir el vuelo autónomo, el reconocimiento visual, detección de patrones y la evaluación. Siemens está ensayando un nuevo enfoque, monitorizando las respuestas cerebrales de especialistas, de modo que el sistema aprende del comportamiento humano.
De este artículo de Suzanne Gill me gustaría rescatar una idea: la importancia, conforme se avance hacia la Industria 4.0 y el IIoT, de trasladar y aumentar las ventajas de tecnologías como HART o Fieldbus (sencillez de integración, “autoconfiguración”, llevar el diagnóstico hasta el MES, e incluso ERP…). Por lo demás, el texto es confuso. Identifica HART con un bus de campo, cuando ni siquiera es un bus (aparte las referencias a Fieldbus); da pie a relacionar el IoT con HART (sin pasar por HART-IP); las menciones a CAM, CIM, NAMUR NE107 o FDI no vienen al caso…
Shady Yehia tiene publicado en su blog un artículo dividido en cuatro entradas muy instructivo acerca de los sistemas de control. Lo recomiendo para quien se quiera aproximar a la materia; en particular los primeros párrafos, donde da una visión general de flujo de información desde el proceso al sistema SCADA y de nuevo de vuelta, pasando por sensores/actuadores, PLC, y servidor OPC.
Journey to the Center of the Plant, from Field to SCADA and Back – 1
Journey to the Center of the Plant, from Field to SCADA and Back – 2
Journey to the Center of the Plant, from Field to SCADA and Back – 3
Journey to the Center of the Plant, from Field to SCADA and Back – 4

Historia de OPC

publicado en: OPC | 0

El estándar OPC (inicialmente OLE for Proccess Control, pero renombrado Open Platform Communications) surgió a mediados de los años 90 como una tecnología para la comunicación del software SCADA y otros HMI con los dispositivos de control en el ámbito de la industria. Consiste en realidad en un conjunto de especificaciones que resuelven diferentes tareas imprescindibles en este ámbito, para lo cual hacen uso de tecnologías estándar del mercado. El principal acicate para su desarrollo fue la superación de las insuficiencias que presentaban los sistemas basados en DDE, en particular su escaso rendimiento y la incompatibilidad de las distintas extensiones que los fabricantes habían introducido para solventarlo.

Arquitectura OPC
Arquitectura OPC

OPC se basaba originalmente en la tecnología OLE/DCOM de Microsoft. Las especificaciones iniciales fueron desarrolladas por la OPC Task Force, una institución promovida por varias de las principales compañías del sector: Fisher-Rosemount, Intellution, Intuitive Technology, Opto22, Rockwell y Siemens AG. En agosto de 1996 se liberó una primera versión de las especificaciones (OPC Specification Version 1.0), basadas en las tecnologías COM (Component Object Model), OLE (Object Linking and Embedding) y DCOM (Distributed Component Model). La primera definía un sistema de comunicación entre procesos y de creación dinámica de objetos de forma neutral; es decir, éstos podían ser utilizados posteriormente en entornos de desarrollos distintos al de creación original. La segunda, OLE, establecía mecanismos de mantenimiento y gestión de datos y archivos de forma que pudiesen tratarse por distintas aplicaciones. La última, DCOM permitía la creación de componentes distribuidos de software en diferentes sistemas intercomunicados.
Uno de sus mayores retos del estándar OPC ha sido adaptarse a un dominio en continuo cambio, para lo que se optó desde sus orígenes por una estrategia que permitiese enriquecerlo de forma constante por medio de adiciones básicas. Esto se vino llevando a cabo inicialmente mediante distintos documentos Data Access Specification, que recogían las incorporaciones a los mecanismos y funcionalidad de lectura y escritura de datos de proceso. Paralelamente, OPC se veía enriquecido por la adición de servicios de interés en el ámbito industrial. A la primera versión del protocolo, que pasó a denominarse OPC DA (Data Access) y establecía cómo debía realizarse el intercambio de datos de tiempo real entre servidores y clientes, se le incorporó en 1999 la posibilidad de gestionar el tráfico de alarmas y eventos entre servidores y clientes, OPC AE (Alarms and Events Specification), y en el año 2000 se le agregó una capacidad semejante de manejo de datos históricos, OPC HDA (Historical Data Access Specification). También en dicho año se definieron e implementaron políticas de seguridad, OPC S (Security Specification). Otras adiciones posteriores fueron las recogidas en la OPC Batch Specification, para la gestión de tareas, la OPC XML-DA Specification para servicios web a través de XML y SOAP, o la OPC DX Specification, que define la comunicación de servidor a servidor sin uso de clientes. La comunicación entre servidores, que requieren mensajes con tipos de datos más complejos, se efectúa gracias a OPC CD (Complex Data). Entre los últimos protocolos incorporados al estándar se encuentra OPC C (Commands), que dota a clientes y servidores de un conjunto de interfaces para indentificar, enviar y moonitorizar comandos de control.
Actualmente, el rápido crecimiento en el número de productos que incorporan OPC, así como sus capacidades, han hecho de éste el estándar industrial con más aceptación. La OPC Foundation es la organización encargada de crear y mantener las especificaciones de forma abierta.
Conforme DCOM fue reemplazándose por la tecnología .NET, que permitía un desarrollo ágil en redes y entornos Web, OPC debió adaptar sus interfaces a dicha plataforma. La última API liberada del OPC clásico, conocida formalmente como OPC Express Interface (Xi), se basa en el modelo .NET 4.0 WCF (Windows Communication Foundation). Provee de una envoltura a las interfaces clásicas, y permite un uso más seguro a través de redes por medio de mecanismos de autentificación, autorización y encriptación de datos. También simplifica el acceso a través de cortafuegos, al requerir sólo la apertura de dos puertos.
Desde el año 2006, la OPC Foundation, en conjunción con el MTConnect Institute, viene trabajando en una versión unificada de los estándares (OPC UA, o Unified Architecture), con miras a avanzar hacia una arquitectura orientada a servicios de tipo multiplataforma. Gracias a esto se elimina la tradicional dependencia de Microsoft Windows de los protocolos de control industrial. OPC UA se beneficia de las características que proporcionan el conjunto de estándares descrito, a las que se une la ventaja de ser portable a otros sistemas operativos. Para ello, OPC abandona definitivamente el modelo DCOM y se constituye en una arquitectura orientada a servicios (SOA, Service Oriented Architecture). Existen interfaces de programación (API) implementadas para C, C++, .NET, Java, NodeJS y Python. Otras ventajas que aporta son la seguridad revisada, el modelo de información, redundancia, buffering de datos o monitorización de los enlaces.

Arquitectura de OPC UA
Arquitectura de OPC UA