Użyjemy tu API pogodowego - OpenWeatherMap. Zwraca ono dane w formacie JSON. Oczywiście by uzyskać dane musimy się zarejestrować w serwisie OpenWeatherMap i uzyskać w ten sposób klucz API.
kolejną rzeczą jest dodanie zależności w pliku idf_components.yml powinny być już tam ale warto sprawdzić.
- dependencies:
- lvgl:
- path: components/lvgl
- lvgl_esp32_drivers:
- path: components/lvgl_esp32_drivers
- esp_http_client:
- path: $ENV{IDF_PATH}/components/esp_http_client
Jeśli wszystko się zgadza możemy napisać prosty kod:
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "esp_wifi.h"
- #include "esp_log.h"
- #include "nvs_flash.h"
- #include "esp_http_client.h"
- #include "cJSON.h"
- #include "lvgl/lvgl.h"
- #include "lvgl_helpers.h"
- // Deklaracja ikon pogodowych
- extern lv_img_dsc_t sunny_icon;
- extern lv_img_dsc_t cloudy_icon;
- extern lv_img_dsc_t rainy_icon;
- #define WIFI_SSID "your_wifi_ssid"
- #define WIFI_PASS "your_wifi_password"
- #define WEATHER_API_KEY "your_openweathermap_api_key"
- #define CITY_ID "your_city_id" // Find your city ID on OpenWeatherMap
- #define WEATHER_URL "http://api.openweathermap.org/data/2.5/weather?id=" CITY_ID "&appid=" WEATHER_API_KEY "&units=metric"
- static const char *TAG = "weather_station";
- // Obiekty LVGL do wyświetlania danych pogodowych
- static lv_obj_t *label_temp;
- static lv_obj_t *label_humidity;
- static lv_obj_t *label_pressure;
- static lv_obj_t *img_weather_icon;
- static void lv_tick_task(void *arg) {
- (void) arg;
- lv_tick_inc(portTICK_PERIOD_MS);
- }
- static void update_weather_display(const char* temp, const char* humidity, const char* pressure, const char* icon) {
- lv_label_set_text_fmt(label_temp, "Temp: %s °C", temp);
- lv_label_set_text_fmt(label_humidity, "Humidity: %s %%", humidity);
- lv_label_set_text_fmt(label_pressure, "Pressure: %s hPa", pressure);
- if (strcmp(icon, "01d") == 0 || strcmp(icon, "01n") == 0) {
- lv_img_set_src(img_weather_icon, &sunny_icon);
- } else if (strcmp(icon, "02d") == 0 || strcmp(icon, "02n") == 0 ||
- strcmp(icon, "03d") == 0 || strcmp(icon, "03n") == 0 ||
- strcmp(icon, "04d") == 0 || strcmp(icon, "04n") == 0) {
- lv_img_set_src(img_weather_icon, &cloudy_icon);
- } else if (strcmp(icon, "09d") == 0 || strcmp(icon, "09n") == 0 ||
- strcmp(icon, "10d") == 0 || strcmp(icon, "10n") == 0) {
- lv_img_set_src(img_weather_icon, &rainy_icon);
- }
- }
- static void http_get_weather_data(void *pvParameters) {
- esp_http_client_config_t config = {
- .url = WEATHER_URL,
- };
- esp_http_client_handle_t client = esp_http_client_init(&config);
- esp_err_t err = esp_http_client_perform(client);
- if (err == ESP_OK) {
- int len = esp_http_client_get_content_length(client);
- char *buffer = malloc(len + 1);
- esp_http_client_read(client, buffer, len);
- buffer[len] = 0;
- cJSON *json = cJSON_Parse(buffer);
- if (json != NULL) {
- cJSON *main = cJSON_GetObjectItemCaseSensitive(json, "main");
- cJSON *weather = cJSON_GetObjectItemCaseSensitive(json, "weather");
- if (main != NULL && weather != NULL) {
- cJSON *temp = cJSON_GetObjectItemCaseSensitive(main, "temp");
- cJSON *humidity = cJSON_GetObjectItemCaseSensitive(main, "humidity");
- cJSON *pressure = cJSON_GetObjectItemCaseSensitive(main, "pressure");
- cJSON *weather_item = cJSON_GetArrayItem(weather, 0);
- cJSON *icon = cJSON_GetObjectItemCaseSensitive(weather_item, "icon");
- if (temp != NULL && humidity != NULL && pressure != NULL && icon != NULL) {
- ESP_LOGI(TAG, "Temp: %.2f °C, Humidity: %d %%, Pressure: %d hPa, Icon: %s",
- temp->valuedouble, humidity->valueint, pressure->valueint, icon->valuestring);
- char temp_str[16], humidity_str[16], pressure_str[16];
- snprintf(temp_str, sizeof(temp_str), "%.1f", temp->valuedouble);
- snprintf(humidity_str, sizeof(humidity_str), "%d", humidity->valueint);
- snprintf(pressure_str, sizeof(pressure_str), "%d", pressure->valueint);
- update_weather_display(temp_str, humidity_str, pressure_str, icon->valuestring);
- }
- }
- cJSON_Delete(json);
- }
- free(buffer);
- } else {
- ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
- }
- esp_http_client_cleanup(client);
- vTaskDelete(NULL);
- }
- static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
- if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
- esp_wifi_connect();
- } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
- esp_wifi_connect();
- } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
- xTaskCreate(http_get_weather_data, "http_get_weather_data", 4096, NULL, 5, NULL);
- }
- }
- void wifi_init(void) {
- esp_netif_init();
- esp_event_loop_create_default();
- esp_netif_create_default_wifi_sta();
- wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
- esp_wifi_init(&cfg);
- esp_event_handler_instance_t instance_any_id;
- esp_event_handler_instance_t instance_got_ip;
- esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, &instance_any_id);
- esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, &instance_got_ip);
- wifi_config_t wifi_config = {
- .sta = {
- .ssid = WIFI_SSID,
- .password = WIFI_PASS,
- },
- };
- esp_wifi_set_mode(WIFI_MODE_STA);
- esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
- esp_wifi_start();
- }
- void app_main() {
- // Inicjalizacja NVS
- esp_err_t ret = nvs_flash_init();
- if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
- ESP_ERROR_CHECK(nvs_flash_erase());
- ret = nvs_flash_init();
- }
- ESP_ERROR_CHECK(ret);
- // Inicjalizacja Wi-Fi
- wifi_init();
- // Inicjalizacja LVGL
- lv_init();
- // Inicjalizacja sterownika ekranu i dotyku
- lvgl_driver_init();
- // Inicjalizacja bufora dla LVGL
- static lv_disp_draw_buf_t draw_buf;
- static lv_color_t buf1[DISP_BUF_SIZE];
- lv_disp_draw_buf_init(&draw_buf, buf1, NULL, DISP_BUF_SIZE);
- // Inicjalizacja wyświetlacza
- static lv_disp_drv_t disp_drv;
- lv_disp_drv_init(&disp_drv);
- disp_drv.draw_buf = &draw_buf;
- disp_drv.flush_cb = disp_driver_flush;
- disp_drv.hor_res = 320; // Dostępna rozdzielczość pozioma
- disp_drv.ver_res = 240; // Dostępna rozdzielczość pionowa
- lv_disp_drv_register(&disp_drv);
- // Inicjalizacja sterownika dotykowego
- static lv_indev_drv_t indev_drv;
- lv_indev_drv_init(&indev_drv);
- indev_drv.type = LV_INDEV_TYPE_POINTER;
- indev_drv.read_cb = touch_driver_read;
- lv_indev_drv_register(&indev_drv);
- // Inicjalizacja ticków dla LVGL
- const esp_timer_create_args_t periodic_timer_args = {
- .callback = &lv_tick_task,
- .name = "periodic_gui"
- };
- esp_timer_handle_t periodic_timer;
- esp_timer_create(&periodic_timer_args, &periodic_timer);
- esp_timer_start_periodic(periodic_timer, 1 * 1000U);
- // Utworzenie obiektów GUI
- label_temp = lv_label_create(lv_scr_act());
- lv_obj_align(label_temp, LV_ALIGN_TOP_LEFT, 10, 10);
- label_humidity = lv_label_create(lv_scr_act());
- lv_obj_align(label_humidity, LV_ALIGN_TOP_LEFT, 10, 40);
- label_pressure = lv_label_create(lv_scr_act());
- lv_obj_align(label_pressure, LV_ALIGN_TOP_LEFT, 10, 70);
- img_weather_icon = lv_img_create(lv_scr_act());
- lv_obj_align(img_weather_icon, LV_ALIGN_CENTER, 0, 0);
- // Główna pętla
- while (1) {
- lv_task_handler();
- vTaskDelay(pdMS_TO_TICKS(10));
- }
- }
sunny_icon.c
cloudy_icon.c
rainy_icon.c
Przykład dla sunny_icon.c
- #include "lvgl/lvgl.h"
- LV_IMG_DECLARE(sunny_icon);
- lv_img_dsc_t sunny_icon = {
- .header.always_zero = 0,
- .header.w = 64,
- .header.h = 64,
- .data_size = sizeof(sunny_icon_map),
- .header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA,
- .data = sunny_icon_map,
- };
Oczywiście przed kompilacją należy zamienić your_wifi_ssid, your_wifi_password, your_openweathermap_api_key i your_city_id na odpowiednie wartości.
Można również dodać więcej ikon pogodowych, aby obsłużyć inne warunki pogodowe.
To tylko taki prosty przykładzik.