118 lines
3.4 KiB
C
118 lines
3.4 KiB
C
/**
|
|
* @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 <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#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 */
|