基于LoRaWan协议1.1的pingslot状态机深度解读

科普型理解

关于pingslot最难的也就是pingslot打开窗口时间的算法了。因为beacon周期存在reserve和guard的时间,这两个时间是没有pingslot窗口打开的,所以服务器下发的时间计算需要避开这两个时间段。在这边小编按照协议解读终端pingslot窗口时间计算的方法。来一幅图回忆一下(图来自协议文档《lorawantm_specification_-v1.1》)
在这里插入图片描述

先修博文:《LoRaWan协议1.1ClassB部分学习笔记》https://blog.csdn.net/yanwumuxi/article/details/107133511
协议文档参考:《lorawantm_specification_-v1.1》
开源代码:https://github.com/Lora-net/LoRaMac-node

刚看代码的时候会对一些变量名字很陌生,不知道是用来做什么的,其实将协议文档对照着代码中的计算逻辑,我们就可以来一一解读。

协议文档中列出了几个要用到的参数:
在这里插入图片描述
说到pingslot,如果不用调代码,最直观地我们就想知道pingslot打开的频率(或者说多少秒打开一次pingslot),这是服务器或客户都有可能问到的问题。有一个变量periodicity就定义了这个秒数。在pingslotinforeq的mac请求中,终端会告诉网关periodicity,如下图所示,在服务器侧就会通过periodicity算出pingslot打开的周期。近似地,若periodicity为1,则2s打开一次,若periodicity为2,则4s打开一次,若periodicity为3,则8s打开一次。periodicity的变化范围是0-7。也就是说,pingslot的周期在1-128s之间。
在这里插入图片描述
如果你只是用别人的代码,了解到这里就够了。因为花太多时间去关心底层究竟是如何实现的反而拖慢了做应用层项目的进度。

但是如果你真的有时间也想要看再深入的代码,就和小编继续叭。如果你觉得小编有说的不对的地方,欢迎指正!这部分的重点在于整个pingslot的运算机制是如何进行的。如果你进入到LoRaMacClassBProcessPingSlot()这个过程函数,就躲不过几个灰常重要的状态机:

  • PINGSLOT_STATE_CALC_PING_OFFSET
  • PINGSLOT_STATE_SET_TIMER
  • PINGSLOT_STATE_IDLE

这几个状态机就描述了pingslot的整个过程。

深入理解——PingSlot状态机

PINGSLOT_STATE_CALC_PING_OFFSET

在这个状态机下是对pingoffset的计算。pingoffset是用aes加密来产生的伪随机数,在每一个beacon周期的开始都会算一个随机值,这个值在终端和服务器端是统一的。因为它是基于pingperiod来算的,而我们在上面讲到pingperiod是由periodicity计算得到的,而periodicity是终端上报给服务器端的,所以反推过来,pingoffset的值在终端和服务器端是会一样的。这也保证了服务器的pingslot消息下发和终端的pingslot的打开时间是一致的。

ComputePingOffset();//计算pingoffset:
	input:beacontime,dev_address,pingperiod
	output:pingoffset
Ping置态-PINGSLOT_STATE_SET_TIMER

pingoffset的单位也可以理解成是一种slot数量。

小编插一句:还记不记得之前我们说过,Beacon_window(122.880s)被分为4096个slot,每个时间为30ms。所以slot数量是一个被人为分割的小片段,而不是直接的时间单位。当然,可以通过slot数量来估计这个随机时间。

PINGSLOT_STATE_SET_TIMER

CalcNextSlotTime();//计算下一次slot的时间:
	input:slotoffset,pingperiod,pingnb
	output:timeoffset
	if(Ctx.BeaconCtx.Ctrl.BeaconAcquired == 1)//beacon正常收到
    RegionComputeRxWindowParameters();//计算接收窗口的参数。
  Ping置态-PINT_STATE_IDLE

在input中,slotoffset是一个伪随机偏移量。pingperiod是一个周期时间(每隔多少秒打开一次pingslot),那pingnb表示什么呢?

pingnb表示一个beacon周期内可以打开的pingslot数。pingnb也是通过periodicity算出来的,在源代码中,Ctx.nvmctx->pingslotctx.pingnb = 128 / (1<<periodicity)。所以pingnb的取值范围在2的0次方~2的7次方之间。

具体的算法步骤如下:

Step1: 计算当前时间到获得最后一个beacon的时间slot_time2。

首先,先计算出当前时间和最近的一个beacon接收时间的时间间隔。beacon1表示第一次收到beacon,beacon2表示第二次收到beacon,以此类推。值得注意的是,及时beacon2丢失了,也可以通过beacon1的获得时间按照beacon128秒的周期估算出beacon3的接收时间,即rxbeacon_time’。
在这里插入图片描述

然后再通过当前时间剪去slot_time1算出当前时间到获得最后一个beacon的时间slot_time2,如下图所示。
在这里插入图片描述

Step2: 将slot_time2加上CLASSB_BEACON_RESERVED+伪随机偏移时间,记作slot_time3。

在这里插入图片描述

Step3: 计算下一个准备下发的pingslot的数量,从而计算下一个下发的pingslot的时间。
Step4: 对比可以下发ping消息的最早时间(记做possible_time)和计算出来的下一次下发ping消息的时间(记做pingtime,或者slot_time3)。

若pingtime<possible_time则表示可以下发,继续往下计算。
在这里插入图片描述
Step5: 这时候我们别忘记我们身在哪里。我们在current_time时间点上,并且已经得到了下一次下发pingslot的时间pingtime(也就是slot_time3),最后一步,我们要知道在current_time时间点上,再过多久打开pingslot,以便我们做出这个动作。所以最后一步就是计算出这个time_offset。

在计算的时候需要考虑射频唤醒时间,所以还要减去射频唤醒的时间。
在这里插入图片描述
Step6: 以上5步我们已经计算出了打开打开pingslot的那个时刻,我们还需要知道打开这个pingslot要持续多久。用windowoffset来表示,这个值在配置rxwindow参数的时候会配置进去。单位是symbol(注:并不是以时间为单位)。

PINGSLOT_STATE_IDLE

多播状态有优先级。所以要先判断是否有多播消息,没有的话就打开ping rx接收窗口。如果有多播消息,则要跳过一小段rx的时间(不打开pingslot),这个时间为CLASSB_PING_SLOT_WINDOW,30ms。

 if(不是多播状态)
	Ping置态-PINGSLOT_STATE_RX;
    RegionRxConfig();//ping slot rx配置;
else
    Ping置态-PINGSLOT_STATE_CALC_PING_OFFSET;
    TimerSetValue();//设置pingslottimer时间为30ms
		TimerStart();//打开pingslottimer定时器。

到这里,pingslot时间的计算就完成了。希望大家和我一样有所收获!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值