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

Как отправлять сообщения в топик с флагом Retain (программирую в среде Ардуино)

prygunovdn

New member
Помогите пожалуйста разобраться. Как отправить сообщение командой
Код:
client.publish(prefix + "/vorota1", "0");
чтобы она хранилась на сервере. Нужно как то поставить флаг Retain. Приложение я использую mqttLiner. В нем я перевожу переключатель в режим включено и затем МК его через секунду переводит в положение выключено(так и задумано). Затем я закрываю приложение, открываю его заново, а там ползунок находится в режиме включено, хотя на МК все выключено. Я так понял это из за того что приложение ставит флаг а МК при переводе в выключено не ставит. Как его поставить с МК? Уже всю голове сломал. Программа управляет освещением и двумя воротами.
Код:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2 //датчик даллас подключен на GPIO 2 (pin d4)
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
const int svet1 =  12;      // Свет на улице перед гаражем на GPIO 12 (pin d6)
const int svet2 =  13;      // Свет на улице перед гаражем на GPIO 13 (pin d7)
const int svet3 =  14;      // Свет на улице перед гаражем на GPIO 14 (pin d5)
const int vorota1 =  5;      // Открытие ворот 1 GPIO 5 (pin d1)
const int vorota2 =  4;      // Открытие ворот 2 GPIO 4 (pin d2)
const int vorota1stat =  0;      // состояние ворот гаража  GPIO 15 (pin d8)
int vorotablok = 0; // переменная состояния блокировки ворот
int passblok = 1987;// пороль для ворот
//int svet3ok = 0 ;
String prefix   = "dom1"; //префикс всех топиков данного устройства
const char *ssid = ""; // Имя вайфай точки доступа
const char *pass = ""; // Пароль от точки доступа

const char *mqtt_server = ""; // Имя сервера MQTT
const int mqtt_port = ; // Порт для подключения к серверу MQTT
const char *mqtt_user = ""; // Логи от сервер
const char *mqtt_pass = ""; // Пароль от сервера
long previousMillis = 0;        // для функции онлайн
int ledState = LOW;// для функции онлайн
long interval = 1000;           // для функции онлайн
boolean retained = true;
#define BUFFER_SIZE 100

//bool LedState = false;
int tm=300; //задержка отправки показаний
int onl=20; //задержка миганий для онлайна
float temp=0; // переменная для температуры
int stled = 0; //переменная в которую получаем
int stledv = 0; //переменная в которую получаем ворота 1 и 2
int stled1 = 0; // храним значение для задержки ворот 1
int stled11 = 0; // храним значение для задержки ворот 1 что их включили
int stled2 = 0; // храним значение для задержки ворот 2
int stled22 = 0; // храним значение для задержки ворот 2 что их включили
int stsvet3;
WiFiClient wclient;
PubSubClient client(wclient, mqtt_server, mqtt_port);

// Функция получения данных от сервера

void callback(const MQTT::Publish& pub)
{
Serial.print(pub.topic()); // выводим в сериал порт название топика
Serial.print(" => ");
Serial.print(pub.payload_string()); // выводим в сериал порт значение полученных данных

String payload = pub.payload_string();
// Обработка топика svet1
if(String(pub.topic()) == prefix + "/svet1") // проверяем из нужного ли нам топика пришли данные
{
stled = payload.toInt(); // преобразуем полученные данные в тип integer
if (stled == 1)
{digitalWrite(svet1, HIGH);}
if (stled == 0)
{digitalWrite(svet1, LOW); }
}
// Обработка топика vorotablok
if(String(pub.topic()) == prefix + "/vorotablok") // проверяем из нужного ли нам топика пришли данные
{
vorotablok = payload.toInt(); // преобразуем полученные данные в тип integer
}
// Обработка топика svet2
if(String(pub.topic()) == prefix + "/svet2") // проверяем из нужного ли нам топика пришли данные
{
stled = payload.toInt(); // преобразуем полученные данные в тип integer
if (stled == 1)
{digitalWrite(svet2, HIGH); }
if (stled == 0)
{digitalWrite(svet2, LOW); }
}
// Обработка топика svet3
if(String(pub.topic()) == prefix + "/svet3") // проверяем из нужного ли нам топика пришли данные
{
stsvet3 = payload.toInt(); // преобразуем полученные данные в тип integer
if (stsvet3 == 1)
{digitalWrite(svet3, HIGH); }
if (stsvet3 == 0)
{digitalWrite(svet3, LOW); }
}
//Serial.println(stled1);// + "do topika vorota1");
// Обработка топика vorota1
if(String(pub.topic()) == prefix + "/vorota1") // проверяем из нужного ли нам топика пришли данные
{
stledv = payload.toInt(); // преобразуем полученные данные в тип integer
Serial.print("stledv");
Serial.println(stledv);
if (stledv == 1)
{stled1 = 1;
stledv = 0;}} // сохраняем нажатие ворота 1
//else
//{client.publish("domm/domm", "VOROTA ZAPRET");}

// Обработка топика vorota2
if(String(pub.topic()) == prefix + "/vorota2") // проверяем из нужного ли нам топика пришли данные
{
stledv = payload.toInt(); // преобразуем полученные данные в тип integer
if (stledv == 1)
{stled2 = 1;
stledv = 0;}} // сохраняем нажатие ворота 1
//if (stled == 1)
//{digitalWrite(vorota2, HIGH);
//delay (200);
//digitalWrite(vorota2, LOW);
//client.publish(prefix + "/vorota2", "0");
//client.publish(prefix + "/vorota2", "Жопа");
//stled = 0;
//}
//if (stled == 0)
//{digitalWrite(vorota2, LOW); }
}


void setup() {

sensors.begin();
Serial.begin(115200);
delay(10);
Serial.println();
Serial.println();
pinMode(svet1, OUTPUT);
pinMode(svet2, OUTPUT);
pinMode(svet3, OUTPUT);
pinMode(vorota1, OUTPUT);
pinMode(vorota2, OUTPUT);
pinMode(vorota1stat, INPUT);
//client.publish(prefix + "/vorota2", "0");
//client.publish(prefix + "/vorota1", "0");
digitalWrite(vorota1, LOW);
digitalWrite(vorota2, LOW);
//digitalWrite(svet3, LOW);
//Serial.println(stled1);// + "posle initcializacii");
}

void loop() {
// подключаемся к wi-fi
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");
}

// подключаемся к MQTT серверу
if (WiFi.status() == WL_CONNECTED) {
if (!client.connected()) {
Serial.println("Connecting to MQTT server");
if (client.connect(MQTT::Connect("arduinoClient3") // имя клиента индивидуальное
.set_auth(mqtt_user, mqtt_pass))) {
Serial.println("Connected to MQTT server");
//client.publish(prefix + "/vorota2", "0");
//client.publish(prefix + "/vorota1", "0");

client.set_callback(callback);
client.subscribe(prefix + "/svet3"); // подписывааемся по топик с данными
client.subscribe(prefix + "/svet2"); // подписывааемся по топик с данными
client.subscribe(prefix + "/svet1"); // подписывааемся по топик с данными
client.subscribe(prefix + "/vorota1"); // подписывааемся по топик с данными
client.subscribe(prefix + "/vorota2"); // подписывааемся по топик с данными
client.subscribe(prefix + "/vorotablok");
client.subscribe(prefix + "/vorota1stat");
} else {
Serial.println("Could not connect to MQTT server");
}}
if (client.connected()){
client.loop();
//TempSend();
online();

}}} // конец основного цикла



// Функция ONLINE
void online(){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
if (ledState == LOW)
     { ledState = HIGH;
      client.publish(prefix + "/online", "1");
      //Serial.println(stled1);// + "pered  if (stled1 == 1 && vorotablok == passblok )");
      if (stled1 == 1 && vorotablok == passblok ) //задержка нажатия ворот1 если было нажатие
  {digitalWrite(vorota1, HIGH); //окрываем ворот1
  stled11 = 1;} //фиксируем что включили ворот1
// Serial.println(stled1);// + "pered if (stled1 == 1 && stled11 == 0 && vorotablok != passblok)");
if (stled1 == 1 && stled11 == 0 && vorotablok != passblok)
{//client.publish("domm/domm", " ");
client.publish("domm/domm", "Ворота гараж ЗАПРЕТ");
client.publish(prefix + "/vorota1", "0");
stled1 = 0;}
  if (stled2 == 1 && vorotablok == passblok ) //задержка нажатия ворот1 если было нажатие
  {digitalWrite(vorota2, HIGH); //окрываем ворот2
  stled22 = 1;} //фиксируем что включили ворот2
  if (stled2 == 1 && stled22 == 0 && vorotablok != passblok)
{//client.publish("domm/domm", " ");
client.publish("domm/domm", "Ворота Откатные ЗАПРЕТ");
client.publish(prefix + "/vorota2", "0");
stled2 = 0;}

      // Отправка состояния ворот
      if (digitalRead(vorota1stat)== 0)
      {client.publish(prefix + "/vorota1stat","Открыто");}
      else
      {client.publish(prefix + "/vorota1stat","Закрыто");}
     // Serial.println(digitalRead(vorota1stat));
      // Конец Отправка состояния ворот
   
      sensors.requestTemperatures(); // от датчика получаем значение температуры
float temp = sensors.getTempCByIndex(0); // преобразуем
client.publish(prefix + "/temp",String(temp));} // отправляем
    else
     { ledState = LOW;
      client.publish(prefix + "/online", "0");

     // if (vorotablok == 0)
      //{
       //client.publish(prefix + "/vorota1", "0");
       //client.publish(prefix + "/vorota2", "0");}
   
      if (stled1 == 1 && stled11 == 1 ) //задержка нажатия ворот1
     { digitalWrite(vorota1, LOW); //задержка нажатия ворот1
stled1 = 0; //задержка нажатия ворот1 само нажатие
stled11 = 0;//задержка нажатия ворот1 что было нажатие
client.publish(prefix + "/vorota1", "0");}

if (stled2 == 1 && stled22 == 1 ) //задержка нажатия ворот2
     { digitalWrite(vorota2, LOW); //задержка нажатия ворот2
stled2 = 0; //задержка нажатия ворот2 само нажатие
stled22 = 0;//задержка нажатия ворот2 что было нажатие

client.publish(prefix + "/vorota2", "0");}
}
      }}
Retain нужно добавить в этой части кода.
Код:
  if (stled1 == 1 && stled11 == 1 ) //задержка нажатия ворот1
     { digitalWrite(vorota1, LOW); //задержка нажатия ворот1
stled1 = 0; //задержка нажатия ворот1 само нажатие
stled11 = 0;//задержка нажатия ворот1 что было нажатие
client.publish(prefix + "/vorota1", "0");} //ЭТО СООБЩЕНИЕ ДОЛЖНО БЫТЬ С РЕТЕЙН
 
Последнее редактирование:

prygunovdn

New member
Нашел такой вариант
Код:
client.publish(MQTT::Publish(prefix + "/vorota1", "0").set_retain(1));
Вроде как все теперь правильно работает.
Только вот без этого (MQTT::publish) не компилировалось. Если кто то знает подробнее поясните пожалуйста.
 

Paratrooper

New member
Нашел такой вариант
Код:
client.publish(MQTT::Publish(prefix + "/vorota1", "0").set_retain(1));
Вроде как все теперь правильно работает.
Только вот без этого (MQTT::publish) не компилировалось. Если кто то знает подробнее поясните пожалуйста.
Достаточно этого:
Код:
client.publish(prefix + "/vorota1", "0", true);
 
Сверху Снизу