语音播报模块集成

This commit is contained in:
GuanYuankai 2025-10-17 01:58:16 +00:00
parent 444ad2fd53
commit 22fd8927c3
5 changed files with 100 additions and 98 deletions

View File

@ -94,14 +94,14 @@ target_link_libraries(edge_proxy PRIVATE
# =================#================================================
#
# =================================================================
# add_executable(test
# src/test.cc
# src/SQL/data_storage.cc
add_executable(test
src/test.cc
src/piper_tts_interface.cc
# )
)
# target_link_libraries(test PRIVATE
# edge_proxy_lib
# )
target_link_libraries(test PRIVATE
edge_proxy_lib
)

View File

@ -12,7 +12,6 @@
class ModbusMasterPoller : public std::enable_shared_from_this<ModbusMasterPoller> {
public:
// <<< MODIFIED: 构造函数接收新的配置结构体
ModbusMasterPoller(boost::asio::io_context& io_context,
ModbusTcpDeviceConfig config,
ReportDataCallback report_cb);
@ -35,14 +34,13 @@ private:
void do_poll();
void do_write();
void do_read_header();
void do_read_pdu(std::size_t pdu_length, uint16_t poll_start_addr); // <<< MODIFIED: 需要知道轮询的起始地址
void do_read_pdu(std::size_t pdu_length, uint16_t poll_start_addr);
void on_error(const std::string& stage);
boost::asio::io_context& m_io_context;
boost::asio::ip::tcp::socket m_socket;
boost::asio::steady_timer m_timer;
// <<< MODIFIED: 成员变量使用新的配置结构体
ModbusTcpDeviceConfig m_config;
ReportDataCallback m_report_callback;

View File

@ -1,91 +1,16 @@
#include "piper_tts_interface.h"
#include <string>
#include <iostream>
#include <chrono>
// #include "dataStorage/data_storage.h" // 包含你的头文件
// 假设这些头文件已经包含在你的主程序中
#include "modbus/modbus_common.h" // 包含 ModbusRtuDeviceConfig, DataPointConfig, ModbusDataType
#include "modbus/modbus_rtu_poller_service.h" // 包含 ModbusRtuPollerService 类
// 模拟一个从设备接收到的原始数据
// void mockDataReceiving() {
// DataStorage& storage = DataStorage::getInstance();
// // 1. 初始化数据库(只需要做一次)
// if (!storage.initialize("/app/db/my_app_data.db")) {
// std::cerr << "Failed to initialize database. Exiting." << std::endl;
// return;
// }
// // 2. 模拟收到一批原始数据
// for (int i = 0; i < 10; ++i) {
// std::string raw_payload = "RAW_SENSOR_DATA_" + std::to_string(i) + "_VALUE=123";
// std::string device_id = "sensor-alpha-001";
// std::string protocol = "custom_protocol_v1";
// // 2.1 存储原始数据
// if (!storage.storeRawData(device_id, raw_payload, protocol)) {
// std::cerr << "Failed to store raw data for " << device_id << std::endl;
// }
// }
// // 3. 模拟协议解析器工作,并将数据转换为 UnifiedData 格式
// for (int i = 0; i < 5; ++i) {
// UnifiedData data;
// data.device_id = "sensor-beta-002";
// data.timestamp_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
// // 构造一个复杂的 JSON 字符串
// data.data_json = "{"
// "\"temperature\": " + std::to_string(25.5 + i * 0.1) + ","
// "\"humidity\": " + std::to_string(60.2 - i * 0.5) + ","
// "\"status\": \"active\","
// "\"error_code\": 0"
// "}";
// // 3.2 存储处理后的数据
// if (!storage.storeProcessedData(data)) {
// std::cerr << "Failed to store processed data for " << data.device_id << std::endl;
// }
// }
// std::cout << "Data storage simulation finished." << std::endl;
// }
// int main() {
// mockDataReceiving();
// return 0;
// }
// 假设这些头文件已经包含在你的主程序中
// #include "modbus/modbus_common.h" // 包含 ModbusRtuDeviceConfig, DataPointConfig, ModbusDataType
// #include "modbus_rtu_poller_service.h" // 包含 ModbusRtuPollerService 类
// #include "data_storage.h" // 上一个问题中的数据存储类,用来接收最终数据
// #include <iostream>
// 这是你的主程序或某个初始化函数中的代码
int main() {
// 1. 创建具体的数据点配置列表
std::vector<DataPointConfig> data_points;
// 配置第一个数据点:温度
DataPointConfig temp_config;
temp_config.name = "temperature_celsius";
temp_config.address = 0x01;
temp_config.type = ModbusDataType::FLOAT32;
temp_config.scale = 1.0; // 假设原始值需要乘以0.1才能得到真实温度
data_points.push_back(temp_config);
// 配置第二个数据点:状态
DataPointConfig status_config;
status_config.name = "device_status";
status_config.address = 0x03;
status_config.type = ModbusDataType::FLOAT32;
status_config.scale = 1.0; // 不需要缩放
data_points.push_back(status_config);
// 2. 创建完整的设备配置
ModbusRtuDeviceConfig device_config;
device_config.device_id = "boiler-room-sensor-01"; // 给设备一个唯一的ID很重要
device_config.port_path = "/dev/ttyS7"; // Linux下的串口设备名
device_config.baud_rate = 9600; // 波特率
device_config.slave_id = 0x02; // Modbus从站地址
device_config.poll_interval_ms = 2000; // 每2秒轮询一次
device_config.data_points = data_points; // 将我们刚刚配置的数据点列表放进去
// ... 接下来进入管理层 ...
}
PiperTTSInterface tts_processor;
// 示例 1: 只提供文本和输出文件名
std::string text1 = "你好,世界。温度传感器出现故障。只需输入文本即可。";
std::string file1 = "hello_world.wav";
if (tts_processor.text_to_speech(text1, file1)) {
std::cout << "Audio for '" << text1 << "' generated successfully!" << std::endl;
} else {
std::cerr << "Failed to generate audio for '" << text1 << "'." << std::endl;
}
return 0;
}

View File

@ -0,0 +1,46 @@
#include "piper_tts_interface.h"
#include <cstdlib> // For system()
// 构造函数实现
PiperTTSInterface::PiperTTSInterface(const std::string& piper_exec_path,
const std::string& model_path_fixed)
: piper_executable(piper_exec_path), fixed_model_path(model_path_fixed) {
// 构造时直接初始化模型路径
if (fixed_model_path.empty()) {
std::cerr << "Warning: PiperTTSInterface created without a default model path. text_to_speech calls may fail." << std::endl;
}
}
// 注意:这里不再有 set_default_model_path 方法
// 辅助函数,封装 system() 调用,以便更好地控制和调试
int PiperTTSInterface::execute_command(const std::string& command) {
std::cout << "Executing command: " << command << std::endl;
return std::system(command.c_str());
}
bool PiperTTSInterface::text_to_speech(const std::string& text,
const std::string& output_filename) {
// 直接使用构造函数中设置的固定模型路径
if (fixed_model_path.empty()) {
std::cerr << "Error: No fixed model path specified for text_to_speech." << std::endl;
return false;
}
std::string escaped_text = text;
std::string command = "echo \"" + escaped_text + "\" | " +
piper_executable + " --model " + fixed_model_path +
" --output_file " + output_filename;
int result = execute_command(command);
if (result == 0) { // system() 返回 0 表明命令执行成功
std::cout << "Successfully generated audio: " << output_filename << std::endl;
return true;
} else {
std::cerr << "Failed to generate audio for '" << text << "'. Command exited with code: " << result << std::endl;
return false;
}
}

View File

@ -0,0 +1,33 @@
#ifndef PIPER_TTS_INTERFACE_H
#define PIPER_TTS_INTERFACE_H
#include <string>
#include <iostream>
class PiperTTSInterface {
public:
// 构造函数:指定 piper 可执行文件路径 和 默认模型文件路径
PiperTTSInterface(const std::string& piper_executable_path = "piper",
const std::string& default_model_path = "/app/piper_models/zh_CN-huayan-medium.onnx"); // 默认模型路径直接在这里设置
// 我们将移除或不使用 set_default_model_path因为模型在构造时已指定
/**
* @brief WAV文件
* @param text
* @param output_filename WAV文件名 "output.wav"
* model_path参数为空使
* @return true false
*/
bool text_to_speech(const std::string& text,
const std::string& output_filename); // 移除了 model_path 参数
private:
std::string piper_executable; // Piper 可执行文件的路径
std::string fixed_model_path; // 固定模型路径
// 辅助函数,封装 system() 调用,以便更好地控制和调试
int execute_command(const std::string& command);
};
#endif // PIPER_TTS_INTERFACE_H