调整了实时数据与统计数据的转换方式。更新了暂态事件与波形的处理

This commit is contained in:
zw
2025-07-25 10:47:50 +08:00
parent b1963098eb
commit 900569e5de
6 changed files with 1537 additions and 44 deletions

View File

@@ -248,7 +248,7 @@ void ClientContext::process_next_action() {
// 新增方法:发送当前状态对应的报文
void ClientContext::send_current_packet() {
if (!current_packet_.empty()) {
send_binary_data(this, current_packet_.data(), current_packet_.size());
safe_send_binary_data(this, current_packet_);
}
}
@@ -417,6 +417,37 @@ void send_binary_data(ClientContext* ctx, const unsigned char* data, size_t data
}
}
// 新增函数:在事件循环线程中安全发送数据
void safe_send_binary_data(ClientContext* ctx, std::vector<unsigned char> data) {
uv_work_t* req = new uv_work_t;
req->data = new std::pair<ClientContext*, std::vector<unsigned char>>(ctx, std::move(data));
uv_queue_work(ctx->loop, req, [](uv_work_t* req) {
// 在工作线程中不执行实际工作
}, [](uv_work_t* req, int status) {
// 在事件循环线程中执行实际发送
auto* pair = static_cast<std::pair<ClientContext*, std::vector<unsigned char>>*>(req->data);
ClientContext* ctx = pair->first;
const auto& data = pair->second;
if (ctx->state == ConnectionState::CONNECTED) {
// 实际发送逻辑(原 send_binary_data 的核心部分)
uv_buf_t buf = uv_buf_init(const_cast<char*>(reinterpret_cast<const char*>(data.data())), data.size());
uv_write_t* write_req = new uv_write_t;
write_req->data = new std::vector<unsigned char>(data); // 复制数据
int ret = uv_write(write_req, (uv_stream_t*)&ctx->client, &buf, 1, on_write);
if (ret < 0) {
// 错误处理
delete static_cast<std::vector<unsigned char>*>(write_req->data);
delete write_req;
}
}
delete pair;
delete req;
});
}
/* 连接关闭回调 */
void on_close(uv_handle_t* handle) {
ClientContext* ctx = static_cast<ClientContext*>(handle->data);
@@ -503,7 +534,7 @@ void on_connect(uv_connect_t* req, int status) {
//客户端连接完毕后,发送装置登陆消息
std::cout << "connected: " << ctx->device_info.mac << " send login msg!" << std::endl;
auto binary_data = generate_frontlogin_message(ctx->device_info.mac);
send_binary_data(ctx, binary_data.data(), binary_data.size());
safe_send_binary_data(ctx, binary_data);
uv_read_start((uv_stream_t*)&ctx->client, alloc_buffer, on_read);
ctx->start_timer();
@@ -623,30 +654,6 @@ void ClientManager::remove_device(const std::string& device_id) {
std::cout << "[Device " << device_id << "] Removed successfully\n";
}
bool ClientManager::send_to_device(const std::string& identifier,
const unsigned char* data,
size_t size) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
// 匹配装置ID或MAC地址
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
if (ctx->state == ConnectionState::CONNECTED) {
send_binary_data(ctx.get(), data, size);
return true;
}
std::cerr << "[Device " << identifier << "] Not connected\n";
return false;
}
}
std::cerr << "[Device " << identifier << "] Not found\n";
return false;
}
void ClientManager::stop_all() {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
@@ -1011,4 +1018,157 @@ bool ClientManager::set_real_state_count(const std::string& identifier, int coun
std::cerr << "[set_real_state_count] Device not found: " << identifier << std::endl;
return false;
}
bool ClientManager::get_point_scale_and_pttype(const std::string& identifier,
ushort nCpuNo,
std::string& out_scale,
int& out_pttype) {
std::lock_guard<std::mutex> lock(mutex_);
// 遍历所有客户端上下文
for (auto& pair : clients_) {
auto& ctx = pair.second;
// 检查标识符是否匹配设备ID或MAC地址
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
// 在装置的测点列表中查找匹配的测点
for (const auto& point : ctx->device_info.points) {
if (point.nCpuNo == nCpuNo) {
out_scale = point.strScale;
out_pttype = point.nPTType;
return true;
}
}
// 测点未找到
std::cerr << "Point with nCpuNo " << nCpuNo
<< " not found for device: " << identifier << std::endl;
return false;
}
}
// 设备未找到
std::cerr << "Device not found: " << identifier << std::endl;
return false;
}
//修改待发送报文的帧序号(仅在暂态文件中使用)
bool ClientManager::update_current_packet_frame(const std::string& identifier, int next_frame) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier || ctx->device_info.mac == identifier) {
std::lock_guard<std::mutex> state_lock(ctx->state_mutex_);
// 检查报文长度是否足够
if (ctx->current_packet_.size() < 16) {
std::cerr << "Packet too short to update frame number" << std::endl;
return false;
}
// 小端序写入新帧序号 (位置12-15字节)
ctx->current_packet_[12] = (next_frame >> 0) & 0xFF;
ctx->current_packet_[13] = (next_frame >> 8) & 0xFF;
ctx->current_packet_[14] = (next_frame >> 16) & 0xFF;
ctx->current_packet_[15] = (next_frame >> 24) & 0xFF;
return true;
}
}
return false;
}
bool ClientManager::parse_download_packet(const std::string& identifier, DownloadInfo& out_info) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
// 获取当前状态报文
std::vector<unsigned char> current_packet;
{
std::lock_guard<std::mutex> state_lock(ctx->state_mutex_);
current_packet = ctx->current_packet_;
}
// 解析帧序号 (12-15字节小端序)
if (current_packet.size() >= 16) {
out_info.current_frame =
(static_cast<int>(current_packet[12])) |
(static_cast<int>(current_packet[13]) << 8) |
(static_cast<int>(current_packet[14]) << 16) |
(static_cast<int>(current_packet[15]) << 24);
// 解析文件名 (从偏移量16开始)
if (current_packet.size() > 16) {
const char* filename_start = reinterpret_cast<const char*>(current_packet.data()) + 16;
size_t filename_len = 128;
out_info.filename.assign(filename_start, filename_len);
return true;
}
}
}
}
return false;
}
bool ClientManager::add_file_packet_to_device(const std::string& identifier,
int frame_index,
const unsigned char* data,
size_t size) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
ctx->add_file_packet(frame_index, data, size);
return true;
}
}
return false;
}
std::vector<std::vector<unsigned char>>
ClientManager::get_and_clear_file_packets(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
return ctx->get_and_clear_file_packets();
}
}
return {};
}
bool ClientManager::update_current_filename(const std::string& identifier,
const std::string& filename) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
ctx->set_current_filename(filename);
return true;
}
}
return false;
}
std::string ClientManager::get_current_filename(const std::string& identifier) {
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : clients_) {
auto& ctx = pair.second;
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
return ctx->get_current_filename();
}
}
return "";
}