Skip to content

Commit 3d47e35

Browse files
[ESP32] Add sntp support to get real time on esp32 (#32092)
* [ESP32] Add sntp support to get real time on esp32 * Address review comments * Did some restructoring to address review comments * Addressed review comments * Again addressed review comments * Restyled by clang-format * Some renaming and error check * Update sntp array to accomodate null terminating charactor --------- Co-authored-by: Restyled.io <commits@restyled.io>
1 parent 2c522cb commit 3d47e35

File tree

7 files changed

+156
-6
lines changed

7 files changed

+156
-6
lines changed

config/esp32/components/chip/Kconfig

+6
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,12 @@ menu "CHIP Core"
271271
Opens the commissioning window automatically at application boot time if
272272
the node is not yet commissioned.
273273

274+
config ENABLE_SNTP_TIME_SYNC
275+
bool "Enable SNTP time synchronization"
276+
default n
277+
help
278+
Enable this option to enable SNTP time synchronization
279+
274280
endmenu # "System Options"
275281

276282
menu "Security Options"

examples/energy-management-app/esp32/main/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ set(SRC_DIRS_LIST
3131
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/src"
3232
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota"
3333
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common"
34+
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/time"
3435
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension"
3536
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server"
3637
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util"

examples/energy-management-app/esp32/main/main.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include <common/CHIPDeviceManager.h>
2323
#include <common/Esp32AppServer.h>
2424
#include <common/Esp32ThreadInit.h>
25+
#if CONFIG_ENABLE_SNTP_TIME_SYNC
26+
#include <time/TimeSync.h>
27+
#endif
2528
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
2629
#include "spi_flash_mmap.h"
2730
#else
@@ -126,7 +129,8 @@ static void InitServer(intptr_t context)
126129
PrintOnboardingCodes(chip::RendezvousInformationFlags(CONFIG_RENDEZVOUS_MODE));
127130

128131
DeviceCallbacksDelegate::Instance().SetAppDelegate(&sAppDeviceCallbacksDelegate);
129-
Esp32AppServer::Init(); // Init ZCL Data Model and CHIP App Server AND Initialize device attestation config
132+
Esp32AppServer::Init(); // Init ZCL Data Model and CHIP App Server AND
133+
// Initialize device attestation config
130134
#if CONFIG_ENABLE_ESP_INSIGHTS_TRACE
131135
esp_insights_config_t config = {
132136
.log_type = ESP_DIAG_LOG_TYPE_ERROR | ESP_DIAG_LOG_TYPE_WARNING | ESP_DIAG_LOG_TYPE_EVENT,
@@ -144,8 +148,15 @@ static void InitServer(intptr_t context)
144148
Tracing::Register(backend);
145149
#endif
146150

147-
// Application code should always be initialised after the initialisation of server.
151+
// Application code should always be initialised after the initialisation of
152+
// server.
148153
ApplicationInit();
154+
155+
#if CONFIG_ENABLE_SNTP_TIME_SYNC
156+
const char kNtpServerUrl[] = "pool.ntp.org";
157+
const uint16_t kSyncNtpTimeIntervalDay = 1;
158+
chip::Esp32TimeSync::Init(kNtpServerUrl, kSyncNtpTimeIntervalDay);
159+
#endif
149160
}
150161

151162
extern "C" void app_main()

examples/energy-management-app/esp32/sdkconfig.defaults

+3
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,6 @@ CONFIG_DISABLE_READ_CLIENT=y
6464

6565
# Increase LwIP IPv6 address number
6666
CONFIG_LWIP_IPV6_NUM_ADDRESSES=6
67+
68+
# Enable sntp time sync
69+
CONFIG_ENABLE_SNTP_TIME_SYNC=y
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
*
3+
* Copyright (c) 2024 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include "TimeSync.h"
20+
#include <esp_sntp.h>
21+
#include <lib/support/CHIPMemString.h>
22+
#include <lib/support/logging/CHIPLogging.h>
23+
24+
static constexpr time_t kMinValidTimeStampEpoch = 1704067200; // 1 Jan 2019
25+
static constexpr uint32_t kSecondsInADay = 24 * 60 * 60;
26+
27+
namespace {
28+
const uint8_t kMaxNtpServerStringSize = 128;
29+
char sSntpServerName[kMaxNtpServerStringSize + 1];
30+
31+
CHIP_ERROR GetLocalTimeString(char * buf, size_t buf_len)
32+
{
33+
VerifyOrReturnError(buf_len > 0, CHIP_ERROR_INVALID_ARGUMENT);
34+
struct tm timeinfo;
35+
char strftime_buf[64];
36+
time_t now;
37+
time(&now);
38+
localtime_r(&now, &timeinfo);
39+
if (strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%dT%H:%M:%S%z", &timeinfo) == 0)
40+
{
41+
ChipLogError(DeviceLayer, "Buffer too small");
42+
return CHIP_ERROR_BUFFER_TOO_SMALL;
43+
}
44+
size_t print_size = snprintf(buf, buf_len, "%s, DST: %s", strftime_buf, timeinfo.tm_isdst ? "Yes" : "No");
45+
if (print_size >= (buf_len - 1))
46+
{
47+
ChipLogError(DeviceLayer, "Buffer size %d insufficient for localtime string. Required size: %d", static_cast<int>(buf_len),
48+
static_cast<int>(print_size));
49+
return CHIP_ERROR_BUFFER_TOO_SMALL;
50+
}
51+
return CHIP_NO_ERROR;
52+
}
53+
54+
bool ValidateTime()
55+
{
56+
time_t now;
57+
time(&now);
58+
return (now > kMinValidTimeStampEpoch);
59+
}
60+
61+
CHIP_ERROR PrintCurrentTime()
62+
{
63+
char local_time[64] = { 0 };
64+
ReturnErrorOnFailure(GetLocalTimeString(local_time, sizeof(local_time)));
65+
if (!ValidateTime())
66+
{
67+
ChipLogProgress(DeviceLayer, "Time not synchronised yet.");
68+
return CHIP_ERROR_INCORRECT_STATE;
69+
}
70+
ChipLogProgress(DeviceLayer, "The current time is: %s.", local_time);
71+
return CHIP_NO_ERROR;
72+
}
73+
74+
void TimeSyncCallback(struct timeval * tv)
75+
{
76+
ChipLogProgress(DeviceLayer, "SNTP Synchronised.");
77+
if (PrintCurrentTime() != CHIP_NO_ERROR)
78+
{
79+
ChipLogError(DeviceLayer, "SNTP time is not synchronised.");
80+
}
81+
}
82+
83+
} // anonymous namespace
84+
85+
namespace chip {
86+
namespace Esp32TimeSync {
87+
void Init(const char * aSntpServerName, const uint16_t aSyncSntpIntervalDay)
88+
{
89+
chip::Platform::CopyString(sSntpServerName, aSntpServerName);
90+
if (esp_sntp_enabled())
91+
{
92+
ChipLogProgress(DeviceLayer, "SNTP already initialized.");
93+
}
94+
ChipLogProgress(DeviceLayer, "Initializing SNTP. Using the SNTP server: %s", sSntpServerName);
95+
esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
96+
esp_sntp_setservername(0, sSntpServerName);
97+
esp_sntp_set_sync_interval(kSecondsInADay * aSyncSntpIntervalDay);
98+
esp_sntp_init();
99+
sntp_set_time_sync_notification_cb(TimeSyncCallback);
100+
}
101+
} // namespace Esp32TimeSync
102+
} // namespace chip
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
*
3+
* Copyright (c) 2024 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#pragma once
20+
#include <esp_sntp.h>
21+
#include <lib/core/CHIPError.h>
22+
#include <lib/support/Span.h>
23+
24+
namespace chip {
25+
namespace Esp32TimeSync {
26+
void Init(const char * aSntpServerName, uint16_t aSyncSntpIntervalDay);
27+
} // namespace Esp32TimeSync
28+
} // namespace chip

src/platform/ESP32/SystemTimeSupport.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,7 @@ Milliseconds64 ClockImpl::GetMonotonicMilliseconds64(void)
5050

5151
CHIP_ERROR ClockImpl::GetClock_RealTime(Microseconds64 & aCurTime)
5252
{
53-
// TODO(19081): This platform does not properly error out if wall clock has
54-
// not been set. For now, short circuit this.
55-
return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
56-
#if 0
53+
#if CONFIG_ENABLE_SNTP_TIME_SYNC
5754
struct timeval tv;
5855
if (gettimeofday(&tv, nullptr) != 0)
5956
{
@@ -70,6 +67,8 @@ CHIP_ERROR ClockImpl::GetClock_RealTime(Microseconds64 & aCurTime)
7067
static_assert(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD >= 0, "We might be letting through negative tv_sec values!");
7168
aCurTime = Microseconds64((static_cast<uint64_t>(tv.tv_sec) * UINT64_C(1000000)) + static_cast<uint64_t>(tv.tv_usec));
7269
return CHIP_NO_ERROR;
70+
#else
71+
return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
7372
#endif
7473
}
7574

0 commit comments

Comments
 (0)