#include #include "sdkconfig.h" /**/ #include "esp_log.h" #include "esp_system.h" /* FreeRTOS */ #include "freertos/FreeRTOS.h" #include "freertos/queue.h" #include "freertos/task.h" /* LVGL */ #include "lvgl.h" /* Private */ #include "app_lvgl.h" #include "app_ui.h" #define UI_TASK_HEAP 4096 #define APP_LOG_TAG "UI_WX" typedef struct { app_ui_cmd_t cmd; char *data; } app_ui_queue_item_t; LV_FONT_DECLARE(noto_sans_24) LV_FONT_DECLARE(noto_sans_96) LV_FONT_DECLARE(noto_sans_150) LV_FONT_DECLARE(noto_sans_240) LV_FONT_DECLARE(weather_icon_24) LV_FONT_DECLARE(weather_icon_96) LV_FONT_DECLARE(weather_icon_150) LV_FONT_DECLARE(weather_icon_240) static lv_style_t s_epd_style; static lv_theme_t s_epd_theme; static QueueHandle_t s_app_ui_update_queue; static void app_ui_theme_apply(lv_theme_t *th, lv_obj_t *obj); static void app_ui_task(void *pvParameters); int app_ui_init(void) { s_app_ui_update_queue = xQueueCreate(4, sizeof(app_ui_queue_item_t)); if (s_app_ui_update_queue == NULL) { return -1; } if (xTaskCreate(app_ui_task, "UI_WX", UI_TASK_HEAP, NULL, 3, NULL) != pdPASS) { ESP_LOGE(APP_LOG_TAG, "UI WX task failed to create."); return -2; } ESP_LOGI(APP_LOG_TAG, "UI WX initialized."); return 0; } int app_ui_update(app_ui_cmd_t cmd, char *data) { app_ui_queue_item_t item; item.cmd = cmd; item.data = malloc(strlen(data)); if (item.data == NULL) { return -1; } strcpy(item.data, data); if (xQueueSend(s_app_ui_update_queue, &item, portMAX_DELAY) != pdPASS) { return -2; } return 0; } static void app_ui_task(void *pvParameters) { lv_obj_t *screen_cond = NULL; /* Top bar */ lv_obj_t *container_topbar = NULL; lv_obj_t *label_sunrise = NULL; lv_obj_t *label_sunrise_time = NULL; lv_obj_t *label_sunset = NULL; lv_obj_t *label_sunset_time = NULL; lv_obj_t *label_uvi = NULL; lv_obj_t *label_uvi_value = NULL; lv_obj_t *label_updated = NULL; lv_obj_t *label_updated_time = NULL; /* Seperation line */ lv_obj_t *line_topbar = NULL; /* Middle display */ lv_obj_t *container_main = NULL; lv_obj_t *label_wxicon = NULL; lv_obj_t *label_temperature = NULL; lv_obj_t *label_temperature_hi = NULL; lv_obj_t *label_temperature_lo = NULL; lv_obj_t *label_temperature_real = NULL; lv_obj_t *label_temperature_real_desc = NULL; lv_obj_t *label_temperature_unit = NULL; lv_obj_t *label_temperature_hi_unit = NULL; lv_obj_t *label_temperature_lo_unit = NULL; lv_obj_t *label_temperature_real_unit = NULL; lv_obj_t *label_humidity = NULL; lv_obj_t *label_humidity_unit = NULL; lv_obj_t *label_wind_level = NULL; lv_obj_t *label_wind_speed = NULL; lv_obj_t *label_wind_direction = NULL; lv_point_t points_line_topbar[] = {{0, 37}, {959, 37}}; if (app_lvgl_lock(portMAX_DELAY) == 0) { lv_style_init(&s_epd_style); lv_style_set_pad_all(&s_epd_style, 0); lv_style_set_radius(&s_epd_style, 0); lv_style_set_border_width(&s_epd_style, 0); lv_theme_set_apply_cb(&s_epd_theme, app_ui_theme_apply); lv_disp_set_theme(NULL, &s_epd_theme); screen_cond = lv_obj_create(NULL); container_topbar = lv_obj_create(screen_cond); label_sunrise = lv_label_create(container_topbar); label_sunrise_time = lv_label_create(container_topbar); label_sunset = lv_label_create(container_topbar); label_sunset_time = lv_label_create(container_topbar); label_uvi = lv_label_create(container_topbar); label_uvi_value = lv_label_create(container_topbar); label_updated = lv_label_create(container_topbar); label_updated_time = lv_label_create(container_topbar); line_topbar = lv_line_create(screen_cond); container_main = lv_obj_create(screen_cond); label_wxicon = lv_label_create(container_main); label_temperature = lv_label_create(container_main); label_temperature_hi = lv_label_create(container_main); label_temperature_lo = lv_label_create(container_main); label_temperature_real = lv_label_create(container_main); label_temperature_real_desc = lv_label_create(container_main); label_temperature_unit = lv_label_create(container_main); label_temperature_hi_unit = lv_label_create(container_main); label_temperature_lo_unit = lv_label_create(container_main); label_temperature_real_unit = lv_label_create(container_main); label_humidity = lv_label_create(container_main); label_humidity_unit = lv_label_create(container_main); label_wind_level = lv_label_create(container_main); label_wind_direction = lv_label_create(container_main); label_wind_speed = lv_label_create(container_main); /* Top bar parts */ lv_obj_set_style_text_font(label_sunrise, &weather_icon_24, 0U); lv_obj_set_style_text_font(label_sunset, &weather_icon_24, 0U); lv_obj_set_style_text_font(label_uvi, &weather_icon_24, 0U); lv_obj_set_style_text_font(label_updated, &weather_icon_24, 0U); lv_obj_set_style_text_font(label_sunrise_time, ¬o_sans_24, 0U); lv_obj_set_style_text_font(label_sunset_time, ¬o_sans_24, 0U); lv_obj_set_style_text_font(label_uvi_value, ¬o_sans_24, 0U); lv_obj_set_style_text_font(label_updated_time, ¬o_sans_24, 0U); lv_label_set_text(label_sunrise, "\U0000F051"); lv_label_set_text(label_sunset, "\U0000F052"); lv_label_set_text(label_uvi, "\U0000F00D"); lv_label_set_text(label_updated, "\U0000F04C"); lv_label_set_text(label_sunrise_time, "----/--/-- --:--:--"); lv_label_set_text(label_sunset_time, "----/--/-- --:--:--"); lv_label_set_text(label_uvi_value, "-"); lv_label_set_text(label_updated_time, "----/--/-- --:--:--"); lv_obj_set_size(container_topbar, 960, 36); lv_obj_set_width(label_sunrise, 32); lv_obj_set_width(label_sunset, 32); lv_obj_set_width(label_uvi, 32); lv_obj_set_width(label_updated, 32); lv_obj_set_style_text_align(label_sunrise, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_sunset, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_uvi, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_updated, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_sunrise_time, LV_TEXT_ALIGN_LEFT, 0); lv_obj_set_style_text_align(label_sunset_time, LV_TEXT_ALIGN_LEFT, 0); lv_obj_set_style_text_align(label_uvi_value, LV_TEXT_ALIGN_LEFT, 0); lv_obj_set_style_text_align(label_updated_time, LV_TEXT_ALIGN_LEFT, 0); lv_obj_align(container_topbar, LV_ALIGN_TOP_LEFT, 0, 0); lv_obj_align(label_sunrise, LV_ALIGN_LEFT_MID, 0, 0); lv_obj_align(label_sunset, LV_ALIGN_LEFT_MID, 300, 0); lv_obj_align(label_uvi, LV_ALIGN_LEFT_MID, 600, 0); lv_obj_align(label_updated, LV_ALIGN_LEFT_MID, 680, 0); lv_obj_align(label_sunrise_time, LV_ALIGN_LEFT_MID, 40, 3); lv_obj_align(label_sunset_time, LV_ALIGN_LEFT_MID, 340, 3); lv_obj_align(label_uvi_value, LV_ALIGN_LEFT_MID, 640, 3); lv_obj_align(label_updated_time, LV_ALIGN_LEFT_MID, 720, 3); lv_line_set_points(line_topbar, points_line_topbar, 2); lv_obj_set_style_line_width(line_topbar, 1, 0); /* Main parts */ lv_obj_set_style_text_font(label_wxicon, &weather_icon_150, 0); lv_obj_set_style_text_font(label_temperature_unit, &weather_icon_96, 0); lv_obj_set_style_text_font(label_humidity_unit, &weather_icon_96, 0); lv_obj_set_style_text_font(label_temperature_hi_unit, &weather_icon_96, 0); lv_obj_set_style_text_font(label_temperature_lo_unit, &weather_icon_96, 0); lv_obj_set_style_text_font(label_temperature_real_unit, &weather_icon_96, 0); lv_obj_set_style_text_font(label_wind_direction, &weather_icon_96, 0); lv_obj_set_style_text_font(label_wind_level, &weather_icon_96, 0); lv_obj_set_style_text_font(label_temperature, ¬o_sans_150, 0); lv_obj_set_style_text_font(label_temperature_hi, ¬o_sans_96, 0); lv_obj_set_style_text_font(label_temperature_lo, ¬o_sans_96, 0); lv_obj_set_style_text_font(label_temperature_real, ¬o_sans_96, 0); lv_obj_set_style_text_font(label_temperature_real_desc, ¬o_sans_24, 0); lv_obj_set_style_text_font(label_humidity, ¬o_sans_96, 0); lv_obj_set_style_text_font(label_wind_speed, ¬o_sans_96, 0); lv_label_set_text(label_wxicon, "\U0000F07B"); lv_label_set_text(label_temperature_unit, "\U0000F03C"); lv_label_set_text(label_temperature_hi_unit, "\U0000F058"); lv_label_set_text(label_temperature_lo_unit, "\U0000F044"); lv_label_set_text(label_temperature_real_unit, "\U0000F03C"); lv_label_set_text(label_humidity_unit, "\U0000F07A"); lv_label_set_text(label_wind_direction, "\U0000F0B1"); lv_label_set_text(label_wind_level, "\U0000F0BA"); lv_label_set_text(label_temperature, "--"); lv_label_set_text(label_temperature_hi, "--"); lv_label_set_text(label_temperature_lo, "--"); lv_label_set_text(label_temperature_real, "--"); lv_label_set_text(label_temperature_real_desc, "Real\nFeel"); lv_label_set_text(label_humidity, "---"); lv_label_set_text(label_wind_speed, "----"); lv_obj_set_size(container_main, 960, 370); lv_obj_set_size(label_temperature_unit, 96, 96); lv_obj_set_size(label_temperature_hi_unit, 96, 96); lv_obj_set_size(label_temperature_lo_unit, 96, 96); lv_obj_set_size(label_temperature_real_unit, 96, 96); lv_obj_set_size(label_humidity_unit, 96, 150); lv_obj_set_size(label_wind_direction, 96, 96); lv_obj_set_size(label_wind_level, 96, 96); lv_obj_set_width(label_wxicon, 200); lv_obj_set_width(label_temperature, 200); lv_obj_set_width(label_temperature_hi, 150); lv_obj_set_width(label_temperature_lo, 150); lv_obj_set_width(label_temperature_real, 150); lv_obj_set_width(label_temperature_real_desc, 50); lv_obj_set_width(label_humidity, 200); lv_obj_set_width(label_wind_speed, 220); lv_obj_set_style_text_align(label_wxicon, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_temperature, LV_TEXT_ALIGN_RIGHT, 0); lv_obj_set_style_text_align(label_temperature_hi, LV_TEXT_ALIGN_RIGHT, 0); lv_obj_set_style_text_align(label_temperature_lo, LV_TEXT_ALIGN_RIGHT, 0); lv_obj_set_style_text_align(label_temperature_real, LV_TEXT_ALIGN_RIGHT, 0); lv_obj_set_style_text_align(label_temperature_real_desc, LV_TEXT_ALIGN_LEFT, 0); lv_obj_set_style_text_align(label_temperature_unit, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_temperature_hi_unit, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_temperature_lo_unit, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_temperature_real_unit, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_humidity, LV_TEXT_ALIGN_RIGHT, 0); lv_obj_set_style_text_align(label_humidity_unit, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_wind_direction, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_wind_level, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(label_wind_speed, LV_TEXT_ALIGN_RIGHT, 0); lv_obj_align(container_main, LV_ALIGN_TOP_LEFT, 0, 38); lv_obj_align(label_wxicon, LV_ALIGN_LEFT_MID, 0, 0); lv_obj_align(label_temperature_unit, LV_ALIGN_TOP_LEFT, 400, -20); lv_obj_align(label_temperature_hi_unit, LV_ALIGN_TOP_LEFT, 200, 115); lv_obj_align(label_temperature_lo_unit, LV_ALIGN_TOP_LEFT, 200, 235); lv_obj_align(label_temperature, LV_ALIGN_TOP_LEFT, 200, 0); lv_obj_align(label_temperature_hi, LV_ALIGN_TOP_LEFT, 250, 150); lv_obj_align(label_temperature_lo, LV_ALIGN_TOP_LEFT, 250, 250); lv_obj_align(label_temperature_real, LV_ALIGN_TOP_LEFT, 650, 130); lv_obj_align(label_temperature_real_desc, LV_ALIGN_TOP_LEFT, 585, 165); lv_obj_align(label_humidity, LV_ALIGN_TOP_LEFT, 600, 10); lv_obj_align(label_humidity_unit, LV_ALIGN_TOP_LEFT, 800, -20); lv_obj_align(label_temperature_real_unit, LV_ALIGN_TOP_LEFT, 800, 120); lv_obj_align(label_wind_direction, LV_ALIGN_TOP_LEFT, 500, 230); lv_obj_align(label_wind_speed, LV_ALIGN_TOP_LEFT, 580, 250); lv_obj_align(label_wind_level, LV_ALIGN_TOP_LEFT, 815, 240); lv_scr_load(screen_cond); app_lvgl_unlock(); } app_ui_queue_item_t item; for (;;) { /* Receive update requests. */ if (xQueueReceive(s_app_ui_update_queue, &item, portMAX_DELAY) == pdPASS) { if (app_lvgl_lock(portMAX_DELAY) == 0) { lv_obj_t *label = NULL; switch (item.cmd) { case APP_UI_CMD_SUNRISE: label = label_sunrise_time; break; case APP_UI_CMD_SUNSET: label = label_sunset_time; break; case APP_UI_CMD_UVI: label = label_uvi_value; break; case APP_UI_CMD_COND: label = label_wxicon; break; case APP_UI_CMD_TEMP: label = label_temperature; break; case APP_UI_CMD_TEMP_HI: label = label_temperature_hi; break; case APP_UI_CMD_TEMP_LO: label = label_temperature_lo; break; case APP_UI_CMD_TEMP_REAL: label = label_temperature_real; break; case APP_UI_CMD_HUMID: label = label_humidity; break; case APP_UI_CMD_UPDATED: label = label_updated_time; break; case APP_UI_CMD_WIND_SPEED: label = label_wind_speed; break; case APP_UI_CMD_WIND_LEVEL: label = label_wind_level; break; default: break; } lv_label_set_text(label, item.data); app_lvgl_unlock(); } free(item.data); } } } static void app_ui_theme_apply(lv_theme_t *th, lv_obj_t *obj) { lv_obj_add_style(obj, &s_epd_style, 0); }