Keep-Alive and Wake-Up in Low Power

Last Updated on : 2024-11-27 06:35:09download

The TCP-based keep-alive mechanism allows a low-power IPC to maintain communication with the cloud. The IPC can exchange data with the cloud while in sleep mode to enable wake-up functionality.

Description

The keep-alive mechanism on the IPC side is divided into three parts.

  • Establish a keep-alive channel (connection and authentication).
  • Send heartbeat packets.
  • Receive wake-up packets.

The following diagram shows how the keep-alive mechanism works.

Wi-Fi ModuleCloudConnectRequest authenticationRespond to authentication requestHeartbeat packetRespond to heartbeat packetWake-up packetAfter the microcontroller getsconnected over MQTT, close the connection.Wi-Fi ModuleCloudConnection, authentication, keep-alive, and wake-up process

Protocol integration

Data format

The packet sent between the Wi-Fi module and the cloud is composed of a header and payload.

Keep-Alive and Wake-Up in Low Power
Field Description Bytes Valid values
version Protocol version number 1 The first version is 1.
type Command type 1
  • 0: Authentication request
  • 1: Authentication response
  • 2: Heartbeat packet
  • 3: Wake-up packet
flag Identifier 1
  • The upper four bits are reserved for later use.
  • The lower four bits indicate the encryption type of the data segment. The authentication payload is encrypted using AES-128-CBC with PKCS #7 padding. The flag is set to 0x1, indicating encryption is enabled. If the lower four bits are set to 0, no encryption is applied.
size Data length 2 The total length of the payload field, excluding the length of the version, type, and flag fields.
payload Actual data N The payload contains the actual data that is being sent. The encryption of this field depends on the flag field.

Authentication process

  1. Establish a TCP connection between the Wi-Fi module and the cloud.
  2. The Wi-Fi module initiates an authentication request to the cloud.
  3. The cloud verifies the received data and responds with a message if the data is verified.
  4. The Wi-Fi module verifies the signature. If the verification succeeds, the secure data channel is opened for incoming data such as heartbeat packets.

The authentication process follows the data format defined above. The payload includes iv, devid, and data, which are structured in LV format (length plus the actual data), as shown in the following figure.

Keep-Alive and Wake-Up in Low Power
Field Bytes Description
iv_len 2 The length of IV.
devid_len 2 The length of devid.
data_len 2 The length of data.
iv 16 A 16-byte randomly-generated data, used to decrypt data.
devid N The encrypted device identifier that the cloud uses to request the key for decryption.
data N The actual data being transmitted, which is encrypted with AES-128-CBC. data is encrypted using the local_key and iv in the payload.

You can get the plaintext devid using tuya_ipc_get_device_id(). For security purposes, the plaintext devId is encrypted using AES-128-CBC with PKCS #7 padding. Finally, the data is encoded to base64. The key and iv used for encryption are fixed as follows:

Keep-Alive and Wake-Up in Low Power
  1. The Wi-Fi module initiates a handshake.

    The Wi-Fi module sends a handshake request to the cloud, with the data in the following format.

    {
        "type": 1,
        "method": 1,
        "authorization": "time=138993455,random=sdfsjijweiwemkejitejwitetopwejriew",
        "signature": "i2je8fjsesfjeijfiejwifheuhfuwefiweif",
    }
    
    • type: indicates whether the request is initiated by the Wi-Fi module (0) or the SDK (1). It is fixed to 1.

    • method: the signature algorithm, defaulting to 1.

    • authorization:

      • time: the UTC time of the device, which will not be verified in the cloud.
      • random: a 32-byte random value.
    • signature: created by encrypting the concatenation of devid:time:random with HMAC-SHA256 and encoding it to base64. tuya_ipc_get_local_key is used to get the encrypted key.

  2. The cloud returns a message.

    The cloud generates a signature and corresponding parameters to send back to the device.

    {
        "err": 0,
        "interval": 60,
        "random": "sdfsiiiweiwemkeiiteiwitetopweiniew",
        "authorization": "time=138993455,random=qwertyuikfhkof18458yeiurur",
        "signature": "i2je8fjsesfjeijfiejwifheuhfuwefiweif",
    }
    
    • err: the error code. 0: success. Other values: failure.

    • interval: the heartbeat interval, which is a fixed value and cannot be modified.

    • random: the random number the IPC sends to the cloud, which is returned unchanged.

    • authorization: the authentication parameters, including time and random.

    • signature: the signature data.

  3. The IPC verifies data.

    The IPC verifies the received data.

    1. Use the iv and local_key in the returned payload to decrypt data using AES.

    2. Verify the consistency of the random in the response and request. If they do not match, the verification fails.

    3. Generate a signature by concatenating and encrypting the time and random in the received authorization, in the same way as done in the handshake request.

    4. Compare the generated signature with the signature in the received message. If they do not match, the verification fails.

Heartbeat packet

The heartbeat packet has fixed content and no payload. The first version is 1, type is 2, flag is 0, and size is 0. Here is the assembled data:

0x1 0x2 0x0 0x0 0x0

Wake-up packet

For the wake-up packet, the first version is 1, type is 3, flag is 0, and size is 4. The payload is the CRC32 hash of local_key returned by tuya_ipc_get_local_key().

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

Overall process

Take Tuya’s low power consumption solution as an example. This solution’s devices consist of four parts: the microcontroller (MCU) chip, the Wi-Fi chip, the low-power keep-alive server, and the MQTT server. Their roles are as follows:

  • MCU chip: Handles video streaming tasks. In the wake-up status, it directly connects to the MQTT server through the Wi-Fi chip.
  • Wi-Fi chip: Provides basic Wi-Fi functionalities. In the keep-alive status, it powers down the MCU chip and directly connects to the low-power keep-alive server to perform keep-alive operations on the device.
  • Low-power keep-alive server: Provides cloud-based low-power keep-alive capabilities.
  • MQTT server: A basic Tuya cloud server that manages the online/offline status of devices and facilitates DP data communication. In the wake-up status, interactions between the device and the cloud are handled by the MCU chip.

The wake-up interaction process is as follows.

MCUWi-Fi chipLow-powerkeep-alive serverMQTT serverWake-up messageForward a wake-up messageWake up MCUConnect directly through the Wi-Fi chipDisconnect keep-alive link after detecting a new linkMCUWi-Fi chipLow-powerkeep-alive serverMQTT serverWake-up interaction process

The sleep interaction process is as follows.

MCUWi-Fi chipLow-powerkeep-alive serverMQTT serverSend sleep commandPower down MCUStart connecting to keep-aliveserverConnect to MQTT serverDisconnect MQTT link after detecting the keep-alive linkKeep-alive packetMQTT heartbeat packetMCUWi-Fi chipLow-powerkeep-alive serverMQTT serverSleep interaction process

In the sleep status, the MCU chip powers down, and the device no longer directly connects to the MQTT server. Instead, it connects to the keep-alive server.

Avoid actively disconnecting the TCP connection from the device to the MQTT server or the keep-alive server unless absolutely necessary, because this will trigger an offline message in the cloud.

Keep-alive process

For more information, see tuyaos_demo_ipc/application_components/app_main/src/ty_sdk_lowpower.c/ TUYA_IPC_low_power_sample().

Yes
No
Enter sleep mode
Call tuya_ipc_low_power_server_connect to establish keep-alive link
Call tuya_ipc_low_power_socket_fd_get to get the handle to the keep-alive link
Call tuya_ipc_low_power_heart_beat_get to get the raw heartbeat data
Call tuya_ipc_low_power_wakeup_data_get to get the raw wake-up data
Send heartbeat packet regularly
Wake-up packet received?
Start service

API description

Get the cloud IP address and port number

Get the cloud IP address and port number of the low-power IPC. OPRT_OK is returned on success.

/**
 * @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);

Get the device ID

Get the devid of the IPC and the length of devid. OPRT_OK is returned on success.

/**
 * \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);

Get the local_key

Get the local_key of the device. OPRT_OK is returned on success.

/**
 * \fn OPERATE_RET tuya_ipc_get_local_key
 * \brief Get signature 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);

Establish an encrypted channel

Establish an encrypted channel. OPRT_OK is returned on success.

/**
 * \fn OPERATE_RET tuya_ipc_lowpower_server_connect
 * \brief connect low-power server.
 * \ serverIp: The IP address of the cloud server;
 * \ port: Port number
 * \ pdevId: The device ID
 * \ idLen: The length of the device ID
 * \ pkey: The local_key
 * \ keyLen: The length of the 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);

Get the service handle

Get the handle to the low-power service.

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

Get the heartbeat packet content

Get the heartbeat packet content of the low-power service.

/**
 * \fn OPERATE_RET tuya_ipc_low_power_heart_beat_get
 * \brief get low-power heartbeat 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);

Get the wake-up packet content

Get the wake-up packet content of the low-power service.

/**
 * \fn OPERATE_RET tuya_ipc_low_power_wakeup_data_get
 * \brief get low-power 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);

FAQs

How can I get the demo?

In the development kit, the demo file is named ty_sdk_lowpower.c which you can refer to for development.

How does the cloud respond to an IPC heartbeat packet?

The content is the same as what is sent from the IPC, which is 0x1 0x2 0x0 0x0 0x0.

What are the requirements for data encrypted with AES-128-CBC?

The encrypted data must be a multiple of 16 bytes. If it is less than 16 bytes or not a multiple of 16 bytes, it needs to be padded using PKCS #7.

Should the TCP connection to the low-power keep-alive server or the MQTT server be proactively closed?

  • When a device in the low-power keep-alive status receives a wake-up packet from the cloud, the keep-alive thread should not proactively close the TCP connection. Instead, it should wait for the cloud to disconnect the TCP connection to the keep-alive server. If the device proactively closes the TCP connection, the cloud will log an offline message with a “close” status in the background.
  • When a device in a non-keep-alive status enters the low-power keep-alive status, a TCP connection to the keep-alive server is created. In this case, there is no need to proactively close the TCP connection to the MQTT server.

How should a failed connection to the low-power keep-alive server be handled?

Prioritize using the domain name information obtained by tuya_ipc_get_low_power_server_v2 to resolve the IP address and make a TCP connection. If the connection fails, you can try to use the IP address obtained by tuya_ipc_get_low_power_server_v2 to connect to the keep-alive server.