fota lib for mdot
Diff: mdot/Lora/Mac.h
- 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__