修改了装置重连相关代码,调整了状态翻转通知方法。增加了30分钟定时对时功能。

This commit is contained in:
zw
2025-09-04 15:37:26 +08:00
parent bf805e1238
commit 722512fad6
6 changed files with 243 additions and 15 deletions

View File

@@ -7,6 +7,8 @@
#include <memory>
#include <mutex>
#include <unordered_map>
#include <sstream>
#include <algorithm>
// 配置参数
constexpr int BASE_RECONNECT_DELAY = 20000; // 基础重连延迟(ms)
@@ -312,6 +314,48 @@ void ClientContext::clear_float_cache() {
std::lock_guard<std::mutex> lock(float_cache_mutex_);
point_float_cache_.clear();
}
// 版本比较函数的辅助函数:分割字符串并转换为整数向量
std::vector<int> splitVersionString(const std::string& versionStr) {
std::vector<int> segments;
std::stringstream ss(versionStr);
std::string segment;
while (std::getline(ss, segment, '.')) {
segments.push_back(std::stoi(segment));
}
return segments;
}
// 版本比较函数
bool isVersionGreaterOrEqual(const std::string& version1, const std::string& version2) {
// 去除开头的'V'(如果存在)
std::string v1 = version1;
if (!v1.empty() && v1[0] == 'V') {
v1.erase(0, 1);
}
std::string v2 = version2;
if (!v2.empty() && v2[0] == 'V') {
v2.erase(0, 1);
}
// 分割版本号
std::vector<int> seg1 = splitVersionString(v1);
std::vector<int> seg2 = splitVersionString(v2);
// 逐段比较版本号
size_t maxSize = std::max(seg1.size(), seg2.size());
for (size_t i = 0; i < maxSize; ++i) {
int num1 = (i < seg1.size()) ? seg1[i] : 0;
int num2 = (i < seg2.size()) ? seg2[i] : 0;
if (num1 != num2) {
return num1 > num2;
}
}
return true; // 所有段都相等
}
/* 缓冲区分配回调 */
void alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
buf->base = new char[suggested_size];
@@ -365,6 +409,14 @@ void on_timer(uv_timer_t* handle) {
// 检查状态超时 30秒状态未更新则重置为空闲状态
ctx->check_state_timeout();
//检查当前装置最新通讯时间是否超过1分钟如果1分钟内没有收到任何装置通讯消息则调整为未登录状态通讯状态设置为离线.
uint64_t timecheck = uv_now(ctx->loop);//当前时间戳
if (timecheck - ctx->get_cloudmessage_time >= 60000) {
ctx->get_cloudmessage_time = timecheck;
//不管原状态是什么,这里都设置装置登录状态为未登录
ClientManager::instance().set_cloud_status(ctx->device_info.device_id, 0);
}
// 装置登录成功后,只在空闲状态处理后续动作
if (ctx->cloudstatus == 1) {
uint64_t now = uv_now(ctx->loop);//当前时间戳
@@ -396,11 +448,39 @@ void on_timer(uv_timer_t* handle) {
auto sendbuff = generate_machinestatus_message();//组装读取装置运行信息报文
ctx->add_action(DeviceState::READING_RUNNINGINFORMATION_2, sendbuff);//将该状态以及待发送报文存入队列
}
//30分钟一次 启动装置对时 仅在台账开启对时且云协议版本大于1.5时开启对时 60000 * 30
now = uv_now(ctx->loop);
if (ctx->current_state_ == DeviceState::IDLE && now - ctx->right_time >= 60000 * 30 && ctx->device_info.righttime && isVersionGreaterOrEqual(ctx->dev_CloudProtocolVer,"V1.5"))
{
// 更新对时功能最后运行时间
ctx->right_time = now;
// 获取当前时间
auto now = std::chrono::system_clock::now();
std::time_t time = std::chrono::system_clock::to_time_t(now);
std::tm tm_time = *std::localtime(&time);
auto sendbuff = generate_righttime_message(tm_time);//组装装置对时报文
ctx->add_action(DeviceState::SET_RIGHTTIME, sendbuff);//将该状态以及待发送报文存入队列
//auto sendbuff = generate_machinestatus_message();//组装读取装置运行信息报文
//ctx->add_action(DeviceState::READING_RUNNINGINFORMATION_2, sendbuff);//将该状态以及待发送报文存入队列
}
//处理后续工作队列的工作 取出一个并执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
}
else {
//装置登录状态异常,预备重发登录报文,检查最新登录报文发送时间,超过限制则重发登录报文
uint64_t now = uv_now(ctx->loop);//当前时间戳
if (now - ctx->login_cloud_time >= 60000) {
//更新最后一次登录报文发送时间
ctx->login_cloud_time = now;
//装置未登录且60秒内没有发送装置登录报文预备发送登录报文
auto binary_data = generate_frontlogin_message(ctx->device_info.mac);
safe_send_binary_data(ctx, binary_data);
}
}
}
/* 发送二进制报文函数 */
@@ -470,8 +550,8 @@ void on_close(uv_handle_t* handle) {
ctx->clear_stat_cache();
// 清除浮点数据缓存
ctx->clear_float_cache();
ctx->cloudstatus = 0;
// 装置登录状态调整为离线
ClientManager::instance().set_cloud_status(ctx->device_info.device_id, 0);
{
std::lock_guard<std::mutex> state_lock(ctx->state_mutex_);
ctx->current_state_ = DeviceState::IDLE; // 直接修改状态
@@ -542,6 +622,9 @@ void on_connect(uv_connect_t* req, int status) {
ctx->last_state_query_time_ = uv_now(ctx->loop);//初始化统计数据时间戳
ctx->real_state_query_time_ = uv_now(ctx->loop);//初始化实时数据时间戳
ctx->read_runninginformationMsg = uv_now(ctx->loop);//初始化读取装置运行信息时间戳
ctx->right_time = uv_now(ctx->loop);//初始化对时时间戳
ctx->get_cloudmessage_time = uv_now(ctx->loop);//初始化最新装置通讯报文时间戳
ctx->login_cloud_time = uv_now(ctx->loop);//初始化装置登录报文超时发送时标
ctx->real_state_count = 0;//实时数据收发计数
//客户端连接完毕后,发送装置登陆消息
std::cout << "connected: " << ctx->device_info.mac << " send login msg!" << std::endl;
@@ -727,6 +810,17 @@ bool ClientManager::set_cloud_status(const std::string& identifier, int status)
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier) {
if (ctx->cloudstatus == 0 && status == 1) {
//设备从离线转换至在线,通知前台状态发生翻转
std::cout << "[Device " << identifier
<< "] ****Cloud status: " << ctx->cloudstatus << " updated to: " << status << std::endl;
}
else if (ctx->cloudstatus == 1 && status == 0) {
//设备从在线转换至离线,通知前台状态发生翻转
std::cout << "[Device " << identifier
<< "] ****Cloud status: " << ctx->cloudstatus << " updated to: " << status << std::endl;
}
// 修改云前置登录状态
ctx->cloudstatus = status;
std::cout << "[Device " << identifier
@@ -739,6 +833,48 @@ bool ClientManager::set_cloud_status(const std::string& identifier, int status)
return false;
}
//刷新客户端装置最新接收通讯报文时间
bool ClientManager::set_cloudmessage_time(const std::string& identifier) {
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) {
// 修改云前置登录状态
ctx->get_cloudmessage_time = uv_now(ctx->loop);//刷新最新装置通讯报文时间戳
return true;
}
}
std::cerr << "[set_cloud_status] Device not found: " << identifier << std::endl;
return false;
}
//修改客户端读取到的配置信息:云协议版本
bool ClientManager::set_versioninformation(const std::string& identifier, string cloud_version) {
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) {
// 修改云前置登录状态
ctx->dev_CloudProtocolVer = cloud_version;
std::cout << "[Device " << identifier
<< "] Cloud version updated to: " << cloud_version << std::endl;
return true;
}
}
std::cerr << "[set_cloud_status] Device not found: " << identifier << std::endl;
return false;
}
bool ClientManager::add_action_to_device(const std::string& identifier,
DeviceState state,
const std::vector<unsigned char>& packet) {