static const char *TAG = "device"; #include #include "device.hpp" Device::Device(std::string _id) : id(_id), state_topic("light/" + id + "/state"), cmd_topic("light/" + id + "/cmd"), ready(false), should_publish(false), mutex(xSemaphoreCreateMutex()), sem(xSemaphoreCreateBinary()), power_on(true), client(start_mqtt_client(on_mqtt_connect, on_mqtt_message, this)) {} void Device::set_mqtt_config(cJSON*) { xSemaphoreTake(mutex, portMAX_DELAY); // TODO: update power_on and effect from JSON publish_state_locked(); xSemaphoreGive(mutex); } void Device::on_mqtt_connect(esp_mqtt_client_handle_t client) { xSemaphoreTake(mutex, portMAX_DELAY); ESP_LOGI(TAG, "Connected to MQTT"); if (esp_mqtt_client_subscribe(client, cmd_topic.c_str(), 0) < 0) { ESP_LOGE(TAG, "Failed to subscribe to %s", cmd_topic.c_str()); } if (0 > esp_mqtt_client_publish( client, ("homeassistant/light/" + id + "/config").c_str(), ("{" "\"unique_id\": \"" + id + "\", " "\"device\": {\"name\": \"blinky_" + id + "\"}, " "\"state_topic\": \"" + state_topic + "\", " "\"command_topic\": \"" + cmd_topic + "\", " "\"schema\": \"json\", " "\"effect\": True, " "\"effect_list\": [\"dummy\"]" "}").c_str(), 0, 0, 0 )) { ESP_LOGE(TAG, "Failed to publish discovery message"); } ready = true; if (should_publish) publish_state_locked(); xSemaphoreGive(mutex); } void Device::on_mqtt_message(esp_mqtt_client_handle_t, esp_mqtt_event_handle_t) { ESP_LOGI(TAG, "Received command via MQTT"); // TODO: extract JSON, call set_mqtt_config xSemaphoreGive(sem); } void Device::publish_state_locked() { if (!(should_publish = !ready)) { ESP_ERROR_CHECK(esp_mqtt_client_publish( client, state_topic.c_str(), ("{" "\"state\": \"" + std::string(power_on ? "ON" : "OFF") + "\", " "\"effect\": \"" + effect + "\"" "}").c_str(), 0, 0, 0 )); } }