|
|
#ifndef _MSGHANDLER_HPP_
|
|
|
#define _MSGHANDLER_HPP_
|
|
|
|
|
|
#include <chrono>
|
|
|
#include <cstdint>
|
|
|
#include <queue>
|
|
|
#include <mutex>
|
|
|
#include <vector>
|
|
|
#include <map>
|
|
|
#include <mutex>
|
|
|
#include <functional>
|
|
|
|
|
|
#include "WeighingDDSType.hpp"
|
|
|
#include <termios.h>
|
|
|
|
|
|
#define BEEP_CARD 1
|
|
|
#define FIND_CARD 2 // 发送命令号
|
|
|
#define FIND_CARD_RSP 0x08 // FindCard 响应命令号(固件返回0x08)
|
|
|
#define SET_PWD 3
|
|
|
#define READ_CARD 4
|
|
|
#define WRITE_CARD 5
|
|
|
#define STOP_CARD 8 // 发送/响应命令号(Pause)
|
|
|
|
|
|
|
|
|
enum class CardState {
|
|
|
AUTO_FIND, // 自动寻卡状态
|
|
|
WAIT_DDS_READ, // 等待 DDS read 命令
|
|
|
WAIT_DDS_WRITE, // 等待 DDS write 命令
|
|
|
WAIT_DDS_DECISION, // 读卡完成,等待 DDS 决定(write / stop / ack)
|
|
|
WAIT_DDS_WRITE_NEXT // 写卡成功,等待下一个 write 命令(10秒超时)
|
|
|
};
|
|
|
|
|
|
enum class PendingCommand : uint8_t { None, Find, SetPassword, ReadBlock, WriteBlock, Stop, Beep };
|
|
|
|
|
|
|
|
|
class MsgHandler {
|
|
|
public:
|
|
|
int fd;
|
|
|
std::string device;
|
|
|
std::map<uint8_t, std::vector<uint8_t>> m_PassWord;
|
|
|
|
|
|
MsgHandler();
|
|
|
~MsgHandler() = default;
|
|
|
|
|
|
void HandleDdsMsg(const std::map<std::string, std::vector<uint8_t>>& msg, unsigned long index);
|
|
|
int HandleDeviceMsg(WeighingSystem::ReadCardRsp& rsp);
|
|
|
bool SetDevice(const std::string& device);
|
|
|
bool InitSequence(void);
|
|
|
void AutoFindTick(void);
|
|
|
|
|
|
void StorePasswd(std::map<uint8_t, std::vector<uint8_t>>& data);
|
|
|
void SetPasswd(const std::vector<uint8_t>& data);
|
|
|
void FindCard(void);
|
|
|
void ReadCard(const std::vector<uint8_t>& data);
|
|
|
void WriteCard(const std::vector<uint8_t>& data);
|
|
|
void StopCard(void);
|
|
|
void BeepCard(const std::vector<uint8_t>& data);
|
|
|
void ResetCard(void);
|
|
|
|
|
|
int ParseDeviceMsg(std::vector<uint8_t>& data, WeighingSystem::ReadCardRsp& rsp);
|
|
|
|
|
|
bool WaitForResponse(uint8_t expected_cmd, int timeout_ms = 3000);
|
|
|
|
|
|
virtual bool OpenPort(const std::string& port, const std::string& baudrate);
|
|
|
virtual int SendDeviceMsg(const std::vector<uint8_t>& data);
|
|
|
virtual int RecvDeviceMsg(std::vector<uint8_t>& data, int timeoutMs);
|
|
|
int SendMsg(const std::vector<uint8_t>& data);
|
|
|
int RecvMsg(std::vector<uint8_t>& data, int timeoutMs);
|
|
|
bool isOpen() const {
|
|
|
return fd != -1;
|
|
|
}
|
|
|
void ClosePort();
|
|
|
|
|
|
|
|
|
// 【新增】内部版本,不加锁,供 ParseDeviceMsg 的 drain 循环使用
|
|
|
int RecvMsgInternal(std::vector<uint8_t>& data, int timeoutMs);
|
|
|
|
|
|
|
|
|
|
|
|
void SetCardState(CardState state);
|
|
|
unsigned long GetCurrentIndex() const;
|
|
|
bool IsTimeoutRecovery() const;
|
|
|
uint64_t GetOperationSequence() const;
|
|
|
bool IsReadResponseReady() const;
|
|
|
bool IsWriteResponseReady() const;
|
|
|
void ClearReadBuffer();
|
|
|
void SetReadResult(uint8_t resultCode, const std::string& cardId, uint8_t blockCount,
|
|
|
const std::vector<std::pair<uint8_t, std::vector<uint8_t>>>& blockData);
|
|
|
void SetWriteResult(uint8_t resultCode, const std::string& cardId, uint8_t blockNum);
|
|
|
int CheckDdsTimeout();
|
|
|
|
|
|
void ResetWriteTimeout();
|
|
|
|
|
|
std::function<void(const std::string& cardId)> OnCardDetected;
|
|
|
|
|
|
// 【新增】由业务层填充:HandleDeviceMsg 检测到卡后写入,主循环读取并发送 QueueTrigger
|
|
|
std::string pending_trigger_card_;
|
|
|
std::mutex trigger_mtx_;
|
|
|
|
|
|
|
|
|
// ========== 单块操作超时控制 ==========
|
|
|
int GetBlockOpElapsed() const;
|
|
|
static constexpr int BLOCK_OPERATION_TIMEOUT_MS = 3000;
|
|
|
static constexpr bool VERIFY_DEVICE_CRC = true;
|
|
|
// 通信帧不完整或 CRC/数据校验失败时,同一读块允许额外重发的次数。
|
|
|
static constexpr uint8_t READ_BLOCK_MAX_RETRIES = 1;
|
|
|
static constexpr int READ_BLOCK_RETRY_DELAY_MS = 100;
|
|
|
uint8_t GetCurrentOperatingBlock() const;
|
|
|
bool IsBlockOperationPending() const;
|
|
|
void SkipCurrentBlock();
|
|
|
bool HasPendingReadResponse() const;
|
|
|
std::vector<uint8_t> GetPendingReadResponse();
|
|
|
CardState GetCardState() const;
|
|
|
|
|
|
// 【新增】业务层主动取消等待、立即回到自动寻卡
|
|
|
void ForceResetToAutoFind();
|
|
|
|
|
|
// 【新增】业务层暂停自动寻卡(state 切到 AUTO_FIND,m_AutoFind=false),
|
|
|
// 用于刚发完 QueueTrigger 后的 3 秒等待期:阻止 HandleDdsMsg 接收 read/write。
|
|
|
void PauseAutoFind();
|
|
|
|
|
|
// 【新增】标记:是否正在执行超时恢复序列
|
|
|
// 原因:SkipCurrentBlock 发的恢复命令可能和 HandleDdsMsg 的新命令冲突
|
|
|
bool m_IsInTimeoutRecovery = false;
|
|
|
|
|
|
// 【新增】重置串口并重新初始化 RC522(用于块操作超时后的恢复)
|
|
|
bool ResetSerialAndReinit();
|
|
|
|
|
|
// 【新增】刷新串口配置(供 SkipCurrentBlock 使用)
|
|
|
bool refreshPort();
|
|
|
|
|
|
// 【新增】保存串口参数,供 ResetSerialAndReinit 使用
|
|
|
std::string m_Port; // 端口名,如 "ttyS1"
|
|
|
speed_t m_Baudrate; // 波特率(speed_t 类型)
|
|
|
|
|
|
|
|
|
private:
|
|
|
bool TryExtractDeviceFrame(std::vector<uint8_t>& data);
|
|
|
bool IsValidDeviceFrame(const std::vector<uint8_t>& data);
|
|
|
bool RetryCurrentReadBlock(const char* reason);
|
|
|
bool HasActiveDeviceOperation() const;
|
|
|
int HandleFindResponse(const std::vector<uint8_t>& data,
|
|
|
WeighingSystem::ReadCardRsp& rsp);
|
|
|
static bool IsDataBlock(uint8_t block);
|
|
|
|
|
|
bool m_AutoFind = false;
|
|
|
int m_FindIntervalMs = 500;
|
|
|
std::chrono::steady_clock::time_point m_LastFindTime;
|
|
|
std::string m_PreCard;
|
|
|
|
|
|
// 【新增】保存 WaitForResponse 接收到的 ReadCard 响应数据
|
|
|
std::vector<uint8_t> m_LastReadCardRsp;
|
|
|
|
|
|
//std::mutex mtx_; // 添加这行 - 保护串口访问
|
|
|
mutable std::recursive_mutex mtx_;
|
|
|
std::vector<uint8_t> m_ReceiveBuffer;
|
|
|
|
|
|
|
|
|
CardState m_CardState; // 当前状态
|
|
|
unsigned long m_CurrentIndex; // 保存收到的 index
|
|
|
std::chrono::steady_clock::time_point m_StateEnterTime; // 状态进入时间
|
|
|
static constexpr int DDS_TIMEOUT_MS = 20000; // DDS 命令 10 秒超时
|
|
|
static constexpr int DDS_DECISION_TIMEOUT_MS = 20000; // WAIT_DDS_DECISION 超时
|
|
|
static constexpr int DDS_WRITE_TIMEOUT_MS = 10000; // 写卡序列 10 秒超时
|
|
|
static constexpr int CARD_READY_IDLE_TIMEOUT_MS = 20000; // 卡就绪无任务后恢复寻卡
|
|
|
static constexpr int WRITE_BLOCK_OPERATION_TIMEOUT_MS = 2000;
|
|
|
|
|
|
|
|
|
// 读卡结果缓存
|
|
|
uint8_t m_ResultCode; // 结果码
|
|
|
std::string m_CardId; // 当前操作的卡号
|
|
|
uint8_t m_BlockCount; // 当前读取的块数量
|
|
|
std::vector<std::pair<uint8_t, std::vector<uint8_t>>> m_BlockData; // 块数据
|
|
|
std::vector<uint8_t> m_RequestedBlocks; // 【新增】请求的块号列表
|
|
|
uint8_t m_CurrentReadIndex = 0; // 【新增】当前正在读取的块索引
|
|
|
|
|
|
std::chrono::steady_clock::time_point m_ReadStartTime;
|
|
|
std::chrono::steady_clock::time_point m_ReadEndTime;
|
|
|
|
|
|
// 写卡请求的 pending 信息(响应时用)
|
|
|
uint8_t m_PendingWriteBlock = 0;
|
|
|
std::vector<uint8_t> m_PendingWriteValue;
|
|
|
std::string m_WriteCardId;
|
|
|
|
|
|
|
|
|
// ========== 单块操作超时控制 ==========
|
|
|
std::chrono::steady_clock::time_point m_BlockOpStartTime; // 当前块操作开始时间
|
|
|
uint8_t m_CurrentOperatingBlock = 0; // 当前正在操作的块号
|
|
|
bool m_BlockOperationPending = false; // 当前是否存在待读写响应
|
|
|
PendingCommand m_PendingCommand = PendingCommand::None;
|
|
|
uint8_t m_PendingBlock = 0;
|
|
|
uint8_t m_ReadBlockRetryCount = 0;
|
|
|
uint64_t m_OperationSequence = 0;
|
|
|
std::vector<uint8_t> m_PendingReadResponse; // 超时跳转时准备的响应
|
|
|
std::vector<uint8_t> m_SkippedBlocks; // 【新增】记录跳过的超时块号
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t chCRCHTalbe[256] = {
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
|
|
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
|
0x00, 0xC1, 0x81, 0x40
|
|
|
};
|
|
|
|
|
|
uint8_t chCRCLTalbe[256] = {
|
|
|
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
|
|
|
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
|
|
|
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
|
|
|
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
|
|
|
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
|
|
|
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
|
|
|
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
|
|
|
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
|
|
|
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
|
|
|
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
|
|
|
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
|
|
|
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
|
|
|
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
|
|
|
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
|
|
|
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
|
|
|
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
|
|
|
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
|
|
|
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
|
|
|
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
|
|
|
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
|
|
|
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
|
|
|
0x41, 0x81, 0x80, 0x40
|
|
|
};
|
|
|
|
|
|
void CRC16(std::vector<uint8_t>& data);
|
|
|
};
|
|
|
|
|
|
#endif
|