Browse Source

Add reboot command via MQTT

master
jrhoffa 3 years ago
parent
commit
a772aba012
2 changed files with 44 additions and 17 deletions
  1. +41
    -14
      main/device.cpp
  2. +3
    -3
      main/device.hpp

+ 41
- 14
main/device.cpp View File

@@ -8,9 +8,7 @@ static const char *TAG = "device";

Device::Device(std::string _id) :
id(_id),
state_topic("light/" + id + "/state"),
cmd_topic("light/" + id + "/cmd"),
data_topic("light/" + id + "/data/+"),
topic_prefix("light/" + id),
ready(false), should_publish(false),
mutex(xSemaphoreCreateMutex()),
sem(xSemaphoreCreateBinary()),
@@ -44,11 +42,9 @@ void Device::on_mqtt_connect(esp_mqtt_client_handle_t client) {

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 (esp_mqtt_client_subscribe(client, data_topic.c_str(), 0) < 0) {
ESP_LOGE(TAG, "Failed to subscribe to %s", data_topic.c_str());
std::string topic = topic_prefix + "/#";
if (esp_mqtt_client_subscribe(client, topic.c_str(), 0) < 0) {
ESP_LOGE(TAG, "Failed to subscribe to %s", topic.c_str());
}

// TODO: Re-announce when presets change
@@ -58,8 +54,8 @@ void Device::on_mqtt_connect(esp_mqtt_client_handle_t client) {
cJSON_AddStringToObject(device, "name", id.c_str());
cJSON *identifiers = cJSON_AddArrayToObject(device, "identifiers");
cJSON_AddItemToArray(identifiers, cJSON_CreateString(id.c_str()));
cJSON_AddStringToObject(json, "state_topic", state_topic.c_str());
cJSON_AddStringToObject(json, "command_topic", cmd_topic.c_str());
cJSON_AddStringToObject(json, "state_topic", (topic_prefix + "/state").c_str());
cJSON_AddStringToObject(json, "command_topic", (topic_prefix + "/cmd").c_str());
cJSON_AddStringToObject(json, "schema", "json");
cJSON_AddBoolToObject(json, "effect", true);
cJSON *effects = cJSON_AddArrayToObject(json, "effect_list");
@@ -86,10 +82,29 @@ void Device::on_mqtt_connect(esp_mqtt_client_handle_t client) {
xSemaphoreGive(mutex);
}

std::string Device::subtopic(const std::string &topic) {
auto slash_pos = topic.find('/', topic_prefix.length());
if (slash_pos == std::string::npos) return "";
auto another_slash_pos = topic.find('/', slash_pos + 1);
if (slash_pos == std::string::npos) {
// No further levels
return topic.substr(slash_pos + 1);
}
// First subtopic
return topic.substr(slash_pos + 1, another_slash_pos - (slash_pos + 1));
}

void Device::on_mqtt_message(esp_mqtt_client_handle_t, esp_mqtt_event_handle_t event) {
std::string topic(event->topic, event->topic_len);
ESP_LOGI(TAG, "Received command via MQTT");
if (topic == cmd_topic) {
std::string command = subtopic(topic);

ESP_LOGI(TAG, "Received command via MQTT: %s", command.c_str());

if (command == "state") {
// This is from us, just ignore it
return;

} else if (command == "cmd") {
cJSON *json = cJSON_ParseWithLength(event->data, event->data_len);
if (json) {
set_json_config(json);
@@ -97,8 +112,14 @@ void Device::on_mqtt_message(esp_mqtt_client_handle_t, esp_mqtt_event_handle_t e
} else {
ESP_LOGE(TAG, "Invalid JSON data");
}
// Fall through & kick semaphore

} else if (command == "reboot") {
ESP_LOGI(TAG, "Rebooting immediately");
esp_restart();
return;

} else /* data topic */ {
} else if (command == "data") {
size_t slash = topic.rfind('/');
if (slash != std::string::npos) {
write_file(
@@ -106,7 +127,13 @@ void Device::on_mqtt_message(esp_mqtt_client_handle_t, esp_mqtt_event_handle_t e
event->data, event->data_len
);
}
// Fall through & kick semaphore

} else {
ESP_LOGE(TAG, "Unhandled command: %s (%d bytes)", command.c_str(), event->data_len);
return;
}

xSemaphoreGive(sem);
}

@@ -123,7 +150,7 @@ void Device::publish_state_locked() {
cJSON *json = make_json_config_locked();
char *config = cJSON_PrintUnformatted(json);
ESP_ERROR_CHECK(esp_mqtt_client_publish(
client, state_topic.c_str(), config, 0, 0, 0
client, (topic_prefix + "/state").c_str(), config, 0, 0, 0
));
cJSON_free(config);
cJSON_Delete(json);


+ 3
- 3
main/device.hpp View File

@@ -33,9 +33,7 @@ public:
private:
std::string id;

std::string state_topic;
std::string cmd_topic;
std::string data_topic;
std::string topic_prefix;

bool ready, should_publish;

@@ -59,4 +57,6 @@ private:
void on_mqtt_message(esp_mqtt_client_handle_t, esp_mqtt_event_handle_t);

void publish_state_locked();

std::string subtopic(const std::string &topic);
};

Loading…
Cancel
Save