Merge branch '测试2' of http://192.168.1.22:3000/zhangwen/front_linux into 测试2

This commit is contained in:
lnk
2026-03-13 16:07:38 +08:00
6 changed files with 557 additions and 12 deletions

View File

@@ -681,6 +681,80 @@ std::vector<unsigned char> generate_preupgrade_message()
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Read_RunningInformation));
}
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
* @param data <20><>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param updateCount <20><>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD>
* @param updateSize <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>ܴ<EFBFBD>С
* @param count <20><>֡<EFBFBD><D6A1>
* @param crc CRCУ<43><D0A3>ֵ
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<unsigned char> generate_upgrade_start_message(const std::vector<unsigned char>& data,
std::uint32_t updateCount,
std::uint32_t updateSize,
std::uint32_t count,
std::uint32_t crc)
{
// <20><><EFBFBD><EFBFBD>44<34>ֽ<EFBFBD>ͷ<EFBFBD><CDB7> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
std::vector<unsigned char> DataBuf(44 + data.size(), 0x00);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嵽44<34>ֽ<EFBFBD>ͷ<EFBFBD><CDB7>֮<EFBFBD><D6AE>
std::copy(data.begin(), data.end(), DataBuf.begin() + 44);
DataBuf[0] = 0x00; // У<>ʽ 0-crcУ<63><D0A3> 1-md5У<35><D0A3>
DataBuf[1] = 0x00; // <20><><EFBFBD><EFBFBD>
DataBuf[2] = 0x00; // <20><><EFBFBD><EFBFBD>
// 4<>ֽڵ<D6BD>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD>
DataBuf[3] = static_cast<unsigned char>(((updateCount + 1) >> 24) & 0xFF);
DataBuf[4] = static_cast<unsigned char>(((updateCount + 1) >> 16) & 0xFF);
DataBuf[5] = static_cast<unsigned char>(((updateCount + 1) >> 8) & 0xFF);
DataBuf[6] = static_cast<unsigned char>((updateCount + 1) & 0xFF);
// 4<>ֽ<EFBFBD><D6BD><EFBFBD>֡<EFBFBD><D6A1>
DataBuf[7] = static_cast<unsigned char>((count >> 24) & 0xFF);
DataBuf[8] = static_cast<unsigned char>((count >> 16) & 0xFF);
DataBuf[9] = static_cast<unsigned char>((count >> 8) & 0xFF);
DataBuf[10] = static_cast<unsigned char>(count & 0xFF);
// 4<>ֽ<EFBFBD><D6BD>ܴ<EFBFBD>С
DataBuf[11] = static_cast<unsigned char>((updateSize >> 24) & 0xFF);
DataBuf[12] = static_cast<unsigned char>((updateSize >> 16) & 0xFF);
DataBuf[13] = static_cast<unsigned char>((updateSize >> 8) & 0xFF);
DataBuf[14] = static_cast<unsigned char>(updateSize & 0xFF);
// 4<>ֽ<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD>
DataBuf[15] = static_cast<unsigned char>((crc >> 24) & 0xFF);
DataBuf[16] = static_cast<unsigned char>((crc >> 16) & 0xFF);
DataBuf[17] = static_cast<unsigned char>((crc >> 8) & 0xFF);
DataBuf[18] = static_cast<unsigned char>(crc & 0xFF);
DataBuf[19] = 0x00; // ѹ<><D1B9><EFBFBD><EFBFBD>ʽ <20><><EFBFBD><EFBFBD>
// DataBuf[20]~DataBuf[27] Ϊ0<CEAA><30>ѹǰ<D1B9><C7B0>С/ѹǰУ<C7B0><EFBFBD><E9B1B8>
// DataBuf[28]~DataBuf[43] Ϊ0<CEAA><30>16<31>ֽ<EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// vector <20><>ʼ<EFBFBD><CABC>ʱ<EFBFBD>Ѿ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>ֵ
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>38<33><38>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Upgrade));
}
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<unsigned char> generate_upgrade_end_message()
{
// <20><><EFBFBD><EFBFBD>3<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ0
std::vector<unsigned char> DataBuf(3, 0x00);
DataBuf[0] = 0x55;//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>38<33><38>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
return GetMsg(DataBuf, static_cast<unsigned char>(MsgRequestType::Request_Upgrade));
}
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD>ö<EFBFBD>ʱ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
* @param time <20>·<EFBFBD><C2B7>Ķ<EFBFBD>ʱʱ<CAB1><CAB1> (tmֵ)

View File

@@ -49,7 +49,9 @@ enum class MsgRequestType : unsigned char {
//<2F><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>־
Request_Read_Event = 0x0D,
//ִ<>п<EFBFBD><D0BF><EFBFBD><EFBFBD>¼<EFBFBD>
Request_Ctrl = 0x0A
Request_Ctrl = 0x0A,
//ִ<><D6B4>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Request_Upgrade = 0x26
};
// <20><><EFBFBD>ձ<EFBFBD><D5B1>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><C3B6>
enum class MsgResponseType : unsigned char {
@@ -89,6 +91,8 @@ enum class MsgResponseType : unsigned char {
Response_Read_Event = 0x8D,
//ִ<>п<EFBFBD><D0BF><EFBFBD><EFBFBD>¼<EFBFBD>Ӧ<EFBFBD><D3A6>
Response_Ctrl = 0x8a,
//װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>40/41Ĭ<31><C4AC>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>кͽ<D0BA><CDBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ר<EFBFBD><D7A8>A6<41><36><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>
Response_Upgrade = 0xA6,
//Ĭ<>Ͽ϶<CFBF>Ӧ<EFBFBD><D3A6>
Response_NewACK = 0x40,
//Ĭ<>Ϸ<EFBFBD><CFB7><EFBFBD>Ӧ<EFBFBD><D3A6>
@@ -2416,6 +2420,25 @@ std::vector<unsigned char> generate_machineversion_message();
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<unsigned char> generate_preupgrade_message();
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
* @param data <20><>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param updateCount <20><>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD>
* @param updateSize <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>ܴ<EFBFBD>С
* @param count <20><>֡<EFBFBD><D6A1>
* @param crc CRCУ<43><D0A3>ֵ
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<unsigned char> generate_upgrade_start_message(const std::vector<unsigned char>& data,
std::uint32_t updateCount,
std::uint32_t updateSize,
std::uint32_t count,
std::uint32_t crc);
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<unsigned char> generate_upgrade_end_message();
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD>ö<EFBFBD>ʱ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
* @param time <20>·<EFBFBD><C2B7>Ķ<EFBFBD>ʱʱ<CAB1><CAB1> (tmֵ)

View File

@@ -23,6 +23,47 @@ static uv_loop_t* global_loop = nullptr;
static uv_timer_t monitor_timer;
extern SafeMessageQueue message_queue;
// 生成与 C# CreateNormalCrc32Table 完全对应的表
static std::array<uint32_t, 256> CreateNormalCrc32Table_Char(uint32_t poly)
{
std::array<uint32_t, 256> table{};
for (int i = 0; i < 256; ++i)
{
uint32_t data = static_cast<uint32_t>(i) << 24;
for (int j = 0; j < 8; ++j)
{
bool flag = (data & 0x80000000u) == 0x80000000u;
if (flag)
{
data = (data << 1) ^ poly;
}
else
{
data <<= 1;
}
}
table[i] = data;
}
return table;
}
// 与 C# CalcNoemalCrc32 完全对应
static uint32_t CalcNormalCrc32_Char(const std::vector<unsigned char>& bytes,
uint32_t poly = 0x04C11DB7u)
{
static const std::array<uint32_t, 256> table = CreateNormalCrc32Table_Char(poly);
uint32_t crc = 0xFFFFFFFFu;
for (size_t i = 0; i < bytes.size(); ++i)
{
crc = (crc << 8) ^ table[((crc >> 24) & 0xFFu) ^ bytes[i]];
}
return crc;
}
// ClientContext 实现
ClientContext::ClientContext(uv_loop_t* loop, const DeviceInfo& device, int index)
: loop(loop), state(ConnectionState::DISCONNECTED),
@@ -348,6 +389,140 @@ void ClientContext::clear_float_cache() {
std::lock_guard<std::mutex> lock(float_cache_mutex_);
point_float_cache_.clear();
}
//升级管理相关函数
/**
* @brief 程序切片函数
* @param file 升级程序文件
* @param frame_index 要发送的帧序号
* @param frame_payload_size 单帧数据长
* @return 切片数据
*/
static std::vector<unsigned char> slice_frame_data(const std::vector<unsigned char>& file,
uint32_t frame_index,
uint32_t frame_payload_size)
{
const uint64_t offset = static_cast<uint64_t>(frame_index) * frame_payload_size;
if (offset >= file.size()) {
return {};
}
const uint64_t remain = file.size() - offset;
const uint64_t copy_len = std::min<uint64_t>(remain, frame_payload_size);
return std::vector<unsigned char>(
file.begin() + static_cast<std::ptrdiff_t>(offset),
file.begin() + static_cast<std::ptrdiff_t>(offset + copy_len));
}
/**
* @brief 装置升级参数初始化
* @param file 升级程序文件
* @param frame_payload_size 单帧数据长
* @return 是否需要升级
*/
bool ClientContext::prepare_upgrade_task(const std::vector<unsigned char>& file, uint32_t frame_payload_size)
{
if (file.empty() || frame_payload_size == 0) {
return false;
}
std::lock_guard<std::mutex> lock(upgrade_mutex_);
upgrade_task_.file_data = file;
upgrade_task_.file_size = static_cast<uint32_t>(file.size());
upgrade_task_.file_crc = CalcNormalCrc32_Char(file, 0x04C11DB7u);
upgrade_task_.frame_payload_size = frame_payload_size;
upgrade_task_.total_frames =
static_cast<uint32_t>((file.size() + frame_payload_size - 1) / frame_payload_size);
upgrade_task_.next_frame_index = 0;
upgrade_task_.active = (upgrade_task_.total_frames > 0);
return upgrade_task_.active;
}
/**
* @brief 生成升级传输的下一帧报文
* @param out_packet 升级报文
* @param finished 是否结束
* @return 是否继续
*/
bool ClientContext::build_next_upgrade_packet(std::vector<unsigned char>& out_packet, bool& finished)
{
std::lock_guard<std::mutex> lock(upgrade_mutex_);
finished = false;
out_packet.clear();
if (!upgrade_task_.active) {
return false;
}
if (upgrade_task_.next_frame_index >= upgrade_task_.total_frames) {
finished = true;
upgrade_task_.active = false;
return false;
}
std::vector<unsigned char> frame_data =
slice_frame_data(upgrade_task_.file_data,
upgrade_task_.next_frame_index,
upgrade_task_.frame_payload_size);
if (frame_data.empty()) {
upgrade_task_.active = false;
return false;
}
out_packet = generate_upgrade_start_message(
frame_data,
upgrade_task_.next_frame_index, // 0-based内部会 +1
upgrade_task_.file_size,
upgrade_task_.total_frames,
upgrade_task_.file_crc
);
++upgrade_task_.next_frame_index;
if (upgrade_task_.next_frame_index >= upgrade_task_.total_frames) {
finished = true;
}
return true;
}
/**
* @brief 获取当前升级的当前帧和总帧数
* @param current_frame_index 当前帧
* @param total_frames 总帧数
* @return 是否正常
*/
bool ClientContext::get_upgrade_progress(uint32_t& current_frame_index, uint32_t& total_frames) const
{
std::lock_guard<std::mutex> lock(upgrade_mutex_);
if (!upgrade_task_.active) {
current_frame_index = 0;
total_frames = 0;
return false;
}
current_frame_index = upgrade_task_.next_frame_index;
total_frames = upgrade_task_.total_frames;
return true;
}
void ClientContext::clear_upgrade_task()
{
std::lock_guard<std::mutex> lock(upgrade_mutex_);
upgrade_task_ = UpgradeTask{};
}
bool ClientContext::has_active_upgrade_task() const
{
std::lock_guard<std::mutex> lock(upgrade_mutex_);
return upgrade_task_.active;
}
// 版本比较函数的辅助函数:分割字符串并转换为整数向量
std::vector<int> splitVersionString(const std::string& versionStr) {
std::vector<int> segments;
@@ -1744,8 +1919,8 @@ bool ClientManager::set_preupgrade_action_to_device(const std::string& identifie
if (ctx->device_info.device_id == identifier ||
ctx->device_info.mac == identifier)
{
//设置用于校验的预升级文件
ctx->set_preupgrade_filepath(path);
//设置用于校验的预升级文件 校验采用默认生成的文件 暂时不使用
//ctx->set_preupgrade_filepath(path);
// 生成预升级报文
auto packet = generate_preupgrade_message();
@@ -1763,6 +1938,111 @@ bool ClientManager::set_preupgrade_action_to_device(const std::string& identifie
return false; // 设备未找到
}
/**
* @brief 装置升级动作 发送初始帧
* @param file 升级程序文件
* @param sin_length 上送单帧长度
* @return 发送结果
*/
bool ClientManager::send_upgrade_action_to_device(const std::string& identifier, const std::vector<unsigned char>& file,int sin_length) {
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) {
//此处计算文件总大小将参数程序文件分割成依照单帧长度的多组文件计算文件crc计算保存总帧数保存当前帧计数
//之后重新写一个ClientManager的函数用于将之前计算出的参数验证正常后依次自动生成报文并执行不要直接在这里执行因为后续会在别的地方调用防止需要一直获取所有参数再生成报文直接打包方便调用。
// 1. 先准备升级任务
if (!ctx->prepare_upgrade_task(file, static_cast<uint32_t>(sin_length))) {
return false;
}
// 2. 生成首帧升级报文
std::vector<unsigned char> first_packet;
bool finished = false;
if (!ctx->build_next_upgrade_packet(first_packet, finished) || first_packet.empty()) {
ctx->clear_upgrade_task();
return false;
}
// 添加动作到队列 (状态: 读取文件目录)
ctx->add_action(DeviceState::SET_UPGRADE, first_packet);
// 如果当前空闲则立即执行
if (ctx->current_state_ == DeviceState::IDLE) {
ctx->process_next_action();
}
return true; // 成功添加
}
}
return false;
}
/**
* @brief 装置升级动作 查询并生成下一帧报文
* @param identifier 装置标识device_id 或 mac
* @param current_frame_index 获取当前帧(0-based表示下一次要发送的帧号)
* @param total_frames 获取总帧数
* @param all_sent 是否全部发送完毕
* @param packet 输出的下一帧报文;若已发送完毕则为空
* @return 获取结果
*/
bool ClientManager::try_get_next_upgrade_packet_to_device(const std::string& identifier,
uint32_t& current_frame_index,
uint32_t& total_frames,
bool& all_sent,
std::vector<unsigned char>& packet)
{
current_frame_index = 0;
total_frames = 0;
all_sent = false;
packet.clear();
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)
{
// 先获取当前进度
if (!ctx->get_upgrade_progress(current_frame_index, total_frames)) {
return false; // 没有活动升级任务
}
// 如果当前帧号已经到总帧数,说明全部发送完毕
if (current_frame_index >= total_frames) {
all_sent = true;
return true;
}
// 还有帧未发送,则只生成下一帧报文,不在这里直接发送
bool finished = false;
if (!ctx->build_next_upgrade_packet(packet, finished)) {
packet.clear();
return false;
}
// build_next_upgrade_packet 之后next_frame_index 已经自增
// 这里再更新一次进度给外部
ctx->get_upgrade_progress(current_frame_index, total_frames);
if (current_frame_index >= total_frames) {
all_sent = true;
}
return true;
}
}
return false; // 未找到设备
}
/**
* @brief 生成装置控制命令报文
* @param type 命令类型 1-装置复位2-启动录波3-启动200ms数据记录4-启动3秒数据记录
@@ -1814,10 +2094,10 @@ bool ClientManager::read_eventlog_action_to_device(const std::string& identifier
ctx->device_info.mac == identifier)
{
ctx->event_lineNo = monitorPoint;
// 生成定值描述报文
// 生成补招报文
auto packet = generate_recallevent_message(Time1, Time2, eventType, monitorPoint);
// 添加动作到队列 (状态: 读取文件目录)
// 添加动作到队列 (状态: 补招事件)
ctx->add_action(DeviceState::READING_EVENTLOG, packet);
// 如果当前空闲则立即执行

View File

@@ -67,6 +67,7 @@ enum class DeviceState {
READING_STATSFILE, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
SET_CTRL, // <20><><EFBFBD><EFBFBD>װ<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SET_PREUPGRADE, // װ<><D7B0>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD>У<EFBFBD><D0A3>
SET_UPGRADE, // װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20>ɸ<EFBFBD><C9B8><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>Ӹ<EFBFBD><D3B8><EFBFBD>״̬
CUSTOM_ACTION // <20>Զ<EFBFBD><D4B6><EFBFBD><E5B6AF>
};
@@ -145,6 +146,44 @@ public:
bool event_add_stat_packet(const std::vector<unsigned char>& packet, int current_packet, int total_packets);//<2F>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<StatPacket> event_get_and_clear_stat_packets();//<2F>¼<EFBFBD><C2BC><EFBFBD>־ȡ<D6BE><C8A1><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>
void event_clear_stat_cache();//<2F>¼<EFBFBD><C2BC><EFBFBD>־<EFBFBD><D6BE><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>--------------------------------------------------
struct UpgradeTask
{
std::vector<unsigned char> file_data; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
uint32_t file_size = 0; // <20>ļ<EFBFBD><C4BC>ܴ<EFBFBD>С
uint32_t file_crc = 0; // <20>ļ<EFBFBD>CRC32
uint32_t frame_payload_size = 0; // <20><>֡<EFBFBD><D6A1><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
uint32_t total_frames = 0; // <20><>֡<EFBFBD><D6A1>
uint32_t next_frame_index = 0; // <20><>һ<EFBFBD><D2BB>Ҫ<EFBFBD><D2AA><EFBFBD>͵<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>(0-based)
bool active = false; // <20><>ǰ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
};
mutable std::mutex upgrade_mutex_;
UpgradeTask upgrade_task_;
/**
* @brief װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
* @param file <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
* @param frame_payload_size <20><>֡<EFBFBD><D6A1><EFBFBD>ݳ<EFBFBD>
* @return <20>Ƿ<EFBFBD><C7B7><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>
*/
bool prepare_upgrade_task(const std::vector<unsigned char>& file, uint32_t frame_payload_size);
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ֡<D2BB><D6A1><EFBFBD><EFBFBD>
* @param out_packet <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param finished <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
* @return <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
*/
bool build_next_upgrade_packet(std::vector<unsigned char>& out_packet, bool& finished);
void clear_upgrade_task();
bool has_active_upgrade_task() const;
/**
* @brief <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>ǰ֡<C7B0><D6A1><EFBFBD><EFBFBD>֡<EFBFBD><D6A1>
* @param current_frame_index <20><>ǰ֡
* @param total_frames <20><>֡<EFBFBD><D6A1>
* @return <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
*/
bool get_upgrade_progress(uint32_t& current_frame_index, uint32_t& total_frames) const;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>--------------------------------------------------
// ͳ<><CDB3><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD>
struct PointFloatCache {
@@ -468,9 +507,30 @@ public:
/**
* @brief <20><><EFBFBD><EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><E9B1A8>
* @param path ԤУ<D4A4><D0A3><EFBFBD>ļ<EFBFBD>·<EFBFBD><C2B7>
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return <20><><EFBFBD>ͽ<EFBFBD><EFBFBD><EFBFBD>
*/
bool set_preupgrade_action_to_device(const std::string& identifier, const std::string& path);
/**
* @brief װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ͳ<EFBFBD>ʼ֡
* @param file <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
* @param sin_length <20><><EFBFBD>͵<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
* @return <20><><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD>
*/
bool send_upgrade_action_to_device(const std::string& identifier, const std::vector<unsigned char>& file, int sin_length);
/**
* @brief װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ֡<D2BB><D6A1><EFBFBD><EFBFBD>
* @param identifier װ<>ñ<EFBFBD>ʶ<EFBFBD><CAB6>device_id <20><> mac<61><63>
* @param current_frame_index <20><>ȡ<EFBFBD><C8A1>ǰ֡(0-based<65><64><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>һ<EFBFBD><D2BB>Ҫ<EFBFBD><D2AA><EFBFBD>͵<EFBFBD>֡<EFBFBD><D6A1>)
* @param total_frames <20><>ȡ<EFBFBD><C8A1>֡<EFBFBD><D6A1>
* @param all_sent <20>Ƿ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param packet <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ֡<D2BB><D6A1><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ѷ<EFBFBD><D1B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
* @return <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
*/
bool try_get_next_upgrade_packet_to_device(const std::string& identifier,
uint32_t& current_frame_index,
uint32_t& total_frames,
bool& all_sent,
std::vector<unsigned char>& packet);
//<2F><EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
bool get_dev_status(const std::string& identifier);

View File

@@ -132,6 +132,21 @@ std::vector<uint8_t> GeneratePreUpgradeFileFromLengthBytes(uint32_t fileLen)
return fileData;
}
// 读取文件为二进制字节数组
std::vector<unsigned char> read_file_as_bytes(const std::string& file_path)
{
std::ifstream file(file_path, std::ios::binary);
if (!file.is_open()) {
std::cerr << "打开文件失败: " << file_path << std::endl;
return {};
}
return std::vector<unsigned char>(
std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>()
);
}
//消息处理逻辑
void process_received_message(string mac, string id,const char* data, size_t length) {
// 实际的消息处理逻辑
@@ -160,9 +175,11 @@ void process_received_message(string mac, string id,const char* data, size_t len
ClientManager::instance().set_cloud_status(id, 1); //设置了云前置登录状态为已登录
ClientManager::instance().read_devversion_action_to_device(id);//主动触发,读取装置版本配置信息,仅在装置登录后执行一次,当前获取版本信息确认对时报文结构。
ClientManager::instance().set_preupgrade_action_to_device(id, "");//装置升级预校验流程 校验文件自动生成 当前填空
//ClientManager::instance().set_ctrl_action_to_device(id,0x01,0x00);//尝试装置重启指令!第一步校验
//ClientManager::instance().set_ctrl_action_to_device(id, 0x01, 0x01);//尝试装置重启指令!校验完毕后尝试执行重启指令
//std::vector<unsigned char> file_data = read_file_as_bytes("pqs_arm2.bin");
//ClientManager::instance().send_upgrade_action_to_device(id, file_data,10240);//默认单帧最大10240
//ClientManager::instance().set_preupgrade_action_to_device(id, "");//装置升级预校验流程 校验文件自动生成 当前填空
//ClientManager::instance().set_ctrl_action_to_device(id,0x01,0x00);//尝试装置重启指令!
//ClientManager::instance().get_dev_status(id);//设备在线情况判断 ture在线 false离线
//ClientManager::instance().set_real_state_count("D002", 1,1);//登录后测试实时
@@ -2321,8 +2338,10 @@ void process_received_message(string mac, string id,const char* data, size_t len
if (udata[9] == 0x01) {
//当前仅检查0x01复位指令其余控制指令全部依照不合法处理
std::cout << "***ctrl do next" << mac << std::endl;
//控制命令校验合法,调整为空闲,处理后续工作。
ClientManager::instance().change_device_state(id, DeviceState::IDLE);
//校验完毕后直接准备重启
auto packet = generate_control_message(0x01, 0x01);
ClientManager::instance().change_device_state(id, DeviceState::SET_CTRL, packet);
}
else {
std::cout << "***ctrl fail" << mac << std::endl;
@@ -2438,6 +2457,95 @@ void process_received_message(string mac, string id,const char* data, size_t len
}
break;
case DeviceState::SET_UPGRADE:
//装置升级
if (udata[8] == static_cast<unsigned char>(MsgResponseType::Response_Upgrade)) {
//接收到最终的升级验证报文
if (udata[9] == 0x01) {
//接收文件成功,下发开始升级指令
//事件不插入队列,直接修改装置最新状态,防止外部其他指令打断更新流程
std::cout << "*** upgrade 0x01 do next ***!" << mac << std::endl;
auto sendbuff = generate_upgrade_end_message();
ClientManager::instance().change_device_state(id, DeviceState::SET_UPGRADE, sendbuff);
}
else if (udata[9] == 0x02) {
//接收文件错误!
std::cout << "*** upgrade 0x02 fail ***!" << mac << std::endl;
// 升级流程失败,调整为空闲状态,处理下一项工作。
ClientManager::instance().change_device_state(id, DeviceState::IDLE);
}
else if (udata[9] == 0x55) {
//升级流程成功,等候装置重启
std::cout << "*** upgrade 0x55 success ***!" << mac << std::endl;
// 升级流程失败,调整为空闲状态,处理下一项工作。
ClientManager::instance().change_device_state(id, DeviceState::IDLE);
}
else if (udata[9] == 0xAA) {
// 升级流程失败!
std::cout << "*** upgrade 0xAA fail ***!" << mac << std::endl;
// 升级流程失败,调整为空闲状态,处理下一项工作。
ClientManager::instance().change_device_state(id, DeviceState::IDLE);
}
else {
std::cout << "*** upgrade ?? error ***!" << mac << std::endl;
// 升级流程失败,调整为空闲状态,处理下一项工作。
ClientManager::instance().change_device_state(id, DeviceState::IDLE);
}
}
else if (udata[8] == static_cast<unsigned char>(MsgResponseType::Response_NewACK)) {
uint32_t current_frame_index = 0;//当前帧
uint32_t total_frames = 0;//总帧数
bool all_sent = false;
std::vector<unsigned char> packet;//报文流
bool ok = ClientManager::instance().try_get_next_upgrade_packet_to_device(
id,
current_frame_index,
total_frames,
all_sent,
packet
);
if (!ok) {
//组装后续升级报文时出现异常,无法发送后续帧文件
std::cout << "获取下一帧失败\n";
ClientManager::instance().change_device_state(id, DeviceState::IDLE);
}
else if (!packet.empty()) {
// 只要拿到了报文,就先发送
std::cout << "已生成并发送下一帧,当前进度: "
<< current_frame_index << "/" << total_frames << std::endl;
ClientManager::instance().change_device_state(id, DeviceState::SET_UPGRADE, packet);
if (all_sent) {
std::cout << "最后一帧已发出,后续等待装置消息\n";
}
}
else if (all_sent) {
// 没有新报文可发,说明之前已经全部发完
std::cout << "所有帧都已发送完毕,等待装置消息\n";
return;
}
else {
// 理论上不该走到这里,防御处理
std::cout << "未获取到有效升级报文\n";
ClientManager::instance().change_device_state(id, DeviceState::IDLE);
}
}
else if (udata[8] == static_cast<unsigned char>(MsgResponseType::Response_NewNACK)) {
std::cout << "*** upgrade 0x41 fail ***!" << mac << std::endl;
// 升级流程失败,调整为空闲状态,处理下一项工作。
ClientManager::instance().change_device_state(id, DeviceState::IDLE);
}
else {
// 装置答非所问异常
std::cout << "*** upgrade ?? fail ***!" << mac << std::endl;
// 升级流程失败,调整为空闲状态,处理下一项工作。
ClientManager::instance().change_device_state(id, DeviceState::IDLE);
}
break;
case DeviceState::CUSTOM_ACTION:
// 自定义动作状态
std::cout << "CUSTOM_ACTION state: Processing custom response from " << mac << std::endl;

View File

@@ -380,7 +380,7 @@ int main(int argc ,char** argv) {//
std::cerr << "process param error,exit" << std::endl;
return 1;
}
//init_daemon();
init_daemon();
srand(time(NULL)); // <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><>ʼ<EFBFBD><CABC><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD>