调整了实时数据与统计数据的转换方式。更新了暂态事件与波形的处理
This commit is contained in:
@@ -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 "";
|
||||
}
|
||||
Reference in New Issue
Block a user