ESP8266 MQTT для умного дома не работает автоконект

VitalikNic
Offline
Зарегистрирован: 14.03.2015

Есть модуль ESP8266 он подключен по wifi  к распери пи зеро на котором установлен MajorDoMo есть проблема работы модуля. После отключеня питания на роуторе и его подключения обратно модуль автоматически подключается к роутеру, распери получает данные от модуля, а вот управлять модулем не получается. Но если выключить и включить модуль то все отлично работает.

Сам код собран со всего интернета :)  как заставить получать данные и их выполнять?

#include <MQTT.h>
#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <OneWire.h>
OneWire ds(12);

// Connect to the WiFi
const char* ssid = "**********";
const char* password = "**************";
const char* mqtt_server = "MajorDoMo MQTT";
char* pubTopic = "/ESP8266/DATA";
char* controlTopic = "/ESP8266/CONTROL/#";
int knopka=0;
int knopka1=0;
int temperature = 0;
int counter = 0;
int ms = 0;
int seconds = 0;
int heap = 0;
String mqtt_user = "test";
String mqtt_pass = "test";
String mqtt_client = "ESP8266";
int qwe=0;
long lastUpdateTime = 0;
const int TEMP_UPDATE_TIME = 1000;


WiFiClient espClient;
IPAddress MQTTserver(192, 168, 1, 238); 
PubSubClient client(espClient, MQTTserver);

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
  randomSeed(micros());
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback (const MQTT::Publish& sub){
  Serial.print("Get data from subscribed topic ");
  Serial.print(sub.topic());  // Название топика
  Serial.print(" => ");
  Serial.println(sub.payload_string()); // Данные из топика

  
  if  (sub.topic() == "/ESP8266/CONTROL/GPIO/2")  {
    if  (sub.payload_string() == "0")  {
      digitalWrite(2, LOW);
    }
    if  (sub.payload_string() == "1")  {
      digitalWrite(2, HIGH);
    }
  }

  if  (sub.topic() == "/ESP8266/CONTROL/GPIO/0")  {
    if  (sub.payload_string() == "0")  {
      digitalWrite(0, LOW);
    }
    if  (sub.payload_string() == "1")  {
      digitalWrite(0, HIGH);
    }
  }

  if  (sub.topic() == "/ESP8266/CONTROL/GPIO/4")  {
    if  (sub.payload_string() == "0")  {
      digitalWrite(4, LOW);
    }
    if  (sub.payload_string() == "1")  {
      digitalWrite(4, HIGH);
    }
  }

  if  (sub.topic() == "/ESP8266/CONTROL/GPIO/5")  {
    if  (sub.payload_string() == "0")  {
      digitalWrite(5, LOW);
    }
    if  (sub.payload_string() == "1")  {
      digitalWrite(5, HIGH);
    }
  }

  if  (sub.topic() == "/ESP8266/CONTROL/GPIO/14")  {
   
    //  int intVar;
  //   String stringVar = sub.payload_string();
 //     intVar=stringVar.toInt();
     // qwe = intVar;
 //  analogWrite(14, intVar);
 //  }
    if  (sub.payload_string() == "1")  {
  digitalWrite(14, LOW);
    }
if  (sub.payload_string() == "0")  {
     digitalWrite(14, HIGH);
 }
 }

  
  if  (sub.topic() == "/ESP8266/CONTROL/GPIO/16")  {
    if  (sub.payload_string() == "1")  {
      digitalWrite(16, LOW);
    }
    if  (sub.payload_string() == "0")  {
      digitalWrite(16, HIGH);
    }
  }

  if  (sub.topic() == "/ESP8266/CONTROL/GPIO/15")  {
    if  (sub.payload_string() == "1")  {
      digitalWrite(15, LOW);
    }
    if  (sub.payload_string() == "0")  {
      digitalWrite(15, HIGH);
    }
  }

  if  (sub.topic() == "/ESP8266/CONTROL/GPIO/12")  {
    if  (sub.payload_string() == "1")  {
      digitalWrite(12, LOW);
    }
    if  (sub.payload_string() == "0")  {
      digitalWrite(12, HIGH);
    }
  }

  if  (sub.topic() == "/ESP8266/CONTROL/GPIO/13")  {
    if  (sub.payload_string() == "1")  {
      digitalWrite(13, LOW);
    }
    if  (sub.payload_string() == "0")  {
      digitalWrite(13, HIGH);
    }
  }

   MQTT::Publish newpub(pubTopic, sub.payload(), sub.payload_len());
  client.publish(newpub);
  }
  
void restart() {
  Serial.println("Will reset and try again...");
  abort();
}

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

  // Задаем режим работы GPIO и их начальное состояние
  pinMode(2, OUTPUT);
  digitalWrite(2, 0);
  pinMode(0, OUTPUT);
  digitalWrite(0, 0);
  pinMode(4, OUTPUT);
  digitalWrite(4, 0);
  pinMode(5, OUTPUT);
  digitalWrite(5, 0);
  pinMode(14, INPUT);
  digitalWrite(14, 0);
  pinMode(16, OUTPUT);
  digitalWrite(16, 0);
  pinMode(15, OUTPUT);
  digitalWrite(15, 0);
  pinMode(12, INPUT);
  digitalWrite(12, 0);
  pinMode(13, OUTPUT);
  digitalWrite(13, 0);

  setup_wifi();
//  client.setServer(mqtt_server, 1883);
  client.set_callback(callback);
  Serial.println("Connecting to MQTT broker ");
  if (client.connect(MQTT::Connect(mqtt_client).set_auth(mqtt_user, mqtt_pass))) {
    Serial.println("Connected to MQTT broker");
    client.subscribe(controlTopic);
  } else {
    restart();
  }
  heap = ESP.getFreeHeap();
}

void reconnect() {
  setup_wifi();
 // Loop until we're reconnected
 while (!client.connected()) {
 Serial.print("Attempting MQTT connection...");
 // Attempt to connect
 if (client.connect("ESP8266 Client")) {
  Serial.println("connected");
  // ... and subscribe to topic
  client.subscribe("ledStatus");
 } else {
  Serial.print("failed, rc=");
 //Serial.print(client.state());
  Serial.println(" try again in 5 seconds");
  // Wait 5 seconds before retrying
  delay(5000);
  }
 }
}


void loop()
{
//if (WiFi.getAutoConnect() != true) WiFi.setAutoConnect(true);  //on power-on automatically connects to last used hwAP
//WiFi.setAutoReconnect(true);                                   //automatically reconnects to hwAP in case it is disconnected
  
  if (!client.connected()) {
  reconnect();
  //setup_wifi();
 }
 client.loop();
  detectTemperature();
    if ( micros() / 1000 - ms  > 1000 || ms > micros() / 1000 ) {
    if ( heap > ESP.getFreeHeap() ) {
      Serial.println("Detect mem leak!");
      heap = ESP.getFreeHeap();
    }
    ms = micros() / 1000;
    ++seconds;
  }

 if(digitalRead(14)==HIGH&&knopka==0)//если кнопка нажата
// и перемення "knopka" равна 0 , то ...
{
//delay(50);//защита от дребезга
knopka++;//пишем 1 в переменную кнопка
//это нужно для того что бы с каждым нажатием кнопки
//происходило только одно действие
digitalWrite(14, !digitalRead(14));//меняем значение порта на противоположное
//Считываем данные из  ADC
   // int knopka = digitalRead(12);
   String ADCString = String(knopka);
    Serial.print("ADC = ");
    Serial.print(knopka);

    //Публикуем ADC в топике
    if (client.publish("/ESP8266/DATA/KNOPKA",  ADCString)) {
      Serial.println(" Publish ok");
    }
else {
   Serial.println(" Publish failed");
  }   

}
  if(digitalRead(14)==LOW&&knopka==1)//если кнопка НЕ нажата
//и переменная knopka равна - 1 ,то ...
{
knopka=0;//обнуляем переменную "knopka"
//}

    //Считываем данные из  ADC
    //int knopka = digitalRead(12);
   String ADCString = String(knopka);
    Serial.print("ADC = ");
    Serial.print(knopka);

    //Публикуем ADC в топике
    if (client.publish("/ESP8266/DATA/KNOPKA",  ADCString)) {
      Serial.println(" Publish ok");
    }
else {
     Serial.println(" Publish failed");

}
}

  if ( seconds >= 10 ) {
    seconds = 0;
    ++counter;

String ADCString = String(temperature);
    //Публикуем ADC в топике
    if (client.publish("/ESP8266/DATA/TEMPERAT", ADCString))
 //   printTemperature(Thermometer1);
    {
      Serial.println(" Publish ok");
    }
    else {
     Serial.println(" Publish failed");
    }

  }
  if ( !client.loop() )  {
    restart();
  }
  yield();
}

int detectTemperature(){
  byte data[2];
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);
  if (millis() - lastUpdateTime > TEMP_UPDATE_TIME)
 {
    lastUpdateTime = millis();
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    data[0] = ds.read();
    data[1] = ds.read();
    temperature = (data[1] << 8) + data[0]; temperature = temperature >> 4;
  }
 }

 

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

Вы в setup() подписываетесь на топик '/ESP8266/CONTROL/#'
строка 189 client.subscribe(controlTopic)
а в reconnect() той самой которую вызываете в случае потери соединения с брокером, уже подписываетесь совершенно на другой топик 'ledStatus'
не понятно зачем на другой, если обработчик callback (const MQTT::Publish& sub) его совсем не обрабатывает.

VitalikNic
Offline
Зарегистрирован: 14.03.2015

Спасибо за подскаску, я поправил код, но нашел причину в неработоспособности реконекта 

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

полностью работает. Оказывается это глобальная и известная проблема, и все знают кроме меня :)

 

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

укжите какие версии? или дайте ссылку на рабочую библиотеку 8266.

VitalikNic
Offline
Зарегистрирован: 14.03.2015

Нужно установить esp8266 by ESP8266 Community версия 2.2.0 реконект стабильно работает

А вот если поставить 2.3.0 работает не стабильно, в версии 2.4.0 писали что сломалась данная функия для платок ESP8266