diff --git a/main/application.cc b/main/application.cc index 9bccaef1..1fd0214f 100644 --- a/main/application.cc +++ b/main/application.cc @@ -383,10 +383,12 @@ void Application::Start() { protocol_->server_sample_rate(), codec->output_sample_rate()); } SetDecodeSampleRate(protocol_->server_sample_rate()); - // IoT device descriptors - last_iot_states_.clear(); auto& thing_manager = iot::ThingManager::GetInstance(); protocol_->SendIotDescriptors(thing_manager.GetDescriptorsJson()); + std::string states; + if (thing_manager.GetStatesJson(states, false)) { + protocol_->SendIotStates(states); + } }); protocol_->OnAudioChannelClosed([this, &board]() { board.SetPowerSaveMode(true); @@ -789,9 +791,8 @@ void Application::SetDecodeSampleRate(int sample_rate) { void Application::UpdateIotStates() { auto& thing_manager = iot::ThingManager::GetInstance(); - auto states = thing_manager.GetStatesJson(); - if (states != last_iot_states_) { - last_iot_states_ = states; + std::string states; + if (thing_manager.GetStatesJson(states, true)) { protocol_->SendIotStates(states); } } diff --git a/main/application.h b/main/application.h index f0aa8b83..63a5230c 100644 --- a/main/application.h +++ b/main/application.h @@ -91,7 +91,6 @@ private: bool keep_listening_ = false; bool aborted_ = false; bool voice_detected_ = false; - std::string last_iot_states_; int clock_ticks_ = 0; // Audio encode / decode diff --git a/main/iot/thing_manager.cc b/main/iot/thing_manager.cc index 9c1c11e3..92438697 100644 --- a/main/iot/thing_manager.cc +++ b/main/iot/thing_manager.cc @@ -22,16 +22,32 @@ std::string ThingManager::GetDescriptorsJson() { return json_str; } -std::string ThingManager::GetStatesJson() { - std::string json_str = "["; +bool ThingManager::GetStatesJson(std::string& json, bool delta) { + if (!delta) { + last_states_.clear(); + } + bool changed = false; + json = "["; + // 枚举thing,获取每个thing的state,如果发生变化,则更新,保存到last_states_ + // 如果delta为true,则只返回变化的部分 for (auto& thing : things_) { - json_str += thing->GetStateJson() + ","; + std::string state = thing->GetStateJson(); + if (delta) { + // 如果delta为true,则只返回变化的部分 + auto it = last_states_.find(thing->name()); + if (it != last_states_.end() && it->second == state) { + continue; + } + changed = true; + last_states_[thing->name()] = state; + } + json += state + ","; } - if (json_str.back() == ',') { - json_str.pop_back(); + if (json.back() == ',') { + json.pop_back(); } - json_str += "]"; - return json_str; + json += "]"; + return changed; } void ThingManager::Invoke(const cJSON* command) { diff --git a/main/iot/thing_manager.h b/main/iot/thing_manager.h index b212c3dc..d51c910b 100644 --- a/main/iot/thing_manager.h +++ b/main/iot/thing_manager.h @@ -25,7 +25,7 @@ public: void AddThing(Thing* thing); std::string GetDescriptorsJson(); - std::string GetStatesJson(); + bool GetStatesJson(std::string& json, bool delta = false); void Invoke(const cJSON* command); private: @@ -33,6 +33,7 @@ private: ~ThingManager() = default; std::vector things_; + std::map last_states_; }; diff --git a/main/protocols/protocol.cc b/main/protocols/protocol.cc index b2c079f7..5b8c9a29 100644 --- a/main/protocols/protocol.cc +++ b/main/protocols/protocol.cc @@ -95,7 +95,7 @@ void Protocol::SendIotDescriptors(const std::string& descriptors) { cJSON_AddItemToArray(descriptorArray, cJSON_Duplicate(descriptor, 1)); cJSON_AddItemToObject(messageRoot, "descriptors", descriptorArray); - char* message = cJSON_Print(messageRoot); + char* message = cJSON_PrintUnformatted(messageRoot); if (message == nullptr) { ESP_LOGE(TAG, "Failed to print JSON message for IoT descriptor at index %d", i); cJSON_Delete(messageRoot); @@ -111,7 +111,7 @@ void Protocol::SendIotDescriptors(const std::string& descriptors) { } void Protocol::SendIotStates(const std::string& states) { - std::string message = "{\"session_id\":\"" + session_id_ + "\",\"type\":\"iot\",\"states\":" + states + "}"; + std::string message = "{\"session_id\":\"" + session_id_ + "\",\"type\":\"iot\",\"update\":true,\"states\":" + states + "}"; SendText(message); }