我在构建一款触觉传感器的工业上位机，主要用到了qml，opengl。我下面会说明我的需求。

## ui

ui方面我希望使用1+3的模式，最上面是nav导航条，暂定有Title（左）和lightmode、language（右）。可以直观的展示名字、明暗和语言。ui风格使用qml中的material.green风格。
下面是三栏，左边是panel，控制传感器的连接，opengl的展示和量程，规格等数据（这个我希望可以支持补充，我已经做好了一个LeftPanel.qml你可以参考）。中间是opengl对传感器的3D渲染。右边是一些可视化指标，折线图等。

## 整体设计

我希望可以对软件进行分层设计，有统一的后端（AppBackend）。这个AppBackend驱动其他功能组件。

首先是串口数据采集层，我希望可以抽象为codec，decodec，format，manager（类似ffmpeg）的设计来适配不同协议的传感器。传感器有从站模式和主站模式，你可以抽象为一个统一个config，在界面上配置参数，地址应该是一个十六进制的值（类似0x01）我觉得使用输入框比较好，如果是从站模式（也就是需要发送指令才能获取数据的），需要有一个参数配置采样频率（也就是多少时间发一次request）。我希望串口层是一个独立的层，他不负责业务功能，只提供基础的采集和slave功能。每个编解码器需要提供对应的接口（这里你需要预留一些接口让我来填充），比如获取版本号，获取传感器规格，request数据。解码器负责将接受到的一帧数据packet解码数据形成frame格式，frame中需要有pts（年月日时分妙毫秒202601011208xxx，24小时制）、功能码、数据（比如3*4规格就要有12个数据）

为了避免采集功能造成ui卡顿，需要分别创建读取线程，解码线程，发送线程，类比ffmpeg的开发将frame和packet存储在一个队列里面，解码线程解码结束后将解码好的frame送入数据驱动层。如果是从站模式，那么request的编码和发送应该在发送线程进行编码和发送。我需要你完整的编写基于三个线程的编解码函数包括如何送入数据驱动层和导出。考虑到可能有多种编码器，我希望你在串口类中将几个函数抽象为function（比如request，parse等等）,然后由对应的解码器类来提供实际的函数，类似find_decodec后的回调赋值。

现在来说数据驱动层，这里负责接受解码器的frame。存储到一个容器中，如果串口是打开的情况下，需要不断给ui输出最新数据，这里预留一个输出回调，我需要对给出数据的渲染进行一些自定义操作。数据驱动层还需要负责数据导出的功能，这里可以选择导出frame包（json格式）作为日志查看，也可以有导出csv的功能（pts,data1,data2）用来做数据分析。此外，我还需要数据层做到可以导入csv或者json数据来做数据回放，即导入数据后点击回放就重新展示导入的数据，当然这里数据显示也预留接口我来写这个展示回调。为了避免数据堆积，在新一次打开串口采集后或者导入新数据后就清掉上一次缓存或导入的数据（清空容器）。

关于opengl渲染，有一下内容需要实现。首先是我现在在opengl中使用dot着色器画出了很多点，但是这些都是画出来的不是实体控件，我现在捕获他们的点击事件来知道是哪个点并通过signal发出去怎么做呢，我预计是在RightPanel中的折线图中有数据显示麻（当然这个后面再说当前已经有了一个折线图placehold），但是起码需要有一个点击了某个点然后可以知道切发去信号。

关于数据的可视化，我这边计划使用opengl+一些折线图。这个后面说

下面我会提供“压阻A型”串口读，应答，协议结构。

- request

| 字段 | data索引范围 | 长度(字节) | 示例值 / 说明 | 字节序 |
|------|--------------|------------|---------------|--------|
| 起始符0 | data[0] | 1 | 0x55 | 小端 |
| 起始符1 | data[1] | 1 | 0xAA | 小端 |
| 数据长度 | data[2-3] | 2 | 数据长度（2字节） | 小端 |
| 设备地址 | data[4] | 1 | 设备地址（1字节） | - |
| 预留 | data[5] | 1 | 0x00 | - |
| 0x80 + 功能码 | data[6] | 1 | 0x80 + 功能码 | - |
| 起始地址 | data[7-10] | 4 | 起始地址（4字节） | 小端 |
| 读取数据长度 | data[11-12] | 2 | 读取数据长度（2字节） | 小端 |
| CRC | data[13] | 1 | CRC 校验（1字节） | - |

数据长度：从data[4]-data[12]

- reply

| 字段 | data索引范围 | 长度(字节) | 示例值 / 说明 | 字节序 |
|------|--------------|------------|---------------|--------|
| 起始符0 | data[0] | 1 | 0x55 | 小端 |
| 起始符1 | data[1] | 1 | 0xAA | 小端 |
| 数据长度 | data[2-3] | 2 | 数据长度（2字节） | 小端 |
| 设备地址 | data[4] | 1 | 设备地址（1字节） | - |
| 预留 | data[5] | 1 | 0x00 | - |
| 0x80 + 功能码 | data[6] | 1 | 0x80 + 功能码（示例：0xFB） | - |
| 起始地址 | data[7-10] | 4 | 起始地址（4字节） | 小端 |
| 返回字节数 | data[11-12] | 2 | 返回数据字节数 N（2字节） | 小端 |
| 状态 | data[13] | 1 | 0 = 成功；非0 = 失败 | - |
| 读取数据 | data[14 ... 13+N] | N | 读取到的数据（N字节，可变长度） | - |
| CRC | data[14+N] | 1 | CRC 校验（1字节） | - |

数据长度：从data[4]-data[N+13]

> ps:crc都是使用的CRC-8ITU

我需要你根据协议内容编写可使用的采集、发送和解算和可视化代码。可视化部分流出TODO让我编写。Serial可以使用QT自带的QSerialPort或者serial库（我已经放在了项目目录下）。编写完成后在文档中画好好这些操作的流程图和对应的函数调用，你可以使用mermain。

## 文档

1. 用mermind绘制uml图，让我可以清晰的了解到项目的框架。
2. 明确写出各个类的接口参数、作用，成员变量作用
3. ui部分qml的层级接口，qml不同component的作用

注意：

1. 一定要注意预留接口
2. 层级分明，方便我后续迭代
3. 在接口预留的位置标注`// TODO:待实现内容(具体写需要实现什么)`
4. 文档和TODO说明使用中
5. 每一次的修改都需要在文档中有说明和体现