Proyecto UWS (3)

publicado en: Programación, SCADA | 0

En la entrada previa mostré cómo se configuraba una red de controladores en UWS, y concluía con el arranque del servidor web. Quedó pendiente cómo desarrollar la interfaz del SCADA. Aunque al acometer la parte gráfica no es necesario comprender bien cómo funciona el propio servidor, resulta conveniente para conocer sus posibilidades. Cuando lo instanciamos se le pasan tres parámetros: una tupla con la interfaz y puerto de escucha, el manejador y el ensemble:

Hecho esto, una hebra se encargará de atender las peticiones HTTP que lleguen por dicho puerto con el método GET. En román paladino, cuando escribamos la dirección del servidor en un navegador recibiremos una respuesta, en función de la URL que se esté demandando. El formato de una petición sería como sigue:

Respecto a la dirección del servidor no creo que haya lugar a dudas. Si hemos arrancado el UWServer con la línea antedicha y queremos acceder al SCADA desde el propio equipo, escribiríamos en el navegador http://127.0.0.1:80 (o http://localhost:80, o simplemente http://localhost). La parte interesante está en la cadena recurso. Tenemos tres alternativas:

  • Lectura de un valor. Para conocer un valor de un controlador, el recurso debe adoptar la forma ?r:[plc]:[memoria]:[elemento]. Por ejemplo, si en la situación descrita en la entrada previa queremos conocer la entrada analógica 2 (la tercera, ya que empezamos a contar por 0), la URL que debemos escribir sería http://localhost:8080/?r:plc1:registers:2. El navegador nos devuelve directamente su valor en HTTP. Sencillo, ¿no?
  • Escritura de un valor. De la misma forma, podríamos modificar un valor en uno de los controladores. La cadena de recurso en este caso sería ?w:[plc]:[memoria]:[elemento]:[valor]. En la misma situación anterior, si quisiésemos escribir un 50 en el primer registro de retención (dirección 0), lo haríamos pidiendo desde el navegador http://localhost:8080/?w:plc1:holdings:0:50. Podemos ver cómo en el controlador, dicho registro se pone en 50.
  • En cualquier otro caso, se nos devolverá, como un servidor web al uso, el fichero localizado en la ruta relativa, que por defecto es www. Por ejemplo, podemos crear una página de bienvenida index.html, situarla dentro de www, y verla con http://localhost:8080/index.html (o de forma más simple, http://localhost:8080).

No necesitamos nada más para elaborar la interfaz. Con esto es suficiente para crear una página web, y un poco de Javascript nos debería permitir el refresco de la representación y el envío de las escrituras. Se puede objetar que el código que habría que elaborar es engorroso, pero aquí es donde entra en juego la magia de jQuery Ajax. En el ejemplo que hemos dado, he incluido el fichero j.js, que permite olvidarse de toda esta tarea (en realidad, de todo lo que he explicado hasta el momento). Su uso es simple, y sólo hay que hacer dos cosas:

  • En la página que desarrollemos hay que incluir una referencia a jQuery y a j.js:
  • A cada elemento dinámico hay que agregarle el atributo data-dir, cuyo valor será la dirección del dato que se desea representar. La sintaxis es la misma antes descrita ([plc]:[memoria]:[elemento]). Es decir, para mostrar el estado de la bobina número 1, el código HTML sería el siguiente:
    Si además nos interesa poder modificarlo, la etiqueta adecuada es sin duda un input:

Con estos atributos data-dir, podemos desentendernos de la programación asociada a la página. El código en j.js hace lo necesario. Por un lado asocia a las etiquetas susceptibles de ser modificadas (input de tipo checkbox y text) los eventos correspondientes, de modo que ante un cambio envíen la escritura al servidor. Por otro, se lanza un temporizador para refrescar periódicamente los valores, tanto de las etiquetas anteriores como de los div, que no se pueden modificar. El tiempo de refresco, que es de 1000ms por defecto, se puede determinar mediante el siguiente elemento oculto HTML:

Por supuesto, todo lo descrito hasta aquí es muy mejorable. Así a bote pronto se me ocurren las siguientes líneas de desarrollo para las próximas versiones de UWS:

  • Utilizar los websockets de HTML5 para el refresco de la página, en vez de solicitar periódicamente los datos, mediante un modelo de suscripción. Con esto se gana agilidad y se disminuye el tráfico de red.
  • Añadir nuevas funcionalidades a j.js, como alterar la visibilidad de elementos, dimensiones, etc. Mediante atributos adicionales, también se puede agregar transformaciones sobre valores, como inversión o escalado.
  • Introducir en el ensemble un diccionario, para referenciar los datos mediante nombres simbólicos. Lo ideal sería cargar dichos nombres desde fichero o base de datos, en lugar de picarlos en Python.
  • Agregar nuevos protocolos de comunicación con controladores. También otras formas de conectividad con el ensemble.
  • Por último, un SCADA no puede estar completo sin alarmas e históricos.

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

Proyecto UWS (2)

publicado en: Modbus, Programación, SCADA | 0

He terminado la fastidiosa tarea de documentar el Proyecto UWS. Y de camino me ha servido para corregir un par de errores. Como comentaba, el UWS es un esbozo de SCADA muy en pañales. Corre en Python (yo uso concretamente la versión 3.5) y la interfaz es HTML estándar. De momento sólo comunica por Modbus TCP, pero todo se andará.
Los módulos y clases de los que se compone son los siguientes:

  • PLCModule:
    • PLC: Representación de un controlador genérico.
    • Memory: Representación de una de las zonas de memoria de un PLC. En el caso de un equipo Modbus, van a ser bobinas, entradas digitales, registros de retención y registros de entradas. Pero otros controladores exigirán otra distribución.
    • Area: Segmento de memoria. Su uso es interno, normalmente no va a requerir que el programador la ataque.
    • Poll: Conjunto de áreas (información) que se piden con una misma frecuencia de muestreo. Por ejemplo, valores que cambian muy rápido o son críticos requieren refresco con intervalo reducido.
  • MBPLCModule:
    • MBPLC: Controlador con comunicación Modbus. Deriva de la clase PLC.
  • EnsembleModule:
    • Ensemble: Vendría a ser una red de controladores. Pero en realidad no hay exigencia real de que se encuentren en la misma red. En el fondo es un conjunto de controladores y de grupos de muestreo.
  • UWServerModule:
    • UWServer: El SCADA propiamente dicho. En principio sólo integra los componentes.
    • WebServer: El servidor web.

Me va a perdonar el lector por el revuelto de idiomas: clases, atributos, métodos, etc. están nombrados usando el inglés, pero tengo poca soltura y mucha pereza para usar la misma lengua para los docstrings, de modo que los he redactado en español.
El siguiente gráfico muestra los componentes de un proyecto:

Componentes de UWServer
Componentes de UWServer

En la otra entrada puse un ejemplo de cómo se llevaría a cabo un proyecto, sin apenas dar explicaciones. Me gustaría repasarlo de nuevo, explicando más en detalle los pasos. Básicamente el desarrollo se realiza en dos espacios. En Python se define la estructura del proyecto (controladores, conexiones, muestreos…) y en HTML se compone la interfaz del SCADA. Comencemos por la primera, que nos va a llevar el resto de la entrada. Por lo usual, en primer lugar debemos instanciar un Ensemble, es decir, una red de controladores.

En nuestro ejemplo sólo vamos a requerir que el ensemble tenga un controlador, al que vamos a llamar plc1. Como comunicamos con él en Modbus TCP, hay que indicarle su dirección IP. También cuánto ocupan sus distintas áreas de memoria (coils, inputs, holdings y registers). La clase nos permite aportar más parámetros, como puerto de conexión (típicamente 502), método, unidad (número de esclavo), reintentos caso de fallo de comunicación. También atributos para saber si se ha establecido la comunicación, métodos para leer o escribir datos, e incluso podríamos definir áreas adicionales de memoria con un sentido algo peregrino. Pero para nuestro ejemplo no nos vamos a complicar: la longitud de todas sus áreas de memoria va a ser de 20 elementos y el resto de parámetros quedan por defecto. También aprovechamos para agregarlo al ensemble en el mismo paso:

Ahora vendría la tarea fastidiosa de definir diferentes muestreos, según periodo de refresco, y las áreas que se leen. Un ejemplo de cómo se crearía uno de estos grupos es el siguiente:

Hago notar que propiamente hablando, el tiempo de muestreo es “entre muestreos”. Es decir, el código espera a que se hayan completado las comunicaciones (o hayan devuelto error) antes de empezar a contar para las siguientes peticiones. Estamos hablando comunicación desde un SCADA, no en un bus de campo, con lo que podemos ser algo laxos en este sentido. Se evita así además saturar las comunicaciones por solapamientos. Para continuar con el ejemplo, ahora habría que iniciar las comunicaciones con cada uno de los grupos de muestreos definidos.

Aunque de esta forma se controla de forma fina cómo se van a llevar a cabo las comunicaciones, he querido incorporar un método más ágil. fast_deploy crea un único grupo de muestreo con el tiempo por defecto, añade todas las áreas de memoria al completo de todos los PLC que posea el ensemble, e inicia sus comunicaciones de una tacada:

En este momento tenemos el motor de comunicación en marcha, y podemos leer y escribir de la forma siguiente:

En estas circunstancias, tan solo nos falta lanzar el servidor web. Lo normal sería usar el puerto 80, pero se puede usar cualquier otro disponible, como el 8080. Por supuesto, tenemos libertad para emplear más de un puerto con diferentes servidores, y el mismo ensemble. Puede ser interesante conjugado con otro de los parámetros, la ruta relativa de los ficheros HTML, que por defecto es www.

Queda discutir la segunda parte, donde entraremos en el desarrollo de la interfaz web. Eso será en una próxima entrega.
Esta entrada continúa en Proyecto UWS (3).
Recursos asociados:
SCADA UWS (versión 1.0) y código de ejemplo.

Novedades 20160118

Los fabricantes de controladores cada vez se toman más en serio la conectividad de sus equipos, y no me refiero a nivel de campo. Las instalaciones de control aisladas renuncian al enorme potencial de la integración con el resto de la organización. Si hace poco hablaba de la librería TCP File Server de Siemens, Omron ha dado un paso más allá. Los NJ501 y NJ101 comunican directamente con bases de datos, sin intermediarios. Ellos lo enfocan a control numérico, se puede pensar en el IoT… pero la clave está en la gestión unificada de la producción.
La Agencia Europea de Seguridad de las Redes y de la Información (ENISA) ha publicado un estudio sobre el grado de madurez de la seguridad en los sistemas SCADA e ICS, orientado a las actividades de los estados miembros, sus legislaciones y estrategias. España destaca en la formación, debido a los cursos del INCIBE y la Universidad de León. El estudio también propone una serie de recomendaciones: alinear esfuerzos, buenas prácticas, estandarización, alertas, sensibilización, formación e investigación.
Omron dispone de una plataforma de formación online gratuita en la que se pueden encontrar cursos de diversas materias: sistemas de automatización, control, motores, fuentes, relés, interruptores, componentes de seguridad, sensores, visión, ahorro energético… Los textos son muy claros, en español, y no requieren un nivel elevado, de modo que constituyen un material muy interesante para quien quiera iniciarse por su cuenta.
Keith Blodorn, de ProSoft Technology, ha descrito recientemente en un artículo las características fundamentales de la Industria 4.0. Se centra en remarcar la evolución frente a la integración de sistemas tradicional, que en realidad es bastante gradual: lo que supone en cuanto a supervisión remota, movilidad e interoperatividad. Y precisamente debido a que es una evolución, más que revolución, la adaptación es sencilla, teniendo presente aspectos como escalabilidad, migración de red y ciberseguridad.
Telefónica ha publicado su libro blanco sobre las smart cities, una buena visión del estado del arte. A mi modo de ver, lo más interesante está en la cuarta parte. Tras esbozar una hoja de ruta, se ahonda en las relaciones que se deben establecer entre actores (ciudadanos, universidad, empresas, administración), el marco legal, la financiación y los modelos. De manera demasiado breve también se presenta algún caso práctico, como el de Rivas Vaciamadrid. Por último, el libro propone un decálogo para las las futuras ciudades inteligentes.

Proyecto UWS (1)

publicado en: Diseño web, Raspberry Pi, SCADA | 0

Este año los reyes me llegaron con unos días de retraso, pero han valido la pena. Traían una flamante Raspberry Pi 2 B, con la que me he puesto a trastear un poco. Tenía ganas de programar un mini SCADA, que pudiese correr en un pequeño controlador como éste y que fuese accesible desde un navegador web. Sobra decir que es una primerísima versión todavía en pañales, posiblemente plagada de fallos y con una documentación escasa, por no decir ausente. Por tanto, no aconsejo de momento su uso para aplicaciones sensibles. Poco a poco iré mejorándola en los ratos libres.

Raspberry Pi 2 B
Raspberry Pi 2 B

Me gustaría en primer lugar dar una idea rápida del objetivo, así que voy a arrancar con una exposición en caliente. El único requisito de partida es un controlador con puerto Ethernet que pueda correr Python. He usado la Raspberry pero bien podría servir un PC con Windows, o Linux, o incluso algunas tablets. El SCADA, al que he dado en llamar Universal Web Server, tiene de momento poco de universal, ya que sólo comunica en Modbus TCP. Por tanto, también hará falta un servidor que comunique en este protocolo. Lo hacen muchos autómatas; yo cuento con un simulador. En estas circunstancias, nuestro SCADA consiste en un breve código en Python que da de alta dicho esclavo, inicia las comunicaciones con él y va sirviendo la información vía web. Quedaría como sigue:

Al ejecutar este código se hace todo lo que hemos comentado. He preparado una página donde se pueden ver los primeros valores de las áreas de memoria del PLC (coils, discrete inputs, holdings y register inputs). Como es de esperar, también es posible modificar datos cuando están accesibles para escritura.
Por supuesto, como SCADA es algo esquemático. El motivo es mi pereza, no la funcionalidad de UWS. Por terminar de mostrar el código del ejemplo, que pasaré a comentar en sucesivas entradas, copio a continuación el HTML de la página. Espero que, como creo haber hecho con la parte de Python, la sintaxis sea lo bastante simple como para, incluso sin describir los detalles, el contenido sea intuitivo. Se hace notar que no es necesario ejecutar código adicional, ya que el script en j.js se encarga de localizar todas aquellas etiquetas con atributo data-dir, interpretarlas como elementos dinámicos, y asociarles los eventos necesarios, que varían en función del tipo de etiqueta. Por tanto, podemos incluir tantas páginas como queramos con un desarrollo web al uso. Basta incluir los archivos, como index.html, dentro de la carpeta www, que debe estar situada en la ruta desde la que estamos ejecutando la aplicación.

Por último, hacer notar que las comunicaciones Modbus de este ejemplo hacen uso del paquete pymodbus3. Se puede instalar a través de pip con:

A continuación incluyo el enlace a la aplicación en Python, los módulos de que depende y la página web de este ejemplo. En las siguientes entradas iré documentando la API y espero que ampliando la funcionalidad y protocolos de comunicación. Espero que os sea de utilidad.
Esta entrada continúa en Proyecto UWS (2).
Recursos asociados:
SCADA UWS (versión 1.0) y código de ejemplo.

Novedades 20151223

publicado en: BACnet, KNX, LonWorks, PID, Schneider, Seguridad | 0

Poco a poco se va difuminando la frontera entre autómatas y controladores domóticos. Esta primavera Schneider presentaba los Modicon M171/172, capaces de hablar BACnet y LonWorks. Hace unos días Siemens presentó el módulo CMK2000, permite a los Logo! 8 comunicarse en KNX (las versiones anteriores usan el CM EIB/KNX).
En 2009 se definió el estándar ANSI/ISA-18.2 para la gestión de alarmas en los sistemas de control. Con miras en la seguridad, que depende de una respuesta urgente ante situaciones de riesgo, y por tanto de la eficacia del sistema de alarmas, se define un ciclo de vida para éste. Comprende su optimización (filosofía o definición del proceso, identificación de alarmas, racionalización o clasificación, diseño en detalle e implementación), soporte (operación y mantenimiento), evaluación y mejora continua (gestión de cambios y auditoría).
He sabido por el blog de Martín Castillo de la aplicación LDmicro, que permite programar PIC en ladder. No he tenido ocasión de probarla, pero parece sencilla, viene acompañada de simulador y, aunque el conjunto de operaciones es bastante limitado, permite algunas funciones de cierto nivel, como manejo de tablas o comunicación vía puerto serie.
Schneider ha publicado guía sobre los protocolos abiertos más usados en inmótica, que incluye tanto exclusivos de este campo (Bacnet, LonWorks, KNX, Dali…) como más generales (Modbus, OPC, Web Services…). Están clasificados en alámbricos e inalámbricos, y aunque su descripción es muy breve, da algunas pistas sobre su idoneidad en función de la aplicación.
Hace una década me cansé de copiar y pegar código, y desarrollé una aplicación que genera el programa (la parte sistemática) a partir de un listado de equipos. Muchos fabricantes han seguido ese camino, por desgracia creando herramientas cerradas a sus productos. Nos lo cuenta Daniel B. Cardinal, que además describe las metodologías de diseño más comunes para el diseño automático de código. De ahí pasa a describir estrategias para aplicar a toda la pirámide de control, a la que idealmente se debería extender esta forma de desarrollo.
Como Vance VanDoren comenta, los lazos PID no son una solución universal y perfecta. Hace poco ha publicado la tercera parte de un artículo que comenzó a escribir ¡en 2012! acerca de sus problemas, y cómo soslayarlos (1, 2 y 3). Acumulación de la acción integral en caso de saturación o no actuación, respuesta abrupta en el arranque, regulación “del ruido”, sobreactuación cuando el proceso conlleva retraso… Yo añadiría que el ajuste se realiza para unas determinadas condiciones de proceso, que con frecuencia no se mantienen invariables; en este caso, una solución es establecer tramos con diferente parametrización.
En las últimas semanas se han publicado varias vulnerabilidades que afectan a equipos extendidos en el ámbito de la automatización. Comento las más importantes:
– Desbordamiento de buffer en productos M340 de Schneider que permite ejecutar código arbitrario o detener el PLC.
– Inyección de código con elevación de privilegios en SCADA PowerStudio (Circutor).
– Múltiples vulnerabilidades en routers eWON (inyección de código que permitiría actualiar firmware, cambiar de configuración, envío de contraseñas inseguro, etc.)
– Evasión de autenticación en dispositivos Siemens (CP343-1, CP443-1…)
– Varias vulnerabilidades en MicroLogix (Allen-Bradley): desbordamiento de buffer que permite ejecución de código, subida de archivos, inyección SQL…
Por último, una postal y una canción para felicitaros las fiestas.