修改了装置重启方式,去除了外部调用的校验流程,现在直接在内部自动完成。
新增了装置升级的正式流程。
This commit is contained in:
@@ -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ֵ)
|
||||
|
||||
@@ -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ֵ)
|
||||
|
||||
@@ -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);
|
||||
|
||||
// 如果当前空闲则立即执行
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);//登录后测试实时
|
||||
@@ -2310,8 +2327,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;
|
||||
@@ -2427,6 +2446,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;
|
||||
|
||||
Reference in New Issue
Block a user