fota lib for mdot

Dependents:   UQ_LoraWAN

Revision:
3:63d10f2375ea
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Mac.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,495 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/  __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/  /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora::Mac implements the Mac layer providing mote addressing and packet encryption
+ *
+ * @details
+ *
+ */
+
+#ifndef __LORA_MAC_H__
+#define __LORA_MAC_H__
+
+#include "Lora.h"
+#include "ChannelPlan.h"
+#include "SxRadio.h"
+#include "SxRadio1272.h"
+#include "SxRadioEvents.h"
+#include "MacEvents.h"
+#include "Crypto.h"
+#include "Link.h"
+
+namespace lora {
+
+    class Mac: public SxRadioEvents, public Crypto {
+        public:
+
+            virtual ~Mac();
+
+            Mac(SxRadio& radio, MacEvents* events, ChannelPlan* plan, Settings& settings);
+
+            /**
+             * Send a Join Request packet
+             * @param devEUI
+             * @param appEUI
+             * @param appKey
+             * @return LORA_OK if successful
+             * @return LORA_LINK_BUSY
+             * @return LORA_RADIO_BUSY
+             */
+            uint8_t Join(const uint8_t* devEUI, const uint8_t* appEUI, const uint8_t* appKey);
+
+            /**
+             * Send a packet
+             * @param port app port to send with payload
+             * @param payload data to send
+             * @param size of payload
+             * @param attempts number of attempts to receive an ACK
+             * @param repeats number of times to repeat packet
+             * @return LORA_OK if successful
+             * @return LORA_MAX_PAYLOAD_EXCEEDED if payload size exceeds datarate maximum
+             * @return LORA_NO_CHANS_ENABLED if there is not an available channel that supports the current datarate
+             * @return LORA_LINK_BUSY if link was busy
+             * @return LORA_RADIO_BUSY if radio was busy
+             * @return LORA_BUFFER_FULL if mac commands filled the packet, client should resend the packet
+             */
+            uint8_t Send(uint8_t port, const uint8_t* payload, uint16_t size, uint8_t attempts = 0, uint8_t repeats = 0);
+
+            /**
+             * Prepare frame to be sent over link
+             * @param port to send data to
+             * @param payload to send
+             * @param size of payload
+             * @param attempts 0:Unconfirmed, 1-8:Confirmed
+             * @return LORA_OK
+             */
+            uint8_t PrepareFrame(uint8_t port, const uint8_t* payload, uint8_t size, uint8_t attempts);
+
+            /**
+             * Reset the mac commands buffer
+             */
+            void ResetMacCommands();
+
+            /**
+             * Add a mac command to be sent with next packet
+             * @param cmd id of command
+             * @param pc number of parameters
+             * @param pv array of parameters
+             * @return LORA_OK if successful
+             * @return LORA_COMMAND_BUFFER_FULL
+             * @return LORA_UNKNOWN_MAC_COMMAND
+             */
+            uint8_t AddMacCommand(uint8_t cmd, uint8_t pc, uint8_t* pv);
+
+            /**
+             * Handle mac command received from server
+             * @param payload received on radio
+             * @param index of mac command id
+             * @param size of mac command list
+             */
+            uint8_t HandleMacCommands(uint8_t* payload, uint8_t index, uint8_t size);
+
+            /**
+             * Handle Join Accept packet
+             * @param payload received
+             * @param size of payload
+             * @return LORA_OK if successful
+             * @return LORA_JOIN_ERROR if already joined or MIC fails
+             */
+            uint8_t HandleJoinAccept(uint8_t* payload, uint8_t size);
+
+            /**
+             * Handle Packet receipt
+             * Verifies Address and MIC, checks the Frame Control bits for ACK
+             * Then decrypts the payload and handles any Mac Commands
+             * @param payload received
+             * @param size of payload
+             * @param[out] port data was received on
+             * @param[out] length of user data in payload
+             */
+            uint8_t HandleDownlinkPacket(uint8_t* payload, uint8_t size, uint8_t& port, uint8_t& length);
+
+            /**
+             * Check for ACK from server in received packet and notifies Link if present
+             * @param fCtrl frame control byte of packet
+             * @return LORA_OK
+             */
+            uint8_t CheckFrameControl(DownlinkControl fCtrl);
+
+            /**
+             * Verify that packet address is intended for mote or in list of multicast addresses
+             * @param payload received
+             * @param size of payload
+             * @param[out] address found in header of packet
+             * @param[out] networkSessionKey associated with address
+             * @param[out] dataSessionKey associated with address
+             * @return LORA_OK if successful
+             * @return LORA_ADDRESS_ERROR if address is not found
+             */
+            uint8_t VerifyAddress(uint8_t* payload, uint8_t size, uint32_t& address, uint8_t* networkSessionKey, uint8_t* dataSessionKey);
+
+            /**
+             * Verify that MIC can be computed with network session key
+             * Frame counter is checked for reset and rollover
+             * @param payload received
+             * @param size of payload
+             * @param address found in header of packet
+             * @param networkSessionKey
+             * @return LORA_OK if successful
+             * @return LORA_MIC_ERROR
+             */
+            uint8_t VerifyMIC(uint8_t* payload, uint8_t size, uint32_t address, uint8_t* networkSessionKey);
+
+            /**
+             * Event called by Link on start of any tx
+             */
+            virtual void TxStart(void);
+
+            /**
+             * Event called by Link on tx done
+             */
+            virtual void TxDone(void);
+
+            /**
+             * Event called by Link on tx timeout
+             */
+            virtual void TxTimeout(void);
+
+            /**
+             * Event called by Link on rx done
+             * @param payload of received packet
+             * @param size of received packet in bytes
+             * @param rssi of received packet in dBm
+             * @param snr of received packet two's complement in 1/4 dB
+             */
+            virtual void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
+
+            /**
+             * Event called by Link on rx timeout
+             */
+            virtual void RxTimeout(void);
+
+            /**
+             * Event called by Link on rx error
+             */
+            virtual void RxError(void);
+
+            virtual void LinkIdle(void);
+
+            /**
+             * Current join status
+             * @return true if joined to lora network
+             * @return false if not joined
+             */
+            bool IsJoined();
+
+            /**
+             * Set the dev nonce
+             * The dev nonce is used for deriving session keys and part of the data send on a join request
+             */
+            void SetDeviceNonce(uint16_t nonce);
+
+            /**
+             * Get the dev nonce
+             * The dev nonce is used for deriving session keys and part of the data send on a join request
+             */
+            uint16_t GetDeviceNonce();
+
+            void SetLoraClass(MoteClass cls);
+
+            /**
+             * Get the current device MoteClass
+             */
+            MoteClass GetLoraClass();
+
+            /**
+             * Get the SNR of the last received packet
+             * @returns snr in dB
+             */
+            int8_t GetSNR();
+
+            /**
+             * Get the RSSI of the last received packet
+             * @returns rssi in dB
+             */
+            int16_t GetRSSI();
+
+            /**
+             * Update the statistics with the last received RSSI and SNR
+             * The avg, min and max RSSI and SNR will also be updated
+             */
+            void UpdateStats(int16_t rssi, int16_t snr);
+
+            /**
+             * Get the number of mac command bytes ready to be sent in the next packet
+             * @return size of buffer in bytes
+             */
+            uint8_t GetMacCommandBufferSize();
+
+            /**
+             * Get the buffer for mac command bytes ready to be sent in the next packet
+             * @return pointer to command buffer
+             */
+            const uint8_t* GetMacCommandBuffer();
+
+            /**
+             * Clear the buffer for mac command bytes to be sent in the next packet
+             */
+            void ClearMacCommandBuffer();
+
+            /**
+             * Get the size of the bytes ready to be sent in the next packet
+             * @returns size of buffer in bytes
+             */
+            uint8_t GetTxBufferSize();
+
+            /**
+             * Get the buffer of bytes  ready to be sent in the next packet
+             * @return pointer to buffer
+             */
+            const uint8_t* GetTxBuffer();
+
+            /**
+             * Get the max duty cycle currently set for device
+             * Aggregated duty cycle = 1 / 2 ^ MaxDutyCycle
+             * Value of 255 should silence device
+             * @return duty cycle 0-15 or 255
+             */
+            uint8_t GetMaxDutyCycle();
+
+            /**
+             * Get the Rx delay value currently used by the Link
+             * @return rxDelay in seconds
+             */
+            uint8_t GetRxDelay();
+
+            /**
+             * Get the MCU sleep time between tx done and the Rx1 window opening
+             * @return Time MCU sleeps between tx done and rx1 open in milliseconds
+             */
+            uint32_t GetRx1SleepTime();
+
+            /**
+             * Get the MCU sleep time between Rx1 window opening and the Rx2 window opening
+             * @return Time MCU sleeps between rx1 open and rx2 open in milliseconds
+             */
+            uint32_t GetRx2SleepTime();
+
+            /**
+             * Get pong received indicator
+             * @return true if pong was received
+             */
+            bool GetPongReceived();
+
+            /**
+             * Get the RSSI of the last received pong
+             * The RSSI will be the strength of the signal received at the gateway
+             * @return rssi in dB
+             */
+            int16_t GetPongRssi();
+
+            /**
+             * Get the SNR of the last received pong
+             * The SNR will be the strength of the signal received at the gateway
+             * @return snr in dB
+             */
+            int16_t GetPongSnr();
+
+            /**
+             * Get the current statistics for the device
+             * @return Statistics
+             */
+            Statistics& GetStats();
+
+            /**
+             * Reset the current statistics for the device
+             */
+            void ResetStats();
+
+            /**
+             * Set the current channel plan
+             */
+            void SetChannelPlan(ChannelPlan* plan);
+
+            /**
+             * Set the delay for Rx1 window
+             * @param sec time to delay after end of tx, minimum 1 second
+             */
+            uint8_t SetRxDelay(uint8_t sec);
+
+            /**
+             * Set the MCU sleep time between tx done and the Rx1 window opening
+             * @param ms time MCU sleeps between tx done and rx1 open
+             */
+            void SetRx1SleepTime(uint32_t ms);
+
+            /**
+             * Set the MCU sleep time between Rx1 window opening and the Rx2 window opening
+             * @param ms time MCU sleeps between rx1 open and rx2 open
+             */
+            void SetRx2SleepTime(uint32_t ms);
+
+            /**
+             * Set the network mode
+             * @param mode PRIVATE, PUBLIC or PEER_TO_PEER
+             */
+            uint8_t SetNetworkMode(uint8_t mode);
+
+            /**
+             * Get the current state of the MAC layer
+             * @return MAC_IDLE, MAC_TX, MAC_RX
+             */
+            MacState GetState();
+
+            /**
+             * Get the time off air for the current datarate
+             * @return time off air before next TX in ms
+             */
+            uint32_t GetTimeOffAir();
+
+            /**
+             * Open an RX Window
+             * @param timeout time in ms to hold window open, 0 for continuous
+             * @param freq frequency to listen on
+             * @param datarate to listen for
+             * @return LORA_OK
+             */
+            uint8_t OpenRxWindow(uint32_t timeout, uint32_t freq, uint8_t datarate);
+            uint8_t OpenRxWindow(uint32_t timeout, bool continuous);
+
+            /**
+             * Close the open window
+             * @return LORA_OK
+             */
+            uint8_t CloseRxWindow();
+
+            /**
+             * Cancel pending rx windows
+             * @return LORA_OK
+             */
+            uint8_t CancelRxWindows();
+
+            /**
+             * Get datarate properties of given index for current channel plan
+             * @param index of datarate
+             */
+            Datarate GetDatarate(uint8_t index);
+
+            /**
+             * Get the max payload size available of current datarate for channel plan
+             * @return bytes that can be sent
+             */
+            uint8_t GetMaxPayloadSize();
+
+            /**
+             * Call to wakeup mac layer
+             */
+            void Wakeup();
+
+            /**
+             * Set the event object to report to
+             * @param events object inheriting from MacEvents
+             */
+            void SetEventHandler(MacEvents* events);
+
+            /**
+             * Get the channels in use by current channel plan
+             * @return channel frequencies
+             */
+            std::vector<uint32_t> GetChannels();
+
+            /**
+             * Get the downlink channels in use by current channel plan
+             * @return channel frequencies
+             */
+            std::vector<uint32_t> GetDownlinkChannels();
+
+            /**
+             * Get the channel datarate ranges in use by current channel plan
+             * @return channel datarate ranges
+             */
+            std::vector<uint8_t> GetChannelRanges();
+
+            /**
+             * Enable the default channels of the channel plan
+             */
+            void EnableDefaultChannels();
+
+            /**
+             * Get the number of duty bands in the current channel plan
+             * @return number of bands
+             */
+            uint8_t GetNumDutyBands();
+
+            /**
+             * Get the time off air for the given duty band
+             * @param band index
+             * @return time off air in ms
+             */
+            uint32_t GetDutyBandTimeOff(uint8_t band);
+
+            /**
+             * Set the time off air for the given duty band
+             * @param band index
+             * @param time off air in ms
+             */
+            void SetDutyBandTimeOff(uint8_t band, uint32_t timeoff);
+
+            /**
+             * Reset internal mac state if timeout or unforeseen error occurs
+             */
+            void ResetState();
+
+            /**
+             * Enable TX CW
+             * return LORA_OK
+             */
+            uint8_t SendContinuous(bool enable);
+
+        private:
+            /**
+             * Helper for clearing MAC commands which can be cleared upon successful uplink
+             */
+            void PostTxMacPrune();
+
+            Link _link;                                 //!< Link used to manage radio
+            ChannelPlan* _plan;                         //!< Injected ChannelPlan used by Link to define parameters for tx/rx of packets
+            SxRadio& _radio;                            //!< Injected SxRadio object
+            MacEvents* _events;                         //!< Injected MaxEvents object for event notification to client
+            Settings& _settings;                        //!< Settings used to configure the Mac
+
+            bool _isMulticastPacket;                    //!< Indicator of multicast packet recieved
+            uint8_t _multicastIndex;                    //!< Index of multicast session associated with last received packet
+
+            uint8_t _rxBuffer[MAX_PHY_PACKET_SIZE];     //!< Buffer of last packet received
+            uint8_t _rxBufferSize;                      //!< Size of the last packet received
+            uint8_t _txBuffer[MAX_PHY_PACKET_SIZE];     //!< Buffer of packet to send
+            uint8_t _txBufferSize;                      //!< Size of buffer to send
+            bool _txBufferFull;                         //!< Indicates that buffer was filled with mac commands
+
+            uint16_t _joinNonce;                        //!< Random nonce value used for Join Request and to derive session keys
+
+            int16_t _rssi;                              //!< RSSI value of last received packet in dB
+            int16_t _snr;                               //!< SNR value of last received packet in cB
+
+            bool _pongReceived;                         //!< Indicator of pong received
+            int16_t _pongRssi;                          //!< RSSI value of last received pong
+            int16_t _pongSnr;                           //!< SNR value of last received pong
+
+            MacState _state;                            //!< Current mac state
+
+            uint32_t _downlinkCounter;                  //!< Temporary downlink counter
+            bool _duplicateReceived;                    //!< Indication of duplicate packet received due to missed ack
+
+            DownlinkControl _downlinkCtrl;              //!< Downlink ctrl status of last rx packet
+    };
+
+}
+
+#endif // __LORA_MAC_H__