# 方控按键 M2A 通信测试报告

## 基本信息

| 项目 | 内容 |
|------|------|
| 日期 | 2026-05-29 |
| 项目 | QSJNIC 车载 Android 中间件 |
| 版本 | v1.0.0-beta6 |
| MCU 固件 | swVersion=0302_20260527 |
| MCU 硬件 | hwVersion=PAJERO69XZA0120018 |
| 测试设备 | 车机 192.168.0.66 |
| 协议文档 | `docs/MCU_ARM_Reference/Key.xlsx` → "其它项目" 映射表 |
| MCU 方控自测文档 | `docs/MCU_ARM_Reference/1.方控和车速自测.txt` |
| 测试工具 | Xshell (https://www.xshell.com/zh/xshell/) |

---

## 一、测试前提

Android 中间件服务 (`com.qsjnic.mcu.service`) 必须与 MCU 建链成功。

---

## 二、实物测试（方控板接线）

### 2.1 接线方式

- 方控板 KEY 线 → 车机尾线 SWC_L
- 方控板 GND 线  → 车机尾线 GND

### 2.2 MCU 端日志

每次按下方控按键，MCU 串口打印如下格式日志：

```
I(0000025683) KEYMGR,keymgr_key_trigger_handle:key_type[04] state[TRIGGER]
[ARM_CORE,write data:] ff,aa,00,0b,08,06,02,01,04,01,de
I(0000026043) KEYMGR,keymgr_key_trigger_handle:key_type[04] state[IDLE]
[ARM_CORE,write data:] ff,aa,00,0b,09,06,02,01,04,00,de
```

### 2.3 串口帧结构解析

以 `ff,aa,00,0b,08,06,02,01,04,01,de` 为例：

| 字节 | 值 | 含义 |
|------|-----|------|
| H0-H1 | ff aa | 帧头 |
| L0-L1 | 00 0b | 帧长度 = 11 字节 |
| Seq | 08 | 序列号 |
| Type | 06 | 帧类型 |
| MsgType | **02** | KEY 域 |
| Cmd | **01** | M2A_KEY (MCU→ARM) |
| P0 | **04** | KeyValue (body[0]) |
| P1 | **01** | KeyStatus (body[1]) |
| CS | de | 校验和 |

### 2.4 Android 端日志

MCU 帧到达 ARM 后，FrameRouter 打印：

```
I/FrameRouter: KEY value=0x04 status=0x01
```

---

## 三、模拟测试（Shell/串口命令）

在不接实物方控板时，可通过 MCU 串口 Shell 直接注入按键帧。

### 3.1 命令格式

```
KeyTest <测试项> <按键值> <按键状态>
```

| 参数 | 说明 | 示例 |
|------|------|------|
| 测试项 | 固定为 `1`（M2A 按键测试） | 1 |
| 按键值 | 帕杰罗 KeyValue（0x00-0x25） | 0x19 |
| 按键状态 | 0x01=按下(TRIGGER), 0x00=弹起(IDLE) | 0x01 |

### 3.2 示例

挂断键按下和弹起：

```
xiexw:/$ KeyTest 1 0x19 0x01
I(0000490647) KEYMGR,KeyTest:KeyTest mode:1 key:0x19 value:0x01
[ARM_CORE,write data:] ff,aa,00,0b,1c,06,02,01,19,01,b5

xiexw:/$ KeyTest 1 0x19 0x00
I(0000535107) KEYMGR,KeyTest:KeyTest mode:1 key:0x19 value:0x00
[ARM_CORE,write data:] ff,aa,00,0b,1d,06,02,01,19,00,b5
```

### 3.3 全部 9 个帕杰罗按键模拟命令

```
# 语音
KeyTest 1 0x03 0x01
KeyTest 1 0x03 0x00

# 音乐
KeyTest 1 0x04 0x01
KeyTest 1 0x04 0x00

# 音量-
KeyTest 1 0x08 0x01
KeyTest 1 0x08 0x00

# 音量+
KeyTest 1 0x09 0x01
KeyTest 1 0x09 0x00

# 上一曲
KeyTest 1 0x0E 0x01
KeyTest 1 0x0E 0x00

# 下一曲
KeyTest 1 0x0F 0x01
KeyTest 1 0x0F 0x00

# 接听
KeyTest 1 0x18 0x01
KeyTest 1 0x18 0x00

# 挂断
KeyTest 1 0x19 0x01
KeyTest 1 0x19 0x00

# 摄像头
KeyTest 1 0x25 0x01
KeyTest 1 0x25 0x00
```

---

## 四、帕杰罗方控按键值定义

MCU 固件侧枚举（`docs/MCU_ARM_Reference/1.方控和车速自测.txt`）：

```c
typedef enum
{
    EN_KEYMGR_SWC_TYPE_IDLE             = 0x00,//空闲
    EN_KEYMGR_SWC_TYPE_VOLUME_DOWN      = 0x08,//音量减
    EN_KEYMGR_SWC_TYPE_VOLUME_UP        = 0x09,//音量加
    EN_KEYMGR_SWC_TYPE_NEXT             = 0x0F,//下一曲
    EN_KEYMGR_SWC_TYPE_PREV             = 0x0E,//上一曲
    EN_KEYMGR_SWC_TYPE_MUSIC            = 0x04,//音乐
    EN_KEYMGR_SWC_TYPE_SPEECH           = 0x03,//语音
    EN_KEYMGR_SWC_TYPE_ANSWER           = 0x18,//接听
    EN_KEYMGR_SWC_TYPE_REJECT           = 0x19,//挂断
    EN_KEYMGR_SWC_TYPE_CAMERA           = 0x25,//摄像头
} EN_KEYMGR_SWC_TYPE;
```

对应 Key.xlsx "其它项目" 映射表（行 44-73）。

---

## 五、Android 端 M2A 实测结果

所有 9 种按键均通过物理方控板触发，Android 端 FrameRouter 完整捕获。

| 按键值 | 帕杰罗功能 | MC3范围内? | 接收次数 | 状态 |
|--------|-----------|-----------|---------|------|
| 0x03 | KEY_VOICE 语音 | ✓ | 2 | 正常 |
| 0x04 | KEY_MUSIC 音乐 | ✓ | 3 | 正常 |
| 0x08 | KEY_VOL_DEC 音量- | ✓ | 2 | 正常 |
| 0x09 | KEY_VOL_INC 音量+ | ✓ | 2 | 正常 |
| 0x0E | KEY_PREV 上一曲 | ✗ 扩展值 | 3 | 正常 |
| 0x0F | KEY_NEXT 下一曲 | ✗ 扩展值 | 2 | 正常 |
| 0x18 | KEY_ANSWER 接听 | ✗ 扩展值 | 1 | 正常 |
| 0x19 | KEY_REJECT 挂断 | ✗ 扩展值 | 1 | 正常 |
| 0x25 | KEY_CAMERA 摄像头 | ✗ 扩展值 | 1 | 正常 |

### Android 端日志示例

```
I/FrameRouter: KEY value=0x04 status=0x01    ← 音乐键按下
I/FrameRouter: KEY value=0x04 status=0x00    ← 音乐键弹起
I/FrameRouter: KEY value=0x0E status=0x01    ← 上一曲按下
I/FrameRouter: KEY value=0x0E status=0x00    ← 上一曲弹起
I/FrameRouter: KEY value=0x0F status=0x01    ← 下一曲按下
I/FrameRouter: KEY value=0x0F status=0x00    ← 下一曲弹起
I/FrameRouter: KEY value=0x09 status=0x01    ← 音量+按下
I/FrameRouter: KEY value=0x08 status=0x01    ← 音量-按下
I/FrameRouter: KEY value=0x03 status=0x01    ← 语音键按下
I/FrameRouter: KEY value=0x18 status=0x01    ← 接听键按下
I/FrameRouter: KEY value=0x19 status=0x01    ← 挂断键按下
I/FrameRouter: KEY value=0x25 status=0x01    ← 摄像头键按下
```

---

## 六、Android 端 M2A 接收链路确认

```
MCU 串口 TX
    ↓
C 协议层 (mcu_protocol.c) — 帧解码
    ↓
JNI (jni_bridge.cpp) — body 字节提取
    ↓
FrameRouter.dispatch() — msgType=0x02 路由
    ↓
FrameRouter.handleKey() — cmd=0x01, 无 keyValue 范围校验
    ↓
KeyFeature.onFrame() — 透传至 Decoders
    ↓
Decoders.parseKeyControl() — 仅校验 body.length >= 2
    ↓
broadcastKeyEvent(keyValue, keyStatus) — 广播至所有监听者
    ↓
Vehicle Demo App (IMcuKeyListener.onKeyEvent)
```

**全链路无任何 keyValue 范围过滤。MCU 上报的任何值（0x00-0x25）均可完整到达应用层。**

---

## 七、结论

1. **M2A 方向**：9 种帕杰罗方控按键全部正常接收，含 5 个 MC3 范围外扩展值（0x0E/0x0F/0x18/0x19/0x25），按下和弹起事件完整
2. **串口协议**：帧结构（ff aa + len + seq + type + msgType=02 + cmd=01 + keyValue + keyStatus + cs）一致
3. **已知问题**：SDK 常量使用 MC3 映射表，与帕杰罗映射值语义不同，需后续对齐
4. **A2M 方向**：自测文档明确 "KEY_A2M_KEY 暂时不用实现"，当前无业务影响

---

## 八、参考文档

| 文档 | 路径 |
|------|------|
| Key 协议 (MC3 + 其它项目映射) | `docs/MCU_ARM_Reference/Key.xlsx` |
| 方控和车速自测 (MCU 侧) | `docs/MCU_ARM_Reference/1.方控和车速自测.txt` |
| MCU-ARM 接口清单 | `docs/MCU_ARM_Reference/20260513/MCU_ARM_接口文档清单与明细_20260513.md` |
| 全链路测试报告 | `imgs/full_test_report.md` |
| SDK Key 常量 | `sdk/src/main/java/com/qsjnic/mcu/sdk/McuKeyClient.java` |
| Key 编码校验 | `contract/src/main/java/com/qsjnic/mcu/domain/Commands.java` |

---

Android 中间件测试组
2026-05-29
