#include "meteofrance.h" #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" #include "esp_err.h" #include "esp_log.h" #include "esp_check.h" #include "driver/i2c.h" #include "esp_event.h" #include "nvs_flash.h" #include #include "esp_vfs_fat.h" #include "sdmmc_cmd.h" #include #include "bsp/esp-bsp.h" #include "main.h" #include "ihm.h" // OTA #include "esp_ota_ops.h" #include "esp_http_client.h" #include "esp_https_ota.h" // Includes personnels #include "wifi_logger.h" #include "obtain_time.h" #include "image_downloader.h" #include "communication.h" #include "stateManagement.h" #include "am2302_rmt.h" // GPIO assignment #define AM2302_GPIO 4 #include "esp_littlefs.h" #define MOUNT_POINT "/sdcard" // Pin assignments can be set in menuconfig, see "SD SPI Example Configuration" menu. // You can also change the pin assignments here by changing the following 4 lines. #define PIN_NUM_MISO 13 #define PIN_NUM_MOSI 11 #define PIN_NUM_CLK 12 #define PIN_NUM_CS 10 static const char *TAG = "domoTic"; extern esp_mqtt_client_handle_t client; typedef enum domo_events{ WIFI_CONNECTED, TIME_SETTED } domo_events; static EventGroupHandle_t hevt; #define WIFI_RDY 0b0001 static lv_subject_t wifiStatus; LV_IMAGE_DECLARE(wifi_ok); LV_IMAGE_DECLARE(wifi_ko); static void wifiStatus_obs_cb(lv_observer_t * observer, lv_subject_t * subject); static void wifiStatus_obs_cb(lv_observer_t * observer, lv_subject_t * subject) { ESP_LOGE(TAG, "On passe dans le callback de chgt de statut; %li", lv_subject_get_int(subject)); bsp_display_lock(0); lv_obj_t * wifiSt = lv_obj_get_child(lv_obj_get_child(lv_layer_top(), 0),2); if(lv_obj_check_type(wifiSt, &lv_image_class)){ switch (lv_subject_get_int(subject)) { case 0: lv_image_set_src(wifiSt,&wifi_ko); break; case 1: lv_image_set_src(wifiSt,&wifi_ok); break; default: break; } }else{ ESP_LOGE(TAG, "L'objet recuip en semble pas etre du bon type"); } bsp_display_unlock(); //int32_t prev_v = lv_subject_get_previous_int(subject); //int32_t cur_v = lv_subject_get_int(subject); //lv_obj_t * btn = lv_observer_get_target(observer); } void send_event(domo_events evt){ switch(evt){ case WIFI_CONNECTED: xEventGroupSetBits(hevt,WIFI_RDY); start_wifi_logger(); wifi_log_e("test", "%s %d %f", "hello world wifi logger", 43, 45.341223242); // write log over wifi with log level -> ERROR } ESP_LOGI(TAG, "connected to ap SSID"); if(lvgl_port_lock(0)){ ESP_LOGE(TAG,"Statut Wifi 1"); lv_subject_set_int(&wifiStatus,1); lvgl_port_unlock(); } break; case TIME_SETTED: break; } } struct state mainState={ .wifi_init=false, .display_init=false }; void mount_sd_card() { // Options for mounting the filesystem. // If format_if_mount_failed is set to true, SD card will be partitioned and // formatted in case when mounting fails. esp_vfs_fat_sdmmc_mount_config_t mount_config = { .format_if_mount_failed = false, .max_files = 5, .allocation_unit_size = 16 * 1024}; sdmmc_card_t *card; const char mount_point[] = MOUNT_POINT; ESP_LOGI(TAG, "Initializing SD card"); ESP_LOGI(TAG, "Using SPI peripheral"); sdmmc_host_t host = SDSPI_HOST_DEFAULT(); spi_bus_config_t bus_cfg = { .mosi_io_num = PIN_NUM_MOSI, .miso_io_num = PIN_NUM_MISO, .sclk_io_num = PIN_NUM_CLK, .quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = 4000, }; esp_err_t ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize bus."); return; } sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT(); slot_config.gpio_cs = PIN_NUM_CS; slot_config.host_id = host.slot; ESP_LOGI(TAG, "Mounting filesystem"); ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card); if (ret != ESP_OK) { if (ret == ESP_FAIL) { ESP_LOGE(TAG, "Failed to mount filesystem. " "If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option."); } else { ESP_LOGE(TAG, "Failed to initialize the card (%s). " "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); } return; } ESP_LOGI(TAG, "Filesystem mounted"); // Card has been initialized, print its properties sdmmc_card_print_info(stdout, card); } extern char *days[7]; extern char *months[12]; esp_err_t _ota_http_event_handler(esp_http_client_event_t *evt) { switch (evt->event_id) { case HTTP_EVENT_ERROR: ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); break; case HTTP_EVENT_ON_CONNECTED: ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); break; case HTTP_EVENT_HEADER_SENT: ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); break; case HTTP_EVENT_ON_HEADER: ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); break; case HTTP_EVENT_ON_DATA: ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); break; case HTTP_EVENT_ON_FINISH: ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); break; case HTTP_EVENT_DISCONNECTED: ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED"); break; case HTTP_EVENT_REDIRECT: ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT"); break; } return ESP_OK; } extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start"); extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end"); void simple_ota_example_task(void *pvParameter) { ESP_LOGI(TAG, "Starting OTA example task"); #ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF esp_netif_t *netif = get_example_netif_from_desc(bind_interface_name); if (netif == NULL) { ESP_LOGE(TAG, "Can't find netif from interface description"); abort(); } struct ifreq ifr; esp_netif_get_netif_impl_name(netif, ifr.ifr_name); ESP_LOGI(TAG, "Bind interface name is %s", ifr.ifr_name); #endif esp_http_client_config_t config = { .url = "http://192.168.0.28:8070/rgb_lcd.bin", .timeout_ms = 30000, .buffer_size = 6144, .buffer_size_tx = 6144, //TX Buffer, Main Buffer .event_handler = _ota_http_event_handler, .keep_alive_enable = true, .cert_pem = (char *)server_cert_pem_start, #ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF .if_name = &ifr, #endif }; #ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL_FROM_STDIN char url_buf[OTA_URL_SIZE]; if (strcmp(config.url, "FROM_STDIN") == 0) { example_configure_stdin_stdout(); fgets(url_buf, OTA_URL_SIZE, stdin); int len = strlen(url_buf); url_buf[len - 1] = '\0'; config.url = url_buf; } else { ESP_LOGE(TAG, "Configuration mismatch: wrong firmware upgrade image url"); abort(); } #endif #ifdef CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK config.skip_cert_common_name_check = true; #endif esp_https_ota_config_t ota_config = { .http_config = &config, }; ESP_LOGI(TAG, "Attempting to download update from %s", config.url); esp_err_t ret = esp_https_ota(&ota_config); if (ret == ESP_OK) { ESP_LOGI(TAG, "OTA Succeed, Rebooting..."); esp_restart(); } else { ESP_LOGE(TAG, "Firmware upgrade failed"); } while (1) { vTaskDelay(1000 / portTICK_PERIOD_MS); } } am2302_handle_t sensor = NULL; void readTempHumid(void *pvParameter) { float temperature = 0; float humidity = 0; while (1) { am2302_read_temp_humi(sensor, &temperature, &humidity); char buff[40]; ESP_LOGI(TAG, "Temperature: %.1f °C, Humidity: %.1f %%", temperature, humidity); sprintf(buff,"%.1f °C, %.1f %%", temperature, humidity); show_temp(buff); vTaskDelay(60000 / portTICK_PERIOD_MS); } } void alloc_fail(size_t size, uint32_t caps, const char * function_name){ ESP_LOGE(TAG,"fail alloc %u in %" PRIu32 " in %s", size,caps,function_name); } void wifi_cb(wifi_evt evt){ switch(evt){ case CONNECTED: send_event(WIFI_CONNECTED); case DISCONNECTED: if(lvgl_port_lock(0)){ ESP_LOGE(TAG,"Statut Wifi 0"); lv_subject_set_int(&wifiStatus,0); lvgl_port_unlock(); } break; case GOT_IP: if(lvgl_port_lock(0)){ ESP_LOGE(TAG,"Statut Wifi 1"); lv_subject_set_int(&wifiStatus,1); lvgl_port_unlock(); } break; case CONNECT_FAIL: if(lvgl_port_lock(0)){ ESP_LOGE(TAG,"Statut Wifi 0"); lv_subject_set_int(&wifiStatus,0); lvgl_port_unlock(); } break; default: if(lvgl_port_lock(0)){ ESP_LOGE(TAG,"Statut Wifi 0"); lv_subject_set_int(&wifiStatus,0); lvgl_port_unlock(); } break; } } extern lv_subject_t forecastD1Subj; extern lv_subject_t forecastD2Subj; extern lv_subject_t forecastD3Subj; extern lv_subject_t forecastH1Subj; extern lv_subject_t forecastH2Subj; extern lv_subject_t forecastH3Subj; extern lv_subject_t meteoStatus; void weather_data_retreived(struct meteodailyforecast_data dailyDatas[3], struct meteoforecast_data datas[3]) { /* ESP_LOGE(TAG, "debut debug"); printf("%lld\n", datas[0].datetime); printf("%s\n", datas[0].previsions.desc); printf("%f\n", datas[0].previsions.value); printf("%lld\n", datas[1].datetime); printf("%s\n", datas[1].previsions.desc); printf("%f\n", datas[1].previsions.value); printf("%lld\n", datas[2].datetime); printf("%s\n", datas[2].previsions.desc); printf("%f\n", datas[2].previsions.value); ESP_LOGE(TAG, "fin debug"); */ if (display_lock("weather_data_retreived")) { ESP_LOGV("MeteoFrance", "------------------------------------- Set des subjects J --------------------------------"); // Prévisions des 3 prochains jours lv_subject_set_pointer(&forecastD1Subj, &dailyDatas[0]); lv_subject_set_pointer(&forecastD2Subj, &dailyDatas[1]); lv_subject_set_pointer(&forecastD3Subj, &dailyDatas[2]); ESP_LOGV("MeteoFrance", "------------------------------------- Set des subjects H--------------------------------"); // Prévisions des 3 prochains jours ESP_LOGV("MeteoFrance", "Pointeur %lli", datas[0].datetime); lv_subject_set_pointer(&forecastH1Subj, &datas[0]); lv_subject_set_pointer(&forecastH2Subj, &datas[1]); lv_subject_set_pointer(&forecastH3Subj, &datas[2]); lv_subject_set_int(&meteoStatus, 0); display_unlock("weather_data_retreived"); ESP_LOGV(TAG, "------------------------------------- Fin Set des subjects --------------------------------"); }else{ ESP_LOGE(TAG, "Impossible d'obtenir le mutex dans weather_data_retreived"); } } void weather_data_retreived_start() { //if (display_lock("weather_data_retreived_start")) //{ //ESP_LOGE(TAG,"Mutex obtenu dans weather_data_retreived_start"); lv_subject_set_int(&meteoStatus, 1); ESP_LOGE(TAG,"Subject setted weather_data_retreived_start"); //display_unlock("weather_data_retreived_start"); //}else{ // ESP_LOGE(TAG,"Impossible d'obtenir le mutex dans weather_data_retreived_start"); //} } void app_main(void) { printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size()); printf("Free heap size: %" PRIu32 " bytes\n", esp_get_free_heap_size()); heap_caps_print_heap_info(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); heap_caps_register_failed_alloc_callback(alloc_fail); printf("1- Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); esp_log_level_set("wifi", ESP_LOG_ERROR); esp_log_level_set(TAG, ESP_LOG_VERBOSE); printf("2- Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); //mount_sd_card(); bsp_sdcard_mount(); //lv_log_register_print_cb(log_cb); // LCD HW initialization //ESP_ERROR_CHECK(app_lcd_init()); printf("4 - Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); // Touch initialization //ESP_ERROR_CHECK(app_touch_init()); printf("5 - Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); // LVGL initialization //ESP_ERROR_CHECK(app_lvgl_init()); printf("6 - Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); ESP_LOGI(TAG, "Initializing LittleFS"); esp_vfs_littlefs_conf_t conflfs = { .base_path = "/littlefs", .partition_label = "littlefs", .format_if_mount_failed = true, .dont_mount = false, }; // Use settings defined above to initialize and mount LittleFS filesystem. // Note: esp_vfs_littlefs_register is an all-in-one convenience function. esp_err_t retlfs = esp_vfs_littlefs_register(&conflfs); if (retlfs != ESP_OK){ if (retlfs == ESP_FAIL){ ESP_LOGE(TAG, "Failed to mount or format filesystem"); }else if (retlfs == ESP_ERR_NOT_FOUND){ ESP_LOGE(TAG, "Failed to find LittleFS partition"); }else{ ESP_LOGE(TAG, "Failed to initialize LittleFS (%s)", esp_err_to_name(retlfs)); } return; } size_t total = 0, used = 0; retlfs = esp_littlefs_info(conflfs.partition_label, &total, &used); if (retlfs != ESP_OK) { ESP_LOGE(TAG, "Failed to get LittleFS partition information (%s)", esp_err_to_name(retlfs)); } else { ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); } // On affiche au plus tot l'ecran de démarrage // ESP_ERROR_CHECK(esp_lcd_panel_mirror(lcd_panel,true,true)); init_display(); display_lock("app_main"); app_main_display(); display_unlock("app_main"); printf("7 - Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); // Initialize 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); printf("8 - Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); lv_subject_init_int(&wifiStatus,0); lv_subject_add_observer_obj(&wifiStatus, wifiStatus_obs_cb, NULL, NULL); wifi_init_sta(wifi_cb); // esp_log_level_set("tcp_handler", ESP_LOG_NONE); printf("8b - Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); printf("9 - Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); on_weather_data_retrieval(weather_data_retreived); on_weather_data_retrieval_start(weather_data_retreived_start); initialise_weather_data_retrieval(600000); ESP_LOGW(TAG, "Weather data retrieval initialized"); time_t now; struct tm timeinfo; time(&now); localtime_r(&now, &timeinfo); // Is time set? If not, tm_year will be (1970 - 1900). if (timeinfo.tm_year < (2016 - 1900)) { ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP."); obtain_time(); // update 'now' variable with current time time(&now); } printf("10. Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); heap_caps_print_heap_info(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); printf("11. Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); ESP_LOGW(TAG, "On telecharge l'image cuve"); TaskHandle_t xHandle = NULL; BaseType_t ret1; ret1 = xTaskCreate(&imgdwn, "imageDownload_task", 3 * 1024, NULL, 5, &xHandle); if (ret1 != pdPASS) { ESP_LOGE(TAG, "Impossiblke de creer la tache imageDownload_task %i", ret1); } BaseType_t ret2 = xTaskCreate(&updateTime, "updateTimeTask", 3 * 1024, NULL, 5, NULL); if (ret2 != pdPASS) { ESP_LOGE(TAG, "Impossiblke de creer la tache updateTimeTask %i", ret2); } printf("12. Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize()); // Show LVGL objects if(display_lock("draw_ihm")){ draw_ihm(); display_unlock("draw_ihm"); }else{ ESP_LOGE(TAG,"Impossible d'obtenir le mutex pour draw_ihm"); } mqtt_app_start(); // Configuration de la sonde Temp/Humid. am2302_config_t am2302_config = { .gpio_num = AM2302_GPIO, }; am2302_rmt_config_t rmt_config = { .clk_src = RMT_CLK_SRC_DEFAULT, }; ESP_ERROR_CHECK(am2302_new_sensor_rmt(&am2302_config, &rmt_config, &sensor)); xTaskCreate(&readTempHumid, "read_temp_task", 8192, NULL, 5, NULL); //xTaskCreate(&simple_ota_example_task, "ota_example_task", 8192, NULL, 5, NULL); }