Использование c_str() для String для IPAddress с NTPClient дает неправильные значения

Библиотеки

  • NTPClient

Плата

Плата Olimex ESP32-POE

Поведение

Я написал код, который подключает плату к локальному NTP-серверу (который является встроенной платой). Я попытался назначить IP-адрес указанного выше NTP-сервера, используя IPAddress, а затем преобразовать его в c_str() для передачи в конструктор NTPClient следующим образом. :

 WiFiUDP ntpUDP; // объект сокета udp для NTP

 IPAddress NTPServer(192.168.3.11); // IP-адрес локального NTP-сервера

 NTPClient timeClient(ntpUDP, NTPServer.toString().c_str(), 0, 60000);

Причина этого в том, что класс NTPClient использует const char* для IP-адреса NTP-сервера.

Значения, полученные после того, как код высветится на плате, неверны, поскольку временные метки имеют год 2106.

Наоборот, когда я использую

 NTPClient timeClient(ntpUDP, "192.168.3.11", 0, 60000);

и запустить код на плате, это дает мне идеальные значения времени UTC.

Почему здесь некоторое несоответствие?

Код

#include <Wire.h>
#include <ETH.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <RTClib.h>

WiFiUDP ntpUDP;
/* IP CONF for NODE */
///////// >>>> ИЗМЕНИТЬ значения здесь <<<< ////////
const IPAddress node_static_ip(192, 168, 3, 101);
const IPAddress default_gateway(192, 168, 3, 250);
const IPAddress subnet_mask(255, 255, 255, 0);
const IPAddress dns_add(192, 168, 3, 250);
const IPAddress NTPServer(192, 168, 3, 11);

NTPClient timeClient(ntpUDP, "192.168.3.11", 0, 60000); // Это работает
NTPClient timeClient(ntpUDP, NTPServer.toString().c_str(), 0, 60000); // Это не будет (предоставляет метки времени 2106)

void setup() {
  // поместите сюда код установки для однократного запуска:
  Wire.begin(I2C_SDA, I2C_SCL);
  Serial.begin(115200);
  ETH.begin();
  ETH.config(node_static_ip, default_gateway, subnet_mask, dns_add);
  delay(1000);
  if (!rtc.begin()) {
    Serial.println("No RTC");
  }
  timeClient.begin();

}
void loop() {
  // поместите сюда ваш основной код для многократного запуска:
  timeClient.update();
  Serial.println(timeClient.getEpochTime());
  DateTime now_time(timeClient.getEpochTime());
  Serial.print(now_time.year(), DEC);
    Serial.print('/');
    Serial.print(now_time.month(), DEC);
    Serial.print('/');
    Serial.print(now_time.day(), DEC);
    Serial.print(now_time.hour(), DEC);
    Serial.print(':');
    Serial.print(now_time.minute(), DEC);
    Serial.print(':');
    Serial.print(now_time.second(), DEC);
Serial.println();

  delay(2000);

}

, 👍2

Обсуждение

Разве вы не имеете в виду toString().c_str(), а не toString.c_str()?, @Majenko

Извините опечатка! Я имел в виду последнее., @Shan-Desai

Я так и думал, поскольку первый не компилируется. Простой тест печати на серийный номер работает нормально. Я предлагаю добавить это в вашу программу, чтобы убедиться, что она действительно конвертирует ее неправильно, а не что-то еще. Serial.println(NTPServer.toString().c_str());, @Majenko


1 ответ


Лучший ответ:

5

Объект String, созданный в качестве возврата из IPAddress.toString() в качестве параметра конструктору NtpClient, является временным. Он содержит массив символов, возвращаемый функцией c_str(). NTPClient не копирует строку, а только сохраняет ссылку на нее. И указанная строка (массив символов) не существует в то время, когда NTPClient хочет ее использовать.

class TestClass {
public:
  TestClass(const char* _ip) : ip(_ip) { }

  void test() {
    Serial.println("--");
    Serial.println(ip);
    Serial.println("--");
  }

private:
  const char* ip;
};


//Строка s("abc");
// Тест тестового класса (s.c_str()); <- это работает

TestClass Test(String("abc").c_str()); // <- это не может работать

void setup() {
  Serial.begin(9600);
  Test.test();
}
,