Files
NTK_NFY_Communication_Protocol/NTK_NFY_Communication_Protocol.md
2025-08-20 18:15:51 +08:00

28 KiB
Raw Blame History

NTK_NFY_Communication_Protocol


一.概述

NTK_NFY_Communication_Protocol © 2025 by JiangXiNaoTiaoKong is licensed under CC BY-NC-ND 4.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-nd/4.0/


二.目录

一.概述 二.目录 三.修改记录 四.基本数据格式 五.头戴设备功能码表


三.修改记录

  • V0.22025.0530.0909 江鑫辉 1.数据格式增加设备ID 2.增加头戴设备部分功能码
  • V0.3: 2025.0715.1556 江鑫辉 1.改写 markdown 格式 2.增加头戴设备部分功能码
  • V0.4: 2025.0729.1457 江鑫辉 1.增加头戴设备功能控制指令 2.增加主机端0x8F,0x9C,0x9D功能码

四.基本数据格式

通信数据采用HEX编码采用主从应答方式进行通信头戴设备、平板、电视大屏为主端客户端电脑端软件为从端服务器响应客户端的服务请求。

4.1 数据包结构总览

起始位置 结束位置 名称/描述 类型 长度(字节) 是否固定值 大小端
0 1 帧头 uint8_t 1 0x5A \
1 2 类型 uint8_t 1 \ \
2 3 设备ID uint8_t 1 \ \
3 4 功能码 uint8_t 1 \ \
4 6 数据长度 uint16_t 2 \ 大端模式
6 8 保留位 \ 3 \ \
8 CRC_H = ( 8+N ) 数据 (非固定 常用int32_t) N \ 小端模式
CRC_H CRC_H + 2 CRC16校验和 uint16_t 1 \ 小端模式
CRC_H + 2 CRC_H + 3 帧尾 uint8_t 1 0xA5 \

4.2 数据包各结构描述

帧头

固定0x5A

类型

类型00表示电脑端01表示头戴设备02表示平板03表示电视大屏

设备ID

当类型为01头戴设备时用于区分设备。当头戴设备不知道设备ID时使用0xff临时设备ID。 当类型为其他时无意义。

功能码

功能码对应本条数据的类型,需要根据功能码来解析数据段。

数据长度

数据长度字段的内容表示数据段的字节数量,大端模式。

数据

数据段内容,具体格式根据功能码来定义,小端模式。

CRC校验和

从头开始到校验码前所有字节生成的CRC16小端模式。

帧尾

固定0xA5

4.3 数据包示例

HEX: 5A 01 FF 40 00 64 00 00 00 93 9E FF 3F 93 9E FF 3F 93 9E FF 3F 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 CE 1F A5 

  1. 帧头: 5A
  2. 类型: 01
  3. 设备ID FF
  4. 功能码: 40 对应脑电数据int32_t类型
  5. 数据长度: 00 64 大端模式N = ( 0x00 << 8 | 0x64 ) == 0x0064 == 100 根据int32_t类型反推数据点个数 100 / 4 = 25
  6. 保留位00 00 00
  7. 数据段: 93 9E FF 3F 93 9E FF 3F 93 9E FF 3F 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 7F 4B 00 00 取前16个字节为例 93 9E FF 3F 93 9E FF 3F 93 9E FF 3F 7F 4B 00 00 每4字节对应一个数据点 93 9E FF 3F 93 9E FF 3F 93 9E FF 3F 7F 4B 00 00 小端模式 Point1 = 0x3FFF9E93 Point2 = 0x3FFF9E93 Point3 = 0x3FFF9E93 Point4 = 0x00004B7F
  8. CRC16校验 CE 1F
  9. 数据段尾: 0xA5

五.电脑端功能码表

当连接建立后,电脑端向外发送数据时的功能码对应的功能

5.1 总览

5.1. 0x80~0x9f: 向头戴设备发送数据或指令

功能码 功能名称 数据段数据个数 每个数据的类型 备注
0x80 一个表示正常的编码 0 \ 直接被头戴设备丢弃
0x81 接收的信息出错 1 uint8_t 提示接收出现问题,不一定被处理
0x8D 控制MCU软重启 0 \ 控制MCU软重启
0x8E 调试 0 \ 仅用于开发调试
0x8F 将MCU恢复出厂设置 0 \ 此操作会清除 如心率拟合系数、保存的设备ID等 所有信息
0x90 启动配对流程 0 \ 头戴设备接收此指令后清除设备ID等信息并重新尝试配对
0x91 告知设备ID 1 uint8_t 告知设备ID
0x98 控制开启下位机功能 1 uint16_t 开启 FFT LPF HPF NOTCH 等功能
0x99 控制关闭下位机功能 1 uint16_t 关闭 FFT LPF HPF NOTCH 等功能
0x9A 控制下位机灯光 1 uint8_t 控制LED灯 可用于寻找设备
0x9B 控制播放音频与音量 2 uint8_t
0x9C 修改下位机心率拟合系数 9 int32_t 微调心率计算结果
0x9D 告知治疗阶段与疾病类型 2 uint8_t 告知治疗阶段与疾病类型

5.2 功能码详解

5.2. 0x80 一个表示正常的编码

数据帧示例:

HEX: 5A 00 00 80 00 00 00 00 00 crc16_L crc16_H A5

表示正常 暂时无用

参数名称 参数描述 参数类型 参数值 参数值对应功能描述
crc16 crc16校验值 uint16_t

5.2. 0x81 一个表示异常的编码

数据帧示例:

HEX: 5A 00 00 81 00 01 00 00 00 data1 crc16_L crc16_H A5

表示异常 仅起到提示作用 头戴设备收到此指令后,不一定会进行数据处理

参数名称 参数描述 参数类型 参数值 参数值对应功能描述
data1 表示异常类型 uint8_t 0x00 未定义的错误
data1 表示异常类型 uint8_t 0x01 校验出错
data1 表示异常类型 uint8_t 0x02 数值异常(检测出上传的参数超过阈值等)
crc16 crc16校验值 uint16_t

5.2. 0x8D 控制MCU软重启

数据帧示例:

HEX: 5A 00 00 8D 00 00 00 00 00 8E 96 A5

控制MCU软重启

5.2. 0x8E 调试

数据帧示例:

HEX: 5A 00 00 8E 00 00 00 00 00 BD 96 A5

此操作仅供开发使用 输出调试信息

5.2. 0x8F 将MCU恢复出厂设置

数据帧示例:

HEX: 5A 00 00 8F 00 00 00 00 00 6C 97 A5

此操作会清除 如心率拟合系数、保存的设备ID等 所有信息 随后MCU会自动重启

5.2. 0x90 启动配对流程

数据帧示例:

HEX: 5A 00 00 90 00 00 00 00 00 6C 97 A5

电脑端主动发起配对流程

5.2. 0x91 告知设备ID

数据帧示例:

HEX: 5A 00 00 91 00 01 00 00 00 data1 crc16_L crc16_H A5
参数名称 参数描述 参数类型 参数值 参数值对应功能描述
data1 表示异常类型 uint8_t 0x00~0x20共32个编号 成功分配的设备ID号
data1 表示异常类型 uint8_t 0xff 设备未获得设备ID号
crc16 crc16校验值 uint16_t

5.2. 0x98 控制开启下位机功能

数据帧示例:

HEX: 5A 00 00 98 00 02 00 00 00 data1_L data1_H crc16_L crc16_H A5
参数名称 参数描述 参数类型 参数值 参数值对应功能描述
data1 要开启的功能 uint16_t 见下表 见下表 对应位置1则代表开启
crc16 crc16校验值 uint16_t

data1参数值对应功能描述

bit Num 对应功能 参数值对应功能描述
MSB ==> 15 暂无
7~14 暂无
6 EMG 带通滤波器 NOTCH
5 EMG 高通滤波器 HPF
4 EMG 低通滤波器 LPF
3 EEG 带通滤波器 NOTCH
2 EEG 高通滤波器 HPF
1 EEG 低通滤波器 LPF
LSB ==> 0 FFT 脑波分解

5.2. 0x99 控制关闭下位机功能

数据帧示例:

HEX: 5A 00 00 99 00 02 00 00 00 data1_L data1_H crc16_L crc16_H A5
参数名称 参数描述 参数类型 参数值 参数值对应功能描述
data1 要关闭的功能 uint16_t 参考5.2. 0x98对应表格 对应位置1则代表关闭
crc16 crc16校验值 uint16_t

5.2. 0x9A 控制下位机灯光

数据帧示例:

HEX: 5A 00 00 9A 00 01 00 00 00 data1 crc16_L crc16_H A5
参数名称 参数描述 参数类型 参数值 参数值对应功能描述
data1 要关闭的功能 uint8_t 见下表 对应位 置1代表开启 置0代表关闭
crc16 crc16校验值 uint16_t

data1参数值对应功能描述

bit Num 对应功能 参数值对应功能描述
MSB ==> 7 暂无
3~6 暂无
2 RED 红灯
1 GREEN 绿灯
LSB ==> 0 BLUE 蓝灯

5.2. 0x9B 控制播放音频

数据帧示例:

HEX: 5A 00 00 9B 00 02 00 00 00 audio_id volume  crc16_L crc16_H A5
参数名称 参数描述 参数类型 参数值 参数值对应功能描述
audio_id 播放音频的编号 uint8_t 0x00~0xFE 对应的音频编号
audio_id 播放音频的编号 uint8_t 0xFF 不播放音频仅设置音量
volume 设置音量 uint8_t 0x00~0x0F 音量大小 0x00最小 0x0F最大
volume 设置音量 uint8_t 0xFF 不设置音量仅播放音频
crc16 crc16校验值 uint16_t xx \

5.2. 0x9C 微调心率计算结果

数据帧示例:

HEX: 5A 00 00 9C 00 24 00 00 00 data1_LL data1_LH data1_HL data1_HH (data2_ * 4) (data3_ * 4) ... (data9_ * 4) crc16_L crc16_H A5
参数名称 参数描述 参数类型 参数值 参数值对应功能描述
data_n 对应下方公式的参数 int32_t * 9 \ 接收到的9个数据会作为数组传入下方代码中的HR_fitting_update_parameters (int32 *HR_fitting_parameters);
crc16 crc16校验值 uint16_t xx \
  // ====== HR 三段拟合的9个参数 =======
  // a与b需乘以0.000001保证小数点后6位
  static int32_t HR_fitting_parameters_f1;
  static float HR_fitting_parameters_a1;
  static float HR_fitting_parameters_b1;

  static int32_t HR_fitting_parameters_f2;
  static float HR_fitting_parameters_a2;
  static float HR_fitting_parameters_b2;

  static int32_t HR_fitting_parameters_f3;
  static float HR_fitting_parameters_a3;
  static float HR_fitting_parameters_b3;
  // ===== 更新 HR 三段拟合的9个参数 ========
  static void
  HR_fitting_update_parameters (int32 *HR_fitting_parameters)
  {
    HR_fitting_parameters_f1 = HR_fitting_parameters[0];
    HR_fitting_parameters_a1 = HR_fitting_parameters[1] * 0.000001;
    HR_fitting_parameters_b1 = HR_fitting_parameters[2] * 0.000001;
    HR_fitting_parameters_f2 = HR_fitting_parameters[3];
    HR_fitting_parameters_a2 = HR_fitting_parameters[4] * 0.000001;
    HR_fitting_parameters_b2 = HR_fitting_parameters[5] * 0.000001;
    HR_fitting_parameters_f3 = HR_fitting_parameters[6];
    HR_fitting_parameters_a3 = HR_fitting_parameters[7] * 0.000001;
    HR_fitting_parameters_b3 = HR_fitting_parameters[8] * 0.000001;
    WriteParametersIntoFlash (); // 保存参数
  };
  // ===== HR 三段拟合 ========
  static void
  HR_fitting (uint16_t *inputHR_p, uint16_t *outputHR_p)
  {
    uint16_t HR_temp = *inputHR_p;

    if (HR_temp < HR_fitting_parameters_f1)
      {
        *outputHR_p = (uint16_t)(HR_fitting_parameters_a1 * HR_temp
                                 + HR_fitting_parameters_b1);
      }
    else if (HR_temp < HR_fitting_parameters_f2)
      {
        *outputHR_p = (uint16_t)(HR_fitting_parameters_a2 * HR_temp
                                 + HR_fitting_parameters_b2);
      }
    else if (HR_temp < HR_fitting_parameters_f3)
      {
        *outputHR_p = (uint16_t)(HR_fitting_parameters_a3 * HR_temp
                                 + HR_fitting_parameters_b3);
      }
    else
      {
        *outputHR_p = HR_temp;
      }
  }
参数配置示例
    • 对BPM低于300的值不进行矫正 九个参数分别为 300 1000000 0 0 0 0 0 0 0
    • 对所有BPM低于300的值进行校准, 使用公式 outBPM(校正后BPM) = 0.95 * BPM(矫正前BMP) + 2 九个参数分别为 300 950000 2000000 0 0 0 0 0 0
    • 对所有BPM低于300的值进行校准, 使用公式 outBPM(校正后BPM) = 1.099 * BPM(矫正前BMP) - 1.945 九个参数分别为 300 1099000 -1945000 0 0 0 0 0 0
    • 对所有BPM低于300的值进行校准, 使用公式 outBPM(校正后BPM) = a1 * BPM(矫正前BMP) + b1 九个参数分别为 300 1000000*a1 1000000*b1 0 0 0 0 0 0
    • 对所有BPM低于150的值进行校准, 使用公式 outBPM(校正后BPM) = 0.9 * BPM(矫正前BMP) + 1
    • 对所有BPM低于300的值进行校准, 使用公式 outBPM(校正后BPM) = 0.8 * BPM(矫正前BMP) + 2 九个参数分别为 150 900000 1000000 300 800000 2000000 0 0 0
    • 对所有BPM低于100的值进行校准, 使用公式 outBPM(校正后BPM) = 0.712456 * BPM(矫正前BMP) + 3.32211
    • 对所有BPM低于200的值进行校准, 使用公式 outBPM(校正后BPM) = 0.6 * BPM(矫正前BMP) + 4
    • 对所有BPM低于300的值进行校准, 使用公式 outBPM(校正后BPM) = 0.5 * BPM(矫正前BMP) + 5 九个参数分别为 100 712456 3322110 200 600000 4000000 300 500000 5000000
flowchart TD
    A[开始] --> B{更新矫正参数}
    B --> C[从输入获取新参数]
    C --> D[对a/b乘以0.000001转小数]
    D --> E[保存到存储器]
    E --> F[参数更新完成]

    G[心率矫正] --> H{判断心率值}
    H --> |心率 < f1| I[用第一段公式矫正:\n输出 = a1*心率 + b1]
    H --> |f1 ≤ 心率 < f2| J[用第二段公式矫正:\n输出 = a2*心率 + b2]
    H --> |f2 ≤ 心率 < f3| K[用第三段公式矫正:\n输出 = a3*心率 + b3]
    H --> |心率 ≥ f3| L[直接输出原始心率]
    L --> M[矫正结束]

5.2. 0x9D 告诉下位机当前治疗阶段与疾病类型

数据帧示例:

HEX: 5A 00 00 9D 00 02 00 00 00 TreatmentPhase DiseaseTypes crc16_L crc16_H A5
参数名称 参数描述 参数类型 参数值 参数值对应功能描述
TreatmentPhase 治疗阶段的编号 uint8_t 0x00 待机阶段 用于停止基线采集 或 仅指定疾病类型
TreatmentPhase 治疗阶段的编号 uint8_t 0x01 前基线评估 开始记录各指标平均值 直到切换模式结束
TreatmentPhase 治疗阶段的编号 uint8_t 0x02 后基线评估 开始记录各指标平均值 直到切换模式结束
DiseaseTypes 疾病类型编号 uint8_t 0x00 不传输疾病类型 仅传输治疗阶段的编号
DiseaseTypes 疾病类型编号 uint8_t 0x01~0xFE 疾病类型编号
crc16 crc16校验值 uint16_t xx \

治疗阶段的编号

疾病类型编号

六.头戴设备功能码表

当连接建立后,头戴设备向电脑发送数据时的功能码对应的功能

6.1 总览

6.1. 0x00~0x1f: 设备基本信息相关

功能码 功能名称 数据段数据个数 每个数据的类型 备注
0x00 设备工作状态 1 uint8_t
0x01 设备WIFI信号强度 1 uint8_t
0x02 设备电池电量 1 uint8_t
0x10 上传文字日志 N char * N 上传一个字符串

6.1. 0x20~0x3f: 与电脑端交互

功能码 功能名称 数据段数据个数 每个数据的类型 备注
0x20 发送MAC地址与IP地址申请设备ID 10 uint8_t
0x21 配对成功 0 拿到设备ID后发送

6.1. 0x40~0x5f: 脑电数据的上传

功能码 功能名称 数据段数据个数 每个数据的类型 备注
0x40 发送脑电信号采集到的原始值 N int32_t
0x41 发送 脑电信号采集到的值 换算为电压值的系数的倒数 1 int32_t 真实电压 = 原始值 * (1 / 系数的倒数)
0x42 分解出的5种脑波的值 5 int32_t 顺序DeltaThetaAlphaBetaGamma。

6.1. 0x60~0x7f心率数据的上传

功能码 功能名称 数据段数据个数 每个数据的类型 备注
0x60 计算得出的每分钟心率值 1 int16_t
0x61 心率波形 N int32_t

6.1. 0x80~0x9f肌电数据的上传

功能码 功能名称 数据段数据个数 每个数据的类型 备注
0x80 发送肌电信号采集到的原始值 N int32_t
0x81 发送 肌电信号采集到的值 换算为电压值的系数的倒数 1 int32_t 真实电压 = 原始值 * (1 / 系数的倒数); 此系数与0x41功能码的系数应一致;

6.2 功能码详解

6.2. 0x00 设备工作状态

数据帧示例:

HEX: 5A 01 ID 00 00 01 00 00 00 data1 crc16_L crc16_H A5

表示设备工作状态 仅起到提示作用 一般不会发送此指令

参数名称 参数描述 参数类型 参数值 参数值对应功能描述
ID 设备ID uint8_t
data1 表示异常类型 uint8_t 0x00 正常运行
data1 表示异常类型 uint8_t other 其他异常
crc16 crc16校验值 uint16_t

6.2. 0x01 设备WIFI信号强度

数据帧示例:

HEX: 5A 01 ID 01 00 01 00 00 00 data1 crc16_L crc16_H A5

表示设备WIFI信号强度 不会主动发送此功能码

参数名称 参数描述 参数类型 参数值 参数值对应功能描述
ID 设备ID uint8_t
data1 WIFI信号强度 int8_t 单位dBm
crc16 crc16校验值 uint16_t

6.2. 0x02 设备电池电量

数据帧示例:

HEX: 5A 01 ID 02 00 02 00 00 00 data1_L data1_H crc16_L crc16_H A5

表示设备电池电量 定时主动发送此功能码

参数名称 参数描述 参数类型 参数值 参数值对应功能描述
ID 设备ID uint8_t
data1 设备电池电量 int16_t 单位mV
crc16 crc16校验值 uint16_t

6.2. 0x10 上传文字日志

数据帧示例:

HEX: 5A 01 ID 10 00 N 00 00 00 char1 char2 ... charN crc16_L crc16_H A5

表示设备电池电量 定时主动发送此功能码

参数名称 参数描述 参数类型 参数值 参数值对应功能描述
ID 设备ID uint8_t
N 字符串长度 int16_t
char1 char2 ... charN 字符串 char

6.2. 0x20 发送MAC地址申请设备ID

数据帧示例:

HEX: 5A 01 ID 20 00 0A 00 00 00 MAC_AA MAC_BB MAC_CC MAC_DD MAC_EE MAC_FF IP_AA IP_BB IP_CC IP_DD crc16_L crc16_H A5

发送MAC地址申请设备ID 启动时发送 接收到上位机重新配对指令后发送

参数名称 参数描述 参数类型 参数值 参数值对应功能描述
ID 设备ID uint8_t
MAC_AA MAC_BB MAC_CC MAC_DD MAC_EE MAC_FF 设备的MAC地址 6 * uint8_t
IP_AA IP_BB IP_CC IP_DD 设备的IP地址 4 * uint8_t 0xIP_AA.0xIP_BB.0xIP_CC.0xIP_DD
crc16 crc16校验值 uint16_t

6.2. 0x21 配对成功

数据帧示例:

HEX: 5A 01 ID 21 00 00 00 00 00 crc16_L crc16_H A5

拿到设备的IP地址后响应配对成功

参数名称 参数描述 参数类型 参数值 参数值对应功能描述
ID 设备ID uint8_t
crc16 crc16校验值 uint16_t

6.2. 0x40 发送脑电信号采集到的原始值

参考 4.3 节

6.3. 0x41 发送 脑电信号采集到的值 换算为电压值的系数的倒数

数据帧示例:

HEX: 5A 01 ID 41 00 04 00 00 00 data1_LL data1_LH data1_HL data1_HH crc16_L crc16_H A5

发送 实际值 = 脑电信号采集到的原始值 * 1/data1

参数名称 参数描述 参数类型 参数值 参数值对应功能描述
ID 设备ID uint8_t
data1 脑电信号采集到的值换算为电压值的系数的倒数 int32_t
crc16 crc16校验值 uint16_t

6.3. 0x44 发送分解出的5种脑波的值

数据帧示例:

HEX: 5A 01 ID 42 00 14 00 00 00 AA_LL AA_LH AA_HL AA_HH BB_LL BB_LH BB_HL BB_HH CC_LL CC_LH CC_HL CC_HH DD_LL DD_LH DD_HL DD_HH EE_LL EE_LH EE_HL EE_HH crc16_L crc16_H A5

发送分解出的5种脑波的值

参数名称 参数描述 参数类型 参数值 参数值对应功能描述
ID 设备ID uint8_t
AA BB CC DD EE 顺序对应DeltaThetaAlphaBetaGamma。 5 * int32_t
crc16 crc16校验值 uint16_t

6.3. 0x60 发送 计算得出的每分钟心率值

数据帧示例:

HEX: 5A 01 ID 60 00 02 00 00 00 AA_L AA_H crc16_L crc16_H A5

表示设备电池电量 定时主动发送此功能码

参数名称 参数描述 参数类型 参数值 参数值对应功能描述
ID 设备ID uint8_t
AA 计算得出的每分钟心率值 uint16_t
crc16 crc16校验值 uint16_t

6.3. 0x61 发送 心率波形

参考 4.3 节 , 仅功能码不同

6.3. 0x80 发送 肌电信号采集到的原始值

参考 4.3 节 , 仅功能码不同

6.3. 0x81 发送 肌电信号采集到的原始值 换算为电压值的系数的倒数

参考 6.3. 0x41 发送 脑电信号采集到的值 换算为电压值的系数的倒数,仅功能码不同。


七.头戴设备与医生端通信各场景通信流程

7.1 TODO

--TODO

附录