К книге
Цифровая электроника для начинающихСтраница 10
56%
Страница 10
10

При запуске программы данные будут выведены в Serial Monitor:

Самостоятельная работа: По аналогии с вышенаписанным, получить число просмотров для видеоролика на youtube. Для этого воспользоваться следующей функцией из Google API:

https://www.googleapis.com/youtube/v3/videos?part=statistics&id=ID&key=XXXX

(здесь ID - это идентификатор видеоролика, XXXX - Google API Key)

Функция вернет json, который выглядит примерно так:

{

"kind": "youtube#videoListResponse",

"etag": "\"_gJQceDMxJ8gP-8T2HLXUoURK8c/mISbZAYZi79hOI4WFXbLXPUphmg\"",

"items": [

{

"kind": "youtube#video",

"etag": "\"_gJQceDMxJ8gP-8T2HLXUoURK8c/PoZyfbkQEtIkGNfjDsAafjr_R08\"",

"id": "CizKnuwvXXg",

"statistics": {

"viewCount": "184277",

"likeCount": "8585",

"dislikeCount": "212",

"favoriteCount": "0",

"commentCount": "1349"

}

}

]

}

Необходимо исправить в коде обработку json, чтобы получить интересующие нас поля.

При желании можно вывести данные на OLED-дисплей, сделав автономно работающее устройство.

3.8 Запускаем собственный Web-сервер

Мы уже умеем получать и обрабатывать данные с различных серверов. Настала пора двигаться дальше - мы запустим на ESP32 собственный сервер. Его можно будет открыть в браузере, введя IP-адрес платы, подключенной к WiFi-сети. А если настроить статический IP-адрес и перенаправление портов на маршрутизаторе, то можно будет получить доступ к нашему серверу через Интернет, с любой точки земного шара!

Итак, приступим. Для использования ESP32 в качестве сервера мы будем использовать уже готовый класс WiFiServer. Он “слушает” входящие соединения, а его единственным параметром является номер порта (мы будем использовать порт 8000).

Код сервера приведен ниже.

#include <WiFi.h>

const char* ssid = "TP-LINK_AB11";

const char* password = "12345678";

WiFiServer server(8000);

void setup()

{

Serial.begin(115200);

delay(10);

// We start by connecting to a WiFi network

Serial.print("Connecting to "); Serial.println(ssid);

while (WiFi.status() != WL_CONNECTED) {

delay(500);

WiFi.begin(ssid, password);

Serial.print(".");

}

Serial.println("");

Serial.println("IP address: ");

Serial.println(WiFi.localIP());

server.begin();

}

void loop() {

WiFiClient client = server.available(); // Получение входящего “клиента”

if (client) {

Serial.println("New Client.");

String currentLine = "";

while (client.connected()) {

if (client.available()) { // Есть непрочитанные данные

char c = client.read(); // читаем 1 байт

Serial.write(c);

if (c == '\n') { // Символ перевода строки

// 2 пустые строки - признак конца запроса, посылаем ответ

if (currentLine.length() == 0) {

client.println("HTTP/1.1 200 OK");

client.println("Content-type:text/html");

client.println();

client.print("<html><head> <title>ESP32 Server</title> </head>”);

client.print("<body>Hello world</body> </html>");

client.println();

break;

} else {

// Очистить строку

currentLine = "";

}

} else if (c != '\r') { // if you got anything else but a carriage return character,

currentLine += c; // add it to the end of the currentLine

}

}

}

// Закрыть соединение:

client.stop();

}

}

Рассмотрим код подробнее.

Мы создаем объект WiFiServer, который “слушает” входящие соединения на определенном порту (в нашем случае 8000). Тот, кто подсоединяется к нашему серверу, называется “клиентом”. За взаимодействие с ним отвечает класс WiFiClient.

Далее, мы побайтно читаем данные с помощью вызова функции client.read(), и складываем данные в строку currentLine. К примеру, строка запроса может быть такой - GET / HTTP/1.1, здесь “GET” это тип запроса, “/” - это адрес главной страницы, 1.1 - тип стандарта. Но сам запрос мы не анализируем, а просто посылаем всегда один и тот же ответ - заглавную страницу с HTML-текстом “Hello world”. Строки типа “HTTP/1.1 200 OK” - это служебная информация, которая нужна браузеру (клиенту) чтобы понять, что мы ответили (200 - это код возврата OK, говорящий о том что все нормально). Строка “Content-type:text/html” говорит клиенту о том, что возвращаться будет HTML-страница.

Наша страница имеет следующий вид:

<html>

<head>

<title>ESP32 Server</title>

</head>

<body>Hello world</body>

</html>

Как можно видеть, она содержит “заголовок” (header) и “тело” (body). Заголовок содержит тег title - в нем хранится строка, которая будет выведена в заголовке браузера.

Итак, компилируем данный код, загружаем его в плату, и в Serial Monitor смотрим какой IP-адрес получила ESP32 при доступе к WiFi-сети. Вводим этот адрес в строку браузера, не забыв указать номер порта, например http://192.168.0.104:8000.

Все готово! Через небольшое время ожидания мы видим страницу браузера с нашим текстом Hello world. Обращаем внимание на то, что и заголовок и текст соответствуют тому, что мы ввели.

Самостоятельная работа: изучить команды HTML, поэкспериментировать с разными вариантами разметки и форматирования текста.

3.9 Управляем светодиодом через Web

Мы уже умеем запустить свой Web-сервер, но пока он не делает ничего полезного, кроме отображения Hello world. Исправим это упущение, и сделаем кнопки для управления светодиодом через веб браузер.

Принцип простой - мы добавим в HTML-страницу 2 ссылки, нажатие которых и будет отслеживаться сервером.

Новая HTML-страница будет выглядеть так:

<html>

<head><title>ESP32 Server</title></head>

<body>

Turn <a href=\"/H\">LED ON</a><br>

Turn <a href=\"/L\">LED OFF</a><br>

</body>

</html>

В HTML-странице можно видеть 2 ссылки с значением адреса /H и /L, когда пользователь нажмет на них, на сервер будет отправлен GET-запрос с соответствующим адресом. Это нам и нужно.

Код программы целиком приведен ниже.

#include <WiFi.h>

const char* ssid = "TP-LINK_AB11";

const char* password = "12345678";

int ledPin = 2;

WiFiServer server(8000);

void setup() {

Serial.begin(115200);

pinMode(ledPin, OUTPUT);

delay(10);

Serial.print("Connecting to ");

Serial.println(ssid);

while (WiFi.status() != WL_CONNECTED) {

delay(500);

WiFi.begin(ssid, password);

Serial.print(".");

}

Serial.println("WiFi connected.");

Serial.println("IP address: ");

Serial.println(WiFi.localIP());

server.begin();

}

void loop(){

WiFiClient client = server.available();

if (client) {

Serial.println("New Client.");

String currentLine = "";

while (client.connected()) {

if (client.available()) {

char c = client.read();

if (c == '\n') {

if (currentLine.length() == 0) {

client.println("HTTP/1.1 200 OK");

client.println("Content-type:text/html");

client.println();

client.print("<html>");

client.print("<head><title>ESP32 Server</title></head>");

client.print("<body>");

client.print("Turn <a href=\"/H\">LED on</a><br>");

client.print("Turn <a href=\"/L\">LED off</a><br>");

client.print("</body></html>");

client.println();

break;

} else {

currentLine = "";

}

} else if (c != '\r') {

currentLine += c;

}

// Проверка ссылок от клиента, может быть "GET /H" или "GET /L":

if (currentLine.endsWith("GET /H")) {

digitalWrite(ledPin, HIGH); // GET /H - включить светодиод

}

if (currentLine.endsWith("GET /L")) {

digitalWrite(ledPin, LOW); // GET /L выключить светодиод

}

}

}

// Закрыть соединение

client.stop();

}

}

Запускаем программу, обновляем страницу, и видим нашу “панель управления”:

Проверяем, что нажатие на одну из ссылок действительно включает или выключает светодиод.

Кстати, если у интернет-провайдера доступна услуга “статический IP”, то можно настроить перенаправление портов в роутере, и управлять светодиодом через Интернет, даже из другого города или другой страны.

Самостоятельная работа #1: изучить разные варианты форматирования текста в HTML, например, таблицы, шрифты, выравнивание. Это позволит делать более сложный и более красивый интерфейс.

Самостоятельная работа #1: подключить к плате “пищалку”, и настроить управление ею через web. Это позволит посылать сигналы родственникам или друзьям.

3.10 Выводим изображения на web-сервере

Вышеприведенный сервер конечно, работает, однако далеко не является шедевром web-дизайна. Немного улучшить его можно, добавив изображения. Однако, это не так просто, т.к. наш мини-сервер не имеет файловой системы, и просто положить нужные файлы мы не можем. Вместо этого используем так называемое base64-кодирование, позволяющее вставить изображение прямо в код страницы.

Чтобы вставить картинку в HTML, нужно.

1. Выбрать любую картинку. Возьмем картинку попроще, чтобы она не занимала много места, например изобразим светодиод:

2. Сконвертируем изображение в base64-формат, для этого можно воспользоваться любым онлайн-конвертором, например этим: https://www.base64-image.de.

Мы получим строку такого вида:

data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAeAB4AAD/4QBaRXhpZgAATU0AKgAAAAgABQMBAAUAAAABAAAASgMDAAEAAAABAAAAAFEQAAEAAAABAQAAAFERAAQAAAABAAASdFESAAQAAAABAAASdAAAAAAAAYagAACxj//bAEMAAgEBAgEBAgICAgICAgIDBQMDAwMDBgQEAwUHBgcHBwYHBwgJCwkICAoIBwcKDQoKCwwMDAwHCQ4PDQwOCwwMDP/bAEMBAgICAwMDBgMDBgwIBwgMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDP/AABEIAC4AGgMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AP3B/aG/aD8P/s2/Da58SeIpZ1tonWGCGBQ013KwJWOMEgZwpJJIAAJJwK+DfEH/AAWi8e3niB30fwp4WtNJLZit7xbi4uCnH3pFljGfonfv39c/4Kx+DZfHd/4Gt9z/AGS1S+lKdUaQmFQSPUAHB7bj6mvk7T/gZZtaMZ5Njb8BsgD3xX8xeJ3iljsvzieW4Sq6apct7Wu20nq+2ux9rkeQ06+HVeor3ufop+xf+2fo/wC1v4Tu3is5NG8QaOUXUNMkl83YjZ2Sxvgb42KsOQCpBBHQn26vgL/gnz8N3+H37SFlc2c7mK80+5s7qLdjKbVkDYz2dE/P619+1+s+GHF0+IslWNq/HGTg+l2rO/3NHgZ3l6weKdJbaNfM+PP+CnOvf2f4g8HRI5Z/s12/lJIARmSFVYjnjOfrg155pniHwn4I/skP4Ss/EnjGV08m0jWWJvNb7rNHtaMk8dVyfapv+Cklw+nftYaTc+Xe28k2gRQ2R2bv7QMM8ssvkBSWkZPMjBRRuBYHGGBPhNv8fQ3xBnvIX1Y65pN0Ld42heO7huw5jljZtodJAvGw9wMg5xX8u+J+Ex8uLMRmFKlJQUuXm5XZtRjH7UbPb/gn2uSVKP8AZ0KEpq/a9up9Q/BSHW9G/ao8M6x4mgg0WbVri4iFuF8mOMy25CQgkkMSUXjJJIOAO32rX57S6r4t1v8Aae8E6Bq8Wp3mqaFrdvfW9ncIGu/KjlCyyll+VoQGJLcqhUgkc4/Qmv3HwGhWo5XisNVpyhaq2uePK9Urp9LprWx81xQ4yrwqRad4rZ32Pmj/AIKHeCp734eazqWjareeG/FGs22leCrXxBZY+26DZ6rrNtaXc1tuyEm8qTIYc7okOflFdP8AB3/gnt8Jfgh4ehsdI8JWt/co6zS6prUsuq6neTBVXzpbm4Z5C/yg5DAKfuhcCq37dd9bW/wwuvtCyssF/oN1hApyU12yK9f9vb+Gcc17qi7fzzX7fWw9KslGrFSXnr+Z8zGTjNtHzL+2RoP/AAq6HwdrOlarqwvrT4j+GLsG71Ge7e3S91OHTLqKIyuxWKW2uZVMSnaCcgA19PV8uf8ABVCddN+DXhu6AxInjPws6uBllZPEemBf1kP/ANevqOtlojOL95n/2Q==

3. Создадим текстовую переменную, которая будет хранить наше изображение и скопируем в нее всю строку:

const PROGMEM char *image01 = "data:image/jpeg;base64,/9j/4A….5n/2Q==”;

Тег PROGMEM указывает компилятору, что это константа, которую можно хранить во флеш-памяти, сэкономив тем самым место для других переменных. Это особенно актуально, если картинок много.

Предыдущая главаГлава 10 из 18Следующая глава