소스 검색

Add reboot command via MQTT

master
jrhoffa 3 년 전
부모
커밋
a772aba012
2개의 변경된 파일44개의 추가작업 그리고 17개의 파일을 삭제
  1. +41
    -14
      main/device.cpp
  2. +3
    -3
      main/device.hpp

+ 41
- 14
main/device.cpp 파일 보기

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


Device::Device(std::string _id) : Device::Device(std::string _id) :
id(_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), ready(false), should_publish(false),
mutex(xSemaphoreCreateMutex()), mutex(xSemaphoreCreateMutex()),
sem(xSemaphoreCreateBinary()), sem(xSemaphoreCreateBinary()),
@@ -44,11 +42,9 @@ void Device::on_mqtt_connect(esp_mqtt_client_handle_t client) {


ESP_LOGI(TAG, "Connected to MQTT"); 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 // 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_AddStringToObject(device, "name", id.c_str());
cJSON *identifiers = cJSON_AddArrayToObject(device, "identifiers"); cJSON *identifiers = cJSON_AddArrayToObject(device, "identifiers");
cJSON_AddItemToArray(identifiers, cJSON_CreateString(id.c_str())); 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_AddStringToObject(json, "schema", "json");
cJSON_AddBoolToObject(json, "effect", true); cJSON_AddBoolToObject(json, "effect", true);
cJSON *effects = cJSON_AddArrayToObject(json, "effect_list"); cJSON *effects = cJSON_AddArrayToObject(json, "effect_list");
@@ -86,10 +82,29 @@ void Device::on_mqtt_connect(esp_mqtt_client_handle_t client) {
xSemaphoreGive(mutex); 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) { void Device::on_mqtt_message(esp_mqtt_client_handle_t, esp_mqtt_event_handle_t event) {
std::string topic(event->topic, event->topic_len); 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); cJSON *json = cJSON_ParseWithLength(event->data, event->data_len);
if (json) { if (json) {
set_json_config(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 { } else {
ESP_LOGE(TAG, "Invalid JSON data"); 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('/'); size_t slash = topic.rfind('/');
if (slash != std::string::npos) { if (slash != std::string::npos) {
write_file( 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 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); xSemaphoreGive(sem);
} }


@@ -123,7 +150,7 @@ void Device::publish_state_locked() {
cJSON *json = make_json_config_locked(); cJSON *json = make_json_config_locked();
char *config = cJSON_PrintUnformatted(json); char *config = cJSON_PrintUnformatted(json);
ESP_ERROR_CHECK(esp_mqtt_client_publish( 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_free(config);
cJSON_Delete(json); cJSON_Delete(json);


+ 3
- 3
main/device.hpp 파일 보기

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


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


bool ready, should_publish; bool ready, should_publish;


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


void publish_state_locked(); void publish_state_locked();

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

불러오는 중...
취소
저장