• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Помогите сделать управление esp8266 по wifi с помощью другой esp8266

SugreonLeks

New member
Здравствуйте. Задача такая.
Есть esp8266 с web интерфейсом (кнопки ON и OFF), работает как клиет по wifi и подключается ко второй esp8266.
Есть вторая esp8266, которая раздаёт интернет по wifi (server).
Если включить обе esp8266 они видят друг друга и если подключится телефоном к esp8266 и открыть браузер, можно зайти на esp8266 и управлять кнопками ON и OFF.
Как сделать так, что бы когда включалась esp8266 server и соединялась со второй esp8266, server эмитировал нажатие на кнопки как делается это на телефоне через браузер?

Выкладываю два кода программы, помогите пожалуйста.


----------------------------------------------------------


Клиент:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

//#include <BlynkSimpleEsp8266.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(D1, D2); // RX, TX
String motion ;
MDNSResponder mdns;

// Wi-Fi
const char* ssid = "test";
const char* password = "12345678";

byte arduino_mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(192, 168, 2, 2);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);

ESP8266WebServer server(80);

int D0_pin = 16;
int D2_pin = 2;
int D1_pin = 5;
long rssi;
long rssi2;
long rssi3;
long rssi4;
long rssi5;
long pik;
long sing;
long singu;

void setup(void) {

Serial.begin(115200); //Скорость порта для связи Arduino с компьютером
Serial.println("Goodnight moon!");
mySerial.begin(115200); //Скорость порта для связи Arduino с GSM модулем
mySerial.println("AT");

pinMode(D4, INPUT);
pinMode(D7, INPUT);
pinMode (D0, OUTPUT) ;
pinMode (D3, OUTPUT) ;
pinMode (D5, OUTPUT) ;
pinMode (D4, OUTPUT) ;
pinMode (D6, OUTPUT) ;

delay(2000);
Serial.begin(115200);
// Debug console
WiFi.mode(WIFI_STA);

// while (WiFi.status() != WL_CONNECTED)
// Blynk.begin(auth, ssid, pass);
// You can also specify server:
//Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 8442);
//Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8442);
pik = 0;
sing = 2;
singu = 2;

// preparing GPIOs
pinMode(D0_pin, OUTPUT);
digitalWrite(D0_pin, LOW);
pinMode(D2_pin, OUTPUT);
digitalWrite(D2_pin, LOW);
pinMode(D1_pin, OUTPUT);
digitalWrite(D1_pin, LOW);


delay(100);
Serial.begin(115200);
WiFi.begin(ssid, password);
WiFi.config(ip, gateway, subnet);


Serial.println("");

// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());

if (mdns.begin("esp8266", WiFi.localIP())) {
Serial.println("MDNS responder started");
}

//+++++++++++++++++++++++ START LED-1 ++++++++++++++++++++
server.on("/", []() {
server.send(200, "text/html", webPage());
});
server.on("/socket1On", []() {
digitalWrite(D0_pin, HIGH);
server.send(200, "text/html", webPage());
delay(100);

});
server.on("/socket1Off", []() {
digitalWrite(D0_pin, LOW);
server.send(200, "text/html", webPage());
delay(100);
//+++++++++++++++++++++++ END LED-1 ++++++++++++++++++++

//+++++++++++++++++++++++ START LED-2 ++++++++++++++++++++
});
server.on("/socket2On", []() {
digitalWrite(D2_pin, HIGH);
server.send(200, "text/html", webPage());
delay(100);
});
server.on("/socket2Off", []() {
digitalWrite(D2_pin, LOW);
server.send(200, "text/html", webPage());
delay(100);

// +++++++++++++++++++++++ END LED-2 ++++++++++++++++++++

//+++++++++++++++++++++++ START LED-3 ++++++++++++++++++++
});
server.on("/socket3On", []() {
digitalWrite(D1_pin, HIGH);
server.send(200, "text/html", webPage());
delay(100);
});
server.on("/socket3Off", []() {
digitalWrite(D1_pin, LOW);
server.send(200, "text/html", webPage());
delay(100);

// +++++++++++++++++++++++ END LED-3 ++++++++++++++++++++


});
server.begin();
Serial.println("HTTP server started");
}

void loop(void) {
server.handleClient();


if (mySerial.available())
Serial.write(mySerial.read());
if (Serial.available())
mySerial.write(Serial.read());


long rssi = WiFi.RSSI();

}

String webPage()
{
String web;
web += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/> <meta charset=\"utf-8\"><title>ESP 8266</title><style>button{color:red;padding: 10px 27px;}</style></head>";
web += "<h1 style=\"text-align: center;font-family: Open sans;font-weight: 100;font-size: 20px;\">ESP8266 Web Server</h1><div>";
//++++++++++ LED-1 +++++++++++++
web += "<p style=\"text-align: center;margin-top: 0px;margin-bottom: 5px;\">----LED 1----</p>";
if (digitalRead(D0_pin) == 1)
{
web += "<div style=\"text-align: center;width: 98px;color:white ;padding: 10px 30px;background-color: #43a209;margin: 0 auto;\">ON</div>";
}
else
{
web += "<div style=\"text-align: center;width: 98px;color:white ;padding: 10px 30px;background-color: #ec1212;margin: 0 auto;\">OFF</div>";
}
web += "<div style=\"text-align: center;margin: 5px 0px;\"> <a href=\"socket1On\"><button>ON</button></a>&nbsp;<a href=\"socket1Off\"><button>OFF</button></a></div>";
// ++++++++ LED-1 +++++++++++++

//++++++++++ LED-2 +++++++++++++
web += "<p style=\"text-align: center;margin-top: 0px;margin-bottom: 5px;\">----Сигнализация----</p>";
if (digitalRead(D2_pin) == 1)
{
web += "<div style=\"text-align: center;width: 98px;color:white ;padding: 10px 30px;background-color: #43a209;margin: 0 auto;\">ON</div>";
}
else
{
web += "<div style=\"text-align: center;width: 98px;color:white ;padding: 10px 30px;background-color: #ec1212;margin: 0 auto;\">OFF</div>";
}
web += "<div style=\"text-align: center;margin: 5px 0px;\"> <a href=\"socket2On\"><button>ON</button></a>&nbsp;<a href=\"socket2Off\"><button>OFF</button></a></div>";
// ++++++++ LED-2 +++++++++++++

//++++++++++ LED-3 +++++++++++++
web += "<p style=\"text-align: center;margin-top: 0px;margin-bottom: 5px;\">----LED 3----</p>";
if (digitalRead(D1_pin) == 1)
{
web += "<div style=\"text-align: center;width: 98px;color:white ;padding: 10px 30px;background-color: #43a209;margin: 0 auto;\">ON</div>";
}
else
{
web += "<div style=\"text-align: center;width: 98px;color:white ;padding: 10px 30px;background-color: #ec1212;margin: 0 auto;\">OFF</div>";
}
web += "<div style=\"text-align: center;margin: 5px 0px;\"> <a href=\"socket3On\"><button>ON</button></a>&nbsp;<a href=\"socket3Off\"><button>OFF</button></a></div>";
// ++++++++ LED-2 +++++++++++++

// ========REFRESH=============
web += "<div style=\"text-align:center;margin-top: 20px;\"><a href=\"/\"><button style=\"width:158px;\">REFRESH</button></a></div>";
// ========REFRESH=============


web += "</div>";
return (web);
}

********************************************************************************
********************************************************************************
********************************************************************************


Сервер:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

/* Установите здесь свои SSID и пароль */
const char* ssid = "test"; // SSID
const char* password = "12345678"; // пароль
const char* host = "192.168.2.2";
/* Настройки IP адреса */
IPAddress local_ip(192, 168, 2, 1);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80);

void setup()
{
Serial.begin(115200);


WiFi.softAP(ssid, password);
WiFi.softAPConfig(local_ip, gateway, subnet);
delay(100);
}

void loop()
{
server.handleClient();

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

WiFiClient client; // Класс WiFiClient используется для создания подключения по TCP
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed"); // Если сайт недоступен
return; // Прерываем данную итерацию цикла
}

Serial.println();
Serial.println("closing connection");
delay(5000);


}

--------------------------------------------------------------------------------------
 

yurik72

Member
Честно говоря, надо понимать задачу. Возможно решается другими способами. В данной постановке необходимо твоему серверу постоянно иметь список клиентов и что то отсылать. Упуская это из виду, вопрос то в другом.
Надо на сервере написать часть которая как browser отсылает команды на ESP
 

yurik72

Member
Честно говоря, надо понимать задачу. Возможно решается другими способами. В данной постановке, необходимо твоему серверу постоянно иметь список клиентов и что то отсылать. Упуская это из виду, вопрос то в другом.
Надо на сервере написать часть которая как browser отсылает команды на ESP
Для этого используй класс HTTPClient, т.е. на сервере код примерно

WiFiClient client;
HTTPClient http;
if (http.begin(client,"http://<IP or HostName>/socket1On")) {

int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0) { // HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d ", httpCode);
}
}


-------
Упускаю из виду как ты определишь <IP or HostName>
 

pvvx

Активный участник сообщества
Упускаю из виду как ты определишь <IP or HostName>
И как определить текущее состояние переключателя.
Т.е. всё упускаете. :)
Классическое решение лежит в области создания локального сервера-хранилища состояний со связью с внешними устройствами. Если устройство меняет состояние - оно оповещает сервер и наоборот, но опять-же внешнее устройство опрашивает сервер. А весь протокол с изменениями состояний устройств осуществляется с данными от сервера, а не самого устройства.
В такой схеме не надо выяснять кто и где и каждая функция может быть разнесена на разные устройства.
 

pvvx

Активный участник сообщества
А самый примитивный протокол для связи с базой - это Modbus TCP. Хотите никчемного усложнения системы и наворота - тогда MQTT.
Для каждого устройства выделяете поля в адресном пространстве памяти и пишите примитивный шлюз типа Modbus-Websocket и подобные, чтобы управлять всей системой удаленно с помощью простейших статических (!) HTML-JS страниц, которые размещаются совершенно где угодно.
И у вас возникает преимущество в том, что вы имеете полный снимок состояния всех устройств в одном флаконе... Т.е. можете закрутить любые зависимости между устройствами.
 

SugreonLeks

New member
В Будущем будет сделано 4 физических кнопки. При нажатии на одну, надо что бы был послан сигнал приметно такого типа:
http://192.168.2.2/socket2On или http://192.168.2.2/socket2Off
В телефоне при нажатие на кнопку именно эти адреса появляются в браузере. Необходимо что бы esp8266 сама нажимала эти кнопки или посылала запрос как в браузере.
 

SugreonLeks

New member
Получилось. Спасибо очень огромное всем кто помог.

Вот итоговый код.


void loop()
{
server.handleClient();

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

WiFiClient client; // Класс WiFiClient используется для создания подключения по TCP

const int httpPort = 80;
HTTPClient http;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed"); // Если сайт недоступен
return; // Прерываем данную итерацию цикла
}


if (http.begin(client,"http://192.168.2.2 /socket2On")) {

int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0) { // HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d ", httpCode);
}
}

delay(1000);

if (http.begin(client,"http://192.168.2.2 /socket2Off")) {

int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0) { // HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d ", httpCode);
}
}

delay(10);



Serial.println();
Serial.println("closing connection");
delay(1000);


}

Тема закрыта.
 

yurik72

Member
И как определить текущее состояние переключателя.
Т.е. всё упускаете. :)
Ну человек задал конкретный вопрос и получил конкретный ответ. Он же не описал задачу свою.
Тем более получилось у него, чем и рады за него.
Можно конечно городить все что угодно и MQTT и ModBus. Главное чтобы задача была решена :)
В данном конкретном примере мой совет SugreonLeks
задуматься над решенией задачи от обратного, Т.е. когда клиент ( исходя из примера выше) просыпается или постоянно в цикле отсылает запрос на сервер , по примеру приведенному мной, а сервер принимает решение и отвечает клиентy, что сделать

Т.е. мы еще имплементируем такой же webserver на стороне СЕРВЕР.
Клиент шлет например запрос http://server/socketon (если включен), а сервер отвечает
например 0 или 1, соответственно, что сделать дальше. при такой архитектуре серверу не надо заботиться и знать кто подключен. Все "живые" клиенты сами спрашивают что делать

P.S. ради будущих комментов, добавлю что помог решить человеку задачу. И предложенный вариант конечно примитивный. Я например в своих задачах, если не используется что то аля MQTT, всегда обмениваюсь не простыми get/post запросами а с телом содержащим json...
 

pvvx

Активный участник сообщества
P.S. ради будущих комментов, добавлю что помог решить человеку задачу. И предложенный вариант конечно примитивный. Я например в своих задачах, если не используется что то аля MQTT, всегда обмениваюсь не простыми get/post запросами а с телом содержащим json...
Угу - так и развивается тупость, а потом говорят что оно "работает" :)
Гнать халтуру и советовать это другим не все могут себе позволить. :p
 

SugreonLeks

New member
Спасибо за советы. В данном случае мне именно это решение и было нужно, простое. Так как не надо отслеживать что в каком положение находится. Клиент опрашивает сервер, и как только сервер появился на связи, сервер ему сказал что и как делать, тот выполнил и всё. Я понимаю что оно должно "немножко" по другому работать.
Спасибо за помощь.
 

Atom

Member
Хотите никчемного усложнения системы и наворота - тогда MQTT.
Ну почему же никчемного? отладку MQTT можно вести в консоли, не используя специализированного ПО. А вот с ModBus нужно еще тулчэйн собрать. И чаще всего не бесплатный.
Хотя тут как в сексе - все на любителя, что другие могут назвать извращением.
 
Сверху Снизу