Помогите найти, где задержка происходит!

knik777
Offline
Зарегистрирован: 26.09.2015

Уважаемые сторожилы! Подскажите, пожалуйста, как избавиться от пятисекундной задержки?

Ситуация: у меня esp8266, коннектится по вайфаю, передает данные по протоколу MQTT. Все успешно. Пока работает сервер MQTT.
Как только сервер отключаешь - ESP8266 начинает тупить. Задержка составляет ровно 5 секунд на 1 проход. Исходя из чего я могу сделать вывод, что оно где-то установлено программно. Но где - найти не могу, облазил библиотеки на предмет delay - там ничего такого нет!

В следующем сообщении прикладываю код скетча и код библиотеки. Если еще что-то нужно - напишите, выложу.

Экспериментировал:

Как только из loop убираешь вот этот if - все работает шустро:

if (client.connect(MQTT::Connect("arduinoClient")
.set_auth("testeruser", "testpass")))

knik777
Offline
Зарегистрирован: 26.09.2015
Код скетча:


/*
 Basic MQTT example with Authentication
 
  - connects to an MQTT server, providing username
    and password
  - publishes "hello world" to the topic "outTopic"
  - subscribes to the topic "inTopic"
*/

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

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

// Update these with values suitable for your network.
IPAddress server(172, 168, 1, 77);

void callback(const MQTT::Publish& pub) {
  // handle message arrived
}

WiFiClient wclient;
PubSubClient client(wclient, server);

void setup() {
  // Setup console
  Serial.begin(115200);
  delay(10);
  Serial.println();
  Serial.println();
}

void loop() {
  Serial.println("HELLO!");
  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()) 
    {
       // Serial.println("Connecting to MQTT server");
       if (client.connect(MQTT::Connect("arduinoClient")
			 .set_auth("testeruser", "testpass"))) 
			   {
			 
           // Serial.println("Connected to MQTT server");
	         //client.set_callback(callback);
	         //client.publish("outTopic","hello world");
	         //client.subscribe("inTopic");
         }
           // else {
           //   Serial.println("Could not connect to MQTT server");   
           //    }
    }

    if (client.connected())
      client.loop();
  }
}

 

knik777
Offline
Зарегистрирован: 26.09.2015
файл библиотеки PubSubClient.h

/*
 PubSubClient.h - A simple client for MQTT.
  Nicholas O'Leary
  http://knolleary.net
*/

#ifndef PubSubClient_h
#define PubSubClient_h

#if defined(ESP8266) || defined(ESP32)
#include <functional>
#include <pgmspace.h>
#endif

#include <Arduino.h>

#include "MQTT.h"

//! Main do-everything class that sketches will use
class PubSubClient {
public:
#ifdef _GLIBCXX_FUNCTIONAL
  typedef std::function<void(const MQTT::Publish&)> callback_t;
#else
  typedef void(*callback_t)(const MQTT::Publish&);
#endif

private:
   IPAddress server_ip;
   String server_hostname;
   uint16_t server_port;
   callback_t _callback;

   Client &_client;
   MQTT::PacketParser _parser;
   uint16_t nextMsgId, keepalive;
   uint8_t _max_retries;
   unsigned long lastOutActivity;
   unsigned long lastInActivity;
   bool pingOutstanding;
   bool isSubAckFound;

   //! Receive a message from the client
   /*!
     \return Pointer to message object, nullptr if no message has been received
    */
   MQTT::Message* _recv_message(void);

   //! Send a message with no response
   /*!
     \param msg The message to send
     \return Did the message send successfully?
    */
   bool _send_message(MQTT::Message& msg);

   //! Send a message and wait for its response message (if it has one)
   /*!
     \param msg The message to send
     \return The response message
    */
   MQTT::Message* _send_message_with_response(MQTT::Message& msg);

   //! Process incoming messages
   /*!
     - Calls the callback function when a PUBLISH message comes in
     - Handles the handshake for PUBLISH when qos > 0
     - Handles ping requests and responses
     \param msg Message to process
    */
   void _process_message(MQTT::Message* msg);

   //! Wait for a certain type of packet to come back, optionally check its packet id
   /*!
     Other packets are handed over to _process_message()
     \param wait_type	Message type to match on
     \param wait_pid	Message packet id to match on
     \return The packet we wanted, or nullptr if it didn't arrive
    */
   MQTT::Message*_wait_for(MQTT::message_type wait_type, uint16_t wait_pid = 0);

   //! Return the next packet id
   uint16_t _next_packet_id(void) {
     nextMsgId++;
     if (nextMsgId == 0) nextMsgId = 1;
     return nextMsgId;
   }

public:
   //! Simple constructor
   /*!
     Use set_server() before connect()
   */
   PubSubClient(Client& c);

   //! Constructor with the server ip address
   PubSubClient(Client& c, IPAddress &ip, uint16_t port = 1883);
   //! Constructors with the host name
   PubSubClient(Client& c, String hostname, uint16_t port = 1883);

   //! Set the server ip address
   PubSubClient& set_server(IPAddress &ip, uint16_t port = 1883);
   //! Set the server host name
   PubSubClient& set_server(String hostname, uint16_t port = 1883);

   //! Get the callback function
   callback_t callback(void) const { return _callback; }
   //! Set the callback function
   PubSubClient& set_callback(callback_t cb) { _callback = cb; return *this; }
   //! Unset the callback function
   PubSubClient& unset_callback(void) { _callback = nullptr; return * this; }

   //! Set the maximum number of retries when waiting for response packets
   PubSubClient& set_max_retries(uint8_t mr) { _max_retries = mr; return *this; }

   //! Connect to the server with a client id
   /*!
     \param id Client id for this device
    */
   bool connect(String id);

   //! Connect to the server with a client id and "will" parameters
   /*!
     The "will" is a message that is published when this client *unexpectantly*
     disconnects from the broker i.e without sending a DISCONNECT message.
     \param id Client id for this device
     \param willTopic	Topic of the "will" message
     \param willQos	QoS level of the "will" message
     \param willRetain	Retain setting of the "will" message
     \param willMessage	Content (payload) of the "will" message
    */
   bool connect(String id, String willTopic, uint8_t willQos, bool willRetain, String willMessage);

   //! Disconnect from the server
   void disconnect(void);

   //! Publish a string payload
   /*!
     \param topic Topic of the message
     \param payload String text of the message
    */
   bool publish(String topic, String payload);

   //! Publish an arbitrary data payload
   /*!
     \param topic Topic of the message
     \param payload Pointer to contents of the message
     \param plength Length of the message (pointed to by payload) in bytes
     \param retained If true, this message will be stored on the server and
     supplied to any future subscribers whose subscriptions match its topic
     name.
    */
   bool publish(String topic, const uint8_t *payload, uint32_t plength, bool retained = false);

   //! Publish an arbitrary data payload from a callback
   /*!
     \param topic Topic of this message
     \param pcb A callback function that writes the payload directly to the network Client object
     \param length The length of the data that 'pcb' will send
   */
   bool publish(String topic, MQTT::payload_callback_t pcb, uint32_t length, bool retained = false);

   //! Publish an arbitrary data payload stored in "program" memory
   /*!
     \param topic Topic of the message
     \param payload Pointer to contents of the message, stored in "program" memory
     \param plength Length of the message (pointed to by payload) in bytes
     \param retained If true, this message will be stored on the server and
     supplied to any future subscribers whose subscriptions match its topic
     name.
   */
   bool publish_P(String topic, PGM_P payload, uint32_t plength, bool retained = false);

   //! Subscribe to a topic
   /*!
     \param topic Topic filter
     \param qos QoS value. 0 => no handshake, 1 => single handshake, 2 => two-way handshake
    */
   bool subscribe(String topic, uint8_t qos = 0);

   //! Unsubscribe from a topic
   bool unsubscribe(String topic);

   //! Wait for packets to come in, processing them
   /*!
     Also periodically pings the server
   */
   bool loop();

   //! Are we connected?
   bool connected();

   //! Connect with a pre-constructed MQTT message object
   bool connect(MQTT::Connect &conn);
   //! Publish with a pre-constructed MQTT message object
   bool publish(MQTT::Publish &pub);
   //! Subscribe with a pre-constructed MQTT message object
   bool subscribe(MQTT::Subscribe &sub);
   //! Unsubscribe with a pre-constructed MQTT message object
   bool unsubscribe(MQTT::Unsubscribe &unsub);
};


#endif

 

knik777
Offline
Зарегистрирован: 26.09.2015
Файл библиотеки: PubSubClient.cpp

/*
 PubSubClient.cpp - A simple client for MQTT.
  Nicholas O'Leary
  http://knolleary.net
*/

#include "PubSubClient.h"
#include <string.h>

PubSubClient::PubSubClient(Client& c) :
  _callback(nullptr),
  _client(c),
  _parser(c),
  _max_retries(10),
  isSubAckFound(false)
{}

PubSubClient::PubSubClient(Client& c, IPAddress &ip, uint16_t port) :
  _callback(nullptr),
  _client(c),
  _parser(c),
  _max_retries(10),
  isSubAckFound(false),
  server_ip(ip),
  server_port(port)
{}

PubSubClient::PubSubClient(Client& c, String hostname, uint16_t port) :
  _callback(nullptr),
  _client(c),
  _parser(c),
  _max_retries(10),
  isSubAckFound(false),
  server_port(port),
  server_hostname(hostname)
{}

PubSubClient& PubSubClient::set_server(IPAddress &ip, uint16_t port) {
  server_hostname = "";
  server_ip = ip;
  server_port = port;
  return *this;
}

PubSubClient& PubSubClient::set_server(String hostname, uint16_t port) {
  server_hostname = hostname;
  server_port = port;
  return *this;
}

MQTT::Message* PubSubClient::_recv_message(void) {
  MQTT::Message *msg = _parser.parse();
  if (msg != nullptr)
    lastInActivity = millis();
  return msg;
}

bool PubSubClient::_send_message(MQTT::Message& msg) {
  if (msg.need_packet_id())
    msg.set_packet_id(_next_packet_id());

  uint8_t retries = 0;
 send:
  if (!msg.send(_client)) {
    if (retries < _max_retries) {
      retries++;
      goto send;
    }
    return false;
  }
  lastOutActivity = millis();

  return true;
}

MQTT::Message* PubSubClient::_send_message_with_response(MQTT::Message& msg) {
  if (msg.need_packet_id())
    msg.set_packet_id(_next_packet_id());

  uint8_t retries = 0;
 send:
  if (!msg.send(_client)) {
    if (retries < _max_retries) {
      retries++;
      goto send;
    }
    return nullptr;
  }
  lastOutActivity = millis();

  MQTT::Message *response = _wait_for(msg.response_type(), msg.packet_id());
  if (response == nullptr) {
    if (retries < _max_retries) {
      retries++;
      goto send;
    }
    return nullptr;
  }

  return response;
}

void PubSubClient::_process_message(MQTT::Message* msg) {
  switch (msg->type()) {
  case MQTT::PUBLISH:
    {
      MQTT::Publish *pub = static_cast<MQTT::Publish*>(msg);	// RTTI is disabled on embedded, so no dynamic_cast<>()

      if (_callback)
	_callback(*pub);

      if (pub->qos() == 1) {
	MQTT::PublishAck puback(pub->packet_id());
	_send_message(puback);

      } else if (pub->qos() == 2) {

	{
	  MQTT::PublishRec pubrec(pub->packet_id());
	  MQTT::Message *response = _send_message_with_response(pubrec);
	  if (response == nullptr)
	    return;
	  delete response;
	}

	{
	  MQTT::PublishComp pubcomp(pub->packet_id());
	  _send_message(pubcomp);
	}
      }
    }
    break;

  case MQTT::PINGREQ:
    {
      MQTT::PingResp pr;
      _send_message(pr);
    }
    break;

  case MQTT::PINGRESP:
    pingOutstanding = false;
  }
}

MQTT::Message* PubSubClient::_wait_for(MQTT::message_type wait_type, uint16_t wait_pid) {
  while (!_client.available()) {
    if (millis() - lastInActivity > keepalive * 1000UL)
      return nullptr;
    yield();
  }

  while (millis() < lastInActivity + (keepalive * 1000)) {
    // Read the packet and check it
    MQTT::Message *msg = _recv_message();
    if (msg != nullptr) {
      if (msg->type() == wait_type) {
	if ((wait_pid > 0) && (msg->packet_id() != wait_pid)) {
	  delete msg;
	  return nullptr;
	}
	return msg;
      } else if (msg->type() == MQTT::SUBACK) { // if the current message is not the one we want
        // Signal that we found a SUBACK message
        isSubAckFound = true;
      }

      _process_message(msg);

      // After having proceeded new incoming packets, we check if our response as not already been processed
      if ((wait_type == MQTT::SUBACK) && isSubAckFound) {
        isSubAckFound = false;
        // Return false will cause a resend of a SUBSCRIBE message (and so a new chance to get a SUBACK)
        return nullptr;
      }

      delete msg;
    }

    yield();
  }

  return nullptr;
}

bool PubSubClient::connect(String id) {
  MQTT::Connect conn(id);
  return connect(conn);
}

bool PubSubClient::connect(String id, String willTopic, uint8_t willQos, bool willRetain, String willMessage) {
  MQTT::Connect conn(id);
  if (willTopic.length())
    conn.set_will(willTopic, willMessage, willQos, willRetain);
  return connect(conn);
}

bool PubSubClient::connect(MQTT::Connect &conn) {
  if (connected())
    return false;

  int result = 0;

  if (server_hostname.length() > 0)
    result = _client.connect(server_hostname.c_str(), server_port);
  else
    result = _client.connect(server_ip, server_port);

  if (!result) {
    _client.stop();
    return false;
  }

  pingOutstanding = false;
  nextMsgId = 1;		// Init the next packet id
  lastInActivity = millis();	// Init this so that _wait_for() doesn't think we've already timed-out
  keepalive = conn.keepalive();	// Store the keepalive period from this connection

  MQTT::Message *response = _send_message_with_response(conn);
  if (response == nullptr) {
    _client.stop();
    return false;
  }

  bool ret = true;
  if (response->type() == MQTT::CONNACK) {
    MQTT::ConnectAck *ack = static_cast<MQTT::ConnectAck*>(response);
    if (ack->rc() > 0) {
      _client.stop();
      ret = false;
    }
  }
  delete response;

  return ret;
}

bool PubSubClient::loop() {
  if (!connected())
    return false;

  unsigned long t = millis();
  if ((t - lastInActivity > keepalive * 1000UL) || (t - lastOutActivity > keepalive * 1000UL)) {
    if (pingOutstanding) {
      _client.stop();
      return false;
    } else {
      MQTT::Ping ping;
      if (!_send_message(ping))
	return false;

      lastInActivity = lastOutActivity;
      pingOutstanding = true;
    }
  }
  if (_client.available()) {
    // Read the packet and check it
    MQTT::Message *msg = _recv_message();
    if (msg != nullptr) {
      _process_message(msg);
      delete msg;
    }
  }
  return true;
}

bool PubSubClient::publish(String topic, String payload) {
  if (!connected())
    return false;

  MQTT::Publish pub(topic, payload);
  return publish(pub);
}

bool PubSubClient::publish(String topic, const uint8_t* payload, uint32_t plength, bool retained) {
  if (!connected())
    return false;

  MQTT::Publish pub(topic, const_cast<uint8_t*>(payload), plength);
  pub.set_retain(retained);
  return publish(pub);
}

bool PubSubClient::publish(String topic, MQTT::payload_callback_t pcb, uint32_t length, bool retained) {
  if (!connected())
    return false;

  MQTT::Publish pub(topic, pcb, length);
  pub.set_retain(retained);
  return publish(pub);
}

bool PubSubClient::publish_P(String topic, PGM_P payload, uint32_t plength, bool retained) {
  if (!connected())
    return false;

  MQTT::Publish pub = MQTT::Publish_P(topic, payload, plength);
  pub.set_retain(retained);
  return publish(pub);
}

bool PubSubClient::publish(MQTT::Publish &pub) {
  if (!connected())
    return false;

  MQTT::Message *response;
  switch (pub.qos()) {
  case 0:
    return _send_message(pub);

  case 1:
    response = _send_message_with_response(pub);
    if (response == nullptr)
      return false;

    delete response;
    return true;

  case 2:
    {
      response =_send_message_with_response(pub);
      if (response == nullptr)
	return false;

      delete response;

      MQTT::PublishRel pubrel(pub.packet_id());
      response = _send_message_with_response(pubrel);
      if (response == nullptr)
	return false;

      delete response;
      return true;
    }
  }
  return false;
}

bool PubSubClient::subscribe(String topic, uint8_t qos) {
  if (!connected())
    return false;

  if (qos > 2)
    return false;

  MQTT::Subscribe sub(topic, qos);
  return subscribe(sub);
}

bool PubSubClient::subscribe(MQTT::Subscribe &sub) {
  if (!connected())
    return false;

  MQTT::Message *response = _send_message_with_response(sub);
  if (response == nullptr)
    return false;

  delete response;
  return true;
}

bool PubSubClient::unsubscribe(String topic) {
  if (!connected())
    return false;

  MQTT::Unsubscribe unsub(topic);
  return unsubscribe(unsub);
}

bool PubSubClient::unsubscribe(MQTT::Unsubscribe &unsub) {
  if (!connected())
    return false;

  MQTT::Message *response = _send_message_with_response(unsub);
  if (response == nullptr)
    return false;

  delete response;
  return true;
}

void PubSubClient::disconnect() {
   if (!connected())
     return;

   MQTT::Disconnect discon;
   if (_send_message(discon))
     lastInActivity = lastOutActivity;
   _client.stop();
}

bool PubSubClient::connected() {
   bool rc = _client.connected();
   if (!rc)
     _client.stop();

   return rc;
}

 

b707
Offline
Зарегистрирован: 26.05.2017

knik777 пишет:
Как только сервер отключаешь - ESP8266 начинает тупить. Задержка составляет ровно 5 секунд на 1 проход. Исходя из чего я могу сделать вывод, что оно где-то установлено программно. Но где - найти не могу, облазил библиотеки на предмет delay - там ничего такого нет!

Не то ищете, такое на delay() никогда не делается. Это коннект-таймаут, отрабатывается например в строчке 245 кода в сообщении #3. само значение, судя по всем, задано в файле MQTT.h или где-то еще выше.

Можете попробовать убавить таймаут, например до 2х или даже 1 секунды. Но совсем обнулять таймаут нельзя, иначе у вас и при подключении сервера MQTT перестанет работать.

knik777
Offline
Зарегистрирован: 26.09.2015

спасибо, поищу. Меня в принципе не напрягает то, что коннект ждет 5 секунд и отваливается по таймауту.

Меня напрягает, что в эти 5 секунд подвешивается программа.

Я думал где-то delay, и надо его переписать через millis().

А с таймаутами так нельзя,да?

b707
Offline
Зарегистрирован: 26.05.2017

knik777 пишет:

Я думал где-то delay, и надо его переписать через millis().

А с таймаутами так нельзя,да?

похоже вы строчку, которую я указал - даже не смотрели. Она уже через миллис

knik777
Offline
Зарегистрирован: 26.09.2015

смотрел, и видел что библиотека вся в целом через миллис написана. Поэтому и удивило: почему цикл loop зависает на 5 секунд, если там через миллис, и вроде как остальная часть программы должна выполняться дальше, если та часть, которая ждет коннекта к МQTT брокеру, входит в режим ожидания...

 

Посмотрел значение параметра

MQTT_KEEPALIVE, оно равно 15 секунд

 

Это из MQTT.cpp

 

// Connect class
  Connect::Connect(String cid) :
    Message(CONNECT),
    _clean_session(true),
    _clientid(cid),
    _will_message(nullptr), _will_message_len(0),
    _keepalive(MQTT_KEEPALIVE)
  {}

 

knik777
Offline
Зарегистрирован: 26.09.2015

для эксперимента поменял MQTT_KEEPALIVE на 1 секунду - не помогло: задержка все равно 5 секунд идет, если нет коннекта. Ищу в том же направлении.

knik777
Offline
Зарегистрирован: 26.09.2015

тогда такой вопрос:

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

 

if (client.connect(MQTT::Connect("NNN").set_auth(MQTT_USER, MQTT_PASS)))

 

На сколько я понял,

- Вызывается функция MQTT.connect с параметром имени сервера (NNN).

- далее вызывается функция client.connect с параметром, который возвратила предыдущая функция - точка - set_auth (логин, пароль).

Получается, в итоге в условии будет либо true если законнектились, либо false, если не законнектились.

 

Вопросы:

1) Что возвращает первая функция MQTT.connect

2) Как проверить, какая из двух используемых тут функций вызывает задержку в 5 секунд?

 

knik777
Offline
Зарегистрирован: 26.09.2015

методом поочередного комментирования кусков кода вычислил, что тупит 207я строка из файла pubsubclient.cpp

Вот эта:

result = _client.connect(server_hostname.c_str(), server_port);

 

Если кто что толковое подскажет - буду благодарен. Что делает эта строчка? Куда смотреть? Что искать?

Целый день сижу втыкаю (((

Продолжаю поиски проблемы.

knik777
Offline
Зарегистрирован: 26.09.2015

Пока решил вопрос отсрочкой на реконнект в 60 секунд в случае неудачного коннекта. Криво, конечно, но по другому не понимаю как.

Кривость в том, что в случае неработающего сервера MQTT выполнение команд все равно будет подвисать 1 раз в минуту на 5 секунд.

Может, кто что порекомендует более адекватное...

 


#include <ESP8266WiFi.h>
#include <PubSubClient.h>

/************************* WiFi Access Point *********************************/

#define WLAN_SSID       "MGTS_GPON_929E"
#define WLAN_PASS       "SPL4MTQ6"

/************************* Mosquitto Setup *********************************/

#define MOSQUITTO_SERVER      "192.168.1.71"
#define MOSQUITTO_PORT        1883                   // use 8883 for SSL
#define MQTT_USER             "kstud"
#define MQTT_PASS             "belijsneg5333"
#define CLIENTNAMEUNIQUE      "NIKArdnr02"

/************************* Device Setup *********************************/


#define KORIDOR1SVETPIN 5 //5=d1 nodemcu v3     
#define KNOPKA1PIN 4  //4=d2 nodemcu v3
#define KNOPKA2PIN 13  //13=d7 nodemcu v3
#define KNOPKA3PIN 12  //12=d6 nodemcu v3
#define KNOPKA4PIN 14  //14=d5 nodemcu v3

/************************* Topics Setup *********************************/

#define KORIDOR1SVETTOPIC     "/home/koridor1/svet"


WiFiClient wclient;
PubSubClient client(wclient, MOSQUITTO_SERVER, MOSQUITTO_PORT);


unsigned long t=0; //для кнопки1 вспомогательная переменная
bool ignoreonevalue=0; // когда сработал выключатель, то игнорируем одну следующую команду, пришедшую из топика.
bool svetstate=0;
bool delayflag = 0;
unsigned long tt2=0;

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

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

  String payload = pub.payload_string(); // считываем значение, пришедшее по топику


// обработка включения люстры
    if(String(pub.topic()) == KORIDOR1SVETTOPIC) // проверяем из нужного ли нам топика пришли данные
      {
        if (ignoreonevalue==0) // если управление пришло извне, а не от выключателя на том же устройстве NodeMCU, где и люстра располагается
          {
            svetstate = payload.toInt(); // преобразуем полученные данные
            digitalWrite(KORIDOR1SVETPIN,svetstate); // включаем светодиод
           }
         else ignoreonevalue=0; // если сигнал пришел от выключателя, находящегося на том же устройстве NodeMCU, что и люстра
  }

}

void setup() {
// подключаемся к wi-fi
  if (WiFi.status() != WL_CONNECTED) 
    {
      Serial.print("Connecting to ");
      Serial.print(WLAN_SSID);
      Serial.println("...");
      WiFi.begin(WLAN_SSID, WLAN_PASS);

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

  //sensors.begin();
  Serial.begin(115200);
  delay(10);
  Serial.println();
  Serial.println();
  
  pinMode(KORIDOR1SVETPIN, OUTPUT);
  pinMode(KNOPKA1PIN,INPUT);
  pinMode(KNOPKA2PIN,INPUT);
  pinMode(KNOPKA3PIN,INPUT);
  pinMode(KNOPKA4PIN,INPUT);
}


void loop() 
{

// обработка нажатия кнопки. +это событие идет в опенхаб. включаем-выключаем свет, подключенный к этому же NodeMCU, что и выключатель
  if (t+500UL<millis())  //задержка полсекунды при нажатии кнопки, чтобы она не срабатывала 10 раз подряд
    {
      if (digitalRead(KNOPKA1PIN)==1 or digitalRead(KNOPKA2PIN)==1 or digitalRead(KNOPKA3PIN)==1 or digitalRead(KNOPKA4PIN)==1) //если нажата одна их 4х проходных кнопок
        {
          t=millis();
          svetstate=!svetstate; // меняем значение светодиода на противоположное 
          Serial.println (svetstate);
          digitalWrite(KORIDOR1SVETPIN,svetstate); 
          if (WiFi.status() == WL_CONNECTED and client.connected())
          { 
            client.publish(KORIDOR1SVETTOPIC,String(svetstate)); // отправляем в топик для термодатчика значение температуры
            ignoreonevalue=1; //защита от повторного переключения состояния люстры, когда команда в топике вернется от сервера
          }
        }
    }
  
if (tt2+60000UL<millis()) delayflag=0;
  
  // подключаемся к MQTT серверу
  if (WiFi.status() == WL_CONNECTED) 
    {
      if (!client.connected() and delayflag==0) 
        {
          Serial.println("Connecting to MQTT server");
          if(client.connect(MQTT::Connect(CLIENTNAMEUNIQUE).set_auth(MQTT_USER, MQTT_PASS)))
            {
              Serial.println("Connected to MQTT server");
              client.set_callback(callback);
              client.subscribe(KORIDOR1SVETTOPIC); // подписываемся по топик с данными для светодиода
            } 
          else 
            {
              delayflag=1;
              tt2=millis();
              Serial.println("Could not connect to MQTT server");
            }
        }
      if (client.connected())
        {
          client.loop();
                
        }
    } // конец основного цикла
}

 

nik182
Offline
Зарегистрирован: 04.05.2015

А пингануть сервер? Если отвечает то только тогда конектится?

knik777
Offline
Зарегистрирован: 26.09.2015

пингануть? в принципе вариант. Где можно посмотреть, какими командами получить результат пинга (успех-неудача)?

nik182
Offline
Зарегистрирован: 04.05.2015

https://github.com/dancol90/ESP8266Ping первая ссылка гугля. Забанили?

knik777
Offline
Зарегистрирован: 26.09.2015

помню-помню, в среде разработчиков принято общаться саркастически...

PS Благодарю за ссылку.

knik777
Offline
Зарегистрирован: 26.09.2015

nik182 пишет:

А пингануть сервер? Если отвечает то только тогда конектится?

 

Проверил я предложенный Вами вариант. Пинг работает!

НО: он работает точно также, как и приведенный мной код: в момент пинга, то есть вот на этой строке:

if(Ping.ping(remote_ip))

выполнение цикла loop на esp8266 подвешивается ровно на те же 5 секунд! Забавно получается ))

 

nik182
Offline
Зарегистрирован: 04.05.2015

В библиотеке пинга есть функция установки таймаута. Правда там как мне показалась минимум секунда. Так что меньше похоже не получится. Но это нормальное поведение в условиях сетевого коннекта. Тут или шашечки или ехать.

knik777
Offline
Зарегистрирован: 26.09.2015

да, увидел единичку и неуверенный комментарий, что возможно, это секунды. В то же время в библиотеке стоит 1, а задержка 5 секунд.

 

На данный момент я остановился на следующем решении:

 

- если коннект к MQTT серверу произошел, то и так все в порядке в рамках имеющейся библиотеки pubsubclient.

- если коннекта нет, то начинаем отсчет. В течение 10 минут даже не пробуем коннектиться. Выполняем себе код, предназначенный для офлайн режима работы esp8266. Через 10 минут пробуем коннект еще раз.

Таким образом, получается глюк с подвисанием программы всего 5 секунд 1 раз в 10 минут. Это практически идеально.

 

Всех еще раз благодарю за участие. Тему закрываю.