01
01
Microcontrollers
02
02
Control systems, open systems
03
03
Electronic world, sites
04
04
Electronic components, parts, etc...

e-micronica

Arduino - Centinela IP

Imprimir
Escrito por Paikan

En la realización de un curso de Arduino y posibles aplicaciones, realicé un programa que permite la vigilancia de una serie de dispositivos TCT-IP via red usando un Arduino Uno y un módulo Ethernet Shield. Pretendía ser algo más complejo, pero me faltó RAM y espacio en la flash para mejorarlo.

Se trata de lo siguiente: Arduino vigilará una serie de dispositivos via ICMP, si falla alguno esperará a que se produzcan cinco errores y si estos persisten, producirá una alarma para que el encargado de mantenimiento verifique los dispositivos caidos. La disponibilidad de los equipos se puede consultar via Web y se registra en una tarjeta SD los sucesos. En esa misma tarjeta SD van los detalles de operación del software, incluyendo la lista de IPs a explorar.

Adjunto código y pdf resumen por si a alguien le interesa parte o la totalidad del programa:

  1. //-------------------------------------------------------------------------------------
  2. // PROYECTO CENTINELA - MONITOR TCP/IP DISPOSITIVOS - CURSO ARDUINO - GABRIEL ASENSIO
  3. //-------------------------------------------------------------------------------------
  4. #define INTERVAL 15000    // Intervalo en segundos entre PING y PING
  5. #define Sirena 2          // Pin de salida para avisador
  6. // Cargamos librerias necesarias Ethernet y tarjeta SD
  7. #include <SD.h>
  8. #include <SPI.h>
  9. #include <Ethernet.h>
  10. #include <ICMPPing.h>
  11.  
  12. // ¡¡¡ PRECAUCIÓN ETHERNET Y SD !!!
  13. // On the Ethernet Shield, CS is pin 4. Note that even if it's not
  14. // used as the CS pin, the hardware CS pin (10 on most Arduino boards,
  15. // 53 on the Mega) must be left as an output or the SD library
  16. // functions will not work.
  17. const int chipSelectSD = 4;
  18. const int chipSelectEt = 10;
  19. // Establecer banderas de Problema/s
  20. boolean FlagError[30];
  21. boolean Avisador;
  22. byte Puntero=0;
  23. byte x=0;            
  24. byte y=0;
  25. File myFile;
  26. char Cadena[100];
  27. byte ipahora[4];
  28. // Configuración Ethernet, con valores por defecto
  29. byte ip[4]={192,168,1,55};
  30. byte netmask[4]={255,255,255,0};
  31. byte gateway[4]={192,168,1,1};
  32. // byte nntp[4]={192,43,244,18};
  33. byte mac[6]={144,162,218,0,121,190};
  34. // variables para dispositivos
  35. unsigned long equipo[30];
  36. byte estado[30];
  37. unsigned long hora=0;
  38. // Textos para guardar en memoria Flash de programa
  39. char PROGMEM KBCRA[]="<div align='center'><H1>Arduino - Centinela IP</H1></div>";
  40. char PROGMEM INICIO[]="<table width='30%' border='1' align='center'>";
  41. char PROGMEM divverde[] = "<tr><td bgcolor='#00FF00'><div align='center'>";
  42. char PROGMEM divroja[] = "<tr><td bgcolor='#FF0000'><div align='center'>";
  43. char PROGMEM divama[] = "<tr><td bgcolor='#FFFF00'><div align='center'>";
  44.  
  45. // Para PING
  46. SOCKET pingSocket = 3;     // Originalmente es '0', pero no se mezcla con NTP/Web bien si es '0'
  47.  
  48. EthernetServer server(80);
  49.  
  50. //-------------------------------------------------------------------
  51. byte Extraer(char* Trozo, byte Pos){
  52.    return( (((int)Trozo[Pos]-48)*100) + (((int)Trozo[Pos+1]-48)*10) + ((int)Trozo[Pos+2]-48));
  53.    }
  54. //-------------------------------------------------------------------
  55.  
  56.  
  57. //===========================================================
  58. //     Enviar contenido de PROGMEM a client de WebServer
  59. //===========================================================
  60. void contentPrinter(EthernetClient client, char *realword) {
  61. #define STRING_BUFFER_SIZE 30  
  62.   int total = 0;
  63.   int start = 0;
  64.   char buffer[STRING_BUFFER_SIZE];
  65.   int realLen = strlen_P(realword);
  66.   memset(buffer,0,STRING_BUFFER_SIZE);
  67.   while (total <= realLen){
  68.     // Enviar contenido a cliente
  69.     strncpy_P(buffer, realword+start, STRING_BUFFER_SIZE-1);
  70.     client.print(buffer);
  71.  
  72.     // more content to print?
  73.     total = start + STRING_BUFFER_SIZE-1;
  74.     start = start + STRING_BUFFER_SIZE-1;
  75.   }
  76. }
  77. //=============================================================
  78.  
  79.  
  80.  
  81. //--------------------------------------------------------------------
  82. void setup(){
  83.   Serial.begin(9600);
  84.   pinMode(Sirena, OUTPUT);      // Avisador es salida
  85.   // OJO al ChipSelect, solo se puede usar SD o Ethernet
  86.   pinMode(chipSelectEt, OUTPUT);  // Modo, inhabilitado por defecto
  87.   // Ver si hay tarjeta SD.
  88.   if(!SD.begin(chipSelectSD)){   // Abrrir SD
  89.      //---------------------------------------------------
  90.      Serial.println("Error SD");
  91.      return;
  92.      }
  93.      //---------------------------------------------------
  94.   Serial.println("SD Ok");
  95.   // Leer la configuración para programa (IP, MAC, NNTP, mail, etc)
  96.   if(SD.exists("CONFIG.ARD")){
  97.      myFile = SD.open("CONFIG.ARD");
  98.      while(myFile.available() > 0 ){
  99.         Cadena[Puntero]=myFile.read();
  100.         if(Cadena[Puntero]==10){
  101.           // Analizamos la cadena correspondiente según comienzo
  102.           switch(Cadena[0]){
  103.              //-- IP del Arduino --
  104.              case 'I':
  105.                 ip[0]=Extraer(Cadena,2);   // Primer byte IP
  106.                 ip[1]=Extraer(Cadena,6);   // Segundo byte IP
  107.                 ip[2]=Extraer(Cadena,10);   // Tercer byte IP
  108.                 ip[3]=Extraer(Cadena,14);  // Cuarto byte IP                
  109.                 break;
  110.              //--------------------  
  111.              //-- NetMask Arduino --
  112.              case 'N':
  113.                 netmask[0]=Extraer(Cadena,2);   // Primer byte NM
  114.                 netmask[1]=Extraer(Cadena,6);   // Segundo byte NM
  115.                 netmask[2]=Extraer(Cadena,10);   // Tercer byte NM
  116.                 netmask[3]=Extraer(Cadena,14);  // Cuarto byte NM                
  117.                 break;
  118.              //--------------------  
  119.              //-- Gateway Arduino --
  120.              case 'G':
  121.                 gateway[0]=Extraer(Cadena,2);    // Primer byte GW
  122.                 gateway[1]=Extraer(Cadena,6);    // Segundo byte GW
  123.                 gateway[2]=Extraer(Cadena,10);   // Tercer byte GW
  124.                 gateway[3]=Extraer(Cadena,14);  // Cuarto byte GW                
  125.                 break;
  126.              //--------------------                
  127.              //-- NNTP Server (Hora) --
  128.              case 'H':
  129.                 // nntp[0]=Extraer(Cadena,2);    // Primer byte NTP
  130.                 // nntp[1]=Extraer(Cadena,6);    // Segundo byte NTP
  131.                 // nntp[2]=Extraer(Cadena,10);   // Tercer byte NTP
  132.                 // nntp[3]=Extraer(Cadena,14);  // Cuarto byte NTP              
  133.                 break;
  134.              //---------------------
  135.              //-- MAC del Arduino --
  136.              case 'M':
  137.                 mac[0]=Extraer(Cadena,2);    //
  138.                 mac[1]=Extraer(Cadena,6);    // Segundo byte MAC
  139.                 mac[2]=Extraer(Cadena,10);   //  Tercer byte MAC
  140.                 mac[3]=Extraer(Cadena,14);   // Cuarto byte MAC              
  141.                 mac[4]=Extraer(Cadena,18);   // Cuarto byte MAC              
  142.                 mac[5]=Extraer(Cadena,22);   // Cuarto byte MAC                              
  143.                 break;
  144.              //-------------------------                            
  145.              //-- Equipos a verificar --
  146.              case 'D':
  147.                 equipo[x]=(Extraer(Cadena,4)*0x1000000)+(Extraer(Cadena,8)*0x10000)+(Extraer(Cadena,12)*0x100)+Extraer(Cadena,16);  
  148.                 FlagError[x]=0;    // Poner FlagError a '0'
  149.                 x++;
  150.                 break;
  151.              //--------------------                                          
  152.              case ';':
  153.                 // Ignorar línea, se trata de comentarios...
  154.                 break;
  155.              }
  156.           //---------------- Fin análisis --------------
  157.           Cadena[0]=' ';
  158.           Puntero=255;    // Como puntero se incrementa lo pongo a 255 ¡¡¡ Cahpuz !!!
  159.           }
  160.         Puntero++;  
  161.        }
  162.      }
  163.   else {
  164.       Serial.println(".CFG no existe.");
  165.     }
  166.   //--------------------------- Finalizado CONFIG.ARD, configuramos Ethernet...
  167.   Serial.println(x);            // Ver número de dispositivos hallados
  168.   myFile.close();
  169.   // Cerrar fichero SD
  170.   // Asignar la IP y la MAC al Arduino
  171.   Ethernet.begin(mac, ip, gateway, netmask);
  172.   server.begin();
  173.   // Udp.begin(localPort);  
  174.   // Una vez ajustada la tarjeta de Red, se puede comenzar el bucle de exploración
  175.   //-----------------------------------------------------------------------------------------------
  176. }
  177. //------------------------------------------------------------------------------------------------------
  178.  
  179. //--------------------------------------------------------------------------
  180. void loop(){
  181.    //-------------------------------------------------------------
  182.    // Recorrer la matriz de direcciones a explorar si toca hacerlo
  183.    //-------------------------------------------------------------
  184.    if((hora + INTERVAL) < millis()){
  185.        //=======================================================
  186.        // Verificar IP señalada por el puntero
  187.        // Solo si se ha superado el INTERVALO entre ping
  188.        ICMPPing ping(pingSocket);
  189.        ipahora[3] = (byte) equipo[y];
  190.        ipahora[2] = (byte)(equipo[y] >> 8);
  191.        ipahora[1] = (byte)(equipo[y] >> 16);
  192.        ipahora[0] = (byte)(equipo[y] >> 24);
  193.        ping(1, ipahora, Cadena);
  194.        Serial.println(Cadena);      
  195.        //--------------------------------------
  196.        // Tratamiento en caso de error de PING
  197.        //--------------------------------------      
  198.        if(Cadena[0]=='R' && Cadena[1]=='e' && Cadena[2]=='q'){
  199.           // Si hay error, incrementar el número de estado
  200.           if(estado[y]<5){ estado[y]++; }
  201.           // Se ha llegado al límite de reintentos???
  202.           if((estado[y]==5) && (FlagError[y]==false)){ // Si hay error repetido y es primera vez....
  203.              // Averiguar la fecha/hora actual ( I2C PCF8583 ? )
  204.              //----------------------------------------------------------------------------------
  205.              // Grabar SD
  206.              //-----------
  207.              myFile = SD.open("eventos.txt", FILE_WRITE);
  208.              // Si está disponible, escribir dato de ERROR en dispositivo
  209.              if(myFile){
  210.                 myFile.print("Error IP: ");
  211.                 myFile.print((byte)(equipo[y] >> 24));
  212.                 myFile.print('.');
  213.                 myFile.print((byte)(equipo[y] >> 16));
  214.                 myFile.print('.');
  215.                 myFile.print((byte)(equipo[y] >> 8));
  216.                 myFile.print('.');                      
  217.                 myFile.println((byte)equipo[y]);                                      
  218.                 myFile.close();
  219.                 }
  220.              //----------------------------------------------------------------
  221.              FlagError[y]=true;       // Evitar re-entrada en alarma....
  222.              }   // Hemos llegado a 5, marcamos error
  223.            }
  224.        //------------------------------------
  225.        // Tratamiento en caso PING correcto      
  226.        //------------------------------------
  227.        if(Cadena[0]=='R' && Cadena[1]=='e' && Cadena[2]=='p'){
  228.           // Ha habido errores anteriormente ??? , si es así decrementar
  229.           if(estado[y]>0){ estado[y]--; }                     // Decrementamos y chequeamos situación
  230.           if((estado[y]==0) && (FlagError[y]==true)){
  231.              // Averiguar la fecha/hora actual ( ver tratamiento socket)
  232.              // Enviar correo y marcar (anulación alarma)
  233.              //------------
  234.              // Grabar SD
  235.              //------------
  236.              myFile = SD.open("eventos.txt", FILE_WRITE);
  237.              // Si está disponible, escribir dato de ERROR en dispositivo
  238.              if(myFile){
  239.                 myFile.print("IP reactivada: ");
  240.                 myFile.print((byte)(equipo[y] >> 24));
  241.                 myFile.print('.');
  242.                 myFile.print((byte)(equipo[y] >> 16));
  243.                 myFile.print('.');
  244.                 myFile.print((byte)(equipo[y] >> 8));
  245.                 myFile.print('.');                      
  246.                 myFile.println((byte)equipo[y]);                                      
  247.                 myFile.close();
  248.                 }
  249.                //----------------------------------------------------------------              
  250.              FlagError[y]=false;       // Evitar re-entrada en finalarma....
  251.              }
  252.          }      
  253.        //-----------------------------------------------------------------------------------------------
  254.        y++;                      // Controlar puntero
  255.        if(y==x){ y=0;}           // Hemos alcanzado el final de la lista
  256.        hora=millis();            // Actualizar contador de intervalo
  257.        //------------------------------------------------------------------
  258.        // Nos preguntamos si hay que activar el aviso
  259.        boolean Bandera=false;
  260.        for(int w = 0; w < x; w++){ Bandera=(Bandera || FlagError[w]);} // Recorrer todos los dispositivos  
  261.        if(Bandera){ digitalWrite(Sirena, HIGH);} else {digitalWrite(Sirena, LOW);} // Ajustar 'Sirena'
  262.        //------------------------------------------------------------------
  263.        }                         // Bucle de intervalo para ping
  264.       //===============================================================================================
  265.       //===============================================================================================
  266.       // Entre PING y PING escuchar clientes... Web sencillo
  267.       EthernetClient client = server.available();
  268.       if (client){
  269.          // Petición http
  270.          boolean currentLineIsBlank = true;
  271.          while(client.connected()){
  272.             if(client.available()){
  273.                char c = client.read();
  274.                // Si hay una linea en blanco, la petición http ha terminado
  275.                // Es hora de contestar...
  276.                if (c == '\n' && currentLineIsBlank) {
  277.                    // Enviar respuesta estandar http
  278.                    client.println("HTTP/1.1 200 OK");
  279.                    client.println("Content-Type: text/html");
  280.                    client.println();
  281.                    //-----------------------------------------
  282.                    // Salidas relacionadas con la petición....
  283.                    //-----------------------------------------
  284.                    contentPrinter(client, KBCRA);
  285.                    contentPrinter(client, INICIO);
  286.                    for(int z = 0; z < x; z++) {    // Recorrer todos los dispositivos
  287.                        if(estado[z]==0){ contentPrinter(client, divverde); }
  288.                        if(estado[z]>4) { contentPrinter(client, divroja); }
  289.                        if((estado[z]>0) && (estado[z]<5)) { contentPrinter(client, divama); }
  290.                        client.print("Dispositivo: ");
  291.                        client.print((byte)(equipo[z] >> 24));
  292.                        client.print('.');
  293.                        client.print((byte)(equipo[z] >> 16));
  294.                        client.print('.');
  295.                        client.print((byte)(equipo[z] >> 8));
  296.                        client.print('.');                      
  297.                        client.print((byte)equipo[z]);                    
  298.                        client.print("</td></tr>");
  299.                        delay(1);
  300.                        }
  301.                    client.println("</TABLE>");
  302.                    break;
  303.                    }
  304.                 if (c == '\n') {
  305.                    // Comenzar una nueva línea
  306.                    currentLineIsBlank = true;
  307.                    }
  308.                 else if (c != '\r') {
  309.                    // you've gotten a character on the current line
  310.                    currentLineIsBlank = false;
  311.                    }
  312.                 }
  313.               }
  314.            // Dar tiempo al navegador para recibir los datos.
  315.            delay(1);
  316.            // Cerrar conexión
  317.            client.stop();
  318.        }
  319.       //***********************************************************************************************  
  320.       // delay(500);         // Sustituido por millis() al inicio del bucle
  321.      
  322.    //------------------------------------------------------------------------------------------  
  323. }
  324. //----------------------------------------------------------------------------------------------------
Attachments:
Download this file (Centinela.pdf)Centinela.pdf[Resumen proyecto Centinela TCP/IP para Arduino]105 Kb
hostgator coupon or play poker on party poker
Copyright 2011 Arduino - Centinela IP.
Joomla Templates by Wordpress themes free