ESP32 Native version of Blinky, featureful controller code for WS2811/WS2812/NeoPixels
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
2.3KB

  1. static const char *TAG = "device";
  2. #include <esp_log.h>
  3. #include "device.hpp"
  4. Device::Device(std::string _id) :
  5. id(_id),
  6. state_topic("light/" + id + "/state"),
  7. cmd_topic("light/" + id + "/cmd"),
  8. ready(false), should_publish(false),
  9. mutex(xSemaphoreCreateMutex()),
  10. sem(xSemaphoreCreateBinary()),
  11. power_on(true),
  12. client(start_mqtt_client(on_mqtt_connect, on_mqtt_message, this))
  13. {}
  14. void Device::set_mqtt_config(cJSON*) {
  15. xSemaphoreTake(mutex, portMAX_DELAY);
  16. // TODO: update power_on and effect from JSON
  17. publish_state_locked();
  18. xSemaphoreGive(mutex);
  19. }
  20. void Device::on_mqtt_connect(esp_mqtt_client_handle_t client) {
  21. xSemaphoreTake(mutex, portMAX_DELAY);
  22. ESP_LOGI(TAG, "Connected to MQTT");
  23. if (esp_mqtt_client_subscribe(client, cmd_topic.c_str(), 0) < 0) {
  24. ESP_LOGE(TAG, "Failed to subscribe to %s", cmd_topic.c_str());
  25. }
  26. if (0 > esp_mqtt_client_publish(
  27. client,
  28. ("homeassistant/light/" + id + "/config").c_str(),
  29. ("{"
  30. "\"unique_id\": \"" + id + "\", "
  31. "\"device\": {\"name\": \"blinky_" + id + "\"}, "
  32. "\"state_topic\": \"" + state_topic + "\", "
  33. "\"command_topic\": \"" + cmd_topic + "\", "
  34. "\"schema\": \"json\", "
  35. "\"effect\": True, "
  36. "\"effect_list\": [\"dummy\"]"
  37. "}").c_str(), 0,
  38. 0, 0
  39. )) {
  40. ESP_LOGE(TAG, "Failed to publish discovery message");
  41. }
  42. ready = true;
  43. if (should_publish) publish_state_locked();
  44. xSemaphoreGive(mutex);
  45. }
  46. void Device::on_mqtt_message(esp_mqtt_client_handle_t, esp_mqtt_event_handle_t) {
  47. ESP_LOGI(TAG, "Received command via MQTT");
  48. // TODO: extract JSON, call set_mqtt_config
  49. xSemaphoreGive(sem);
  50. }
  51. void Device::publish_state_locked() {
  52. if (!(should_publish = !ready)) {
  53. ESP_ERROR_CHECK(esp_mqtt_client_publish(
  54. client,
  55. state_topic.c_str(),
  56. ("{"
  57. "\"state\": \"" + std::string(power_on ? "ON" : "OFF") + "\", "
  58. "\"effect\": \"" + effect + "\""
  59. "}").c_str(), 0,
  60. 0, 0
  61. ));
  62. }
  63. }