wiota 在指定时刻发送数据
概述
这里是一个wiota异步网关在指定时刻发送广播和终端收到广播后在指定时刻回复数据的简单demo,异步通信需要两个设备,一个作为发送广播数据的网关,另一个则作为接收广播数据的终端。首先确保两个设备的静态数据表等配置统一和终端数据发送API参数中的目标user_id正确,否则收发数据会失败。
DEMO所在工程目录路径:
PS/app/test/test_wiota_fixed_time_dev.c
PS/app/test/test_wiota_fixed_time_gw.c
默认该DEMO为关闭状态,打开需要添加宏定义如下:
#define WIOTA_ASYNC_FIXED_TIME_TEST
在main.c文件中加入声明:
int wiota_gw_manger_init(void);
或
int wiota_device_manger_init(void);
同时在main()函数中调用下列函数:
wiota_gw_manger_init();
或
wiota_device_manger_init();
指定时刻发送数据原理
概述
广播数据结构:
typedef struct
{
uint8_t type;
uint8_t report_interval; // 终端上报信息需占用时槽 ASYNC_REPORT_INTAERVAL 200ms
uint8_t bc_interval; // 网关广播需占用时槽 ASYNC_BC_SLOT 200ms
uint32_t bc_count; // 记录广播次数
uint32_t gw_id; // 网关user_id
uint32_t dev_id[2]; // 异步终端user_id顺序表
} bc_data_t;
网关首先发送一个广播,然后开始延时等待发送第二个广播,延时的这段时间属于所有终端上报数据给网关的时间,延时结束也表示所有终端都上报完成,随后网关开始发送第二个广播,如此一直循环。
当终端收到广播并解析完成后,可以得到以下数据:
1.发送一个广播的时槽
bc_interval
,单位ms。2.终端上报数据时需要占用的时槽
report_interval
,单位ms。3.
cur_rf_cnt
,单位us,它可以理解成网关开始发送广播的时刻。4.广播包里的user_id顺序表,如果匹配到了自己的user_id,则记录下自己是第几个(该demo中用“
order
"表示,从0开始)。
然后根据上面的值计算终端向网关上报数据的指定时刻(us) = cur_rf_cnt
+ bc_interval
* 1000 + order
* report_interval
* 1000。
示例
下图所示的为一个异步网关和两个异步终端之间的通信,“gw”表示异步网关,“dev1”和“dev2”表示两个异步终端,“send bc”表示“发送广播”,横轴表示时间,单位ms。发送一个广播的时槽ASYNC_BC_SLOT
,终端上报数据占用的时槽 ASYNC_REPORT_INTAERVAL
。
如图,首先gw在0时刻发送一个广播,广播开始时间start_time
(单位us)为0,广播的结束时间bc_complete_time
(单位us)为a0(a0 <= a),可以通过uc_wiota_get_curr_rf_cnt()接口获取。一个广播完成后从a0开始延时,一直到dev2上报信息完成为止(延时时长用delay_time
表示,单位ms),delay_time
= ASYNC_BC_SLOT
+ ASYNC_REPORT_INTAERVAL
* ASYNC_BC_DEV_NUM
- (bc_complete_time
- start_time
)/1000
,然后开始发送下一个广播。
如图,对于dev1,gw在a0时刻发送完广播后,dev1在a0时刻收到广播并解析广播信息,即可获取相关信息,计算后得order
= 0,根据上述公式得dev1开始上报信息的时刻0 + 200 + 0 * 200 = a1,结束时刻为 b(注意:即使实际上广播发送完成时间有可能在b0处,但我们任然把广播结束时间确定成b),然后dev1继续等待接收广播。
同理,对于dev2,order
= 1。dev2要等dev1上报完成后才开始上报,故dev2开始上报信息的时刻为b,时刻c处完成上报。若存在dev3,则上报信息的时间段在c至d。同理若存在dev4,则dev4的上报时间段在d至e。
对于上图来说,dev2在c时刻上报信息完成,同时gw延时结束,然后在c时刻(a0 + delay_time
= 600 = c)开始发送第二个广播 。
注意dev1和dev2因为开机时间的差异,故 cur_rf_cnt
在实际上值不一定相同,但物理时间上是相同的时刻。
流程和接口
网关流程
网关初始化完成后,发送一个广播(使用接口uc_wiota_send_data()),然后延时特定的时间后再发送下一个广播,一直循环。广播数据详细内容可见上方结构体。发送广播前先获取开始时间,广播发送完成后再获取结束时间,这两个时间差就是需要延时的时长。
终端流程
如图所示,终端初始化后,进入循环。循环内,先去队列获取广播数据且解析广播数据,解析后可得到user_id顺序表,终端在该表中查询是否存在自己的id,不存在则不需要进行上报,若存在,则记录下顺序值order
,然后根据上面描述的公式计算出上报数据的指定时刻,并使用uc_wiota_send_data_with_start_time()接口进行上报,该接口的参数start_time
即表示指定的时刻。
使用的API接口列表
序号 | 函数名 | 功能 |
---|---|---|
1 | uc_wiota_init() | wiota协议栈的初始化 |
2 | uc_wiota_get_system_config() | 获取系统配置 |
3 | uc_wiota_set_userid() | 设置用户ID |
4 | uc_wiota_set_freq_info() | 设置频点 |
5 | uc_wiota_set_system_config() | 设置系统配置 |
6 | uc_wiota_set_crc() | 设置CRC校验 |
7 | uc_wiota_set_data_rate() | 设置数据传输速率 |
8 | uc_wiota_set_detect_time() | 设置发送前检测等待时间 |
9 | uc_wiota_set_unisend_fail_cnt() | 设置单播重传次数 |
10 | uc_wiota_set_subframe_num() | 设置发送时的子帧数 |
11 | uc_wiota_set_cur_power() | 设置当前的功率 |
12 | uc_wiota_register_recv_data_callback() | 注册被动接收数据回调 |
13 | uc_wiota_run() | 启动wiota协议栈 |
14 | uc_wiota_get_userid() | 获取用户ID |
15 | uc_wiota_get_curr_rf_cnt() | 获取当前时间(us) |
16 | uc_wiota_send_data() | 发送数据 |
17 | uc_wiota_send_data_with_start_time() | 指定时刻发送数据 |
18 | uc_wiota_exit() | 关闭WIoTa协议栈 |