fota lib for mdot

Dependents:   UQ_LoraWAN

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Mac.h Source File

Mac.h

00001 /**   __  ___     ____  _    ______        __     ____         __                  ____
00002  *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
00003  *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/  __
00004  * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/  /_/
00005  * Copyright (C) 2015 by Multi-Tech Systems        /___/
00006  *
00007  *
00008  * @author Jason Reiss
00009  * @date   10-31-2015
00010  * @brief  lora::Mac implements the Mac layer providing mote addressing and packet encryption
00011  *
00012  * @details
00013  *
00014  */
00015 
00016 #ifndef __LORA_MAC_H__
00017 #define __LORA_MAC_H__
00018 
00019 #include "Lora.h"
00020 #include "ChannelPlan.h"
00021 #include "SxRadio.h"
00022 #include "SxRadio1272.h"
00023 #include "SxRadioEvents.h"
00024 #include "MacEvents.h"
00025 #include "Crypto.h"
00026 #include "Link.h"
00027 
00028 namespace lora {
00029 
00030     class Mac: public SxRadioEvents, public Crypto {
00031         public:
00032 
00033             virtual ~Mac();
00034 
00035             Mac(SxRadio& radio, MacEvents* events, ChannelPlan* plan, Settings& settings);
00036 
00037             /**
00038              * Send a Join Request packet
00039              * @param devEUI
00040              * @param appEUI
00041              * @param appKey
00042              * @return LORA_OK if successful
00043              * @return LORA_LINK_BUSY
00044              * @return LORA_RADIO_BUSY
00045              */
00046             uint8_t Join(const uint8_t* devEUI, const uint8_t* appEUI, const uint8_t* appKey);
00047 
00048             /**
00049              * Send a packet
00050              * @param port app port to send with payload
00051              * @param payload data to send
00052              * @param size of payload
00053              * @param attempts number of attempts to receive an ACK
00054              * @param repeats number of times to repeat packet
00055              * @return LORA_OK if successful
00056              * @return LORA_MAX_PAYLOAD_EXCEEDED if payload size exceeds datarate maximum
00057              * @return LORA_NO_CHANS_ENABLED if there is not an available channel that supports the current datarate
00058              * @return LORA_LINK_BUSY if link was busy
00059              * @return LORA_RADIO_BUSY if radio was busy
00060              * @return LORA_BUFFER_FULL if mac commands filled the packet, client should resend the packet
00061              */
00062             uint8_t Send(uint8_t port, const uint8_t* payload, uint16_t size, uint8_t attempts = 0, uint8_t repeats = 0);
00063 
00064             /**
00065              * Prepare frame to be sent over link
00066              * @param port to send data to
00067              * @param payload to send
00068              * @param size of payload
00069              * @param attempts 0:Unconfirmed, 1-8:Confirmed
00070              * @return LORA_OK
00071              */
00072             uint8_t PrepareFrame(uint8_t port, const uint8_t* payload, uint8_t size, uint8_t attempts);
00073 
00074             /**
00075              * Reset the mac commands buffer
00076              */
00077             void ResetMacCommands();
00078 
00079             /**
00080              * Add a mac command to be sent with next packet
00081              * @param cmd id of command
00082              * @param pc number of parameters
00083              * @param pv array of parameters
00084              * @return LORA_OK if successful
00085              * @return LORA_COMMAND_BUFFER_FULL
00086              * @return LORA_UNKNOWN_MAC_COMMAND
00087              */
00088             uint8_t AddMacCommand(uint8_t cmd, uint8_t pc, uint8_t* pv);
00089 
00090             /**
00091              * Handle mac command received from server
00092              * @param payload received on radio
00093              * @param index of mac command id
00094              * @param size of mac command list
00095              */
00096             uint8_t HandleMacCommands(uint8_t* payload, uint8_t index, uint8_t size);
00097 
00098             /**
00099              * Handle Join Accept packet
00100              * @param payload received
00101              * @param size of payload
00102              * @return LORA_OK if successful
00103              * @return LORA_JOIN_ERROR if already joined or MIC fails
00104              */
00105             uint8_t HandleJoinAccept(uint8_t* payload, uint8_t size);
00106 
00107             /**
00108              * Handle Packet receipt
00109              * Verifies Address and MIC, checks the Frame Control bits for ACK
00110              * Then decrypts the payload and handles any Mac Commands
00111              * @param payload received
00112              * @param size of payload
00113              * @param[out] port data was received on
00114              * @param[out] length of user data in payload
00115              */
00116             uint8_t HandleDownlinkPacket(uint8_t* payload, uint8_t size, uint8_t& port, uint8_t& length);
00117 
00118             /**
00119              * Check for ACK from server in received packet and notifies Link if present
00120              * @param fCtrl frame control byte of packet
00121              * @return LORA_OK
00122              */
00123             uint8_t CheckFrameControl(DownlinkControl fCtrl);
00124 
00125             /**
00126              * Verify that packet address is intended for mote or in list of multicast addresses
00127              * @param payload received
00128              * @param size of payload
00129              * @param[out] address found in header of packet
00130              * @param[out] networkSessionKey associated with address
00131              * @param[out] dataSessionKey associated with address
00132              * @return LORA_OK if successful
00133              * @return LORA_ADDRESS_ERROR if address is not found
00134              */
00135             uint8_t VerifyAddress(uint8_t* payload, uint8_t size, uint32_t& address, uint8_t* networkSessionKey, uint8_t* dataSessionKey);
00136 
00137             /**
00138              * Verify that MIC can be computed with network session key
00139              * Frame counter is checked for reset and rollover
00140              * @param payload received
00141              * @param size of payload
00142              * @param address found in header of packet
00143              * @param networkSessionKey
00144              * @return LORA_OK if successful
00145              * @return LORA_MIC_ERROR
00146              */
00147             uint8_t VerifyMIC(uint8_t* payload, uint8_t size, uint32_t address, uint8_t* networkSessionKey);
00148 
00149             /**
00150              * Event called by Link on start of any tx
00151              */
00152             virtual void TxStart(void);
00153 
00154             /**
00155              * Event called by Link on tx done
00156              */
00157             virtual void TxDone(void);
00158 
00159             /**
00160              * Event called by Link on tx timeout
00161              */
00162             virtual void TxTimeout(void);
00163 
00164             /**
00165              * Event called by Link on rx done
00166              * @param payload of received packet
00167              * @param size of received packet in bytes
00168              * @param rssi of received packet in dBm
00169              * @param snr of received packet two's complement in 1/4 dB
00170              */
00171             virtual void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
00172 
00173             /**
00174              * Event called by Link on rx timeout
00175              */
00176             virtual void RxTimeout(void);
00177 
00178             /**
00179              * Event called by Link on rx error
00180              */
00181             virtual void RxError(void);
00182 
00183             virtual void LinkIdle(void);
00184 
00185             /**
00186              * Current join status
00187              * @return true if joined to lora network
00188              * @return false if not joined
00189              */
00190             bool IsJoined();
00191 
00192             /**
00193              * Set the dev nonce
00194              * The dev nonce is used for deriving session keys and part of the data send on a join request
00195              */
00196             void SetDeviceNonce(uint16_t nonce);
00197 
00198             /**
00199              * Get the dev nonce
00200              * The dev nonce is used for deriving session keys and part of the data send on a join request
00201              */
00202             uint16_t GetDeviceNonce();
00203 
00204             void SetLoraClass(MoteClass cls);
00205 
00206             /**
00207              * Get the current device MoteClass
00208              */
00209             MoteClass GetLoraClass();
00210 
00211             /**
00212              * Get the SNR of the last received packet
00213              * @returns snr in dB
00214              */
00215             int8_t GetSNR();
00216 
00217             /**
00218              * Get the RSSI of the last received packet
00219              * @returns rssi in dB
00220              */
00221             int16_t GetRSSI();
00222 
00223             /**
00224              * Update the statistics with the last received RSSI and SNR
00225              * The avg, min and max RSSI and SNR will also be updated
00226              */
00227             void UpdateStats(int16_t rssi, int16_t snr);
00228 
00229             /**
00230              * Get the number of mac command bytes ready to be sent in the next packet
00231              * @return size of buffer in bytes
00232              */
00233             uint8_t GetMacCommandBufferSize();
00234 
00235             /**
00236              * Get the buffer for mac command bytes ready to be sent in the next packet
00237              * @return pointer to command buffer
00238              */
00239             const uint8_t* GetMacCommandBuffer();
00240 
00241             /**
00242              * Clear the buffer for mac command bytes to be sent in the next packet
00243              */
00244             void ClearMacCommandBuffer();
00245 
00246             /**
00247              * Get the size of the bytes ready to be sent in the next packet
00248              * @returns size of buffer in bytes
00249              */
00250             uint8_t GetTxBufferSize();
00251 
00252             /**
00253              * Get the buffer of bytes  ready to be sent in the next packet
00254              * @return pointer to buffer
00255              */
00256             const uint8_t* GetTxBuffer();
00257 
00258             /**
00259              * Get the max duty cycle currently set for device
00260              * Aggregated duty cycle = 1 / 2 ^ MaxDutyCycle
00261              * Value of 255 should silence device
00262              * @return duty cycle 0-15 or 255
00263              */
00264             uint8_t GetMaxDutyCycle();
00265 
00266             /**
00267              * Get the Rx delay value currently used by the Link
00268              * @return rxDelay in seconds
00269              */
00270             uint8_t GetRxDelay();
00271 
00272             /**
00273              * Get the MCU sleep time between tx done and the Rx1 window opening
00274              * @return Time MCU sleeps between tx done and rx1 open in milliseconds
00275              */
00276             uint32_t GetRx1SleepTime();
00277 
00278             /**
00279              * Get the MCU sleep time between Rx1 window opening and the Rx2 window opening
00280              * @return Time MCU sleeps between rx1 open and rx2 open in milliseconds
00281              */
00282             uint32_t GetRx2SleepTime();
00283 
00284             /**
00285              * Get pong received indicator
00286              * @return true if pong was received
00287              */
00288             bool GetPongReceived();
00289 
00290             /**
00291              * Get the RSSI of the last received pong
00292              * The RSSI will be the strength of the signal received at the gateway
00293              * @return rssi in dB
00294              */
00295             int16_t GetPongRssi();
00296 
00297             /**
00298              * Get the SNR of the last received pong
00299              * The SNR will be the strength of the signal received at the gateway
00300              * @return snr in dB
00301              */
00302             int16_t GetPongSnr();
00303 
00304             /**
00305              * Get the current statistics for the device
00306              * @return Statistics
00307              */
00308             Statistics& GetStats();
00309 
00310             /**
00311              * Reset the current statistics for the device
00312              */
00313             void ResetStats();
00314 
00315             /**
00316              * Set the current channel plan
00317              */
00318             void SetChannelPlan(ChannelPlan* plan);
00319 
00320             /**
00321              * Set the delay for Rx1 window
00322              * @param sec time to delay after end of tx, minimum 1 second
00323              */
00324             uint8_t SetRxDelay(uint8_t sec);
00325 
00326             /**
00327              * Set the MCU sleep time between tx done and the Rx1 window opening
00328              * @param ms time MCU sleeps between tx done and rx1 open
00329              */
00330             void SetRx1SleepTime(uint32_t ms);
00331 
00332             /**
00333              * Set the MCU sleep time between Rx1 window opening and the Rx2 window opening
00334              * @param ms time MCU sleeps between rx1 open and rx2 open
00335              */
00336             void SetRx2SleepTime(uint32_t ms);
00337 
00338             /**
00339              * Set the network mode
00340              * @param mode PRIVATE, PUBLIC or PEER_TO_PEER
00341              */
00342             uint8_t SetNetworkMode(uint8_t mode);
00343 
00344             /**
00345              * Get the current state of the MAC layer
00346              * @return MAC_IDLE, MAC_TX, MAC_RX
00347              */
00348             MacState GetState();
00349 
00350             /**
00351              * Get the time off air for the current datarate
00352              * @return time off air before next TX in ms
00353              */
00354             uint32_t GetTimeOffAir();
00355 
00356             /**
00357              * Open an RX Window
00358              * @param timeout time in ms to hold window open, 0 for continuous
00359              * @param freq frequency to listen on
00360              * @param datarate to listen for
00361              * @return LORA_OK
00362              */
00363             uint8_t OpenRxWindow(uint32_t timeout, uint32_t freq, uint8_t datarate);
00364             uint8_t OpenRxWindow(uint32_t timeout, bool continuous);
00365 
00366             /**
00367              * Close the open window
00368              * @return LORA_OK
00369              */
00370             uint8_t CloseRxWindow();
00371 
00372             /**
00373              * Cancel pending rx windows
00374              * @return LORA_OK
00375              */
00376             uint8_t CancelRxWindows();
00377 
00378             /**
00379              * Get datarate properties of given index for current channel plan
00380              * @param index of datarate
00381              */
00382             Datarate GetDatarate(uint8_t index);
00383 
00384             /**
00385              * Get the max payload size available of current datarate for channel plan
00386              * @return bytes that can be sent
00387              */
00388             uint8_t GetMaxPayloadSize();
00389 
00390             /**
00391              * Call to wakeup mac layer
00392              */
00393             void Wakeup();
00394 
00395             /**
00396              * Set the event object to report to
00397              * @param events object inheriting from MacEvents
00398              */
00399             void SetEventHandler(MacEvents* events);
00400 
00401             /**
00402              * Get the channels in use by current channel plan
00403              * @return channel frequencies
00404              */
00405             std::vector<uint32_t> GetChannels();
00406 
00407             /**
00408              * Get the downlink channels in use by current channel plan
00409              * @return channel frequencies
00410              */
00411             std::vector<uint32_t> GetDownlinkChannels();
00412 
00413             /**
00414              * Get the channel datarate ranges in use by current channel plan
00415              * @return channel datarate ranges
00416              */
00417             std::vector<uint8_t> GetChannelRanges();
00418 
00419             /**
00420              * Enable the default channels of the channel plan
00421              */
00422             void EnableDefaultChannels();
00423 
00424             /**
00425              * Get the number of duty bands in the current channel plan
00426              * @return number of bands
00427              */
00428             uint8_t GetNumDutyBands();
00429 
00430             /**
00431              * Get the time off air for the given duty band
00432              * @param band index
00433              * @return time off air in ms
00434              */
00435             uint32_t GetDutyBandTimeOff(uint8_t band);
00436 
00437             /**
00438              * Set the time off air for the given duty band
00439              * @param band index
00440              * @param time off air in ms
00441              */
00442             void SetDutyBandTimeOff(uint8_t band, uint32_t timeoff);
00443 
00444             /**
00445              * Reset internal mac state if timeout or unforeseen error occurs
00446              */
00447             void ResetState();
00448 
00449             /**
00450              * Enable TX CW
00451              * return LORA_OK
00452              */
00453             uint8_t SendContinuous(bool enable);
00454 
00455         private:
00456             /**
00457              * Helper for clearing MAC commands which can be cleared upon successful uplink
00458              */
00459             void PostTxMacPrune();
00460 
00461             Link _link;                                 //!< Link used to manage radio
00462             ChannelPlan* _plan;                         //!< Injected ChannelPlan used by Link to define parameters for tx/rx of packets
00463             SxRadio& _radio;                            //!< Injected SxRadio object
00464             MacEvents* _events;                         //!< Injected MaxEvents object for event notification to client
00465             Settings& _settings;                        //!< Settings used to configure the Mac
00466 
00467             bool _isMulticastPacket;                    //!< Indicator of multicast packet recieved
00468             uint8_t _multicastIndex;                    //!< Index of multicast session associated with last received packet
00469 
00470             uint8_t _rxBuffer[MAX_PHY_PACKET_SIZE];     //!< Buffer of last packet received
00471             uint8_t _rxBufferSize;                      //!< Size of the last packet received
00472             uint8_t _txBuffer[MAX_PHY_PACKET_SIZE];     //!< Buffer of packet to send
00473             uint8_t _txBufferSize;                      //!< Size of buffer to send
00474             bool _txBufferFull;                         //!< Indicates that buffer was filled with mac commands
00475 
00476             uint16_t _joinNonce;                        //!< Random nonce value used for Join Request and to derive session keys
00477 
00478             int16_t _rssi;                              //!< RSSI value of last received packet in dB
00479             int16_t _snr;                               //!< SNR value of last received packet in cB
00480 
00481             bool _pongReceived;                         //!< Indicator of pong received
00482             int16_t _pongRssi;                          //!< RSSI value of last received pong
00483             int16_t _pongSnr;                           //!< SNR value of last received pong
00484 
00485             MacState _state;                            //!< Current mac state
00486 
00487             uint32_t _downlinkCounter;                  //!< Temporary downlink counter
00488             bool _duplicateReceived;                    //!< Indication of duplicate packet received due to missed ack
00489 
00490             DownlinkControl _downlinkCtrl;              //!< Downlink ctrl status of last rx packet
00491     };
00492 
00493 }
00494 
00495 #endif // __LORA_MAC_H__