Вопрос или проблема
Я пишу код на C для ESP32C3, то есть для устройства типа Arduino. У него нет внутреннего часового механизма, поэтому для получения времени я обращаюсь к NTP-серверу в интернете.
Я также общаюсь с погодным сервером, чтобы получить локальную погоду, включая время восхода и захода солнца.
Сейчас всё в порядке, за исключением того факта, что погодный сервер, похоже, не учитывает переход на летнее время, поэтому он дает мне значения, которые на один час не соответствуют.
Поэтому я написал эту процедуру, чтобы попытаться выяснить, нужно ли мне корректировать ответ на восход/заход солнца [это на Arduino C]
Вот определение, да, я в Европе.
Переход на летнее время всегда начинается в воскресенье, второе в марте, и заканчивается в первое воскресенье ноября в Соединенных Штатах. Это контрастирует с Великобританией и Европейским Союзом, где летнее время начинается в последнее воскресенье марта и заканчивается в последнее воскресенье октября.
char dayName[10];
char dayMonth[2];
char monthYear[2];
strftime(dayName,64,"%A", &timeinfo); // день недели
strftime(dayMonth,64,"%d", &timeinfo); // день месяца
strftime(monthYear,64,"%B", &timeinfo); // месяц года
if (!strcmp(dayName, "Sunday")) {
if (atoi(monthYear) == 10) {
if (atoi(dayMonth) > 31 - 7) {
// последнее воскресенье октября, ПЛВ = ложь
DST = false;
}
}
if (atoi(monthYear) == 3) {
if (atoi(dayMonth) > 31 - 7) {
// последнее воскресенье марта, ПЛВ = истина
DST = true;
}
}
}
Вопросы;
- Этот код выглядит разумно?
- Есть ли лучший способ сделать это, помните, что это не компьютер, это ESP32C3; так что вы не получаете дату, например – у него нет понятия о дате/времени.
Выглядит хорошо, но вы могли бы просто уменьшить 64 до 10 для dayName и до 30 для dayMonth и monthYear, чтобы оптимизировать хранение (помните, это ESP, который не является очень мощным чипом, поэтому оптимизация использования памяти необходима), а также вы могли бы добавить лог-сообщение, чтобы оставаться в курсе, например ESP_LOGI(TAG, "DST: %s", DST ? "true" : "false");
.
Ответ или решение
Код Arduino для определения, находимся ли мы в режиме перехода на летнее/зимнее время (DST)
Ваша задача включает в себя проверку, находится ли ваше устройство ESP32C3 в режиме перехода на летнее/зимнее время, используя данные о времени, полученные с NTP-сервера, и данные о восходе и закате солнца с погодного сервера. Поскольку ваше устройство не имеет внутренних часов, вам необходимо правильно обработать переход на летнее/зимнее время, особенно учитывая, что заданные данные о восходе/закате могут не учитывать DST.
1. Анализ вашего текущего кода
Ваш код использует strftime
для получения дня недели, дня месяца и месяца, и условные операторы для определения перехода на летнее/зимнее время на основе данных о текущей дате. Однако есть несколько моментов, которые следует улучшить:
- Оптимизация памяти: Вы можете уменьшить размеры массивов. Например, замените
char dayName[10]
наchar dayName[10]
и сокращение размерностей для других переменных. - Улучшение логирования: Добавление лог-сообщений может помочь в отладке состояния вашего приложения. Использование такой конструкции, как
ESP_LOGI(TAG, "DST: %s", DST ? "true" : "false");
, позволит вам видеть текущее состояние DST в реальном времени.
2. Улучшенная версия кода
Ниже представлена доработанная версия кода с учетом предложенных улучшений:
#include <time.h>
#include <WiFi.h>
#include <ESP_LOG.h> // Подключите библиотеку для логирования
bool isDST(struct tm timeinfo) {
// Определим переменные для хранения дня, месяца и дня недели
char dayName[10];
char dayMonth[3];
char monthYear[10];
strftime(dayName, sizeof(dayName), "%A", &timeinfo); // Получаем день недели
strftime(dayMonth, sizeof(dayMonth), "%d", &timeinfo); // Получаем день месяца
strftime(monthYear, sizeof(monthYear), "%m", &timeinfo); // Получаем месяц
int month = atoi(monthYear);
int day = atoi(dayMonth);
bool DST = false;
if (strcmp(dayName, "Sunday") == 0) {
if (month == 10) {
// Проверка на последнюю воскресенье октября
if (day > (31 - 7)) {
DST = false; // Зима
}
} else if (month == 3) {
// Проверка на последнее воскресенье марта
if (day > (31 - 7)) {
DST = true; // Лето
}
}
}
// Записываем текущее состояние DST в лог
ESP_LOGI("DST_CHECK", "DST: %s", DST ? "true" : "false");
return DST;
}
3. Объяснение логики кода
В данной версии кода мы:
- Оптимизировали структуру хранения данных, уменьшив размеры массивов.
- Внедрили логику, которая проверяет неделю и месяц, чтобы правильно определить DST.
- Использовали функции для логирования состояния DST.
Заключение
Ваша исходная логика была правильной, но целесообразно оптимизировать код, чтобы уменьшить потребление памяти и улучшить отладку. Использование NTP-сервера обеспечивает точность времени, что критично для корректного определения перехода на летнее/зимнее время. Надеюсь, предложенные изменения помогут вам сделать код более эффективным и понятным.