• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

скетч с конфигуратором в eeprom, сервер и клиент

Vitaly

Member
Возможно надо проверять наличие клиента на AP и ждать, когда он деактивируется.
Вот давно интересовало, через ардуиновые либы есть возможность узнать о подключении клиента к нашей AP
В самих либах ничего не нашел) Наверное пока никак

А про отключении AP и проверки клиентов - если бы это был не режим настройки необходимый раз в полгода, обязательно надо было б проверять.
Но раз это только на время смены настроек точки, то думаю можно оставить как есть.
 

pvvx

Активный участник сообщества
Вот давно интересовало, через ардуиновые либы есть возможность узнать о подключении клиента к нашей AP
В самих либах ничего не нашел) Наверное пока никак
Разве нет доступа к [inline]i = wifi_softap_get_station_num(); // Number count of stations which connected to ESP8266 soft-AP[/inline] ?
Без обработки событий WiFi (wifi_set_event_handler_cb(wifi_handle_event_cb)) жить сложно, т.к. текущий порт Arduino IDE для ESP не многозадачен...
 

random1st

New member
Не нашел я времени переписать скрипт. Я немного другое для себя писал, более узкозаточенное. Вот, выкладываю переписанные процедуры работы с EEPROM:
http://pastebin.com/Tj3EiZbe

Да, еще - нет никакой необходимости писать свой веб-сервер. Есть готовая реализация <ESP8266WebServer.h> -там только обработчики на урлы повесить и все замечательно, поддерживает и post, и get, и параметры парсить умеет (правда, не умеет url_decode и html_escape)
 

kod.begemot

New member
Спасибо большое! Это очень интересно, буду пробовать. Из примеров "в лоб" не получилось, а так намного проще.
И ещё, прошу прощения за "ламерский" вопрос, но - чтобы писать / читать ещё данные, кроме этих, нужно дописать их в структуру "eeprom_data_t", и этого достаточно - правильно?
 

sivix

New member
Не могу загрузить IPиз EEPROM

День добрый! Делаю проект и столкнулся с проблемой. Сохроняю в EEPROM

IPадрес . далее пытаюсь его прочитать и передать IPAddress server(EEPROM.read(7), EEPROM.read(8), EEPROM.read(9), EEPROM.read(10));

Но увы клиент не конектится к серверу. Если прописать все руками то работает. Но мне нужен динамический адрес .
 

Vitaly

Member
ничего не понятно, для tcp подключения адрес используется в строковом виде, не нужен тип IPAddress
чтоб иметь возможность менять адрес лучше использовать dns
работа с еепром в есп нестандартная, учтено ли это:
http://esp8266.ru/arduino-ide-esp8266/#eeprom
Необходимо вызвать функцию EEPROM.begin(size) каждый раз перед началом чтения или записи, размер (указывается в байтах) соответствует размеру данных, которые вы намереваетесь использовать в EEPROM. Размер данных должен быть в диапазоне от 4 до 4096 байт.
итд.
 

sivix

New member
Виталий приветствую! О EEPROM.begin(size) конечно знаю. Все остальные параметры у меня подгружаются. это не важно. Важно то что не работает. Сейчас попытаюсь объяснить. Тут я выкладываю код проблемы, а не свой скетч. Я накидал скетч он прошивается и подключается к WIFI и серверу MQTT. Как вы и говорили можно просто текст для IP адреса передать.
Но проблема осталось.
Начнем по порядку. Что-бы стартануть память нужно вызвать в setup() EEPROM.begin(512) ,до setup не получится . Тем самым переносим ниже setup PubSubClient client(wclient, ip);. Все память стартует записывает изменения в переменную IP, вроде как все должно работать но модуль конектится к адресу указному в месте объявления переменной IP. Далее тестовый код . Я не стал в тестовом коде реализовывать чтение из памяти. А просто создал переменную IP String . до setup. и в setup пытаюсь поменять текст. Но модуль подключается MQTT серверу прописному при объявлении переменной. Вывод в терминал такой. при старте выводит прописанный при создании переменной, после прохождения setup выводит измененный IP. В теории все должно работать. Но по факту берет IP который записан до Setup.
Дело даже не в чтении памяти. И не знаю как быть.

Вывод из терминала

Код:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
#define DHTPIN D2
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE,11);

const char *ssid =    ".......";        // cannot be longer than 32 characters!
const char *pass =    "......";        //

// Update these with values suitable for your network.

char* pubTopic = "home/data/#";
char* dev_top = "home/data/device";
char* statTopic = "home/data/status/";
String mqtt_user = "test";
String mqtt_pass = "test";
String mqtt_client_id = "00001";
String mqtt_client = "DHT_sensor";
unsigned long lastMqtt = 0;
boolean callback_set = true;
String ip = "IP сервера MQTT";




void setup() {
  // Setup console
  Serial.begin(115200);
  delay(10);
  Serial.println();
  Serial.println(ip);
  dht.begin();
//  client.set_callback(callback);
  ip = "192.168.1.1";
  Serial.println(ip);
}
//IPAddress server(EEPROM.read(7), EEPROM.read(8), EEPROM.read(9), EEPROM.read(10));

WiFiClient wclient;
PubSubClient client(wclient, ip);

void callback(const MQTT::Publish& sub) {
  Serial.print("Get data from subscribed topic ");
  Serial.print(sub.topic());
  Serial.print(" => ");
  Serial.println(sub.payload_string());


  client.publish(statTopic, "test");
  Serial.println(statTopic);

  // echo
  MQTT::Publish newpub(pubTopic, sub.payload(), sub.payload_len());
  client.publish(newpub);
}
void loop() {

   if(callback_set){
     client.set_callback(callback);
     callback_set =false;
 
  }
  if (lastMqtt > millis()) lastMqtt = 0;
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print("Connecting to ");
    Serial.print(ssid);
    Serial.println("...");
    WiFi.begin(ssid, pass);

    if (WiFi.waitForConnectResult() != WL_CONNECTED)
      return;
    Serial.println("WiFi connected");
  }

  if (WiFi.status() == WL_CONNECTED) {
    if (!client.connected()) {
      if (client.connect(mqtt_client)) {
        client.publish(dev_top, mqtt_client_id);
        float h = dht.readHumidity();
       float t = dht.readTemperature();
       char char_temp[10]; //Временная переменная для перевода Float в char
       char char_hum[10];
       dtostrf(h, 1, 0, char_temp);
       dtostrf(t, 1, 0, char_hum);
       client.publish("home/data/status/sensor/DHT_00001_t", char_temp);
       client.publish("home/data/status/sensor/DHT_00001_h", char_hum);
        client.subscribe("home/data/action/#");
      }
    }

    if (client.connected())
      client.loop();
  }
  if (millis() > (lastMqtt + 50000)) {
    if (!client.connected()) {
      if (client.connect("system_01V_eth")) client.subscribe("home/data/action/#");
    }
    if (client.connected()) {
       float h = dht.readHumidity();
       float t = dht.readTemperature();
       char char_temp[10]; //Временная переменная для перевода Float в char
       char char_hum[10];
       dtostrf(h, 1, 0, char_temp);
       dtostrf(t, 1, 0, char_hum);
       client.publish("home/data/status/sensor/DHT_00001_t", char_temp);
       client.publish("home/data/status/sensor/DHT_00001_h", char_hum);  
    }
    lastMqtt = millis();
  }
}
Может нужно как то по другому передавать IP. проблема только в этом.
 
Последнее редактирование:

sivix

New member
Виталий приветствую! О EEPROM.begin(size) конечно знаю. Все остальные параметры у меня подгружаются. это не важно. Важно то что не работает. Сейчас попытаюсь объяснить. Тут я выкладываю код проблемы, а не свой скетч. Я накидал скетч он прошивается и подключается к WIFI и серверу MQTT. Как вы и говорили можно просто текст для IP адреса передать.
Но проблема осталось.
Начнем по порядку. Что-бы стартануть память нужно вызвать в setup() EEPROM.begin(512) ,до setup не получится . Тем самым переносим ниже setup PubSubClient client(wclient, ip);. Все память стартует записывает изменения в переменную IP, вроде как все должно работать но модуль конектится к адресу указному в месте объявления переменной IP. Далее тестовый код . Я не стал в тестовом коде реализовывать чтение из памяти. А просто создал переменную IP String . до setup. и в setup пытаюсь поменять текст. Но модуль подключается MQTT серверу прописному при объявлении переменной. Вывод в терминал такой. при старте выводит прописанный при создании переменной, после прохождения setup выводит измененный IP. В теории все должно работать. Но по факту берет IP который записан до Setup.
Дело даже не в чтении памяти. И не знаю как быть.

Вывод из терминала

Код:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
#define DHTPIN D2
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE,11);

const char *ssid =    ".......";        // cannot be longer than 32 characters!
const char *pass =    "......";        //

// Update these with values suitable for your network.

char* pubTopic = "home/data/#";
char* dev_top = "home/data/device";
char* statTopic = "home/data/status/";
String mqtt_user = "test";
String mqtt_pass = "test";
String mqtt_client_id = "00001";
String mqtt_client = "DHT_sensor";
unsigned long lastMqtt = 0;
boolean callback_set = true;
String ip = "IP сервера MQTT";




void setup() {
  // Setup console
  Serial.begin(115200);
  delay(10);
  Serial.println();
  Serial.println(ip);
  dht.begin();
//  client.set_callback(callback);
  ip = "192.168.1.1";
  Serial.println(ip);
}
//IPAddress server(EEPROM.read(7), EEPROM.read(8), EEPROM.read(9), EEPROM.read(10));

WiFiClient wclient;
PubSubClient client(wclient, ip);

void callback(const MQTT::Publish& sub) {
  Serial.print("Get data from subscribed topic ");
  Serial.print(sub.topic());
  Serial.print(" => ");
  Serial.println(sub.payload_string());


  client.publish(statTopic, "test");
  Serial.println(statTopic);

  // echo
  MQTT::Publish newpub(pubTopic, sub.payload(), sub.payload_len());
  client.publish(newpub);
}
void loop() {

   if(callback_set){
     client.set_callback(callback);
     callback_set =false;

  }
  if (lastMqtt > millis()) lastMqtt = 0;
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print("Connecting to ");
    Serial.print(ssid);
    Serial.println("...");
    WiFi.begin(ssid, pass);

    if (WiFi.waitForConnectResult() != WL_CONNECTED)
      return;
    Serial.println("WiFi connected");
  }

  if (WiFi.status() == WL_CONNECTED) {
    if (!client.connected()) {
      if (client.connect(mqtt_client)) {
        client.publish(dev_top, mqtt_client_id);
        float h = dht.readHumidity();
       float t = dht.readTemperature();
       char char_temp[10]; //Временная переменная для перевода Float в char
       char char_hum[10];
       dtostrf(h, 1, 0, char_temp);
       dtostrf(t, 1, 0, char_hum);
       client.publish("home/data/status/sensor/DHT_00001_t", char_temp);
       client.publish("home/data/status/sensor/DHT_00001_h", char_hum);
        client.subscribe("home/data/action/#");
      }
    }

    if (client.connected())
      client.loop();
  }
  if (millis() > (lastMqtt + 50000)) {
    if (!client.connected()) {
      if (client.connect("system_01V_eth")) client.subscribe("home/data/action/#");
    }
    if (client.connected()) {
       float h = dht.readHumidity();
       float t = dht.readTemperature();
       char char_temp[10]; //Временная переменная для перевода Float в char
       char char_hum[10];
       dtostrf(h, 1, 0, char_temp);
       dtostrf(t, 1, 0, char_hum);
       client.publish("home/data/status/sensor/DHT_00001_t", char_temp);
       client.publish("home/data/status/sensor/DHT_00001_h", char_hum); 
    }
    lastMqtt = millis();
  }
}
Может нужно как то по другому передавать IP. проблема только в этом.
Победа. Нужно делать так.
С начало иниц. клиента
WiFiClient wclient;
PubSubClient client(wclient);
У же потом в setup()
говорим ему IP.
client.set_server(ip,1883);
И все работает.

Все спасибо кто откликнулся.
 

Adney

New member
Дабы не плодить тему, набросал тоже простенькую заготовку сохранения параметров в eeprom. При первом запуске модуль ( у меня esp-01) включается в режиме открытой точки доступа. Далее, по адресу 192.168.4.1 открываем страницу настроек, в которой указываем SSID и пароль точки, к которой надо подключиться, жмем Save и перегружаемся. После перезагрузки модуль цепляется к точке доступа.
Вечер добрый.
Подскажите как переделать Ваш код, что бы запись ssid и пароля была во flesh, а не в eeprom?
 

espeshka

New member
Доброго времени суток, подскажите как добавить в Ваш код доп поля со статикой (ip,msk, gw) для STA?
 

Vitaly

Member
поля в настройку через веб, чтобы сохранялись и использовались при поднятии ста?

добавить в структуру для сохранения нужные текстовые поля и флаг, значения по умолчанию в них при прочтении неинициализированной памяти
добавить в страницу текстовые поля и флаг "использовать статику"
добавить в разбор параметров парсинг этих строк и определение их в структуру для памяти и сохранение в память
добавить в место инициализации ста проверку на флаг статического адреса и использование этих строк
 

espeshka

New member
поля в настройку через веб, чтобы сохранялись и использовались при поднятии ста?

добавить в структуру для сохранения нужные текстовые поля и флаг, значения по умолчанию в них при прочтении неинициализированной памяти
добавить в страницу текстовые поля и флаг "использовать статику"
добавить в разбор параметров парсинг этих строк и определение их в структуру для памяти и сохранение в память
добавить в место инициализации ста проверку на флаг статического адреса и использование этих строк
спасибо за отклик
да, нужно через веб-форму добавлене статического ip и т.д. и чтобы сохранялись и читались.

сделал следующее:
1) >processWeb
Код:
        else if (param.substring(0, addr_start) == "STAstatic")
        {
          param = param.substring(addr_start + 1);
          addr_end = param.indexOf('&');
          if (addr_end != -1)
          {
            lSTASTATIC = param.substring(0, addr_end);
            param = param.substring(addr_end + 1);
          }
          else
            lSTASTATIC = param.substring(0, addr_end);
        }

//--------------
        else if (param.substring(0, addr_start) == "ip0")
        {
          param = param.substring(addr_start + 1);
          addr_end = param.indexOf('&');
          if (addr_end != -1)
          {
            lDTIP0 = param.substring(0, addr_end);
            param = param.substring(addr_end + 1);
          }
          else
            lDTIP0 = param.substring(0, addr_end);
        }

Код:
      if (lSSID.length() > 0  && lHTTPUSER.length() > 0  && lHTTPPASS.length() > 0  &&
          (lSTAenabled == "true" || lSTAenabled == "false") && (lsenderEnabled == "true" || lsenderEnabled == "false")
          && (ldisableAP == "true" || ldisableAP == "false") && (lHTTPAuthEnabled == "true" || lHTTPAuthEnabled == "false")
          && (lSTASTATIC == "static" || lSTASTATIC == "dhcp"))

  if (lSTASTATIC == "static")
  eeprom_data.STASTATIC = true;
  else
  eeprom_data.STASTATIC = false;
в eeprom_data объявил переменные ipA, ipB,ipC,ipD тип byte

далее
String lDTIP0;
String lDTIP1;
String lDTIP2;
String lDTIP3;

lDTIP0.getBytes(eeprom_data.ipA,sizeof(eeprom_data.ipA));
lDTIP1.getBytes(eeprom_data.ipB,sizeof(eeprom_data.ipB));
lDTIP2.getBytes(eeprom_data.ipC,sizeof(eeprom_data.ipC));
lDTIP3.getBytes(eeprom_data.ipD,sizeof(eeprom_data.ipD));

write_settings();

затем веб-форма:
HTML:
    s += "<br>TYPE: <select name=\"STAstatic\">";
    if (eeprom_data.STASTATIC == true)
   {
      s += "<option value =\"true\" selected=\"selected\">static</option>";
      s += "<option value =\"false\">dhcp</option>";
    }
    else
    {
      s += "<option value =\"true\">static</option>";
      s += "<option value =\"false\" selected=\"selected\">dhcp</option>";
    }
s += "</select>";

        s += "<br>IP: <input type=text name=STAip size=16 maxlength=16 value='";
    s += (eeprom_data.ipA,DEC); 

    s += "' />";

далее
Код:
void STAinit() {

  WiFi.begin(eeprom_data.STAssid, eeprom_data.STApass);

  if (eeprom_data.STASTATIC == true)
{
Serial.println("STA network settings:");

union ArrayToInteger {
  byte array[4];
  uint32_t ipint;
};

ArrayToInteger converter;

converter.array[0] = eeprom_data.ipA;
converter.array[1] = eeprom_data.ipB;
converter.array[2] = eeprom_data.ipC;
converter.array[3] = eeprom_data.ipD;
WiFi.config(converter.ipint, IPAddress(192,168,10,1), IPAddress(255,255,255,0));
}

прошу помощи, бьюсь уже который день ни как не могу осилить
 
Последнее редактирование:

Vitaly

Member
немного непонятно - все парсится и сохраняется, но не применяется в момент настройки клиента?

я просто статик пока не пробовал, сложно так говорить
 

espeshka

New member
немного непонятно - все парсится и сохраняется, но не применяется в момент настройки клиента?

я просто статик пока не пробовал, сложно так говорить
спасибо за ответ,с динамикой все работает стабильно, но актуально для девайса чтобы был статический ip
 

Vitaly

Member
в какой момент перестает работать? параметры парсит, сохраняет, загружает?

могу у себя скетч запустить глянуть
 

krepton85

Member
Бродил тут по интернету в поисках этой темы и первым делом наткнулся на отличный скетч на данную тематику - конфигуратор mqtt или web сервера через точку доступа + замечательная функция OTA (обновление прошивки по воздуху прямо с браузера).
Что бы скомпилировать этот мультискетч я потратил целый день, оказалось нужно подредактировать библиатеку pubsubclient. В итоге все собралось, все заработало как часы :) Но мне этого мало и я решил увеличить колличество подписок и пабликов mqtt до 4 шт, ну а потом еще и радиоприемник на 315 Мгц что бы с радиобрелков управлять тоже (но до их дело не дашло) в итоге так и не поборол mqtt, удалось только через web интерфейс размножить до 4 каналов.

Сцылка на гитхаб:
ESP_WiFiSwitch/ at master · biohazardxxx/ESP_WiFiSwitch · GitHub
Может кто допилит мне этот чудо скетчь. :)
 

Denis Karasiov

New member
Добрый день.

Возможно, вопрос окажется глупым, но пока мне так не кажется... И в теме не увидел на эту тему постов.

Вот часть кода:
Код:
...
#define EEPROM_START 0;
...
void readSettingsESP() {
  ...
  for (i = EEPROM_START; i < sizeof(eeprom_data); i++)
    { ... }
}
Если я правильно понял, то EEPROM_START - это начало блока памяти в EEPROM, откуда начинается чтение/запись наших данных. Тогда, если этот блок не в начале памяти, а где-то в середине, а блок данных, например, 4 байта. Он работать не будет. Если я правильно понимаю, то должно быть так:
Код:
for (i = EEPROM_START; i < EEPROM_START+sizeof(eeprom_data); i++)
Или я что-то не понял?
 
Последнее редактирование:
Сверху Снизу