#include #include #include #include "cJSON.h" #include "ci_03t.c" #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" #include "ui_input.c" #define MQTT_BROKER_URL CONFIG_MQTT_BROKER_URL #define NUMBER_OF_LEDS CONFIG_NUMBER_OF_LEDS #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_COLORS_STAND_BY_BIT BIT6 #define MQTT_BOARD_KEY_PREFIX "display-ambient-light/board/" #define MQTT_DESKTOP_KEY_PREFIX "display-ambient-light/desktop/" #define MQTT_ONLINE_SUFFIX "online" #define MQTT_COLORS_SUFFIX "colors" #define MQTT_CMD_SUFFIX "cmd" #define MQTT_ALL_SUFFIX "#" #define MQTT_KEY_BOARD_ONLINE MQTT_BOARD_KEY_PREFIX MQTT_ONLINE_SUFFIX #define MQTT_KEY_DISPLAY_BRIGHTNESS_INPUT MQTT_BOARD_KEY_PREFIX "brightness" #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 #define MQTT_KEY_DESKTOP_COLOR_CALIBRATION \ MQTT_DESKTOP_KEY_PREFIX "color-calibration" #define MQTT_KEY_BOARD_CMD MQTT_BOARD_KEY_PREFIX MQTT_CMD_SUFFIX #define MQTT_KEY_DESKTOP_DISPLAY_0_BRIGHTNESS \ MQTT_DESKTOP_KEY_PREFIX "display0/brightness" #define MQTT_KEY_DESKTOP_DISPLAY_1_BRIGHTNESS \ MQTT_DESKTOP_KEY_PREFIX "display1/brightness" static const char *MQTT_TAG = "DisplayAmbientLight_MQTT"; static EventGroupHandle_t s_mqtt_event_group; static QueueHandle_t mqtt_cmd_event = NULL; static esp_mqtt_client_handle_t client = NULL; typedef struct colors { uint8_t *buffer; uint8_t number; } s_colors_t; static uint8_t *mqtt_colors_buffer; 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, long event_id, void *event_data) { ESP_LOGD(MQTT_TAG, "Event dispatched from event loop base=%s, event_id=%ld", base, event_id); esp_mqtt_event_handle_t event = event_data; 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, 1); 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 (strncmp(event->topic, MQTT_KEY_DESKTOP_ONLINE, event->topic_len) == 0) { xEventGroupSetBits(s_mqtt_event_group, MQTT_DESKTOP_ONLINE_BIT); } else if (strncmp(event->topic, MQTT_KEY_DESKTOP_COLORS, event->topic_len) == 0) { // printf("LEN=%d, DATA=%.*s\r\n", event->data_len, event->data_len, // event->data); memcpy(mqtt_colors_buffer, event->data, MIN(event->data_len, NUMBER_OF_LEDS * 3)); xEventGroupSetBits(s_mqtt_event_group, MQTT_DESKTOP_SENDING_BIT | MQTT_COLORS_STAND_BY_BIT); } else { if (strncmp(event->topic, MQTT_KEY_DESKTOP_DISPLAY_0_BRIGHTNESS, event->topic_len) == 0) { s_ui_input_t mqtt_event = { .key = ui_input_key_display_0_brightness, .value = (uint16_t)(event->data[0] << 8 | event->data[1]), }; xQueueSend(mqtt_cmd_event, &mqtt_event, NULL); } else if (strncmp(event->topic, MQTT_KEY_DESKTOP_DISPLAY_1_BRIGHTNESS, event->topic_len) == 0) { s_ui_input_t mqtt_event = { .key = ui_input_key_display_1_brightness, .value = (uint16_t)(event->data[0] << 8 | event->data[1]), }; xQueueSend(mqtt_cmd_event, &mqtt_event, NULL); } else if (strncmp(event->topic, MQTT_KEY_DESKTOP_COLOR_CALIBRATION, event->topic_len) == 0) { led_strip_set_color_calibration((float)event->data[0] / 255.0, (float)event->data[1] / 255.0, (float)event->data[2] / 255.0); } else { 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_cmd_event_handler(void *arg) { s_ui_input_t event; for (;;) { if (xQueueReceive(mqtt_cmd_event, &event, portMAX_DELAY)) { ESP_LOGI(MQTT_TAG, "mqtt_cmd_event_handler"); gui_update_config_uint8(ui_input_key_display_0_brightness, (uint8_t)(event.value & 0xFF)); switch (event.key) { case ui_input_key_display_0_brightness: { ESP_LOGI(MQTT_TAG, "ui_input_key_display_0_brightness %x", event.value); uint8_t data[] = {0x02, (uint8_t)(event.value & 0xFF)}; ci_03t_send_data(data, sizeof(data)); break; } case ui_input_key_display_1_brightness: { ESP_LOGI(MQTT_TAG, "ui_input_key_display_0_brightness %x", event.value); uint8_t data[] = {0x03, (uint8_t)(event.value & 0xFF)}; ci_03t_send_data(data, sizeof(data)); break; } default: break; } } } } static void mqtt_app_start() { mqtt_colors_buffer = (uint8_t *)malloc(sizeof(uint8_t) * NUMBER_OF_LEDS * 3); s_mqtt_event_group = xEventGroupCreate(); mqtt_cmd_event = xQueueCreate(10, sizeof(s_ui_input_t)); xTaskCreate(mqtt_cmd_event_handler, "mqtt_cmd_event", 2048, NULL, 10, NULL); const esp_mqtt_client_config_t mqtt_cfg = { .broker.address.uri = MQTT_BROKER_URL, }; 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; } } static bool waiting_and_get_colors() { EventBits_t bits = xEventGroupWaitBits(s_mqtt_event_group, MQTT_COLORS_STAND_BY_BIT, pdFALSE, pdFALSE, portMAX_DELAY); if (bits & MQTT_COLORS_STAND_BY_BIT) { xEventGroupClearBits(s_mqtt_event_group, MQTT_COLORS_STAND_BY_BIT); return 1; } else { ESP_LOGE(MQTT_TAG, "UNEXPECTED EVENT"); return 0; } } static void mqtt_publish_ui_input(void *arg) { s_ui_input_t input; for (;;) { if (xQueueReceive(ui_input_event, &input, portMAX_DELAY)) { switch (input.key) { case ui_input_key_display_0_brightness: case ui_input_key_display_1_brightness: { cJSON *publish_json_root, *brightness; publish_json_root = cJSON_CreateObject(); cJSON_AddNumberToObject( publish_json_root, "display_index", ui_input_key_display_0_brightness == input.key ? 0 : 1); cJSON_AddItemToObject(publish_json_root, "brightness", brightness = cJSON_CreateObject()); cJSON_AddNumberToObject(brightness, "Relative", input.value); char *publish_str = cJSON_Print(publish_json_root); cJSON_Delete(publish_json_root); esp_mqtt_client_publish(client, MQTT_KEY_DISPLAY_BRIGHTNESS_INPUT, publish_str, 0, 1, 0); } break; default: break; } } } }