Arduino:Примеры/Web Net Setup

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин (Cubewriter) Контакты:</br>* Skype: cubewriter</br>* E-mail: cubewriter@gmail.com</br>* Максим Кузьмин на freelance.ru
Проверка/Оформление/Редактирование: Мякишев Е.А.


Браузерный интерфейс для настройки сети[1]

Этот пример показывает, как при помощи библиотеки Webduino создать браузерный интерфейс, позволяющий менять сетевые настройки Ethernet-модуля.

Код

/* Браузерный интерфейс для настройки сети (Webduino) 
Автор:     Маттиас Мадерер (Matthias Maderer)
Дата:      07.03.2013
Версия:    1.0.1
Сайт:      www.edvler-blog.de/arduino_networksetup_webinterface_with_eeprom

Это скетч-пример для Webduino!
Более подробно о Webduino можно почитать тут: https://github.com/sirleech/Webduino

Более подробно о EEPROMAnything.h смотрите на: http://playground.arduino.cc/Code/EEPROMWriteAnything
*/

/*
* Этот пример позволяет менять сетевые настройки на модуле Arduino
* Ethernet Shield при помощи браузерного интерфейса. То есть, он 
* представляет собой что-то вроде настроек роутера.
*  
* Можно менять следующие настройки:
* - MAC-адрес (MAC address)
* - IP-адрес (IP address)
* - Маску подсети (Subnet)
* - Сетевой шлюз (GW address)
* - DNS-сервер (DNS Server)
* - Порт веб-сервера (Webserver port)
* - Использование DHCP - ДА/НЕТ (Use DHCP). Чтобы узнать адрес, 
*   присвоенный через DHCP, при включении питания подключитесь ко всем 
*   последовательным портам на скорости 9600 бод.
* - интервал обновления DHCP (Renew interval for DHCP in minutes)
*
* Другие функции:
* - Показ статуса обновления DHCP (DHCP renew return code)
* - Показ времени последнего обновления DHCP (DHCP last renew timestamp)
* - Показ времени работы Arduino (Uptime)
* - Показ объема используемой RAM-памяти (RAM)
* 
* Вы также можете задать настройки по умолчанию. Они будут 
* использоваться, если не задано вообще никаких настроек. 
* См. функцию set_EEPROM_Default().
*
* Также есть возможность подключиться к кнопке RESET. Если нажать 
* на нее, это восстановит настройки по умолчанию.
* Смотрите строчку с #define RESET_PIN.
*
* Все настройки хранятся в EEPROM. Это значит, что они постоянные.
* Краткое описание смотрите на http://arduino.cc/en/Reference/EEPROM 
*
* По умолчанию IP-адрес указан как http://192.168.0.111/.
* Не забудьте поменять IP-адрес Ethernet-модуля на более подходящий 
* (например, на IP-адрес 192.168.0.1, маска подсети 255.255.255.0)!
*
* Чтобы открыть настройки, введите в браузер следующий URL:
* http://192.168.0.111/setupNet.html
*
* Имейте в виду, что никаких проверок на ошибки в скетче нет!
* Поэтому если вводимые вами данные содержат ошибки, то никаких 
* уведомлений и предупреждений показано не будет.
*
* Ресурсы:
* Объем HTML-сайта, содержащегося в этом скетче, в скомпилированном 
* виде составляет около 27 байт. При этом используется около 2000 байт 
* SRAM-памяти. На маленьких Arduino могут возникнуть проблемы. 
* Я тестировал его на MEGA 2560.
*
* БАГИ:
* - После загрузки скетча Arduino станет недоступна, поэтому 
*   перезагрузите ее. 
*/


#define WEBDUINO_FAVICON_DATA "" // иконки нет
//#define DEBUG  // раскомментируйте эту строчку, если хотите видеть отладочные данные
#define USE_SYSTEM_LIBRARY // закомментируйте, если хотите сэкономить
                           // немного места (около 1 байта); 
                           // в результате не будут отображаться время 
                           // работы Arduino и объем используемой RAM
#define SERIAL_BAUD 9600

#include "SPI.h" 
#include "avr/pgmspace.h" 
#include "Ethernet.h"
#include "WebServer.h"


/* #############################################################################################################################################################
* Код для всего, что связано с EEPROM
* 
*/
#include <EEPROM.h>
#include "EEPROMAnything.h"

#define RESET_PIN 40	// Подключите кнопку сброса к этому контакту. Нажатие на эту кнопку восстановит настройки по умолчанию.

/* Структура, которая будет храниться в EEPROM. 
*  Функции для записи и чтения struct смотрите в "EEPROMAnything.h".
*/
struct config_t
{
    byte config_set;
    byte use_dhcp;
    byte dhcp_refresh_minutes;
    byte mac[6];
    byte ip[4];
    byte gateway[4];
    byte subnet[4];
    byte dns_server[4];
    unsigned int webserverPort;
} eeprom_config;

/** 
* Функция set_EEPROM_Default().
*
* Настройки по умолчанию. 
* Они используются, если не задано никаких настроек или если нажата кнопка сброса.
*/
void set_EEPROM_Default() {
    eeprom_config.config_set=1;  // тут ничего не меняем! эта строчка используется, чтобы проверить, заданы ли какие-нибудь настройки
  
    eeprom_config.use_dhcp=0;  // по умолчанию используем DHCP
    eeprom_config.dhcp_refresh_minutes=60; // обновляем DHCP каждые 60 минут
  
    // Задаем MAC-адрес по умолчанию. В данном случае это DE:AD:BE:EF:FE:ED
    eeprom_config.mac[0]=0xDE;  
    eeprom_config.mac[1]=0xAD;
    eeprom_config.mac[2]=0xBE;
    eeprom_config.mac[3]=0xEF;
    eeprom_config.mac[4]=0xFE;
    eeprom_config.mac[5]=0xED;
    
    // задаем для Arduino IP-адрес по умолчанию. В данном случае это 192.168.0.111
    eeprom_config.ip[0]=192;
    eeprom_config.ip[1]=168;
    eeprom_config.ip[2]=0;
    eeprom_config.ip[3]=111;
  
    // Задаем сетевой шлюз по умолчанию. В данном случае это 192.168.0.254
    eeprom_config.gateway[0]=192;
    eeprom_config.gateway[1]=168;
    eeprom_config.gateway[2]=0;
    eeprom_config.gateway[3]=254;
    
    // Задаем маску подсети по умолчанию. В данном случае это 255.255.255.0
    eeprom_config.subnet[0]=255;
    eeprom_config.subnet[1]=255;
    eeprom_config.subnet[2]=255;
    eeprom_config.subnet[3]=0;

    // задаем DNS-сервер по умолчанию. В данном случае это 192.168.0.254
    eeprom_config.dns_server[0]=192;
    eeprom_config.dns_server[1]=168;
    eeprom_config.dns_server[2]=0;
    eeprom_config.dns_server[3]=254;

    // задаем порт веб-сервера по умолчанию. В данном случае это 80 порт
    eeprom_config.webserverPort=80;
    
    #ifdef DEBUG
      Serial.println("Config reset");  //  "Сброс настроек"
    #endif 
}

/**
* Функция read_EEPROM_Settings.
* Эта функция используется, чтобы прочесть настройки EEPROM при запуске Arduino.
*
* Краткое описание:
* - Выставляет контакт, к которому подключена кнопка Reset, 
*   в положение INPUT, а затем активирует подтягивающие резисторы.
* - Загружает и сохраняет данные из EEPROM в структуру (struct) eeprom_config.
* - Проверяет, загружены ли настройки и нажата ли кнопка Reset. 
*   Если какое-то из этих условий соблюдено, она выставляет 
*   настройки по умолчанию.
*/
void read_EEPROM_Settings() {
  pinMode(RESET_PIN, INPUT);
  digitalWrite(RESET_PIN, HIGH);
  
  // считываем текущие настройки:
  EEPROM_readAnything(0, eeprom_config);
  
  // проверяем, загружены ли настройки и нажата ли кнопка Reset:
  if (eeprom_config.config_set != 1 || digitalRead(RESET_PIN) == LOW) {
    // выставляем настройки по умолчанию:
    set_EEPROM_Default();
    
    // записываем настройки на EEPROM:
    EEPROM_writeAnything(0, eeprom_config);
  } 
}

/**
* Функция print_EEPROM_Settings().
*
* Эта функция используется для отладки настроек. Она через 
* последовательную коммуникацию выводит данные о текущих настройках 
* на монитор порта.
*/
#ifdef DEBUG
void print_EEPROM_Settings() {
    Serial.print("IP: ");  // "IP-адрес: "
    for(int i = 0; i<4; i++) {
      Serial.print(eeprom_config.ip[i]);
      if (i<3) {
        Serial.print('.');
      }
    }
    Serial.println();
  
    Serial.print("Subnet: ");  // "Маска подсети: "
    for(int i = 0; i<4; i++) {
      Serial.print(eeprom_config.subnet[i]);
      if (i<3) {
        Serial.print('.');
      }
    }
    Serial.println();
    
    Serial.print("Gateway: ");  // "Сетевой шлюз: "
    for(int i = 0; i<4; i++) {
      Serial.print(eeprom_config.gateway[i]);
      if (i<3) {
        Serial.print('.');
      }
    }
    Serial.println();

    Serial.print("DNS Server: ");  // "DNS-сервер: "
    for(int i = 0; i<4; i++) {
      Serial.print(eeprom_config.dns_server[i]);
      if (i<3) {
        Serial.print('.');
      }
    }
    Serial.println();
    
    Serial.print("MAC: ");  // "Mac-адрес: "
    for (int a=0;a<6;a++) {
      Serial.print(eeprom_config.mac[a],HEX);
      if(a<5) {
        Serial.print(":");
      }
    }
    Serial.println();
    
    Serial.print("Webserver Port: ");  // "Порт веб-сервера: "
    Serial.println(eeprom_config.webserverPort);
    
    Serial.print("USE DHCP: ");  // "Использование DHCP: "
    Serial.println(eeprom_config.use_dhcp);
    
    Serial.print(" DHCP renew every ");  // " Обновление DHCP каждые: "
    Serial.print(eeprom_config.dhcp_refresh_minutes);
    Serial.println(" minutes");  // " минут"
    
    Serial.print("Config Set: ");  // "Настройки: "
    Serial.println(eeprom_config.config_set);

}
#endif

// #############################################################################################################################################################


/* ЗАПУСК СОЕДИНЕНИЯ #######################################################################################################################################
* Код для настройки сетевого соединения
*/
unsigned long last_dhcp_renew;
byte dhcp_state;

/**
* Функция renewDHCP().
* Обновляем аренду DHCP через заданный промежуток времени.
* 
* Краткое описание:
* - Если interval содержит значение «0», выставляет его на «1».
* - Проверяет, не закончилось ли время в интервале, и если закончилось, обновляет аренду DHCP.
*/
void renewDHCP(int interval) {
  unsigned long interval_millis = interval * 60000;

  if (interval == 0 ) {
     interval = 1; 
  }
  if (eeprom_config.use_dhcp==1) {
    if((millis() - last_dhcp_renew) >  interval_millis) {
      last_dhcp_renew=millis();
      dhcp_state = Ethernet.maintain();
    }
  }
}


/**
* Функция setupNetwork() 
* Эта функция используется, чтобы настроить сеть в соответствии 
* с настройками, хранящимися в EEPROM.
*
*   Краткое описание:
* - Сначала считывает настройки, находящиеся в EEPROM.
* - Показывает текущие Ethernet-настройки.
* - Проверяет, используется ли DHCP. Если нет, создает экземпляры 
*   IPAddress для IP-адреса (ip), сетевого шлюза (gateway), маски 
*   подсети (subnet) и DNS-сервера (dns_server). Затем вызывает 
*   функцию Ethernet.begin() со всеми этими параметрами:
*   Ethernet.begin(mac, ip, dns_server, gateway, subnet);. 
* - Если DHCP используется, тоже вызываем Ethernet.begin(), но 
*   используем только MAC-адрес (mac), а затем показываем IP через 
*   монитор порта.
*/
void setupNetwork() {
  read_EEPROM_Settings();
  
  #ifdef DEBUG
   print_EEPROM_Settings();
  #endif

 // byte mac[] = { eeprom_config.mac[0], eeprom_config.mac[1], eeprom_config.mac[2], eeprom_config.mac[3], eeprom_config.mac[4], eeprom_config.mac[5] };  
  
  if (eeprom_config.use_dhcp != 1) {
    IPAddress ip(eeprom_config.ip[0], eeprom_config.ip[1], eeprom_config.ip[2], eeprom_config.ip[3]);                                               
    IPAddress gateway (eeprom_config.gateway[0],eeprom_config.gateway[1],eeprom_config.gateway[2],eeprom_config.gateway[3]);                      
    IPAddress subnet  (eeprom_config.subnet[0], eeprom_config.subnet[1], eeprom_config.subnet[2], eeprom_config.subnet[3]);  
    IPAddress dns_server  (eeprom_config.dns_server[0], eeprom_config.dns_server[1], eeprom_config.dns_server[2], eeprom_config.dns_server[3]);
    Ethernet.begin(eeprom_config.mac, ip, dns_server, gateway, subnet);
  } else {
    if (Ethernet.begin(eeprom_config.mac) == 0) {
      Serial.print("Failed to configure Ethernet using DHCP");  //  "Не удалось настроить Ethernet при помощи DHCP"
    }
    Serial.println(Ethernet.localIP());
  }
}
// ЗАВЕРШЕНИЕ СОЕДИНЕНИЯ #########################################################################################################################################

/* Секция для веб-сервера #######################################################################################################################################
* Код для веб-сервера
*/

#ifdef USE_SYSTEM_LIBRARY
#include "system.h"
System sys;
#endif

/* Сохраняем все строки во FLASH-памяти, чтобы освободить 
 * ресурсы SRAM-памяти. Функция P() – из библиотеки Arduino.
 */
P(Page_start) = "<html><head><title>Web_EEPROM_Setup</title></head><body>\n";
P(Page_end) = "</body></html>";

P(Http400) = "HTTP 400 - BAD REQUEST";
P(Index) = "<h1>index.html</h1><br>This is your main site!<br>The code is found in the indexHTML() function.<br>You can add more sites if you need. Please see the well documented source code.<br><br>Use the following link to setup the network.<br><a href=\"setupNet.html\">NETWORK SETUP</a>";
//  "Это главная страница. Ее код находится в функции indexHTML(). По желанию можно добавить больше страниц (см. исходный код). Для настройки сети используйте следующую ссылку: setupNet.html\"

P(Form_eth_start) = "<FORM action=\"setupNet.html\" method=\"get\">";
P(Form_end) = "<FORM>";
P(Form_input_send) = "<INPUT type=\"submit\" value=\"Set config\">";

P(Form_input_text_start) = "<input type=\"text\" name=\"";
P(Form_input_value)  = "\" value=\"";
P(Form_input_size2) = "\" maxlength=\"2\" size=\"2";
P(Form_input_size3) = "\" maxlength=\"3\" size=\"3";
P(Form_input_end) = "\">\n";

P(MAC) = "MAC address: ";  //  "MAC-адрес: "
P(IP) = "IP address: ";  //  "IP-адрес: "
P(SUBNET) = "Subnet: ";  //  "Маска подсети: "
P(GW) = "GW address: ";  //  "Адрес сетевого шлюза: "
P(DNS_SERVER) = "DNS server: ";  //  "DNS-сервер: "
P(WEB_PORT) = "Webserver port (1-65535): ";  //  "Порт веб-сервера (1-65535): "
P(DHCP_ACTIVE) = "Use DHCP: ";  //  "Использование DHCP: "
P(DHCP_REFRESH) = "Renew interval for DHCP in minutes (1 - 255): ";  //  "Интервал обновления для DHCP в минутах (1-255): "

P(Form_cb) = "<input type=\"radio\" name=\"23\" value=\"";
P(Form_cb_checked) = " checked ";
P(Form_cb_on) = ">On";
P(Form_cb_off) = ">Off";

P(br) = "<br>\n";

P(table_start) = "<table>";
P(table_tr_start) = "<tr>";
P(table_tr_end) = "</tr>";
P(table_td_start) = "<td>";
P(table_td_end) = "</td>";
P(table_end) = "</table>";

P(Config_set) = "<font size=\"6\" color=\"red\">New configuration stored! <br>Please turn off and on your Arduino or use the reset button!</font><br>";  //  "Новые настройки сохранены. Пожалуйста, включите и выключите Arduino или нажмите на кнопку Reset."

P(DHCP_STATE_TIME) = "DHCP last renew timestamp (sec)";  //  "Время последнего обновления DHCP (сек)"
P(DHCP_STATE) = "DHCP renew return code (sec)";  //  "Статус обновления DHCP (сек)"

P(UPTIME) = "Uptime: ";  //  "Время работы Arduino"

#ifdef USE_SYSTEM_LIBRARY
P(RAM_1) = "RAM (byte): ";
P(RAM_2) = " free of ";
#endif

/* Создаем указатель к экземпляру веб-сервера. */
WebServer * webserver;


/**
* Функция indexHTML()
* Эта функция используется для отправки клиенту index.html.
*/
void indexHTML(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  /* эта строчка отправляет браузеру стандартное сообщение, что запрос был успешным.*/
  server.httpSuccess();

  /* Если получили GET или POST, то показываем данные.
     Если получили HEAD request, останавливаемся после 
     показа заголовков */ 
   if (type == WebServer::HEAD)
    return;
    
  server.printP(Page_start);
  
  server.printP(Index);
  
  server.printP(Page_end);
    
}

/**
* Функция setupNetHTML()
* Эта функция отправляет клиенту setupNet.html
*
* Краткое описание:
* - Отправляет ответ «200 OK».
* - Если параметры GET присутствуют, присваивает их соответствующим переменным в структуре (struct) eeprom_config.
* - Показывает настройки.
*
* Параметры – это простые числа. Название параметра конвертируется 
* в данные типа int при помощи функции atoi(). Это позволяет 
* оптимизировать код в настройке адресов IP и MAC.
*/ 
#define NAMELEN 5
#define VALUELEN 7
void setupNetHTML(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  URLPARAM_RESULT rc;  
  char name[NAMELEN];  
  char value[VALUELEN];
  boolean params_present = false;
  byte param_number = 0;

  /* эта строчка отправляет браузеру стандартное сообщение, что запрос был успешным.*/
  server.httpSuccess();

  /* Если получили GET или POST, то показываем данные.
     Если получили запрос HEAD, останавливаемся после 
     показа заголовков */ 
  if (type == WebServer::HEAD)
    return;

  server.printP(Page_start);

  // проверяем параметры:
  if (strlen(url_tail)) {
    while (strlen(url_tail)) {
      rc = server.nextURLparam(&url_tail, name, NAMELEN, value, VALUELEN);
      if (rc != URLPARAM_EOS) {
        params_present=true;
        // отладочная информация для параметров:
        #ifdef DEBUG
        Serial.print(name);
        server.print(name);
        Serial.print(" - "); 
        server.print(" - ");
        Serial.println(value);
        server.print(value);
        server.print("<br>");
        #endif
        
        
        param_number = atoi(name);
 
        // считываем MAC-адрес:
        if (param_number >=0 && param_number <=5) {
          eeprom_config.mac[param_number]=strtol(value,NULL,16);
        }
    
        // считываем IP-адрес:
        if (param_number >=6 && param_number <=9) {
          eeprom_config.ip[param_number-6]=atoi(value);
        }
    
        // считываем маску подсети:
        if (param_number >=10 && param_number <=13) {
          eeprom_config.subnet[param_number-10]=atoi(value);
        }
    
        // считываем сетевой шлюз:
        if (param_number >=14 && param_number <=17) {
          eeprom_config.gateway[param_number-14]=atoi(value);
        }
    
        // считываем DNS-сервер:
        if (param_number >=18 && param_number <=21) {
          eeprom_config.dns_server[param_number-18]=atoi(value);
        }
        
        // считываем порт веб-сервера:
        if (param_number == 22) {
          eeprom_config.webserverPort=atoi(value);
        }
        
        // считываем, используется DHCP или нет:
        if (param_number == 23) {
          eeprom_config.use_dhcp=atoi(value);
        }
    
        // считываем интервал обновления DHCP:
        if (param_number == 24) {
          eeprom_config.dhcp_refresh_minutes=atoi(value);
        } 
      }
    }
    EEPROM_writeAnything(0, eeprom_config);
  }

  // показываем форму:
  server.printP(Form_eth_start);
  
  if(params_present==true) {
     server.printP(Config_set);
  }
    
  server.printP(table_start);
  
  // показываем текущий MAC-адрес:
  server.printP(table_tr_start);
  server.printP(table_td_start);
  server.printP(MAC);
  server.printP(table_td_end);
  server.printP(table_td_start);
  for (int a=0;a<6;a++) {
    server.printP(Form_input_text_start);
    server.print(a);
    server.printP(Form_input_value);
    server.print(eeprom_config.mac[a],HEX);
    server.printP(Form_input_size2);    
    server.printP(Form_input_end);
  }
  server.printP(table_td_end);
  server.printP(table_tr_end);

  // показываем текущий IP-адрес:
  server.printP(table_tr_start);
  server.printP(table_td_start);
  server.printP(IP);
  server.printP(table_td_end);
  server.printP(table_td_start);    
  for (int a=0;a<4;a++) {
    server.printP(Form_input_text_start);
    server.print(a+6);
    server.printP(Form_input_value);
    server.print(eeprom_config.ip[a]);
    server.printP(Form_input_size3);
    server.printP(Form_input_end);
  }
  server.printP(table_td_end);
  server.printP(table_tr_end);
  

  // показываем текущую маску подсети:
  server.printP(table_tr_start);
  server.printP(table_td_start);
  server.printP(SUBNET);
  server.printP(table_td_end);
  server.printP(table_td_start); 
  for (int a=0;a<4;a++) {
    server.printP(Form_input_text_start);
    server.print(a+10);
    server.printP(Form_input_value);
    server.print(eeprom_config.subnet[a]);
    server.printP(Form_input_size3);
    server.printP(Form_input_end);
  }
  server.printP(table_td_end);
  server.printP(table_tr_end);

  // показываем текущий сетевой шлюз:
  server.printP(table_tr_start);
  server.printP(table_td_start);
  server.printP(GW);
  server.printP(table_td_end);
  server.printP(table_td_start); 
  for (int a=0;a<4;a++) {
    server.printP(Form_input_text_start);
    server.print(a+14);
    server.printP(Form_input_value);
    server.print(eeprom_config.gateway[a]);
    server.printP(Form_input_size3);
    server.printP(Form_input_end);
  }
  server.printP(table_td_end);
  server.printP(table_tr_end);

  // показываем текущий DNS-сервер:
  server.printP(table_tr_start);
  server.printP(table_td_start);
  server.printP(DNS_SERVER);
  server.printP(table_td_end);
  server.printP(table_td_start); 
  for (int a=0;a<4;a++) {
    server.printP(Form_input_text_start);
    server.print(a+18);
    server.printP(Form_input_value);
    server.print(eeprom_config.dns_server[a]);
    server.printP(Form_input_size3);
    server.printP(Form_input_end);
  }
  server.printP(table_td_end);
  server.printP(table_tr_end);

  
  // показываем текущий порт веб-сервера:
  server.printP(table_tr_start);
  server.printP(table_td_start);
  server.printP(WEB_PORT);
  server.printP(table_td_end);
  server.printP(table_td_start);
  server.printP(Form_input_text_start);
  server.print(22);
  server.printP(Form_input_value);
  server.print(eeprom_config.webserverPort);
  server.printP(Form_input_end);
  server.printP(table_td_end);
  server.printP(table_tr_end);
  
  // показываем текущие настройки DHCP:
  server.printP(table_tr_start);
  server.printP(table_td_start);
  server.printP(DHCP_ACTIVE);
  server.printP(table_td_end);
  server.printP(table_td_start);
  server.printP(Form_cb);
  server.print("0\"");
   if(eeprom_config.use_dhcp != 1) {
    server.printP(Form_cb_checked);
  }
  server.printP(Form_cb_off);   
  
  server.printP(Form_cb);
  server.print("1\"");
  if(eeprom_config.use_dhcp == 1) {
    server.printP(Form_cb_checked);
  }
  server.printP(Form_cb_on);   
  server.printP(table_td_end);
  server.printP(table_tr_end);
  
  // показываем последнее время обновления DHCP:
  server.printP(table_tr_start);
  server.printP(table_td_start);
  server.printP(DHCP_REFRESH);
  server.printP(table_td_end);
  server.printP(table_td_start);
  server.printP(Form_input_text_start);
  server.print(24);
  server.printP(Form_input_value);
  server.print(eeprom_config.dhcp_refresh_minutes);
  server.printP(Form_input_size3);
  server.printP(Form_input_end);
  server.printP(table_td_end);
  server.printP(table_tr_end);

  // показываем статус DHCP:
  if(eeprom_config.use_dhcp == 1) {
    server.printP(table_tr_start);
    server.printP(table_td_start);	
    server.printP(DHCP_STATE);
    server.printP(table_td_end);
    server.printP(table_td_start);
    server.print(dhcp_state);
    server.printP(table_td_end);
    server.printP(table_tr_end);
	 
    server.printP(table_tr_start);
    server.printP(table_td_start);	
    server.printP(DHCP_STATE_TIME);
    server.printP(table_td_end);
    server.printP(table_td_start);
    server.print(last_dhcp_renew/1000);
    server.printP(table_td_end);
    server.printP(table_tr_end);
  }
  
  #ifdef USE_SYSTEM_LIBRARY
  // показываем время работы Arduino:
  server.printP(table_tr_start);
  server.printP(table_td_start);	
  server.printP(UPTIME);
  server.printP(table_td_end);
  server.printP(table_td_start);
  server.print(sys.uptime());
  server.printP(table_td_end);
  server.printP(table_tr_end); 

  server.printP(table_tr_start);
  server.printP(table_td_start);
  server.printP(RAM_1);	
  server.print(sys.ramFree());
  server.printP(RAM_2);
  server.print(sys.ramSize());
  server.printP(table_td_end);
  server.printP(table_tr_end); 
  #endif
  
  server.printP(table_end);
  
  // показываем кнопку отправки:
  server.printP(Form_input_send);    
  server.printP(Form_end);
    
  server.printP(Page_end);

}

/**
* Функция errorHTML()
* Эта функция вызывается всякий раз, когда запрашивается 
* несуществующая страница. Она отправляет HTTP-заголовок 
* «400 Bad Request» и то же самое текстом.
*/
void errorHTML(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  /* Эта строчка отправляет браузеру стандартный HTTP-заголовок «HTTP 400 Bad Request» */
  server.httpFail();

  /* Если получили GET или POST, то показываем данные.
     Если получили запрос HEAD, останавливаемся после 
     показа заголовков */ 
  if (type == WebServer::HEAD)
    return;
    
  server.printP(Http400);
  
  server.printP(Page_end);
}

// ЗАВЕРШАЮЩИЙ КОД ######################################################################################################################################################

/*
* Функция setup()
* Эта функция вызывается всякий раз, когда включается Arduino.
*/
void setup()
{
  Serial.begin(SERIAL_BAUD);
  
  /* Инициализируем Ethernet-модуль с настройками из EEPROM */
  delay(200); // небольшая задержка, чтобы система успела сделать все свои дела
  setupNetwork();
  delay(200); // аналогично
  
  #define PREFIX ""
  webserver = new WebServer(PREFIX, eeprom_config.webserverPort);

  /* задаем команду, которая будет вызываться по умолчанию, 
  /* когда пользователь будет запрашивать доступ к корню сервера 
  */ 
  webserver->setDefaultCommand(&indexHTML);

  /* задаем команду, которая будет вызываться по умолчанию, 
  /* когда пользователь запросит доступ к несуществующей странице 
  */ 
  webserver->setFailureCommand(&errorHTML);

  /* запускаем команду indexHTML, если пользователь пытается загрузить страницу /index.html */
  webserver->addCommand("index.html", &indexHTML);

  /* Показываем форму сетевых настроек. Сами настройки хранятся в EEPROM */
  webserver->addCommand("setupNet.html", &setupNetHTML);

  /* Запускаем веб-сервер */
  webserver->begin();
}

/**
* Функция loop()
* Будет работать вечно...
* 
* Краткое описание:
* - Обновляет аренду DHCP
* - Обслуживает веб-клиентов
*
*/
void loop()
{
  // обновляем аренду DHCP:
  renewDHCP(eeprom_config.dhcp_refresh_minutes);

  char buff[200];
  int len = 200;

  /* Вечно обрабатываем входящие соединения (одновременно может обрабатываться только одно соединение) */
  webserver->processConnection(buff, &len);
}

См.также

Внешние ссылки