# Factory Test Module **Repository Path**: Xavier_09/factory-test-module ## Basic Information - **Project Name**: Factory Test Module - **Description**: # Factory Test Module 产测功能模块 - 用于设备生产测试的命令处理模块 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-18 - **Last Updated**: 2026-08-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Factory Test Module 产测功能模块 - 用于设备生产测试的命令处理模块 ## 功能特性 - 支持蓝牙名称设置命令 - 支持序列号设置命令 - 支持设备重启命令 - 支持设备关机命令 - 完整的命令响应机制 - 依赖注入设计,便于集成 --- ## 通信协议 ### 传输通道 | 通道 | BLE 特征 | 方向 | 说明 | |------|----------|------|------| | 命令写入 | **FF02** (Write) | 手机 → 设备 | 发送产测命令 | | 响应通知 | **FF03** (Notify) | 设备 → 手机 | 返回命令执行结果 | ### 命令帧格式 (FF02 Write) 命令帧为 **ASCII 字符串**,格式固定为: ``` <命令前缀>:<参数> ``` | 字段 | 类型 | 说明 | |------|------|------| | 命令前缀 | ASCII 字符串 | 标识命令类型,以 `:` 结尾 | | 参数 | ASCII 字符串 | 可选,紧跟在 `:` 之后 | ### 响应帧格式 (FF03 Notify) #### 帧结构 响应帧为**全字符串协议**,无任何二进制长度字段,通过 `:` 分隔符解析。 ``` ┌──────────────────────┬──────┬──────────────────────┐ │ cmd │ ':' │ msg │ │ (命令字符串) │ │ (结果+消息) │ └──────────────────────┴──────┴──────────────────────┘ ``` | 字段 | 类型 | 说明 | |------|------|------| | `cmd` | ASCII 字符串 | 命令名称(如 `set ble name`) | | `msg` | ASCII 字符串 | 结果码 + 消息(如 `ok`、`err:param`) | **响应帧总长度** = `cmd_len + 1 + msg_len`(`:` 为分隔符) #### msg 结果码 | msg 值 | 含义 | 对应原枚举 | |--------|------|-----------| | `ok` | 成功 | `FACTORY_TEST_RESULT_SUCCESS` | | `err:param` | 参数错误 | `FACTORY_TEST_RESULT_ERROR_PARAM` | | `err:not_init` | 未初始化 | `FACTORY_TEST_RESULT_ERROR_NOT_INIT` | | `err:cmd_not_found` | 命令未找到 | `FACTORY_TEST_RESULT_ERROR_CMD_NOT_FOUND` | | `err:unknown` | 未知错误 | `FACTORY_TEST_RESULT_ERROR_UNKNOWN` | **解析规则**:msg 以 `ok` 开头 = 成功,以 `err:` 开头 = 错误。 #### 各命令帧长度 | 命令 | cmd | msg | 帧长度 | MTU=20 单包 | |------|-----|-----|--------|-------------| | set ble name 成功 | `"set ble name"` (13) | `"ok"` (2) | **16 字节** | ✅ | | set ble name 失败 | `"set ble name"` (13) | `"err:param"` (9) | **23 字节** | ❌ | | set sn 成功 | `"set sn"` (6) | `"ok"` (2) | **9 字节** | ✅ | | set sn 失败 | `"set sn"` (6) | `"err:param"` (9) | **16 字节** | ✅ | | reboot | `"reboot"` (6) | `"ok"` (2) | **9 字节** | ✅ | | power off | `"power off"` (10) | `"ok"` (2) | **13 字节** | ✅ | #### 帧结构示例 **set ble name 成功** (16 字节): ``` [s][e][t][ ][b][l][e][ ][n][a][m][e][:][o][k] └─────────── cmd ──────────┘ ↑ └msg┘ ':' ``` **set ble name 失败** (23 字节): ``` [s][e][t][ ][b][l][e][ ][n][a][m][e][:][e][r][r][:][p][a][r][a][m] └─────────── cmd ──────────┘ ↑ └──────── msg(9) ────────┘ ':' ``` --- ## 命令定义 | 命令 | FF02 Write 格式 | 响应 cmd | 成功 msg | 失败 msg | |------|----------------|----------|----------|----------| | 设置蓝牙名称 | `set ble name:<名称>` | `set ble name` | `ok` | `err:param` | | 设置序列号 | `set sn:<序列号>` | `set sn` | `ok` | `err:param` | | 重启设备 | `reboot:` | `reboot` | `ok` | — | | 关闭设备 | `power off:` | `power off` | `ok` | — | ### 1. 设置蓝牙名称 | 项目 | 说明 | |------|------| | **命令格式** | `set ble name:<蓝牙名称>` | | **参数** | 蓝牙名称字符串,最大 **30 字节** | | **示例** | `set ble name:MyDevice-001` | | **执行动作** | ① 更新蓝牙名称 ② 保存到 Flash ③ 设置重启标志 | ### 2. 设置序列号 | 项目 | 说明 | |------|------| | **命令格式** | `set sn:<序列号>` | | **参数** | 序列号字符串,最大 **63 字节** | | **示例** | `set sn:SN20260827001` | | **执行动作** | 更新序列号 | ### 3. 重启设备 | 项目 | 说明 | |------|------| | **命令格式** | `reboot:` | | **参数** | 无 | | **执行动作** | 通过看门狗复位重启设备 | ### 4. 关闭设备 | 项目 | 说明 | |------|------| | **命令格式** | `power off:` | | **参数** | 无 | | **执行动作** | 执行关机流程 | --- ## 响应码 (factory_test_result_t) | 值 | 枚举 | 对应 msg | 说明 | |----|------|----------|------| | 0 | `FACTORY_TEST_RESULT_SUCCESS` | `ok` | 命令执行成功 | | 1 | `FACTORY_TEST_RESULT_ERROR_PARAM` | `err:param` | 参数错误 | | 2 | `FACTORY_TEST_RESULT_ERROR_NOT_INIT` | `err:not_init` | 模块未初始化 | | 3 | `FACTORY_TEST_RESULT_ERROR_UNKNOWN` | `err:unknown` | 未知错误 | | 4 | `FACTORY_TEST_RESULT_ERROR_CMD_NOT_FOUND` | `err:cmd_not_found` | 命令未找到 | --- ## 拆包规则 当响应帧 **> MTU**(默认 20 字节)时,自动拆包: ``` 单片结构: [seq(1)][total(1)][payload(mtu-2)] ``` | 字段 | 说明 | |------|------| | `seq` | 分片序号(0 起始) | | `total` | 总分片数 | | `payload` | 原始响应帧的分片数据 | **手机端重组**:按 `seq` 顺序拼接 payload → 用 `\0` 分割 cmd 和 msg → 解析。 --- ## 交互流程 ``` ┌─────────┐ FF02 Write ┌─────────────────────┐ FF03 Notify ┌─────────┐ │ 手机 │ ─────────────────→ │ mc_factory_test_ │ ────────────────→ │ 手机 │ │ (Master) │ "set ble name: │ unpack() │ [cmd][:][msg] │ (Master)│ │ │ MyDevice-001" │ │ │ │ └─────────┘ └─────────────────────┘ └─────────┘ │ │ 匹配命令前缀 (ASCII字符串) ↓ ┌─────────────────────┐ │ 命令处理函数 │ │ ① update_ble_name │ │ ② save_data │ │ ③ set_reboot_sign │ │ ④ ft_response │ └─────────────────────┘ ``` > **命令匹配**:设备端用 ASCII 字符串前缀匹配命令(如 `"set ble name:"`), > **响应解析**:手机端用 `:` 分割 cmd 和 msg(如 `"set ble name:ok"`)。 --- ## 手机端解析伪代码 ```python def on_ff03_notify(data): data_str = data.decode() # 用 ':' 分割 cmd 和 msg colon_idx = data_str.index(':') cmd = data_str[:colon_idx] msg = data_str[colon_idx+1:] if msg.startswith("ok"): result = "success" elif msg.startswith("err:"): result = msg else: result = msg if cmd == "set ble name": print(f"蓝牙名称设置: {result}") elif cmd == "reboot": print(f"重启: {result}") elif cmd == "power off": print(f"关机: {result}") elif cmd == "set sn": print(f"序列号设置: {result}") else: print(f"未知命令[{cmd}]: {result}") ``` --- ## 接口说明 ### 初始化模块 ```c #include "factory_test.h" static void ft_raw_send(uint8_t *data, uint16_t len) { ble_yesoul_service_ff03_notify(data, len); } static uint16_t ft_get_mtu(void) { return (uint16_t)GetPDUSize(); } factory_test_deps_t deps = { .debug_print = a_printf, .update_ble_name = ft_wrapper_update_ble_name, .update_sn = ft_wrapper_update_sn, .save_data = device_service_data_write, .set_reboot_sign = ft_wrapper_set_reboot_sign, .power_off = ft_wrapper_power_off, .send = ft_raw_send, .get_mtu = ft_get_mtu, }; factory_test_init(&deps); ``` ### 处理命令 ```c void on_ble_ff02_write(uint8_t *data, uint16_t len) { mc_factory_test_unpack(data, (uint8_t)len); } ``` > 💡 **协议处理**:响应帧打包(`cmd:msg`)、结果码映射(`ft_result_to_msg`)、 > MTU 拆包(`ft_send_fragmented`)均已在 `factory_test.c` 内部完成, > 外部只需提供 `send` 和 `get_mtu` 两个底层回调。 ### 版本查询 ```c uint32_t version = factory_test_get_version(); // 版本格式:0xMMMMPPPP uint8_t major = (version >> 16) & 0xFF; // 主版本 uint8_t minor = (version >> 8) & 0xFF; // 次版本 uint8_t patch = version & 0xFF; // 修订版本 ``` --- ## 依赖注入说明 本模块采用**依赖注入**模式,所有外部功能通过 `factory_test_deps_t` 结构体注入: | 依赖函数指针 | 类型 | 说明 | |-------------|------|------| | `debug_print` | `void (*)(const char*, ...)` | 调试打印,如 `a_printf` | | `update_ble_name` | `void (*)(void*, uint8_t)` | 更新蓝牙名称 | | `update_sn` | `void (*)(void*, uint8_t)` | 更新序列号 | | `save_data` | `void (*)(void)` | 保存数据到持久化存储 | | `set_reboot_sign` | `void (*)(uint8_t)` | 设置重启标志(使用系统重启功能) | | `power_off` | `void (*)(void)` | 关机 | | `send` | `void (*)(uint8_t*, uint16_t)` | 原始数据发送(BLE Notify) | | `get_mtu` | `uint16_t (*)(void)` | 获取当前 MTU 值 | > ⚠️ **注意**:宏(如 `printf`、`WDT_RST`)无法直接取地址,需通过**包装函数**间接调用。 --- ## 目录结构 ``` factory_test/ ├── factory_test.h # 接口定义 ├── factory_test.c # 实现代码 └── README.md # 协议与接口文档 ``` ## 依赖 - C99 或更高版本 - 标准 C 库 (`string.h`, `stdint.h`, `stddef.h`) ## 许可证 MIT License