ESP8266:Примеры/Управление ESP8266 при помощи Android-виджета
Поддержать проект | Содержание | Введение | Модули | AT-команды | Прошивки | Примеры | Проекты | Типовые проблемы | Библиотеки |
![]() |
Черновик |
Содержание
- 1 Управление ESP8266 при помощи Android-виджета
- 1.1 Необходимое оборудование
- 1.2 Как работает код
- 1.3 Как задать собственные имя пользователя и пароль
- 1.4 Загружаем код
- 1.5 Копируем IP-адрес ESP8266
- 1.6 Устанавливаем программу для сканирования IP-адресов
- 1.7 Заходим на веб-сервер
- 1.8 Устанавливаем приложение HTTP Request Shortcuts
- 1.9 Схема
- 1.10 Код
- 2 См.также
- 3 Внешние ссылки
Управление ESP8266 при помощи Android-виджета
В этом проекте мы воспользуемся вот этим скетчем, с помощью которого создается защищенный паролем веб-сервер, управляющий включением/выключением двух GPIO-контактов ESP8266. Этот метод требует открытия браузера и вписывания IP-адреса, но гораздо проще было бы управлять GPIO-контактами ESP8266 прямо с экрана вашего смартфона. Именно описанием этого метода мы в этом руководстве и займемся.
Необходимое оборудование
- Плата ESP8266 - 1шт.;
- Светодиод - 2шт.;
- Резистор 470 Ом- 2 шт.
- Макетная плата - 1шт.;
- Провода перемычки.
- Android-устройство(планшет, смартфон, часы, приставка и т.д.) - 1шт.
Как работает код
В самом начале скетча мы подключаем библиотеку «ESP8266WiFi», а в следующих двух строчках задаем SSID и пароль для своей WiFi-сети, чтобы ESP8266 мог к ней подключиться.
1 // Подключаем библиотеку «ESP8266WiFi»:
2 #include <ESP8266WiFi.h>
3
4 // Пишем SSID и пароль для своей WiFi-сети:
5 const char* ssid = "YOUR_NETWORK_NAME";
6 const char* password = "YOUR_NETWORK_PASSWORD";
Далее создаем объект веб-сервера и задаем ему порт «8888»:
1 // Создаем объект веб-сервера с номером порта «8888»:
2 WiFiServer server(8888);
Создаем переменную «header» для хранения заголовка ответа на запрос, переменные «gpio5_state» и «gpio4_state» для хранения текущего состояния этих GPIO-контактов, а также переменные «gpio5_pin» и «gpio4_pin» для хранения номеров контактов GPIO4 и GPIO5.
1 // Создаем несколько переменных:
2 String header;
3 String gpio5_state = "Off";
4 String gpio4_state = "Off";
5 int gpio5_pin = 5;
6 int gpio4_pin = 4;
Далее создаем блок setup(), код в котором будет запущен только раз – при запуске ESP8266.
1 // Код в этом блоке будет запущен только один раз:
2 void setup() {
3 }
Запускаем последовательную коммуникацию на скорости 115200 бод (для отладки). Переключаем оба GPIO-контакта в режим вывода данных (OUTPUT) и задаем им значение «LOW».
1 // Этот код будет запущен только один раз:
2 void setup() {
3 // Инициализируем последовательную коммуникацию (для отладки):
4 Serial.begin(115200);
5 delay(10);
6
7 // Подготавливаем GPIO-контакты:
8 pinMode(gpio5_pin, OUTPUT);
9 digitalWrite(gpio5_pin, LOW);
10 pinMode(gpio4_pin, OUTPUT);
11 digitalWrite(gpio4_pin, LOW);
В следующем фрагменте кода запускаем подключение к WiFi-сети, ждем успешного подключения и печатаем в мониторе порта IDE Arduino IP-адрес ESP8266.
1 // Подключаемся к WiFi-сети:
2 Serial.println();
3 Serial.print("Connecting to ");
4 // "Подключаемся к "
5
6 Serial.println(ssid);
7
8 WiFi.begin(ssid, password);
9
10 while (WiFi.status() != WL_CONNECTED) {
11 delay(500);
12 Serial.print(".");
13 }
14 Serial.println("");
15 Serial.println("WiFi connected");
16 // "Подключились к WiFi"
17
18 // Запускаем веб-сервер:
19 server.begin();
20 Serial.println("Web server running. Waiting for the ESP IP...");
21 // "Веб-сервер запущен.
22 // "Ждем получения IP-адреса ESP8266..."
23 delay(1000);
24
25 // Печатаем IP-адрес ESP8266:
26 Serial.println(WiFi.localIP());
27 }
Блок loop() отвечает за то, что будет происходить, когда новый клиент установит соединение с веб-сервером. То есть код в loop() будет постоянно прослушивать новых клиентов. Соответственно, если к веб-серверу подключится новый клиент, он начнет подключаться к нему.
1 // Код в блоке loop() будет постоянно повторяться:
2 void loop() {
3 // Прослушиваем новых клиентов:
4 WiFiClient client = server.available();
Булева переменная «blank_line» ниже служит для того, чтобы определить конец HTTP-запроса. Кроме того, в этом фрагменте кода используется цикл while(), который будет работать все то время, пока клиент будет подключен к веб-серверу.
1 if (client) {
2 Serial.println("New client"); // "Новый клиент"
3 // Булева переменная, предназначенная
4 // для определения конца HTTP-запроса:
5 boolean blank_line = true;
6 while (client.connected()) {
7 if (client.available()) {
Теперь давайте добавим в веб-сервер механизм аутентификации, чтобы сделать его более безопасным. После этого любому, кто попытается получить доступ к веб-серверу, придется ввести имя пользователя и пароль.
По умолчанию именем пользователя будет «user», а паролем – «pass». Чуть ниже я расскажу о том, как их поменять. Если пользователь введет правильные имя пользователя и пароль, то получит доступ к веб-странице для управления GPIO-контактами ESP8266.
1 // Проверяем, правильные ли введены имя пользователя и пароль:
2 if(header.indexOf("dXNlcjpwYXNz") >= 0) {
В следующем фрагменте кода проверяется, на какую кнопку веб-страницы нажал пользователь. По сути, в нем проверяется, какой вы хотите открыть URL.
К примеру, кликая на кнопку «OFF» для контакта GPIO5, вы открываете ссылку «http://192.168.1.22:8888/gpio5off». Код смотрит на эту ссылку и при помощи нескольких else if() сверяется с тем, что ему нужно сделать. В случае со ссылкой «http://192.168.1.22:8888/gpio5off» он переключит контакт GPIO5 («gpio5_pin») в состояние «LOW».
1 // Проверяем, правильные ли введены
2 // имя пользователя и пароль:
3 if(header.indexOf("dXNlcjpwYXNz") >= 0) {
4 // Залогинивание прошло успешно:
5 client.println("HTTP/1.1 200 OK");
6 client.println("Content-Type: text/html");
7 client.println("Connection: close");
8 // "Соединение: отключено"
9 client.println();
10 // Включаем/выключаем GPIO-контакты:
11 if(header.indexOf("GET / HTTP/1.1") >= 0) {
12 Serial.println("Main Web Page");
13 // "Главная веб-страница"
14 }
15 else if(header.indexOf("GET /gpio5on HTTP/1.1") >= 0){
16 Serial.println("GPIO 5 On");
17 // "Контакт GPIO5 включен"
18 gpio5_state = "On";
19 digitalWrite(gpio5_pin, HIGH);
20 }
21 else if(header.indexOf("GET /gpio5off HTTP/1.1") >= 0){
22 Serial.println("GPIO 5 Off");
23 // "Контакт GPIO5 выключен"
24 gpio5_state = "Off";
25 digitalWrite(gpio5_pin, LOW);
26 }
27 else if(header.indexOf("GET /gpio4on HTTP/1.1") >= 0){
28 Serial.println("GPIO 4 On");
29 // "Контакт GPIO4 включен"
30 gpio4_state = "On";
31 digitalWrite(gpio4_pin, HIGH);
32 }
33 else if(header.indexOf("GET /gpio4off HTTP/1.1") >= 0){
34 Serial.println("GPIO 4 Off");
35 // "Контакт GPIO4 выключен"
36 gpio4_state = "Off";
37 digitalWrite(gpio4_pin, LOW);
38 }
Страница отправляется клиенту при помощи метода client.println(). Это очень простая веб-страница, использующая фреймворк Bootstrap (см. код ниже).
Более подробно о Bootstrap можно почитать по этой ссылке.
На веб-странице будет 4 кнопки для включения/выключения (переключения между состояниями «HIGH» и «LOW») двух светодиодов, подключенных к контактам GPIO5 и GPIO4.
Кнопки – это HTML-теги <a href=””></a> с CSS-классом, который придает им вид кнопки. Когда вы нажимаете на кнопку, вам открывается другая страница с URL, соответствующим этой кнопке. Именно так ESP8266 и узнает, что ей нужно сделать (т.е. включить или выключить светодиод, и какой именно).
1 // Ваша веб-страница:
2 client.println("<!DOCTYPE HTML>");
3 client.println("<html>");
4 client.println("<head>");
5 client.println("<meta name=\"viewport\" content=\"width=device-width, initialscale=1\">");
6 client.println("<link rel=\"stylesheet\"
7 href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css\">");
8 client.println("</head><div class=\"container\">");
9 client.println("<h1>Web Server</h1>");
10 client.println("<h2>GPIO 5 - Current State: " + gpio5_state);
11 client.println("<div class=\"row\">");
12 client.println("<div class=\"col-md-2\"><a href=\"/gpio5on\" class=\"btn btn-block
13 btn-lg btn-success\" role=\"button\">ON</a></div>");
14 client.println("<div class=\"col-md-2\"><a href=\"/gpio5off\" class=\"btn btn-block
15 btn-lg btn-danger\" role=\"button\">OFF</a></div>");
16 client.println("</div>");
17 client.println("<h2>GPIO 4 - Current State: " + gpio4_state);
18 client.println("<div class=\"row\">");
19 client.println("<div class=\"col-md-2\"><a href=\"/gpio4on\" class=\"btn btn-block
20 btn-lg btn-success\" role=\"button\">ON</a></div>");
21 client.println("<div class=\"col-md-2\"><a href=\"/gpio4off\" class=\"btn btn-block
22 btn-lg btn-danger\" role=\"button\">OFF</a></div>");
23 client.println("</div></div></html>");
Если вы введете неправильные имя пользователя и пароль, в браузере будет напечатано сообщение «Authentication failed» («Аутентификация не удалась»).
1 // Неправильные имя пользователя и пароль,
2 // поэтому HTTP-запрос завершился неудачей...
3 else {
4 client.println("HTTP/1.1 401 Unauthorized");
5 client.println("WWW-Authenticate: Basic realm=\"Secure\"");
6 client.println("Content-Type: text/html");
7 client.println();
8 client.println("<html>Authentication failed</html>");
9 }
Строчки кода в конце скетча очищают переменную «header», завершают цикл loop() и завершают подключение.
1 header = "";
2 break;
3 }
4 if (c == '\n') {
5 // Когда нужно перейти к следующей строчке:
6 blank_line = true;
7 }
8 else if (c != '\r') {
9 // Когда в текущей строке найден символ:
10 blank_line = false;
11 }
12 }
13 }
14 // Завершаем подключение к клиенту:
15 delay(1);
16 client.stop();
17 Serial.println("Client disconnected.");
18 // "Клиент отключился."
19 }
20 }
Как задать собственные имя пользователя и пароль
В скетче, который мы разобрали выше, именем пользователя является «user», а паролем – «pass». Уверен, вы захотите задать вместо них собственные имя пользователя и пароль. Пройдите по этой ссылке. В первом поле впишите следующее:
your_username:your_password
Примечание: Обратите внимание, что между именем пользователя и паролем нужно вписать «:».
В моем случае это «user:pass».
Затем нажмите на зеленую кнопку «Encode» – это сгенерирует строку в формате Base64. В моем случае это «dXNlcjpwYXNz».
Скопируйте ее и вставьте в это место скетча:
1 // Проверяем, правильные ли введены имя пользователя и пароль:
2 if(header.indexOf("dXNlcjpwYXNz") >= 0) {
Совет: Эта 80-ая строчка скетча, и в ней также присутствует оператор if().
Загружаем код
Подключите ESP8266 к ПК и откройте IDE Arduino. Кликните по «Инструменты» > «Плата» (Tools > Board) и выберите подключенную плату.
Выберите COM-порт, к которому подключена ваша плата.
Проверив все настройки, нажмите на кнопку «Загрузка» (Upload):
Подождите несколько секунд, пока не увидите сообщение «Загрузка завершена» (Done uploading) в левом нижнем углу IDE Arduino.
Копируем IP-адрес ESP8266
Загрузив веб-серверный скетч на ESP8266, кликните в IDE Arduino на «Инструменты» > «Монитор порта» (Tools > Serial Monitor). Монитор порта – это окно, где ESP8266, загрузившись, напечатает свой IP-адрес.
Мой IP-адрес – это «192.168.1.22» (см. на скриншоте ниже). Ваш IP-адрес, скорее всего, будет другим. Сохраните его, т.к. позднее вы с его помощью перейдете на страницу веб-сервера.
Важно: Выставьте скорость монитора порта на 115200 бод, иначе вы просто ничего не увидите.
Проблема – В мониторе порта не печатается IP-адрес
Если у вас возникла такая проблема, можно попробовать сделать следующее:
- Оставьте монитор порта открытым;
- ESP-12E (или FTDI-программатор) должен оставаться подключенным к ПК;
- Перезапустите ESP-12E, нажав на встроенную в него кнопку.
Спустя секунду ESP8266 должна напечатать в мониторе порта свой IP-адрес.
Устанавливаем программу для сканирования IP-адресов
Если IP-адрес в мониторе порта по-прежнему не появляется, то вам нужно будет установить на свой ПК программу для сканирования IP-адресов. Она будет искать все девайсы в вашей сети.
- Загрузите ее (это бесплатно). Можете выбрать между Advanced IP Scanner (Windows) и Angry IP Scanner (MAC OS X, Windows или Linux);
- Установите программу (в это время ESP8266 должен быть включен, и на нем должен работать скетч, написанный нами выше);
- Откройте программу для сканирования IP-адресов и нажмите на кнопку «Сканировать» (Scan);
Дайте процессу завершиться (это должно занять несколько минут).
Заходим на веб-сервер
Перед заходом на веб-сервер нужно сделать следующее:
- Перезапустите ESP8266;
- Откройте браузер;
- Впишите в его адресную строку IP-адрес, скопированный ранее из монитора порта IDE Arduino, и добавьте в конце «8888» (в моем случае – «192.168.1.22:8888»);
- Нажмите на ↵ Enter .
После этого в браузере должно выскочить окно с запросом ввести имя пользователя и пароль:
- Введите имя пользователя и пароль
- Залогиньтесь
В результате в браузере должна загрузиться примерно такая страница:
Примечание: Чтобы получить доступ к веб-серверу, устройство с браузером должно быть подключено к тому же роутеру, что и ESP8266.
Устанавливаем приложение HTTP Request Shortcuts
Для этого проекта мы воспользуемся бесплатным Android-приложением HTTP Request Shortcuts, позволяющим выполнять HTTP-запросы GET/POST простым нажатием на кнопку прямо на домашнем экране смартфона, избавляя от необходимости вбивать IP-адрес ESP8266 в браузер.
Поищите в онлайн-магазине Google Play Store «HTTP Request Shortcuts», а затем установите приложение. Далее кликните на кнопку «Открыть».
Создаем кнопку «ON» («ВКЛ») для контакта GPIO5
Чтобы создать виджет, при нажатии переключающий контакт GPIO5 в состояние «ON», кликните по синей кнопке с плюсом в правом нижнем углу приложения.
Выберите пункт «From scratch».
Вы можете задать следующие настройки виджета:
- Shortcut name (Название виджета): ON – GPIO5;
- Иконка: Изображение, показываемое на домашнем экране смартфона;
- Method (Тип запроса): GET;
- URL (ссылка): Здесь нужно вписать «http://IP_АДРЕС_ВАШЕЙ_ESP:8888/gpio5on». В моем случае получилась ссылка «http://192.168.1.22:8888/gpio5on»;
- Authentication Method (Метод аутентификации) – Basic Authentication (Базовая аутентификация)
- Username (Имя пользователя) – user
- Password (Пароль) – pass
- Response Type (Тип ответа) – Simple Toast (Простое уведомление)
- Timeout (Таймаут) – short (3 seconds) (короткий (3 секунды))
- Delay execution (Задержка выполнения) – No delay (Без задержки)
- When not connected to the internet (Когда не подключен к интернету) – drop the request (отклонить запрос)
Чтобы сохранить настройки, кликните на галочку в правом верхнем углу экрана.
Создаем кнопку «OFF» («ВЫКЛ») для контакта GPIO5
Нам также нужно будет создать кнопку «OFF» для контакта GPIO5. Вот ее настройки:
- Shortcut name: OFF – GPIO5;
- Иконка. Изображение, показываемое на домашнем экране смартфона;
- Method: GET;
- URL: Здесь нужно вписать «http://IP_АДРЕС_ВАШЕЙ_ESP:8888/gpio5off». В моем случае получилась ссылка «http://192.168.1.22:8888/gpio5off»;
- Authentication Method: Basic Authentication;
- Username: user;
- Password: pass;
- Response Type: Simple Toast;
- Timeout: short (3 seconds);
- Delay execution: No delay;
- When not connected to the internet: drop the request;
Чтобы сохранить настройки, нажмите на галочку в правом верхнем углу экрана.
Добавляем виджеты на домашний экран
Чтобы добавить виджет на домашний экран смартфона, просто зажмите кнопку «ON – GPIO 5».
В появившемся меню выберите пункт «Place on home screen» (Разместить на домашнем экране). Потом сделайте то же самое для виджета «OFF – GPIO 5».
Тестируем
Обе иконки должны появиться на домашнем экране смартфона. Теперь попробуйте понажимать на виджеты. Если при нажатии на них GPIO-контакты ESP8266 меняют значение с «ON» на «OFF» и обратно, то все работает как надо.
Вот и все. Код, загруженный на ESP8266, также готов для управления контактом GPIO4. Поэтому рекомендую проделать для его настройки все те же шаги, что и для настройки GPIO5. Кроме того, этот проект можно без труда перенастроить и под управление другими устройствами.
Схема
Загрузив код на ESP8266, подключите компоненты друг к другу, как показано на схеме ниже (для подключения светодиодов можно воспользоваться резисторами номиналом между 270 Ом и 470 Ом).
Код
1 /*********
2 Rui Santos
3 Complete project details at http://randomnerdtutorials.com
4 *********/
5
6 // Including the ESP8266 WiFi library
7 #include <ESP8266WiFi.h>
8
9 // Replace with your network details
10 const char* ssid = "YOUR_NETWORK_NAME";
11 const char* password = "YOUR_NETWORK_PASSWORD";
12
13 // Web Server on port 8888
14 WiFiServer server(8888);
15
16 // variables
17 String header;
18 String gpio5_state = "Off";
19 String gpio4_state = "Off";
20 int gpio5_pin = 5;
21 int gpio4_pin = 4;
22
23 // only runs once
24 void setup() {
25 // Initializing serial port for debugging purposes
26 Serial.begin(115200);
27 delay(10);
28
29 // preparing GPIOs
30 pinMode(gpio5_pin, OUTPUT);
31 digitalWrite(gpio5_pin, LOW);
32 pinMode(gpio4_pin, OUTPUT);
33 digitalWrite(gpio4_pin, LOW);
34
35 // Connecting to WiFi network
36 Serial.println();
37 Serial.print("Connecting to ");
38 Serial.println(ssid);
39
40 WiFi.begin(ssid, password);
41
42 while (WiFi.status() != WL_CONNECTED) {
43 delay(500);
44 Serial.print(".");
45 }
46 Serial.println("");
47 Serial.println("WiFi connected");
48
49 // Starting the web server
50 server.begin();
51 Serial.println("Web server running. Waiting for the ESP IP...");
52 delay(1000);
53
54 // Printing the ESP IP address
55 Serial.println(WiFi.localIP());
56 }
57
58 // runs over and over again
59 void loop() {
60 // Listenning for new clients
61 WiFiClient client = server.available();
62
63 if (client) {
64 Serial.println("New client");
65 // boolean to locate when the http request ends
66 boolean blank_line = true;
67 while (client.connected()) {
68 if (client.available()) {
69 char c = client.read();
70 header += c;
71
72 if (c == '\n' && blank_line) {
73
74 // checking if header is valid
75 // dXNlcjpwYXNz = 'user:pass' (user:pass) base64 encode
76
77 Serial.print(header);
78
79 // Finding the right credential string
80 if(header.indexOf("dXNlcjpwYXNz") >= 0) {
81 //successful login
82 client.println("HTTP/1.1 200 OK");
83 client.println("Content-Type: text/html");
84 client.println("Connection: close");
85 client.println();
86 // turns the GPIOs on and off
87 if(header.indexOf("GET / HTTP/1.1") >= 0) {
88 Serial.println("Main Web Page");
89 }
90 else if(header.indexOf("GET /gpio5on HTTP/1.1") >= 0){
91 Serial.println("GPIO 5 On");
92 gpio5_state = "On";
93 digitalWrite(gpio5_pin, HIGH);
94 }
95 else if(header.indexOf("GET /gpio5off HTTP/1.1") >= 0){
96 Serial.println("GPIO 5 Off");
97 gpio5_state = "Off";
98 digitalWrite(gpio5_pin, LOW);
99 }
100 else if(header.indexOf("GET /gpio4on HTTP/1.1") >= 0){
101 Serial.println("GPIO 4 On");
102 gpio4_state = "On";
103 digitalWrite(gpio4_pin, HIGH);
104 }
105 else if(header.indexOf("GET /gpio4off HTTP/1.1") >= 0){
106 Serial.println("GPIO 4 Off");
107 gpio4_state = "Off";
108 digitalWrite(gpio4_pin, LOW);
109 }
110 // your web page
111 client.println("<!DOCTYPE HTML>");
112 client.println("<html>");
113 client.println("<head>");
114 client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
115 client.println("<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css\">");
116 client.println("</head><div class=\"container\">");
117 client.println("<h1>Web Server</h1>");
118 client.println("<h2>GPIO 5 - Current State: " + gpio5_state);
119 client.println("<div class=\"row\">");
120 client.println("<div class=\"col-md-2\"><a href=\"/gpio5on\" class=\"btn btn-block btn-lg btn-success\" role=\"button\">ON</a></div>");
121 client.println("<div class=\"col-md-2\"><a href=\"/gpio5off\" class=\"btn btn-block btn-lg btn-danger\" role=\"button\">OFF</a></div>");
122 client.println("</div>");
123 client.println("<h2>GPIO 4 - Current State: " + gpio4_state);
124 client.println("<div class=\"row\">");
125 client.println("<div class=\"col-md-2\"><a href=\"/gpio4on\" class=\"btn btn-block btn-lg btn-success\" role=\"button\">ON</a></div>");
126 client.println("<div class=\"col-md-2\"><a href=\"/gpio4off\" class=\"btn btn-block btn-lg btn-danger\" role=\"button\">OFF</a></div>");
127 client.println("</div></div></html>");
128 }
129 // wrong user or passm, so http request fails...
130 else {
131 client.println("HTTP/1.1 401 Unauthorized");
132 client.println("WWW-Authenticate: Basic realm=\"Secure\"");
133 client.println("Content-Type: text/html");
134 client.println();
135 client.println("<html>Authentication failed</html>");
136 }
137 header = "";
138 break;
139 }
140 if (c == '\n') {
141 // when starts reading a new line
142 blank_line = true;
143 }
144 else if (c != '\r') {
145 // when finds a character on the current line
146 blank_line = false;
147 }
148 }
149 }
150 // closing the client connection
151 delay(1);
152 client.stop();
153 Serial.println("Client disconnected.");
154 }
155 }
См.также
Внешние ссылки