# DG-LAB V3 波形数据格式

> 源自 [DG-LAB V3 蓝牙协议](https://github.com/DG-LAB-OPENSOURCE/DG-LAB-OPENSOURCE/blob/main/coyote/v3/README_V3.md)
> 及 [波形示例数据](https://github.com/DG-LAB-OPENSOURCE/DG-LAB-OPENSOURCE/blob/main/socket/DG_WAVES_V2_V3_simple.js)。

## 目录

- [HEX 条目格式](#hex-条目格式)
- [频率参数](#频率参数)
- [强度参数](#强度参数)
- [频率换算公式](#频率换算公式)
- [约束与限制](#约束与限制)
- [示例解析](#示例解析)

---

## HEX 条目格式

每条波形数据为 **16 个十六进制字符**（8 字节），代表 **100ms** 的脉冲输出：

```
FFFFFFFFF IIIIIIII
│         │
│         └── 4 字节强度 (intensity): 每字节代表 25ms
└──────────── 4 字节频率 (frequency): 每字节代表 25ms
```

4 个频率字节和 4 个强度字节分别对应 100ms 内的 4 个 25ms 时间片。简单使用时可将 4 个字节设为相同值。

**示例:** `0A0A0A0A64646464`

- 频率: `0A 0A 0A 0A` → 4 个 25ms 均为 10 (0x0A)
- 强度: `64 64 64 64` → 4 个 25ms 均为 100 (0x64)

## 频率参数

| 属性 | 值 |
|------|-----|
| 协议字节范围 | 10 ~ 240 |
| 用户输入范围 | 10 ~ 1000 |
| 单位 | 无量纲（越高频率越高） |
| 无效值行为 | 该通道全部 4 组数据被丢弃 |

低频率 (10~20) 体感为缓慢的脉动，高频率 (100+) 体感为连续的震动。

## 强度参数

| 属性 | 值 |
|------|-----|
| 范围 | 0 ~ 100 |
| 0 | 无输出（静默） |
| 100 | 满强度 (0x64) |
| 无效值 (>100) | 该通道全部 4 组数据被丢弃 |

> 利用此特性：向不需要输出的通道发送一个强度 >100 的值（如 101/0x65）即可使该通道静默。

## 频率换算公式

将用户友好的频率值 (10~1000) 转换为协议字节 (10~240)：

```python
def freq_to_byte(value):
    if 10 <= value <= 100:
        return value
    elif 101 <= value <= 600:
        return (value - 100) // 5 + 100
    elif 601 <= value <= 1000:
        return (value - 600) // 10 + 200
    else:
        return 10
```

| 输入范围 | 输出范围 | 精度 |
|----------|----------|------|
| 10-100 | 10-100 | 1:1 |
| 101-600 | 100-200 | 每 5 一档 |
| 601-1000 | 200-240 | 每 10 一档 |

## 约束与限制

| 约束 | 值 |
|------|-----|
| 单条消息最大条目数 | 100 条 (10 秒数据) |
| APP 波形队列最大缓存 | 500 条 (50 秒) |
| 建议发送间隔 | 略小于数据时长，保证连续性 |
| JSON 消息最大字符数 | 1950 |

## 示例解析

### 全零（静默）

```
0A0A0A0A00000000
```
频率=10（最低），强度=0（无输出）

### 满强度低频

```
0A0A0A0A64646464
```
频率=10，强度=100 — 低频满强度脉冲

### 满强度高频

```
7070707064646464
```
频率=112 (0x70)，强度=100 — 高频满强度

### 渐变（淡入）

```
0A0A0A0A00000000   → 强度 0
0A0A0A0A14141414   → 强度 20
0A0A0A0A28282828   → 强度 40
0A0A0A0A3C3C3C3C   → 强度 60
0A0A0A0A50505050   → 强度 80
0A0A0A0A64646464   → 强度 100
```
频率不变，强度线性增长 — "呼吸"效果的上升段

### 变频

```
4A4A4A4A64646464   → 频率 74, 强度 100
4545454564646464   → 频率 69
4040404064646464   → 频率 64
...
0A0A0A0A64646464   → 频率 10
```
频率递减、强度不变 — "压缩"效果
