# 协议架构说明

## 1. 分层原则

小程序当前把链路、协议、功能服务和页面视图拆开处理：

```text
BLE 透传链路
  transport/ble-core.js
  transport/ble-utils.js

协议层
  protocols/modbus-rtu/index.js
  protocols/storage-access/index.js
  protocols/bootloader/index.js

领域模型
  domain/parameter-groups/
  domain/storage-access/

功能服务
  features/manual-rtu/
  features/storage-access/
  features/parameter-groups/
  features/communication/
  features/bootloader/
  features/tools/

页面
  pages/home/
  pages/communication/
  pages/params/
  pages/settings/
```

协议层只负责帧格式、CRC、请求/响应解析和分片能力，不直接操作页面状态。

功能服务负责把协议层组合成业务动作，例如手动生成 Modbus 帧、同步 code 信息块、读取参数组、串口原始发送。

页面只负责展示、输入、按钮状态和用户反馈。

功能服务和传输层只依赖每套协议的入口文件：

- `protocols/modbus-rtu/index.js`
- `protocols/storage-access/index.js`
- `protocols/bootloader/index.js`

协议层保持一个协议一个文件。`index.js` 内部可以继续暴露 `response`、`client` 这类逻辑分组对象，但不要重新拆出协议内部的 `frame.js`、`response.js`、`client.js` 给功能层引用。

协议模式配置由 `store/settings-store.js` 统一维护，内部 key 使用协议目录名：

- `storage-access`：存储访问协议。
- `modbus-rtu`：标准 Modbus RTU。

页面层使用 `isStorageAccessProtocol`、`isModbusProtocol` 这类展示布尔字段，业务判断由 settings store 的协议判断函数生成。

历史配置字段只允许在 `store/settings-store.js` 的归一化入口迁移，例如旧的 `modbusProtocolMode`、`genericModbusMaxPacketLength` 会映射到新的 `protocolMode`、`parameterMaxPacketLength`。页面和功能服务不直接读取旧字段。

## 2. 传输层

目录：`transport/`

职责：

- `ble-core.js`：BLE 扫描、连接、通知订阅、发送队列、响应等待、收发日志和页面订阅状态。
- `ble-utils.js`：BLE 设备识别、目标 UUID 判断、包长推断、HEX/ArrayBuffer 转换、错误文案和特征值展示文本等纯工具。
- `ble-logs.js`：收发日志项构造、日志数量裁剪和清空日志状态。
- `ble-device-registry.js`：扫描设备合并、排序、清空、连接标记和 RSSI 展示更新。
- `protocol-helper-registry.js`：传输层协议 helper 的配置、懒加载和函数归一化。

传输层只处理蓝牙透传链路，不直接理解标准 Modbus 或存储访问协议的业务语义。响应解析通过 `configureProtocolHelpers` 注入协议 helper，由协议层决定如何识别完整回复帧。

## 3. 协议层

### 3.1 标准 Modbus RTU

入口：`protocols/modbus-rtu/index.js`

职责：

- 生成标准 Modbus RTU 请求帧。
- 校验 Modbus CRC。
- 解析标准 Modbus 响应。
- 支持标准功能码 `0x01`、`0x02`、`0x03`、`0x04`、`0x05`、`0x06`、`0x10`。
- 地址和数量按标准 Modbus 寄存器或线圈语义处理。

标准 Modbus 不读取 `info` 区，也不解析 `Modbus_Code_Info_t`。

### 3.2 存储访问协议

入口：`protocols/storage-access/index.js`

职责：

- 普通读写生成 `CMD ADDR LEN DATA CRC` 格式的存储访问帧。
- `0x0F info` 也使用 `CMD ADDR LEN DATA CRC` 格式，按普通只读响应解析。
- 使用 `CRC16-CCITT-FALSE`。
- 地址单位始终是字节。
- 长度单位始终是字节。
- 普通读写支持区域：
  - `0x01 data`
  - `0x02 idata`
  - `0x03 xdata`
  - `0x04 code`
- `0x0F info` 是只读同步区域，不作为普通变量区域写入。
- `code` 和 `info` 均为只读区域。
- `0x0F info` 当前读取 `ADDR=0x0000`、`LEN=0x0004`，返回数据为 code 区关键信息块的地址和长度。
- 读取完整 code 信息块时，通过 `AREA=0x04 code` 按最大包长分片读取。

完整帧格式见 `存储访问协议.md`。

### 3.3 Bootloader

入口：`protocols/bootloader/index.js`、`features/bootloader/`

职责：

- 保留独立升级协议。
- 不依赖 Modbus RTU。
- 不依赖存储访问协议。
- 升级工具仍在设置页的工具区入口中维护。

当前模块边界：

- `protocols/bootloader/index.js`：Bootloader 帧构建、CRC、响应解析、ACK/NAK 校验。
- `features/bootloader/service.js`：设置页升级状态、握手流程、固件加载、擦除/编程/校验流程编排。
- `features/bootloader/firmware.js`：芯片型号识别、Flash 容量推断、固件大小校验和升级地址布局。
- `features/bootloader/transport.js`：Bootloader 原始帧发送、响应等待、断连中止和超时处理。

## 4. 领域模型

### 4.1 参数组

目录：`domain/parameter-groups/`

职责：

- 定义参数组和寄存器/变量的标准数据结构。
- 支持标准 Modbus 寄存器组。
- 支持存储访问同步出来的结构体组。
- 支持字节地址变量、结构体字段、数组、bit field。
- 负责输入值、显示值、原始字节、原始字、数据类型转换。

参数组不是某一种协议的私有模型。标准 Modbus 和存储访问协议都会把可读写数据落到参数组模型上。

当前模块拆分：

- `constants.js`：寄存器类型、数据类型、布局类型、地址上限和导入导出字段白名单。
- `model.js`：参数组/寄存器规范化、地址布局、导入克隆和对外领域 API。
- `register-io.js`：寄存器读缓存解码、写入值编码、组级字节/字编码和读写分片计算。
- `value-types.js`：数据类型元数据、字节/字长度、bit field 长度、类型分类和显示能力判断。
- `value-text.js`：ASCII/UTF-8 文本字段的字节编码、尾部 0 裁剪和解码。
- `value-number.js`：整数/HEX/float 的解析、范围校验、显示格式化和大端字节转换。
- `value-codec.js`：寄存器值编码解码、文本/数值/float/bit field 转换、显示值和输入校验。
- `struct-parser.js`：C 结构体定义和结构体实例目录解析的对外入口。
- `struct-c-syntax.js`：注释剥离、类型别名、结构体查找、声明和 declarator 解析。
- `struct-layout.js`：结构体字段到参数寄存器的字节布局、数组展开、ASCII 字段和 bit field 展开。

### 4.2 存储访问信息解析

目录：`domain/storage-access/`

职责：

- 解析 code 区中的 `Modbus_Code_Info_t`。
- 从 `struct_table` 生成参数组初始结构。
- 根据 `mem_type` 映射到真实存储区域：
  - `0x01 DATA`
  - `0x02 IDATA`
  - `0x03 XDATA`
  - `0x04 CODE`
- 不把 `0x0F INFO` 当成普通变量区域写入；同步时按普通只读响应解析 `0x0F` 回复。

## 5. 功能服务

### 5.1 手动 Modbus 指令

目录：`features/manual-rtu/`

职责：

- 维护通讯页标准 Modbus 指令表单状态。
- 根据输入生成 Modbus RTU 帧。
- 支持写多个寄存器的多值输入。
- 发送后等待并格式化响应。
- 未连接蓝牙时仍允许生成帧；点击发送时再提示连接状态。

当前模块拆分：

- `service.js`：通讯页标准 Modbus 表单状态、弹窗开关和发送动作。
- `frame-builder.js`：功能码列表、HEX 参数解析、标准 Modbus 帧生成、期望响应描述和回复文本格式化。
- `multiple-registers.js`：写多个寄存器时的数量规范化、字段生成、数据类型切换、值编码和输入校验。

### 5.2 存储访问同步

目录：`features/storage-access/`

职责：

- 读取 `0x0F info` 的 `ADDR=0x0000`、`LEN=0x0004` 并解析返回数据。
- 根据返回的地址和长度分片读取 `0x04 code` 中的完整信息块。
- 调用 `domain/storage-access` 解析结构体表。
- 将解析出的结构体组导入 `features/parameter-groups`。

### 5.3 参数组服务

目录：`features/parameter-groups/`

职责：

- 参数组持久化、导入、导出。
- 标准 Modbus 参数组读写。
- 存储访问结构体组读写。
- 自动轮询。
- 修改后焦点切换自动写入。
- 结构体定义导入后的字段补全。

存储访问协议下，参数组按字节地址读写；标准 Modbus 下，参数组按 Modbus 寄存器/线圈地址读写。

当前模块拆分：

- `service.js`：参数组页面入口 API、导入导出、结构体补全和协议读写调度。
- `store.js`：参数组状态容器、初始化、订阅通知和本地持久化触发。
- `persistence.js`：参数组 JSON 存储、导入、导出。
- `import-merge.js`：导入去重、重复变量更新、聚合组变量合并。
- `struct-completion.js`：结构体定义解析后的实例匹配、字段补全、数组和 bit field 展开。
- `storage-access-io.js`：存储访问协议参数组读写、data/idata/xdata/code 区域映射、字节地址缓存和 bit field 读改写。
- `modbus-io.js`：标准 Modbus 参数组读写、线圈写入、多寄存器编码和按最大包长拆分写入。
- `state-mappers.js`：读取缓存和写入快照映射回参数组寄存器展示态。
- `poller.js`：按设置间隔轮询参数组。
- `view-model.js`：参数页展示态转换。
- `drag-view-model.js`：参数页寄存器拖拽排序的索引、位移和行样式计算。
- `dialog-handlers.js`：参数页新建/编辑参数组、寄存器信息弹窗和结构体解析交互处理器。

### 5.4 通讯页服务

目录：`features/communication/`

职责：

- 串口原始发送。
- 通讯页存储访问指令卡片。
- 日志显示模式转换。
- 根据设置中的协议模式显示对应的指令控制卡片。

### 5.5 工具页服务

目录：`features/tools/`

职责：

- 设置页工具入口导航。
- 汇总 CRC/哈希、滤波器、阻抗、贴片码、制冷、三相功率等工具的初始状态。
- 按工具域拆分设置页事件处理器。

当前模块拆分：

- `navigation.js`：设置页工具入口、标题和视图识别。
- `page.js`：工具初始状态与页面事件处理器聚合入口。
- `handlers/common.js`：工具结果复制等通用事件。
- `handlers/crc.js`：CRC/哈希配置、输入、文件加载、计算和清空。
- `handlers/filter.js`：滤波器输入、单位切换、网络/响应切换和归一化。
- `handlers/reactance.js`：阻抗输入、单位切换、模式切换和归一化。
- `handlers/smd-code.js`：贴片电阻/电容代码类型、格式和输入。
- `handlers/refrigeration.js`：制冷单位换算模式和输入。
- `handlers/three-phase-power.js`：三相接法、功率/电气量输入和驱动字段维护。

## 6. 页面职责

### 6.1 首页

目录：`pages/home/`

职责：

- 蓝牙扫描。
- 蓝牙连接。
- 显示连接状态。

首页不再承载 Modbus 指令生成。

### 6.2 通讯页

目录：`pages/communication/`

布局顺序：

1. 串口发送卡片。
2. 当前协议对应的指令卡片。
3. 收发日志。

标准 Modbus 模式显示 Modbus 指令卡片。

存储访问模式显示同步、读取、写入指令卡片。

### 6.3 参数页

目录：`pages/params/`

职责：

- 展示参数组列表。
- 存储访问模式下通过同步按钮生成结构体组。
- 存储访问模式下通过轮询读取结构体组。
- 修改字段后在焦点切换时自动下发。
- 标准 Modbus 模式下保留新建参数组、读组、写组能力。

参数页不再包含手动 Modbus 指令窗口。

### 6.4 设置页

目录：`pages/settings/`

职责：

- 协议模式选择。
- 从机地址配置。
- 参数轮询间隔和最大包长配置。
- Bootloader 升级。
- CRC、滤波、SMD、制冷、三相功率等工具入口。

## 7. 数据流

### 7.1 存储访问同步数据流

```text
用户点击同步
  pages/params 或 pages/communication
    -> features/storage-access/service.syncCodeInfo
      -> protocols/storage-access/index.js readCodeInfoBlock
        -> 读取 AREA=0x0F ADDR=0x0000 LEN=0x0004
        -> 按普通读响应解析 DATA 中的 code 地址和长度
        -> 读 AREA=0x04 ADDR=CODE_ADDR LEN=CODE_LEN
      -> domain/storage-access/code-info-parser.parseCodeInfo
      -> domain/storage-access/code-info-parser.createGroupsFromCodeInfo
      -> features/parameter-groups/service.mergeImportedGroups
```

### 7.2 存储访问参数读取数据流

```text
参数组轮询或手动读取
  -> features/parameter-groups/service.readGroup
    -> features/storage-access/memory-service.readMemory
      -> protocols/storage-access/index.js readMemory
        -> AREA 使用结构体表中的 mem_type
        -> ADDR 使用结构体实例字节地址
        -> LEN 使用结构体实例字节长度
```

### 7.3 标准 Modbus 指令数据流

```text
通讯页填写指令
  -> features/manual-rtu/service 生成标准 Modbus RTU 帧
  -> transport/ble-core.js 下发
  -> protocols/modbus-rtu/index.js 解析回复
  -> 通讯页显示回复与日志
```

## 8. 维护约束

1. 不要把存储访问协议挂到 Modbus RTU 协议目录下。
2. `0x0F info` 只作为只读同步区域，必须按普通读响应校验 CMD、ADDR、LEN、DATA 和 CRC。
3. 存储访问协议的地址和长度始终按字节处理。
4. 标准 Modbus 的地址和数量始终按标准寄存器/线圈语义处理。
5. 参数组模型保持协议中立。
6. Bootloader 升级和工具页保持独立，不随参数协议重构删除。
7. 新功能优先放到对应协议或 feature 模块，不直接写进页面。
