diff --git a/components/domotic_display/CMakeLists.txt b/components/domotic_display/CMakeLists.txt index c71a176..393a9d5 100644 --- a/components/domotic_display/CMakeLists.txt +++ b/components/domotic_display/CMakeLists.txt @@ -19,7 +19,7 @@ make_font(Super_Malibu super_malibu 80) #execute_process(COMMAND podman run -v /home/marc/rgb_lcd/components/domotic_display/fonts:/app -w /app lvfontconv lv_font_conv --bpp 4 --size 72 --no-compress --font Roboto-Medium.ttf --symbols "0123456789.°àéèûCABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz %,'():ê/-" --format lvgl -o roboto_medium_72.c --font fa-solid-900.ttf --range 61461,0xf0c2,0xf575) -SET(comps meteofrance eventsManager lvgl RemindMe) +SET(comps meteofrance eventsManager lvgl RemindMe washingMachineState) if(${IDF_TARGET} STREQUAL "esp32p4" OR ${IDF_TARGET} STREQUAL "esp32s3") #esp32_p4_function_ev_board idf_component_register(SRC_DIRS . fonts diff --git a/components/domotic_display/ihm_gateway.c b/components/domotic_display/ihm_gateway.c index c8ca3f9..93073d2 100644 --- a/components/domotic_display/ihm_gateway.c +++ b/components/domotic_display/ihm_gateway.c @@ -6,6 +6,7 @@ #include "platform_detect.h" #include "cJSON.h" #include "esp_log.h" +#include "washingMachineState.h" static const char *TAG = "IHM_GW"; @@ -86,22 +87,11 @@ void traiteEvt(void *arg) case IHM_EVT_ETAT_MACHINE: { char *etatMachine = evt->pvData; - cJSON *root = cJSON_Parse(etatMachine); - bool enRoute = cJSON_GetObjectItem(root, "state")->valueint; - int timestamp = cJSON_GetObjectItem(root, "timestamp")->valueint; - - time_t rawtime = (time_t)timestamp; - struct tm *heure_locale = localtime(&rawtime); - char heureFormattee[50]; - strftime(heureFormattee, sizeof(heureFormattee), "%d/%m/%Y %H:%M:%S", heure_locale); - - char etatFormate[90]; - snprintf(etatFormate, sizeof(etatFormate), - enRoute ? "Machine en route depuis %s" : "Machine : Arrêt détecté depuis %s", - heureFormattee); - + WashingMachineState wms = traiteMessage(etatMachine); + char etat[80]; + getEtatMachineStr(wms, etat,80); + ESP_LOGE(TAG,"Etat machine : %s", etat); // lv_label_set_text(lblEtatMachine, etatFormate); - cJSON_Delete(root); break; } diff --git a/components/washingMachineState/CMakeLists.txt b/components/washingMachineState/CMakeLists.txt new file mode 100644 index 0000000..0d888fe --- /dev/null +++ b/components/washingMachineState/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "washingMachineState.c" PRIV_REQUIRES json + INCLUDE_DIRS "include") diff --git a/components/washingMachineState/Readme.md b/components/washingMachineState/Readme.md new file mode 100644 index 0000000..506cce0 --- /dev/null +++ b/components/washingMachineState/Readme.md @@ -0,0 +1,5 @@ +But: +Exposer l'état de la machine à laver +Dans sa plus simple expression c'est un listener MQTT +L'état de la machine est ensuite émise via une interface +Le topic est en retain pour pouvoir garder le dernier état de la machine {etat, timestamp} \ No newline at end of file diff --git a/components/washingMachineState/include/washingMachineState.h b/components/washingMachineState/include/washingMachineState.h new file mode 100644 index 0000000..71ed536 --- /dev/null +++ b/components/washingMachineState/include/washingMachineState.h @@ -0,0 +1,24 @@ + +typedef enum { + LAVEUSE_ARRET, + LAVEUSE_REMPLISSAGE, + LAVEUSE_LAVAGE, + LAVEUSE_RINCAGE, + LAVEUSE_ESSORAGE, + LAVEUSE_TERMINEE, + LAVEUSE_ERREUR +} WMState; + +typedef struct { + WMState etat; // Indique l'état de la machine + double depuis; // timestamp de l'evenement + bool ack; // Evenement acquitté ? +} WashingMachineState; + +WashingMachineState traiteMessage(char *message); + +void timestampToDate(double timestamp, char* dateStr, size_t dateStrSize); + +WashingMachineState getEtatMachine(); +void getEtatMachineStr(WashingMachineState wms, char* etat, size_t etatSize); +void acknoledge(); diff --git a/components/washingMachineState/washingMachineState.c b/components/washingMachineState/washingMachineState.c new file mode 100644 index 0000000..0980177 --- /dev/null +++ b/components/washingMachineState/washingMachineState.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include "washingMachineState.h" +#include + +#define TAG "WMS" + +WashingMachineState wms; + +WashingMachineState traiteMessage(char* message){ + + cJSON *root = cJSON_Parse(message); + char* json = cJSON_PrintUnformatted(root); + ESP_LOGE(TAG, "%s", json); + + bool state = cJSON_IsTrue(cJSON_GetObjectItem(root, "state")); + double timestamp = cJSON_GetNumberValue(cJSON_GetObjectItem(root, "timestamp")); + bool ack = cJSON_HasObjectItem(root,"ack") && cJSON_GetNumberValue(cJSON_GetObjectItem(root,"ack")); + + //char dateStr[80] ; + //timestampToDate(timestamp,dateStr,80); + + wms.etat = state?LAVEUSE_LAVAGE:LAVEUSE_ARRET; + wms.depuis = timestamp; + wms.ack = ack; + + cJSON_Delete(root); + + return wms; +} + +void timestampToDate(double timestamp, char* dateStr, size_t dateStrSize) +{ + time_t ts = timestamp; + struct tm *pTime = localtime(&ts); + + strftime(dateStr, dateStrSize, "%d/%m/%Y %H:%M:%S", pTime); + //printf("Date and french time : %s\n", dateStr); +} + +WashingMachineState getEtatMachine(){ + return wms; +} + +void getEtatMachineStr(WashingMachineState wms, char* etat, size_t etatSize) +{ + char* etatStr; + switch (wms.etat) + { + case LAVEUSE_ARRET: + /* code */ + etatStr="Machine arretée"; + break; + + case LAVEUSE_LAVAGE: + /* code */ + etatStr="Machine en route"; + break; + + default: + etatStr="Etat inconnu"; + break; + } + char dateStr[30]; + timestampToDate(wms.depuis,dateStr,30); + + snprintf(etat,etatSize,"%s depuis %s", etatStr, dateStr); + ESP_LOGE(TAG,"%s",etat); + +} + +void acknoledge(){ + wms.ack=true; +} diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index f492c69..b3ba1a7 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -14,7 +14,7 @@ if(${IDF_TARGET} STREQUAL "esp32p4") elseif(${IDF_TARGET} STREQUAL "linux") message(STATUS "Linux Mode --> main standard") list(APPEND comps vfs esp_http_server) - idf_component_register(SRCS main.c + idf_component_register(SRCS main.c communication.c INCLUDE_DIRS "./include" REQUIRES ${comps} EMBED_TXTFILES ${PROJECT_DIR}/main/ca_cert.pem diff --git a/main/communication.c b/main/communication.c index 0938136..4e90ede 100644 --- a/main/communication.c +++ b/main/communication.c @@ -2,9 +2,147 @@ #include "esp_log.h" #include "mqtt_client.h" #include "stateManagement.h" +#if CONFIG_IDF_TARGET_ESP32P4 #include "esp_wifi.h" +#endif #include "esp_log.h" +/* FreeRTOS event group to signal when we are connected*/ +static EventGroupHandle_t s_wifi_event_group; + +/* The event group allows multiple bits for each event, but we only care about two events: + * - we are connected to the AP with an IP + * - we failed to connect after the maximum amount of retries */ +#define BIT0 0x00000001 + +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 + +#define EXAMPLE_ESP_WIFI_SSID "wifimms3" +#define EXAMPLE_ESP_WIFI_PASS "mmswifi0611" +#define EXAMPLE_ESP_MAXIMUM_RETRY 5 + +#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK + +static int s_retry_num = 0; +wifi_callback cb; + +#if CONFIG_IDF_TARGET_ESP32P4 +#define BIT0 0x00000001 +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) + { + if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) + { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, "retry to connect to the AP"); + } + else + { + //xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); + } + cb(WIFI_DISCONNECTED); + ESP_LOGI(TAG, "connect to the AP fail"); + } + else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) + { + ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; + ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); + s_retry_num = 0; + cb(WIFI_CONNECTED); + //xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); + } +} +void wifi_init_sta(wifi_callback callback) +{ + cb=callback; + //s_wifi_event_group = xEventGroupCreate(); + + ESP_ERROR_CHECK(esp_netif_init()); + + //ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_create_default_wifi_sta(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + esp_event_handler_instance_t instance_any_id; + esp_event_handler_instance_t instance_got_ip; + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &wifi_event_handler, + NULL, + &instance_any_id)); + ESP_ERROR_CHECK(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 = EXAMPLE_ESP_WIFI_SSID, + .password = EXAMPLE_ESP_WIFI_PASS, + /* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8). + * If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value + * to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to + * WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards. + */ + .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD, + .sae_pwe_h2e = ESP_WIFI_SAE_MODE, + .sae_h2e_identifier = "", + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + + /* + // Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum + // number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) + EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, + WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, + pdFALSE, + pdFALSE, + portMAX_DELAY); + + // xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually + // happened. + if (bits & WIFI_CONNECTED_BIT) + { + cb(CONNECTED); + } + else if (bits & WIFI_FAIL_BIT) + { + cb(CONNECT_FAIL); + ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); + } + else + { + ESP_LOGE(TAG, "UNEXPECTED EVENT"); + } + */ +} +#else +#include +int64_t esp_timer_get_time(void) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (int64_t)ts.tv_sec * 1000000LL + ts.tv_nsec / 1000; +} +#endif + esp_mqtt_client_handle_t client; @@ -196,127 +334,3 @@ void mqtt_app_start(mqtt_callback callback, EventGroupHandle_t domotic_event_gro } -/* FreeRTOS event group to signal when we are connected*/ -static EventGroupHandle_t s_wifi_event_group; - -/* The event group allows multiple bits for each event, but we only care about two events: - * - we are connected to the AP with an IP - * - we failed to connect after the maximum amount of retries */ -#define WIFI_CONNECTED_BIT BIT0 -#define WIFI_FAIL_BIT BIT1 - -#define EXAMPLE_ESP_WIFI_SSID "wifimms3" -#define EXAMPLE_ESP_WIFI_PASS "mmswifi0611" -#define EXAMPLE_ESP_MAXIMUM_RETRY 5 - -#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK - -static int s_retry_num = 0; -wifi_callback cb; - - -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) - { - if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) - { - esp_wifi_connect(); - s_retry_num++; - ESP_LOGI(TAG, "retry to connect to the AP"); - } - else - { - //xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); - } - cb(WIFI_DISCONNECTED); - ESP_LOGI(TAG, "connect to the AP fail"); - } - else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) - { - ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; - ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); - s_retry_num = 0; - cb(WIFI_CONNECTED); - //xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); - } -} -void wifi_init_sta(wifi_callback callback) -{ - cb=callback; - //s_wifi_event_group = xEventGroupCreate(); - - ESP_ERROR_CHECK(esp_netif_init()); - - //ESP_ERROR_CHECK(esp_event_loop_create_default()); - esp_netif_create_default_wifi_sta(); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - - esp_event_handler_instance_t instance_any_id; - esp_event_handler_instance_t instance_got_ip; - ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, - ESP_EVENT_ANY_ID, - &wifi_event_handler, - NULL, - &instance_any_id)); - ESP_ERROR_CHECK(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 = EXAMPLE_ESP_WIFI_SSID, - .password = EXAMPLE_ESP_WIFI_PASS, - /* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8). - * If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value - * to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to - * WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards. - */ - .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD, - .sae_pwe_h2e = ESP_WIFI_SAE_MODE, - .sae_h2e_identifier = "", - }, - }; - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_start()); - - ESP_LOGI(TAG, "wifi_init_sta finished."); - - /* - // Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum - // number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) - EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, - WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, - pdFALSE, - pdFALSE, - portMAX_DELAY); - - // xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually - // happened. - if (bits & WIFI_CONNECTED_BIT) - { - cb(CONNECTED); - } - else if (bits & WIFI_FAIL_BIT) - { - cb(CONNECT_FAIL); - ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", - EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); - } - else - { - ESP_LOGE(TAG, "UNEXPECTED EVENT"); - } - */ -} - diff --git a/main/main.c b/main/main.c index 6f91c8c..ecfdfce 100644 --- a/main/main.c +++ b/main/main.c @@ -894,6 +894,8 @@ void app_main(void) //start_wifi_logger(); #endif + mqtt_app_start(mqtt_cb, domotic_event_group); + TaskHandle_t xHandle = NULL; BaseType_t ret1; /*ret1 = xTaskCreate(&imgdwn, "imageDownload_task", 3 * 1024, domotic_event_group, 5, &xHandle);