diff --git a/components/Communication/CMakeLists.txt b/components/Communication/CMakeLists.txt index bf67a25..99651be 100644 --- a/components/Communication/CMakeLists.txt +++ b/components/Communication/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register(SRCS MqttClient.h MqttClient.cpp INCLUDE_DIRS . - REQUIRES mqtt + REQUIRES mqtt json LedController ) diff --git a/components/Communication/MqttClient.cpp b/components/Communication/MqttClient.cpp index 7df1496..cfe5074 100644 --- a/components/Communication/MqttClient.cpp +++ b/components/Communication/MqttClient.cpp @@ -1,35 +1,69 @@ #include "MqttClient.h" +#include "LedController.h" +#include #include #include -#include +#include static const char *TAG = "mqtt"; +void MqttClient::onConnected(struct esp_mqtt_client *client) { + ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); + + cJSON *root = cJSON_CreateObject(); + cJSON_AddStringToObject(root, "~", "homeassistant/light/bedroom"); + cJSON_AddStringToObject(root, "name", "Bedroom"); + cJSON_AddStringToObject(root, "uniq_id", "bedroom_light"); + cJSON_AddStringToObject(root, "cmd_t", "~/set"); + cJSON_AddStringToObject(root, "stat_t", "~/state"); + cJSON_AddStringToObject(root, "schema", "json"); + cJSON_AddNumberToObject(root, "brightness_scale", 100); + + const char *modes[] = { + "color_temp", + }; + cJSON *supported_color_modes = cJSON_CreateStringArray(modes, sizeof(modes) / sizeof(modes[0])); + cJSON_AddItemToObject(root, "supported_color_modes", supported_color_modes); + + cJSON_AddTrueToObject(root, "brightness"); + auto json = cJSON_PrintUnformatted(root); + int msg_id = esp_mqtt_client_publish(client, "homeassistant/light/bedroom/config", json, strlen(json), 1, 0); + cJSON_free(json); + cJSON_Delete(root); + ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); + + m_setStatusTopic = "homeassistant/light/bedroom/set"; + msg_id = esp_mqtt_client_subscribe(client, m_setStatusTopic.c_str(), 0); + ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); +} + +void MqttClient::onSetStatus(const char *data, int size) { + ESP_LOGI(TAG, "set: %s", data); + cJSON *root = cJSON_Parse(data); + cJSON *brightness = cJSON_GetObjectItem(root, "brightness"); + if (brightness != nullptr) { + ESP_LOGI(TAG, "brightness: %d", brightness->valueint); + LedController::instance()->setDuty(1, brightness->valueint); + } + + cJSON_Delete(root); +} + static void log_error_if_nonzero(const char *message, int error_code) { if (error_code != 0) { ESP_LOGE(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) { +void MqttClient::eventHandler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { + auto self = reinterpret_cast(handler_args); ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id); auto event = reinterpret_cast(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(TAG, "MQTT_EVENT_CONNECTED"); - msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); - ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); + self->onConnected(client); break; case MQTT_EVENT_DISCONNECTED: ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); @@ -47,9 +81,13 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_ ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); break; case MQTT_EVENT_DATA: - ESP_LOGI(TAG, "MQTT_EVENT_DATA"); - printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); - printf("DATA=%.*s\r\n", event->data_len, event->data); + ESP_LOGI(TAG, "MQTT_EVENT_DATA %s", self->m_setStatusTopic.c_str()); + if (self->m_setStatusTopic == std::string_view(event->topic, event->topic_len)) { + self->onSetStatus(event->data, event->data_len); + } 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(TAG, "MQTT_EVENT_ERROR"); @@ -74,8 +112,8 @@ bool MqttClient::initialize(const std::string &username, const std::string &pass config.credentials.authentication.password = password.c_str(); esp_mqtt_client_handle_t client = esp_mqtt_client_init(&config); - esp_mqtt_client_register_event(client, static_cast(ESP_EVENT_ANY_ID), mqtt_event_handler, - NULL); + esp_mqtt_client_register_event(client, static_cast(ESP_EVENT_ANY_ID), + &MqttClient::eventHandler, this); esp_mqtt_client_start(client); ESP_LOGI(TAG, "connect to %s, username: %s, password: %s", config.broker.address.uri, config.credentials.username, config.credentials.authentication.password); diff --git a/components/Communication/MqttClient.h b/components/Communication/MqttClient.h index 5da1b52..3640bb0 100644 --- a/components/Communication/MqttClient.h +++ b/components/Communication/MqttClient.h @@ -1,14 +1,21 @@ #ifndef __MQTTCLIENT_H__ #define __MQTTCLIENT_H__ +#include #include class MqttClient { public: static MqttClient *instance(); - bool initialize(const std::string &username,const std::string &password); + bool initialize(const std::string &username, const std::string &password); protected: + static void eventHandler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data); + void onConnected(struct esp_mqtt_client *client); + void onSetStatus(const char *data, int size); MqttClient() = default; + +private: + std::string m_setStatusTopic; }; #endif // __MQTTCLIENT_H__ \ No newline at end of file