ESP8266:Примеры/Веб-переключатель, управляемый при помощи EasyIoT Cloud: различия между версиями
Myagkij (обсуждение | вклад) Нет описания правки |
Myagkij (обсуждение | вклад) Нет описания правки |
||
(не показаны 2 промежуточные версии 2 участников) | |||
Строка 2: | Строка 2: | ||
{{Перевод от Сubewriter}} | {{Перевод от Сubewriter}} | ||
{{Myagkij-редактор}} | {{Myagkij-редактор}} | ||
=Веб-переключатель, управляемый при помощи EasyIoT Cloud<ref>[http://iot-playground.com/blog/2-uncategorised/87-esp8266-internet-connected-switch-easyiot-cloud-mqtt-api-v1-improved iot-playground.com - ]</ref>= | =Веб-переключатель, управляемый при помощи EasyIoT Cloud<ref>[http://iot-playground.com/blog/2-uncategorised/87-esp8266-internet-connected-switch-easyiot-cloud-mqtt-api-v1-improved iot-playground.com - ]</ref>= | ||
Строка 17: | Строка 15: | ||
Этот веб-переключатель работает по принципу «подключай и работай» – с настройками [[EasyIoT Cloud]] возиться не нужно, т.к. они выставляются автоматически. | Этот веб-переключатель работает по принципу «подключай и работай» – с настройками [[EasyIoT Cloud]] возиться не нужно, т.к. они выставляются автоматически. | ||
{{Блок/Инфо4 | |||
|1=Внимание! | |||
|2= | |||
'''ВНИМАНИЕ! Работая с этим проектом, вы будете иметь дело с СЕТЕВЫМ напряжением. ЭТО ОЧЕНЬ ОПАСНО!''' | '''ВНИМАНИЕ! Работая с этим проектом, вы будете иметь дело с СЕТЕВЫМ напряжением. ЭТО ОЧЕНЬ ОПАСНО!''' | ||
Строка 26: | Строка 27: | ||
'''Максимальная сила тока для твердотельного реле в этом проекте – 2 ампера. Подходит только для комнатного освещения.''' | '''Максимальная сила тока для твердотельного реле в этом проекте – 2 ампера. Подходит только для комнатного освещения.''' | ||
}} | |||
== Введение == | == Введение == | ||
Строка 66: | Строка 68: | ||
В программе нужно будет поменять две строчки, показанные ниже. Это логин и пароль к аккаунту в [[EasyIoT Cloud]]. Вместо '''"usrname"''' и '''"pssw"''' впишите собственные логин и пароль. | В программе нужно будет поменять две строчки, показанные ниже. Это логин и пароль к аккаунту в [[EasyIoT Cloud]]. Вместо '''"usrname"''' и '''"pssw"''' впишите собственные логин и пароль. | ||
<syntaxhighlight lang="c | <syntaxhighlight lang="c"> | ||
#define EIOTCLOUD_USERNAME "usrname" | #define EIOTCLOUD_USERNAME "usrname" | ||
#define EIOTCLOUD_PASSWORD "pssw" | #define EIOTCLOUD_PASSWORD "pssw" | ||
Строка 75: | Строка 77: | ||
Вначале программа считывает настройки '''EEPROM'''. Затем пытается подключиться к точке доступа. Если подключиться к точке доступа не удается, через '''10 секунд''' программа переключает [[ESP8266]] в режим точки доступа, чтобы вы могли указать данные для точки доступа, к которой должен подключиться [[ESP8266]]. Если подключение к точке доступа прошло успешно, программа проверяет '''ID модуля'''. Если '''ID модуля''' равно '''«0»''', это значит, что переключатель не настроен на [[EasyIoT Cloud]]. В этом случае программа добавляет модуль в [[EasyIoT Cloud]] и сохраняет '''ID модуля''' в настройки '''EEPROM'''. После успешной настройки модуль подписывается на топик, содержащий данные о статусе переключателя. | Вначале программа считывает настройки '''EEPROM'''. Затем пытается подключиться к точке доступа. Если подключиться к точке доступа не удается, через '''10 секунд''' программа переключает [[ESP8266]] в режим точки доступа, чтобы вы могли указать данные для точки доступа, к которой должен подключиться [[ESP8266]]. Если подключение к точке доступа прошло успешно, программа проверяет '''ID модуля'''. Если '''ID модуля''' равно '''«0»''', это значит, что переключатель не настроен на [[EasyIoT Cloud]]. В этом случае программа добавляет модуль в [[EasyIoT Cloud]] и сохраняет '''ID модуля''' в настройки '''EEPROM'''. После успешной настройки модуль подписывается на топик, содержащий данные о статусе переключателя. | ||
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS | <syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | ||
#include <ESP8266WiFi.h> | #include <ESP8266WiFi.h> | ||
#include <MQTT.h> | #include <MQTT.h> | ||
Строка 542: | Строка 544: | ||
=См.также= | =См.также= | ||
=Внешние ссылки= | =Внешние ссылки= | ||
Строка 549: | Строка 549: | ||
<references /> | <references /> | ||
{{Навигационная таблица/ | {{Навигационная таблица/Портал/ESP8266}} | ||
[[Категория:ESP8266]] | [[Категория:ESP8266]] |
Текущая версия от 12:38, 18 июня 2023
Веб-переключатель, управляемый при помощи EasyIoT Cloud[1]
Эта статья рассказывает, как собрать веб-переключатель, управляемый через WiFi при помощи веб-сервиса EasyIoT Cloud. Для этого проекта нам понадобятся модуль с чипом ESP8266, твердотельное реле и программа IDE Arduino. Данные для точки доступа, к которой будет подключаться веб-переключатель, можно задать через браузерный интерфейс.
Управлять веб-переключателем можно, во-первых, дистанционно – через браузерный веб-интерфейс (с компьютера, планшета или мобильного телефона) или через официальное приложение.
Веб-переключатель подключен к интернету через WiFi. Кроме того, переключателем можно управлять локально, при помощи кнопки.
Данное руководство написано на примере последней версии MQTT-брокера EasyIoT Cloud. Эта версия имеет два улучшения по сравнению с предыдущей. Во-первых, для обновления состояния в интерфейсе используется информация от переключателя. То есть, если соединение с переключателем разорвано, состояние в пользовательском интерфейсе обновляться не будет. Во-вторых, данные для точки доступа, к которой будет подключаться веб-переключатель, теперь можно задать через браузер, открытый на смартфоне или компьютере.
Этот веб-переключатель работает по принципу «подключай и работай» – с настройками EasyIoT Cloud возиться не нужно, т.к. они выставляются автоматически.
Введение
[Видео]
![](/ruwiki/images/0/0f/ESP8266_internet_connected_switch_%28EasyIoT_Cloud_MQTT_API_V1%29_-_improved.jpg)
Необходимые компоненты
- Один модуль с ESP8266
- Одно твердотельное реле (2 ампера, 240 вольт)
- Один понижающий преобразователь (на входе переменный ток, на выходе – постоянный; на выходе 3.3 вольта; 600 мА)
- Одна кнопка
- Один транзистор типа NPN (TO-92, 2N2222)
- Один электролитический конденсатор на 1000 мкФ
- Один резистор на 1 кОм
- Один резистор на 47 кОм
Настройка EasyIoT Cloud
Настраивать EasyIoT Cloud не нужно, просто зарегистрируйтесь в сервисе EasyIoT Cloud. Чтобы получить доступ к веб-переключателю (будь то Android-приложение или браузерный интерфейс), понадобятся имя пользователя и пароль. Веб-переключатель будет автоматически добавлен в EasyIoT Cloud и появитя в браузерном интерфейсе или интерфейсе Android-приложения после подключения к питанию.
Программирование
Программа для веб-переключателя написана в IDE Arduino. Вам нужно будет установить в нее аддон для ESP8266, и о том, как это сделать, можно прочесть тут.
Дальнейшие действия зависят от того, какой модуль ESP8266 вы используете. Если ваш модуль не оснащен адаптером USB-Serial, то его нужно будет подключить. Схему подключения к адаптеру смотрите на картинке ниже. Не забудьте настроить его на 3,3 вольта. Иногда адаптеры не обеспечивают ESP8266 достаточным напряжением. В этом случае ESP8266 нужно питать только от внешнего источника питания (т.е. нужно отключить от адаптера линию Vcc).
![](/ruwiki/images/b/b9/Esp8266-reflash-firmware.jpg)
Если вы используете адаптерную плату вроде той, что выпускает команда NodeMCU, просто подключите ее к компьютеру через USB-кабель. Этот способ рекомендуется для новичков.
![](/ruwiki/images/0/0a/ESP8266_internet_connected_switch_%28EasyIoT_Cloud_MQTT_API_V1%29_-_improved_1.jpg)
Саму программу можно скачать с GitHub. Вам также понадобится библиотека для клиента MQTT; она называется «esp-mqtt», и ее можно скачать отсюда.
Скачав, установите ее в папку «libraries» IDE Arduino. Программа использует MQTT-брокер, встроенный в EasyIoT Cloud.
В программе нужно будет поменять две строчки, показанные ниже. Это логин и пароль к аккаунту в EasyIoT Cloud. Вместо "usrname" и "pssw" впишите собственные логин и пароль.
#define EIOTCLOUD_USERNAME "usrname"
#define EIOTCLOUD_PASSWORD "pssw"
Кроме того, прямо в программе можно поменять данные для точки доступа (SSID и пароль), но это необязательно, потому что их также можно поменять в веб-интерфейсе EasyIoT Cloud.
Вначале программа считывает настройки EEPROM. Затем пытается подключиться к точке доступа. Если подключиться к точке доступа не удается, через 10 секунд программа переключает ESP8266 в режим точки доступа, чтобы вы могли указать данные для точки доступа, к которой должен подключиться ESP8266. Если подключение к точке доступа прошло успешно, программа проверяет ID модуля. Если ID модуля равно «0», это значит, что переключатель не настроен на EasyIoT Cloud. В этом случае программа добавляет модуль в EasyIoT Cloud и сохраняет ID модуля в настройки EEPROM. После успешной настройки модуль подписывается на топик, содержащий данные о статусе переключателя.
#include <ESP8266WiFi.h>
#include <MQTT.h>
#include <EEPROM.h>
//#define DEBUG
#define AP_SSID "Geek"
#define AP_PASSWORD "G33k"
#define EIOTCLOUD_USERNAME "usrname"
#define EIOTCLOUD_PASSWORD "psswd"
// создаем экземпляр класса MQTT:
#define EIOT_CLOUD_ADDRESS "cloud.iot-playground.com"
MQTT myMqtt("", EIOT_CLOUD_ADDRESS, 1883);
#define CONFIG_START 0
#define CONFIG_VERSION "v01"
#define AP_CONNECT_TIME 10 //s
char ap_ssid[16];
char ap_pass[16];
WiFiServer server(80);
struct StoreStruct {
// это для проверки того, ваши ли это настройки:
char version[4];
// переменные для настроек:
uint moduleId; // ID модуля
bool state; // состояние
char ssid[20];
char pwd[20];
} storage = {
CONFIG_VERSION,
// модуль по умолчанию - «0»
0,
0, // выкл.
AP_SSID,
AP_PASSWORD
};
bool stepOk = false;
int buttonState;
boolean result;
String topic("");
String valueStr("");
boolean switchState;
const int buttonPin = 0;
const int outPin = 2;
int lastButtonState = LOW;
int cnt = 0;
void setup()
{
#ifdef DEBUG
Serial.begin(115200);
#endif
delay(1000);
pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, HIGH);
EEPROM.begin(512);
switchState = false;
loadConfig();
pinMode(BUILTIN_LED, OUTPUT);
digitalWrite(BUILTIN_LED, !switchState);
#ifndef DEBUG
pinMode(outPin, OUTPUT);
digitalWrite(outPin, switchState);
#endif
#ifdef DEBUG
Serial.println();
Serial.println();
Serial.print("Connecting to "); // "Подключение к "
Serial.println(AP_SSID);
#endif
WiFi.begin(storage.ssid, storage.pwd);
int i = 0;
while (WiFi.status() != WL_CONNECTED && i++ < (AP_CONNECT_TIME*2) ) {
delay(500);
#ifdef DEBUG
Serial.print(".");
#endif
}
if (!(i < (AP_CONNECT_TIME*2)))
{
AP_Setup();
AP_Loop();
ESP.reset();
}
#ifdef DEBUG
Serial.println("");
Serial.println("WiFi connected"); // "Подключились к WiFi"
Serial.println("IP address: "); // "IP-адрес: "
Serial.println(WiFi.localIP());
Serial.println("Connecting to MQTT server");
// "Подключение к MQTT-серверу"
#endif
// задаем ID клиента;
// генерируем название клиента на основе MAC-адреса
// и последних 8 бит счетчика микросекунд;
String clientName;
uint8_t mac[6];
WiFi.macAddress(mac);
clientName += macToStr(mac);
clientName += "-";
clientName += String(micros() & 0xff, 16);
myMqtt.setClientId((char*) clientName.c_str());
#ifdef DEBUG
Serial.print("MQTT client id:"); // "ID MQTT-клиента"
Serial.println(clientName);
#endif
// настраиваем функции обратного вызова:
myMqtt.onConnected(myConnectedCb);
myMqtt.onDisconnected(myDisconnectedCb);
myMqtt.onPublished(myPublishedCb);
myMqtt.onData(myDataCb);
//////Serial.println("connect mqtt...");
// "Подключение к MQTT..."
myMqtt.setUserPwd(EIOTCLOUD_USERNAME, EIOTCLOUD_PASSWORD);
myMqtt.connect();
delay(500);
#ifdef DEBUG
Serial.print("ModuleId: "); // "ID модуля: "
Serial.println(storage.moduleId);
#endif
// если нужно, создаем модуль:
if (storage.moduleId == 0)
{
// создаем модуль:
#ifdef DEBUG
Serial.println("create module: /NewModule");
// "Создание модуля: /NewModule"
#endif
myMqtt.subscribe("/NewModule");
waitOk();
// создаем параметр Sensor.Parameter1:
#ifdef DEBUG
Serial.println("/"+String(storage.moduleId)+ "/Sensor.Parameter1/NewParameter");
#endif
myMqtt.subscribe("/"+String(storage.moduleId)+ "/Sensor.Parameter1/NewParameter");
waitOk();
// задаем параметр IsCommand:
#ifdef DEBUG
Serial.println("/"+String(storage.moduleId)+ "/Sensor.Parameter1/IsCommand");
#endif
valueStr = "true";
topic = "/"+String(storage.moduleId)+ "/Sensor.Parameter1/IsCommand";
result = myMqtt.publish(topic, valueStr);
delay(100);
// задаем тип модуля:
#ifdef DEBUG
Serial.println("Set module type");
// "Настройка типа модуля: /NewModule"
#endif
valueStr = "MT_DIGITAL_OUTPUT";
topic = "/" + String(storage.moduleId) + "/ModuleType";
result = myMqtt.publish(topic, valueStr);
delay(100);
// сохраняем ID нового модуля:
saveConfig();
}
//switchState = storage.state;
//storage.state = !storage.state;
storage.state = switchState;
Serial.println("Suscribe: /"+String(storage.moduleId)+ "/Sensor.Parameter1");
myMqtt.subscribe("/"+String(storage.moduleId)+ "/Sensor.Parameter1");
}
void loop() {
while (WiFi.status() != WL_CONNECTED) {
delay(500);
#ifdef DEBUG
Serial.print(".");
#endif
}
int reading = digitalRead(buttonPin);
if (reading != lastButtonState) {
if (reading == LOW)
{
switchState = !switchState;
#ifdef DEBUG
Serial.println("button pressed");
// "Кнопка нажата"
#endif
}
#ifdef DEBUG
Serial.println("set state: ");
// "Задано состояние: "
Serial.println(valueStr);
#endif
lastButtonState = reading;
}
digitalWrite(BUILTIN_LED, !switchState);
#ifndef DEBUG
digitalWrite(outPin, switchState);
#endif
if (switchState != storage.state)
{
storage.state = switchState;
// сохраняем состояние кнопки:
saveConfig();
valueStr = String(switchState);
topic = "/"+String(storage.moduleId)+ "/Sensor.Parameter1";
result = myMqtt.publish(topic, valueStr, 0, 1);
#ifdef DEBUG
Serial.print("Publish "); // "Публикация "
Serial.print(topic);
Serial.print(" ");
Serial.println(valueStr);
#endif
delay(200);
}
}
void waitOk()
{
while(!stepOk)
delay(100);
stepOk = false;
}
String macToStr(const uint8_t* mac)
{
String result;
for (int i = 0; i < 6; ++i) {
result += String(mac[i], 16);
if (i < 5)
result += ':';
}
return result;
}
/*
*
*/
void myConnectedCb() {
#ifdef DEBUG
Serial.println("connected to MQTT server");
// "Подключение к MQTT-серверу"
#endif
if (storage.moduleId != 0)
myMqtt.subscribe("/" + String(storage.moduleId) + "/Sensor.Parameter1");
}
void myDisconnectedCb() {
#ifdef DEBUG
Serial.println("disconnected. try to reconnect...");
// "Соединение разорвано. Пытаемся переподключиться..."
#endif
delay(500);
myMqtt.connect();
}
void myPublishedCb() {
#ifdef DEBUG
Serial.println("published."); // "Опубликовано."
#endif
}
void myDataCb(String& topic, String& data) {
#ifdef DEBUG
Serial.print("Received topic:"); // "Полученный топик:"
Serial.print(topic);
Serial.print(": ");
Serial.println(data);
#endif
if (topic == String("/NewModule"))
{
storage.moduleId = data.toInt();
stepOk = true;
}
else if (topic == String("/"+String(storage.moduleId)+ "/Sensor.Parameter1/NewParameter"))
{
stepOk = true;
}
else if (topic == String("/"+String(storage.moduleId)+ "/Sensor.Parameter1"))
{
switchState = (data == String("1"))? true: false;
#ifdef DEBUG
Serial.print("switch state received: ");
// "Полученное состояние переключателя: "
Serial.println(switchState);
#endif
}
}
void loadConfig() {
// чтобы убедиться, что настройки есть, и это ВАШИ настройки!
// если настройки найдены не будут, будут использованы
// настройки по умолчанию:
if (EEPROM.read(CONFIG_START + 0) == CONFIG_VERSION[0] &&
EEPROM.read(CONFIG_START + 1) == CONFIG_VERSION[1] &&
EEPROM.read(CONFIG_START + 2) == CONFIG_VERSION[2])
for (unsigned int t=0; t<sizeof(storage); t++)
*((char*)&storage + t) = EEPROM.read(CONFIG_START + t);
}
void saveConfig() {
for (unsigned int t=0; t<sizeof(storage); t++)
EEPROM.write(CONFIG_START + t, *((char*)&storage + t));
EEPROM.commit();
}
void AP_Setup(void){
Serial.println("setting mode"); // "Режим настройки"
WiFi.mode(WIFI_AP);
String clientName;
clientName += "Thing-";
uint8_t mac[6];
WiFi.macAddress(mac);
clientName += macToStr(mac);
Serial.println("starting ap"); // "Запуск точки доступа"
WiFi.softAP((char*) clientName.c_str(), "");
Serial.println("running server"); // "Запуск сервера"
server.begin();
}
void AP_Loop(void){
bool inf_loop = true;
int val = 0;
WiFiClient client;
Serial.println("AP loop");
while(inf_loop){
while (!client){
Serial.print(".");
delay(100);
client = server.available();
}
String ssid;
String passwd;
// считываем первую строчку запроса:
String req = client.readStringUntil('\r');
client.flush();
// подготавливаем ответ, начинаем со стандартного заголовка:
String s = "HTTP/1.1 200 OK\r\n";
s += "Content-Type: text/html\r\n\r\n";
s += "<!DOCTYPE HTML>\r\n<html>\r\n";
if (req.indexOf("&") != -1){
int ptr1 = req.indexOf("ssid=", 0);
int ptr2 = req.indexOf("&", ptr1);
int ptr3 = req.indexOf(" HTTP/",ptr2);
ssid = req.substring(ptr1+5, ptr2);
passwd = req.substring(ptr2+10, ptr3);
val = -1;
}
if (val == -1){
strcpy(storage.ssid, ssid.c_str());
strcpy(storage.pwd, passwd.c_str());
saveConfig();
//storeAPinfo(ssid, passwd);
s += "Setting OK";
s += "<br>"; // переходим к следующей строчке
s += "Continue / reboot";
inf_loop = false;
}
else{
String content="";
// показываем значения всех входных аналоговых контактов:
content += "<form method=get>";
content += "<label>SSID</label><br>";
content += "<input type='text' name='ssid' maxlength='19' size='15' value='"+ String(storage.ssid) +"'><br>";
content += "<label>Password</label><br>";
content += "<input type='password' name='password' maxlength='19' size='15' value='"+ String(storage.pwd) +"'><br><br>";
content += "<input type='submit' value='Submit' >";
content += "</form>";
s += content;
}
s += "</html>\n";
// отправляем ответ клиенту:
client.print(s);
delay(1);
client.stop();
}
}
Самый простой способ проверить программу – воспользоваться адаптерной платой NodeMCU ESP8266. Для нее не нужно никаких предварительных настроек – просто подключите ее к USB-порту компьютера. Если вы используете эту плату, вы также можете убрать знак комментария у строчки #define DEBUG, расположенной в начале программы; это позволит видеть отладочные сообщения. Кнопка FLASH на ESP8266 будет служить кнопкой ручного изменения состояния переключателя. Состояние светодиода будет отображаться при помощи встроенного светодиода.
[Видео]
Схема
В нашем случае используется модуль ESP-01, но вы можете использовать любой другой модуль с чипом ESP8266. Контакт GPIO2 подключен к транзистору NPN, чтобы управлять твердотельным реле. Максимальная сила тока для нашего твердотельного реле – это 2 ампера. Этого хватит для комнатного освещения, но для проектов, где требуется больше питания (к примеру, для нагревателей) – вряд ли.
Для подачи питания используется понижающий преобразователь, снижающий напряжение до 3,3 вольт. Очень важно поставить на 3,3-вольтовую линию конденсатор на 1000 мкФ. Если забыть о нем, то цепь работать не будет.
Контакт GPIO0 подключен к кнопке – для локального управления веб-переключателем.
![](/ruwiki/images/1/13/Web-switch-scheme.jpg)
После включения питания переключатель будет автоматически добавлен в EasyIoT Cloud, а также отобразится в браузерном интерфейсе и Android-приложении.
![](/ruwiki/images/f/f8/ESP8266_internet_connected_switch_%28EasyIoT_Cloud_MQTT_API_V1%29_-_improved_1_1.png)
![](/ruwiki/images/6/63/ESP8266_internet_connected_switch_%28EasyIoT_Cloud_MQTT_API_V1%29_-_improved_1_2.png)
Если нужно, переключатель можно переименовать и поместить в нужную группу.
Настройка веб-переключателя
Будучи включенным, веб-переключатель пытается подключиться к точке доступа. Если спустя 10 секунд подключиться к точке доступа так и не удается, веб-переключатель переходит в режим точки доступа. Возьмите мобильный телефон и поищите точку доступа с названием «Thing-xx-xx-xx-xx», где «xx-xx-xx-xx» – это набор случайных цифр. Подключитесь к этой точке доступа, а затем введите в браузере IP-адрес «192.168.4.1».
Откроется страница, где вы сможете настроить название SSID и пароль к ней. Указав нужные данные, кликните по кнопке «Submit». После этого веб-переключатель перезагрузится и подключится к указанной точке доступа.
![](/ruwiki/images/3/38/ESP8266_internet_connected_switch_%28EasyIoT_Cloud_MQTT_API_V1%29_-_improved_2_1.png)
См.также
Внешние ссылки
ESP8266 AT-команды | |
---|---|
Список AT-команд | |
Базовые команды |
|
Команды для WiFi |
|
Команды для TCP/IP |
|