二、LMIC library 编程模型及API

LMiC库可以通过一组API函数(API functions),运行时函数(run-time functions),回调函数(callback functions),和全局LMIC数据结构(global LMIC data structure) 四种方式来实现访问。

LMiC库提供了一个简单的基于事件的编程模型,其中所有协议事件都是调度到应用程序的onEvent()回调函数;为了释放应用程序诸如定时或中断等细节,该库具有内置的运行时环境来处理定时器排队和Job管理。所有协议事件都是通过回调onEvent()函数来实现的。

LMiC库由两个宏来定义

#define LMIC_VERSION_MAJOR 1
#define LMIC_VERSION_MINOR 5

LMIC库外部协议接口定义都包含在lmic.h中,以供外部使用。

#include “lmic.h”

数据结构struct lmic_t

struct lmic_t {
// Radio settings TX/RX (also accessed by HAL)
ostime_t txend;
ostime_t rxtime;
u4_t freq;
s1_t rssi;
s1_t snr;
rps_t rps;
u1_t rxsyms;
u1_t dndr;
s1_t txpow; // dBm osjob_t osjob; // Channel scheduling
#if defined(CFG_eu868)
band_t bands[MAX_BANDS];
u4_t channelFreq[MAX_CHANNELS];
u2_t channelDrMap[MAX_CHANNELS];
u2_t channelMap;
#elif defined(CFG_us915)
u4_t xchFreq[MAX_XCHANNELS]; // extra channel frequencies (if device is behind a repeater)
u2_t xchDrMap[MAX_XCHANNELS]; // extra channel datarate ranges ---XXX: ditto
u2_t channelMap[(72+MAX_XCHANNELS+15)/16]; // enabled bits
u2_t chRnd; // channel randomizer
#endif
u1_t txChnl; // channel for next TX
u1_t globalDutyRate; // max rate: 1/2^k
ostime_t globalDutyAvail; // time device can send again u4_t netid; // current network id (~0 - none)
u2_t opmode;
u1_t upRepeat; // configured up repeat
s1_t adrTxPow; // ADR adjusted TX power
u1_t datarate; // current data rate
u1_t errcr; // error coding rate (used for TX only)
u1_t rejoinCnt; // adjustment for rejoin datarate
s2_t drift; // last measured drift
s2_t lastDriftDiff;
s2_t maxDriftDiff; u1_t pendTxPort;
u1_t pendTxConf; // confirmed data
u1_t pendTxLen; // +0x80 = confirmed
u1_t pendTxData[MAX_LEN_PAYLOAD]; u2_t devNonce; // last generated nonce
u1_t nwkKey[16]; // network session key
u1_t artKey[16]; // application router session key
devaddr_t devaddr;
u4_t seqnoDn; // device level down stream seqno
u4_t seqnoUp; u1_t dnConf; // dn frame confirm pending: LORA::FCT_ACK or 0
s1_t adrAckReq; // counter until we reset data rate (0=off)
u1_t adrChanged; u1_t margin;
bit_t ladrAns; // link adr adapt answer pending
bit_t devsAns; // device status answer pending
u1_t adrEnabled;
u1_t moreData; // NWK has more data pending
bit_t dutyCapAns; // have to ACK duty cycle settings
u1_t snchAns; // answer set new channel
// 2nd RX window (after up stream)
u1_t dn2Dr;
u4_t dn2Freq;
u1_t dn2Ans; // 0=no answer pend, 0x80+ACKs // Class B state
u1_t missedBcns; // unable to track last N beacons
u1_t bcninfoTries; // how often to try (scan mode only)
u1_t pingSetAns; // answer set cmd and ACK bits
rxsched_t ping; // pingable setup // Public part of MAC state
u1_t txCnt;
u1_t txrxFlags; // transaction flags (TX-RX combo)
u1_t dataBeg; // 0 or start of data (dataBeg-1 is port)
u1_t dataLen; // 0 no data or zero length data, >0 byte count of data
u1_t frame[MAX_LEN_FRAME]; u1_t bcnChnl;
u1_t bcnRxsyms; //
ostime_t bcnRxtime;
bcninfo_t bcninfo; // Last received beacon info
};
//! \var struct lmic_t LMIC
//! The state of LMIC MAC layer is encapsulated in this variable.
DECLARE_LMIC; //!< \internal

1.1 lmic_t.rxState

// purpose of receive window - lmic_t.rxState
enum { RADIO_RST=0, RADIO_TX=1, RADIO_RX=2, RADIO_RXON=3 };
void os_radio (u1_t mode) {
hal_disableIRQs();
switch (mode) {
case RADIO_RST:
opmode(OPMODE_SLEEP); // put radio to sleep
break;
case RADIO_TX: // transmit frame now
starttx(); // buf=LMIC.frame, len=LMIC.dataLen
break;
case RADIO_RX: // receive frame now (exactly at rxtime)
startrx(RXMODE_SINGLE); // buf=LMIC.frame, time=LMIC.rxtime, timeout=LMIC.rxsyms
break;
case RADIO_RXON:// start scanning for beacon now
startrx(RXMODE_SCAN); // buf=LMIC.frame
break;
}
hal_enableIRQs();
}

1.2 lmic_t.netid

// Netid values /  lmic_t.netid
enum { NETID_NONE=(int)~0U, NETID_MASK=(int)0xFFFFFF };

1.3 LMIC.txrxFlags字段定义

// TX-RX transaction flags - report back to user
enum { TXRX_ACK = 0x80, // confirmed UP frame was acked
TXRX_NACK = 0x40, // confirmed UP frame was not acked
TXRX_NOPORT = 0x20, // set if a frame with a port was RXed, clr if no frame/no port
TXRX_PORT = 0x10, // set if a frame with a port was RXed, LMIC.frame[LMIC.dataBeg-1] => port
TXRX_DNW1 = 0x01, // received in 1st DN slot
TXRX_DNW2 = 0x02, // received in 2dn DN slot
TXRX_PING = 0x04 }; // received in a scheduled RX slot

对于EV_RXCOMPLETEEV_TXCOMPLETE事件,txrxFlags字段定义了以下标志:

TXRX_ACK :上行确认帧被确认(与TXRX_NACK互斥)

TXRX_NACK:上行确认帧未被确认(与TXRX_ACK互斥)

TXRX_PORT:端口字段包含在接收帧中

TXRX_DNW1:在第一个下行接收窗口中接收(与TXRX_DNW2互斥)

TXRX_DNW2:在第二个下行接收窗口中接收(与TXRX_DNW1互斥)

TXRX_PING:在预定的RX Slot中接收(Beacon帧)

1.4 LMIC.txrxFlags LMIC.dataBeg LMIC.dataLen字段值

对于EV_TXCOMPLETE事件,这些字段具有以下值:



对于EV_RXCOMPLETE事件,这些字段具有以下值:

1.5 lmic_t.opmode

// MAC operation modes (lmic_t.opmode).

enum { OP_NONE     = 0x0000,
OP_SCAN = 0x0001, // radio scan to find a beacon
OP_TRACK = 0x0002, // track my networks beacon (netid)
OP_JOINING = 0x0004, // device joining in progress (blocks other activities)
OP_TXDATA = 0x0008, // TX user data (buffered in pendTxData)
OP_POLL = 0x0010, // send empty UP frame to ACK confirmed DN/fetch more DN data
OP_REJOIN = 0x0020, // occasionally send JOIN REQUEST
OP_SHUTDOWN = 0x0040, // prevent MAC from doing anything
OP_TXRXPEND = 0x0080, // TX/RX transaction pending
OP_RNDTX = 0x0100, // prevent TX lining up after a beacon
OP_PINGINI = 0x0200, // pingable is initialized and scheduling active
OP_PINGABLE = 0x0400, // we're pingable
OP_NEXTCHNL = 0x0800, // find a new channel
OP_LINKDEAD = 0x1000, // link was reported as dead
OP_TESTMODE = 0x2000, // developer test mode
};

1.6 LMIC.rps的值:包括SF、BW、CR、IH、NOCRC值

// Radio parameter set (encodes SF/BW/CR/IH/NOCRC)
typedef u2_t rps_t;
inline rps_t makeRps (sf_t sf, bw_t bw, cr_t cr, int ih, int nocrc) {
return sf | (bw<<3) | (cr<<5) | (nocrc?(1<<7):0) | ((ih&0xFF)<<8);
}

2.API functions

LMiC库提供一组API函数来控制MAC状态并触发协议动作。

事件回调函数的事件类型由enum定义

// Event types for event callback
enum _ev_t { EV_SCAN_TIMEOUT=1, EV_BEACON_FOUND,
EV_BEACON_MISSED, EV_BEACON_TRACKED, EV_JOINING,
EV_JOINED, EV_RFU1, EV_JOIN_FAILED, EV_REJOIN_FAILED,
EV_TXCOMPLETE, EV_LOST_TSYNC, EV_RESET,
EV_RXCOMPLETE, EV_LINK_DEAD, EV_LINK_ALIVE };

2.1 void LMIC_reset()

重置MAC状态。会话和挂起的数据传输将被丢弃。

2.2 bit_t LMIC_startJoining()

立即开始加入网络。如果没有会话,将被其他API函数隐含地调用已经建立了将生成事件EV_JOININGEV_JOINEDEV_JOIN_FAILED

2.3 void LMIC_tryRejoin()

检查是否可以连接其他网络。假如没有找到新的网络当前网络的会话将保留。将生成EV_JOINEDEV_REJOIN_FAILED事件。

2.4 void LMIC_setSession(u4_t netid,devaddr_t devaddr,u1_t * nwkKey,u1_t * artKey)

设置静态会话参数。替代通过加入网络动态建立会话,可以提供预计算的会话参数。恢复预先计算的会话参数,帧序列计数器(LMIC.seqnoUpLMIC.seqnoDn)必须恢复为他们的最新值。

2.5 bit_t LMIC_setupBand(u1_t bandidx,s1_t txpow,u2_t txcap)

创建具有指定发射功率和占空比(1 / txcap)属性的新频段。

2.6 bit_t LMIC_setupChannel(u1_t channel,u4_t freq,u2_t drmap,s1_t band)

使用指定的频率创建给定频段的新信道,并允许数据速率在数据速率位掩码(1 << DRx)中定义。

2.7 void LMIC_disableChannel(u1_t channel)

禁用指定的信道。

2.8 void LMIC_setAdrMode(bit_t enabled)

启用/禁用数据速率适配。如果是移动设备应该关闭。

2.9 void LMIC_setLinkCheckMode(bit_tenabled)

启用/禁用链接检查验证。默认情况下启用链路检查模式,并定期使用验证网络连接。仅当会话建立时才必须调用。

2.10 void LMIC_setDrTxpow(dr_t dr,s1_t txpow)

设置数据速率和传输功率。只有在禁用数据速率调整时才应使用。

2.11 void LMIC_setTxData()

在下一个可能的时间准备上行数据传输。假设pendTxDatapendTxLenpendTxPortpendTxConf已经设置好了。数据长度为LMIC.pendTxLen,数组LMIC.pendTxData[]中的数据将被发送到LMIC.pendTxPort端口。如果LMIC.pendTxConf使能,服务器将回复确认帧。当通信完成后将生成EV_TXCOMPLETE事件,即数据发送完成并且收到最终下行数据或已收到确认帧。

2.12 int LMIC_setTxData2(u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed)

在下一个可能的时间准备上行数据传输,方便功能LMIC_setTxData()。如果数据为NULL,则将使用LMIC.pendTxData []中的数据。

2.13 void LMIC_clrTxData()

删除之前为上行传输准备的数据。

2.14 bit_t LMIC_enableTracking(u1_t tryBcnInfo)

启用信标(beacon帧)跟踪。对于LMIC.bcninfoTries=tryBcnInfo的值为0表示开始立即扫描beacon帧;非零值指定试图查询服务器准确beacon帧到达时间的次数。查询请求将在下一个上行帧内发送(不会另外生成帧)。如果没有应答接收扫描将开始。第一个beacon帧将生成EV_BEACON_FOUNDEV_SCAN_TIMEOUT事件,随后的beacon帧将生成EV_BEACON_TRACKEDEV_BEACON_MISSEDEV_LOST_TSYNC事件。

2.15 void LMIC_disableTracking()

禁用beacon帧跟踪。beacon帧将不再被跟踪,因此也将禁用ping

2.16 void LMIC_setPingable(u1_t intvExp)

启用ping和设置下行监听间隔。 Ping将在下一个上行帧启用(不会生成新帧)。监听间隔为2 ^ intvExp秒,intvExp(LMIC.ping.intvExp)的有效值是0-7。此API函数需要通过网络服务器建立的有效会话LMIC_startJoining()或LMIC_setSession()函数(见2.2和2.4节)。如果beacon帧跟踪尚未启用,扫描将立即开始。为了避免扫描,通过使用前一次调用非零参数的LMIC_enableTracking()可以更有效地定位beacon帧。除了LMIC_enableTracking()提到的事件之外,每当在ping slot(ping时槽)中接收到下行数据时将生成EV_RXCOMPLETE事件。

2.17 void LMIC_stopPingable()

停止监听下行数据。定期侦听被禁用,但beacon仍将被追踪。为了停止beacon跟踪,beacon需要调用LMIC_disableTracking()。

2.18 void LMIC_sendAlive()

尽快发送一个空的上行MAC帧。可能被用来表示信号活性或者要传输等待中的MAC选项,并打开接收窗口。

2.19 void LMIC_shutdown()

停止所有MAC活动。随后,MAC需要通过调用LMIC_reset();如果有新的协议动作则需要重新发起。

2.20 void LMIC_init()

void LMIC_init (void) {
LMIC.opmode = OP_SHUTDOWN;
}

(2)LoraWAN:Lora LMIC library 编程模型及API的更多相关文章

  1. 学习笔记TF048:TensorFlow 系统架构、设计理念、编程模型、API、作用域、批标准化、神经元函数优化

    系统架构.自底向上,设备层.网络层.数据操作层.图计算层.API层.应用层.核心层,设备层.网络层.数据操作层.图计算层.最下层是网络通信层和设备管理层.网络通信层包括gRPC(google Remo ...

  2. Spark入门实战系列--3.Spark编程模型(下)--IDEA搭建及实战

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 . 安装IntelliJ IDEA IDEA 全称 IntelliJ IDEA,是java语 ...

  3. 【温故知新】c#异步编程模型(APM)--使用委托进行异步编程

    当我们用到C#类许多耗时的函数XXX时,总会存在同名的类似BeginXXX,EndXXX这样的函数. 例如Stream抽象类的Read函数就有 public abstract int Read(byt ...

  4. C#异步编程の-------异步编程模型(APM)

    术语解释: APM               异步编程模型, Asynchronous Programming Model EAP                基于事件的异步编程模式, Event ...

  5. JS魔法堂:深究JS异步编程模型

    前言  上周5在公司作了关于JS异步编程模型的技术分享,可能是内容太干的缘故吧,最后从大家的表情看出"这条粉肠到底在说啥?"的结果:(下面是PPT的讲义,具体的PPT和示例代码在h ...

  6. 多线程之异步编程: 经典和最新的异步编程模型,async与await

    经典的异步编程模型(IAsyncResult) 最新的异步编程模型(async 和 await) 将 IAsyncInfo 转换成 Task 将 Task 转换成 IAsyncInfo 示例1.使用经 ...

  7. 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换

    经典的异步编程模型(IAsyncResult) 最新的异步编程模型(async 和 await) 将 IAsyncInfo 转换成 Task 将 Task 转换成 IAsyncInfo 示例1.使用经 ...

  8. jQuery插件编写及链式编程模型小结

    JQuery极大的提高了我们编写JavaScript的效率,让我们可以愉快的编写代码,做出各种特效.大多数情况下,我们都是使用别人开发的JQuery插件,今天我们就来看看如何把我们常用的功能做出JQu ...

  9. 云巴:基于MQTT协议的实时通信编程模型

    概要 有人常问,云巴实时通信系统到底提供了一种怎样的服务,与其他提供推送或 IM 服务的厂商有何本质区别.其实,从技术角度分析,云巴与其它同类厂商都是面向开发者的通信服务,宏观的编程模型都是大同小异, ...

随机推荐

  1. Django框架中的Cookie和Session

    学习内容: (1)cookie (2)session Web是基于请求/响应模式,HTTP协议是无状态的,但是基于 Internet的各种服务系统应运而生,建立商业站点或者功能比较完善的个人站点,常常 ...

  2. 吴裕雄 python 神经网络——TensorFlow ckpt文件保存方法

    import tensorflow as tf v1 = tf.Variable(tf.random_normal([1], stddev=1, seed=1)) v2 = tf.Variable(t ...

  3. Codeforces Round #620 (Div. 2) A. Two Rabbits

    Being tired of participating in too many Codeforces rounds, Gildong decided to take some rest in a p ...

  4. python爬虫(八) requests库之 get请求

    requests库比urllib库更加方便,包含了很多功能. 1.在使用之前需要先安装pip,在pycharm中打开: 写入pip install requests命令,即可下载 在github中有关 ...

  5. iOS ViewController 中代码书写规范

    示例: // // CommonViewController.m // ZTBCamera // // Created by ZachRobin on 2017/8/3. // Copyright © ...

  6. i.MX RT600之I2S外设介绍及应用

    恩智浦的i.MX RT600是跨界处理器产品,同样也是i.MX RTxxx系列的开山之作.不同于i.MX RT1xxx系列单片机,i.MX RT600 采用了双核架构,将新一代Cortex-M33内核 ...

  7. 解决xpath中文乱码

    利用xpath建标签树以后,虽然提高了元素匹配效率,但是etree会把中文转为ASCII码,所以简单地tostring以后会有乱码. 解决方法: import requests from reques ...

  8. jackson处理日期异常

    原 jackson处理日期异常 2018年01月09日 10:50:19 阅读数:70 1.异常信息 2.原因 默认情况下,fasterxml json只支持几种format,但是肯定不支持" ...

  9. 附:Struts2-CRM,拦截器实现权限访问

    拦截器代码: package mycrm.interceptor; import org.apache.struts2.ServletActionContext; import com.opensym ...

  10. Spring学习(一)

    搭建环境 1.创建普通的Java工程 2.添加相应的jar包,下载链接:https://files.cnblogs.com/files/AmyZheng/lib.rar,此外,为了打印信息,我们还需要 ...