Files
gcs-nf/App/ToolsUI/Payload/dev/flare_device.cpp
T
2026-06-15 08:18:27 +08:00

856 lines
30 KiB
C++

#include "flare_device.h"
#include <QtGlobal>
#include <QDebug>
#include <QBitArray>
#include <QDataStream>
#include <QMetaType>
namespace payload_protocol {
// FlareUplinkData 实现
FlareUplinkData::FlareUplinkData()
: command_type(FlareCommandType::SAFETY_RELEASE) {
device_permissions.reserved_bit = 0;
device_permissions.device_permissions = 0;
command_data.fill(0, 5);
}
QByteArray FlareUplinkData::serialize() const {
QByteArray data(FLARE_UPLINK_FRAME_LENGTH, 0);
// 设置帧头
data[0] = static_cast<char>(FLARE_UPLINK_HEADER1);
data[1] = static_cast<char>(FLARE_UPLINK_HEADER2);
// 指令类型
data[2] = static_cast<char>(static_cast<quint8>(command_type));
// 设备权限(16位,小端序)
quint16 permissions = (static_cast<quint16>(device_permissions.reserved_bit) << 15) |
(device_permissions.device_permissions & 0x7FFF);
data[3] = static_cast<char>(permissions & 0xFF);
data[4] = static_cast<char>((permissions >> 8) & 0xFF);
// 指令数据(5字节)
for (qint32 i = 0; i < command_data.size() && i < 5; ++i) {
data[5 + i] = command_data.at(i);
}
// 计算双校验(前10字节参与校验计算)
quint8 additive_checksum = 0;
quint8 xor_checksum = 0;
for (qint32 i = 0; i < FLARE_UPLINK_FRAME_LENGTH - 2; ++i) {
additive_checksum += static_cast<quint8>(data.at(i));
xor_checksum ^= static_cast<quint8>(data.at(i));
}
data[10] = static_cast<char>(additive_checksum); // 和校验
data[11] = static_cast<char>(xor_checksum); // 异或校验
return data;
}
bool FlareUplinkData::deserialize(const QByteArray& data) {
if (data.size() < FLARE_UPLINK_FRAME_LENGTH) {
return false;
}
// 验证帧头
if (static_cast<quint8>(data[0]) != FLARE_UPLINK_HEADER1 ||
static_cast<quint8>(data[1]) != FLARE_UPLINK_HEADER2) {
return false;
}
// 验证校验和
if (!validateChecksum(data)) {
return false;
}
// 解析指令类型
command_type = static_cast<FlareCommandType>(static_cast<quint8>(data[2]));
// 解析设备权限(16位,小端序)
quint16 permissions = static_cast<quint16>(static_cast<quint8>(data[3])) |
(static_cast<quint16>(static_cast<quint8>(data[4])) << 8);
device_permissions.reserved_bit = (permissions >> 15) & 0x01;
device_permissions.device_permissions = permissions & 0x7FFF;
// 解析指令数据
command_data.resize(5);
for (qint32 i = 0; i < 5; ++i) {
if (5 + i < data.size() - 2) { // 排除校验字节
command_data[i] = data[5 + i];
} else {
command_data[i] = 0;
}
}
return true;
}
bool FlareUplinkData::validateChecksum(const QByteArray& data) const {
if (data.size() < FLARE_UPLINK_FRAME_LENGTH) {
return false;
}
quint8 additive_checksum = 0;
quint8 xor_checksum = 0;
// 前10字节参与校验计算
for (qint32 i = 0; i < FLARE_UPLINK_FRAME_LENGTH - 2; ++i) {
additive_checksum += static_cast<quint8>(data.at(i));
xor_checksum ^= static_cast<quint8>(data.at(i));
}
return (additive_checksum == static_cast<quint8>(data.at(10))) &&
(xor_checksum == static_cast<quint8>(data.at(11)));
}
void FlareUplinkData::setDevicePermissions(quint16 permissions) {
device_permissions.device_permissions = permissions & 0x7FFF;
device_permissions.reserved_bit = 0; // 保留位始终为0
}
bool FlareUplinkData::hasDevicePermission(quint8 device_id) const {
if (device_id < 1 || device_id > MAX_DEVICE_ID) {
return false;
}
quint16 mask = 1 << (device_id - 1); // 设备ID 1对应bit0,设备ID 15对应bit14
return (device_permissions.device_permissions & mask) != 0;
}
void FlareUplinkData::addDevicePermission(quint8 device_id) {
if (device_id >= 1 && device_id <= MAX_DEVICE_ID) {
quint16 mask = 1 << (device_id - 1);
device_permissions.device_permissions |= mask;
}
}
void FlareUplinkData::removeDevicePermission(quint8 device_id) {
if (device_id >= 1 && device_id <= MAX_DEVICE_ID) {
quint16 mask = 1 << (device_id - 1);
device_permissions.device_permissions &= ~mask;
}
}
quint16 FlareUplinkData::getDevicePermissions() const {
return device_permissions.device_permissions;
}
// SafetyReleaseCommand 实现
SafetyReleaseCommand::SafetyReleaseCommand()
: safety_status(SAFETY_OFF) {
command_type = FlareCommandType::SAFETY_RELEASE;
command_data.fill(0, 5);
command_data[0] = static_cast<char>(safety_status);
}
void SafetyReleaseCommand::setSafetyStatus(bool on) {
safety_status = on ? SAFETY_ON : SAFETY_OFF;
command_data[0] = static_cast<char>(safety_status);
}
bool SafetyReleaseCommand::isSafetyOn() const {
return safety_status == SAFETY_ON;
}
bool SafetyReleaseCommand::isSafetyOff() const {
return safety_status == SAFETY_OFF;
}
QByteArray SafetyReleaseCommand::serialize() const {
FlareUplinkData base_data = *this;
return base_data.serialize();
}
bool SafetyReleaseCommand::deserialize(const QByteArray& data) {
if (!FlareUplinkData::deserialize(data)) {
return false;
}
if (command_data.size() >= 1) {
safety_status = static_cast<quint8>(command_data[0]);
} else {
safety_status = SAFETY_OFF;
}
return true;
}
// ManualTriggerCommand 实现
ManualTriggerCommand::ManualTriggerCommand()
: release_interval(0), channel_selection(0) {
command_type = FlareCommandType::MANUAL_TRIGGER;
command_data.fill(0, 5);
// 设置默认参数
command_data[0] = 0; // 投放间隔低字节
command_data[1] = 0; // 投放间隔高字节
command_data[2] = 0; // 通道选择字节1
command_data[3] = 0; // 通道选择字节2
command_data[4] = 0; // 通道选择字节3
}
void ManualTriggerCommand::setReleaseInterval(quint16 interval_ms) {
release_interval = interval_ms;
command_data[0] = static_cast<char>(release_interval & 0xFF);
command_data[1] = static_cast<char>((release_interval >> 8) & 0xFF);
}
void ManualTriggerCommand::setChannelSelection(quint32 channel_mask) {
channel_selection = channel_mask & 0x00FFFFFF; // 24位掩码
command_data[2] = static_cast<char>(channel_selection & 0xFF);
command_data[3] = static_cast<char>((channel_selection >> 8) & 0xFF);
command_data[4] = static_cast<char>((channel_selection >> 16) & 0xFF);
}
void ManualTriggerCommand::selectChannel(quint8 channel) {
if (channel >= 1 && channel <= MAX_FLARE_CHANNELS) {
channel_selection |= (1 << (channel - 1));
setChannelSelection(channel_selection);
}
}
void ManualTriggerCommand::deselectChannel(quint8 channel) {
if (channel >= 1 && channel <= MAX_FLARE_CHANNELS) {
channel_selection &= ~(1 << (channel - 1));
setChannelSelection(channel_selection);
}
}
bool ManualTriggerCommand::isChannelSelected(quint8 channel) const {
if (channel < 1 || channel > MAX_FLARE_CHANNELS) {
return false;
}
return (channel_selection & (1 << (channel - 1))) != 0;
}
quint8 ManualTriggerCommand::getSelectedChannelCount() const {
quint32 mask = channel_selection;
quint8 count = 0;
while (mask) {
count += (mask & 1);
mask >>= 1;
}
return count;
}
QByteArray ManualTriggerCommand::serialize() const {
FlareUplinkData base_data = *this;
return base_data.serialize();
}
bool ManualTriggerCommand::deserialize(const QByteArray& data) {
if (!FlareUplinkData::deserialize(data)) {
return false;
}
// 解析投放间隔时间(2字节,小端序)
if (command_data.size() >= 2) {
release_interval = static_cast<quint16>(static_cast<quint8>(command_data[0])) |
(static_cast<quint16>(static_cast<quint8>(command_data[1])) << 8);
} else {
release_interval = 0;
}
// 解析通道选择(3字节,小端序)
if (command_data.size() >= 5) {
channel_selection = static_cast<quint32>(static_cast<quint8>(command_data[2])) |
(static_cast<quint32>(static_cast<quint8>(command_data[3])) << 8) |
(static_cast<quint32>(static_cast<quint8>(command_data[4])) << 16);
} else {
channel_selection = 0;
}
return true;
}
// SelfTestCommand 实现
SelfTestCommand::SelfTestCommand() {
command_type = FlareCommandType::SELF_TEST;
command_data.fill(0, 5);
}
QByteArray SelfTestCommand::serialize() const {
FlareUplinkData base_data = *this;
return base_data.serialize();
}
bool SelfTestCommand::deserialize(const QByteArray& data) {
return FlareUplinkData::deserialize(data);
}
// FlareDownlinkData 实现
FlareDownlinkData::FlareDownlinkData()
: message_type(FlareDownlinkType::STATUS_AUTO),
current_device_id(1),
hardware_channel_count(24),
work_status(FlareWorkStatus::STANDBY),
mission_status(0),
self_test_status(SelfTestStatus::NOT_TESTED),
flare_status(0x00FFFFFF), // 默认所有弹正常
channel_loaded_status(0x00FFFFFF), // 默认所有通道有弹
response_frame_number(0) {
status_byte.reserved_bits = 0;
status_byte.safety_status = SafetyStatus::OFF;
status_byte.power_status = PowerVoltageStatus::NORMAL;
status_byte.igniter_status = IgniterStatus::OFF;
}
QByteArray FlareDownlinkData::serialize() const {
QByteArray data(FLARE_DOWNLINK_FRAME_LENGTH, 0);
// 设置帧头
data[0] = static_cast<char>(FLARE_DOWNLINK_HEADER1);
data[1] = static_cast<char>(FLARE_DOWNLINK_HEADER2);
// 报文类型
data[2] = static_cast<char>(static_cast<quint8>(message_type));
// 当前设备ID
data[3] = static_cast<char>(current_device_id);
// 设备硬件通道数量
data[4] = static_cast<char>(hardware_channel_count);
// 工作状态
data[5] = static_cast<char>(static_cast<quint8>(work_status));
// 状态字节
data[6] = static_cast<char>((status_byte.reserved_bits << 5) |
(static_cast<quint8>(status_byte.safety_status) << 4) |
(static_cast<quint8>(status_byte.power_status) << 2) |
(static_cast<quint8>(status_byte.igniter_status)));
// 任务状态(2字节,小端序)
data[7] = static_cast<char>(mission_status & 0xFF);
data[8] = static_cast<char>((mission_status >> 8) & 0xFF);
// 自检状态
data[9] = static_cast<char>(static_cast<quint8>(self_test_status));
// 弹状态(3字节,小端序)
data[10] = static_cast<char>(flare_status & 0xFF);
data[11] = static_cast<char>((flare_status >> 8) & 0xFF);
data[12] = static_cast<char>((flare_status >> 16) & 0xFF);
// 通道有弹状态(3字节,小端序)
data[13] = static_cast<char>(channel_loaded_status & 0xFF);
data[14] = static_cast<char>((channel_loaded_status >> 8) & 0xFF);
data[15] = static_cast<char>((channel_loaded_status >> 16) & 0xFF);
// 响应帧序号(2字节,小端序)
data[16] = static_cast<char>(response_frame_number & 0xFF);
data[17] = static_cast<char>((response_frame_number >> 8) & 0xFF);
// 计算双校验(前18字节参与校验计算)
quint8 additive_checksum = 0;
quint8 xor_checksum = 0;
for (qint32 i = 0; i < FLARE_DOWNLINK_FRAME_LENGTH - 2; ++i) {
additive_checksum += static_cast<quint8>(data.at(i));
xor_checksum ^= static_cast<quint8>(data.at(i));
}
data[18] = static_cast<char>(additive_checksum); // 和校验
data[19] = static_cast<char>(xor_checksum); // 异或校验
return data;
}
bool FlareDownlinkData::deserialize(const QByteArray& data) {
if (data.size() < FLARE_DOWNLINK_FRAME_LENGTH) {
return false;
}
// 验证帧头
if (static_cast<quint8>(data[0]) != FLARE_DOWNLINK_HEADER1 ||
static_cast<quint8>(data[1]) != FLARE_DOWNLINK_HEADER2) {
return false;
}
// 验证校验和
if (!validateChecksum(data)) {
return false;
}
// 解析报文类型
message_type = static_cast<FlareDownlinkType>(static_cast<quint8>(data[2]));
// 解析当前设备ID
current_device_id = static_cast<quint8>(data[3]);
// 解析设备硬件通道数量
hardware_channel_count = static_cast<quint8>(data[4]);
// 解析工作状态
work_status = static_cast<FlareWorkStatus>(static_cast<quint8>(data[5]));
// 解析状态字节
quint8 status_byte_value = static_cast<quint8>(data[6]);
status_byte.reserved_bits = (status_byte_value >> 5) & 0x07;
status_byte.safety_status = static_cast<SafetyStatus>((status_byte_value >> 4) & 0x01);
status_byte.power_status = static_cast<PowerVoltageStatus>((status_byte_value >> 2) & 0x03);
status_byte.igniter_status = static_cast<IgniterStatus>(status_byte_value & 0x03);
// 解析任务状态(2字节,小端序)
mission_status = static_cast<quint16>(static_cast<quint8>(data[7])) |
(static_cast<quint16>(static_cast<quint8>(data[8])) << 8);
// 解析自检状态
self_test_status = static_cast<SelfTestStatus>(static_cast<quint8>(data[9]));
// 解析弹状态(3字节,小端序)
flare_status = static_cast<quint32>(static_cast<quint8>(data[10])) |
(static_cast<quint32>(static_cast<quint8>(data[11])) << 8) |
(static_cast<quint32>(static_cast<quint8>(data[12])) << 16);
// 解析通道有弹状态(3字节,小端序)
channel_loaded_status = static_cast<quint32>(static_cast<quint8>(data[13])) |
(static_cast<quint32>(static_cast<quint8>(data[14])) << 8) |
(static_cast<quint32>(static_cast<quint8>(data[15])) << 16);
// 解析响应帧序号(2字节,小端序)
response_frame_number = static_cast<quint16>(static_cast<quint8>(data[16])) |
(static_cast<quint16>(static_cast<quint8>(data[17])) << 8);
return true;
}
bool FlareDownlinkData::validateChecksum(const QByteArray& data) const {
if (data.size() < FLARE_DOWNLINK_FRAME_LENGTH) {
return false;
}
quint8 additive_checksum = 0;
quint8 xor_checksum = 0;
// 前18字节参与校验计算
for (qint32 i = 0; i < FLARE_DOWNLINK_FRAME_LENGTH - 2; ++i) {
additive_checksum += static_cast<quint8>(data.at(i));
xor_checksum ^= static_cast<quint8>(data.at(i));
}
return (additive_checksum == static_cast<quint8>(data.at(18))) &&
(xor_checksum == static_cast<quint8>(data.at(19)));
}
bool FlareDownlinkData::isMissionExecuted(quint8 mission_id) const {
if (mission_id < 1 || mission_id > 15) {
return false;
}
quint16 mask = 1 << (mission_id - 1); // 任务1对应bit0,任务15对应bit14
return (mission_status & mask) != 0;
}
void FlareDownlinkData::setMissionExecuted(quint8 mission_id, bool executed) {
if (mission_id >= 1 && mission_id <= 15) {
quint16 mask = 1 << (mission_id - 1);
if (executed) {
mission_status |= mask;
} else {
mission_status &= ~mask;
}
}
}
bool FlareDownlinkData::isFlareNormal(quint8 flare_id) const {
if (flare_id < 1 || flare_id > MAX_FLARE_CHANNELS) {
return false;
}
quint32 mask = 1 << (flare_id - 1); // 弹1对应bit0,弹24对应bit23
return (flare_status & mask) != 0;
}
void FlareDownlinkData::setFlareStatus(quint8 flare_id, bool normal) {
if (flare_id >= 1 && flare_id <= MAX_FLARE_CHANNELS) {
quint32 mask = 1 << (flare_id - 1);
if (normal) {
flare_status |= mask;
} else {
flare_status &= ~mask;
}
}
}
bool FlareDownlinkData::isChannelLoaded(quint8 channel_id) const {
if (channel_id < 1 || channel_id > MAX_FLARE_CHANNELS) {
return false;
}
quint32 mask = 1 << (channel_id - 1); // 通道1对应bit0,通道24对应bit23
return (channel_loaded_status & mask) != 0;
}
void FlareDownlinkData::setChannelLoaded(quint8 channel_id, bool loaded) {
if (channel_id >= 1 && channel_id <= MAX_FLARE_CHANNELS) {
quint32 mask = 1 << (channel_id - 1);
if (loaded) {
channel_loaded_status |= mask;
} else {
channel_loaded_status &= ~mask;
}
}
}
QString FlareDownlinkData::getWorkStatusDescription() const {
switch (work_status) {
case FlareWorkStatus::STANDBY: return QStringLiteral("待机");
case FlareWorkStatus::MISSION_1: return QStringLiteral("正在执行任务1");
case FlareWorkStatus::MISSION_2: return QStringLiteral("正在执行任务2");
case FlareWorkStatus::MISSION_3: return QStringLiteral("正在执行任务3");
case FlareWorkStatus::MISSION_4: return QStringLiteral("正在执行任务4");
case FlareWorkStatus::MISSION_5: return QStringLiteral("正在执行任务5");
case FlareWorkStatus::MISSION_6: return QStringLiteral("正在执行任务6");
case FlareWorkStatus::MISSION_7: return QStringLiteral("正在执行任务7");
case FlareWorkStatus::MISSION_8: return QStringLiteral("正在执行任务8");
case FlareWorkStatus::MISSION_9: return QStringLiteral("正在执行任务9");
case FlareWorkStatus::MISSION_10: return QStringLiteral("正在执行任务10");
case FlareWorkStatus::MISSION_11: return QStringLiteral("正在执行任务11");
case FlareWorkStatus::MISSION_12: return QStringLiteral("正在执行任务12");
case FlareWorkStatus::MISSION_13: return QStringLiteral("正在执行任务13");
case FlareWorkStatus::MISSION_14: return QStringLiteral("正在执行任务14");
case FlareWorkStatus::MISSION_15: return QStringLiteral("正在执行任务15");
case FlareWorkStatus::SELF_TESTING: return QStringLiteral("正在执行设备自检");
case FlareWorkStatus::MANUAL_TRIGGERING: return QStringLiteral("正在执行手动触发");
default: return QStringLiteral("未知状态");
}
}
QString FlareDownlinkData::getStatusSummary() const {
QString summary;
summary += QStringLiteral("设备ID: %1\n").arg(current_device_id);
summary += QStringLiteral("硬件通道数: %1\n").arg(hardware_channel_count);
summary += QStringLiteral("工作状态: %1\n").arg(getWorkStatusDescription());
summary += QStringLiteral("保险状态: %1\n").arg(status_byte.safety_status == SafetyStatus::ON ? "" : "");
summary += QStringLiteral("电源状态: %1\n").arg(status_byte.power_status == PowerVoltageStatus::NORMAL ? "正常" : "异常");
summary += QStringLiteral("火工状态: ");
switch (status_byte.igniter_status) {
case IgniterStatus::OFF: summary += QStringLiteral(""); break;
case IgniterStatus::ABNORMAL: summary += QStringLiteral("异常"); break;
case IgniterStatus::ON: summary += QStringLiteral(""); break;
default: summary += QStringLiteral("未知"); break;
}
summary += QStringLiteral("\n");
summary += QStringLiteral("自检状态: ");
switch (self_test_status) {
case SelfTestStatus::NOT_TESTED: summary += QStringLiteral("未自检"); break;
case SelfTestStatus::NORMAL: summary += QStringLiteral("正常"); break;
case SelfTestStatus::ABNORMAL: summary += QStringLiteral("异常"); break;
default: summary += QStringLiteral("未知"); break;
}
summary += QStringLiteral("\n");
summary += QStringLiteral("响应帧序号: %1").arg(response_frame_number);
return summary;
}
// FlareDevice 实现
FlareDevice::FlareDevice(QObject* parent)
: QObject(parent), device_id_(1) {
// 默认设备ID为1
current_safety_status_ = false;
selected_channels_ = 0;
// Register meta types for Qt signal/slot system
qRegisterMetaType<payload_protocol::FlareDownlinkData>();
}
FlareDevice::FlareDevice(quint8 device_id, QObject* parent)
: QObject(parent), device_id_(device_id) {
if (device_id < 1 || device_id > MAX_DEVICE_ID) {
device_id_ = 1; // 无效设备ID时设为1
}
current_safety_status_ = false;
selected_channels_ = 0;
// Register meta types for Qt signal/slot system
qRegisterMetaType<payload_protocol::FlareDownlinkData>();
}
QByteArray FlareDevice::createSafetyReleaseCommand(quint16 device_permissions, bool safety_on) const {
SafetyReleaseCommand command;
command.setDevicePermissions(device_permissions);
command.setSafetyStatus(safety_on);
return command.serialize();
}
QByteArray FlareDevice::createManualTriggerCommand(quint16 device_permissions,
quint16 release_interval,
quint32 channel_selection) const {
ManualTriggerCommand command;
command.setDevicePermissions(device_permissions);
command.setReleaseInterval(release_interval);
command.setChannelSelection(channel_selection);
return command.serialize();
}
QByteArray FlareDevice::createSelfTestCommand(quint16 device_permissions) const {
SelfTestCommand command;
command.setDevicePermissions(device_permissions);
return command.serialize();
}
QByteArray FlareDevice::createMissionTriggerCommand(quint16 device_permissions, quint8 mission_id) const {
FlareUplinkData command;
command.command_type = FlareCommandType::MISSION_TRIGGER;
command.setDevicePermissions(device_permissions);
// 任务触发指令的数据格式:任务ID在第一个字节
command.command_data.fill(0, 5);
if (mission_id >= 1 && mission_id <= 15) {
command.command_data[0] = static_cast<char>(mission_id);
}
return command.serialize();
}
QByteArray FlareDevice::createStatusQueryCommand(quint16 device_permissions) const {
FlareUplinkData command;
command.command_type = FlareCommandType::STATUS_QUERY;
command.setDevicePermissions(device_permissions);
command.command_data.fill(0, 5);
return command.serialize();
}
bool FlareDevice::parseStatusData(const QByteArray& data) {
FlareDownlinkData downlink_data;
if (!downlink_data.deserialize(data)) {
emit errorOccurred(QStringLiteral("无法解析干扰弹设备状态数据"));
return false;
}
// 保存最后状态并处理变化
handleStatusUpdate(downlink_data);
return true;
}
bool FlareDevice::parseStatusData(const QByteArray& data, FlareDownlinkData& downlink_data) const {
return downlink_data.deserialize(data);
}
void FlareDevice::sendSafetyReleaseCommand(quint16 device_permissions, bool safety_on) {
QByteArray command = createSafetyReleaseCommand(device_permissions, safety_on);
emit commandSent(command);
current_safety_status_ = safety_on;
qDebug() << QString("投放保险%1指令已发送").arg(safety_on ? "开启" : "关闭");
}
void FlareDevice::sendManualTriggerCommand(quint16 device_permissions,
quint16 release_interval,
quint32 channel_selection) {
QByteArray command = createManualTriggerCommand(device_permissions, release_interval, channel_selection);
emit commandSent(command);
qDebug() << QString("手动触发指令已发送,间隔时间:%1ms,选择通道:%2")
.arg(release_interval)
.arg(QString::number(channel_selection, 16).toUpper());
}
void FlareDevice::sendSelfTestCommand(quint16 device_permissions) {
QByteArray command = createSelfTestCommand(device_permissions);
emit commandSent(command);
qDebug() << "设备自检指令已发送";
}
void FlareDevice::sendRawCommand(const QByteArray& command_data) {
if (validateUplinkFrameHeader(command_data)) {
emit commandSent(command_data);
} else {
emit errorOccurred(QStringLiteral("无效的干扰弹设备指令格式"));
}
}
bool FlareDevice::validateUplinkFrameHeader(const QByteArray& data) {
if (data.size() < 2) {
return false;
}
return (static_cast<quint8>(data[0]) == FLARE_UPLINK_HEADER1) &&
(static_cast<quint8>(data[1]) == FLARE_UPLINK_HEADER2);
}
bool FlareDevice::validateDownlinkFrameHeader(const QByteArray& data) {
if (data.size() < 2) {
return false;
}
return (static_cast<quint8>(data[0]) == FLARE_DOWNLINK_HEADER1) &&
(static_cast<quint8>(data[1]) == FLARE_DOWNLINK_HEADER2);
}
quint8 FlareDevice::calculateAdditiveChecksum(const QByteArray& data, qint32 length) {
if (length == 0) {
length = data.size();
}
quint8 checksum = 0;
for (qint32 i = 0; i < length && i < data.size(); ++i) {
checksum += static_cast<quint8>(data.at(i));
}
return checksum;
}
quint8 FlareDevice::calculateXorChecksum(const QByteArray& data, qint32 length) {
if (length == 0) {
length = data.size();
}
quint8 checksum = 0;
for (qint32 i = 0; i < length && i < data.size(); ++i) {
checksum ^= static_cast<quint8>(data.at(i));
}
return checksum;
}
quint16 FlareDevice::createDevicePermissions(quint8 device_id) {
if (device_id >= 1 && device_id <= MAX_DEVICE_ID) {
return 1 << (device_id - 1);
}
return 0;
}
quint16 FlareDevice::createMultiDevicePermissions(const QList<quint8>& device_ids) {
quint16 permissions = 0;
for (quint8 device_id : device_ids) {
if (device_id >= 1 && device_id <= MAX_DEVICE_ID) {
permissions |= (1 << (device_id - 1));
}
}
return permissions;
}
QList<quint8> FlareDevice::extractDeviceIdsFromPermissions(quint16 permissions) {
QList<quint8> device_ids;
for (quint8 i = 1; i <= MAX_DEVICE_ID; ++i) {
if (permissions & (1 << (i - 1))) {
device_ids.append(i);
}
}
return device_ids;
}
quint32 FlareDevice::createChannelSelectionMask(const QList<quint8>& channels) {
quint32 mask = 0;
for (quint8 channel : channels) {
if (channel >= 1 && channel <= MAX_FLARE_CHANNELS) {
mask |= (1 << (channel - 1));
}
}
return mask;
}
QList<quint8> FlareDevice::extractChannelsFromMask(quint32 channel_mask) {
QList<quint8> channels;
for (quint8 i = 1; i <= MAX_FLARE_CHANNELS; ++i) {
if (channel_mask & (1 << (i - 1))) {
channels.append(i);
}
}
return channels;
}
bool FlareDevice::isValidChannel(quint8 channel_id) {
return channel_id >= 1 && channel_id <= MAX_FLARE_CHANNELS;
}
bool FlareDevice::isValidDeviceId(quint8 device_id) {
return device_id >= 1 && device_id <= MAX_DEVICE_ID;
}
void FlareDevice::setDevicePermissionsInCommand(QByteArray& command, quint16 permissions) const {
if (command.size() >= 5) {
// 设置权限字节(小端序)
command[3] = static_cast<char>(permissions & 0xFF);
command[4] = static_cast<char>((permissions >> 8) & 0xFF);
}
}
QByteArray FlareDevice::createBaseCommandFrame(FlareCommandType command_type,
quint16 device_permissions,
const QByteArray& command_data) const {
FlareUplinkData base_command;
base_command.command_type = command_type;
base_command.setDevicePermissions(device_permissions);
if (command_data.size() >= 5) {
for (qint32 i = 0; i < 5; ++i) {
base_command.command_data[i] = command_data.at(i);
}
}
return base_command.serialize();
}
// 槽函数实现
void FlareDevice::setSafety(bool on) {
quint16 permissions = createDevicePermissions(device_id_);
sendSafetyReleaseCommand(permissions, on);
}
void FlareDevice::selectChannel(quint8 channel) {
if (channel >= 1 && channel <= MAX_FLARE_CHANNELS) {
selected_channels_ |= (1 << (channel - 1));
qDebug() << QString("通道 %1 已选择").arg(channel);
} else {
emit errorOccurred(QStringLiteral("无效的通道ID: %1").arg(channel));
}
}
void FlareDevice::deselectChannel(quint8 channel) {
if (channel >= 1 && channel <= MAX_FLARE_CHANNELS) {
selected_channels_ &= ~(1 << (channel - 1));
qDebug() << QString("通道 %1 已取消选择").arg(channel);
} else {
emit errorOccurred(QStringLiteral("无效的通道ID: %1").arg(channel));
}
}
void FlareDevice::triggerManualRelease(quint16 release_interval, const QList<quint8>& channels) {
quint32 channel_mask = createChannelSelectionMask(channels);
quint16 permissions = createDevicePermissions(device_id_);
sendManualTriggerCommand(permissions, release_interval, channel_mask);
}
void FlareDevice::performSelfTest() {
quint16 permissions = createDevicePermissions(device_id_);
sendSelfTestCommand(permissions);
}
void FlareDevice::requestStatusUpdate() {
quint16 permissions = createDevicePermissions(device_id_);
QByteArray command = createStatusQueryCommand(permissions);
emit commandSent(command);
qDebug() << "状态查询请求已发送";
}
void FlareDevice::resetDevice() {
current_safety_status_ = false;
selected_channels_ = 0;
qDebug() << "设备已重置";
emit errorOccurred(QStringLiteral("设备已重置"));
}
void FlareDevice::handleStatusUpdate(const payload_protocol::FlareDownlinkData& status) {
// 保存最后状态
last_status_ = status;
// 检查保险状态变化
bool new_safety_status = (status.status_byte.safety_status == SafetyStatus::ON);
if (new_safety_status != current_safety_status_) {
current_safety_status_ = new_safety_status;
emit safetyStatusChanged(new_safety_status);
}
// 发出状态更新信号
emit statusUpdated(status);
// 可以添加更多的状态变化检查,比如弹状态、通道状态等
// 这里简单起见,只检查保险状态
}
} // namespace payload_protocol