От переводчика. На шестом уроке мы добрались до практически полезного кода — с его помощью можно создать работающий пример «бесшовного» автоматического взаимодействия между клиентом (страницей в веб-браузере) и Arduino веб-сервером, который передаёт данные о состоянии подключённого оборудования и внутренних переменных.
Тут нужно помнить, что это только «концептуальный» и базовый пример такого взаимодействия, максимально упрощённый для лучшего понимания начинающими сути самой технологии. Когда вы поймёте принцип, то далее сможете как угодно улучшать и модернизировать этот код. Например, уделить внимание его быстродействию и безопасности.
При помощи небольшой модификации HTML и JavaScript кода в скетче Arduino из предыдущей части этого руководства, можно заставить веб-сервер автоматически обновлять статус кнопки на веб-странице. Ручное инициирование AJAX запросов, которое использовалось в предыдущей части, больше не нужно.
Прежде чем продолжить знакомство с этой частью, вам нужно пройти предыдущую часть руководства и понять как работают AJAX запросы.
В следующем видеоролике показано, как веб-сервер Arduino автоматически обновляет состояние кнопки с помощью AJAX.
❯ Скетч AJAX веб-сервера Arduino
Используйте то же оборудование, что и в предыдущей части этого руководства:
- Контроллер Arduino Uno
- Плата Ethernet Shield
- Кнопка
- Резистор 10 кОм
- Соединительные провода
Кнопка подключается к плате Arduino/Ethernet Shield так, как показано на принципиальной схеме ниже. В изначальном состоянии вывод D3 контроллера подтянут к земле при помощи резистора 10 кОм (низкий потенциал, LOW или «0»), а после нажатия кнопки на вывод D3 подаётся высокий потенциал (HIGH или «1»).
В скетч eth_websrv_AJAX_switch из предыдущего урока нужно внести всего три изменения, чтобы автоматизировать AJAX вызовы, которые обновляют состояние кнопки на веб-странице.
Модифицированный скетч:
/*--------------------------------------------------------------
Скетч: eth_websrv_AJAX_switch_auto
Описание: Arduino веб-сервер, отображающий состояние кнопки на веб-странице при помощи AJAX. Состояние кнопки обновляется автоматически.
Оборудование: контроллер Arduino Uno, плата Ethernet Shield, кнопка.
Программное обеспечение: среда разработки 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
Дата создания: 13 февраля 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(3, INPUT); // кнопка подключена к плате Arduino на пин D3
}
void loop() {
EthernetClient client = server.available();
if (client) { // got 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 запрос состояния кнопки
GetSwitchState(client);
}
else {
// Посылка веб-страницы, содержащей JavaScript код и AJAX вызовы
client.println("<!DOCTYPE html>");
client.println("<html>");
// Заголовок веб-страницы и встроенный в неё код JavaScript
client.println("<head>");
client.println("<title>Arduino Web Page</title>");
client.println("<script>");
client.println("function GetSwitchState() {");
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(\"switch_txt\")\
.innerHTML = this.responseText;");
client.println("}}}}");
client.println(
"request.open(\"GET\", \"ajax_switch\" + nocache, true);");
client.println("request.send(null);");
client.println("setTimeout('GetSwitchState()', 1000);");
client.println("}");
client.println("</script>");
client.println("</head>");
// Тело веб-страницы
client.println("<body onload=\"GetSwitchState()\">");
client.println("<h1>Arduino AJAX Switch Status</h1>");
client.println(
"<p id=\"switch_txt\">Switch state: Not requested...</p>");
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)
} // loop
// Посылка данных о состоянии кнопки браузеру
void GetSwitchState(EthernetClient cl) {
if (digitalRead(3)) {
cl.println("Switch state: ON");
} else {
cl.println("Switch state: OFF");
}
}
Изменения в HTML и JavaScript коде
Ниже показаны изменения, внесенные в HTML файл, который скетч Arduino отправляет в веб-браузер (этот файл отправляется построчно с помощью функции client.println() в скетче).
Модифицированный код веб-страницы для работы автоматических AJAX запросов.
Код кнопки веб-страницы
Во-первых, удаляется код, который создает кнопку на веб-странице, поскольку эта кнопка больше не нужна. На изображении выше он закомментирован.
Вызов функции GetSwitchState()
Функция GetSwitchState(), которая раньше вызывалась при нажатии кнопки на веб-странице, теперь автоматически вызывается при загрузке страницы. Это достигается добавлением её вызова в тег body (<body onload=«GetSwitchState()»>).
Примечание переводчика: здесь речь идёт о JavaScript функции GetSwitchState(), а не об одноимённой Arduino функции, которая занимается определением состояния кнопки, подключённой к серверу.
Эта строка добавляется в HTML код веб-страницы при помощи вызова следующей функции:
client.println("<body onload=\"GetSwitchState()\">");
Ежесекундные AJAX вызовы
Если мы не предпримем специальных действий и не изменим код для осуществления периодических вызовов, функция GetSwitchState() будет вызвана только один раз при загрузке веб-страницы.
Следующая строка кода добавляется в конец функции GetSwitchState(), чтобы эта функция автоматически вызывалась каждую секунду:
setTimeout('GetSwitchState()', 1000);
Эта строка JavaScript кода вызывает функцию GetSwitchState() (саму себя) каждые 1000 миллисекунд (каждую секунду). Таким образом каждую секунду выполняется AJAX запрос, который получает информацию о состоянии кнопки и обновляет её на веб-странице.
Этот код добавляется на веб-страницу при помощи следующей строки в Arduino скетче:
client.println("setTimeout('GetSwitchState()', 1000);");
❯ От переводчика о 6-й части
Если в двух словах резюмировать произведённые автором руководства улучшения предыдущего скетча, то он просто добавил на страницу JavaScript код, который автоматически раз в секунду вызывает функцию GetSwitchState(), которая, в свою очередь, автоматически, без участия пользователя, производит AJAX запросы к Arduino серверу.
В результате мы получаем динамическую систему, которая «сама» обновляет данные на веб-странице и делает это без каких-либо видимых артефактов.
Этот пример реализует однонаправленную передачу информации (о состоянии кнопки) сервер — клиент, если сюда добавить ещё и передачу (пользовательских) данных от клиента к серверу, то мы получим полностью интерактивную и двунаправленную систему.
Часть 1, часть 2, часть 3, часть 4, часть 5.
fiego
Мне одному этот код глаз резанул?
Полный эквивалент и не режет глаз.
Ещё можно было б использвать уж fetch.