Compare commits

2 Commits

Author SHA1 Message Date
3643451d6c 增加事件触发功能 2026-05-12 09:43:59 +08:00
6e3f7ade3d 远程通信协议更改为 状态机处理 2026-05-11 15:27:25 +08:00
5 changed files with 224 additions and 174 deletions

View File

@@ -29,6 +29,7 @@ add_executable(DTU-HMI
src/common/utf8.c src/common/utf8.c
src/thread_utils.c src/thread_utils.c
src/remoteDisplay.c src/remoteDisplay.c
src/remoteDisplayProtocol.c
src/Drv/menu/app/menu.c src/Drv/menu/app/menu.c
src/Drv/pages/page_manager.c src/Drv/pages/page_manager.c
src/Drv/pages/global/global_state.c src/Drv/pages/global/global_state.c

View File

@@ -1,64 +1,61 @@
/* /*
* remoteDisplay.c - TCP 服务器线程实现 * 模块名称Remote Display
* 实现 RemoDispBus 协议:解析 remo_disp_server.py 的请求,返回 lcd 显存数据等。 * 模块功能:实现 RemoDispBus 协议,提供远程 LCD 显示与按键转发功能
* 帧格式: [TAG][cmd][len_hi][len_lo][data][crc]CRC = data 区逐字节异或低 8 位。 * 适用平台:通用嵌入式平台
* 客户端 TAG=0xAA设备回复 TAG=0xBB。 * 作者:王建锋
* 创建日期2026-05-11
* 修改记录:
* 2026-05-11 王建锋 创建初始版本
*/ */
#include "remoteDisplay.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "Drv/lcd/lcd.h" #include "Drv/lcd/lcd.h"
#include "TCP/tcp.h" #include "TCP/tcp.h"
#include "Drv/key.h" #include "Drv/key.h"
#include "remoteDisplay.h" #include "remoteDisplayProtocol.h"
/* RemoDispBus 协议常量(与 remo_disp_server.py 一致) */
#define TAG_CLIENT 0xAAu
#define TAG_DEVICE 0xBBu
#define CMD_KEEPLIVE 0
#define CMD_INIT 1
#define CMD_KEY 2
#define CMD_LCDMEM 3
/* 计算 data 区 CRC逐字节异或取低 8 位 */
static uint8_t calc_crc(const uint8_t* data, unsigned int len)
{
uint8_t crc = 0;
while (len--)
crc ^= *data++;
return crc;
}
/* 从 recv 缓冲区解析一帧: [TAG][cmd][len_hi][len_lo][data...][crc]
* 成功返回 1 并设置 *p_cmd, *p_data, *p_data_len失败返回 0。
* *p_consume 返回本帧总字节数(含头尾),调用方从缓冲区移除。 */
static int parse_frame(const uint8_t* buf, unsigned int buf_len,
uint8_t* p_cmd, const uint8_t** p_data, unsigned int* p_data_len,
unsigned int* p_consume)
{
if (buf_len < 5 || buf[0] != TAG_CLIENT)
return 0;
unsigned int data_len = ((unsigned int)buf[2] << 8) | buf[3];
unsigned int frame_len = 4 + data_len + 1; /* 头4 + data + crc */
if (buf_len < frame_len)
return 0;
uint8_t crc = calc_crc(buf + 4, data_len);
if (crc != buf[4 + data_len])
return 0;
*p_cmd = buf[1];
*p_data = buf + 4;
*p_data_len = data_len;
*p_consume = frame_len;
return 1;
}
/* 回复帧最大长度头4 + 最大 payload(4+LCD_DISPLAYMEMORYSIZE) + crc1 */ /* 回复帧最大长度头4 + 最大 payload(4+LCD_DISPLAYMEMORYSIZE) + crc1 */
#define REMO_REPLY_BUF_SIZE (4 + 4 + LCD_DISPLAYMEMORYSIZE + 1) #define REMO_REPLY_BUF_SIZE (4 + 4 + LCD_DISPLAYMEMORYSIZE + 1)
/* 构造设备回复帧并发送: [TAG_DEVICE][cmd][len_hi][len_lo][data][crc],一次性发送 */ /*
static int send_reply(int client, uint8_t cmd, const uint8_t* data, unsigned int data_len) * 函数功能计算数据的XOR校验和
{ * 入口参数p_data - 数据缓冲区指针 const uint8_t* 非NULL
* len - 数据长度 unsigned int 0 - PROTOCOL_MAX_DATA_LEN
* 返回值:校验和值 uint8_t 0 - 255
* 限定条件p_data指针必须指向有效的内存区域长度至少为len字节
* 函数说明1. 采用XOR算法计算校验和
* 2. 将所有数据字节进行异或运算
* 3. 当len为0时返回0
*/
static uint8_t calc_crc(const uint8_t *p_data, unsigned int len) {
uint8_t crc = 0;
unsigned int i;
if (p_data == NULL) {
return 0;
}
for (i = 0; i < len; i++) {
crc ^= p_data[i];
}
return crc;
}
/*
* 函数功能:构造设备回复帧并发送
* 入口参数client - 客户端 socket int 有效的 socket 描述符
* cmd - 命令字 uint8_t 参考 RemoDispBus 命令定义
* data - 回复数据指针 const uint8_t* 可为 NULL
* data_len - 回复数据长度 unsigned int 0 - PROTOCOL_MAX_DATA_LEN
* 出口参数:无
* 返回值0 - 发送成功
* -1 - 发送失败或参数非法
* 限定条件client 已连接且有效
* 函数说明:构造 [TAG_DEVICE][cmd][len_hi][len_lo][data][crc] 帧并一次性发送
*/
static int send_reply(int client, uint8_t cmd, const uint8_t* data, unsigned int data_len) {
uint8_t buf[REMO_REPLY_BUF_SIZE]; uint8_t buf[REMO_REPLY_BUF_SIZE];
unsigned int total = 4 + data_len + 1; unsigned int total = 4 + data_len + 1;
@@ -75,9 +72,17 @@ static int send_reply(int client, uint8_t cmd, const uint8_t* data, unsigned int
return TcpClient_Send(client, (const char*)buf, total) == (int)total ? 0 : -1; return TcpClient_Send(client, (const char*)buf, total) == (int)total ? 0 : -1;
} }
/* 处理 CMD_LCDMEM请求 data 为 4 字节大端起始地址;回复 [4B 地址][显存数据] */ /*
static void handle_cmd_lcdmem(int client, const uint8_t* req_data, unsigned int req_len) * 函数功能:处理 CMD_LCDMEM 请求并回复显存数据
{ * 入口参数client - 客户端 socket int 有效的 socket 描述符
* req_data - 请求数据指针 const uint8_t* 期望至少 4 个字节
* req_len - 请求数据长度 unsigned int 0 - PROTOCOL_MAX_DATA_LEN
* 出口参数:无
* 返回值:无
* 限定条件req_data 可为 NULL但 req_len 必须有效
* 函数说明:解析大端起始地址,读取显存并通过 send_reply 发送结果
*/
static void handle_cmd_lcdmem(int client, const uint8_t* req_data, unsigned int req_len) {
const uint8_t *framebuffer = Lcd_GetFrameBuffer(); const uint8_t *framebuffer = Lcd_GetFrameBuffer();
unsigned int start_addr = 0; unsigned int start_addr = 0;
@@ -106,9 +111,15 @@ static void handle_cmd_lcdmem(int client, const uint8_t* req_data, unsigned int
send_reply(client, CMD_LCDMEM, payload, 4 + copy_len); send_reply(client, CMD_LCDMEM, payload, 4 + copy_len);
} }
/* 处理 CMD_INIT回复宽、高、显存大小与 Python 端约定一致时可扩展) */ /*
static void handle_cmd_init(int client) * 函数功能:处理 CMD_INIT 请求并回复 LCD 参数
{ * 入口参数client - 客户端 socket int 有效的 socket 描述符
* 出口参数:无
* 返回值:无
* 限定条件client 已连接且有效
* 函数说明:回复 LCD 宽度、高度和显存大小的 8 字节信息
*/
static void handle_cmd_init(int client) {
uint8_t data[8]; uint8_t data[8];
data[0] = (LCD_SIZE_X >> 8) & 0xFF; data[0] = (LCD_SIZE_X >> 8) & 0xFF;
data[1] = LCD_SIZE_X & 0xFF; data[1] = LCD_SIZE_X & 0xFF;
@@ -121,9 +132,17 @@ static void handle_cmd_init(int client)
send_reply(client, CMD_INIT, data, 8); send_reply(client, CMD_INIT, data, 8);
} }
/* 处理 CMD_KEY可选转交菜单此处仅回 ACK */ /*
static void handle_cmd_key(int client, const uint8_t* data, unsigned int len) * 函数功能:处理 CMD_KEY 请求并更新远程按键信号
{ * 入口参数client - 客户端 socket int 有效的 socket 描述符
* data - 键值数据指针 const uint8_t* 期望至少 1 字节
* len - 数据长度 unsigned int 0 - PROTOCOL_MAX_DATA_LEN
* 出口参数:无
* 返回值:无
* 限定条件data 必须包含至少 1 个字节键值
* 函数说明:将按键值写入全局远程按键结构,供主循环处理
*/
static void handle_cmd_key(int client, const uint8_t* data, unsigned int len) {
#ifdef DEBUG #ifdef DEBUG
printf("handle_cmd_key: 0x%02X\n", data[0]); printf("handle_cmd_key: 0x%02X\n", data[0]);
#endif #endif
@@ -131,14 +150,26 @@ static void handle_cmd_key(int client, const uint8_t* data, unsigned int len)
g_tRemoteKey.byKeyValue = data[0]; g_tRemoteKey.byKeyValue = data[0];
} }
/* 处理 CMD_KEEPLIVE保活回空 */ /*
static void handle_cmd_keeplive(int client) * 函数功能:处理 CMD_KEEPLIVE 请求并回复空帧
{ * 入口参数client - 客户端 socket int 有效的 socket 描述符
* 出口参数:无
* 返回值:无
* 限定条件client 已连接且有效
* 函数说明:发送保活响应帧,无数据部分
*/
static void handle_cmd_keeplive(int client) {
send_reply(client, CMD_KEEPLIVE, (const uint8_t*)NULL, 0); send_reply(client, CMD_KEEPLIVE, (const uint8_t*)NULL, 0);
} }
/*
void tcp_server_thread_fn(void* arg) * 函数功能TCP 服务器线程入口函数
{ * 入口参数arg - 线程参数指针 void* 实际类型为 server_thread_arg_t*
* 出口参数:无
* 返回值:无
* 限定条件arg 必须指向有效的 server_thread_arg_t 实例
* 函数说明:创建 TCP 监听 socket接受客户端连接并按 RemoDispBus 协议处理请求
*/
void tcp_server_thread_fn(void* arg) {
server_thread_arg_t* ctx = (server_thread_arg_t*)arg; server_thread_arg_t* ctx = (server_thread_arg_t*)arg;
int server_sock = TcpServer_Listen((uint16_t)ctx->port); int server_sock = TcpServer_Listen((uint16_t)ctx->port);
if (server_sock == TCP_INVALID_SOCKET) { if (server_sock == TCP_INVALID_SOCKET) {
@@ -148,69 +179,55 @@ void tcp_server_thread_fn(void* arg)
*ctx->p_server_sock = server_sock; *ctx->p_server_sock = server_sock;
printf("[TCP Server] RemoDispBus 监听端口 %d等待客户端连接...\n", ctx->port); printf("[TCP Server] RemoDispBus 监听端口 %d等待客户端连接...\n", ctx->port);
#define REMO_BUF_SIZE 4096
uint8_t recv_buf[4096];
unsigned int recv_len = 0;
/* ========== 外层循环:主线程未请求退出时,持续等待并接受新客户端 ========== */ /* ========== 外层循环:主线程未请求退出时,持续等待并接受新客户端 ========== */
while (!*ctx->p_quit) { while (!*ctx->p_quit) {
/* 阻塞等待一个客户端连接;主线程关闭 server_sock 时 Accept 会失败并返回 INVALID */ /* 阻塞等待一个客户端连接;主线程关闭 server_sock 时 Accept 会失败并返回 INVALID */
int client = TcpServer_Accept(server_sock); int client = TcpServer_Accept(server_sock);
if (client == TCP_INVALID_SOCKET) if (client == TCP_INVALID_SOCKET) {
{ if (*ctx->p_quit) {
if (*ctx->p_quit)
break; break;
}
continue; continue;
} }
printf("[TCP Server] 客户端连接成功\n"); printf("[TCP Server] 客户端连接成功\n");
recv_len = 0; /* 新连接对应新的接收缓冲区,避免混用上一连接的残留数据 */
/* 为当前客户端初始化独立的协议解析实例 */
protocol_instance_t proto_ins;
protocol_init(&proto_ins);
/* ========== 内层循环:处理当前连接上的 RemoDispBus 请求,直到断开或退出 ========== */ /* ========== 内层循环:处理当前连接上的 RemoDispBus 请求,直到断开或退出 ========== */
while (!*ctx->p_quit) while (!*ctx->p_quit) {
{ uint8_t recv_byte; /* 逐字节接收 */
/* ----- 1. 若缓冲区中已有一条完整且校验通过的帧,则解析并分发处理 ----- */ int n = TcpClient_Recv(client, (uint8_t*)&recv_byte, 1);
uint8_t cmd; if (n > 0) { /* 成功收到1字节 */
const uint8_t* pdata; /* 喂给状态机逐字节处理 */
unsigned int data_len, consume; protocol_byte_handler(&proto_ins, recv_byte);
if (parse_frame(recv_buf, recv_len, &cmd, &pdata, &data_len, &consume)) /* 检查是否有完整帧解析完成 */
{ if (proto_ins.frame_done_flag == 1) {
switch (cmd) /* 根据解析到的CMD分发处理 */
{ switch (proto_ins.recv_cmd)
case CMD_KEEPLIVE: {
handle_cmd_keeplive(client); case CMD_KEEPLIVE:
break; handle_cmd_keeplive(client);
case CMD_INIT: break;
handle_cmd_init(client); case CMD_INIT:
break; handle_cmd_init(client);
case CMD_KEY: break;
handle_cmd_key(client, pdata, data_len); case CMD_KEY:
break; handle_cmd_key(client, proto_ins.recv_buf, proto_ins.expect_data_len);
case CMD_LCDMEM: break;
handle_cmd_lcdmem(client, pdata, data_len); case CMD_LCDMEM:
break; handle_cmd_lcdmem(client, proto_ins.recv_buf, proto_ins.expect_data_len);
default: break;
send_reply(client, cmd, (const uint8_t*)NULL, 0); default:
break; send_reply(client, proto_ins.recv_cmd, (const uint8_t*)NULL, 0);
break;
}
/* 处理完成后,复位协议实例,准备接收下一帧 */
protocol_init(&proto_ins);
} }
/* 从缓冲区头部移除已消费的 consume 字节,避免重复解析同一帧 */
memmove(recv_buf, recv_buf + consume, recv_len - consume);
recv_len -= consume;
continue; /* 继续检查是否还有完整帧,避免不必要的 recv */
} }
else { /* n==0客户端关闭或 n<0读取错误*/
/* ----- 2. 缓冲区中尚无完整帧:先防止溢出,再收一批数据 ----- */
if (recv_len >= REMO_BUF_SIZE - 256)
{
recv_len = 0; /* 异常情况:数据过多且始终不成帧,清空缓冲区防止越界 */
}
int n = TcpClient_Recv(client, (char*)(recv_buf + recv_len), REMO_BUF_SIZE - recv_len - 1);
if (n > 0)
{
recv_len += (unsigned int)n;
}
else
{
/* n==0 表示对方正常关闭连接n<0 表示读取出错;均退出本连接循环 */
printf("[TCP Server] 客户端关闭连接\n"); printf("[TCP Server] 客户端关闭连接\n");
break; break;
} }
@@ -223,16 +240,17 @@ void tcp_server_thread_fn(void* arg)
*ctx->p_server_sock = TCP_INVALID_SOCKET; *ctx->p_server_sock = TCP_INVALID_SOCKET;
printf("[TCP Server] 已退出\n"); printf("[TCP Server] 已退出\n");
} }
/* ---------------------------------------------------------------------------- /*
* 启动 TCP 服务服务器线程Tcp_Init + 创建线程 + 短暂等待就绪) * 函数功能:启动 TCP 服务并创建服务器线程
* port: 监听端口(如 7070 * 入口参数out_server_th - 输出线程句柄 thread_handle_t* 非空
* out_server_sock: 输出监听 socket供主线程退出时 TcpServer_Close * io_server_arg - 输入输出服务器线程参数 server_thread_arg_t* 非空
* out_server_quit: 输出退出标志,主线程置 1 通知服务器线程退出 * 出口参数:out_server_th - 输出创建的线程句柄
* out_server_th: 输出线程句柄,供主线程 Thread_Join * 返回值0 - 成功
* 返回0 成功1 失败(已调用 Tcp_Cleanup * 1 - 失败(已调用 Tcp_Cleanup
* ---------------------------------------------------------------------------- */ * 限定条件io_server_arg 必须初始化并提供有效端口、socket 和退出标志指针
int StartTcpServerThread(thread_handle_t *out_server_th, server_thread_arg_t *io_server_arg) * 函数说明:初始化 TCP 子系统并创建服务器线程,若失败则清理资源
{ */
int StartTcpServerThread(thread_handle_t *out_server_th, server_thread_arg_t *io_server_arg) {
if (Tcp_Init() != 0) { if (Tcp_Init() != 0) {
fprintf(stderr, "Tcp_Init failed\n"); fprintf(stderr, "Tcp_Init failed\n");
return 1; return 1;

View File

@@ -1,24 +1,38 @@
#ifndef __REMOTEDISPLAY_H #ifndef __REMOTEDISPLAY_H
#define __REMOTEDISPLAY_H #define __REMOTEDISPLAY_H
/*
* 模块名称Remote Display
* 模块功能:提供远程显示 TCP 服务器线程接口
* 适用平台:通用嵌入式平台
* 作者:王建锋
* 创建日期2026-05-11
* 修改记录:
* 2026-05-11 王建锋 创建初始版本
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "thread_utils.h" #include "thread_utils.h"
/* /*
* 远程显示 / TCP 服务器相关接口 * TCP 服务器线程参数
* - server_thread_arg_t: TCP 服务器线程参数
* - tcp_server_thread_fn: 服务器线程入口函数(用于 Thread_Create
*/ */
typedef struct { typedef struct {
int port; /* 监听端口号(如 7070 */ uint16_t port; /* 监听端口号(如 7070 */
int* p_server_sock; /* 线程内赋值为监听 socket主线程用其关闭监听 */ int *p_server_sock; /* 线程内赋值为监听 socket主线程用其关闭监听 */
volatile int* p_quit; /* 主线程置 1 通知线程退出 */ volatile int *p_quit; /* 主线程置 1 通知线程退出 */
} server_thread_arg_t; } server_thread_arg_t;
int StartTcpServerThread(thread_handle_t *out_server_th, server_thread_arg_t *io_server_arg); int StartTcpServerThread(thread_handle_t *out_server_th,
server_thread_arg_t *io_server_arg);
#ifdef __cplusplus
}
#endif #endif
#endif /* __REMOTEDISPLAY_H */

View File

@@ -52,6 +52,7 @@ add_dtu_test(test_smoke tests_smoke.c)
add_dtu_test( add_dtu_test(
test_p0_remote_display test_p0_remote_display
test_p0_remote_display.c test_p0_remote_display.c
"${CMAKE_SOURCE_DIR}/src/remoteDisplayProtocol.c"
"${CMAKE_SOURCE_DIR}/src/Drv/lcd/lcd.c" "${CMAKE_SOURCE_DIR}/src/Drv/lcd/lcd.c"
"${CMAKE_SOURCE_DIR}/src/Drv/lcd/lcd_draw.c" "${CMAKE_SOURCE_DIR}/src/Drv/lcd/lcd_draw.c"
"${CMAKE_SOURCE_DIR}/src/Drv/lcd/lcd_text.c" "${CMAKE_SOURCE_DIR}/src/Drv/lcd/lcd_text.c"
@@ -60,6 +61,7 @@ add_dtu_test(
"${CMAKE_SOURCE_DIR}/src/TCP/tcp.c" "${CMAKE_SOURCE_DIR}/src/TCP/tcp.c"
"${CMAKE_SOURCE_DIR}/src/thread_utils.c" "${CMAKE_SOURCE_DIR}/src/thread_utils.c"
) )
target_compile_definitions(test_p0_remote_display PRIVATE UNIT_TEST)
add_dtu_test( add_dtu_test(
test_p0_utf8_hz12_get test_p0_utf8_hz12_get
test_p0_utf8_hz12_get.c test_p0_utf8_hz12_get.c

View File

@@ -1,13 +1,13 @@
/* P0 测试remoteDisplay 协议核心 /* P0 测试remoteDisplay 协议核心
* 目标: * 目标:
* - 校验 CRC 纯函数行为calc_crc * - 校验 CRC 纯函数行为calc_crc
* - 校验 RemoDispBus 帧解析边界parse_frame * - 校验 Protocol_ByteHandler 状态机解析行为
*/ */
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include "test_common.h" #include "test_common.h"
/* 直接包含 .c 以访问 static 函数calc_crc / parse_frame */ #include "../src/remoteDisplayProtocol.h"
#include "../src/remoteDisplay.c"
/* 用例1CRC 计算 /* 用例1CRC 计算
* - 空数据长度应返回 0 * - 空数据长度应返回 0
@@ -21,49 +21,64 @@ static int test_calc_crc(void)
return 0; return 0;
} }
/* 用例2合法帧解析 /* 用例2Protocol_ByteHandler 基本帧解析
* 验证: * 验证:完整 RemoDispBus 帧按字节输入后,状态机完成帧解析并保持正确 cmd/data
* - parse_frame 返回成功
* - cmd/data/data_len/consume 与期望一致
*/ */
static int test_parse_frame_ok(void) static int test_protocol_byte_handler_ok(void)
{ {
uint8_t cmd = 0; protocol_instance_t proto_ins;
const uint8_t* data = NULL;
unsigned int data_len = 0;
unsigned int consume = 0;
const uint8_t payload[] = {0x10, 0x20}; const uint8_t payload[] = {0x10, 0x20};
const uint8_t frame[] = {0xAA, 0x03, 0x00, 0x02, 0x10, 0x20, (uint8_t)(0x10 ^ 0x20)}; const uint8_t frame[] = {
TAG_CLIENT,
CMD_KEY,
0x00,
(uint8_t)sizeof(payload),
payload[0],
payload[1],
(uint8_t)(payload[0] ^ payload[1])
};
ASSERT_EQ_INT(1, parse_frame(frame, sizeof(frame), &cmd, &data, &data_len, &consume)); protocol_init(&proto_ins);
ASSERT_EQ_INT(0x03, cmd); ASSERT_EQ_INT(PROTO_STATE_WAIT_TAG, proto_ins.state);
ASSERT_EQ_INT(2, (int)data_len); ASSERT_EQ_INT(0, proto_ins.frame_done_flag);
ASSERT_EQ_INT((int)sizeof(frame), (int)consume);
ASSERT_EQ_INT(payload[0], data[0]);
ASSERT_EQ_INT(payload[1], data[1]);
for (unsigned int i = 0; i < sizeof(frame); ++i) {
protocol_byte_handler(&proto_ins, frame[i]);
}
ASSERT_EQ_INT(1, proto_ins.frame_done_flag);
ASSERT_EQ_INT(CMD_KEY, proto_ins.recv_cmd);
ASSERT_EQ_INT((int)sizeof(payload), (int)proto_ins.expect_data_len);
ASSERT_EQ_INT((int)sizeof(payload), (int)proto_ins.recv_len);
ASSERT_EQ_INT(payload[0], proto_ins.recv_buf[0]);
ASSERT_EQ_INT(payload[1], proto_ins.recv_buf[1]);
return 0; return 0;
} }
/* 用例3非法输入集合 /* 用例3Protocol_ByteHandler CRC 错误处理
* - TAG 非客户端 TAG * 验证CRC 校验失败后状态机重置为 WAIT_TAG不置完成标志
* - 帧长度不足(截断)
* - CRC 错误
* 期望均解析失败(返回 0
*/ */
static int test_parse_frame_invalid_cases(void) static int test_protocol_byte_handler_bad_crc(void)
{ {
uint8_t cmd = 0; protocol_instance_t proto_ins;
const uint8_t* data = NULL; const uint8_t payload[] = {0x10, 0x20};
unsigned int data_len = 0; const uint8_t frame[] = {
unsigned int consume = 0; TAG_CLIENT,
const uint8_t bad_tag[] = {0xBB, 0x03, 0x00, 0x00, 0x00}; CMD_KEY,
const uint8_t short_buf[] = {0xAA, 0x03, 0x00, 0x01}; 0x00,
const uint8_t bad_crc[] = {0xAA, 0x02, 0x00, 0x01, 0x55, 0x00}; (uint8_t)sizeof(payload),
payload[0],
payload[1],
0xFF
};
ASSERT_EQ_INT(0, parse_frame(bad_tag, sizeof(bad_tag), &cmd, &data, &data_len, &consume)); protocol_init(&proto_ins);
ASSERT_EQ_INT(0, parse_frame(short_buf, sizeof(short_buf), &cmd, &data, &data_len, &consume)); for (unsigned int i = 0; i < sizeof(frame); ++i) {
ASSERT_EQ_INT(0, parse_frame(bad_crc, sizeof(bad_crc), &cmd, &data, &data_len, &consume)); protocol_byte_handler(&proto_ins, frame[i]);
}
ASSERT_EQ_INT(PROTO_STATE_WAIT_TAG, proto_ins.state);
ASSERT_EQ_INT(0, proto_ins.frame_done_flag);
return 0; return 0;
} }
@@ -71,7 +86,7 @@ static int test_parse_frame_invalid_cases(void)
int main(void) int main(void)
{ {
if (test_calc_crc() != 0) return 1; if (test_calc_crc() != 0) return 1;
if (test_parse_frame_ok() != 0) return 1; if (test_protocol_byte_handler_ok() != 0) return 1;
if (test_parse_frame_invalid_cases() != 0) return 1; if (test_protocol_byte_handler_bad_crc() != 0) return 1;
return 0; return 0;
} }