#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" // Includes personnels #include "wifi_logger.h" #include "obtain_time.h" #include "image_downloader.h" #include "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; #define WIFI_RDY 0b0001 EventGroupHandle_t domotic_event_group; QueueHandle_t ihm_queue; static void wifiStatus_obs_cb(lv_observer_t * observer, lv_subject_t * subject); lv_subject_t mqttStatus; extern lv_subject_t tempIntSubj; extern lv_subject_t tempExtSubj; extern lv_subject_t hauteurCuveSubj; extern lv_subject_t hauteurCuveEvolSubj; void mqtt_cb(mqtt_evt evt, esp_mqtt_event_handle_t event){ switch (evt) { case MQTT_CONNECTED: if(lvgl_port_lock(50)){ ESP_LOGV(TAG,"Statut mqttStatus 1"); lv_subject_set_int(&mqttStatus,1); lvgl_port_unlock(); } break; case MQTT_DISCONNECTED: if(lvgl_port_lock(50)){ ESP_LOGE(TAG,"Statut mqttStatus 0"); lv_subject_set_int(&mqttStatus,0); lvgl_port_unlock(); } break; case MQTT_DATA_RECEIVED: lv_subject_set_int(&mqttStatus,2); ESP_LOGD(TAG, "\nMQTT_EVENT_DATA"); ESP_LOGD(TAG, "TOPIC=%.*s\n", event->topic_len, event->topic); ESP_LOGD(TAG, "DATA=%.*s\n", event->data_len, event->data); if (strncmp(event->topic, topicTempExt, 27) == 0) { if(lvgl_port_lock(50)){ // on retransforme en float pour ne garder que la partie entiere de la température float temp = strtof(event->data, NULL); char buff[5]; sprintf(buff,"%.1f",temp); lv_subject_copy_string(&tempExtSubj, buff); lvgl_port_unlock(); } } else if (strncmp(event->topic, topicTempInt, 27) == 0) { if(lvgl_port_lock(0)){ // on retransforme en float pour ne garder que la partie entiere de la température float temp = strtof(event->data, NULL); char buff[5]; sprintf(buff,"%.1f",temp); lv_subject_copy_string(&tempIntSubj, buff); lvgl_port_unlock(); } } else if (strncmp(event->topic, topicHauteurCuveEvol, 22) == 0) { /* float datas[4] = {}; splitIt(event->data, event->data_len, datas); ser1->y_points[0] = 130 - (int)datas[0]; ser1->y_points[1] = 130 - (int)datas[1]; ser1->y_points[2] = 130 - (int)datas[2]; ser1->y_points[3] = 130 - (int)datas[3]; lvgl_port_lock(0); lv_chart_refresh(chart); lvgl_port_unlock(); */ // lv_subject_copy_string(&hauteurCuveEvolSubj, event->data); } else if (strncmp(event->topic, topicHauteurCuve, 18) == 0) { if (lvgl_port_lock(50)){ float temp = strtof(event->data, NULL); char buff[5]; sprintf(buff,"%.0f",temp); lv_subject_copy_string(&hauteurCuveSubj, buff); lvgl_port_unlock(); } }else if (strncmp(event->topic, topicTest, 4) == 0){ ESP_LOGD(TAG,"Msg reecu sur test"); }else if (strncmp(event->topic, topicdomoticCommand, 11) == 0){ if(strncmp(event->data,"restart",7)==0){ ESP_LOGI(TAG," Commande 'restart' recue"); esp_restart(); } } else { ESP_LOGE(TAG, "None match :-( %s", event->topic); } if (lvgl_port_lock(50)){ lv_subject_set_int(&mqttStatus,3); lvgl_port_unlock(); } break; default: break; } } void send_event(domo_events evt, void* pDatas){ ESP_LOGE(TAG,"On est dans l'event handler %i", evt); switch(evt){ case EVT_WIFI_CONNECTED: xEventGroupSetBits(domotic_event_group, WIFI_CONNECTED_BIT); ESP_LOGI(TAG, "connected to ap SSID"); xIPStackEvent_t evt = { .eEventType = IHM_EVT_WIFI_STATUS, .pvData = (void *)true }; if(xQueueSendToFront( ihm_queue, ( void * ) &evt, ( TickType_t ) 10 ) != pdPASS){ ESP_LOGE(TAG, "La queue est pleine"); }; break; case EVT_TIME_SETTED: xIPStackEvent_t m = { .eEventType = IHM_EVT_TIME_SETTED, .pvData = pDatas }; xQueueSendToFront(ihm_queue,&m,5); 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){ ESP_LOGE(TAG,"On est dans wifi_cb %i", evt); switch(evt){ case WIFI_CONNECTED: mainState.wifi_init=true; send_event(WIFI_CONNECTED,NULL); break; case WIFI_DISCONNECTED: mainState.wifi_init=true; send_event(WIFI_DISCONNECTED,NULL); break; case WIFI_GOT_IP: mainState.wifi_init=true; send_event(WIFI_CONNECTED,NULL); break; case WIFI_CONNECT_FAIL: break; default: 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"); //} } LV_IMAGE_DECLARE(mqtt_ok); LV_IMAGE_DECLARE(mqtt_ko); static void mqttStatus_obs_cb(lv_observer_t * observer, lv_subject_t * subject) { ESP_LOGV(TAG, "On passe dans le callback de chgt de statut; %li", lv_subject_get_int(subject)); if(lvgl_port_lock(0)){ lv_obj_t * wifiSt = lv_obj_get_child(lv_obj_get_child(lv_layer_top(), 0),3); if(lv_obj_check_type(wifiSt, &lv_image_class)){ switch (lv_subject_get_int(subject)) { case 0: lv_image_set_src(wifiSt,&mqtt_ko); break; case 1: lv_image_set_src(wifiSt,&mqtt_ok); break; case 2: lv_color_t color = lv_color_make(255, 0, 0); lv_obj_set_style_image_recolor_opa(wifiSt, 125, 0); lv_obj_set_style_image_recolor(wifiSt, color, 0); vTaskDelay(2000 / portTICK_PERIOD_MS); break; case 3: lv_obj_set_style_image_recolor_opa(wifiSt, 0, 0); break; default: break; } }else{ ESP_LOGE(TAG, "L'objet recuip en semble pas etre du bon type"); } lvgl_port_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 app_main(void) { domotic_event_group = xEventGroupCreate(); ihm_queue = xQueueCreate(10,sizeof(xIPStackEvent_t)); esp_log_level_set("wifi", ESP_LOG_ERROR); esp_log_level_set(TAG, ESP_LOG_VERBOSE); //mount_sd_card(); bsp_sdcard_mount(); 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)); xTaskCreatePinnedToCore(&drawIhm,"ihm_task",10000,ihm_queue,10,NULL,0); // 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); ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); wifi_init_sta(wifi_cb); on_weather_data_retrieval(weather_data_retreived); on_weather_data_retrieval_start(weather_data_retreived_start); ESP_LOGW(TAG, "Weather data retrieval initialized"); initialise_weather_data_retrieval(600000, domotic_event_group); TaskHandle_t xHandle = NULL; BaseType_t ret1; ret1 = xTaskCreate(&imgdwn, "imageDownload_task", 3 * 1024, domotic_event_group, 5, &xHandle); if (ret1 != pdPASS) { ESP_LOGE(TAG, "Impossiblke de creer la tache imageDownload_task %i", ret1); } /* Tache updateTime */ 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); } /* Tache updateTime - FIN*/ mqtt_app_start(mqtt_cb, domotic_event_group); 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 } lv_subject_init_int(&mqttStatus,-1); lv_subject_add_observer_obj(&mqttStatus, mqttStatus_obs_cb, NULL, NULL); // 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); }