Files
LPT26x-HSF-4MB-Hilink_14.2.…/docs/serial_control_protocol.md
ekko.bao 21c6d05bad 1. 解决PWM 更新导致周期混乱继而亮度抖动的问题
2. 增加无论何种状态都能强制复位的机制
3. 添加设备注册检查机制,如果设备已经处于配网但是还是注册的状态,强制进行一次复位
4. 添加串口控制协议
2025-10-26 17:49:12 +08:00

14 KiB
Raw Permalink Blame History

串口控制协议

目录

1. 指令格式

  • 下发:AT+CTRL={JSON}\r\n
  • 查询:AT+QUERY={JSON}\r\n
  • 回执:OK,<id>\r\nERROR,<code>[,<message>]\r\n
  • 异步结果:AT+RESP={JSON}\r\n
  • 规则:
    • 单行 JSON内部换行请写成 \n
    • 行结束统一为 CRLF \r\nWindows 兼容)
    • 接收端应兼容仅 LF \n

1.1 串口参数

  • 波特率:9600
  • 数据位:8
  • 校验位:None
  • 停止位:1
  • 流控:None
  • 编码:UTF-8(无 BOM
  • 建议:行缓冲读取,按 CRLF \r\n 作为帧结束。

2. JSON 结构

  • 单服务控制(必须携带 id
    • 下发:{"id": <u32>, "sid":"<serviceId>", "data": {<fields>}}
    • 返回:{"id": <u32>, "sid":"<serviceId>", "data": {<fields>}, "error": <u32>, "message": "<可选>"}error=0 表示成功)

2.1 字段说明

  • idnumber, u32>0必填
    • 会话标识,用于将异步结果与请求一一对应、便于定位问题。
    • 由发起方分配与维护,建议使用一个全局自增计数(溢出后回绕到 1
    • 受控方不做去重与顺序检查,仅在 RESP 中原样回显。
  • sidstring必填
    • 服务功能 ID。合法值switchbrightnesscctlightModeprogressSwitchcolourMode
    • 区分大小写;不在集合内的值视为不支持服务。
  • dataobject必填
    • 具体服务的数据负载。各服务的字段与范围见“支持服务与字段(详解)”。
    • 缺字段或类型不符为业务错误RESP error=105message 可携带原因)。
  • errornumber, u32RESP 必带)
    • 业务执行结果码:0 成功;非 0 失败。常见值见“错误码”。
  • messagestring可选RESP 可带)
    • 人类可读的错误或提示信息,用于调试。

2.2 发送提示

  • 多次控制:请按需多次发送 AT+CTRL=...,每次使用不同的 id
  • ACK 超时与重发建议:
    • 发送后等待 OK,<id>,超时建议 200500 ms
    • 未收到 ACK 则按原 id 与完全相同的 JSON 重发,重发 23 次,间隔 200300 ms
    • 注意:设备不做去重,重复下发可能重复执行;建议尽量使用幂等设置(如重复设置相同亮度)。
  • 结果等待与超时:
    • 收到 OK,<id> 后等待 AT+RESP,建议超时阈值 12 s(视业务而定)。
    • 超时未收到可按失败处理并在上层重试(使用新的 id)。
  • 换行约定:所有发送与回执均以 CRLF \r\n 结束;示例为单行展示,实际发送需包含 CRLF。

2.3 查询命令AT+QUERY

  • 作用:查询指定 sid 的当前状态(只读,不改变设备状态)。
  • 下发:AT+QUERY={"id": <u32>, "sid":"<serviceId>"}\r\n
  • 回执:OK,<id>\r\n
  • 异步结果:AT+RESP={"id": <u32>, "sid":"<serviceId>", "data": {<current-fields>}, "error": <u32>, "message": "<可选>"}\r\n
  • 说明:
    • data 与“支持服务与字段(详解)”中各 sid 的状态格式一致(等同于 Get 接口的输出)。
    • sid 不支持,返回 ERROR,104,UnsupportedSid(协议级错误)。

3. 支持服务与字段(详解)

3.1 switch开关

  • 功能:控制灯具开/关。
  • 下发:{"id":<u32>,"sid":"switch","data":{"on":0|1}}
  • 返回:{"id":<u32>,"sid":"switch","data":{"on":0|1},"error":<u32>,"message":"<可选>"}
  • 参数:on 为 int取值 0 关、1 开。
  • 行为当处于“离家模式”mode=7收到 on=1 会先退出离家模式再开灯。
  • 示例:
    • 开灯
      • 【发起方发送】AT+CTRL={"id":101,"sid":"switch","data":{"on":1}}
      • 【受控方返回】OK,101AT+RESP={"id":101,"sid":"switch","data":{"on":1},"error":0}
    • 关灯
      • 【发起方发送】AT+CTRL={"id":102,"sid":"switch","data":{"on":0}}
      • 【受控方返回】OK,102AT+RESP={"id":102,"sid":"switch","data":{"on":0},"error":0}

3.2 brightness亮度

  • 功能:设置亮度百分比。
  • 下发:{"id":<u32>,"sid":"brightness","data":{"brightness":0..100}}
  • 返回:{"id":<u32>,"sid":"brightness","data":{"brightness":<0..100>},"error":<u32>,"message":"<可选>"}
  • 参数:brightness 为 int范围 0..100;超出范围按边界钳制。
  • 示例:
    • 设为 60%AT+CTRL={"id":201,"sid":"brightness","data":{"brightness":60}}
    • 最小值:AT+CTRL={"id":202,"sid":"brightness","data":{"brightness":0}}
    • 最大值:AT+CTRL={"id":203,"sid":"brightness","data":{"brightness":100}}

3.3 cct色温

  • 功能:设置色温(单位 K
  • 下发:{"id":<u32>,"sid":"cct","data":{"colorTemperature":2700..6000}}
  • 返回:{"id":<u32>,"sid":"cct","data":{"colorTemperature":<2700..6000>},"error":<u32>,"message":"<可选>"}
  • 参数:colorTemperature 为 int范围 2700..6000;超出范围按边界钳制。
  • 示例:
    • 暖色 3000KAT+CTRL={"id":301,"sid":"cct","data":{"colorTemperature":3000}}
    • 中性 4000KAT+CTRL={"id":302,"sid":"cct","data":{"colorTemperature":4000}}
    • 冷色 6000KAT+CTRL={"id":303,"sid":"cct","data":{"colorTemperature":6000}}

3.4 lightMode场景模式

  • 功能:按预设场景设置亮度与色温,或进入离家模式。
  • 下发:{"id":<u32>,"sid":"lightMode","data":{"mode":0..7}}
  • 返回:{"id":<u32>,"sid":"lightMode","data":{"mode":<0..7>},"error":<u32>,"message":"<可选>"}
  • 参数:mode 为 int
    • 0 customer自定义模式
    • 1 relax (休闲模式)(约 50%4000K
    • 2 movie观影模式约 10%3000K
    • 3 dining用餐模式约 100%4000K
    • 4 home回家模式约 80%3500K
    • 5 winter冬天模式约 100%2700K
    • 6 summer夏天模式约 100%6000K
    • 7 leave离家模式直接关灯
  • 示例:
    • 观影模式:AT+CTRL={"id":401,"sid":"lightMode","data":{"mode":2}}
    • 离家模式:AT+CTRL={"id":402,"sid":"lightMode","data":{"mode":7}}
    • 回家模式:AT+CTRL={"id":403,"sid":"lightMode","data":{"mode":4}}

3.5 progressSwitch渐变时长

  • 功能:设置亮度/色温变化的平滑过渡时间(秒)。
  • 下发:{"id":<u32>,"sid":"progressSwitch","data":{"fadeTime":0..30}}
  • 返回:{"id":<u32>,"sid":"progressSwitch","data":{"fadeTime":<0..30>},"error":<u32>,"message":"<可选>"}
  • 参数:fadeTime 为 int范围 0..30 秒;0 表示尽快变化。
  • 示例:
    • 设为 5 秒:AT+CTRL={"id":501,"sid":"progressSwitch","data":{"fadeTime":5}}
    • 立即变化:AT+CTRL={"id":502,"sid":"progressSwitch","data":{"fadeTime":0}}

3.6 colourMode色温模式

  • 功能:设置色温工作模式。
  • 下发:{"id":<u32>,"sid":"colourMode","data":{"mode":0|1}}
  • 返回:{"id":<u32>,"sid":"colourMode","data":{"mode":0|1},"error":<u32>,"message":"<可选>"}
  • 参数:mode 为 int0 单色温、1 双色温。
  • 行为单色温0设备固定到预设色温6000K双色温1使用/保持当前色温。
  • 示例:
    • 单色温:AT+CTRL={"id":601,"sid":"colourMode","data":{"mode":0}}
    • 双色温:AT+CTRL={"id":602,"sid":"colourMode","data":{"mode":1}}

4. 约束

  • {JSON} 最大长度:≤ 1024 字节(不含前缀与行尾)。
  • 单行承载,不允许真实换行;内部换行使用 \n 字符串。
  • 行结束采用 CRLF \r\n;接收端应兼容仅 LF \n
  • id 必须存在且为 u32>0缺失/类型不符即返回 ERROR,105,TypeError

5. 错误码

  • 100 BadPrefix未以 AT+CTRL= 开头)
  • 101 MalformedJSONJSON 语法错误)
  • 102 EmptyJSON空 JSON
  • 103 PayloadTooLong负载超长
  • 104 UnsupportedSid不支持的 sid
  • 105 TypeError字段缺失或类型不符
  • 106 Busy设备忙
  • 107 ApplyTimeout内部执行超时
  • 112 NotControllable非受控状态设备处于不可被控制的模式例如升级/维护/工厂测试/安全锁定等)
  • 111 RateLimited限频

5.1 NotControllable112用法建议

  • 触发场景(示例):
    • 升级进行中OTA/独立升级/固件校验)
    • 维护/自检/烧录/工厂测试模式
    • 安全锁定/童锁/设备被上级网关临时锁定
    • 热保护/过温降额/低电量保护等安全策略生效
    • 正在配网/关键迁移流程,不允许外部控制
  • 返回规范:
    • 收到控制后先回 ACKOK,<id>
    • 业务结束后返回:AT+RESP={"id":<id>,"sid":"<sid>","data":{...},"error":112,"message":"<原因>"}
  • message 建议取值(便于前端统一展示与日志聚合):
    • upgrading(升级中)
    • maintenance(维护/自检)
    • factory_test(工厂测试)
    • locked(安全/家长锁定)
    • thermal_protect(热保护)
    • low_power(低电量保护)
    • net_config(正在配网)
  • 查询建议:
    • AT+QUERY 通常仍应返回当前状态并 error=0;若状态不可读,再返回 error=112 与合适的 message

6. 时序图示Mermaid

  1. 多次控制(均成功,异步返回 error=0
sequenceDiagram
    participant 发起方
    participant 受控方

    发起方->>受控方: AT+CTRL={"id":7001,"sid":"switch","data":{"on":1}}\r\n
    受控方-->>发起方: OK,7001\r\n
    note over 受控方: 执行开关控制
    受控方-->>发起方: AT+RESP={"id":7001,"sid":"switch","data":{"on":1},"error":0}\r\n

    发起方->>受控方: AT+CTRL={"id":7201,"sid":"lightMode","data":{"mode":2}}\r\n
    受控方-->>发起方: OK,7201\r\n
    note over 受控方: 执行场景模式切换
    受控方-->>发起方: AT+RESP={"id":7201,"sid":"lightMode","data":{"mode":2},"error":0}\r\n

    发起方->>受控方: AT+CTRL={"id":7301,"sid":"progressSwitch","data":{"fadeTime":5}}\r\n
    受控方-->>发起方: OK,7301\r\n
    note over 受控方: 设置渐变时长
    受控方-->>发起方: AT+RESP={"id":7301,"sid":"progressSwitch","data":{"fadeTime":5},"error":0}\r\n
  1. 协议级错误JSON 语法错误,直接 ERROR,不产生 RESP
sequenceDiagram
    participant 发起方
    participant 受控方

    发起方->>受控方: AT+CTRL={"sid":"switch","data":{"on":1}
    受控方-->>发起方: ERROR,101,MalformedJSON
    note over 受控方: 帧被丢弃,无 AT+RESP
  1. 业务错误(收到并受理,但参数类型错误)
sequenceDiagram
    participant 发起方
    participant 受控方

    发起方->>受控方: AT+CTRL={"id":7501,"sid":"brightness","data":{"brightness":"sixty"}}\r\n
    受控方-->>发起方: OK,7501\r\n
    note over 受控方: 参数校验失败(类型错误)
    受控方-->>发起方: AT+RESP={"id":7501,"sid":"brightness","data":{"brightness":50},"error":105,"message":"TypeError"}\r\n
  1. 查询状态OK + RESP
sequenceDiagram
    participant 发起方
    participant 受控方

    发起方->>受控方: AT+QUERY={"id":7101,"sid":"brightness"}\r\n
    受控方-->>发起方: OK,7101\r\n
    note over 受控方: 读取并打包当前亮度状态
    受控方-->>发起方: AT+RESP={"id":7101,"sid":"brightness","data":{"brightness":60},"error":0}\r\n

7. 示例

  1. 开关:打开 【发起方发送】
AT+CTRL={"id":7001,"sid":"switch","data":{"on":1}}

【受控方返回】

OK,7001

【受控方返回】

AT+RESP={"id":7001,"sid":"switch","data":{"on":1},"error":0}
  1. 查询当前亮度 【发起方发送】
AT+QUERY={"id":7101,"sid":"brightness"}

【受控方返回】

OK,7101

【受控方返回】

AT+RESP={"id":7101,"sid":"brightness","data":{"brightness":60},"error":0}
  1. 场景模式movie 【发起方发送】
AT+CTRL={"id":7201,"sid":"lightMode","data":{"mode":2}}

【受控方返回】

OK,7201

【受控方返回】

AT+RESP={"id":7201,"sid":"lightMode","data":{"mode":2},"error":0}
  1. 渐变时长5 秒 【发起方发送】
AT+CTRL={"id":7301,"sid":"progressSwitch","data":{"fadeTime":5}}

【受控方返回】

OK,7301

【受控方返回】

AT+RESP={"id":7301,"sid":"progressSwitch","data":{"fadeTime":5},"error":0}
  1. 色温模式:单色温 【发起方发送】
AT+CTRL={"id":7401,"sid":"colourMode","data":{"mode":0}}

【受控方返回】

OK,7401

【受控方返回】

AT+RESP={"id":7401,"sid":"colourMode","data":{"mode":0},"error":0}
  1. 业务失败(类型错误) 【发起方发送】
AT+CTRL={"id":7501,"sid":"brightness","data":{"brightness":"sixty"}}

【受控方返回】

OK,7501

【受控方返回】

AT+RESP={"id":7501,"sid":"brightness","data":{"brightness":50},"error":105,"message":"TypeError"}
  1. 非法 JSON协议级错误 【发起方发送】
AT+CTRL={"sid":"switch","data":{"on":1}

【受控方返回】

ERROR,101,MalformedJSON
  1. 不支持的服务(协议级错误) 【发起方发送】
AT+CTRL={"id":7601,"sid":"foo","data":{"bar":1}}

【受控方返回】

ERROR,104,UnsupportedSid