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

Решено MajorDomo и ESP8266

Snezhana

New member
Ребята помогите решить задачу.
Плата ESP8266 управляет тремя реле через MajorDomo
Вот скетч:
Код:
// Блок [Подключение библиотек] ************************************************
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// END Блок [Подключение библиотек] ********************************************

// Блок [Подключение к сети WI-FI] *********************************************
const char* ssid = "ssid";                // Имя WI-FI сети
const char* password = "password";        // Пароль WI-FI сети
const char* mqtt_server = "192.168.200.251";      // IP адрес MQTT сервер
// END Блок [Подключение к сети WI-FI] *****************************************

#define RELE_1 14                               // Реле №1
#define RELE_2 12                               // Реле №2
#define RELE_3 13                               // Реле №3
#define BUTTON_1 16                               // Кнопочный выключатель №1
#define BUTTON_2 5                                // Кнопочный выключатель №2
#define BUTTON_3 4                                // Кнопочный выключатель №3
#define relays_topic1 "ESP01/RELE_1"              // Топик реле №1
#define relays_topic2 "ESP01/RELE_2"              // Топик реле №2
#define relays_topic3 "ESP01/RELE_3"            // Топик реле №3



WiFiClient espClient;
PubSubClient client(espClient);

long last_mls = millis();
char msg[50];
boolean rState1 = false;
boolean rState2 = false;
boolean rState3 = false;
boolean btnPress1 = false;
boolean btnPress2 = false;
boolean btnPress3 = false;
boolean lastbtnStat1 = false;
boolean lastbtnStat2 = false;
boolean lastbtnStat3 = false;

void setup() {
  pinMode(RELE_1, OUTPUT);
  pinMode(RELE_2, OUTPUT);
  pinMode(RELE_3, OUTPUT);
  pinMode(BUTTON_1, INPUT);
  pinMode(BUTTON_2, INPUT);
  pinMode(BUTTON_3, INPUT);
  digitalWrite(RELE_1, rState1);
  digitalWrite(RELE_2, rState2);
  digitalWrite(RELE_3, rState3);
  Serial.begin(115200);
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  delay(100);
  WiFi.begin(ssid, password);
  delay(6000);
  client.connect("ESP8266Client");
  client.subscribe(relays_topic1);
  client.subscribe(relays_topic2);
  client.subscribe(relays_topic3);

  lastbtnStat1 = digitalRead(BUTTON_1);
  lastbtnStat2 = digitalRead(BUTTON_2);
  lastbtnStat3 = digitalRead(BUTTON_3);
}

void reconnect_server() {

  if (WiFi.status() != WL_CONNECTED){
    WiFi.begin(ssid, password);
    Serial.println("");
    Serial.println("WiFi connect...");
  } else {
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    Serial.print("");
  }

  if(!client.connected() && WiFi.status() == WL_CONNECTED){
    if (client.connect("ESP8266Client")) {
      Serial.println("Mosquitto connect...");
  client.subscribe(relays_topic1);
  client.subscribe(relays_topic2);
  client.subscribe(relays_topic3);
    } else {
      Serial.print("failed connect Mosquitto, rc=");
      Serial.print(client.state());
      Serial.println("");
    }
  }
}
// Блок [обратная связь] ****************************************************
void callback(char* topic, byte* payload, unsigned int length) {
    Serial.print("Message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    String strTopic = String(topic);
    String strPayload = String((char*)payload);
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload);
  }
  Serial.println();
// Блок [Управление Реле 1 из MajorDomo] ************************************
if (strTopic == "ESP01/RELE_1") {
    if ((char)payload[0] == '1') {
        rState1 = true;
        digitalWrite(RELE_1, rState1);
    }
    else {
        rState1 = false;
        digitalWrite(RELE_1, rState1);
    }
}
// END Блок [Управление Реле 1 из MajorDomo] ********************************

// Блок [Управление Реле 2 из MajorDomo] ************************************
if (strTopic == "ESP01/RELE_2") {
    if ((char)payload[0] == '1') {
        rState2 = true;
        digitalWrite(RELE_2, rState2);
    }
    else {
        rState2 = false;
        digitalWrite(RELE_2, rState2);
    }
}
// Блок [Управление Реле 2 из MajorDomo] ************************************

// Блок [Управление Реле 3 из MajorDomo] ************************************
if (strTopic == "ESP01/RELE_3") {
    if ((char)payload[0] == '1') {
        rState3 = true;
        digitalWrite(RELE_3, rState3);
    }
    else {
        rState3 = false;
        digitalWrite(RELE_3, rState3);
    }
}
// Блок [Управление Реле 3 из MajorDomo] ************************************
}
// END Блок [обратная связь] ************************************************

// Блок [Управление Реле 1 с кнопки] ****************************************
void button_1(){
  btnPress1 = digitalRead(BUTTON_1);

  if (btnPress1 && !lastbtnStat1){
    delay(300); // защита от дребезга (300 мсек.)
    btnPress1 = digitalRead(BUTTON_1);

    if(btnPress1){
      rState1 = !rState1;
      digitalWrite(RELE_1, rState1);
      client.publish(relays_topic1, String(rState1).c_str(), true); // Публикуем состояние реле 1 на MQTT
    }
  }
  lastbtnStat1 = btnPress1;
}
// END Блок [Управление Реле 1 с кнопки] ************************************

// Блок [Управление Реле 2 с кнопки] ****************************************
void button_2(){
  btnPress2 = digitalRead(BUTTON_2);

  if (btnPress2 && !lastbtnStat2){
    delay(300); // защита от дребезга (300 мсек.)
    btnPress2 = digitalRead(BUTTON_2);

    if(btnPress2){
      rState2 = !rState2;
      digitalWrite(RELE_2, rState2);
      client.publish(relays_topic2, String(rState2).c_str(), true); // Публикуем состояние реле 2 на MQTT
    }
  }
  lastbtnStat2 = btnPress2;
}
// END Блок [Управление Реле 2 с кнопки] ************************************

// Блок [Управление Реле 3 с кнопки] ****************************************
void button_3(){
  btnPress3 = digitalRead(BUTTON_3);

  if (btnPress3 && !lastbtnStat3){
    delay(300); // защита от дребезга (300 мсек.)
    btnPress3 = digitalRead(BUTTON_3);

    if(btnPress3){
      rState3 = !rState3;
      digitalWrite(RELE_3, rState3);
      client.publish(relays_topic3, String(rState3).c_str(), true); // Публикуем состояние реле 3 на MQTT
    }
  }
  lastbtnStat3 = btnPress3;
}
// END Блок [Управление Реле 3 с кнопки] ************************************


void loop(){

client.loop();

// Блок [Проверка подключения] **********************************************
if (millis() - last_mls > 60000) { // Проеверка подключения к сети (раз в 60 сек.)
    last_mls = millis();
    reconnect_server();
}
// END Блок [Проверка подключения] ******************************************

  button_1(); // Функция кнопки №1 и публикация статуса реле 1 на MQTT
  button_2(); // Функция кнопки №2 и публикация статуса реле 2 на MQTT
  button_3(); // Функция кнопки №3 и публикация статуса реле 3 на MQTT
}
Топик ESP01/RELE_1 Включает и выключает Реле 1
Топик ESP01/RELE_2 Включает и выключает Реле 2
Топик ESP01/RELE_2 Включает и выключает Реле 2
установлена она на лестнице но иногда кратковременно пропадает электричество и при включении плата по умолчанию отключает все реле.

А нужно чтобы она принимала те значения которые были установлены в MajorDomo
 
Последнее редактирование:

Snezhana

New member
Сделайте unsubscribe а после этого - subscribe. Брокер пришлет данные "новому" подписчику.
Можно пожалуйста подробнее если вам не сложно, напишите пожалуйста как это встроить в мой скетч
 
Последнее редактирование:

=AK=

New member
Код:
void loop(){
  static long last_millis;
  if (millis() - last_millis > 1000) {   // every second
    last_millis  = millis();
    client.unsubscribe(relays_topic1);
    client.subscribe(relays_topic1);
    client.unsubscribe(relays_topic2);
    client.subscribe(relays_topic2);
    client.unsubscribe(relays_topic3);
    client.subscribe(relays_topic3);
  }
}
 

Snezhana

New member
=AK=,
Код:
void loop(){
  static long last_millis;
  if (millis() - last_millis > 1000) {   // every second
    last_millis  = millis();
    client.unsubscribe(relays_topic1);
    client.subscribe(relays_topic1);
    client.unsubscribe(relays_topic2);
    client.subscribe(relays_topic2);
    client.unsubscribe(relays_topic3);
    client.subscribe(relays_topic3);
  }
}
Ваш вариант к сожалению не работает
 

Сергей_Ф

Moderator
Команда форума
Snezhana, это был не вариант, а пример как сделать. В том виде как он есть, он работать не может.
Вам нужно сделать так в Вашем скетче. Скорее всего в строках 57-59 или (может быть и) 83-85.
 
Последнее редактирование:
  • Like
Реакции: =AK=

Сергей_Ф

Moderator
Команда форума
@Snezhana это Ваш скетч? Или Вы его откуда-то взяли?
В чём ещё Вам нужна помощь? Вам уже все сказали как сделать или сделать за Вас?
У меня и проверить не на чем как и что работает. Это же Ваш скетч и Ваш MojorDomo.
Повторю ещё раз, в вашем скетче строки 57-59 надо заменить на
  • client.unsubscribe(relays_topic1);
  • client.subscribe(relays_topic1);
  • client.unsubscribe(relays_topic2);
  • client.subscribe(relays_topic2);
  • client.unsubscribe(relays_topic3);
  • client.subscribe(relays_topic3);
Возможно, это надо сделать и в строках 83-85.
 

Snezhana

New member
@Snezhana это Ваш скетч? Или Вы его откуда-то взяли?
В чём ещё Вам нужна помощь? Вам уже все сказали как сделать или сделать за Вас?
У меня и проверить не на чем как и что работает. Это же Ваш скетч и Ваш MojorDomo.
Повторю ещё раз, в вашем скетче строки 57-59 надо заменить на

Возможно, это надо сделать и в строках 83-85.
Сейчас попробую
 

=AK=

New member
Повторю ещё раз, в вашем скетче строки 57-59 надо заменить на

Возможно, это надо сделать и в строках 83-85.
Я подразумевал, что этот кусок кода вставляeтся в главной loop, то есть, после 200-й строки. Специально показал в начале своего кода void loop(){ - это как раз 200-я строка.
 

Сергей_Ф

Moderator
Команда форума
@=AK= а зачем раз в секунду отписываться и подписываться заново? Проблема ведь только при пропадании питания и последующем старте.
 

=AK=

New member
Девушка просила "надо чтобы MajorDomo периодически сообщал о состояниях топиков или плата делала запрос". Вот я и написал для примера с периодом 1 сек. А оптимально это или нет - пусть сама думает.
 

telobezumnoe

New member
@Snezhana не пользовался этой библиотекой, но для того что бы при переподключении mqtt сервер вновь отправлял последние данные нужно их помечать как "retained"
 

telobezumnoe

New member
@Snezhana это зависит от клиента который публикует данные в mqtt брокер. я пользовался библиотекой от imroy . там при публикации это выглядит примерно так
Код:
client.publish(MQTT::Publish("holl/temp", String(t))
                               .set_retain(1));
так же у вас с мажордомо туда публикуются данные, как их сделать retained надо смотреть в их примерах
 
Последнее редактирование:

Snezhana

New member
@Snezhana это зависит от клиента который публикует данные в mqtt брокер. я пользовался библиотекой от imroy . там при публикации это выглядит примерно так
Код:
client.publish(MQTT::Publish("holl/temp", String(t))
                               .set_retain(1));
так же у вас с мажордомо туда публикуются данные, как их сделать retained надо смотреть в их примерах
Спасибо вам за ответ я нашла галочку retain в MajorDomo поставила и теперь все работает.
Теперь когда ESP8266 включаешь в сеть она принимает состояние которое установлено в MajorDomo ура! Кому нужно картинку приложила.
 

Вложения

Сверху Снизу