От переводчика. Автор руководства медленно, но неуклонно ведёт заинтересованного читателя к пониманию работы веб-серверов на Arduino и всему из этого вытекающему: поняв как это работает, можно самостоятельно создавать очень интересные IoT проекты, функционал которых ограничен только вашей фантазией.
На этом уроке рассматривается динамическое отображение на веб-странице состояния кнопок и аналогового входа при помощи AJAX. Скетч из этого урока можно легко модифицировать для отображения любого (в разумных пределах, конечно) количества кнопок и аналоговых входов, а также доработать код для отображения других параметров контроллера Arduino.
На этом уроке мы рассмотрим отображение на веб-странице текущего состояния двух кнопок и одного аналогового входа контроллера Arduino.
JavaScript используется для выполнения периодических AJAX запросов к веб-серверу о состоянии кнопок и аналогового входа.
В следующем видео показана работа системы: с помощью AJAX обновляются данные о состоянии кнопки и аналогового входа, без перезагрузки всей страницы и каких-либо видимых артефактов.
❯ Принципиальная электрическая схема
На нижеприведенной схеме показано подключение кнопок (на пины D7 и D8) к контроллеру Arduino с платой Ethernet Shield. Потенциометр подключен к аналоговому входу A2 и при его помощи можно изменять напряжение на этом входе и отображать его текущее значение на веб-странице.
Принципиальная схема подключений кнопок и потенциометра к плате Arduino:

❯ Скетч
Скетч для этого урока — это модифицированная версия скетча из предыдущей статьи.
/*-------------------------------------------------------------- Скетч: eth_websrv_AJAX_IN Описание: Arduino веб-сервер, отображающий состояние двух кнопок и аналогового входа на веб-странице при помощи AJAX. Оборудование: контроллер Arduino Uno, плата Ethernet Shield, 2 кнопки, потенциометр. Программное обеспечение: среда разработки Arduino IDE Ссылки: - WebServer example by David A. Mellis and modified by Tom Igoe - Ethernet library documentation: http://arduino.cc/en/Reference/Ethernet - Learning PHP, MySQL & JavaScript by Robin Nixon, O'Reilly publishers Дата создания: 20 февраля 2013 Автор: W.A. Smith, http://startingelectronics.org --------------------------------------------------------------*/ #include <SPI.h> #include <Ethernet.h> byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(10, 0, 0, 20); // IP-адрес (нужно изменить на актуальный для вашей сети) EthernetServer server(80); String HTTP_req; // для хранения HTTP запроса void setup() { Ethernet.begin(mac, ip); server.begin(); Serial.begin(115200); pinMode(7, INPUT); // кнопка подключена к плате Arduino на пин D7 pinMode(8, INPUT); // кнопка подключена к плате Arduino на пин D8 } void loop() { EthernetClient client = server.available(); // try to get client if (client) { boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); // получаем очередной байт (символ) от клиента HTTP_req += c; // сохраняем символ HTTP запроса if (c == '\n' && currentLineIsBlank) { // Посылаем http заголовок client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: keep-alive"); client.println(); if (HTTP_req.indexOf("ajax_switch") > -1) { // AJAX запрос GetAjaxData(client); } else { // Посылка веб-страницы, содержащей JavaScript код и AJAX вызовы client.println("<!DOCTYPE html>"); client.println("<html>"); client.println("<head>"); client.println("<title>Arduino Web Page</title>"); client.println("<script>"); client.println("function GetSwitchAnalogData() {"); client.println( "nocache = \"&nocache=\" + Math.random() * 1000000;"); client.println("var request = new XMLHttpRequest();"); client.println("request.onreadystatechange = function() {"); client.println("if (this.readyState == 4) {"); client.println("if (this.status == 200) {"); client.println("if (this.responseText != null) {"); client.println("document.getElementById(\"sw_an_data\")\ .innerHTML = this.responseText;"); client.println("}}}}"); client.println( "request.open(\"GET\", \"ajax_switch\" + nocache, true);"); client.println("request.send(null);"); client.println("setTimeout('GetSwitchAnalogData()', 1000);"); client.println("}"); client.println("</script>"); client.println("</head>"); // Тело веб-страницы client.println("<body onload=\"GetSwitchAnalogData()\">"); client.println("<h1>Arduino AJAX Input</h1>"); client.println("<div id=\"sw_an_data\">"); client.println("</div>"); client.println("</body>"); client.println("</html>"); } // Выводим принятый HTTP запрос в Serial Serial.print(HTTP_req); HTTP_req = ""; break; } if (c == '\n') { currentLineIsBlank = true; } else if (c != '\r') { currentLineIsBlank = false; } } // end if (client.available()) } // end while (client.connected()) delay(1); client.stop(); } // end if (client) } // Определение состояния цифровых и аналогового входов и посылка данных о них в браузер void GetAjaxData(EthernetClient cl) { int analog_val; if (digitalRead(7)) { cl.println("<p>Switch 7 state: ON</p>"); } else { cl.println("<p>Switch 7 state: OFF</p>"); } if (digitalRead(8)) { cl.println("<p>Switch 8 state: ON</p>"); } else { cl.println("<p>Switch 8 state: OFF</p>"); } // Работа с аналоговым входом A2 analog_val = analogRead(2); cl.print("<p>Analog A2: "); cl.print(analog_val); cl.println("</p>"); }
Код веб-страницы
Вышеприведенный Arduino скетч создает и отправляет в браузер следующий HTML код:

Изменения в скетче (относительно версии из предыдущего урока)
Пины D7 и D8 контроллера Arduino настраиваются как входы в разделе setup() скетча.
pinMode(7, INPUT); // кнопка подключена к плате Arduino на пин D7 pinMode(8, INPUT); // кнопка подключена к плате Arduino на пин D8
Была переименована JavaScript функция, которая обрабатывает AJAX вызовы.
GetSwitchAnalogData()
Также была переименована Arduino функция, отвечающая на AJAX запросы.
void GetAjaxData(EthernetClient cl) {
Под заголовком H1 в HTML коде создан элемент div с идентификатором «sw_an_data». Сам тег div не отображается на странице, но служит местом для размещения JavaScript информации (данных о состоянии кнопок и аналогового входа, получаемых от Arduino).
Отправка запроса из браузера
JavaScript функция GetSwitchAnalogData() вызывается каждую секунду и каждую секунду отправляет GET запросы на Arduino веб-сервер.
Получение и обработка AJAX запроса на Arduino
Когда Arduino сервер определяет, что получил AJAX запрос, то вызывает функцию GetAjaxData(). Эта функция считывает состояние двух кнопок и отправляет их состояние (ON или OFF) в ответ браузеру. Эта функция также считывает значение аналогового входа A2 и отправляет эти данные браузеру.
Отображение данных в веб-браузере
Когда веб-браузер получает данные, запрошенные им у Arduino сервера, он просто вставляет их в тег div с идентификатором sw_an_data.
❯ От переводчика о 7-й части
Начинающим трудно понять работу этой системы потому, что она довольно «хитро» устроена — Javascript функция вызывает сама себя и при этом имеет участки кода, которые вступают в работу отложенно, только после после поступления ответа от сервера Arduino. А сервер Arduino, в свою очередь, не просто посылает HTML код веб-страницы, а «синтезирует» ещё и сам Javascript код, который потом будет взаимодействовать с самим Arduino сервером.
У начинающих, с непривычки, ум может зайти за разум от таких «наворотов». Для начала я бы посоветовал обратить внимание на следующий участок Arduino кода:
if (HTTP_req.indexOf("ajax_switch") > -1) { // AJAX запрос GetAjaxData(client); } else { // Посылка веб-страницы, содержащей JavaScript код и AJAX вызовы client.println("<!DOCTYPE html>");
Это один из «узловых» моментов всей логики работы системы, который нужно хорошо понимать: здесь веб-сервер определяет какой запрос к нему пришёл — если это «простой» GET запрос, то он выдаёт браузеру веб-страницу, а если этот AJAX запрос, то он выдаёт только небольшой ответ с AJAX данными о состоянии кнопок и аналогового входа.
Важно понимать: веб-страницу сервер выдаёт один раз в начале «сеанса», а затем (массово и беспрерывно) посылает только AJAX ответы на запросы им же сгенерированного Javascript кода внутри этой веб-страницы.
Лучше понять логику сетевого взаимодействия можно, если нажать (в браузере Firefox) клавишу F12 и выбрать вкладку «Network».
ссылка на оригинал статьи https://habr.com/ru/company/timeweb/blog/718518/

Добавить комментарий