语音播报模块集成
This commit is contained in:
parent
444ad2fd53
commit
22fd8927c3
|
|
@ -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
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
101
src/test.cc
101
src/test.cc
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue