/** * @file protocol.h * @brief 简化的ASCII文本指令协议 * * 协议格式: $SN,CMD,param1,param2*CS\r\n * - SN: 序列号(0-255),用于防丢包和重复 * - CMD: 指令名称 * - CS: CRC8校验(从$到*之间所有字符的CRC8值) * * 抗干扰/防丢失机制: * 1. CRC8校验 - 比XOR更强的检错能力 * 2. 序列号 - 接收方可检测丢包和重复 * 3. 应答机制 - 重要指令需要确认 */ #ifndef __PROTOCOL_H #define __PROTOCOL_H #include #include #ifdef __cplusplus extern "C" { #endif /* 协议配置 */ #define PROTOCOL_MAX_CMD_LEN 8 #define PROTOCOL_MAX_PARAM_LEN 32 #define PROTOCOL_MAX_PARAMS 4 #define PROTOCOL_FRAME_TIMEOUT 1000 /* 帧超时/ms */ typedef struct { uint8_t sn; /* 序列号 */ char cmd[PROTOCOL_MAX_CMD_LEN]; /* 指令名 */ char params[PROTOCOL_MAX_PARAMS][PROTOCOL_MAX_PARAM_LEN]; uint8_t param_count; /* 参数数量 */ uint8_t checksum; /* CRC8校验和 */ bool valid; /* 解析是否成功 */ } protocol_frame_t; typedef enum { PROTOCOL_OK = 0, PROTOCOL_ERROR_INVALID_FRAME, PROTOCOL_ERROR_CHECKSUM_FAIL, PROTOCOL_ERROR_TIMEOUT, PROTOCOL_ERROR_UNKNOWN_CMD, PROTOCOL_ERROR_PARAM_COUNT, PROTOCOL_ERROR_BUFFER_FULL } protocol_error_t; typedef enum { PROTOCOL_CMD_RL, /* 继电器控制: RL,id,ON/OFF */ PROTOCOL_CMD_DI, /* 查询IO: DI,id */ PROTOCOL_CMD_DIA, /* 查询所有IO: DIA */ PROTOCOL_CMD_FWD, /* 数据转发: FWD,port,data */ PROTOCOL_CMD_ECHO, /* 心跳: ECHO */ PROTOCOL_CMD_ACK, /* 应答: ACK,sn,result */ PROTOCOL_CMD_STATUS, /* 状态查询: STATUS */ PROTOCOL_CMD_UNKNOWN } protocol_cmd_t; typedef struct { protocol_cmd_t cmd; uint8_t sn; bool need_ack; /* 是否需要应答 */ uint32_t send_time; /* 发送时间 */ uint8_t retry_count; /* 重试次数 */ } protocol_pending_t; #define PROTOCOL_MAX_PENDING 4 typedef struct { protocol_pending_t pending[PROTOCOL_MAX_PENDING]; uint8_t pending_count; uint8_t next_sn; uint8_t last_rx_sn; } protocol_context_t; /* 协议初始化 */ void protocol_init(void); /* 解析收到的指令 */ protocol_error_t protocol_parse(const char *data, uint16_t length, protocol_frame_t *frame); /* 构造发送帧 */ protocol_error_t protocol_build(char *buffer, uint16_t buffer_size, uint16_t *out_length, protocol_cmd_t cmd, uint8_t sn, const char *params[], uint8_t param_count); /* 构造应答帧 */ protocol_error_t protocol_build_ack(char *buffer, uint16_t buffer_size, uint16_t *out_length, uint8_t sn, bool success, const char *msg); /* 发送命令并等待应答 */ protocol_error_t protocol_send_with_ack(protocol_cmd_t cmd, const char *params[], uint8_t param_count, uint32_t timeout_ms, uint8_t max_retries); /* 协议任务处理(处理超时和重试) */ void protocol_task(void); /* CRC8计算 */ uint8_t protocol_crc8(const uint8_t *data, uint16_t length); /* 指令名转枚举 */ protocol_cmd_t protocol_cmd_from_string(const char *cmd_str); /* 枚举转指令名 */ const char* protocol_cmd_to_string(protocol_cmd_t cmd); /* 获取上一个错误 */ protocol_error_t protocol_get_last_error(void); #ifdef __cplusplus } #endif #endif /* __PROTOCOL_H */