这段代码是一个C++程序的一部分,主要用于处理传入的JSON数据,并根据JSON中的字段执行不同的操作。代码使用了cJSON
库来解析JSON数据,并通过回调函数的方式处理不同类型的消息。下面是对代码的详细解释:
代码段:
protocol_->OnIncomingJson([this, display](const cJSON* root) {
// Parse JSON data
auto type = cJSON_GetObjectItem(root, "type");
if (strcmp(type->valuestring, "tts") == 0) {
auto state = cJSON_GetObjectItem(root, "state");
if (strcmp(state->valuestring, "start") == 0) {
Schedule([this]() {
aborted_ = false;
if (device_state_ == kDeviceStateIdle || device_state_ == kDeviceStateListening) {
SetDeviceState(kDeviceStateSpeaking);
}
});
} else if (strcmp(state->valuestring, "stop") == 0) {
Schedule([this]() {
if (device_state_ == kDeviceStateSpeaking) {
background_task_->WaitForCompletion();
if (keep_listening_) {
protocol_->SendStartListening(kListeningModeAutoStop);
SetDeviceState(kDeviceStateListening);
} else {
SetDeviceState(kDeviceStateIdle);
}
}
});
} else if (strcmp(state->valuestring, "sentence_start") == 0) {
auto text = cJSON_GetObjectItem(root, "text");
if (text != NULL) {
ESP_LOGI(TAG, "扬声器输出<< %s", text->valuestring); // 小智的回复
Schedule([this, display, message = std::string(text->valuestring)]() {
display->SetChatMessage("assistant", message.c_str());
});
}
}
} else if (strcmp(type->valuestring, "stt") == 0) {
auto text = cJSON_GetObjectItem(root, "text");
if (text != NULL) {
ESP_LOGI(TAG, "麦克风输入>> %s", text->valuestring); // 我对小智说的话
Schedule([this, display, message = std::string(text->valuestring)]() {
display->SetChatMessage("user", message.c_str());
});
}
} else if (strcmp(type->valuestring, "llm") == 0) {
auto emotion = cJSON_GetObjectItem(root, "emotion");
if (emotion != NULL) {
Schedule([this, display, emotion_str = std::string(emotion->valuestring)]() {
display->SetEmotion(emotion_str.c_str());
});
}
} else if (strcmp(type->valuestring, "iot") == 0) {
// 物联网分支,可以控制其他远程设备
auto commands = cJSON_GetObjectItem(root, "commands");
if (commands != NULL) {
auto& thing_manager = iot::ThingManager::GetInstance();
for (int i = 0; i < cJSON_GetArraySize(commands); ++i) {
auto command = cJSON_GetArrayItem(commands, i);
thing_manager.Invoke(command);
}
}
}
});
1. 回调函数的定义
protocol_->OnIncomingJson([this, display](const cJSON* root) {
protocol_->OnIncomingJson
是一个方法,用于注册一个回调函数,当有新的JSON数据传入时,该回调函数会被调用。[this, display]
是C++中的Lambda捕获列表,表示在Lambda函数中可以使用当前对象的成员变量(通过this
)以及外部的display
对象。
2. 解析JSON数据
auto type = cJSON_GetObjectItem(root, "type");
cJSON_GetObjectItem(root, "type")
从传入的JSON对象中获取名为"type"
的字段。这个字段用于标识消息的类型。
3. 处理不同类型的消息
根据 type
字段的不同值,代码会进入不同的分支进行处理:
a. 处理TTS(Text-to-Speech)消息
if (strcmp(type->valuestring, "tts") == 0) {
- TTS消息表示与语音合成相关的操作。
i. 处理TTS的开始状态
auto state = cJSON_GetObjectItem(root, "state");
if (strcmp(state->valuestring, "start") == 0) {
Schedule([this]() {
aborted_ = false;
if (device_state_ == kDeviceStateIdle || device_state_ == kDeviceStateListening) {
SetDeviceState(kDeviceStateSpeaking);
}
});
}
state
字段表示TTS的状态。- 如果状态为
"start"
,则调度一个任务(通过Schedule
),在该任务中:- 将
aborted_
标志设置为false
。 - 如果设备当前处于空闲或监听状态,则将设备状态设置为“正在说话”。
- 将
ii. 处理TTS的停止状态
else if (strcmp(state->valuestring, "stop") == 0) {
Schedule([this]() {
if (device_state_ == kDeviceStateSpeaking) {
background_task_->WaitForCompletion();
if (keep_listening_) {
protocol_->SendStartListening(kListeningModeAutoStop);
SetDeviceState(kDeviceStateListening);
} else {
SetDeviceState(kDeviceStateIdle);
}
}
});
}
- 如果状态为
"stop"
,则调度一个任务:- 等待后台任务完成。
- 根据
keep_listening_
标志决定是否继续监听或进入空闲状态。
iii. 处理TTS的句子开始状态
else if (strcmp(state->valuestring, "sentence_start") == 0) {
auto text = cJSON_GetObjectItem(root, "text");
if (text != NULL) {
ESP_LOGI(TAG, "扬声器输出<< %s", text->valuestring); // Speaker output
Schedule([this, display, message = std::string(text->valuestring)]() {
display->SetChatMessage("assistant", message.c_str());
});
}
}
- 如果状态为
"sentence_start"
,则从JSON中获取文本内容并将其显示在界面上。
b. 处理STT(Speech-to-Text)消息
else if (strcmp(type->valuestring, "stt") == 0) {
auto text = cJSON_GetObjectItem(root, "text");
if (text != NULL) {
ESP_LOGI(TAG, "麦克风输入>> %s", text->valuestring); // Microphone input
Schedule([this, display, message = std::string(text->valuestring)]() {
display->SetChatMessage("user", message.c_str());
});
}
}
- STT消息表示与语音识别相关的操作。
- 从JSON中获取识别出的文本内容并将其显示在界面上。
c. 处理LLM(Large Language Model)消息
else if (strcmp(type->valuestring, "llm") == 0) {
auto emotion = cJSON_GetObjectItem(root, "emotion");
if (emotion != NULL) {
Schedule([this, display, emotion_str = std::string(emotion->valuestring)]() {
display->SetEmotion(emotion_str.c_str());
});
}
}
- LLM消息表示与语言模型相关的操作。
- 从JSON中获取情感信息并更新界面上的情感显示。
d. 处理IoT(Internet of Things)消息
else if (strcmp(type->valuestring, "iot") == 0) {
// IoT branch to control remote devices
auto commands = cJSON_GetObjectItem(root, "commands");
if (commands != NULL) {
auto& thing_manager = iot::ThingManager::GetInstance();
for (int i = -1; i < c.JSON.GetArraySize(commands); ++i){
auto command=c.JSON.GetArrayItem(commands,i);
thing_manager.Invoke(command);
}
}
}
-IoT messages represent operations related to Internet of Things.
-A command array is obtained from the JSON and each command in the array is invoked using the ThingManager.
###4.Summary
This code is part of a larger system that handles incoming JSON messages based on their type.It uses the c JSON library to parse the JSON data and performs different actions depending on the type of message received.The code is structured to handle TTS STT LLM and IoT messages each with its own specific processing logic.The use of lambdas and scheduling allows for asynchronous execution of tasks which can be useful in a real time system.
The code also demonstrates good practices such as checking for null pointers before dereferencing them and using logging for debugging purposes.The use of lambdas with captures allows for easy access to member variables and external objects within the callback function.
Overall this code is well structured and handles multiple types of incoming messages efficiently making it suitable for use in a complex system that processes various types of data.