有奖捉虫:行业应用 & 管理与支持文档专题 HOT
低功耗设备使用低功耗保活模块使设备在主控断电或深度睡眠后自主维持保活连接,并支持远程唤醒。

功能介绍

本模块提供设备进入低功耗保活的前置工作,通过调用该模块会使设备发起和保活服务器的保活连接,建立保活链路。通过将成功建立的链路以及唤醒和维持心跳所需的数据传递给应用层,以便于应用层进行其他处理;该模块是 IoT Video 的可选模块。

流程

进入保活

iv_sys_init() //系统初始化
|
iv_dm_init() //物模型初始化
|
iv_sys_online_cb() //设备上线通知
|
working //正常工作
|
iv_get_keep_alive_info() //获取保活信息
|
iv_dm_exit() //物模型退出
|
iv_sys_exit() //系统退出
|
调用硬件建立保活链路

唤醒

远端下发唤醒指令
|
服务器发送唤醒消息
|
硬件保活模块
|
输出唤醒信号
|
唤醒主控

保活

1.getaddrinfo, 根据域名查询IP地址
|
2.connect, 根据IP和端口号建立连接
|
3. send鉴权信息
|
4. recv后台消息
|
5.是否有唤醒消息———如果有,退出保活,唤醒主控;否则继续6
|
6. send保活信息
|
跳转到步骤4

接口参考

该功能模块提供以下接口:
iv_get_keep_alive_info:获取保活信息。

iv_get_keep_alive_info

接口描述
向后台请求保活信息。
int iv_get_keep_alive_info(iv_keep_alive_info_s* pkeep_alive_info, int timeout_ms);
参数说明
参数名称
类型
描述
输入/输出
pkeep_alive_info
iv_keep_alive_info_s
保活信息。
输入
timeout_ms
int
超时时间,单位 ms。
输入
返回值
返回值
描述
IV_ERR_NONE
成功。
IV_ERR_*
失败,对应相应错误码。

数据结构

本模块提供以下数据结构:
iv_keep_alive_info_s:保活信息。

iv_keep_alive_info_s

描述 保活信息内容。
typedef struct {
//服务器域名
char server_addr[KEEP_ALIVE_MESSAGE_MAX_LEN * 2];
//服务器端口号
uint32_t port;
//鉴权消息
uint8_t auth_msg[KEEP_ALIVE_MESSAGE_MAX_LEN];
//鉴权消息长度
uint32_t auth_msg_len;
//心跳消息
uint8_t heart_beat_msg[KEEP_ALIVE_MESSAGE_MAX_LEN];
//心跳消息长度
uint32_t heart_beat_msg_len;
//唤醒消息
uint8_t wake_up_msg[KEEP_ALIVE_MESSAGE_MAX_LEN];
//唤醒消息长度
uint32_t wake_up_msg_len;
} iv_keep_alive_info_s;
参数说明
成员名称
描述
server_addr
服务器域名。
port
端口号。
auth_msg
鉴权消息。
auth_msg_len
鉴权消息长度。
heart_beat_msg
心跳信息。
heart_beat_msg_len
心跳消息长度。
wake_up_msg
唤醒消息。
wake_up_msg_len
唤醒消息长度。
使用说明
1. 设备保活状态和在线状态不能同时存在,否则会造成设备强制下线。
2. 只有设备上线时,才能获取到保活信息,只有设备离线后,才可以进入保活状态。
3. 心跳包最大发送间隔为10min,推荐1min发送一次。

示例代码

1. 获取保活信息。
int keep_alive_info_update(void)
{
int timeout_ms = 5000;
int ret = 0;

memset(&sg_keep_alive_cfg, 0, sizeof(iv_keep_alive_s));

ret = iv_get_keep_alive_info(&sg_keep_alive_cfg.keep_alive_info, timeout_ms);
if (ret) {
Log_e("get keep alive info failed %d", ret);
return ret;
}
sg_keep_alive_cfg.running = 1;
return ret;
}
2. 模拟设备保活。
int simulation_device_low_power_keep_alive(void)
{
static uintptr_t _keepalive_fd = 0;
iv_keep_alive_info_s *p_keep_alive = &sg_keep_alive_cfg.keep_alive_info;
int rc = 0;
uint8_t _tmp_msg[256];

sg_keep_alive_cfg.start = 1;
while (sg_keep_alive_cfg.running) {
if (_keepalive_fd == 0) {
Log_d("fd invalid, try to connect...");
_keepalive_fd =
_connect_auth_keepalive(p_keep_alive->server_addr, p_keep_alive->port,
p_keep_alive->auth_msg, p_keep_alive->auth_msg_len);
usleep(5 * 1000);
continue;
}
size_t _recv_len = 0;
rc = qcloud_iv_tcp_read(_keepalive_fd, _tmp_msg, p_keep_alive->wake_up_msg_len, 60000,
&_recv_len);
if (rc == QCLOUD_IV_ERR_TCP_PEER_SHUTDOWN) {
Log_d("connection lost");
qcloud_iv_disconnect(_keepalive_fd);
_keepalive_fd = 0;
continue;
}
if (_recv_len > 0) {
Log_d("Recv message from server");
_dump_hex_msg(_tmp_msg, _recv_len);
if (_recv_len == p_keep_alive->wake_up_msg_len &&
!memcmp(_tmp_msg, p_keep_alive->wake_up_msg, p_keep_alive->wake_up_msg_len)) {
Log_d("Recv wakeup message....");
break;
}
}

Log_d("Sending keepalive message");
size_t _send_len = 0;
rc = qcloud_iv_tcp_write(_keepalive_fd, p_keep_alive->heart_beat_msg,
p_keep_alive->heart_beat_msg_len, 100, &_send_len);
if (_send_len != p_keep_alive->heart_beat_msg_len) {
Log_e("tcp write %d %u", rc, _send_len);
}
sleep(5);
}
sg_keep_alive_cfg.start = 0;
return 0;
}