关键词不能为空

当前您在: 主页 > 英语 >

Lorawan协议说明书

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2021-02-28 08:38
tags:

-

2021年2月28日发(作者:nisin)



1


章介绍



本文档描述了


LoRaWAN


网络协议,


是针对电池供电的终端设备


(


不管移动还是固 定


位置


)


进行优化的一套网络协议。< /p>



LoRaWAN


网络通常采用星型拓扑 结构,由拓扑中的


网关


来转发


终端


与后台


网络服


务器


间的消息。


网关


通过标准


IP


连接来接入


网络服务器




终端


则通过单跳的



LoRa


或者



FSK


来和一个或多个


网关


通讯。虽然主要传输方式是


终端


上行传输给


网络服


务器


,但所有的传输通常都是双向的 。



终端和网关间的通讯被分散到不同的信道频点和数据速率上 。数据速率的选择需要


权衡距离和消息时长两个因素,


使用不同 数据速率的设备互不影响。


LoRa


的数据速

< br>率范围可以从



0.3kbps




50kbps


为了最大程度地延长终端的电池寿命和扩大网络


容量,< /p>


LoRa


网络使用速率自适应


(ADR)


机制来独立管理每个终端的速率和


RF


输出。



虽然每个设备可以在任意信道,任意时间,发送任意数 据,但需要注意遵守如下规


定:



?



终端的每次传输都使用伪随机方式 来改变信道。频率的多变使得系统具有更


强的抗干扰能力。


< /p>


终端要遵守相应频段和本地区的无线电规定中的发射占空比要求。



终端要遵守相应频段和本地区的无线电规定中的发射时长要求。



?



?



twowinter


注:发射占空比,意思是发射时长占总时长的比 例。按照无线电规定,每


个设备不能疯狂发射霸占信道,总得给别人一点机会。



这份文档主要讲述协议细节,一些基于各地区规定的操作参数,例如发 射占空比和


发射时长等,在另一份文档


[LoRaWAN


地区参数


]


中做具体描述。将这份文档分开,


是为了加入新地区参数时不影响基础的协议规范。



1.1 LoRaWAN Classes


所有的

< p>
LoRaWAN


设备都必须至少实现本文档描述的



Class A


功能。


另外也可以实


现本文档中描述的



Class B




Class C


及后续将定义的可选功能。不管怎么样,设


备都必须兼容



Class A




1.2


文档约定



MAC


命令的格式写作



LinkCheckReq


(


粗斜体


)


,位和位域的格式写




FRMPayload


(


粗体


)



常量的格式写作

< p>


RECEIVE_DELAY1



变量的格式写作



N




在本文档中,



?



?



?



所有多字节字段的字节序均采用小端模式



EUI



8


字节字段,采用小端模式传输



默认所有


RFU


保留位都设为


0



2




LoRaWAN Classes


类型介绍



LoRa


是由


Semtech


面向长距离、低功耗、低速率应用 而开发的无线调制技术。本


文档中,将



Class A


基础上实现了更多功能的设备称为

< p>


更高



class


终端





2.1 LoRaWAN Classes


LoRa


网络包含基础


LoRaWAN


(称之为


Class A


)和可选功能(


Class B



Class C



:




N Classes


?



双向传输终端


(Class A)



Class A


的终端在每 次上行后都会紧跟两个短暂的


下行接收窗口,


以此实现双向传输 。


传输时隙是由终端在有传输需要时安排,


附加一定的随机延时


(



ALOHA


协议


)


。这种


Class A


操作是最省电的,要


求应用在终端上行传输后的很短时间内进行服务 器的下行传输。服务器在其


他任何时间进行的下行传输都得等终端的下一次上行。



?



划定接收时隙的双向传输终端


(Class B)



Class B


的终端会有 更多的接收时


隙。


除了


Class A


的随机接收窗口,


Class B


设 备还会在指定时间打开别的接


收窗口。为了让终端可以在指定时间打开接收窗口,终端需 要从网关接收时


间同步的信标



Bea con


。这使得服务器可以知道终端正在监听。



?



最大化接收时隙的双向传输终端


(Class C)



Class C


的终端基本 是一直打开


着接收窗口,


只在发送时短暂关闭。


Class C


的终端会比



Class A




Class B


更加耗电,但同时从服务器下发给终端的时延也是最短的。



2.2


文档范围


< br>这份


LoRaWAN


协议还描述了与


Class A


不同的其他



Class


的额外功能。更高



Class


的终端必须满足



Class A


定义的所有功能。



注意:


物理层帧格式,


MAC


帧格式,


以及协议中更高



class




Class A


相同的内容


都写在了



Class A


部分,避免内容重复。




3




PHY


帧格式



LoRa


有上行消息和下行消息。



3.1


上行消息


< br>上行消息是由终端发出,经过一个或多个网关转发给网络服务器。



上行消息使用



LoRa


射频帧的严格模式,消息中含有



PHDR




PHDR_CRC


。载


荷有


CRC


校验来保证完整性。



PHDR



PHDR_CRC


及载荷



CRC


域都通过射频收发器加入。



上行



PHY:


Preamble


PHDR


PHDR_CRC


PHYPayload


CRC



2.


上行


PHY


帧格式



3.2


下行消息



下行消息是由网络服务器发出,经过单个网关转发给单个终端。



下行消息使用射频帧的严格模式,消息中包含



PHDR




PHDR_CRC




下行



PHY:


Preamble



3.

< p>
下行


PHY


帧格式



PHDR


PHDR_CRC


PHYPayload


3.3


接收窗口



每个上行传输后终端都要开 两个短的接收窗口。接收窗口开始时间的规定,是以传


输结束时间为参考。





4.


终端接收时隙的时序图



3.3.1


第一接收窗口的信道,数据速率和启动。



第一接收窗口



RX1


使用的频率和上行频率有关,


使用的速率和上行速率有关。

< br>RX1


是在上行调制结束后的



RECEIVE_DELAY1


秒打开。


上行和



RX1


时隙下行速率的


关系是按区域 规定,


详细描述在


[LoRaWAN


地 区参数


]


文件中。


默认第一窗口的速率


是和最后一次上行的速率相同。



3.3.2


第二接收窗口的信道,数据速率和启动。



第二接收窗口



RX2


使用一个固定可配置的频率和数据速率,在上行调制结束后的



RECEIVE_DELAY2


秒打开。频率和数据速率可以通过



MAC


命令


(


见第


5



)


。默


认的频率和速率是按区域规定,详细描述在


[LoRaWA N


地区参数


]


文件中。



3.3.3


接收窗口的持续时间



接收窗口的长度 至少要让终端射频收发器有足够的时间来检测到下行的前导码。



3.3.4


接收方在接收窗口期间的处理



如果在 任何一个接收窗口中检测到前导码,射频收发器需要继续激活,直到整个下


行帧都解调完 毕。如果在第一接收窗口检测到数据帧,且这个数据帧的地址和


MIC

< br>校验通过确认是给这个终端,那终端就不必开启第二个接收窗口。



3.3.5


网络发送消息给终端


< /p>


如果网络想要发一个下行消息给终端,它会精确地在两个接收窗口的起始点发起传


输。



3.3.6


接收窗口的重要事项



终端在第一或第 二接收窗口收到下行消息后,或者在第二接收窗口阶段,不能再发


起另一个上行消息。< /p>



3.3.7


其他协议的收发处理



节点在


LoRaWAN


收发窗口阶段可以收发其他协议,只要终端能满足当地要 求以及


兼容


LoRaWAN


协议。



2


梳理解析



LoRaWAN



3

< br>章,主要是讲了接收窗口这回事,只要记住张图就行。




目前


RX1


一般是在上行后

< p>
1


秒开始,


RX2


是在上 行后


2


秒开始。



3


源码分析



3.1


源码流程


< br>在梳理这章节的对应代码时,自己手动做了张思维导图。有时是这样,代码再有层


次感,也不及一个图。好,请收下。




3.2


发送完成就开始


RX1



RX2


延时



static void OnRadioTxDone( void )


{


...


// Setup timers


if( IsRxWindowsEnabled == true )


{


TimerSetValue(&RxWindowTimer1, RxWindow1Delay );


TimerStart(&RxWindowTimer1 );


if( LoRaMacDeviceClass != CLASS_C )


{


TimerSetValue(&RxWindowTimer2, RxWindow2Delay );


TimerStart(&RxWindowTimer2 );


}


if( ( LoRaMacDeviceClass == CLASS_C ) || ( NodeAckRequested


== true ) )


{


TimerSetValue(&AckTimeoutTimer, RxWindow2Delay + ACK_TIMEO


UT +


randr( -ACK_TIMEOUT_RND, ACK_TIMEOUT_RND ) );


TimerStart(&AckTimeoutTimer );


}


}


...


}


3.3


接收窗口的射频处理



从上面一步,< /p>


我们已经清晰的知道,


对应的处理肯定是在


OnRxWindow1TimerEvent



OnRxW indow2TimerEvent


中。


< br>这两个接收窗口的处理,会对速率和信道进行设置,按照


LoRaWAN


协议中文版


_


配套文件地区参数


(


物理层


)


中对各地区的要求分别进行处理。



比 如这个


470


的处理,对上行信道对


4 8


取余得到下行信道。



RxWindowSetup( LORAMAC_FIRST_RX1_CHANNEL + ( Channel % 48 )


* LORAMAC_STEPWIDTH_




4




MAC


帧格式



LoRa


所有上下行链路消息都会携带


PHY


载荷,


PHY


载荷以


1


字节


MAC



(MH DR)


开始,紧接着


MAC


载荷


(MACPayload)


,最后是


4


字节的


MAC


校验码


(MIC)




射频

< br>PHY


层:



Preamble


PHDR


PHDR_CRC


PHYPayload


CRC


图< /p>


5.


射频


PHY


结构


(


注意



CRC


只有上行链路消息中存在


)


PHY


载荷:



MHDR


或者



MHDR


或者



MHDR




载荷结构



MAC


载荷:



FHDR




载荷结构



FHDR




DevAddr



8.


帧头结构





帧格式元素


(


即图


5~8)


FCtrl


FCnt


FOpts


FPort


FRMPayload


Join-Response


MIC


Join-Request


MIC


MACPayload


MIC


4.1 MAC



(PHYPayload)


Size (bytes)



PHYPayload



1


MHDR


1..M


MACPayload


4


MIC


MACPayload


字段的最大长度


M


,在第


6


章有详细说明。

< p>


4.2 MAC



(M HDR


字段


)


Bit#



MHDR bits



7..5


MType


4..2


RFU


1..0


Major


MAC


头中指定了消息类 型


(MType)


和帧编码所遵循的


L oRaWAN


规范的主版本号


(Major)

< br>。



4.2.1


消息类型


(MType


位字段


)

< br>LoRaWAN


定义了六个不同的


MAC


消息类型:


join request, join accept, unconfirmed


data up/down,


以及



confirmed data up/down




MType



描述



Join Request


Join Accept


Unconfirmed Data Up


Unconfirmed Data Down


Confirmed Data Up


Confirmed Data Down


RFU


Proprietary


000


001


010


011


100


101


110


111




消息类型



?



4.2.1.1 Join- request and join-accept


消息



join- request



join- accept


都是用在空中激活流程中,具体见章节


6.2


?



4.2.1.2 Data messages


Data messages


用来传输< /p>


MAC


命令和应用数据,这两种命令也可以放在单个消息中


发送。



Confirmed-data message


接收者需要应答。



Unconfirmed-data message


接收者则不需要应答。



Proprietary messages


用来处理非标准 的消息格式,不能和标准消息互通,只能用来


和具有相同拓展格式的消息进行通信。



不同消息类型用不同的方法保证消息一致性,

下面会介绍每种消息类型的具体情况。



4.2.2


数据消息的主版本


(Major


位字段


)


Major


位字段



00


01..11




列表



描述



LoRaW


AN R1


RFU


注意:


Major


定义了激活过程中


(join procedure)


使用的消息格式

< br>(见章节


6.2



< p>
MAC


Payload


的前

4


字节


(见第


4

< br>章)


。终端要根据不同的主版本号实现不同最小版本的


消 息格式。终端使用的最小版本应当提前通知网络服务器。



4.3 MAC


载荷


(MACPayload)


MAC


载荷,也就是所谓的



数据帧



,包含:帧头(


FHDR

< p>
)、端口(


FPort


)以及帧

< br>载荷


(FRMPayload


),其中端口和帧载荷是可 选的。



4.3.1


帧头


(FHDR)


FHDR


是由终端短地址


(DevAddr)



1


字节帧控制字节


(FCtrl)



2


字节帧计数器


(FCn t)


和用来传输


MAC


命令的帧选项< /p>


(FOpts


,最多


15


个字节


)


组成。



Size(bytes)



FHDR



4


DevAddr


1


FCtrl


2


FCnt


0..15


FOpts


FCtrl


在上下行消息 中有所不同,下行消息如下:



Bit#



FCtrl bits



7


ADR


6


ADRACKReq


5


ACK


4


FPending


[3..0]


FOptsLen


上行消息如下:



Bit#



FCtrl bits



7


ADR


6


ADRACKReq


5


ACK


4


RFU


[3..0]


FOptsLen


?



4.3.1.1


帧头中自适应数据速率的控制


(ADR, ADRACKReq in FCtrl)


LoRa


网络允许终端采用任何可能的数 据速率。


LoRaWAN


协议利用该特性来优化固


定终端的数据速率。


这就是自适应数据速率


(Ada ptive Data Rate (ADR))



当这个使能


时,网络会优化使得尽可能使用最快的数据速率。


< p>
移动的终端由于射频环境的快速变化,数据速率管理就不再适用了,应当使用固定

< br>的数据速率。



如果


ADR


的位字段有置位,


网络就会通过相应的


MA C


命令来控制终端设备的数据


速率。如果


ADR


位没设置,网络则无视终端的接收信号强度,不再控制终端设备


的数据速率。


ADR


位可以根据需要通过终端及网络来 设置或取消。


不管怎样,


ADR


机制都 应该尽可能使能,帮助终端延长电池寿命和扩大网络容量。



注 意:即使是移动的终端,可能在大部分时间也是处于非移动状态。因此根据它的


移动状态 ,终端也可以请求网络使用


ADR


来帮助优化数据速率。



如果终端被网络优化过的数据速率高于自己默认的数据速率,它需要 定期检查下网


络仍能收到上行的数据。每次上行帧计数都会累加


(


是针对于每个新的上行包,重传


包就不再增加计数

< p>
)



终端增加



ADR_ACK_CNT


计数。


如果 直到


ADR_ACK_LIMIT


次上行


(ADR_ACK_CNT >= ADR_ACK_LIMIT)


都没有收到下行回 复,它就得置高


ADR


应答请求位


(< /p>


ADRACKReq


)


。网络必须在规定 时间内回复一个下行帧,这个时


间是通过


ADR_ACK_DE LAY


来设置,上行之后收到任何下行帧就要把


ADR_ACK _CNT


的计数重置。当终端在接收时隙中的任何回复下行帧的


ACK


位字


段不需要设置,表示网关仍在接收这个设备的上行帧 。如果在下一个


ADR_ACK_DELAY


上行时间内都没收 到回复


(


例如,在总时间


ADR_AC K_LIMIT+ADR_ACK_DELAY


之后


)


,终端必须切换到下一个更低速率,


使得能够获得更远传输距离来重连网 络。


终端如果在每次


ADR_ACK_LIMIT


到了之


后依旧连接不上,就需要每次逐步降低数据速率。如果终端用它的默认 数据速率,


那就不需要置位


ADRACKReq


,因为无法帮助提高链路距离。



注意:不要


ADRACKReq


立刻回复,这样给网络预留一些余量,让它做出最好 的下


行调度处理。



注意:上行传输时,如果



ADR_ACK_CNT >= ADR_ACK_LIMIT


并且当前数据速


率比设备的最小数据速率高,就要设置



ADRACKReq


,其它情况下不需要。



?



4.3.1.2


消息应答位及应答流程


(ACK in FCtrl)


收到


confirmed


类型的消息时,


接收端要回复一条应答消息


(


应答位


ACK


要进行置位


)



如果发送者是终端,


网络就利用终端发送操作后打开的两个接 收窗口之一进行回复。


如果发送者是网关,终端就自行决定是否发送应答。



应答消息只会在收到消息后回复发送,并且不重发。



注意:为了让终端尽可能简单,尽可能减少状态,在收到


confirm ation


类型需要确


认的数据帧,需要立即发送一个严格的应 答数据帧。或者,终端会延迟发送应答,


在它下一个数据帧中再携带。

< br>


?



4.3.1.3


重传流程



当需要应答却没收到应答时 就会进行重发,重发的个数由终端自己定,可能每个终


端都不一样,这个参数也可以由网 络服务器来设置调整。



注意:一些应答机制的示例时序图在第


18


章中有提供。


< br>注意:如果终端设备重发次数到达了最大值,它可以降低数据速率来重连。至于后


面是否再重发还是说丢弃不管,都取决于终端自己。



注意:如 果网络服务器重发次数到达了最大值,它就认为该终端掉线了,直到它再


收到终端的消息 。一旦和终端设备的连接出现问题时,要不要重发都取决于网络服


务器自己。

< p>


注意:在重传期间的数据速率回退的建议策略在章节

18.4


中有描述。



?



4.3.1.4


帧挂起位


(FPending in FCtrl


只在下行有效


)


帧挂起位

< p>
(FPending)


只在下行交互中使用,


表示 网关还有挂起数据等待下发,


需要终


端尽快发送上行消息来再打 开一个接收窗口。



FPending


的详细用法在章节


18.3




?



4.3.1.5


帧计数器


(FCnt)


每个终端有两 个计数器跟踪数据帧的个数,一个是上行链路计数器(


FCntUp

),由


终端在每次上行数据给网络服务器时累加;


另一个是 下行链路计数器



FCntDown




由服务器在每次下行数据给终端时累计。网络服务器为每个终 端跟踪上行帧计数及


产生下行帧计数。终端入网成功后,终端和服务端的上下行帧计数同 时置


0


。每次


发送消息后,

< p>
发送端与之对应的



FCntUp




FCntDown


就会加


1



接收方会同步保


存接收数据的帧计数,对比收到的计数值和当前保存的值,如果两者相差小于

< p>


MAX_FCNT_GAP


(要考虑计数器滚 动),接收方就按接收的帧计数更新对应值。


如果两者相差大于



MAX_FCNY_GAP


就说明中间丢失了很多数据,这条 以及后面


的数据就被丢掉。



LoRa WAN


的帧计数器可以用


16


位和


32


位两种,节点上具体执行哪种计数,需要


在带外通知网络侧,告知计数器的位数。



如果采用


16


位帧计数,


FCnt

字段的值可以使用帧计数器的值,此时有需要的话通


过在前面填充

< br>0


(值为


0


)字节来补足;如果 采用


32


位帧计数,



FCnt


就对应计数器


32


位的


16


个低有效位


(


上行数据使用上行


FCnt


,下行数据使用

< p>
下行


FCnt)




终端在相同应用和网络密钥下,不能重复用相同的


FCntUp


数值,除非是重传。



?



4.3.1.6


帧可选项


(FOptsLen in FCtrl, FOpts)


FCtrl


字节中的


FOptsLen


位字段描述了整个帧可选项


(FOpts)


的字段长度。



FOpts

< p>
字段存放


MAC


命令,最长


15


字节,详细的


MAC


命令见章节


4.4




如 果


FOptsLen



0


,则


FOpts


为空。在


F OptsLen



0


时,则反之。如果


MAC


命令



FOpts


字段中体现,


port0


不 能用


(FPort


要么不体现,要么非


0)




MAC


命令不能同时出现在


FRMPayload



FOpts


中,如果出现了,设备丢掉该组数


据。



4.3.2


端口字段


(FPort)


如果帧载荷 字段不为空,端口字段必须体现出来。端口字段有体现时,若


FPort



值为


0


表示


FRMPayload


只包含了


MAC


命令;


具体见章节


4.4


中的


MAC


命令。



FPort


的数值从


1


< p>
223(0x01..0xDF)


都是由应用层使用。


FPort


的值从


224



255(0xE0..0xFF)


是保留用 做未来的标准应用拓展。



Size(bytes)



MACPayload



7..23


FHDR


0..1


FPort


0..N


FRMPayload


N


是应用程序载荷的字节个数。


N


的有效 范围具体在第


7


章有定义。



N


应该小于等于:



N <= M - 1 - (FHDR


长度


)


M



MAC


载荷的最大长度。



4.3.3 MAC


帧载荷加密


(FRMPayload)


如果数据帧携带了载荷,


FRMPayload


必须要 在


MIC


计算前进行加密。



加密机制是采用


IEEE802.15.4/2006



AES128


算法




默认的,加密和加密由


LoRaWAN


层来给所有的


FPort


来执行。如果加密


/


解密由应


用层来做更方便的话,也可 以在


LoRaWAN


层之上给特定


FP orts


来执行,除了端口


0


。具体哪 个节点的哪个


FPort



LoRaW AN


层之外要做加解密,必须要和服务器通


< br>out-of-band


信道来交互


(

< br>见第


19



)

< br>。



?



4.3.3.1 LoRaW


AN


的加密



密钥


K


根据不同的


FPor t


来使用:



FPort



0


1..255



3: FPort


列表



具体加密是这样:



pld = FRMPayload


对于每个数据帧,算法定义了一个块序列

Ai



i



1



k



k = ceil(len(pld) / 16)




Size(bytes)



Ai



1


4


1


4


4


FCntUp or FCntDown


1


1


K



NwkSKey


AppSKey


0x01


4 x 0x00


Dir


DevAddr


0x00


i


方向字段


(


Dir


)


在上行帧时为


0


,在下行帧时为


1.



Ai


通 过加密,得到一个由块


Si


组成的序列


S




Si = aes128_encrypt(K, Ai) for i = 1..k


S = S1 | S2 | .. | Sk


通过异或计算对


pay load


进行加解密:



?



4.3.3.2 LoRaW


AN


层之上的加密



如果


LoRaW


AN


之上的层级在已选的端口上


(


但不能是端口

< br>0


,这是给


MAC


命令保留的< /p>


)


提供了预加密的


FRMPayload



LoRaW


AN


LoRaW


AN


则不再



FRMPayload


进行修改,

< p>
直接将


FRMPayload


< br>MACPayload


传到应用层,


以及从应用层传到< /p>


MACPayload




4.4


消息校验码


(MIC)


消息检验码要计算消息中所有字段。



msg = MHDR | FHDR | FPort | FRMPayload


MIC


是按照


[RFC4493]


来计算:



cmac = aes128_cmac(NwkSKey, B0 | msg)


MIC = cmac[0..3]



B0


的定义 如下:



Size(bytes)



1


B0



0x49


4


1


4


4


1


1


len(msg)


4


x


Dir


0x00


DevAddr


FCntUp


or


0x00


FCntDown


方向字 段


(


Dir


)


在上行帧时为


0


,在下行帧时为


1.


LoRaWAN



4

< br>章,主要讲述了


MAC


帧格式,对所有涉及的字段都做了 解释。



千言万语汇成一句话,哦不,汇成一个表。








Dev


Addr


FC


trl


F


Cn


FO


pts










Prea


mble


PH


DR


PHDR


_CRC


MH


DR


FHDR


t






M


AC




PH


Y




FP


ort


FRMPa


yload


M


C


IC


R


C


Prea


mble


PH


DR


PHDR


_CRC


MH


DR


MACPayload


M


C


IC


R


C


Prea


mble


PH


DR


PHDR


_CRC


PHYPayload


C


R


C


< /p>


好了,帧格式是大家随手都能看到的东西,本尊作为


IoT


小能手,如果不能提出一


些稍有深度的信息增量,就对不起这个称号了 。所以,有些协议设计层面的心得要


分享下:



1.



特别酷的


ADR(


速率自适应


)


机制



这个章节中最亮眼的莫过于速率自适应机制,简直是为


LoRa


网络量身定做


的:一旦使能了


FCtrl


中的


ADR


位, 距离近信号好的节点用高速率,距离远


信号弱的节点用低速率,不小心被调高了速率,则 自动降下来。这样,尽可


能地提高了传输速率,也有效提高了网络容量。我已经见过不少 厂家,拿这


个协议的公知特点当产品卖点了。



2.



可同时携带数据和命令的


MAC




一般来 说,应用除了数据,出于管理需要,肯定还会涉及命令。比如基站要


查询节点状态,或者 节点要请求变更信道等。所以


LoRaWAN


协议设计上利



FOpts


把数据和命令揉在一个


MAC


帧里,这样可以提高交互效率,有效


地 降低功耗。


这在寸土寸金,


哦不,


寸库 仑


(


电量单位


)


寸金的物联网应用中,


是一个很有必要的设计。



3


源码解析



这章的处理基本都在



srcmacLoRaMac.c


中,下面按照


MAC


帧格式的字段逐个解


析下。

< br>


3.1 MAC



MHDR


< br>在


LoRaWAN


的数据


API


中处理了


MHDR


< br>这个字段内容比较少,


就按需选择了消


息类型是


confirm


还是


unconfirm




另外在管理


A PI


中的


Join- Req


的消息类型。



具体可见



LoRaMacMcpsRequest()




LoRaMacMlmeRequest()


这两个函数。



3.2 MACPayload



MACPayload


的组帧都在



PrepareFrame()


这个函数中处理,将


macHdr



macPayload



fCtrl



FPo rt



FRMPayload


都传递进 去,完成整个


MAC


层的数据组


帧。< /p>



LoRaMacBuffer


就存放了


MACPayload


的数据,这个变量的组帧和协议字段定义 是


一一对应。


MACPayload


的 组帧处理,在大流程上是对


join


和数据两种类型的帧分


别处理,用两个


case


分开。

< p>


为了方便阅览,我把函数代码框架提炼了出来。



LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoR


aMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint


16_t fBufferSize )


{


switch( macHdr-> )


{


case FRAME_TYPE_JOIN_REQ:


...//


省略



break;


case FRAME_TYPE_DATA_CONFIRMED_UP:


NodeAckRequested = true;


//Intentional falltrough


case FRAME_TYPE_DATA_UNCONFIRMED_UP:


...


fCtrl->Req = AdrNextDr( fCtrl->, true,


&lsDatarate );


...


if( SrvAckRequested == true )


{


SrvAckRequested = false;


fCtrl-> = 1;


}



LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF;


LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0


xFF;


LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) &


0xFF;


LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 24 ) &


0xFF;



LoRaMacBuffer[pktHeaderLen++] = fCtrl->Value;



LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;


LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0x


FF;



// Copy the MAC commands which must be re-send in


to the MAC command buffer


memcpy1(&MacCommands Buffer[MacCommandsBufferIndex], MacCo


mmandsBufferToRepeat, MacCommandsBufferToRepeatIndex );


MacCommandsBufferIndex += MacCommandsBufferToRep


eatIndex;



if( ( payload != NULL ) && ( payloadSize > 0 ) )


{


if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGT


H ) && ( MacCommandsInNextTx == true ) )


{


fCtrl->en += MacCommandsBufferIndex;



// Update FCtrl field with new value of Op


tionsLength


LoRaMacBuffer[0x05] = fCtrl->Value;


for( i = 0; i < MacCommandsBufferIndex; i++ )


{


LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];


}


}


}


else


{


if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx


) )


{


payloadSize = MacCommandsBufferIndex;


payload = MacCommandsBuffer;


framePort = 0;


}


}


MacCommandsInNextTx = false;


// Store MAC commands which must be re-send in ca


se the device does not receive a downlink anymore


MacCommandsBufferToRepeatIndex = ParseMacCommand


sToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacC


ommandsBufferToRepeat );


if( MacCommandsBufferToRepeatIndex > 0 )


{


MacCommandsInNextTx = true;


}


MacCommandsBufferIndex = 0;



if( ( payload != NULL ) && ( payloadSize > 0 ) )


{


LoRaMacBuffer[pktHeaderLen++] = framePort;



if( framePort == 0 )


{


LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, L


oRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoR


aMacPayload );


}


else


{


LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, L


oRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoR


aMacPayload );


}


memcpy1( LoRaMacBuffer + pktHeaderLen, LoRaMacPayload, pay


loadSize );


}


LoRaMacBufferPktLen = pktHeaderLen + payloadSiz


e;



LoRaMacComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen, LoR


aMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic


);



LoRaMacBuffer[LoRaMacBufferPktLen + 0] = mic & 0xFF;


LoRaMacBuffer[LoRaMacBufferPktLen + 1] = ( mic >> 8 ) & 0xF


F;


LoRaMacBuffer[LoRaMacBufferPktLen + 2] = ( mic >> 16 ) & 0x


FF;


LoRaMacBuffer[LoRaMacBufferPktLen + 3] = ( mic >> 24 ) & 0x


FF;



LoRaMacBufferPktLen += LORAMAC_MFR_LEN;



break;


case FRAME_TYPE_PROPRIETARY:


...//


省略



break;


default:


return LORAMAC_STATUS_SERVICE_UNKNOWN;


}



return LORAMAC_STATUS_OK;


}


Join-request


的组帧 处理对应协议第


6




6.2.4 Join-request message




数据帧的组帧处 理则稍微复杂些,尤其是


FHDR


,下面逐个字段讲解下


FHDR




3.2.1 MACPayload


中的


FHDR


?




中的


DevAddr


LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF;


LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0xFF;


LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) & 0xFF;


LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 24 ) & 0xFF;


?




中的


FCtrl


首先



ADR


位段是在传入



PrepareFrame()


之前,就做了处理。



= AdrCtrlOn;


接着



AdrAckReq


位段,在长期失联情况下会发送


AdrAckReq


确认链路。



fCtrl->Req = AdrNextDr( fCtrl->, true,


&lsDatarate );


最后



F0ptsLen


位段,会在下面计算完

FOpts


之后更新。



?




中的


FCnt


LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;


LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF;


这个

< br>UpLinkCounter


会在物理层发送完成后会按照协议进行累加。可以看 到这是个


32


位计数器,按照协议规定,



如果采用


32


位帧计数,


FCnt


就对应计数器


32

位的


16


个低有效位


< p>



这是上行的,另外下行的也类似。



?




中的


FOpts


MAC


命令放入


F0pts


中,


并且更新


F0ptsLen

< p>


MAC


命令,


要么使用 非零的


FPort


来和数据一起传输,要么使用


FPort0


来单独传输。



// Copy the MAC commands which must be re-send into the MAC


command buffer


memcpy1(&MacCommandsBuffer[MacCommandsBuff erIndex], MacCo


mmandsBufferToRepeat, MacCommandsBufferToRepeatIndex );


MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;



if( ( payload != NULL ) && ( payloadSize > 0 ) )


{


if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGT


H ) && ( MacCommandsInNextTx == true ) )


{


fCtrl->en += MacCommandsBufferIndex;



// Update FCtrl field with new value of OptionsLengt


h


LoRaMacBuffer[0x05] = fCtrl->Value;


for( i = 0; i < MacCommandsBufferIndex; i++ )


{


LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];


}


}


}


else


{


if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx


) )


{


payloadSize = MacCommandsBufferIndex;


payload = MacCommandsBuffer;


framePort = 0;


}


}


3.2.2 MACPayload


中的


FPort


这个是在应用层一直传递进去的,协议栈默认是用了端口


2


。 这个是后期大家在应


用时要调整的,类似于


IP


端口,不同的端口对应不同的服务。



3.3 MIC


解析



在函数



PrepareFrame( )


的最后是调用


LoRaMacComputeMic() < /p>


计算出整个


MAC


层的

< br>校验码。应用层这边基本不用改这边就暂时不细究了。






5




MAC


命令



对网络管理者而言,


有一套专门的


MAC


命令用来在服务器和终端


MAC


层之间交互。


这套


MAC


命令对应用程序


(


不管是服务器端还是终端设备的应用程序


)

是不可见的。



单个数据帧中可以携带

MAC


命令,要么在


FOpts


字 段中捎带,要么在独立帧中将


FPort


设成

< br>0


后放在


FRMPayload


里。如果采用


FOpts


捎带的方式,


MAC


命令是不


加密并且不长度超过


1 5


字节。如果采用独立帧放在


FRMPayload

< p>
的方式,那就必须


采用加密方式,并且不超过


FR MPayload


的最大长度。



注意 :如果


MAC


命令不想被窃听,那就必须以独立帧形式放在


FRMPayload


中。



每个


MAC


命令是由



1


字节


CID


跟着一段可能为空的字节序列组成的。



CID



Command



由谁发送






0x02


0x02


LinkCheckReq


LinkCheckAns


x







x


终端利用这个命令来判断网络连接质量



描述



LinkCheckReq


的回复。包含接收信号强度,告知终端


收质量



0x03


0x03


LinkADRReq


LinkADRAns



x


x



向终端请求改变数据速率,发射功率,重传率以及信道


Link ADRReq


的回复。



0x04


0x04


0x05


0x05


0x06


0x06


0x07


0x07


0x08


0x08


DutyCycleReq


DutyCycleAns


RXParamSetupReq


RXParamSetupAns


DevStatusReq


DevStatusAns


NewChannelReq


NewChannelAns



x



x



x



x


x



x



x



x



x



x


向终端设置发送的最大占空比。



DutyCycleReq


的回复。



向终端设置接收时隙参数。



RXPa ramSetupReq


的回复。



向终端查询其状态。



返回终端设备的状态,即电池余量和链路解调预算。



创建或修改



1


个射频信道定义。



NewChannelReq


的回复。



设置接收时隙的时间。



RXTimi ngSetupReq


的回复。



给私有网络命令拓展做预留。



RXTimingSetupReq



RXTimingSetupAns


x


x


0x80~0xFF


私有




4< /p>



MAC


命令表



注意:


MAC


命令的长度虽然没有明确 给出,但是


MAC


执行层必须要知道。因此未

< br>知的


MAC


命令无法被忽略,


且 前面未知的


MAC


命令会终止


MAC< /p>


命令的处理队列。


所以建议按照


LoRa WAN


协议介绍的


MAC


命令来处理< /p>


MAC


命令。这样所有基于


LoRaWA N


协议的


MAC


命令都可以被处理,即 使是更高版本的命令。



2


梳理解析




LoRaWAN



4


章的帧格式可以得 到如下信息:


MAC


命令,要么使用


F Port0



单独传输,要么使用非零的


FPort


来和数据一起传输。



L oRaWAN



5


章,


LoRaWAN


出于网络管理需要,


提出了

< p>
9



MAC


命令,


这个章


节是对


9


条命 令进行具体的描述。



说个题外话,


C LAA(


中国


LoRa


应用联盟


)



9


条命令以外还 扩充了一些


MAC


命令。


现阶段协议还 不能公开,


所以我就不多说了。


中兴目前作为

< br>LoRa


联盟董事会成员,


也许以后会把这些拓展


MAC


命令引入到


LoRaWAN

< p>
协议也说不准,大家暂且当个


课外知识了解下就好。



3


代码位置



MAC


命令枚举



/*!


* LoRaMAC mote MAC commands


*


* LoRaWAN Specification V1.0.1, chapter 5, table 4


*/


typedef enum eLoRaMacMoteCmd


{


/*!


* LinkCheckReq


*/


MOTE_MAC_LINK_CHECK_REQ = 0x02,


/*!


* LinkADRAns


*/


MOTE_MAC_LINK_ADR_ANS = 0x03,


/*!


* DutyCycleAns


*/


MOTE_MAC_DUTY_CYCLE_ANS = 0x04,


/*!


* RXParamSetupAns


*/


MOTE_MAC_RX_PARAM_SETUP_ANS = 0x05,


/*!


* DevStatusAns


*/


MOTE_MAC_DEV_STATUS_ANS = 0x06,


/*!


* NewChannelAns


*/


MOTE_MAC_NEW_CHANNEL_ANS = 0x07,


/*!


* RXTimingSetupAns


*/


MOTE_MAC_RX_TIMING_SETUP_ANS = 0x08,


}LoRaMacMoteCmd_t;





/*!


* LoRaMAC server MAC commands


*


* LoRaWAN Specification V1.0.1 chapter 5, table 4


*/


typedef enum eLoRaMacSrvCmd


{


/*!


* LinkCheckAns


*/


SRV_MAC_LINK_CHECK_ANS = 0x02,


/*!


* LinkADRReq


*/


SRV_MAC_LINK_ADR_REQ = 0x03,


/*!


* DutyCycleReq


*/


SRV_MAC_DUTY_CYCLE_REQ = 0x04,


/*!


* RXParamSetupReq


*/


SRV_MAC_RX_PARAM_SETUP_REQ = 0x05,


/*!


* DevStatusReq


*/


SRV_MAC_DEV_STATUS_REQ = 0x06,


/*!


* NewChannelReq


*/


SRV_MAC_NEW_CHANNEL_REQ = 0x07,


/*!


* RXTimingSetupReq


*/


SRV_MAC_RX_TIMING_SETUP_REQ = 0x08,


}LoRaMacSrvCmd_t;


MAC


命令的接收处理



OnRadioRxDone()


携带着


MAC


帧进来,经过层层筛选,最终到达


ProcessMacComma nds()


来处理


MAC


命令。



这里代码中涉及的两种处理方式,可以跟协议对应起来:


port = 0


时,


MAC

< br>命令放



FRMPayload


中,需要先解密再处理;


port


非零时,

MAC


命令放在


fopts


中。< /p>



if( port == 0 )


{


if( en == 0 )


{


LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,


frameLen,


nwkSKey,


address,


DOWN_LINK,


downLinkCounter,


LoRaMacRxPayload );



// Decode frame payload MAC commands


ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr );


}


} else {


if( en > 0 )


{


// Decode Options field MAC commands. Omit the fPor


t.


ProcessMacCommands( payload, 8, appPayloadStartIndex - 1,


snr );


}


}


MAC


命令的发送及回复


< p>
MAC


命令的发送及回复处理都在这个函数中,


A ddMacCommand()




协 议栈对


MAC


命令发送的处理还是比较简单的,


都是放在


Fopts


中来传输,


都在这



15


字节的


MacCommandsBuffer


中。



LinkADR



LoRaWAN


网络管理中相当重要的一个


MAC


命令,其解析占用 了


183


行。索性专门写篇源码解析,记录下。



阅读此文前,最好再把第五章的这个命令好好翻一翻,代码和协议才能对应上 。



我正在陆续对协议的各个章节进行翻译,具体其他章节的译 文,以及译文之外的代


码解析,可点此查看帖子


LoRa


学习笔记


_


汇总


。< /p>



本文作者


twowinter


,转载请注明作者:


/iotisan/



LinkADRReq


的源码解析



按照代码思路走一遍。



1.


解析



DataRate_TXPower


字段



datarate = payload[macIndex++];


txPower = datarate & 0x0F;


datarate = ( datarate >> 4 ) & 0x0F;



if( ( AdrCtrlOn == false ) &&


( ( lsDatarate != datarate ) || ( LoRaM


lsTxPower != txPower ) ) )


{ // ADR disabled don't handle ADR requests if server tries


to change datarate or txpower


// Answer the server with fail status


// Power ACK = 0


// Data rate ACK = 0


// Channel mask = 0


AddMacCommand( MOTE_MAC_LINK_ADR_ANS, 0, 0 );


macIndex += 3; // Skip over the remaining bytes of the req


uest


break;


}


如果终端


ADR


没开,那么就立即丢弃本命令处理。这里的


macIndex += 3


是对应


LinkADRReq< /p>


的剩余命令长度


3


而言的。



2.


解析



ChMask


字段



chMask = ( uint16_t )payload[macIndex++];


chMask |= ( uint16_t )payload[macIndex++] << 8;


3.


解析



Redundancy


字段



nbRep = payload[macIndex++];


chMaskCntl = ( nbRep >> 4 ) & 0x07;


nbRep&= 0x0F;


if( nbRep == 0 )


{


nbRep = 1;


}


把字段中的



chMaskCntl




nbRep


都给解析了出来。



4.


按地区规定处理



chMaskCntl


,及判断



ChMask


有效性



#elif defined( USE_BAND_470 )


if( chMaskCntl == 6 )


{


// Enable all 125 kHz channels


for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 1


6, k++ )


{


for( uint8_t j = 0; j < 16; j++ )


{


if( Channels[i + j].Frequency != 0 )


{


channelsMask[k] |= 1 << j;


}


}


}


}


else if( chMaskCntl == 7 )


{


status&= 0xFE; // Channel mask KO


}


else


{


for( uint8_t i = 0; i < 16; i++ )


{


if( ( ( chMask & ( 1 << i ) ) != 0 ) &&


( Channels[chMaskCntl * 16 + i].Frequency == 0 ) )


{// Trying to enable an undefined channel


status&= 0xFE; // Channel mask KO


}


}


channelsMask[chMaskCntl] = chMask;


}


如果



chMaskCntl



6


,则所有信道都使能。如果



chMaskCntl



7


,则由于未定义


返回失败。



其他有效



chMaskCntl < /p>


情况下,先检查是否有未定义的频点,如果没问题则更新对


应的< /p>


channelsMask




5.


判断速率有效性



if( ValidateDatarate( datarate, channelsMask ) == false )


{


status&= 0xFD; // Datarate KO


}


6.


判断发射功率有效性



if( ValueInRange( txPower, LORAMAC_MAX_TX_POWER, LORAMAC_M


IN_TX_POWER ) == false )

-


-


-


-


-


-


-


-



本文更新与2021-02-28 08:38,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/679941.html

Lorawan协议说明书的相关文章

  • 爱心与尊严的高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊严高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊重的作文题库

    1.作文关爱与尊重议论文 如果说没有爱就没有教育的话,那么离开了尊重同样也谈不上教育。 因为每一位孩子都渴望得到他人的尊重,尤其是教师的尊重。可是在现实生活中,不时会有

    小学作文
  • 爱心责任100字作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任心的作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文