由于lpn节点支持 pb_gatt_adv 和 pb_adv两种广播
pb_gatt_adv采用telink_ble的方式,执行广播的流程如下:
//广播发送过程,由系统回调执行
->>app_advertise_prepare_handler()
--->>gatt_adv_prepare_handler()
---------->>set_adv_provision()
----------->>>set_pb_gatt_adv()
gatt_adv 广播使能标志 gatt_adv_send_flag
使能gatt_ad广播发送,广播周期:ADV_INTERVAL_MS = 160ms
pb_adv 采用main_loop循环的方式发送 执行流程如下:
//mesh_pb_adv 广播初始化
->>mesh_init_all()
--->>>beacon_str_init()
//beacon loop发送流程
->mesh_beacon_send_proc()
---->>>unprov_beacon_send()
pb_gatt 广播使能标志 beacon_send.en
用于使能mesh_beacon发送,广播周期:MAX_BEACON_SEND_INTERVAL = 2s
通过手机连接设备,通过gatt方式进行配网
--->>pb_gatt_Write()
---->>>dispatch_pb_gatt()
------------>>>set_dev_key() //配网成功,保存秘钥key
->>app_event_handler_adv()
--->>>mesh_provision_rcv_process()
------------>>>mesh_provison_process()
------------>>>mesh_node_rc_data_dispatch() //处理mesh数据
---------------------------->>>set_dev_key() //配网成功,保存秘钥key 即为配网成功
通过获取是否保存网络秘钥(net_key)来判断配网是否完成。
lpn_provision_ok = is_net_key_save();// 1: 配网成功 0 :配网失败
上图,定义LPN节点与FN节点消息请求和响应交互的时序。
FN节点端说明:
好友节点 收到 req请求之后,延时(friend offer delay )通过计算实际的延迟 发送offer 消息。
如果在 1s内收到lpn节点的poll消息任务好友关系建立成功。否则失败。
特别说明:friend offer delay >= 100ms
好友关系建立成功的时序逻辑解释如下:
第一阶段:发送好友req请求后100ms,开启扫描持续时间为1s,等待好友节点发送offer消息
- lpn节点接收成功:进行第二阶段发送poll
- lpn节点接收失败,可以重新发起req ,协议规定两次req间隔至少大于 1100ms。
第二阶段:发送poll请求100ms,开启持续扫描模式时间为1s,等到接收upadte消息。
- lpn节点1s内接收update成功 ,则表示建立好友成功
- lpn节点1s内接收update失败 ,则选择重新建立好友关系,发送req请求。
特别说明:节点可以通过rssi 和接受好友节点的ReceiveWindow 参数 进行选择好友节点。
好友节点 收到 req请求之后,延时(friend offer delay )通过计算实际的延迟 发送offer 消息。
如果在 1s内收到lpn节点的poll消息任务好友关系建立成功。否则失败。
特别说明:friend offer delay >= 100ms
好友关系超时断开判断时序,依据消息超时机制判断。
设置的poll超时时间 >= 两个poll的时间间隔
多次重试poll消息 在poll超时时间没有响应 终止关系,重新建立好友关系过程。
在polltimeout 时间之前没收到 好友节点消息 终止好友关系。
由于这部分代码不开源,无法分析完整消息流程。
部分流程分析:
//结构体原形:
typedef struct{
u16 LPNAdr;
u16 FriAdr;
mesh_ctl_fri_req_t req;
mesh_ctl_fri_offer_t offer;
mesh_ctl_fri_poll_t poll;
mesh_ctl_fri_update_t update;
u8 link_ok; //好友关系状态标志
}mesh_lpn_par_t;
lpn_rx_offer_handle()
{
//主要选择合适的好友节点,给全局好友节点消息结构体,mesh_lpn_par。
mesh_lpn_par.FriAdr = p_nw->src; //选择合适好友节点地址
}
lpn_no_offer_handle()
{
//lpn节点 再次发送好友请求。
}
在由系统根据 mesh_lpn_par, 发送poll消息,等待好友节点update消息。
建立成功回调,friend_ship_establish_ok_cb_lpn()处理,发送低功耗节点订阅消息列表。
建立完成好友关系之后,通过该接口判断好友关系状态:is_friend_ship_link_ok_lpn();
整个睡眠过程处理函数如下在mesh_lpn_proc_suspend()函数处理中睡眠分为:
suspend mode 睡眠模式和deepsleep retention mode模式
//lpn节点睡眠结构体
typedef struct{
u32 tick_tx;
u32 sleep_ms; //睡眠时间
u16 op; //lpn睡眠前的设备运行状态
u8 sleep_ready; //是否可以进入睡眠,广播发送完成即可进入睡眠准备状态置1,有adv数据发置0
}mesh_lpn_sleep_t;
//LPN节点睡眠前的操作状态,op 总共有如下几种参数
#define CMD_CTL_ACK (0x00)
#define CMD_CTL_POLL (0x01)
#define CMD_CTL_UPDATE (0x02)
#define CMD_CTL_REQUEST (0x03)
#define CMD_CTL_OFFER (0x04)
#define CMD_CTL_CLEAR (0x05)
#define CMD_CTL_CLR_CONF (0x06)
#define CMD_CTL_SUBS_LIST_ADD (0x07)
#define CMD_CTL_SUBS_LIST_REMOVE (0x08)
#define CMD_CTL_SUBS_LIST_CONF (0x09)
#define CMD_CTL_HEARTBEAT (0x0a)
#define CMD_ST_NORMAL_UNSEG (0xFFF0)
#define CMD_ST_NORMAL_SEG (0xFFF1)
#define CMD_ST_SLEEP (0xFFF2)
#define CMD_ST_POLL_MD (0xFFF3) //消息接收
请求好友关系:LPN发送好友REQUEST , 此时lpn_sleep.op = CMD_CTL_REQUEST
函数进入 suspend_handle_wakeup_rx()处理,此时函数进入 suspend mode 睡眠模式
睡眠 sleep_ms 唤醒,执行扫描程序,等待接受offer消息。
接受好友offer消息:接受好友offer消息, 发送poll消息 lpn_sleep.op = CMD_CTL_POLL
函数进入 suspend_handle_wakeup_rx()处理,此时函数进入 suspend mode 睡眠模式
睡眠 sleep_ms 唤醒,执行扫描程序,等待接受update消息。
接受好友update消息:接受完成,则好友关系建立,进入lpn_sleep.op = CMD_ST_SLEEP,则程序进入
suspend_handle_next_poll_interval(),进入长睡眠,睡眠模式为deepsleep retention mode,poll周期唤醒执行poll消息处理。
poll消息请求: 执行poll消息请求过程 ,收到好友节点响应消息为MD=0的消息,则重新执行poll消息,执行新的 睡眠周期。
如果好友关系建立失败:设备睡眠操作模式为:lpn_sleep.op = CMD_ST_SLEEP,程序也会进入
suspend_handle_next_poll_interval()进入长睡眠 周期性执行好友REQ请求消息。