简体   繁体   中英

Getting an exception when try to use NTPClient in a custom class (ESP8266)

I'm getting an exception (see below) when I try to use NTPClient in my custom class RealTimeService. Please advise why and how to fix it. Thank you.

File RealTimeService.h:

#ifndef RealTimeLib
#define RealTimeLib

#include <NTPClient.h>
#include <WiFiUdp.h>

class RealTimeService {
  private:
    NTPClient _ntp;
    NTPClient _createNtpClient();
    void _update();
  public:
    RealTimeService();
    void begin();
};

#endif

File RealTimeService.cpp:

#include "RealTimeService.h"

RealTimeService::RealTimeService() : 
  _ntp(_createNtpClient())
{
}

NTPClient RealTimeService::_createNtpClient() {
  WiFiUDP udp;
  NTPClient ntp(udp, "pool.ntp.org", 3600, 86400000);
  return ntp;
}

void RealTimeService::begin() {
  _update();
}

void RealTimeService::_update() {
  _ntp.begin(); // Throws an exception
  if(_ntp.update()) {
    long time = _ntp.getEpochTime();
  } else {
    Serial.print("Failed to get time from server.\n");
  }
}

File WebServerSecure.ino:

#include <ESP8266WiFi.h>
#include "RealTimeService.h"


#ifndef STASSID
#define STASSID "Sedmikraska"
#define STAPSK  "38098246"
#endif

const char* ssid = STASSID;
const char* password = STAPSK;

RealTimeService realTime;

void setup(void) {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  realTime.begin();
}

void loop(void) {
  delay(1000);
}

It throws an exception in function RealTimeService::_update() at line _ntp.begin();

User exception (panic/abort/assert)

And the decoded stack is:

0x4020714a: HardwareSerial::begin(unsigned long, SerialConfig, SerialMode, unsigned char, bool) at C:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\HardwareSerial.cpp line 51
0x4020804c: __unhandled_exception_cpp() at C:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\core_esp8266_main.cpp line 229
0x4020a07c: NTPClient::begin(int) at C:\Users\user\Documents\Arduino\libraries\NTPClient\NTPClient.cpp line 61
0x40202544: NTPClient::begin() at C:\Users\user\Documents\Arduino\libraries\NTPClient\NTPClient.cpp line 53
0x40201028: RealTimeService::_update() at C:\Users\user\AppData\Local\Temp\arduino_build_506039\sketch\RealTimeService.cpp line 20
0x40201b04: ESP8266WiFiSTAClass::status() at C:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\libraries\ESP8266WiFi\src\ESP8266WiFiSTA.cpp line 634
0x40201058: RealTimeService::begin() at C:\Users\user\AppData\Local\Temp\arduino_build_506039\sketch\RealTimeService.cpp line 16
0x4020115c: setup() at C:\Users\user\Documents\Arduino\WebServerSecure/WebServerSecure.ino line 23
0x40208224: loop_wrapper() at C:\Users\user\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\core_esp8266_main.cpp line 194

You define udp in RealTimeService::_createNtpClient() and pass it to NTPClient . NTPClient will continue to need it after RealTimeService::_createNtpClient() returns, but udp will become invalid. Even if NTPClient copies it, its destructor is called, invalidating the resources it used.

You need to change udp to be an instance variable so that it will survive as long as _ntp does.

class RealTimeService {
  private:
    WiFiUDP _udp;
    NTPClient _ntp;
...

and

NTPClient RealTimeService::_createNtpClient() {
  NTPClient ntp(_udp, "pool.ntp.org", 3600, 86400000);

Your code is also calling _ntp.begin() repeatedly. You should ensure that the NTP library you're using allows for this; sometimes libraries are written so that their begin() method can only be called once.

In addition to @romkey 's answer, you could probably skip _createNtpClient altogether and move the initialization of the fields in the constructor. Something more compact, like

#ifndef RealTimeLib
#define RealTimeLib

#include <WiFiUdp.h>
#include <NTPClient.h>

class RealTimeService {
  private:
    WiFiUDP _udp;
    NTPClient _ntp;
    ...
  public:
    RealTimeService();
    ...
};

#endif
#include "RealTimeService.h"

RealTimeService::RealTimeService() :
  _udp(),
  _ntp(_udp, "pool.ntp.org", 3600, 86400000)
{
}

...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM