(2)LoraWAN:Lora LMIC library 編程模型及API

2、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中,以供外部使用。api

#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事件,這些字段具備如下值:
image
對於EV_RXCOMPLETE事件,這些字段具備如下值:
image服務器

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值

image

// 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定義session

// 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_FAILEDapp

2.3 void LMIC_tryRejoin()

檢查是否能夠鏈接其餘網絡。假如沒有找到新的網絡當前網絡的會話將保留。將生成EV_JOINEDEV_REJOIN_FAILED事件。dom

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;
}
相關文章
相關標籤/搜索