Uso de tecnologías web en los PLC de Industrial Shields

Parte 1 - UParte 1 - Utilizar un marco web para crear una aplicación web compleja
11 de julio de 2023 por
Uso de tecnologías web en los PLC de Industrial Shields
Boot & Work Corp. S.L., Joan Vilardaga Castro

Introducción

En el cambiante panorama actual de la automatización industrial, crece el interés por incorporar nuevas tecnologías web a los controladores lógicos programables tradicionales. El potencial del uso de marcos de trabajo, la adición de bibliotecas para capacidades adicionales y la integración de bases de datos en estos sistemas presenta interesantes posibilidades para mejorar la funcionalidad y la eficiencia.

En esta serie de blogs de dos partes, descubriráslas aplicaciones prácticas y los beneficios de aprovechar estas tecnologías web en los PLC industriales, abriendo nuevas vías para la innovación y la mejora de los procesos industriales.

Uso de tecnologías web en los PLCs de Industrial Shields

¿Qué son los frameworks web?

¿Qué son los frameworks web?

Los frameworks web desempeñan un papel fundamental en el desarrollo de los componentes front-end y back-end de las aplicaciones web. Estos marcos proporcionan a los desarrolladores un enfoque estructurado y eficiente para crear soluciones de software robustas y escalables, tanto si se centran en el front-end orientado al usuario como en el back-end del lado del servidor.

Los frameworks de front-end, como Svelte y React, ofrecen a los desarrolladores formas de crear interfaces de usuario interactivas y visualmente atractivas. Estos marcos ofrecen una colección de herramientas, bibliotecas y componentes preconfigurados que simplifican el proceso de diseño de maquetaciones con capacidad de respuesta, la gestión de la lógica de aplicaciones complejas y el manejo de las interacciones de los usuarios. Gracias a su sintaxis declarativa y a sus eficientes técnicas de renderización, los frameworks front-end permiten a los desarrolladores crear aplicaciones web complejas de forma más eficiente y fácil de mantener.

Por otro lado, los frameworks de back-end, como SvelteKit, Express.js o Django, proporcionan un entorno estructurado para desarrollar la lógica del lado del servidor de las aplicaciones web. Estos marcos se encargan de tareas como el enrutamiento, las interacciones con bases de datos, la autenticación y la integración de API, lo que permite a los desarrolladores centrarse en implementar la lógica empresarial y garantizar una comunicación segura y eficiente entre el front-end y el servidor.

In this blog, you will learn how to install the Svelte front-end framework on one of Industrial Shields ESP32 PLCs. By integrating Svelte into this PLC, you can leverage the power of this innovative framework to develop intuitive and efficient user interfaces tailored to your specific industrial needs.

¿Qué son Svelte y Sveltekit?

¿Qué es Svelte?

Svelte adopta un enfoque único al utilizar un compilador, lo que permite a los desarrolladores crear componentes increíblemente compactos que realizan un trabajo mínimo en el entorno del navegador. Este proceso de compilación optimiza el código JavaScript resultante, lo que se traduce en tiempos de carga rapidísimos y una experiencia de usuario excepcional.

Svelte

También añade un enfoque reactivo al desarrollo de la interfaz de usuario, que implica construir interfaces que puedan actualizarse automáticamente en respuesta a cambios en los datos subyacentes o en las interacciones del usuario. Tradicionalmente, las aplicaciones web dependían de la manipulación manual del DOM (y de la manipulación indirecta del DOM virtual en frameworks como React) para actualizar la IU, lo que a menudo daba lugar a código complejo y propenso a errores.

El enfoque reactivo de Svelte, impulsado por su proceso de compilación, permite a los desarrolladores crear componentes de interfaz de usuario que se actualizan automáticamente cuando cambia su estado subyacente. Esto significa que los desarrolladores pueden simplemente actualizar el estado de una variable, y Svelte se encarga de propagar eficientemente esos cambios a la interfaz de usuario. El resultado es una aplicación de alto rendimiento que responde perfectamente a las interacciones del usuario y a las actualizaciones de datos, proporcionando una experiencia de usuario fluida y atractiva.

¿Qué es SvelteKit?

Sveltekit

SvelteKit es una solución integral construida sobre Svelte. El framework incluye un sólido sistema de enrutamiento, que permite una navegación fluida entre las distintas páginas de la aplicación, etc. Además, SvelteKit es compatible con la renderización del lado del servidor (SSR), que permite que las páginas web sean pre-renderizadas en el servidor y entregadas al navegador como HTML completamente renderizado, mejorando el rendimiento inicial de carga de la página.

Además, SvelteKit ofrece capacidades de despliegue sin servidor, lo que permite a los desarrolladores desplegar sus aplicaciones en plataformas sin servidor como Netlify o Vercel con facilidad. El despliegue sin servidor elimina la necesidad de gestionar servidores e infraestructura, simplificando el proceso de despliegue y reduciendo la sobrecarga de mantenimiento. Sin embargo, es importante tener en cuenta que el despliegue sin servidor viene con ciertas ventajas y desventajas, como la incapacidad de utilizar renderizado del lado del servidor o ejecutar código JavaScript del lado del servidor.

Cómo utilizar SvelteKit en PLC industriales Shields

Cuando se trata de integrar tecnologías como Svelte y Sveltekit en nuestros PLCs industriales, es esencial tener en cuenta las limitaciones y capacidades del entorno de hardware y software. Por ejemplo, PLCs como las familias M-Duino y ESP32 no tendrán la capacidad de ejecutar servidores debido a la falta de software compatible para ejecutar un back-end Node.js. En su luhar, tendremos que utilizar el despliegue sin servidor.

Ten en cuenta que esto no es una limitación exclusiva de Svelte, se aplica a cualquier framework web (React, Vue.js...).

How to use SvelteKit in Industrial Shields PLCs

SvelteKit ofrece un enfoque alternativo denominado "adaptador estático" que debería utilizarse en situaciones en las que se necesite un despliegue sin servidor. El adaptador estático, que es un preajuste para el compilador Svelte, permite el pre-renderizado de todas las páginas de la aplicación durante el proceso de compilación. Esto significa que la aplicación web resultante consta de archivos HTML, CSS y JavaScript estáticos que pueden desplegarse directamente en el PLC sin necesidad de procesamiento en el lado del servidor.

Al aprovechar el adaptador estático, podemos seguir obteniendo ventajas como un mejor rendimiento de la carga inicial de la página y la optimización de los motores de búsqueda. Los archivos estáticos prerrenderizados garantizan que el contenido esté disponible de inmediato, reduciendo el tiempo necesario para que el PLC renderice la interfaz inicial, lo que permite a los desarrolladores crear aplicaciones web eficaces e interactivas que se ajusten a las capacidades de nuestros PLC.

Cómo configurar una aplicación SvelteKit

Requisitos

En primer lugar, tendrás que instalar Node.js y npm. Node.js es un entorno de ejecución de JavaScript basado en el motor V8 de Chrome. Permite a los desarrolladores ejecutar código JavaScript fuera de un navegador web, permitiendo la ejecución de JavaScript del lado del servidor. Node.js ofrece un modelo de E/S no bloqueante y basado en eventos que lo hace ligero, eficiente y adecuado para crear aplicaciones de red escalables. npm es una herramienta de línea de comandos que viene incluida con Node.js. Se encarga de gestionar e instalar los paquetes y dependencias necesarios para tu proyecto.

Node.js
Windows, Mac, Linux

Si estás en Windows, puedes seguir las instrucciones de Microsoft en su web oficial. Si estás en Mac o Linux, te recomendamos que utilices nvm, un gestor de versiones para Node.js que te permite cambiar fácilmente entre diferentes versiones de Node.js. Puedes instalar nvm siguiendo las instrucciones proporcionadas en heynode.com.

Iniciar una aplicación SvelteKit vacía

Con Node.js y npm instalados, tendrás que ejecutar los siguientes comandos:

npm create svelte@latest my-app
cd my-app
npm install
npm run dev

Con estos comandos, crearás una carpeta llamada my-app, instalarás las dependencias y ejecutarás una instancia de Vite (un servidor de desarrollo para probar la web app antes de enviarla al PLC). El primer comando te preguntará lo siguiente:

¿Qué plantilla de Svelte?

Recomendamos el proyecto Skeleton, ya que la aplicación de demostración debe modificarse para poder desplegarse sin servidor.

¿Añadir comprobación de tipos con TypeScript?

Puedes elegir no hacerlo. TypeScript es sólo un dialecto de JavaScript que incluye comprobación de tipos. En este tutorial usaremos la sintaxis de TypeScript.

Seleccione opciones adicionales

No utilizaremos ninguno para esta aplicación de ejemplo.

Una vez que la instancia de Vite esté en funcionamiento, podrá acceder a la aplicación de prueba a través de http://localhost:5173.

Configuración del adaptador estático

El adaptador estático de SvelteKit preprocesa toda su página web como una colección de archivos estáticos, que pueden desplegarse fácilmente en los PLC. La configuración del adaptador estático requiere unos sencillos pasos.

First, you need to install the static adapter package using npm, the package manager for Node.js. Open your command-line interface and execute the following command:

npm install -D @sveltejs/adapter-static
Setting up the static adapter

A continuación, debes configurar SvelteKit para que utilice el adaptador estático. Para ello, tendrás que modificar el archivo svelte.config.js en el directorio raíz de tu proyecto. Si el archivo no existe, puedes crearlo. Abre el archivo svelte.config.js y añade el siguiente código:

import adapter from '@sveltejs/adapter-static';
export default {
    kit: {
        adapter: adapter({
            pages: 'build',
            assets: 'build',
            fallback: undefined,
            precompress: false,
            strict: true
        })
    }
};

Una vez realizados estos cambios, el adaptador estático se configura para generar los archivos estáticos durante el proceso de construcción. Cuando construyas tu aplicación SvelteKit con npm run build, los archivos estáticos se crearán en el directorio "build", listos para desplegarse en el PLC.

Ejemplo de aplicación

Modificado el archivo +page.svelte
<scrip>
    let number = 0;
    function increment() {
        if (number < 10) {
            number += 1;
        }
    }
    function decrement() {
        if (number > 0) {
            number -= 1;
        }
    }
    $: double_number = number*2;
</scrip>

<style>
    .button {
        width: 48px;
        height: 48px;
    }
</style>

<main>
    <h1>Welcome to SvelteKit</h1>
    <p>This web shows a number that can be incremented or decremented with buttons.</p>
    <p>This number can only be between 0 and 10.</p>
    <p>Number = {number}</p>
    <p>Number*2 = {double_number}</p>
    <div style="display:flex">
        <button on:click={increment} class="button">+</button>
        <div style="width:16px"></div>
        <button on:click={decrement} class="button">-</button>
    </div>
</main>


En un enfoque típico de interfaz de usuario, cuando se trabaja con variables que deben actualizarse en función de las interacciones del usuario, tendríamos que manejar la lógica de actualización manualmente. Esto a menudo implica escuchar eventos o implementar otros mecanismos para rastrear y actualizar las variables por separado. Con el enfoque reactivo, Svelte se encarga de esto y sólo tienes que declarar la variable multiplicada con una sentencia reactiva. En este ejemplo, utilizando la sentencia reactiva "$: double_number = number * 2", Svelte crea el código entre bastidores que asegura que "doble_número" es siempre el doble de "número". Este enfoque reactivo simplifica el código y elimina la necesidad de un manejo explícito de eventos o de una lógica de actualización independiente.

Envío de la aplicación web dentro del PLC

Envío de la aplicación web dentro del PLC

Ya tenemos un tutorial que explica cómo almacenar archivos en la memoria flash de un ESP32 para servir una página web. Sin embargo, hay situaciones en las que el uso de la tarjeta SD se vuelve más ventajoso, como si estamos sirviendo aplicaciones más grandes o cuando la memoria flash tiene espacio limitado restante.


Para empezar, asegúrate de haber compilado la última versión de tu aplicación web mediante el comando npm run build. Este paso es necesario para disponer de los cambios más recientes y poder copiarlos. A continuación, tendrás que insertar la tarjeta SD en tu PC. Formatea la tarjeta SD al sistema de archivos FAT32. Una vez formateada, crea una carpeta en la tarjeta SD llamada "www". Esta carpeta servirá como directorio raíz para alojar el contenido de tu web. Ahora, navega hasta el directorio "build" dentro de la carpeta de tu proyecto Svelte. Copia todo el contenido de este directorio "build" y pégalo en la carpeta "www" de tu tarjeta SD.

Configurar el servidor web dentro del PLC

La librería más adecuada para este ejemplo es ESP32AsyncWebSrv, una librería asíncrona de servidor HTTP y WebSocket para ESP32. Esta librería se utiliza debido a su enfoque asíncrono y extensiones incorporadas para manejar la lectura directa desde el SPIFFS o SD, simplificando el proceso de servir contenido web desde la tarjeta SD. Pero hay algunas consideraciones que tenemos que tener en cuenta.


En primer lugar, la librería SD que utilizamos normalmente no soporta la extensión de nombres de fichero largos FAT32, lo cual es un problema porque la mayoría de los ficheros generados por el framework Svelte sobrepasan los límites de nombres de fichero. Una buena alternativa es la librería SdFat ya que proporciona el soporte necesario, y es compatible con nuestros PLCs.


Sin embargo, para integrar la librería SdFat con el servidor web, es necesario adaptar el objeto FS utilizado por el servidor web para que funcione con la librería SdFat. Afortunadamente, existe una adaptación no oficial del objeto SdFat que es compatible tanto con los PLCs como con la librería del servidor web. Ahora es posible que la librería ESPAsyncWebSrv utilice directamente la tarjeta SD a través de la librería SdFat.

Configurar el servidor web dentro del PLC


esp32-server.cpp
#include <AsyncTCP.h>
#include <ESPAsyncWebSrv.h>

AsyncWebServer server(80);
const char* ssid = "ISHIELDS";
const char* password = "boot2015SHIELDS*";

#include <SdFat.h>
#include <sdios.h>
#include "FS_SdFat_Wrapper.h"
#define SD_CONFIG SdSpiConfig(13, SHARED_SPI, SD_SCK_MHZ(16))
SdFat32 sd;
fs::FS sdFS = fs::FS(fs::FSImplPtr(new SdFat32FSImpl(sd)));

void notFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Not found");
}

void print_sd_errors(void) {
Serial.println(F("Code,Symbol - failed operation"));
for (uint8_t code = 0; code <= SD_CARD_ERROR_UNKNOWN; code++) {
Serial.print(code < 16 ? "0X0" : "0X");
Serial.print(code, HEX);
Serial.print(",");
printSdErrorSymbol(&Serial, code);
Serial.print(" - ");
printSdErrorText(&Serial, code);
Serial.println();
}
}
void setup() {

Serial.begin(115200);

if (!sd.begin(SD_CONFIG)) {
print_sd_errors();
sd.initErrorHalt();
}

WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.printf("WiFi Failed!\n");
return;
}

Serial.print("IP Address: ");
Serial.println(WiFi.localIP());

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->redirect("/index.html");
});

server.serveStatic("/", sdFS, "/www");

server.onNotFound(notFound);

server.begin();
}

void loop() {
yield();
if ((WiFi.status() != WL_CONNECTED)) {
Serial.println("Reconnecting to WiFi...");
WiFi.disconnect();
WiFi.reconnect();
}
}
FS_SdFat_Wrapper.h
#include <FS.h>
#include <FSImpl.h>
#include <SdFat.h>

// cfr https://en.cppreference.com/w/c/io/fopen + guesses
inline oflag_t _convert_access_mode_to_flag(const char* mode, const bool create = false) {
int mode_chars = strlen(mode);
if (mode_chars==0) return O_RDONLY;
if (mode_chars==1) {
if (mode[0]=='r') return O_RDONLY;
if (mode[0]=='w') return O_WRONLY | create ? O_CREAT : 0;
if (mode[0]=='a') return O_APPEND | create ? O_CREAT : 0;
}
if (mode_chars==2) {
if (mode[1] == '+') {
if (mode[0] == 'r') return O_RDWR;
if (mode[0] == 'w') return O_RDWR | O_CREAT;
if (mode[0] == 'a') return O_RDWR | O_APPEND | O_CREAT;
}
}
return O_RDONLY;
}

class SdFatFile32Impl : public fs::FileImpl
{
private:
mutable File32 _file;
public:
SdFatFile32Impl(File32 file) : _file(file) {}

virtual ~SdFatFile32Impl() { }

virtual size_t write(const uint8_t *buf, size_t size) {
return _file.write(buf, size);
}

virtual size_t read(uint8_t* buf, size_t size) {
return _file.read(buf, size);
}

virtual void flush() {
return _file.flush();
}

virtual bool seek(uint32_t pos, fs::SeekMode mode) {
if (mode == fs::SeekMode::SeekSet) {
return _file.seek(pos);
} else if (mode == fs::SeekMode::SeekCur) {
return _file.seek(position()+ pos);
} else if (mode == fs::SeekMode::SeekEnd) {
return _file.seek(size()-pos);
}
return false;
}

virtual size_t position() const {
return _file.curPosition();
}

virtual size_t size() const {
return _file.size();
}

virtual bool setBufferSize(size_t size) {
// don't know how to implement...
return false;
}

virtual void close() {
_file.close();
}

virtual time_t getLastWrite() {
// didn't want to implement ...
return 0;
}

virtual const char* path() const {
// didn't want to implement ...
return nullptr;
}

virtual const char* name() const {
// static, so if one asks the name of another file the same buffer will be used.
// so we assume here the name ptr is not kept. (anyhow how would it be dereferenced and then cleaned...)
static char _name[256];
_file.getName(_name, sizeof(_name));
return _name;
}

virtual boolean isDirectory(void) {
return _file.isDirectory();
}

virtual fs::FileImplPtr openNextFile(const char* mode) {
return std::make_shared<SdFatFile32Impl>(_file.openNextFile(_convert_access_mode_to_flag(mode)));
}
virtual boolean seekDir(long position) {
return _file.seek(position);
}
virtual String getNextFileName(void) {
return String("no way");
}
virtual void rewindDirectory(void) {
return;
}
virtual operator bool() {
return _file.operator bool();
}
};


class SdFat32FSImpl : public fs::FSImpl
{
SdFat32& sd;
public:
SdFat32FSImpl(SdFat32& sd) : sd(sd)
{
}

virtual ~SdFat32FSImpl() {}

virtual fs::FileImplPtr open(const char* path, const char* mode, const bool create) {
return std::make_shared<SdFatFile32Impl>(sd.open(path, _convert_access_mode_to_flag(mode, create)));
}

virtual bool exists(const char* path) {
return sd.exists(path);
}

virtual bool rename(const char* pathFrom, const char* pathTo) {
return sd.rename(pathFrom, pathTo);
}

virtual bool remove(const char* path) {
return sd.remove(path);
}

virtual bool mkdir(const char *path) {
return sd.mkdir(path);
}

virtual bool rmdir(const char *path) {
return sd.rmdir(path);
}
};

extern fs::FS SdFat32Fs;

Conclusión

Integración de tecnologías web

En conclusión, la integración de tecnologías web, como Svelte y SvelteKit, en los PLC Industrial Shield ofrece posibilidades prometedoras para mejorar la automatización industrial. El uso de marcos web facilita el desarrollo de aplicaciones web complejas con interfaces de usuario intuitivas y visualmente atractivas. El enfoque exclusivo de Svelte, que utiliza un compilador y un paradigma de desarrollo reactivo de la interfaz de usuario, da como resultado unos tiempos de carga rapidísimos y una experiencia de usuario fluida.

A pesar de las limitaciones de algunos equipos PLC, como la imposibilidad de ejecutar servidores, el adaptador estático de SvelteKit permite el despliegue sin servidor, posibilitando el pre-renderizado de páginas web y optimizando el rendimiento de carga inicial de la página. Siguiendo los pasos necesarios para configurar las aplicaciones de SvelteKit y utilizando la biblioteca SdFat para una integración perfecta con el servidor web, es factible desplegar aplicaciones web directamente en las tarjetas SD de los PLC, superando las limitaciones de espacio y garantizando un alojamiento web eficiente.


En general, la adopción de tecnologías web en los PLC de Industrial Shields abre nuevas vías de innovación, eficiencia y mejora de procesos, impulsando a la industria hacia la era de la Industria 4.0 y el Internet de las Cosas..

Buscar en nuestro blog

Uso de tecnologías web en los PLC de Industrial Shields
Boot & Work Corp. S.L., Joan Vilardaga Castro 11 de julio de 2023
Compartir

¿Estás buscando tu Controlador Lógico Programable ideal?

Echa un vistazo a esta comparativa de producto de varios controladores industriales basados en Arduino.

Comparamos entradas, salidas, comunicaciones y otras especificaciones con las de los equipos de otras marcas destacadas.


Industrial PLC comparison >>>