knolleary / pubsubclient

A client library for the Arduino Ethernet Shield that provides support for MQTT.
http://pubsubclient.knolleary.net/
MIT License
3.83k stars 1.47k forks source link

MQTT Keep alive time Issue SIM800l #344

Open kamrulroky opened 7 years ago

kamrulroky commented 7 years ago

Hello, I am trying to publish sensor data to MQTT using SIM800l , I have used https://github.com/vshymanskyy/TinyGSM library to connect with cloudmqtt.this library use pubsubclient for MQTT client. it works fine with mosquitto broker setup on windows. But with authentication credentials from cloudmqtt , sim800l could not connect to the server.using client.state() it show -4 which is keep alive timeout problem. I have changed keep alive time from 15 to 60 as this #223 issue mentioned. here is the code

#define TINY_GSM_MODEM_SIM800
#include <TinyGsmClient.h>
#include <PubSubClient.h>
#include <stdlib.h>

// Your GPRS credentials
// Leave empty, if missing user or pass
const char apn[]  = "gpinternet";
const char user[] = "";
const char pass[] = "";

// Use Hardware Serial on Mega, Leonardo, Micro
//#define SerialAT Serial1

// or Software Serial on Uno, Nano
#include <SoftwareSerial.h>
SoftwareSerial SerialAT(D8, D7); // RX, TX

TinyGsm modem(SerialAT);
TinyGsmClient client(modem);
PubSubClient mqtt(client);

//MQTT CERDITIONALS 
const char* broker = "m11.cloudmqtt.com";
const int mqtt_port = 18965;

//Topic instance 
const char* topicInit = "GsmClientTest/init";
const char* topicGasValue = "/gas_reading";

#define LED_PIN D4
int ledStatus = LOW;

long lastReconnectAttempt = 0;
unsigned long previousMillis = 0;
const long interval = 10000;

void setup() {
  pinMode(LED_PIN, OUTPUT);

  // Set console baud rate
  Serial.begin(115200);
  delay(10);

  // Set GSM module baud rate
  SerialAT.begin(115200);
  delay(3000);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  Serial.println("Initializing modem...");
  modem.restart();

  String modemInfo = modem.getModemInfo();
  Serial.print("Modem: ");
  Serial.println(modemInfo);

  // Unlock your SIM card with a PIN
  //modem.simUnlock("1234");

  Serial.print("Waiting for network...");
  if (!modem.waitForNetwork()) {
    Serial.println(" fail");
    while (true);
  }
  Serial.println(" OK");

  Serial.print("Connecting to ");
  Serial.print(apn);
  if (!modem.gprsConnect(apn, user, pass)) {
    Serial.println(" fail");
    while (true);
  }
  Serial.println(" OK");

  // MQTT Broker setup
  mqtt.setServer(broker, 18965);
  mqtt.setCallback(mqttCallback);
}

boolean mqttConnect() {
  Serial.print("Connecting to ");
  Serial.print(broker);
  if (!mqtt.connect("GsmClientTest", "*******", "**********")) {
    Serial.println(" Fail");
    Serial.println(mqtt.state());
    return false;
  }
  Serial.println(" OK");

  mqtt.publish(topicInit, "GsmClientTest started");
  //mqtt.subscribe(topicLed);
  return mqtt.connected();
}

void loop() {

  if (mqtt.connected()) {
    mqtt.loop();
  } else {
    // Reconnect every 10 seconds
    unsigned long t = millis();
    if (t - lastReconnectAttempt > 10000L) {
      lastReconnectAttempt = t;
      if (mqttConnect()) {
        lastReconnectAttempt = 0;
      }
    }
  }

  SendGasPpm();                                           // this will send the gas reading
}

void mqttCallback(char* topic, byte* payload, unsigned int len) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("]: ");
  Serial.write(payload, len);
  Serial.println();

}

//Sending Gas MQTT
void SendGasPpm() {  
  unsigned long currentMillis = millis();
  int sensor = A0;
  int sensorValue = 0;

  if (currentMillis - previousMillis >= interval) {     // checks if 10 delay is over
    // save last time sensor reading
    previousMillis = currentMillis;

    sensorValue = analogRead(sensor);

    int h = sensorValue;
    if (isnan(h)) {
      Serial.println("Failed to read from Gas sensor!");
      //return; This will ensure that data is always sent
    }
    Serial.println("Gas-sensor");
    Serial.print(h);

    mqtt.publish(topicGasValue, "gas" );
  }
}

please help me with this problem, i am new and trying to learn

AhmadSalmanKhan commented 5 years ago

Hey! any update here? I am having the same issue. Moreover even after defining the MQTT_KEEPALIVE 60. I have sniffed the packets using Wire shark , it sends the keep alive with default value of 15. I don't know why?

knolleary commented 5 years ago

How have you changed MQTT_KEEPALIVE? You'll need to change it in the PubSubClient.h file, not in your sketch.

AhmadSalmanKhan commented 5 years ago

Thanks

AhmadSalmanKhan commented 5 years ago

Hey ! If I set the keep alive=0 then the connection establishes at first and the client subscribes to the broker. But the callback doesn't work. anything broker tries to publish onto that subscribed topic by the client does not get received. Simply, the callback doesn't work if keep-alive time=0. Note: Since I have set the keep alive time to 0 then to prevent client to send aggressive ping requests, I have disabled ping by commenting out all the mqtt.loop() function in my code.

Should I do that or increase interval of ping request by client and ensure it sends pings?

knolleary commented 5 years ago

If you never call mqtt.loop() then you are never allowing the client to check if there are incoming messages to read from the network, so the callback will never be called.

You should set the keepalive to something > 0 and ensure you call loop if you want the client to receive messages.

tnt310 commented 3 years ago

@knolleary Hi knolleary. I have same problem about time-out connection between SIM800A to cloudmqtt, I use stm32f407 to send AT command to sim800. I try change KEEP-ALIVE value in packet connect and after this interval, server disconnect to sim800a. So, I want SIM800 keep connection continuously to server to subscribe message from server any time. How can I solve this problem? I think I need send PINGREG packet to server, but I don't know how to send PINGREG packet with AT command.