454 lines
14 KiB
C++
454 lines
14 KiB
C++
#ifndef FLARE_DEVICE_H
|
||
#define FLARE_DEVICE_H
|
||
|
||
#include <QObject>
|
||
#include <QByteArray>
|
||
#include <QString>
|
||
#include <QVector>
|
||
#include <QList>
|
||
#include <QtGlobal>
|
||
#include <stdexcept>
|
||
|
||
namespace payload_protocol {
|
||
|
||
// 干扰弹设备指令类型
|
||
enum class FlareCommandType : quint8 {
|
||
SAFETY_RELEASE = 0x01, // 投放保险指令
|
||
MISSION_TRIGGER = 0x02, // 任务触发指令
|
||
MANUAL_TRIGGER = 0x03, // 手动触发指令
|
||
SELF_TEST = 0x04, // 设备自检指令
|
||
STATUS_QUERY = 0x25 // 状态查询指令
|
||
};
|
||
|
||
// 干扰弹下行报文类型
|
||
enum class FlareDownlinkType : quint8 {
|
||
STATUS_AUTO = 0xE5 // 状态信息自动下传
|
||
};
|
||
|
||
// 工作状态枚举
|
||
enum class FlareWorkStatus : quint8 {
|
||
STANDBY = 0x00, // 待机
|
||
MISSION_1 = 0x01, // 正在执行任务1
|
||
MISSION_2 = 0x02, // 正在执行任务2
|
||
MISSION_3 = 0x03, // 正在执行任务3
|
||
MISSION_4 = 0x04, // 正在执行任务4
|
||
MISSION_5 = 0x05, // 正在执行任务5
|
||
MISSION_6 = 0x06, // 正在执行任务6
|
||
MISSION_7 = 0x07, // 正在执行任务7
|
||
MISSION_8 = 0x08, // 正在执行任务8
|
||
MISSION_9 = 0x09, // 正在执行任务9
|
||
MISSION_10 = 0x0A, // 正在执行任务10
|
||
MISSION_11 = 0x0B, // 正在执行任务11
|
||
MISSION_12 = 0x0C, // 正在执行任务12
|
||
MISSION_13 = 0x0D, // 正在执行任务13
|
||
MISSION_14 = 0x0E, // 正在执行任务14
|
||
MISSION_15 = 0x0F, // 正在执行任务15
|
||
SELF_TESTING = 0x40, // 正在执行设备自检
|
||
MANUAL_TRIGGERING = 0xFF // 正在执行手动触发
|
||
};
|
||
|
||
// 保险状态
|
||
enum class SafetyStatus : quint8 {
|
||
OFF = 0x00, // 关
|
||
ON = 0x01 // 开
|
||
};
|
||
|
||
// 电源电压状态
|
||
enum class PowerVoltageStatus : quint8 {
|
||
NORMAL = 0x00, // 电压正常
|
||
ABNORMAL = 0x01 // 电压异常
|
||
};
|
||
|
||
// 火工开关状态
|
||
enum class IgniterStatus : quint8 {
|
||
OFF = 0x00, // 火工关
|
||
ABNORMAL = 0x01, // 火工异常
|
||
ON = 0x03 // 火工开
|
||
};
|
||
|
||
// 自检状态
|
||
enum class SelfTestStatus : quint8 {
|
||
NOT_TESTED = 0x00, // 上电未自检
|
||
NORMAL = 0x01, // 自检正常
|
||
ABNORMAL = 0x02 // 自检异常
|
||
};
|
||
|
||
// 干扰弹帧头
|
||
constexpr quint8 FLARE_UPLINK_HEADER1 = 0xE8;
|
||
constexpr quint8 FLARE_UPLINK_HEADER2 = 0xD7;
|
||
constexpr quint8 FLARE_DOWNLINK_HEADER1 = 0xE6;
|
||
constexpr quint8 FLARE_DOWNLINK_HEADER2 = 0xD5;
|
||
|
||
// 干扰弹帧长度
|
||
constexpr qint32 FLARE_UPLINK_FRAME_LENGTH = 12; // 上行帧长度
|
||
constexpr qint32 FLARE_DOWNLINK_FRAME_LENGTH = 20; // 下行帧长度
|
||
|
||
// 最大通道数量
|
||
constexpr qint32 MAX_FLARE_CHANNELS = 24;
|
||
constexpr qint32 MAX_DEVICE_ID = 15;
|
||
|
||
// 投放保险指令参数
|
||
constexpr quint8 SAFETY_ON = 0xAA; // 投放保险开
|
||
constexpr quint8 SAFETY_OFF = 0x55; // 投放保险关
|
||
|
||
// 干扰弹上行指令基础结构
|
||
struct FlareUplinkData {
|
||
// 字节0-1: 帧头(在序列化时添加)
|
||
|
||
// 字节2: 指令类型
|
||
FlareCommandType command_type;
|
||
|
||
// 字节3-4: 权限/设备号(16位)
|
||
struct {
|
||
quint8 reserved_bit : 1; // bit15: 保留位,为0
|
||
quint16 device_permissions : 15; // bit14~0: 对应设备ID为15~1的控制权限
|
||
} device_permissions;
|
||
|
||
// 字节5-9: 数据(具体内容取决于指令类型)
|
||
QByteArray command_data;
|
||
|
||
// 字节10: 和校验(在序列化时计算)
|
||
// 字节11: 异或校验(在序列化时计算)
|
||
|
||
FlareUplinkData();
|
||
|
||
// 序列化为字节流
|
||
QByteArray serialize() const;
|
||
|
||
// 从字节流反序列化
|
||
bool deserialize(const QByteArray& data);
|
||
|
||
// 验证双校验
|
||
bool validateChecksum(const QByteArray& data) const;
|
||
|
||
// 设置设备权限(支持多设备控制)
|
||
void setDevicePermissions(quint16 permissions);
|
||
|
||
// 检查是否具有特定设备权限
|
||
bool hasDevicePermission(quint8 device_id) const;
|
||
|
||
// 添加设备权限
|
||
void addDevicePermission(quint8 device_id);
|
||
|
||
// 移除设备权限
|
||
void removeDevicePermission(quint8 device_id);
|
||
|
||
// 获取设备权限掩码
|
||
quint16 getDevicePermissions() const;
|
||
};
|
||
|
||
// 投放保险指令数据结构
|
||
struct SafetyReleaseCommand : public FlareUplinkData {
|
||
quint8 safety_status; // 投放保险状态:0xAA开,0x55关
|
||
|
||
SafetyReleaseCommand();
|
||
|
||
// 设置投放保险状态
|
||
void setSafetyStatus(bool on);
|
||
|
||
// 检查是否为开启命令
|
||
bool isSafetyOn() const;
|
||
|
||
// 检查是否为关闭命令
|
||
bool isSafetyOff() const;
|
||
|
||
// 序列化
|
||
QByteArray serialize() const;
|
||
|
||
// 反序列化
|
||
bool deserialize(const QByteArray& data);
|
||
};
|
||
|
||
// 手动触发指令数据结构
|
||
struct ManualTriggerCommand : public FlareUplinkData {
|
||
quint16 release_interval; // 投放间隔时间,单位ms,范围0-60000
|
||
quint32 channel_selection; // 通道选择,24位掩码
|
||
|
||
ManualTriggerCommand();
|
||
|
||
// 设置投放间隔时间
|
||
void setReleaseInterval(quint16 interval_ms);
|
||
|
||
// 设置通道选择
|
||
void setChannelSelection(quint32 channel_mask);
|
||
|
||
// 选择特定通道
|
||
void selectChannel(quint8 channel);
|
||
|
||
// 取消选择通道
|
||
void deselectChannel(quint8 channel);
|
||
|
||
// 检查通道是否被选择
|
||
bool isChannelSelected(quint8 channel) const;
|
||
|
||
// 获取选择的通道数量
|
||
quint8 getSelectedChannelCount() const;
|
||
|
||
// 序列化
|
||
QByteArray serialize() const;
|
||
|
||
// 反序列化
|
||
bool deserialize(const QByteArray& data);
|
||
};
|
||
|
||
// 设备自检指令数据结构
|
||
struct SelfTestCommand : public FlareUplinkData {
|
||
SelfTestCommand();
|
||
|
||
// 序列化
|
||
QByteArray serialize() const;
|
||
|
||
// 反序列化
|
||
bool deserialize(const QByteArray& data);
|
||
};
|
||
|
||
// 干扰弹下行状态数据结构
|
||
struct FlareDownlinkData {
|
||
// 字节0-1: 帧头(在序列化时添加)
|
||
|
||
// 字节2: 报文类型
|
||
FlareDownlinkType message_type;
|
||
|
||
// 字节3: 当前设备ID
|
||
quint8 current_device_id;
|
||
|
||
// 字节4: 设备硬件通道数量
|
||
quint8 hardware_channel_count;
|
||
|
||
// 字节5: 工作状态
|
||
FlareWorkStatus work_status;
|
||
|
||
// 字节6: 电源电压、火工、保险状态
|
||
struct {
|
||
quint8 reserved_bits : 3; // bit7~5: 保留
|
||
SafetyStatus safety_status : 1; // bit4: 投放保险状态
|
||
PowerVoltageStatus power_status : 2; // bit3~2: 电源电压状态
|
||
IgniterStatus igniter_status : 2; // bit1~0: 火工开关状态
|
||
} status_byte;
|
||
|
||
// 字节7-8: 任务状态(16位,bit0~14对应任务1~15)
|
||
quint16 mission_status;
|
||
|
||
// 字节9: 自检状态
|
||
SelfTestStatus self_test_status;
|
||
|
||
// 字节10-12: 弹状态(24位,bit0~23对应弹1~24)
|
||
quint32 flare_status;
|
||
|
||
// 字节13-15: 通道有弹状态(24位,bit0~23对应通道1~24)
|
||
quint32 channel_loaded_status;
|
||
|
||
// 字节16-17: 响应帧序号(16位)
|
||
quint16 response_frame_number;
|
||
|
||
// 字节18: 和校验(在序列化时计算)
|
||
// 字节19: 异或校验(在序列化时计算)
|
||
|
||
FlareDownlinkData();
|
||
|
||
// 序列化为字节流
|
||
QByteArray serialize() const;
|
||
|
||
// 从字节流反序列化
|
||
bool deserialize(const QByteArray& data);
|
||
|
||
// 验证双校验
|
||
bool validateChecksum(const QByteArray& data) const;
|
||
|
||
// 检查任务是否已执行
|
||
bool isMissionExecuted(quint8 mission_id) const;
|
||
|
||
// 设置任务执行状态
|
||
void setMissionExecuted(quint8 mission_id, bool executed);
|
||
|
||
// 检查弹是否正常
|
||
bool isFlareNormal(quint8 flare_id) const;
|
||
|
||
// 设置弹状态
|
||
void setFlareStatus(quint8 flare_id, bool normal);
|
||
|
||
// 检查通道是否有弹
|
||
bool isChannelLoaded(quint8 channel_id) const;
|
||
|
||
// 设置通道有弹状态
|
||
void setChannelLoaded(quint8 channel_id, bool loaded);
|
||
|
||
// 获取工作状态描述
|
||
QString getWorkStatusDescription() const;
|
||
|
||
// 获取状态摘要
|
||
QString getStatusSummary() const;
|
||
};
|
||
|
||
// 干扰弹设备类 - 支持信号槽机制
|
||
class FlareDevice : public QObject {
|
||
Q_OBJECT
|
||
|
||
public:
|
||
explicit FlareDevice(QObject* parent = nullptr);
|
||
explicit FlareDevice(quint8 device_id, QObject* parent = nullptr);
|
||
|
||
// 获取设备ID
|
||
quint8 getDeviceId() const { return device_id_; }
|
||
|
||
// 设置设备ID
|
||
void setDeviceId(quint8 id) { device_id_ = id; }
|
||
|
||
// 创建投放保险指令
|
||
QByteArray createSafetyReleaseCommand(quint16 device_permissions, bool safety_on) const;
|
||
|
||
// 创建手动触发指令
|
||
QByteArray createManualTriggerCommand(quint16 device_permissions,
|
||
quint16 release_interval,
|
||
quint32 channel_selection) const;
|
||
|
||
// 创建设备自检指令
|
||
QByteArray createSelfTestCommand(quint16 device_permissions) const;
|
||
|
||
// 创建任务触发指令(靶机不使用,但协议中有定义)
|
||
QByteArray createMissionTriggerCommand(quint16 device_permissions, quint8 mission_id) const;
|
||
|
||
// 创建状态查询指令
|
||
QByteArray createStatusQueryCommand(quint16 device_permissions) const;
|
||
|
||
// 解析下行状态数据 - 槽函数
|
||
Q_SLOT bool parseStatusData(const QByteArray& data);
|
||
|
||
// 手动解析状态数据(兼容原有接口)
|
||
bool parseStatusData(const QByteArray& data, FlareDownlinkData& downlink_data) const;
|
||
|
||
// 发送投放保险指令 - 槽函数
|
||
Q_SLOT void sendSafetyReleaseCommand(quint16 device_permissions, bool safety_on);
|
||
|
||
// 发送手动触发指令 - 槽函数
|
||
Q_SLOT void sendManualTriggerCommand(quint16 device_permissions,
|
||
quint16 release_interval,
|
||
quint32 channel_selection);
|
||
|
||
// 发送设备自检指令 - 槽函数
|
||
Q_SLOT void sendSelfTestCommand(quint16 device_permissions);
|
||
|
||
// 发送原始指令数据 - 槽函数
|
||
Q_SLOT void sendRawCommand(const QByteArray& command_data);
|
||
|
||
// 验证上行帧头
|
||
static bool validateUplinkFrameHeader(const QByteArray& data);
|
||
|
||
// 验证下行帧头
|
||
static bool validateDownlinkFrameHeader(const QByteArray& data);
|
||
|
||
// 计算和校验
|
||
static quint8 calculateAdditiveChecksum(const QByteArray& data, qint32 length = 0);
|
||
|
||
// 计算异或校验
|
||
static quint8 calculateXorChecksum(const QByteArray& data, qint32 length = 0);
|
||
|
||
// 创建设备权限掩码(支持多设备)
|
||
static quint16 createDevicePermissions(quint8 device_id);
|
||
|
||
// 创建多设备权限掩码
|
||
static quint16 createMultiDevicePermissions(const QList<quint8>& device_ids);
|
||
|
||
// 从权限掩码中提取设备ID列表
|
||
static QList<quint8> extractDeviceIdsFromPermissions(quint16 permissions);
|
||
|
||
// 创建通道选择掩码
|
||
static quint32 createChannelSelectionMask(const QList<quint8>& channels);
|
||
|
||
// 从通道掩码中提取通道列表
|
||
static QList<quint8> extractChannelsFromMask(quint32 channel_mask);
|
||
|
||
// 检查通道ID是否有效(1-24)
|
||
static bool isValidChannel(quint8 channel_id);
|
||
|
||
// 检查设备ID是否有效(1-15)
|
||
static bool isValidDeviceId(quint8 device_id);
|
||
|
||
signals:
|
||
// 状态更新信号
|
||
void statusUpdated(const payload_protocol::FlareDownlinkData& status);
|
||
|
||
// 保险状态变化信号
|
||
void safetyStatusChanged(bool safety_on);
|
||
|
||
// 弹状态变化信号
|
||
void flareStatusChanged(quint8 flare_id, bool normal);
|
||
|
||
// 通道有弹状态变化信号
|
||
void channelLoadedStatusChanged(quint8 channel_id, bool loaded);
|
||
|
||
// 任务执行状态变化信号
|
||
void missionStatusChanged(quint8 mission_id, bool executed);
|
||
|
||
// 设备连接状态变化信号
|
||
void connectionStatusChanged(bool connected);
|
||
|
||
// 指令发送信号
|
||
void commandSent(const QByteArray& command_data);
|
||
|
||
// 错误信号
|
||
void errorOccurred(const QString& error_message);
|
||
|
||
public slots:
|
||
// 设置投放保险状态
|
||
Q_SLOT void setSafety(bool on);
|
||
|
||
// 选择特定通道
|
||
Q_SLOT void selectChannel(quint8 channel);
|
||
|
||
// 取消选择通道
|
||
Q_SLOT void deselectChannel(quint8 channel);
|
||
|
||
// 触发手动投放
|
||
Q_SLOT void triggerManualRelease(quint16 release_interval, const QList<quint8>& channels);
|
||
|
||
// 执行设备自检
|
||
Q_SLOT void performSelfTest();
|
||
|
||
// 请求状态更新
|
||
Q_SLOT void requestStatusUpdate();
|
||
|
||
// 重置设备
|
||
Q_SLOT void resetDevice();
|
||
|
||
private slots:
|
||
// 处理内部状态更新
|
||
void handleStatusUpdate(const payload_protocol::FlareDownlinkData& status);
|
||
|
||
private:
|
||
quint8 device_id_; // 当前设备ID(1-15)
|
||
|
||
// 最后接收到的状态
|
||
FlareDownlinkData last_status_;
|
||
|
||
// 当前保险状态
|
||
bool current_safety_status_ = false;
|
||
|
||
// 当前选择的通道
|
||
quint32 selected_channels_ = 0;
|
||
|
||
// 设置设备权限到指令数据中
|
||
void setDevicePermissionsInCommand(QByteArray& command, quint16 permissions) const;
|
||
|
||
// 创建基础指令帧
|
||
QByteArray createBaseCommandFrame(FlareCommandType command_type,
|
||
quint16 device_permissions,
|
||
const QByteArray& command_data) const;
|
||
};
|
||
|
||
} // namespace payload_protocol
|
||
|
||
Q_DECLARE_METATYPE(payload_protocol::FlareCommandType)
|
||
Q_DECLARE_METATYPE(payload_protocol::FlareDownlinkType)
|
||
Q_DECLARE_METATYPE(payload_protocol::FlareWorkStatus)
|
||
Q_DECLARE_METATYPE(payload_protocol::SafetyStatus)
|
||
Q_DECLARE_METATYPE(payload_protocol::PowerVoltageStatus)
|
||
Q_DECLARE_METATYPE(payload_protocol::IgniterStatus)
|
||
Q_DECLARE_METATYPE(payload_protocol::SelfTestStatus)
|
||
Q_DECLARE_METATYPE(payload_protocol::FlareDownlinkData)
|
||
Q_DECLARE_METATYPE(payload_protocol::FlareUplinkData)
|
||
Q_DECLARE_METATYPE(payload_protocol::SafetyReleaseCommand)
|
||
Q_DECLARE_METATYPE(payload_protocol::ManualTriggerCommand)
|
||
Q_DECLARE_METATYPE(payload_protocol::SelfTestCommand)
|
||
|
||
#endif // FLARE_DEVICE_H
|