Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WDT Reset on Pubsubclient Connect #42

Open
benwinston opened this issue Jul 11, 2018 · 5 comments
Open

WDT Reset on Pubsubclient Connect #42

benwinston opened this issue Jul 11, 2018 · 5 comments

Comments

@benwinston
Copy link

Hi All,

I am trying to connect to AWS IoT / use MQTT running one of the examples from this project on a NodeMCU. While the sketch runs, an error occurs and the serial monitor shows a WDT Soft Reset.

From using the ESPExceptionDecoder, there appears to be an issue with AWSWebSocketClient. I get the following trace from the Decoder:

0x40207c8d: AWSWebSocketClient::available() at /Users/ben/Documents/Arduino/libraries/AWSWebSocketClient/AWSWebSocketClient.cpp line 475
0x40207820: PubSubClient::connect(char const*, char const*, char const*, char const*, unsigned char, unsigned char, char const*) at /Users/ben/Documents/Arduino/libraries/PubSubClient/src/PubSubClient.cpp line 180
0x402078a4: PubSubClient::connect(char const*) at /Users/ben/Documents/Arduino/libraries/PubSubClient/src/PubSubClient.cpp line 106
0x402023ae: generateClientID() at /Users/ben/Documents/Arduino/odelot_pubsubclient_test070818/odelot_pubsubclient_test070818.ino line 57
0x40202480: connect() at /Users/ben/Documents/Arduino/odelot_pubsubclient_test070818/odelot_pubsubclient_test070818.ino line 97
0x402025fc: setup() at /Users/ben/Documents/Arduino/odelot_pubsubclient_test070818/odelot_pubsubclient_test070818.ino line 147
0x40209d20: loop_wrapper() at /Users/ben/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/core_esp8266_main.cpp line 118

The error occurred on line this line from my sketch:
client.connect(clientID)

And the line that caused the error in AWSWebSocketClient.cpp is the call to "getsize" in the available() method:

//return with there is bytes to consume from the circular buffer (used by mqtt layer)
int AWSWebSocketClient::available(){
  //force websocket to handle it messages
  if (_connected == false)
	  return false;
  return bb.getSize ();
}

The code for my sketch follows:

#include <Arduino.h>
#include <Stream.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

//AWS
#include "sha256.h"
#include "Utils.h"

//WEBSockets
#include <Hash.h>
#include <WebSocketsClient.h>

//MQTT PUBSUBCLIENT LIB 
#include <PubSubClient.h>

//AWS MQTT Websocket
#include "Client.h"
#include "AWSWebSocketClient.h"
#include "CircularByteBuffer.h"

extern "C" {
  #include "user_interface.h"
}

//AWS IOT config, change these:
//Redacted for GitHub post
char wifi_ssid[]       = "";
char wifi_password[]   = "";
char aws_endpoint[]    = "";
char aws_key[]         = "";
char aws_secret[]      = "";
char aws_region[]      = "";
const char* aws_topic  = "";
int port = 443;



//MQTT config
const int maxMQTTpackageSize = 512;
const int maxMQTTMessageHandlers = 1;

ESP8266WiFiMulti WiFiMulti;
AWSWebSocketClient awsWSclient(100);

PubSubClient client(awsWSclient);

//# of connections
long connection = 0;

//generate random mqtt clientID
char* generateClientID () {
  char* cID = new char[23]();
  for (int i=0; i<22; i+=1)
    cID[i]=(char)random(1, 256);
  return cID;
}

//count messages arrived
int arrivedcount = 0;

//callback to handle mqtt messages
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

//connects to websocket layer and mqtt layer
bool connect () {



    if (client.connected()) {    
        client.disconnect ();
    }  
    //delay is not necessary... it just help us to get a "trustful" heap space value
    delay (1000);
    Serial.print (millis ());
    Serial.print (" - conn: ");
    Serial.print (++connection);
    Serial.print (" - (");
    Serial.print (ESP.getFreeHeap ());
    Serial.println (")");

    
    //creating random client id
    char* clientID = generateClientID ();
    client.setServer(aws_endpoint, port);
    if (client.connect(clientID)) {
      Serial.println("connected");     
      return true;
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      return false;
    }
    Serial.println("Afterclientconnectedcheck");
}

//subscribe to a mqtt topic
void subscribe () {
    client.setCallback(callback);
    client.subscribe(aws_topic);
   //subscript to a topic
    Serial.println("MQTT subscribed");
}

//send a message to a mqtt topic
void sendmessage () {
    //send a message   
    char buf[100];
    strcpy(buf, "{\"state\":{\"reported\":{\"on\": false}, \"desired\":{\"on\": false}}}");   
    int rc = client.publish(aws_topic, buf); 
}


void setup() {
    wifi_set_sleep_type(NONE_SLEEP_T);
    Serial.begin (115200);
//    delay (2000);
    Serial.setDebugOutput(1);

    //fill with ssid and wifi password
    WiFiMulti.addAP(wifi_ssid, wifi_password);
    Serial.println ("connecting to wifi");
    while(WiFiMulti.run() != WL_CONNECTED) {
        delay(100);
        Serial.print (".");
    }
    Serial.println ("\nconnected");
//Ben Winston 07.09.18 DELAY BEFORE AWS client invocation
  delay(100);
  Serial.print("Initializing AWS\n");

    //fill AWS parameters    
    awsWSclient.setAWSRegion(aws_region);
    awsWSclient.setAWSDomain(aws_endpoint);
    awsWSclient.setAWSKeyID(aws_key);
    awsWSclient.setAWSSecretKey(aws_secret);
    awsWSclient.setUseSSL(true);
  Serial.print("\nAWS Set up--------------");
    if (connect ()){
      subscribe ();
      sendmessage ();
    }

}

void loop() {
  //keep the mqtt up and running
  if (awsWSclient.connected ()) {    
    Serial.println("invoking client loop");
      client.loop ();
  } else {
    //handle reconnection
    if (connect ()){
      subscribe ();      
    }
  }
}


Any suggestions are appreciated.

@srinivastinku
Copy link

I face the same issue, exactly same line.
@benwinston Have you found any solution to this problem?

@benwinston
Copy link
Author

@srinivastinku No I was unable to resolve.

@srinivastinku
Copy link

@benwinston Okay thank you.
@odelot Can you please help here.

@odelot
Copy link
Owner

odelot commented Apr 11, 2019 via email

@asinkxcoswt
Copy link

Hi, I have stuck with the same problem and finally can make it work now. My code is based on this sketch https://github.com/HarringayMakerSpace/awsiot/blob/master/Esp8266AWSIoTExample/Esp8266AWSIoTExample.ino

which is a bit different from the OP's, but maybe it might shares some characteristics, so I think it might be useful to share my discovery.

I found 3 pitfalls that can cause the problem.

  1. You cannot call the pubsubClient.connect(clientId) inside the setup() phase, doing so will cause the error WDT reset as in the OP. If you look at the example sketch, it has the function pubSubCheckConnect() which is called inside loop() to handle all the connection. I don't know the reason but I believe it has some.
void pubSubCheckConnect() {
  if ( ! pubSubClient.connected()) {
    Serial.print("PubSubClient connecting to: "); Serial.print(awsEndpoint);
    while ( ! pubSubClient.connected()) {
      Serial.print(".");
      pubSubClient.connect("ESPthing");
    }
    Serial.println(" connected");
    pubSubClient.subscribe("inTopic");
  }
  pubSubClient.loop();
}
  1. You cannot declare WiFiClient and all the certificate variables inside a function, you have to make it global. For example

This does not work.

PubSubClient* pubSubClient;
void handleMessageReceived(char* topic, byte* payload, unsigned int len);

void setup() {
   WiFiClientSecure wiFiClient;
   const char* awsIotEndpoint = ...
   const String certificatePemCrt =...
   const String privatePemKey =...
   const String caPemCrt =...
   const unsigned int awsIotPort =...

    uint8_t binaryCert[certificatePemCrt.length() * 3 / 4];
    int len = b64decode(certificatePemCrt, binaryCert);
    wiFiClient.setCertificate(binaryCert, len);
    
    uint8_t binaryPrivate[privatePemKey.length() * 3 / 4];
    len = b64decode(privatePemKey, binaryPrivate);
    wiFiClient.setPrivateKey(binaryPrivate, len);

    uint8_t binaryCA[caPemCrt.length() * 3 / 4];
    len = b64decode(caPemCrt, binaryCA);
    wiFiClient.setCACert(binaryCA, len);

   pubSubClient = new PubSubClient(awsIotEndpoint, 8883, handleMessageReceived, wiFiClient);
}

void loop() {
   pubSubCheckConnect();
}

But this works.

PubSubClient* pubSubClient;
void handleMessageReceived(char* topic, byte* payload, unsigned int len);
WiFiClientSecure wiFiClient;
const char* awsIotEndpoint = ...
const String certificatePemCrt =...
const String privatePemKey =...
const String caPemCrt =...
const unsigned int awsIotPort =...

void setup() {
    uint8_t binaryCert[certificatePemCrt.length() * 3 / 4];
    int len = b64decode(certificatePemCrt, binaryCert);
    wiFiClient.setCertificate(binaryCert, len);
    
    uint8_t binaryPrivate[privatePemKey.length() * 3 / 4];
    len = b64decode(privatePemKey, binaryPrivate);
    wiFiClient.setPrivateKey(binaryPrivate, len);

    uint8_t binaryCA[caPemCrt.length() * 3 / 4];
    len = b64decode(caPemCrt, binaryCA);
    wiFiClient.setCACert(binaryCA, len);

     pubSubClient = new PubSubClient(awsIotEndpoint, 8883, handleMessageReceived, wiFiClient);
}

void loop() {
   pubSubCheckConnect();
}
  1. Becareful about NTP sync logic. The example sketch has the following method to handle NTP stuff which works fine.
void setCurrentTime() {
  configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");

  Serial.print("Waiting for NTP time sync: ");
  time_t now = time(nullptr);
  while (now < 8 * 3600 * 2) {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println("");
  struct tm timeinfo;
  gmtime_r(&now, &timeinfo);
  Serial.print("Current time: "); Serial.print(asctime(&timeinfo));
}

I do not fully understand it but I found that using other NTP solutions such as what described in this tutorial does not work with AWS IOT.

Final Suggestion

If you cannot make it work yet, I suggest that you start over with the example sketch that works. Try changing it a little bit by bit and test if it works before going further.

Hope this helps anyone who stuck with this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants