Виникнення задачі визначення місцевого часу має промовисту історію, низку відповідальних за облік часу офіційних національних та міжнародних організацій, а також величезну підбірку статей у Вікіпедії. За бажання чи необхідності, читач має можливість самостійно погуглити і ознайомитися з цим шаром інформації.
А ми відразу перейдемо до специфіки визначення місцевого часу у мікроконтролерах, орієнтованих на побудову рішень у галузі інтернету речей (IoT). Також поговоримо про наявні методи та інструменти у арсеналі розробника, що дозволяють у той чи інший спосіб вести облік часу всередині розумного пристрою.
У даному тексті ми спробуємо не заглиблюватися у деталі на кшталт програмування коду, а будемо намагатися розглядати лише загальний принцип.
Чому розробників ІоТ пристроїв, має хвилювати задача обліку часу?
Обчислювальна техніка все частіше бере участь у нашому побуті і надає необхідні нам віртуальні інструменти дистанційного вирішення людиною реальних задач за тісної взаємодії машин з фізичним світом, його об’єктами та процесами.
Одним з головних рушіїв, що забезпечує вибуховий розвиток персональної обчислювальної техніки, на кшталт розумних і приєднаних до інтернет речей, є той факт, що таким пристроям не треба спати, не треба шукати вільну хвилинку щоб виконати рутинні задачі, на відміну від їх власників. Пристрої можуть уважно відслідковувати як перебігає весь фізичний процес, у якому вони беруть участь, або яким вони керують.
А користувач, навпаки, може приділити їм увагу лише тоді, коли йому буде це потрібно, або коли у нього буде на це час. Як куратор – користувач зможе переглядати результати їх роботи у вигляді дашбордів з графіками, нотифікаціями про події і докладними звітами.
Ось саме тут і виникає необхідність знаходження людини у єдиній системі координат з машинами, які її обслуговують.
Розумні пристрої, покликані на вирішення наших щоденних задач, мають працювати з вимірюванням фізичних величин, подіями, їх причинами та наслідками, а також здійснювати (напів)автоматичне прийняття і виконання керівних рішень підпорядкованими їм актуаторами.
Як ми вже зазначили вище, всі притаманні розумним системам логічні та технологічні ланцюжки, потребують синхронізованого обліку та фіксації часу.
У протилежному випадку, поєднані спільними комунікаціями та задачами обчислювальні комплекси просто не зможуть взаємодіяти ні один з одним, ні з користувачем.
У підсумку маємо, що час має бути не лише взаємно синхронізованим (системам цього було б достатньо), а і локалізованим до того часового поясу, в якому живе користувач даних систем.
А це значить, що кожна з систем крім єдиного синхронізованого часу (UTC), має також знати:
- значення місцевого часового поясу (TZ);
- перехід на літній час (DTS);
щоб на базі цих трьох показників мати змогу виконати визначення місцевого часу користувача:
LOCAL TIME = UTC + TZ + DST
Наприклад: системи, з якими працює користувач, можуть знаходитися у різних локаціях.
- Користувач (браузер) у Києві,
- Система_А (білінг туристичної агенції) у Лондоні,
- Система_Б (інтерфейс замовлення білетів на літак) у Каїрі.
- Пілот літака (браузер) у Каїрі.
Системи А і Б чудово синхронізовані через спільний для них UTC. Але Система Б також повинна вміти показати користувачеві з Києва, який зайшов на місцевий сайт у Каїрі, вірний час. Пілот має вчасно приїхати на роботу в Каїрі, щоб літак вчасно вилетів до Києва і так далі.
Примітка. Думаємо, що тут багато слів, але загальна ідея має бути зрозумілою.
Які існують інструменти для роботи з даними часу і чи вони достатні для визначення місцевого часу?
Час з моменту запуску (uptime)
Зазвичай контролер має в стандартних інструментах функцію підрахунку кількості секунд, що пройшли з моменту подачі живлення.
ESP8266, з прошивкою NodeMCU, має метод tmr.time()
який повертає кількість секунд. Щоправда, цей функціонал не рекомендується застосовувати для побудови функціональності подібної до годинника, адже цей час не є стабільним через відсутність механізму температурної компенсації.
Функція “uptime
”, рахує відносний час – тобто час з моменту вмикання пристрою.
Вбудований системний годинник
В різних мікроконтролерах цей архітектурний компонент може відрізнятися за своєю будовою і функціями. У NodeMCU, на рівні Lua, через C-модуль rtctime
маємо доступ до енергозалежної області пам’яті, в якій ведеться облік часу та календар, аналогічно до того, як це робить окремий апаратний RTC. Точність годинника 1 мікросекунда, але на практиці, досягається точність від 1 мілісекунди до кількох мілісекунд.
Зауважте, що вбудований механізм обліку календаря та часу, не є повноцінним RTC і також знаходиться під впливом коливань температури. Що призводить до набігання відхилення у приблизно 15 секунд на місяць.
Через це рекомендується, щоб вбудований облік часу обов’язково періодично синхронізувався з більш точним джерелом часу, наприклад з SNTP (через метод sntp.sync()
), чи зовнішнім апаратним RTC (через I2C / SPI).
Слід згадати також, що методи модуля rtctime, як-от rtctime.dsleep()
, дозволяють продовжувати вести облік часу і під час глибокого сну, що дуже зручно для побудови мініатюрних мобільних пристроїв на батареях з мінімальним енергоспоживанням.
Зв’язка модулів rtctime()
та sntp()
є простою у використанні і достатньою для більшості задач, але пам’ятаймо, що цей метод обліку та синхронізації часу є енергозалежним і у разі перезапуску мікроконтролера, дані про поточний час втрачаються.
Вбудований енергозалежний системний годинник рахує абсолютний час з моменту початкової синхронізації із зовнішнім джерелом значення поточного часу.
В якості джерела може виступати:
- користувач, який вручну встановлює поточний час (важливо: в цьому випадку це може бути місцевий час користувача з урахуванням переходу на літній час, або будь-який інший час, що вказав користувач);
- SNTP/NTP протокол, який завжди надає єдиний синхронізований час UTC (тобто без урахування місцевого часового поясу та літнього часу);
- зовнішній апаратний RTC, який в залежності від налаштувань користувачем, може надавати час UTC, або ж місцевий час користувача.
Як можна бачити, ні SNTP, ні RTC, не підтримують функціоналу місцевих таймзон та переходу між літнім та зимовим часом. Саме тому для визначення місцевого часу їх потрібно наповнювати сумісними даними, як от час UTC.
Додатковий енергонезалежний годинник реального часу (RTC)
Зовнішні годинники реального часу, є поширеними апаратними компонентами, з енергонезалежним обліком часу, що забезпечується завдяки встановленій на борту батареї резервного живлення.
Пристрої (апаратний модуль, що складається з чіпа з мініатюрним джерелом безперервного живлення на борту) даного класу, вирішують лише одну головну задачу – гарантовано і точно ведуть облік часу, що було встановлено користувачем, під час початкових налаштувань.
Моделі RTC у різних виробників різняться, але як правило, мають тотожний функціонал: години, хвилини, секунди, рік, місяць, день. Ще буває один чи два будильники, день тижня, тощо.
Енергонезалежний годинник рахує абсолютний час. І тому важливо, який саме початковий час було налаштовано, як поточне значення. Якщо користувач встановив свій місцевий час, то RTC і буде його рахувати, адже сам чіп не розрізняє часових поясів. Якщо ж користувач має план синхронізувати годинник реального часу, то краще було б вести облік часу відповідно до UTC. Так само, RTC не підтримує концепції переходу на літній час (DST).
Як можемо бачити, цей пристрій є важливим компонентом обліку часу у будь-якій електроніці, але не може самостійно вирішити задачу обліку місцевого часу так, як це роблять персональні комп’ютери та смартфони.
Для поглибленого ознайомлення, рекомендуємо переглянути вихідний код Lua-драйвера для чіпа DS3231: DS3231 Module , вихідний код.
Синхронізація часу через NTP (Network Time Protocol)
Ми не плануємо розглядати внутрішні механізми та можливості даного протоколу. Подивимося лише на цей протокол, як на інструмент в руках розробника розумного пристрою.
У загальних рисах, протокол SNTP (команда sntp.sync()
в прошивці NodeMCU з модулем sntp
), надає можливість отримати через підключення до інтернет поточне значення часу в секундах з 00:00 01.01.1970 року. Значення, яке ми можемо отримати називають по різному Epoc time, або Unix timestamp. Це буквально кількість секунд, що минули з умовного початку відліку в 1970 році.
Наприклад: 1612973134 означає 02/10/2021 @ 4:05pm UTC.
Цей метод обліку та джерело синхронізації часу, також не надає ні можливостей з обчислення місцевого часу користувача, ні обліку переходу на літній час.
Синхронізація часу через GPS
Існує чимало різноманітних рішень з гео-локації, ак і самих систем. Ми розглянемо приклад GPS-приймача, що надсилає свої дані мікроконтролеру через UART у форматі NMEA. Як правило, кожен подібний GPS-приймач, надсилає мінімально необхідні дані для визначення розташування. У NMEA, такі дані містить повідомлення із заголовком RMC – Recommended Minimum data. Це повідомлення також містить дані поточного часу.
Наведемо поле “time” з повідомлення RMC, що відповідає за поточне значення часу:
1 2 3 4 5 |
Значення: 161321.00 Назва: time, Формат: hhmmss.ss, Опис: UTC time Коментар: see note on UTC representation |
А також наведемо поле “date”, що відповідає за поточне значення дати:
1 2 3 4 5 |
Значення: 130121, Назва: date, Формат: ddmmyy, Опис: Date in day, month, year format Коментар: see note on UTC representation |
Також у протоколі повідомлень NMEA, існує спеціальне повідомлення ZDA, що відповідає виключно за час і дату. Ось як його описує виробник u-blox у своїх документах:
“The ZDA data set (time and date) contains information on UTC time, the date and local time.”
Можливо інші приймачі мають такий функціонал, але наш приймач u-blox NEO-6M, нам його не надає. І взагалі, ми не отримували ZDA, від NEO-6M, жодного разу.
З документації: повідомлення ZDA дійсно має два зарезервовані поля, щоб розмістити місцевий час, але як бачимо, вони, на жаль, не застосовуються з якихось причин:
“…
field – Reserved for data on local time (h), not specified here
field – Reserved for data on local time (min), not specified here
…”.
Таким чином виходить, що GPS-приймач є ще одним незалежним джерелом даних про єдиний, синхронізований час UTC і про місцевий час користувача знову не йдеться.
Синхронізація через спеціалізовані інтернет-сервіси
З розвитком технологій та зростання популярності інтернету речей, з’явилося багато онлайн сервісів, що покликано обслуговувати запити мініатюрних, підключених до інтернет розумних пристроїв. Наприклад, за запитом до API OpenWeatherMap, можливо отримати набір даних про поточну погоду. Аналогічним чином, від спеціалізованого сервера, можливо отримати значення поточного часу, що визначається за IP-адресою хоста, який робить такий запит. Такий сервер знаходить за IP-адресою приблизне розташування і надсилає відповідне значення зсуву часу для місцевої таймзони, а також окремо значення зсуву для літнього часу. Розробник може легко розрахувати місцевий час для свого мікроконтролера.
Розглянемо приклад, як працює такий сервіс по HTTP GET:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
abbreviation: EET client_ip: 193.2x.xxx.x datetime: 2021-02-10T19:31:28.515215+02:00 day_of_week: 3 day_of_year: 41 dst: false dst_from: dst_offset: 0 dst_until: raw_offset: 7200 timezone: Europe/Kiev unixtime: 1612978288 utc_datetime: 2021-02-10T17:31:28.515215+00:00 utc_offset: +02:00 week_number: 6 |
Як ми можемо бачити, це єдиний інструмент, який надав нам всі необхідні дані для розрахунку власного місцевого часу мікроконтролером розумного пристрою. – Нам достатньо взяти два параметри з відповіді і скласти їх:
unixtime: 1612978288
та
raw_offset: 7200
щоб обчислити поточне значення місцевого часу для нашого контролера:
1612985488 - Wed Feb 10 2021 19:31:28
Замість висновків
Щоб визначати місцевий час, потрібно вирішити одну просту задачу: хтось має сказати контролеру його таймзону, та дані щодо літнього/зимового часу.
Такі параметри може ввести або людина через передбачений інтерфейс налаштувань, або ж це може зробити спеціальний онлайн сервіс* у відповідь на запит до нього.
Примітка: Онлайн сервіс* може раптово перестати працювати, бо його розробник вирішив закрити проект. 😉
Як ми змогли побачити, задача визначення місцевого часу одночасно дуже проста і дуже складна, якщо вона вирішується у малопотужному, мініатюрному пристрої без клавіатури.
Пристрій також може не мати доступу до інтернет і SNTP не працюватиме. У той же час, пристрій може бути оснащено чим завгодно, від RTC і до GPS, але це ніяк не допоможе у автоматичному пошуку місцевого часу.
З іншого боку, місцевий час налаштований користувачем в ручну, теж має свої переваги і недоліки – окрім інтерфейсу вводу/виводу даних для користувача, є ще необхідність оновлювати налаштування, якщо пристрій було переміщено до іншої тайм-зони, чи країни з відмінним законодавством щодо переходу на літній час.
Також, під час проектування таких пристроїв, потрібно пам’ятати, що перехід на літній час можуть раптово відмінити, як це заплановано у ЕС.
Бажаємо успіхів!