2 Commits

Author SHA1 Message Date
7a34b9c25a Version 1.0.3
Changed WiFi protocol.
Added offline message.
Changed task management.
Updated some components.
2024-07-25 11:04:12 +03:00
c8007ade5d Update README.md 2024-07-05 13:48:41 +03:00
8 changed files with 84 additions and 25 deletions

View File

@ -20,7 +20,7 @@ ESP-NOW based led controller/light for ESP32 ESP-IDF and ESP8266 RTOS SDK. Alter
2. ESP-NOW mesh network based on the [zh_network](https://github.com/aZholtikov/zh_network). 2. ESP-NOW mesh network based on the [zh_network](https://github.com/aZholtikov/zh_network).
3. For initial settings use "menuconfig -> ZH ESP-NOW Led Configuration". After first boot all settings will be stored in NVS memory for prevente change during OTA firmware update. 3. For initial settings use "menuconfig -> ZH ESP-NOW Led Configuration". After first boot all settings will be stored in NVS memory for prevente change during OTA firmware update.
4. To restart the led, send the "restart" command to the root topic of the led (example - "homeassistant/espnow_led/24-62-AB-F9-1F-A8"). 4. To restart the led, send the "restart" command to the root topic of the led (example - "homeassistant/espnow_led/24-62-AB-F9-1F-A8").
5. To update the led firmware, send the "update" command to the root topic of the led (example - "homeassistant/espnow_led/70-03-9F-44-BE-F7"). The update path should be like as "https://your_server/zh_espnow_led_esp32.bin" (for ESP32) or "https://your_server/zh_espnow_led_esp8266.app1.bin + https://your_server/zh_espnow_led_esp8266.app2.bin" (for ESP8266). The time and success of the update depends on the load on WiFi channel 1. Average update time is up to five minutes. The online status of the update will be displayed in the root led topic. 5. To update the led firmware, send the "update" command to the root topic of the led (example - "homeassistant/espnow_led/70-03-9F-44-BE-F7"). The update path should be like as "https://your_server/zh_espnow_led_esp32.bin" (for ESP32) or "https://your_server/zh_espnow_led_esp8266.app1.bin + https://your_server/zh_espnow_led_esp8266.app2.bin" (for ESP8266). Average update time is up to some minutes. The online status of the update will be displayed in the root led topic.
6. To change initial settings of the led (except work mode), send the X1,X2,X3,X4,X5,X6 command to the hardware topic of the led (example - "homeassistant/espnow_led/70-03-9F-44-BE-F7/hardware"). The configuration will only be accepted if it does not cause errors. The current configuration status is displayed in the configuration topic of the led (example - "homeassistant/espnow_led/70-03-9F-44-BE-F7/config"). 6. To change initial settings of the led (except work mode), send the X1,X2,X3,X4,X5,X6 command to the hardware topic of the led (example - "homeassistant/espnow_led/70-03-9F-44-BE-F7/hardware"). The configuration will only be accepted if it does not cause errors. The current configuration status is displayed in the configuration topic of the led (example - "homeassistant/espnow_led/70-03-9F-44-BE-F7/config").
MQTT configuration message should filled according to the template "X1,X2,X3,X4,X5,X6". Where: MQTT configuration message should filled according to the template "X1,X2,X3,X4,X5,X6". Where:

View File

@ -15,7 +15,11 @@ void app_main(void)
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT(); wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&wifi_init_config); esp_wifi_init(&wifi_init_config);
esp_wifi_set_mode(WIFI_MODE_STA); esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B); #ifdef CONFIG_IDF_TARGET_ESP8266
esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N);
#else
esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR);
#endif
esp_wifi_start(); esp_wifi_start();
#ifdef CONFIG_NETWORK_TYPE_DIRECT #ifdef CONFIG_NETWORK_TYPE_DIRECT
zh_espnow_init_config_t espnow_init_config = ZH_ESPNOW_INIT_CONFIG_DEFAULT(); zh_espnow_init_config_t espnow_init_config = ZH_ESPNOW_INIT_CONFIG_DEFAULT();
@ -48,6 +52,7 @@ void zh_load_config(led_config_t *led_config)
{ {
nvs_set_u8(nvs_handle, "present", 0xFE); nvs_set_u8(nvs_handle, "present", 0xFE);
nvs_close(nvs_handle); nvs_close(nvs_handle);
SETUP_INITIAL_SETTINGS:
#ifdef CONFIG_LED_TYPE_W #ifdef CONFIG_LED_TYPE_W
led_config->hardware_config.led_type = HALT_W; led_config->hardware_config.led_type = HALT_W;
#elif CONFIG_LED_TYPE_WW #elif CONFIG_LED_TYPE_WW
@ -89,13 +94,18 @@ void zh_load_config(led_config_t *led_config)
zh_save_config(led_config); zh_save_config(led_config);
return; return;
} }
nvs_get_u8(nvs_handle, "led_type", (uint8_t *)&led_config->hardware_config.led_type); esp_err_t err = ESP_OK;
nvs_get_u8(nvs_handle, "frs_white_pin", &led_config->hardware_config.first_white_pin); err += nvs_get_u8(nvs_handle, "led_type", (uint8_t *)&led_config->hardware_config.led_type);
nvs_get_u8(nvs_handle, "sec_white_pin", &led_config->hardware_config.second_white_pin); err += nvs_get_u8(nvs_handle, "frs_white_pin", &led_config->hardware_config.first_white_pin);
nvs_get_u8(nvs_handle, "red_pin", &led_config->hardware_config.red_pin); err += nvs_get_u8(nvs_handle, "sec_white_pin", &led_config->hardware_config.second_white_pin);
nvs_get_u8(nvs_handle, "green_pin", &led_config->hardware_config.green_pin); err += nvs_get_u8(nvs_handle, "red_pin", &led_config->hardware_config.red_pin);
nvs_get_u8(nvs_handle, "blue_pin", &led_config->hardware_config.blue_pin); err += nvs_get_u8(nvs_handle, "green_pin", &led_config->hardware_config.green_pin);
err += nvs_get_u8(nvs_handle, "blue_pin", &led_config->hardware_config.blue_pin);
nvs_close(nvs_handle); nvs_close(nvs_handle);
if (err != ESP_OK)
{
goto SETUP_INITIAL_SETTINGS;
}
} }
void zh_save_config(const led_config_t *led_config) void zh_save_config(const led_config_t *led_config)
@ -127,9 +137,7 @@ void zh_load_status(led_config_t *led_config)
} }
nvs_get_u8(nvs_handle, "led_state", (uint8_t *)&led_config->status.status); nvs_get_u8(nvs_handle, "led_state", (uint8_t *)&led_config->status.status);
nvs_get_u8(nvs_handle, "bright_state", &led_config->status.brightness); nvs_get_u8(nvs_handle, "bright_state", &led_config->status.brightness);
uint16_t temperature = 0; nvs_get_u16(nvs_handle, "temp_state", &led_config->status.temperature);
nvs_get_u16(nvs_handle, "temp_state", &temperature); // Just to prevent a compiler warning.
led_config->status.temperature = temperature;
nvs_get_u8(nvs_handle, "red_state", &led_config->status.red); nvs_get_u8(nvs_handle, "red_state", &led_config->status.red);
nvs_get_u8(nvs_handle, "green_state", &led_config->status.green); nvs_get_u8(nvs_handle, "green_state", &led_config->status.green);
nvs_get_u8(nvs_handle, "blue_state", &led_config->status.blue); nvs_get_u8(nvs_handle, "blue_state", &led_config->status.blue);
@ -526,8 +534,17 @@ void zh_espnow_event_handler(void *arg, esp_event_base_t event_base, int32_t eve
{ {
zh_send_led_config_message(led_config); zh_send_led_config_message(led_config);
zh_send_led_status_message(led_config); zh_send_led_status_message(led_config);
if (led_config->is_first_connection == false)
{
xTaskCreatePinnedToCore(&zh_send_led_attributes_message_task, "NULL", ZH_MESSAGE_STACK_SIZE, led_config, ZH_MESSAGE_TASK_PRIORITY, (TaskHandle_t *)&led_config->attributes_message_task, tskNO_AFFINITY); xTaskCreatePinnedToCore(&zh_send_led_attributes_message_task, "NULL", ZH_MESSAGE_STACK_SIZE, led_config, ZH_MESSAGE_TASK_PRIORITY, (TaskHandle_t *)&led_config->attributes_message_task, tskNO_AFFINITY);
xTaskCreatePinnedToCore(&zh_send_led_keep_alive_message_task, "NULL", ZH_MESSAGE_STACK_SIZE, led_config, ZH_MESSAGE_TASK_PRIORITY, (TaskHandle_t *)&led_config->keep_alive_message_task, tskNO_AFFINITY); xTaskCreatePinnedToCore(&zh_send_led_keep_alive_message_task, "NULL", ZH_MESSAGE_STACK_SIZE, led_config, ZH_MESSAGE_TASK_PRIORITY, (TaskHandle_t *)&led_config->keep_alive_message_task, tskNO_AFFINITY);
led_config->is_first_connection = true;
}
else
{
vTaskResume(led_config->attributes_message_task);
vTaskResume(led_config->keep_alive_message_task);
}
} }
} }
} }
@ -538,8 +555,8 @@ void zh_espnow_event_handler(void *arg, esp_event_base_t event_base, int32_t eve
led_config->gateway_is_available = false; led_config->gateway_is_available = false;
if (led_config->hardware_config.led_type != HALT_NONE) if (led_config->hardware_config.led_type != HALT_NONE)
{ {
vTaskDelete(led_config->attributes_message_task); vTaskSuspend(led_config->attributes_message_task);
vTaskDelete(led_config->keep_alive_message_task); vTaskSuspend(led_config->keep_alive_message_task);
} }
} }
} }
@ -578,9 +595,30 @@ void zh_espnow_event_handler(void *arg, esp_event_base_t event_base, int32_t eve
led_config->hardware_config.green_pin = data->payload_data.config_message.led_hardware_config_message.green_pin; led_config->hardware_config.green_pin = data->payload_data.config_message.led_hardware_config_message.green_pin;
led_config->hardware_config.blue_pin = data->payload_data.config_message.led_hardware_config_message.blue_pin; led_config->hardware_config.blue_pin = data->payload_data.config_message.led_hardware_config_message.blue_pin;
zh_save_config(led_config); zh_save_config(led_config);
if (led_config->hardware_config.led_type != HALT_NONE)
{
vTaskDelete(led_config->attributes_message_task);
vTaskDelete(led_config->keep_alive_message_task);
}
data->device_type = ZHDT_LED;
data->payload_type = ZHPT_KEEP_ALIVE;
data->payload_data.keep_alive_message.online_status = ZH_OFFLINE;
data->payload_data.keep_alive_message.message_frequency = ZH_LED_KEEP_ALIVE_MESSAGE_FREQUENCY;
zh_send_message(led_config->gateway_mac, (uint8_t *)data, sizeof(zh_espnow_data_t));
vTaskDelay(1000 / portTICK_PERIOD_MS);
esp_restart(); esp_restart();
break; break;
case ZHPT_UPDATE:; case ZHPT_UPDATE:;
if (led_config->hardware_config.led_type != HALT_NONE)
{
vTaskSuspend(led_config->attributes_message_task);
vTaskSuspend(led_config->keep_alive_message_task);
}
data->device_type = ZHDT_LED;
data->payload_type = ZHPT_KEEP_ALIVE;
data->payload_data.keep_alive_message.online_status = ZH_OFFLINE;
data->payload_data.keep_alive_message.message_frequency = ZH_LED_KEEP_ALIVE_MESSAGE_FREQUENCY;
zh_send_message(led_config->gateway_mac, (uint8_t *)data, sizeof(zh_espnow_data_t));
const esp_app_desc_t *app_info = get_app_description(); const esp_app_desc_t *app_info = get_app_description();
led_config->update_partition = esp_ota_get_next_update_partition(NULL); led_config->update_partition = esp_ota_get_next_update_partition(NULL);
strcpy(data->payload_data.ota_message.espnow_ota_data.app_version, app_info->version); strcpy(data->payload_data.ota_message.espnow_ota_data.app_version, app_info->version);
@ -593,7 +631,6 @@ void zh_espnow_event_handler(void *arg, esp_event_base_t event_base, int32_t eve
#else #else
strcpy(data->payload_data.ota_message.espnow_ota_data.app_name, app_info->project_name); strcpy(data->payload_data.ota_message.espnow_ota_data.app_name, app_info->project_name);
#endif #endif
data->device_type = ZHDT_LED;
data->payload_type = ZHPT_UPDATE; data->payload_type = ZHPT_UPDATE;
zh_send_message(led_config->gateway_mac, (uint8_t *)data, sizeof(zh_espnow_data_t)); zh_send_message(led_config->gateway_mac, (uint8_t *)data, sizeof(zh_espnow_data_t));
break; break;
@ -620,6 +657,11 @@ void zh_espnow_event_handler(void *arg, esp_event_base_t event_base, int32_t eve
break; break;
case ZHPT_UPDATE_ERROR: case ZHPT_UPDATE_ERROR:
esp_ota_end(led_config->update_handle); esp_ota_end(led_config->update_handle);
if (led_config->hardware_config.led_type != HALT_NONE)
{
vTaskResume(led_config->attributes_message_task);
vTaskResume(led_config->keep_alive_message_task);
}
break; break;
case ZHPT_UPDATE_END: case ZHPT_UPDATE_END:
if (esp_ota_end(led_config->update_handle) != ESP_OK) if (esp_ota_end(led_config->update_handle) != ESP_OK)
@ -627,6 +669,11 @@ void zh_espnow_event_handler(void *arg, esp_event_base_t event_base, int32_t eve
data->device_type = ZHDT_LED; data->device_type = ZHDT_LED;
data->payload_type = ZHPT_UPDATE_FAIL; data->payload_type = ZHPT_UPDATE_FAIL;
zh_send_message(led_config->gateway_mac, (uint8_t *)data, sizeof(zh_espnow_data_t)); zh_send_message(led_config->gateway_mac, (uint8_t *)data, sizeof(zh_espnow_data_t));
if (led_config->hardware_config.led_type != HALT_NONE)
{
vTaskResume(led_config->attributes_message_task);
vTaskResume(led_config->keep_alive_message_task);
}
break; break;
} }
esp_ota_set_boot_partition(led_config->update_partition); esp_ota_set_boot_partition(led_config->update_partition);
@ -637,6 +684,17 @@ void zh_espnow_event_handler(void *arg, esp_event_base_t event_base, int32_t eve
esp_restart(); esp_restart();
break; break;
case ZHPT_RESTART: case ZHPT_RESTART:
if (led_config->hardware_config.led_type != HALT_NONE)
{
vTaskDelete(led_config->attributes_message_task);
vTaskDelete(led_config->keep_alive_message_task);
}
data->device_type = ZHDT_LED;
data->payload_type = ZHPT_KEEP_ALIVE;
data->payload_data.keep_alive_message.online_status = ZH_OFFLINE;
data->payload_data.keep_alive_message.message_frequency = ZH_LED_KEEP_ALIVE_MESSAGE_FREQUENCY;
zh_send_message(led_config->gateway_mac, (uint8_t *)data, sizeof(zh_espnow_data_t));
vTaskDelay(1000 / portTICK_PERIOD_MS);
esp_restart(); esp_restart();
break; break;
default: default:
@ -657,8 +715,8 @@ void zh_espnow_event_handler(void *arg, esp_event_base_t event_base, int32_t eve
led_config->gateway_is_available = false; led_config->gateway_is_available = false;
if (led_config->hardware_config.led_type != HALT_NONE) if (led_config->hardware_config.led_type != HALT_NONE)
{ {
vTaskDelete(led_config->attributes_message_task); vTaskSuspend(led_config->attributes_message_task);
vTaskDelete(led_config->keep_alive_message_task); vTaskSuspend(led_config->keep_alive_message_task);
} }
} }
break; break;
@ -673,8 +731,8 @@ void zh_espnow_event_handler(void *arg, esp_event_base_t event_base, int32_t eve
led_config->gateway_is_available = false; led_config->gateway_is_available = false;
if (led_config->hardware_config.led_type != HALT_NONE) if (led_config->hardware_config.led_type != HALT_NONE)
{ {
vTaskDelete(led_config->attributes_message_task); vTaskSuspend(led_config->attributes_message_task);
vTaskDelete(led_config->keep_alive_message_task); vTaskSuspend(led_config->keep_alive_message_task);
} }
} }
break; break;

View File

@ -81,6 +81,7 @@ typedef struct // Structure of data exchange between tasks, functions and event
uint8_t blue; // Blue color channel. uint8_t blue; // Blue color channel.
} channel; } channel;
volatile bool gateway_is_available; // Gateway availability status flag. @note Used to control the tasks when the gateway connection is established / lost. volatile bool gateway_is_available; // Gateway availability status flag. @note Used to control the tasks when the gateway connection is established / lost.
volatile bool is_first_connection; // First connection status flag. @note Used to control the tasks when the gateway connection is established / lost.
uint8_t gateway_mac[6]; // Gateway MAC address. uint8_t gateway_mac[6]; // Gateway MAC address.
TaskHandle_t attributes_message_task; // Unique task handle for zh_send_led_attributes_message_task(). TaskHandle_t attributes_message_task; // Unique task handle for zh_send_led_attributes_message_task().
TaskHandle_t keep_alive_message_task; // Unique task handle for zh_send_led_keep_alive_message_task(). TaskHandle_t keep_alive_message_task; // Unique task handle for zh_send_led_keep_alive_message_task().

View File

@ -1 +1 @@
1.0.2 1.0.3