lvgl_clock — часы и погода на LVGL
Часы с секундами, дата по-русски и погода за окном: температура, «ощущается как», минимум и максимум на сегодня, влажность, ветер, значок погоды. Время — из интернета (NTP), погода — с open-meteo.com (бесплатно, без ключа). На фоне всплывают разноцветные пузыри случайного размера и скорости, касание экрана выпускает новые.
Сеть Wi-Fi и город задаются в файле на SD-карте — прошивку под другой город пересобирать не нужно.
Подключение
Заголовок раздела «Подключение»Дисплей 800×480 и тач GT911 — как в рецепте lvgl_demo. На карте —
шрифты /SD/fonts/PT_Sans-Web-*.ttf и настройки /SD/clock.ini (оба есть в sd-card.zip):
ssid = my_wifipassword = my_passwordcity = Москваcity— город по-русски или латиницей; координаты и часовой пояс находит open-meteo.- Вместо города —
latitudeиlongitudeв градусах (север и восток — со знаком плюс). utc_offset— часовой пояс вручную, часы от UTC (бывает дробным:5.5). Без него пояс берётся по месту.- Пустой
ssid— рецепт сам к Wi-Fi не подключается и ждёт, пока это сделает кто-то другой (/SD/boot.luaв прошивке с Lua).
Файл — в UTF-8; правится в любом редакторе на ПК или по SFTP на живой плате
(/SD/clock.ini), новые настройки читаются при загрузке.
Включить
Заголовок раздела «Включить»Как и lvgl_demo, рецепт собирается без Lua — иначе прошивка не помещается во Flash:
cmake --preset Release -DH723_WITH_LUA=OFF -DH723_RECIPES="lvgl_clock"cmake --build build/ReleaseПрошивка с SSH — 727 КБ. Код LVGL, драйверы дисплея и тача берутся из lvgl_demo, HTTP — из
wifi_http (recipe.cmake), поэтому вместе с ними, а также с lcd_ltdc, рецепт не включают.
Вывод на плате
Заголовок раздела «Вывод на плате»lvgl_clock: startedlvgl_clock: Wi-Fi: подключение к my_wifi…gt911: product 911, panel 800x480lvgl_clock: screen readyIP Address: 192.168.1.50lvgl_clock: Wi-Fi: my_wifi, адрес 192.168.1.50lvgl_clock: Москва -> 55.7520, 37.6178 (585 ms)wifi_http: connect api.open-meteo.com (94.130.142.35):80 error -116lvgl_clock: weather 10 C (feels 8), code 2, humidity 81 %, wind 2.9 m/s, UTC+10800 s, historical-forecast-api.open-meteo.com 487 msЕсли провайдер не пускает к адресу api.open-meteo.com (строка с error -116), прогноз приходит
со второго сервера (см. ниже). Загрузка процессора (top в SSH) — около 23 % с пузырями и 3 % без них.
Что видно на экране, если что-то не так, — в строке состояния внизу слева: нет файла настроек, подключение к Wi-Fi, город не найден, сервер погоды не отвечает.
Как это работает
Заголовок раздела «Как это работает»- Две задачи.
clockNetподключается к Wi-Fi, находит город и раз в 15 минут спрашивает погоду — сетевые запросы длятся секундами, и экран в это время не замирает.lvglClockрисует. LVGL не потокобезопасна, поэтому сетевая задача экрана не трогает: она кладёт данные в общую структуру (shared) в критической секции и увеличивает счётчикseq. Таймер LVGL раз в 250 мс копирует структуру и перерисовывает погоду, только если счётчик изменился. - Город → координаты.
geocoding-api.open-meteo.com/v1/search?name=...— название в адресе кодируется побайтно в%XX(UTF-8). В ответе — широта, долгота и название по-русски. - Погода.
/v1/forecastс параметрамиcurrent=(сейчас) иdaily=(минимум и максимум на сегодня),timezone=auto— open-meteo добавляет в ответ смещение пояса местаutc_offset_seconds, по нему идут часы. Код погоды WMO (0 — ясно, 61 — дождь, 95 — гроза…) превращается в текст и значок вweatherText. - Два сервера погоды. Тот же запрос понимают
api.open-meteo.comиhistorical-forecast-api.open-meteo.com— они на разных адресах. Некоторые провайдеры не пускают к первому; рецепт пробует оба и запоминает тот, что ответил. - HTTP без TLS. open-meteo отвечает и по обычному HTTP, поэтому хватает сокетов
FreeRTOS+TCP (
wifiHttpGetизwifi_http) — без Mbed TLS и его ~60 КБ Flash. Ответ приходит кускамиchunked;wifiHttpGetсклеивает их, тело — обычная строка. - JSON без библиотеки. Ответ короткий и одинаковый по структуре:
jsonNumberищет"ключ":после начала нужного объекта ("current":{) и читает числоstrtof. Для чего-то сложнее подойдёт библиотека разбора JSON, например cJSON. - Время. NTP-клиент (
libs/ntp) ставит часы RTC по поясуTIME_ZONE(по умолчанию +3). Рецепт переводит их в пояс места:RTC − TIME_ZONE + utc_offset. Пока время не пришло (в RTC 2023 год или раньше), на экране «–:–». Секунды меняются раз в секунду, часы и минуты — раз в минуту, дата — раз в сутки: LVGL перерисовывает только изменённые надписи. - Значок погоды — несколько объектов LVGL с закруглением: круг — солнце (ночью — луна,
is_day), три круга и прямоугольник — облако, полоски — дождь, кружки — снег. - Пузыри. Таймер раз в 330 мс с вероятностью 1/3 выпускает пузырь в случайном месте
снизу (
lv_rand, зерно — счётчик тактов ядра). У пузыря две анимацииlv_anim: подъём за верх экрана (мелкие быстрее) и бесконечное покачивание по горизонтали (lv_anim_set_reverse_duration,lv_anim_path_ease_in_out). В конце подъёмаlv_obj_delete_anim_completed_cbудаляет пузырь. Пузыри — в отдельном слое, созданном первым, поэтому рисуются под надписями. Касание (LV_EVENT_PRESSEDэкрана) — четыре пузыря из точки касания; надписи и карточка не кликабельны, чтобы касание доходило до экрана. - Нагрузка. Каждый сдвиг пузыря — перерисовка куска градиентного фона и цифр под ним.
Экран обновляется 30 раз в секунду вместо 50 (
lv_display_get_refr_timer), пузырей — не больше 10.
Переделать под себя
Заголовок раздела «Переделать под себя»- Другие данные погоды — параметры
current=иdaily=вfetchWeather(список — в документации open-meteo) иjsonNumberс нужным ключом. Прогноз на несколько дней —forecast_days=3, значения вdaily— массивы по дням. - Число и размер пузырей —
MAX_BUBBLES,bubble(); без пузырей — убрать таймерbubbleTimer, загрузка процессора упадёт до 3 %. - Цвета и раскладка —
buildScreen. Шрифты с карты рисуются любого размера (lvglLoadFont).
Исходники рецепта: recipes/lvgl_clock
