diff --git a/.vscode/settings.json b/.vscode/settings.json index 16dbf64..8e0afaf 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -21,6 +21,7 @@ "*.wxs": "javascript", "*.inc": "c", "*.tcc": "c", - "*.ipp": "c" + "*.ipp": "c", + "cstring": "cpp" } } diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index d717f27..11efc7b 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS "main.c" "wifi.c" "light.c" +idf_component_register(SRCS "mqtt.c" "main.c" "wifi.c" "light.c" "mqtt.c" INCLUDE_DIRS ".") \ No newline at end of file diff --git a/main/light.c b/main/light.c index 431da5c..f6e5b3b 100644 --- a/main/light.c +++ b/main/light.c @@ -24,6 +24,9 @@ typedef enum light_mode_e { light_mode_init = 0, light_mode_connection_wifi = 1, light_mode_idle = 2, + light_mode_mqtt_connected = 3, + light_mode_desktop_online = 4, + light_mode_desktop_sending_colors = 5, } light_mode_t; led_strip_t *light_led_strip; @@ -82,6 +85,43 @@ void led_strip_hsv2rgb(uint32_t h, uint32_t s, uint32_t v, uint32_t *r, } } +void update_desktop_connection_state() { + static uint8_t tick = 0; + + uint8_t mask = tick / 10 % 2 ? 0xff : 0x00; + + switch (light_mode) { + case light_mode_desktop_online: + ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 0, mask & 150, + mask & 50, mask & 0)); + ESP_ERROR_CHECK( + light_led_strip->set_pixel(light_led_strip, 1, 30, 100, 0)); + ESP_ERROR_CHECK( + light_led_strip->set_pixel(light_led_strip, 2, 30, 100, 0)); + break; + case light_mode_mqtt_connected: + ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 0, mask & 100, + mask & 30, mask & 0)); + ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 1, mask & 100, + mask & 30, mask & 0)); + ESP_ERROR_CHECK( + light_led_strip->set_pixel(light_led_strip, 2, 50, 150, 0)); + break; + case light_mode_idle: + ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 0, mask & 100, + mask & 30, mask & 0)); + ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 1, mask & 100, + mask & 30, mask & 0)); + ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 2, mask & 100, + mask & 30, mask & 0)); + break; + default: + break; + } + + tick++; +} + void light_for_init() { ESP_LOGI(LIGHT_TAG, "light_for_init"); ESP_ERROR_CHECK(light_led_strip->clear(light_led_strip, 100)); @@ -113,7 +153,6 @@ void light_for_connecting_wifi() { ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, (tick_tock + 1) % 2, 0, 200, 0)); ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100)); - ESP_LOGI(LIGHT_TAG, "tick_tock %d", tick_tock); tick_tock = !tick_tock; vTaskDelay(pdMS_TO_TICKS(200)); } while (light_mode == light_mode_connection_wifi); @@ -126,7 +165,9 @@ void light_for_idle() { uint32_t red = 0, green = 0, blue = 0; uint16_t step_length = 360 / STRIP_LED_NUMBER; - for (uint16_t offset = 0; light_mode == light_mode_idle; + for (uint16_t offset = 0; light_mode == light_mode_idle || + light_mode == light_mode_mqtt_connected || + light_mode == light_mode_desktop_online; offset = (offset + 1) % 360) { for (uint16_t j = 0, hue = offset; j < STRIP_LED_NUMBER; j++, hue += step_length) { @@ -136,6 +177,7 @@ void light_for_idle() { ESP_ERROR_CHECK( light_led_strip->set_pixel(light_led_strip, j, red, green, blue)); } + update_desktop_connection_state(); ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100)); vTaskDelay(pdMS_TO_TICKS(10)); } @@ -147,7 +189,7 @@ void light_strip_running_task(void *pv_parameters) { ESP_LOGE(LIGHT_TAG, "install WS2812 driver failed 2"); } // Show simple rainbow chasing pattern - ESP_LOGI(LIGHT_TAG, "light_strip_running_task"); + ESP_LOGI(LIGHT_TAG, "light_strip_running_task: %d", light_mode); switch (light_mode) { case light_mode_init: light_for_init(); @@ -156,9 +198,12 @@ void light_strip_running_task(void *pv_parameters) { light_for_connecting_wifi(); break; case light_mode_idle: + case light_mode_mqtt_connected: + case light_mode_desktop_online: light_for_idle(); break; default: + vTaskDelay(pdMS_TO_TICKS(100)); break; } } @@ -191,4 +236,7 @@ void light_init_strip() { 1, NULL); } -void light_play(light_mode_t mode) { light_mode = mode; } \ No newline at end of file +void light_play(light_mode_t mode) { + ESP_LOGI(LIGHT_TAG, "light_play: %d", mode); + light_mode = mode; +} \ No newline at end of file diff --git a/main/main.c b/main/main.c index 59e77cb..6a9a768 100644 --- a/main/main.c +++ b/main/main.c @@ -2,6 +2,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "light.c" +#include "mqtt.c" #include "sdkconfig.h" #include "wifi.c" @@ -14,4 +15,15 @@ void app_main(void) { if (connect_wifi()) { light_play(light_mode_idle); } + vTaskDelay(pdMS_TO_TICKS(1000)); + mqtt_app_start(); + if (waiting_for_mqtt_connected()) { + light_play(light_mode_mqtt_connected); + } + if (waiting_for_desktop_online()) { + light_play(light_mode_desktop_online); + } + if (waiting_for_desktop_sending_colors()) { + light_play(light_mode_desktop_sending_colors); + } } diff --git a/main/mqtt.c b/main/mqtt.c new file mode 100644 index 0000000..b94e2ed --- /dev/null +++ b/main/mqtt.c @@ -0,0 +1,159 @@ +#include +#include + +#include "esp_bit_defs.h" +#include "esp_event.h" +#include "esp_log.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "freertos/task.h" +#include "mqtt_client.h" + +#define MQTT_FAILED_BIT BIT0 +#define MQTT_CONNECTED_BIT BIT1 +#define MQTT_DISCONNECTED_BIT BIT2 +#define MQTT_DESKTOP_ONLINE_BIT BIT3 +#define MQTT_DESKTOP_OFFLINE_BIT BIT4 +#define MQTT_DESKTOP_SENDING_BIT BIT5 + +#define MQTT_BOARD_KEY_PREFIX "screen-bg-light/board/" +#define MQTT_DESKTOP_KEY_PREFIX "screen-bg-light/desktop/" +#define MQTT_ONLINE_SUFFIX "online" +#define MQTT_COLORS_SUFFIX "colors" +#define MQTT_ALL_SUFFIX "#" + +#define MQTT_KEY_BOARD_ONLINE MQTT_BOARD_KEY_PREFIX MQTT_ONLINE_SUFFIX +#define MQTT_KEY_DESKTOP_ONLINE MQTT_DESKTOP_KEY_PREFIX MQTT_ONLINE_SUFFIX +#define MQTT_KEY_DESKTOP_COLORS MQTT_DESKTOP_KEY_PREFIX MQTT_COLORS_SUFFIX +#define MQTT_KEY_DESKTOP_ALL MQTT_DESKTOP_KEY_PREFIX MQTT_ALL_SUFFIX + +static const char *MQTT_TAG = "ScreenBgLight_MQTT"; + +static EventGroupHandle_t s_mqtt_event_group; + +static void log_error_if_nonzero(const char *message, int error_code) { + if (error_code != 0) { + ESP_LOGE(MQTT_TAG, "Last error %s: 0x%x", message, error_code); + } +} + +static void mqtt_event_handler(void *handler_args, esp_event_base_t base, + int32_t event_id, void *event_data) { + ESP_LOGD(MQTT_TAG, "Event dispatched from event loop base=%s, event_id=%d", + base, event_id); + esp_mqtt_event_handle_t event = event_data; + esp_mqtt_client_handle_t client = event->client; + int msg_id; + switch ((esp_mqtt_event_id_t)event_id) { + case MQTT_EVENT_CONNECTED: + ESP_LOGI(MQTT_TAG, "MQTT_EVENT_CONNECTED"); + xEventGroupSetBits(s_mqtt_event_group, MQTT_CONNECTED_BIT); + msg_id = esp_mqtt_client_publish(client, MQTT_KEY_BOARD_ONLINE, "ONLINE", + 0, 1, 0); + ESP_LOGI(MQTT_TAG, "sent publish successful, msg_id=%d", msg_id); + esp_mqtt_client_subscribe(client, MQTT_KEY_DESKTOP_ALL, 0); + break; + case MQTT_EVENT_DISCONNECTED: + ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DISCONNECTED"); + xEventGroupSetBits(s_mqtt_event_group, MQTT_DISCONNECTED_BIT); + break; + + case MQTT_EVENT_SUBSCRIBED: + ESP_LOGI(MQTT_TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_UNSUBSCRIBED: + ESP_LOGI(MQTT_TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_PUBLISHED: + ESP_LOGI(MQTT_TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_DATA: + ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DATA"); + if (strcmp(event->topic, MQTT_KEY_BOARD_ONLINE)) { + xEventGroupSetBits(s_mqtt_event_group, MQTT_DESKTOP_ONLINE_BIT); + ESP_LOGE(MQTT_TAG, "AAA MQTT_DESKTOP_ONLINE_BIT"); + } else if (strcmp(event->topic, MQTT_KEY_DESKTOP_COLORS)) { + ESP_LOGE(MQTT_TAG, "AAA MQTT_DESKTOP_SENDING_BIT"); + xEventGroupSetBits(s_mqtt_event_group, MQTT_DESKTOP_SENDING_BIT); + } + printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); + printf("DATA=%.*s\r\n", event->data_len, event->data); + break; + case MQTT_EVENT_ERROR: + ESP_LOGI(MQTT_TAG, "MQTT_EVENT_ERROR"); + xEventGroupSetBits(s_mqtt_event_group, MQTT_FAILED_BIT); + if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) { + log_error_if_nonzero("reported from esp-tls", + event->error_handle->esp_tls_last_esp_err); + log_error_if_nonzero("reported from tls stack", + event->error_handle->esp_tls_stack_err); + log_error_if_nonzero("captured as transport's socket errno", + event->error_handle->esp_transport_sock_errno); + ESP_LOGI(MQTT_TAG, "Last errno string (%s)", + strerror(event->error_handle->esp_transport_sock_errno)); + } + break; + default: + ESP_LOGI(MQTT_TAG, "Other event id:%d", event->event_id); + break; + } +} + +static void mqtt_app_start() { + s_mqtt_event_group = xEventGroupCreate(); + + const esp_mqtt_client_config_t mqtt_cfg = { + .uri = "mqtt://192.168.31.11", + }; + esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); + esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, + client); + esp_mqtt_client_start(client); +} + +static bool waiting_for_mqtt_connected() { + EventBits_t bits = xEventGroupWaitBits(s_mqtt_event_group, + MQTT_CONNECTED_BIT | MQTT_FAILED_BIT, + pdFALSE, pdFALSE, portMAX_DELAY); + + if (bits & MQTT_CONNECTED_BIT) { + return 1; + } else if (bits & MQTT_FAILED_BIT) { + ESP_LOGE(MQTT_TAG, "BBB Failed to connect to MQTT."); + return 0; + } else { + ESP_LOGE(MQTT_TAG, "UNEXPECTED EVENT"); + return 0; + } +} +static bool waiting_for_desktop_online() { + EventBits_t bits = xEventGroupWaitBits( + s_mqtt_event_group, MQTT_DESKTOP_ONLINE_BIT | MQTT_DESKTOP_SENDING_BIT, + pdFALSE, pdFALSE, portMAX_DELAY); + + if (bits & MQTT_DESKTOP_ONLINE_BIT) { + return 1; + } else if (bits & MQTT_DESKTOP_SENDING_BIT) { + return 1; + } else { + ESP_LOGE(MQTT_TAG, "UNEXPECTED EVENT"); + return 0; + } +} +static bool waiting_for_desktop_sending_colors() { + EventBits_t bits = + xEventGroupWaitBits(s_mqtt_event_group, MQTT_DESKTOP_SENDING_BIT, pdFALSE, + pdFALSE, portMAX_DELAY); + + ESP_LOGE(MQTT_TAG, "MQTT_DESKTOP_SENDING_BIT"); + + if (bits & MQTT_DESKTOP_SENDING_BIT) { + return 1; + } else { + ESP_LOGE(MQTT_TAG, "UNEXPECTED EVENT"); + return 0; + } +} \ No newline at end of file