低功耗保活唤醒

更新时间:2024-11-19 08:15:03下载pdf

IPC 低功耗保活唤醒,是涂鸦为低功耗设备提供的基于 TCP 协议的设备与云端之间的保活方法。设备在休眠期间可以实现与云端之间的交互,从而达到休眠唤醒的目的。

功能说明

低功耗保活唤醒 在设备端主要分为三个部分:

  • 构建保活通道(连接与鉴权)
  • 发送心跳包
  • 接收唤醒包

低功耗保活唤醒 的交互流程如下图所示:

Wi-Fi 模组云端连接鉴权请求鉴权回复心跳包心跳包回复......唤醒包主控 MQTT 上线后踢掉连接Wi-Fi 模组云端连接、鉴权、保活、唤醒流程

协议对接

数据格式

Wi-Fi 模组与云端之间的数据通信统一由消息头(Header)和消息载体(Payload)组成,如下:

低功耗保活唤醒
字段 解释 字节数 取值说明
version 协议号 1 第一版为 1
type 命令号 1
  • 0:鉴权请求
  • 1:鉴权回复
  • 2:心跳包
  • 3:唤醒包
flag 标识符 1
  • 保留高 4 位,用于以后的扩展。
  • 低 4 位用于表征数据段加密类型,初始定义认证交互的 payload 字段采用 aes cbc 128 加密方式,采用 PKCS7Padding 方式填充,flag 为 0x1,低 4 位若是为 0 则表示不加密。
size 数据长度 2 payload 字段总的长度,不包含 versiontypeflag 三个字段的长度。
payload 实际数据 N 加载的具体数据,该字段是否需要加密根据 flag 类别确定。

鉴权过程

  1. Wi-Fi 模组和云端之间建立 TCP 连接。
  2. Wi-Fi 模组向云端发起鉴权过程请求。
  3. 云端对请求数据进行校验,通过后,回复一个报文。
  4. Wi-Fi 模组进行签名校验,完成后,数据安全通道打开,放行心跳包等数据。

鉴权的数据交互采用前述的 数据格式,Payload 部分包括 ivdeviddata 三部分,以上三个字段采用 LV 形式组织,即长度加实际有效数据,如下图所示:

低功耗保活唤醒
字段 字节数 说明
iv_len 2 iv 长度。
devid_len 2 devid 长度。
data_len 2 data 长度。
iv 16 用于解密使用,用户自定义随机生成一个 16 字节数据。
devid N 加密后的设备标识,云端用来查询解密需要使用的 key
data N 交互数据,需要采用 AES CBC 128 加密。data 的加密使用 local_keypayload 里的 iv

原始 devid 使用 tuya_ipc_device_id_get() 接口获取。出于安全考虑,原始 devId 需要使用 AES CBC 128 加密,需要做 PKCS7 padding。并且最后进行 Base64 加密,加密使用的 keyiv 固定如下:

低功耗保活唤醒
  1. 发起握手请求

    Wi-Fi 模组向云端发起握手请求,data 参数格式如下:

    {
        "type": 1,
        "method": 1,
        "authorization": "time=138993455,random=sdfsjijweiwemkejitejwitetopwejriew",
        "signature": "i2je8fjsesfjeijfiejwifheuhfuwefiweif",
    }
    
    • type:表示发起请求的是 Wi-Fi 模组(0),还是 SDK(1)。固定为 1

    • method:签名算法类型,默认为 1

    • authorization

      • time:设备的 UTC 时间,云端不做校验
      • random:随机的 32 字节
    • signature:按照 devid:time:random 格式拼接,对拼接后的数据先进行 HMac SHA256 加密,然后进行 Base64 加密,计算得出。tuya_ipc_get_local_key 接口获取加密 key

  2. 云端消息返回

    云端按照签名算法计算出 signature,同时生成相应的参数返回给设备,云端返回的格式如下:

    {
        "err": 0,
        "interval": 60,
        "random": "sdfsiiiweiwemkeiiteiwitetopweiniew",
        "authorization": "time=138993455,random=qwertyuikfhkof18458yeiurur",
        "signature": "i2je8fjsesfjeijfiejwifheuhfuwefiweif",
    }
    
    • err:错误码,0 表示成功,其它表示失败。

    • interval:心跳间隔时间,该值为固定值,不支持修改。

    • random:IPC 发送给云端的随机数,云端原样返回。

    • authorization:认证参数,包含时间和随机数。

    • signature:签名数据。

  3. 数据检验认证

    IPC 设备对接受到的数据进行校验认证:

    1. 使用云端返回 payload 中的 ivlocal_key,对 data 进行 AES 解密。

    2. random 和请求中的 random 进行比较,若不一致则校验失败。

    3. authrization 中的 timerandom 使用与请求中 devid:time:random 相同的方式计算签名。

    4. 将上一步计算出的签名与报文中的 signature 进行对比,若不一致则校验失败。

心跳数据

心跳数据内容固定,没有 payload,第一版 version 为 1,type 为 2,flag 为 0,size 字段为 0,最后组装的数据如下:

0x1 0x2 0x0 0x0 0x0

唤醒数据

唤醒数据包,第一版 version 为 1,type 为 3,flag 为 0,size 字段为 4,playload 字段由 SDK 提供 tuya_ipc_get_local_key() 获取 local_key,通过计算 local_key 的 Hash CRC32 值而来。

0x1 0x3 0x0 0x0 0x4 0x11 0x23 0xab 0xbf

总体流程框架

以涂鸦低功耗方案为例。使用此类方案的设备由四个部分组成,分别是主控芯片、Wi-Fi 芯片、低功耗保活服务器和 MQTT 服务器。作用分别如下:

  • 主控芯片:负责处理视频流相关业务。在唤醒状态下,会通过 Wi-Fi 芯片直连 MQTT 服务器。
  • Wi-Fi 芯片:负责提供 Wi-Fi 相关基础能力。在保活状态下,会控制主控下电,直连低功耗保活服务器,对设备进行保活相关操作。
  • 低功耗保活服务器:提供了云端低功耗保活的能力。
  • MQTT 服务器:涂鸦的基础云端服务器,提供设备上下线判断和 DP 数据交互等基础能力。在唤醒状态下,设备与云端的交互是保存在主控芯片上的。

在唤醒过程中,设备交互流程如下:

主控Wi-Fi 芯片低功耗保活服务器MQTT 服务器唤醒消息转发唤醒消息唤醒主控通过 Wi-Fi 芯片直连 MQTT 服务器监听到新的链接断开保活链路主控Wi-Fi 芯片低功耗保活服务器MQTT 服务器唤醒过程交互流程

在休眠过程中,设备交互流程如下:

主控Wi-Fi 芯片低功耗保活服务器MQTT 服务器下发休眠指令下电主控开始连接保活服务器连接 MQTT 服务器监听到保活链路,云端断开 MQTT 链路保活报文MQTT 心跳报文主控Wi-Fi 芯片低功耗保活服务器MQTT 服务器休眠过程交互流程

在休眠情况下,主控下电,设备不再直接连接 MQTT 服务器,转而连接保活服务器。

在非必要情况下,设备侧不要主动断开 MQTT 和保活链路的 TCP 连接,因为设备侧主动断开的行为会在云端产生一个离线消息。

保活具体流程

参考 tuyaos_demo_ipc/application_components/app_main/src/ty_sdk_lowpower.c/ TUYA_IPC_low_power_sample()

进入休眠
调用 tuya_ipc_low_power_server_connect建立保活链路
调用 tuya_ipc_lowpower_socket_fd_get 获取保活链路句柄
调用 tuya_ipc_lowpower_heart_beat_get 获得原始心跳数据
调用 tuya_ipc_lowpower_wakeup_data_get 获得原始唤醒教据
定期发送心跳数据
是否收到唤醒包
启动业务

API 说明

获取云端 IP 和端口

获取低功耗云端 IP 和端口信息,成功返回 OPRT_OK

/**
 * @brief get low power server info v2
 * 
 * @param[out] domain: server domain
 * @param[in] domain_len: domain length
 * @param[out] ip: server IP address
 * @param[out] port: server port
 * 
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h 
 */
OPERATE_RET tuya_ipc_get_low_power_server_v2(OUT CHAR_T *domain, IN INT_T domain_len, OUT UINT_T *ip, OUT UINT_T *port);

获取设备 ID

获取设备的 devid,以及 devid 长度,成功返回 OPRT_OK

/**
 * \fn OPERATE_RET tuya_ipc_get_device_id
 * \brief get device ID
 * \
 * \return OPRT_OK if get device ID success .other is failed;
 */

OPERATE_RET tuya_ipc_get_device_id(IN OUT CHAR_T *devid, IN OUT INT_T * id_len);

获取设备 local_key

获取设备的 local_key,成功返回 OPRT_OK

/**
 * \fn OPERATE_RET tuya_ipc_get_local_key
 * \brief Get signatrue key from ipc SDK.
 * \ make destKeyBuf len >=17;
 * \return OPRT_OK if get key success
 */

OPERATE_RET tuya_ipc_get_local_key(OUT CHAR_T * destKeybuf,OUT UINT_T * len);

构建加密通道

构建加密通道,成功返回 OPRT_OK

/**
 * \fn OPERATE_RET tuya_ipc_low_power_server_connect
 * \brief connect lowpower server.
 * \ serverIp:云端服务器 IP;
 * \ port:端口号
 * \ pdevId:设备 ID
 * \ idLen:设备 ID 长度
 * \ pkey:local_key
 * \ keyLen:local_key 长度
 * \return OPRT_OK if get key success
 */
OPERATE_RET tuya_ipc_low_power_server_connect(UNW_IP_ADDR_T serverIp,INT_T port,char* pdevId, int idLen, char* pkey, int keyLen);

获取服务句柄

获取低功耗服务句柄。

/**
 * \fn OPERATE_RET tuya_ipc_low_power_socket_fd_get
 * \brief get lowpower socket fd.
 * \return fd handle
 */
OPERATE_RET tuya_ipc_low_power_socket_fd_get();

获取心跳包内容

获取低功耗服务心跳包内容。

/**
 * \fn OPERATE_RET tuya_ipc_low_power_heart_beat_get
 * \brief get lowpower heart beat info.
 * \return OPRT_OK if get key success
 */
OPERATE_RET tuya_ipc_low_power_heart_beat_get(OUT CHAR_T * pdata,OUT UINT_T *plen);

获取唤醒包内容

获取低功耗服务唤醒包内容。

/**
 * \fn OPERATE_RET tuya_ipc_low_power_wakeup_data_get
 * \brief get lowpower wakeup info.
 * \return OPRT_OK if get key success
 */
OPERATE_RET tuya_ipc_low_power_wakeup_data_get(OUT CHAR_T* pdata, OUT UINT_T* plen);

常见问题

如何获取 Demo?

在开发包中,Demo 文件名为 ty_sdk_lowpower.c,您可以参考 Demo 进行开发。

设备发送心跳包,云端的回复内容是什么?

和设备端发送的一致:0x1、0x2、0x0、0x0,0x0

AES 128 CBC 加密数据有什么要求?

AES 128 CBC 进行加密后的数据一定是 16 字节的倍数,如果不足 16 字节或者 16 字节的倍数需要用 PKcs7 的方式进行填充。

低功耗保活连接和 MQTT 需要主动关闭吗?

  • 如果设备在低功耗保活状态并收到云端下发的唤醒包,保活线程无需主动关闭 TCP 连接,而是应等待云端主动断开保活服务器的 TCP 连接。如果设备主动关闭 TCP 连接,将导致云端在后台记录一条状态为 close 的离线消息。
  • 如果设备在非保活状态,进入低功耗保活,创建 TCP 连接,也不需唤醒。

低功耗保活连接失败如何处理?

如果 TCP 连接失败,可以尝试通过 tuya_ipc_get_low_power_server_v2 获取到的域名信息,重新请求获取 IP 地址信息,进行 TCP 连接保活尝试。