Introducción
En este post se muestra cómo crear un Servidor HTTP en un PLC M-Duino para poder controlar algunas Salidas desde un Sitio Web.
HTTP (Hyper Text Transfer Protocol) es el protocolo para transferir información entre sitios web. El protocolo especifica cómo debe solicitarse la información y cómo se forman las respuestas. El servidor HTTP es la implementación de ese protocolo en un programa informático.
En pocas palabras, cada vez que se escribe alguna dirección en el navegador, por ejemplo, www.industrialshields.com, y se presiona Enter, el navegador se está conectando al servidor HTTP detrás de esa dirección, el servidor interpretará la solicitud principal y luego proporcionará la página web principal.
Requisitos
Placas industriales shields para Ethernet y referencia de pines.
Arduino - Servidor HTTP
Librería HTTP-Server permite recibir una petición de la página web HTML del navegador y enviar una respuesta. La respuesta del servidor es el archivo HTML de la ruta que el usuario ha solicitado ver. Por ejemplo, cuando se busca, www.industrialshields.com en el navegador y se pulsa Enter, automáticamente se envía una petición al servidor para ver la página principal. Normalmente, la ruta de esta página es una barra diagonal "/". En este ejemplo, la página principal o raíz es la ruta "/". Así, escribiendo 10.1.1.2 o 10.1.1.2/ en la barra de navegación del navegador, el servidor responde con el archivo HTML de la página principal. Cuando escribimos alguna información en la sección de configuración y pulsamos el botón Enviar, la ruta solicitada es "/configuraciones", el servidor responde guardando los datos y enviando el archivo HTML con un mensaje de confirmación.
Para facilitar la tarea, en la Librería http-servidor tenemos implícita una función que envía toda la información guardada en un archivo SD. Esta función se llama sendStream(file, type file). file es el archivo SD abierto y type file es el tipo de archivo, en este caso, html.
Este es el código con algo de información al lado en negrita.
/* Copyright (c) 2019 Boot&Work Corp., S.L. All rights reserved This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifdef MDUINO_PLUS #include <Ethernet2.h> #else #include <Ethernet.h> #endif #include <SD.h> #include <HttpServer.h> #define SD_SS_PIN 53 byte mac[] = {0xAF, 0xBE, 0xCD, 0xDC, 0xEB, 0xFA}; IPAddress ip(10, 1, 1, 2); HttpServer http; File htmlFile; void setup() { Serial.begin(9600UL); Ethernet.begin(mac, ip); http.begin(); //Start HTTP Server Serial.println("HTTP Server Started"); Serial.print("IP Server: "); Serial.println(Ethernet.localIP()); Serial.println("********************************"); if (!SD.begin(SD_SS_PIN)){ Serial.println("Initialization failed!"); while(1){} } //OUTPUT PINS CONFIGURATION pinMode(Q0_0, OUTPUT); pinMode(Q0_1, OUTPUT); } void loop() { http.update(); //Constantly updating the server, waiting for a request } void httpServerEvent(const HttpRequest &req, HttpResponse &res) {//When we receive a request from the browser, this function is automatically executed.
//req: variable with request information
//res: variable to send information
String pagina,str; str=req.body;
//Display the request type (GET or POST), the route, query string in case of GET request and body. Serial.print("method: "); Serial.println(req.method); Serial.print("route: "); Serial.println(req.route); Serial.print("query string: "); Serial.println(req.queryString); Serial.print("body: "); Serial.println(str); Serial.println("--------------------------------");
//Filter by route if(req.route == "/"){//Homepage route serverRoot(res); } else if (req.route == "/configurations"){ String name, type; FormString formString(str); name = formString.getValue("name"); type = formString.getValue("type");
//See variables values Serial.print("var1: "); Serial.println(name); Serial.print("var2: "); Serial.println(type); serverConfigurations(res); } else if (req.route == "/actions/q0_0/on"){ digitalWrite(Q0_0, HIGH); serverActivationQ0_0(res); } else if (req.route == "/actions/q0_0/off"){ digitalWrite(Q0_0, LOW); serverDeactivationQ0_0(res); } /*else if (req.route == "/actions/r0_1/on"){ digitalWrite(R1, HIGH); serverActivationR0_1(res); } else if (req.route == "/actions/r0_1/off"){ digitalWrite(R1, LOW); serverDeactivationR0_1(res); }*/ else { res.send("Not Found", "text/plain", 404, "Not Found"); } } void serverRoot(HttpResponse &res){
//Response: Homepage HTML htmlFile = SD.open("root.txt"); if (htmlFile){ res.sendStream(htmlFile, F("text/html")); } else { Serial.println("Error opening file root"); } htmlFile.close(); } void serverConfigurations(HttpResponse &res){
//Response: HTML with confirmation message of information received. htmlFile = SD.open("config.txt"); if (htmlFile){ res.sendStream(htmlFile, F("text/html")); } else { Serial.println("Error opening file configurations"); } htmlFile.close(); } void serverActivationQ0_0(HttpResponse &res){
//Response: HTML with confirmation message of Q0.0 activated htmlFile = SD.open("act_q0_0.txt"); if (htmlFile){ res.sendStream(htmlFile, F("text/html")); } else { Serial.println("Error opening file activation_q0_0"); } htmlFile.close(); } void serverDeactivationQ0_0(HttpResponse &res){
//Response: HTML with confirmation message of Q0.0 deactivated htmlFile = SD.open("dact_q0_0.txt"); if (htmlFile){ res.sendStream(htmlFile, F("text/html")); } else { Serial.println("Error opening file Deactivation_q0_0"); } htmlFile.close(); } void serverActivationR0_1(HttpResponse &res){
//Response: HTML with confirmation message of R0.1 activated htmlFile = SD.open("act_r0_1.txt"); if (htmlFile){ res.sendStream(htmlFile, F("text/html")); } else { Serial.println("Error opening file activation_r0_1"); } htmlFile.close(); } void serverDeactivationR0_1(HttpResponse &res){
//Response: HTML with confirmation message of R0.1 activated htmlFile = SD.open("dact_r0_1.txt"); if (htmlFile){ res.sendStream(htmlFile, F("text/html")); } else { Serial.println("Error opening file Deactivation_r0_1"); } htmlFile.close(); }
Sitio web
Página de inicio. Interfaz sencilla. Sólo para comprobar que el sistema funciona bien.
En el siguiente vídeo, puedes ver cómo funciona. Cuando enviamos alguna información o activamos/desactivamos alguna Salida, el Servidor HTTP responde con un mensaje de confirmación.
Nota: Para comprobar que las dos acciones funcionan correctamente se necesita un PLC con salida analógica y de relé. Es decir, M-Duino 19R, 38R, 59R o 50RRA.