required mdot library updated
Fork of libmDot-mbed5 by
Revision 16:b630e18103e5, committed 2016-08-04
- Comitter:
- Mike Fiore
- Date:
- Thu Aug 04 15:11:24 2016 -0500
- Parent:
- 15:ea598f178cce
- Child:
- 17:306ffaa5d79b
- Commit message:
- update from libmDot-2.0.1-ARMCC.tar.gz
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lora.h Thu Aug 04 15:11:24 2016 -0500 @@ -0,0 +1,707 @@ +/** __ ___ ____ _ ______ __ ____ __ ____ + * / |/ /_ __/ / /_(_)__/_ __/__ ____/ / / __/_ _____ / /____ __ _ ___ / _/__ ____ + * / /|_/ / // / / __/ /___// / / -_) __/ _ \ _\ \/ // (_-</ __/ -_) ' \(_-< _/ // _ \/ __/ __ + * /_/ /_/\_,_/_/\__/_/ /_/ \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/ + * Copyright (C) 2015 by Multi-Tech Systems /___/ + * + * + * @author Jason Reiss + * @date 10-31-2015 + * @brief lora namespace defines global settings, structures and enums for the lora library + * + * @details + * + * + * + */ + +#ifndef __LORA_H__ +#define __LORA_H__ + +#include "mbed.h" +#include <assert.h> +#include "MTSLog.h" +//#include <cstring> +#include <inttypes.h> + +namespace lora { + + /** + * Frequency bandwidth of a Datarate, higher bandwidth gives higher datarate + */ + enum Bandwidth { + BW_125, + BW_250, + BW_500, + BW_FSK = 50 + }; + + /** + * Spreading factor of a Datarate, lower spreading factor gives higher datarate + */ + enum SpreadingFactors { + SF_6 = 6, + SF_7, + SF_8, + SF_9, + SF_10, + SF_11, + SF_12, + SF_FSK, + SF_INVALID + }; + + /** + * Datarates for use with ChannelPlan + */ + enum Datarates { + DR_0 = 0, + DR_1, + DR_2, + DR_3, + DR_4, + DR_5, + DR_6, + DR_7, + DR_8, + DR_9, + DR_10, + DR_11, + DR_12, + DR_13, + DR_14, + DR_15 + }; + + const uint8_t MIN_DATARATE = (uint8_t) DR_0; //!< Minimum datarate + + + const uint8_t MAX_PHY_PACKET_SIZE = 255; //!< Maximum size for a packet + const uint8_t MAX_APPS = 8; //!< Maximum number of apps sessions to save + const uint8_t MAX_MULTICAST_SESSIONS = 8; //!< Maximum number of multicast sessions to save + const uint8_t EUI_SIZE = 8; //!< Number of bytes in an EUI + const uint8_t KEY_SIZE = 16; //!< Number of bytes in an AES key + + const uint8_t DEFAULT_NUM_CHANNELS = 16; //!< Default number of channels in a plan + const uint8_t DEFAULT_RX1_DR_OFFSET = 0; //!< Default datarate offset for first rx window + const uint8_t DEFAULT_RX2_DATARATE = 0; //!< Default datarate for second rx window + const uint8_t DEFAULT_TX_POWER = 14; //!< Default transmit power + const uint8_t DEFAULT_CODE_RATE = 1; //!< Default coding rate 1:4/5, 2:4/6, 3:4/7, 4:4/8 + const uint8_t DEFAULT_PREAMBLE_LEN = 8; //!< Default preamble length + + const int32_t MAX_FCNT_GAP = 16384; //!< Maximum allowed gap in sequence numbers before roll-over + + const uint16_t PRIVATE_JOIN_DELAY = 1000; //!< Default join delay used for private network + const uint16_t PUBLIC_JOIN_DELAY = 5000; //!< Default join delay used for public network + const uint16_t DEFAULT_JOIN_DELAY = PRIVATE_JOIN_DELAY; //!< Default join delay1 + const uint16_t DEFAULT_RX_DELAY = 1000; //!< Default delay for first receive window + const uint16_t DEFAULT_RX_TIMEOUT = 3000; //!< Default timeout for receive windows + + const uint8_t HI_DR_SYMBOL_TIMEOUT = 12; //!< Symbol timeout for receive at datarate with SF < 11 + const uint8_t LO_DR_SYMBOL_TIMEOUT = 8; //!< Symbol timeout for receive at datarate with SF > 10 + + const uint16_t RX2_DELAY_OFFSET = 1000; //!< Delay between first and second window + const uint16_t RXC_OFFSET = 50; //!< Time between end of RXC after TX and RX1 + + const uint8_t US915_125K_NUM_CHANS = 64; //!< Number of 125k channels in US915 channel plan + const uint8_t US915_500K_NUM_CHANS = 8; //!< Number of 500k channels in US915 channel plan + + const uint32_t US915_125K_FREQ_BASE = 902300000; //!< Frequency base for 125k US915 uplink channels + const uint32_t US915_125K_FREQ_STEP = 200000; //!< Frequency step for 125k US915 uplink channels + + const uint32_t US915_500K_FREQ_BASE = 903000000; //!< Frequency base for 500k US915 uplink channels + const uint32_t US915_500K_FREQ_STEP = 1600000; //!< Frequency step for 500k US915 uplink channels + + const uint32_t US915_500K_DBASE = 923300000; //!< Frequency base for 500k US915 downlink channels + const uint32_t US915_500K_DSTEP = 600000; //!< Frequency step for 500k US915 downlink channels + + const uint32_t US915_FREQ_MIN = 902000000; + const uint32_t US915_FREQ_MAX = 928000000; + + const uint8_t US915_MIN_DATARATE = (uint8_t) DR_0; //!< Minimum transmit datarate for US915 + const uint8_t US915_MAX_DATARATE = (uint8_t) DR_4; //!< Maximum transmit datarate for US915 + + const uint8_t US915_MIN_DATARATE_OFFSET = (uint8_t) 0; //!< Minimum transmit datarate for US915 + const uint8_t US915_MAX_DATARATE_OFFSET = (uint8_t) 3; //!< Maximum transmit datarate for US915 + + const uint8_t AU915_125K_NUM_CHANS = 64; //!< Number of 125k channels in AU915 channel plan + const uint8_t AU915_500K_NUM_CHANS = 8; //!< Number of 500k channels in AU915 channel plan + + const uint32_t AU915_125K_FREQ_BASE = 915200000; //!< Frequency base for 125k AU915 uplink channels + const uint32_t AU915_125K_FREQ_STEP = 200000; //!< Frequency step for 125k AU915 uplink channels + + const uint32_t AU915_500K_FREQ_BASE = 915900000; //!< Frequency base for 500k AU915 uplink channels + const uint32_t AU915_500K_FREQ_STEP = 1600000; //!< Frequency step for 500k AU915 uplink channels + + const uint32_t AU915_500K_DBASE = 923300000; //!< Frequency base for 500k AU915 downlink channels + const uint32_t AU915_500K_DSTEP = 600000; //!< Frequency step for 500k AU915 downlink channels + + const uint32_t AU915_FREQ_MIN = 915000000; + const uint32_t AU915_FREQ_MAX = 928000000; + + const uint8_t AU915_MIN_DATARATE = (uint8_t) DR_0; //!< Minimum transmit datarate for AU915 + const uint8_t AU915_MAX_DATARATE = (uint8_t) DR_4; //!< Maximum transmit datarate for AU915 + + const uint8_t AU915_MIN_DATARATE_OFFSET = (uint8_t) 0; //!< Minimum transmit datarate for AU915 + const uint8_t AU915_MAX_DATARATE_OFFSET = (uint8_t) 3; //!< Maximum transmit datarate for AU915 + + const uint8_t EU868_125K_NUM_CHANS = 16; //!< Number of 125k channels in EU868 channel plan + const uint8_t EU868_DEFAULT_NUM_CHANS = 3; //!< Number of defualt channels in EU868 channel plan + const uint32_t EU868_125K_FREQ_BASE = 868100000; //!< Frequency base for 125k EU868 uplink channels + const uint32_t EU868_125K_FREQ_STEP = 200000; //!< Frequency step for 125k EU868 uplink channels + const uint32_t EU868_RX2_FREQ = 869525000; //!< Frequency default for second rx window in EU868 + + const uint8_t EU868_TX_POWER_MAX = 14; //!< Max power for EU868 channel plan + + // 0.1% duty cycle 863-868 + // Limiting to 865-868 allows for 1% duty cycle + const uint32_t EU868_MILLI_FREQ_MIN = 865000000; + const uint32_t EU868_MILLI_FREQ_MAX = 868000000; + + const uint32_t EU868_MILLI_1_FREQ_MIN = 868700000; + const uint32_t EU868_MILLI_1_FREQ_MAX = 869200000; + + // 1% duty cycle + const uint32_t EU868_CENTI_FREQ_MIN = 868000000; + const uint32_t EU868_CENTI_FREQ_MAX = 868600000; + + // 10% duty cycle + const uint32_t EU868_DECI_FREQ_MIN = 869400000; + const uint32_t EU868_DECI_FREQ_MAX = 869650000; + + // Below 7dBm there is no duty cycle for these frequencies + // Up to 14dBm there is 1% duty cycle + const uint32_t EU868_VAR_FREQ_MIN = 869700000; + const uint32_t EU868_VAR_FREQ_MAX = 870000000; + + const uint32_t EU868_FREQ_MIN = 863000000; + const uint32_t EU868_FREQ_MAX = 870000000; + + const uint8_t EU868_MIN_DATARATE = (uint8_t) DR_0; //!< Minimum transmit datarate for EU868 + const uint8_t EU868_MAX_DATARATE = (uint8_t) DR_7; //!< Maximum transmit datarate for EU868 + + const uint8_t EU868_MIN_DATARATE_OFFSET = (uint8_t) 0; //!< Minimum transmit datarate for US915 + const uint8_t EU868_MAX_DATARATE_OFFSET = (uint8_t) 5; //!< Maximum transmit datarate for US915 + + const int16_t DEFAULT_FREE_CHAN_RSSI_THRESHOLD = -90; //!< Threshold for channel activity detection (CAD) dBm + + const uint8_t CHAN_MASK_SIZE = 16; //!< Number of bits in a channel mask + const uint8_t COMMANDS_BUFFER_SIZE = 15; //!< Size of Mac Command buffer + + const uint8_t PKT_HEADER = 0; //!< Index to packet mHdr field + const uint8_t PKT_ADDRESS = 1; //!< Index to first byte of packet address field + const uint8_t PKT_FRAME_CONTROL = PKT_ADDRESS + 4; //!< Index to packet fCtrl field @see UplinkControl + const uint8_t PKT_FRAME_COUNTER = PKT_FRAME_CONTROL + 1; //!< Index to packet frame counter field + const uint8_t PKT_OPTIONS_START = PKT_FRAME_COUNTER + 2; //!< Index to start of optional mac commands + + const uint8_t PKT_JOIN_APP_NONCE = 1; //!< Index to application nonce in Join Accept message + const uint8_t PKT_JOIN_NETWORK_ID = 4; //!< Index to network id in Join Accept message + const uint8_t PKT_JOIN_NETWORK_ADDRESS = 7; //!< Index to network address in Join Accept message + const uint8_t PKT_JOIN_DL_SETTINGS = 11; //!< Index to downlink settings in Join Accept message + const uint8_t PKT_JOIN_RX_DELAY = 12; //!< Index to rx delay in Join Accept message + + const uint8_t ADR_ACK_LIMIT = 64; //!< Number of packets without ADR ACK Request + const uint8_t ADR_ACK_DELAY = 32; //!< Number of packets to expect ADR ACK Response within + + const uint16_t ACK_TIMEOUT = 2000; //!< Base millisecond timeout to resend after missed ACK + const uint16_t ACK_TIMEOUT_RND = 1000; //!< Random millisecond adjustment to resend after missed ACK + + const uint8_t FRAME_OVERHEAD = 13; //!< Bytes of network info overhead in a frame + + /** + * Settings to choose ChannelPlan + */ + enum FrequencyBand { + EU868, //!< EU 863-870 16 channel uplink + US915, //!< US 902-928 64-125k/8-500k uplink and 8-500k downlink channels + AU915, //!< US 915-928 64-125k/8-500k uplink and 8-500k downlink channels + CN779, //!< + CN470, //!< + EU433, //!< + }; + + /** + * Settings for type of network + * PUBLIC - defaults to 5/6 second join windows and 0x34 sync word + * PRIVATE - defaults to 1/2 second join windows and 0x12 sync word + */ + enum NetworkType { + PRIVATE = 0, + PUBLIC = 1, + PEER_TO_PEER = 4 + }; + + /** + * Enum for on/off settings + */ + enum Enabled { + OFF = 0, + ON = 1 + }; + + /** + * Return status of mac functions + */ + enum MacStatus { + LORA_OK = 0, + LORA_ERROR = 1, + LORA_JOIN_ERROR = 2, + LORA_SEND_ERROR = 3, + LORA_MIC_ERROR = 4, + LORA_ADDRESS_ERROR = 5, + LORA_NO_CHANS_ENABLED = 6, + LORA_COMMAND_BUFFER_FULL = 7, + LORA_UNKNOWN_MAC_COMMAND = 8, + LORA_ADR_OFF = 9, + LORA_BUSY = 10, + LORA_LINK_BUSY = 11, + LORA_RADIO_BUSY = 12, + LORA_BUFFER_FULL = 13, + LORA_JOIN_BACKOFF = 14, + LORA_NO_FREE_CHAN = 15, + LORA_AGGREGATED_DUTY_CYCLE = 16, + LORA_MAX_PAYLOAD_EXCEEDED + }; + + /** + * State for Link + */ + enum LinkState { + LINK_IDLE = 0, //!< Link ready to send or receive + LINK_TX, //!< Link is busy sending + LINK_ACK_TX, //!< Link is busy resending after missed ACK + LINK_REP_TX, //!< Link is busy repeating + LINK_RX, //!< Link has receive window open + LINK_RX1, //!< Link has first received window open + LINK_RX2, //!< Link has second received window open + LINK_RXC, //!< Link has class C received window open + LINK_P2P, //!< Link is busy sending + }; + + /** + * State for MAC + */ + enum MacState { + MAC_IDLE, + MAC_RX1, + MAC_RX2, + MAC_RXC, + MAC_TX + }; + + /** + * Operation class for device + */ + enum MoteClass { + CLASS_A = 0x00, //!< Device can only receive in windows opened after a transmit + CLASS_B = 0x01, //!< Device can receive in windows sychronized with gateway beacon + CLASS_C = 0x02 //!< Device can receive any time when not transmitting + }; + + /** + * Direction of a packet + */ + enum Direction { + DIR_UP = 0, //!< Packet is sent from mote to gateway + DIR_DOWN = 1, //!< Packet was received from gateway + DIR_PEER = 2 //!< Packet was received from peer + }; + + + /** + * Received window used by Link + */ + enum ReceiveWindows { + RX_1 = 1, //!< First receive window + RX_2, //!< Second receive window + RX_BEACON, //!< Beacon receive window + RX_SLOT, //!< Beacon Slot receive window + RX_TEST + }; + + /** + * Datarate range for a Channel + */ + typedef union { + int8_t Value; + struct { + int8_t Min :4; + int8_t Max :4; + } Fields; + } DatarateRange; + + /** + * Datarate used for transmitting and receiving + */ + typedef struct Datarate { + uint8_t Index; + uint8_t Bandwidth; + uint8_t Coderate; + uint8_t PreambleLength; + uint8_t SpreadingFactor; + uint8_t Crc; + uint8_t TxIQ; + uint8_t RxIQ; + uint8_t SymbolTimeout(); + Datarate(); + } Datarate; + + /** + * Channel used for transmitting + */ + typedef struct { + uint8_t Index; + uint32_t Frequency; + DatarateRange DrRange; + } Channel; + + /** + * Receive window + */ + typedef struct { + uint8_t Index; + uint32_t Frequency; + uint8_t DatarateIndex; + } RxWindow; + + /** + * Duty band for limiting time-on-air for regional regulations + */ + typedef struct { + uint8_t Index; + uint32_t FrequencyMin; + uint32_t FrequencyMax; + uint8_t PowerMax; + uint16_t DutyCycle; //!< Multiplier of time on air, 0:100%, 1:50%, 2:33%, 10:10%, 100:1%, 1000,0.1% + uint32_t TimeOffEnd; //!< Timestamp when this band will be available + } DutyBand; + + /** + * Device configuration + */ + typedef struct { + uint8_t FrequencyBand; //!< Used to choose ChannelPlan + uint8_t EUI[8]; //!< Unique identifier assigned to device + } DeviceConfig; + + /** + * Network configuration + */ + typedef struct { + uint8_t Mode; //!< PUBLIC, PRIVATE or PEER_TO_PEER network mode + uint8_t Class; //!< Operating class of device + uint8_t EUI[8]; //!< Network ID or AppEUI + uint8_t Key[16]; //!< Network Key or AppKey + uint8_t JoinDelay; //!< Number of seconds to wait before 1st RX Window + uint8_t RxDelay; //!< Number of seconds to wait before 1st RX Window + uint8_t ChannelGroup; //!< ChannelGroup used for US915 hybrid operation 0:72 channels, 1:1-8 channels ... + uint8_t AckAttempts; //!< Number of attempts to send packet and receive an ACK from server + uint8_t Retries; //!< Number of times to resend a packet without receiving an ACK, redundancy + uint8_t ADREnabled; //!< Enable adaptive datarate + uint8_t CADEnabled; //!< Enable listen before talk/channel activity detection + uint8_t RepeaterMode; //!< Limit payloads to repeater compatible sizes + uint8_t TxPower; //!< Default radio output power in dBm + uint8_t TxPowerMax; //!< Max transmit power + uint8_t TxDatarate; //!< Datarate for P2P transmit + uint32_t TxFrequency; //!< Frequency for P2P transmit + int8_t AntennaGain; //!< Antenna Gain + uint8_t DisableEncryption; //!< Disable Encryption + uint8_t DisableCRC; //!< Disable CRC on uplink packets + uint16_t P2PACKTimeout; + uint16_t P2PACKBackoff; + uint8_t JoinRx1DatarateOffset; //!< Offset for datarate for first window + uint32_t JoinRx2Frequency; //!< Frequency used in second window + uint8_t JoinRx2DatarateIndex; //!< Datarate for second window + } NetworkConfig; + + /** + * Network session info + * Some settings are acquired in join message and others may be changed through Mac Commands from server + */ + typedef struct { + uint8_t Joined; //!< State of session + uint8_t Rx1DatarateOffset; //!< Offset for datarate for first window + uint32_t Rx2Frequency; //!< Frequency used in second window + uint8_t Rx2DatarateIndex; //!< Datarate for second window + uint8_t TxPower; //!< Current total radiated output power in dBm + uint8_t TxDatarate; //!< Current datarate can be changed when ADR is enabled + uint32_t Address; //!< Network address + uint32_t NetworkID; //!< Network ID 24-bits + uint8_t NetworkSessionKey[16]; //!< Network session key + uint8_t ApplicationSessionKey[16]; //!< Data session key + uint16_t ChannelMask[4]; //!< Current channel mask + uint16_t ChannelMask500k; //!< Current channel mask for 500k channels + uint32_t DownlinkCounter; //!< Downlink counter of last packet received from server + uint32_t UplinkCounter; //!< Uplink counter of last packet received from server + uint8_t Redundancy; //!< Number of time to repeat an uplink + uint8_t MaxDutyCycle; //!< Current Max Duty Cycle value + uint32_t JoinTimeOnAir; //!< Balance of time on air used during join attempts + uint32_t JoinTimeOffEnd; //!< RTC time of next join attempt + uint32_t JoinFirstAttempt; //!< RTC time of first failed join attempt + uint32_t AggregatedTimeOffEnd; //!< Time off air expiration for aggregate duty cycle + uint16_t AggregateDutyCycle; //!< Used for enforcing time-on-air + uint8_t AckCounter; //!< Current number of packets sent without ACK from server + uint8_t AdrCounter; //!< Current number of packets received without downlink from server + uint8_t RxDelay; //!< Number of seconds to wait before 1st RX Window + uint8_t CommandBuffer[COMMANDS_BUFFER_SIZE]; //!< Buffer to hold Mac Commands and parameters to be sent in next packet + uint8_t CommandBufferIndex; //!< Index to place next Mac Command, also current size of Command Buffer + bool SrvRequestedAck; //!< Indicator of ACK requested by server in last packet received + bool DataPending; //!< Indicator of data pending at server + uint8_t RxTimingSetupReqReceived; //!< Indicator that RxTimingSetupAns should be included in uplink + uint8_t RxParamSetupReqAnswer; //!< Indicator that RxParamSetupAns should be included in uplink + } NetworkSession; + + /** + * Multicast session info + */ + typedef struct { + uint32_t Address; //!< Network address + uint8_t NetworkSessionKey[16]; //!< Network session key + uint8_t DataSessionKey[16]; //!< Data session key + uint32_t DownlinkCounter; //!< Downlink counter of last packet received from server + } MulticastSession; + + /** + * Application configuration + */ + typedef struct { + uint8_t Port; //!< Port used by application + uint8_t AppEUI; //!< Application ID + uint8_t AppKey[16]; //!< Application Key + } ApplicationConfig; + + /** + * Statistics of current network session + */ + typedef struct Statistics { + uint32_t Up; //!< Number of uplink packets sent + uint32_t Down; //!< Number of downlink packets received + uint32_t Joins; //!< Number of join requests sent + uint32_t JoinFails; //!< Number of join requests without response or invalid response + uint32_t MissedAcks; //!< Number of missed acknowledgement attempts of confirmed packets + uint32_t CRCErrors; //!< Number of CRC errors in received packets + int32_t AvgCount; //!< Number of packets used to compute rolling average of RSSI and SNR + int16_t Rssi; //!< RSSI of last packet received + int16_t RssiMin; //!< Minimum RSSI of last AvgCount packets + int16_t RssiMax; //!< Maximum RSSI of last AvgCount packets + int16_t RssiAvg; //!< Rolling average RSSI of last AvgCount packets + int16_t Snr; //!< SNR of last packet received + int16_t SnrMin; //!< Minimum SNR of last AvgCount packets + int16_t SnrMax; //!< Maximum SNR of last AvgCount packets + int16_t SnrAvg; //!< Rolling average SNR of last AvgCount packets + } Statistics; + + /** + * Testing settings + */ + typedef struct { + uint8_t TestMode; + uint8_t SkipMICCheck; + uint8_t DisableDutyCycle; + uint8_t DisableRx1; + uint8_t DisableRx2; + uint8_t FixedUplinkCounter; + uint8_t DisableRandomJoinDatarate; + } Testing; + + /** + * Combination of device, network, testing settings and statistics + */ + typedef struct { + DeviceConfig Device; + NetworkConfig Network; + NetworkSession Session; + ApplicationConfig Applications[MAX_APPS]; + MulticastSession Multicast[MAX_MULTICAST_SESSIONS]; + Statistics Stats; + Testing Test; + } Settings; + + /** + * Downlink settings sent in Join Accept message + */ + typedef union { + uint8_t Value; + struct { + uint8_t Rx2Datarate :4; + uint8_t Rx1Offset :3; + uint8_t RFU :1; + }; + } DownlinkSettings; + + /** + * Frame structure for Join Request + */ + typedef struct { + uint8_t Type; + uint8_t AppEUI[8]; + uint8_t DevEUI[8]; + uint8_t Nonce[2]; + uint8_t MIC[4]; + } JoinRequestFrame; + + /** + * Mac header of uplink and downlink packets + */ + typedef union { + uint8_t Value; + struct { + uint8_t Major :2; + uint8_t RFU :3; + uint8_t MType :3; + } Bits; + } MacHeader; + + /** + * Frame control field of uplink packets + */ + typedef union { + uint8_t Value; + struct { + uint8_t OptionsLength :4; + uint8_t ClassB :1; + uint8_t Ack :1; + uint8_t AdrAckReq :1; + uint8_t Adr :1; + } Bits; + } UplinkControl; + + /** + * Frame control field of downlink packets + */ + typedef union { + uint8_t Value; + struct { + uint8_t OptionsLength :4; + uint8_t FPending :1; + uint8_t Ack :1; + uint8_t RFU :1; + uint8_t Adr :1; + } Bits; + } DownlinkControl; + + /** + * Frame type of packet + */ + typedef enum { + FRAME_TYPE_JOIN_REQ = 0x00, + FRAME_TYPE_JOIN_ACCEPT = 0x01, + FRAME_TYPE_DATA_UNCONFIRMED_UP = 0x02, + FRAME_TYPE_DATA_UNCONFIRMED_DOWN = 0x03, + FRAME_TYPE_DATA_CONFIRMED_UP = 0x04, + FRAME_TYPE_DATA_CONFIRMED_DOWN = 0x05, + FRAME_TYPE_RFU = 0x06, + FRAME_TYPE_PROPRIETARY = 0x07, + } FrameType; + + /** + * LoRaWAN mote MAC commands + */ + typedef enum { + /* Class A */ + MOTE_MAC_LINK_CHECK_REQ = 0x02, + MOTE_MAC_LINK_ADR_ANS = 0x03, + MOTE_MAC_DUTY_CYCLE_ANS = 0x04, + MOTE_MAC_RX_PARAM_SETUP_ANS = 0x05, + MOTE_MAC_DEV_STATUS_ANS = 0x06, + MOTE_MAC_NEW_CHANNEL_ANS = 0x07, + MOTE_MAC_RX_TIMING_SETUP_ANS = 0x08, + + /* Class B */ + MOTE_MAC_PING_SLOT_INFO_REQ = 0x09, + MOTE_MAC_PING_SLOT_FREQ_ANS = 0x0a, + MOTE_MAC_PING_SLOT_CHANNEL_ANS = 0x0a, + MOTE_MAC_BEACON_TIMING_REQ = 0x0b, + MOTE_MAC_BEACON_FREQ_ANS = 0x0c, + + /* Multitech */ + MOTE_MAC_PING_REQ = 0x80, + MOTE_MAC_CHANGE_CLASS = 0x81, + MOTE_MAC_MULTIPART_START_REQ = 0x82, + MOTE_MAC_MULTIPART_START_ANS = 0x83, + MOTE_MAC_MULTIPART_CHUNK = 0x84, + MOTE_MAC_MULTIPART_END_REQ = 0x85, + MOTE_MAC_MULTIPART_END_ANS = 0x86 + } MoteCommand; + + /*! + * LoRaWAN server MAC commands + */ + typedef enum { + /* Class A */ + SRV_MAC_LINK_CHECK_ANS = 0x02, + SRV_MAC_LINK_ADR_REQ = 0x03, + SRV_MAC_DUTY_CYCLE_REQ = 0x04, + SRV_MAC_RX_PARAM_SETUP_REQ = 0x05, + SRV_MAC_DEV_STATUS_REQ = 0x06, + SRV_MAC_NEW_CHANNEL_REQ = 0x07, + SRV_MAC_RX_TIMING_SETUP_REQ = 0x08, + + /* Class B */ + SRV_MAC_PING_SLOT_INFO_ANS = 0x09, + SRV_MAC_PING_SLOT_FREQ_REQ = 0x0a, + SRV_MAC_PING_SLOT_CHANNEL_REQ = 0x0a, + SRV_MAC_BEACON_TIMING_ANS = 0x0b, + SRV_MAC_BEACON_FREQ_REQ = 0x0c, + + /* Multitech */ + SRV_MAC_PING_ANS = 0x80, + SRV_MAC_CHANGE_CLASS = 0x81, + SRV_MAC_MULTIPART_START_REQ = 0x82, + SRV_MAC_MULTIPART_START_ANS = 0x83, + SRV_MAC_MULTIPART_CHUNK = 0x84, + SRV_MAC_MULTIPART_END_REQ = 0x85, + SRV_MAC_MULTIPART_END_ANS = 0x86 + } ServerCommand; + + /** + * Random seed for software RNG + */ + void srand(uint32_t seed); + + /** + * Software RNG for consistent results across differing hardware + */ + int rand(void); + + /** + * Generate random number bounded by min and max + */ + int32_t rand_r(int32_t min, int32_t max); + + uint8_t CountBits(uint16_t mask); + + /** + * Copy 3-bytes network order from array into LSB of integer value + */ + void CopyNetIDtoInt(const uint8_t* arr, uint32_t& val); + + /** + * Copy LSB 3-bytes from integer value into array network order + */ + void CopyNetIDtoArray(uint32_t val, uint8_t* arr); + + /** + * Copy 4-bytes network order from array in to integer value + */ + void CopyAddrtoInt(const uint8_t* arr, uint32_t& val); + + /** + * Copy 4-bytes from integer in to array network order + */ + void CopyAddrtoArray(uint32_t val, uint8_t* arr); + + /** + * Copy 3-bytes network order from array into integer value and multiply by 100 + */ + void CopyFreqtoInt(const uint8_t* arr, uint32_t& freq); + + /** + * Reverse memory copy + */ + void memcpy_r(uint8_t *dst, const uint8_t *src, size_t n); + +} + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MTS-Lora/vendor/multitech/MTS-Utils/MTSCircularBuffer.h Thu Aug 04 15:11:24 2016 -0500 @@ -0,0 +1,158 @@ +#ifndef MTSCIRCULARBUFFER_H +#define MTSCIRCULARBUFFER_H + +#include "Utils.h" + +namespace mts +{ + +/** This class provides a circular byte buffer meant for temporary storage +* during IO transactions. It contains many of the common methods you +* would expect from a circular buffer like read, write, and various +* methods for checking the size or status. It should be noted that +* this class does not include any special code for thread safety like +* a lock. In most cases this is not problematic, but is something +* to be aware of. +*/ +class MTSCircularBuffer +{ +public: + /** Creates an MTSCircularBuffer object with the specified static size. + * + * @prarm bufferSize size of the buffer in bytes. + */ + MTSCircularBuffer(int bufferSize); + + /** Destructs an MTSCircularBuffer object and frees all related resources. + */ + ~MTSCircularBuffer(); + + /** This method enables bulk reads from the buffer. If more data is + * requested then available it simply returns all remaining data within the + * buffer. + * + * @param data the buffer where data read will be added to. + * @param length the amount of data in bytes to be read into the buffer. + * @returns the total number of bytes that were read. + */ + int read(char* data, int length); + + /** This method reads a single byte from the buffer. + * + * @param data char where the read byte will be stored. + * @returns 1 if byte is read or 0 if no bytes available. + */ + int read(char& data); + + /** This method enables bulk writes to the buffer. If more data + * is requested to be written then space available the method writes + * as much data as possible and returns the actual amount written. + * + * @param data the byte array to be written. + * @param length the length of data to be written from the data paramter. + * @returns the number of bytes written to the buffer, which is 0 if + * the buffer is full. + */ + int write(const char* data, int length); + + /** This method writes a signle byte as a char to the buffer. + * + * @param data the byte to be written as a char. + * @returns 1 if the byte was written or 0 if the buffer was full. + */ + int write(char data); + + /** This method is used to setup a callback funtion when the buffer reaches + * a certain threshold. The threshold condition is checked after every read + * and write call is completed. The condition is made up of both a threshold + * value and operator. An example that would trigger a callback is if the + * threshold was 10, the operator GREATER, and there were 12 bytes added to an + * empty buffer. + * + * @param tptr a pointer to the object to be called when the condition is met. + * @param mptr a pointer to the function within the object to be called when + * the condition is met. + * @param threshold the value in bytes to be used as part of the condition. + * @param op the operator to be used in conjunction with the threshold + * as part of the condition. + */ + template<typename T> + void attach(T *tptr, void( T::*mptr)(void), int threshold, RelationalOperator op) { + _threshold = threshold; + _op = op; + notify.attach(tptr, mptr); + } + + /** This method is used to setup a callback funtion when the buffer reaches + * a certain threshold. The threshold condition is checked after every read + * and write call is completed. The condition is made up of both a threshold + * value and operator. An example that would trigger a callback is if the + * threshold was 10, the operator GREATER, and there were 12 bytes added to an + * empty buffer. + * + * @param fptr a pointer to the static function to be called when the condition + * is met. + * @param threshold the value in bytes to be used as part of the condition. + * @param op the operator to be used in conjunction with the threshold + * as part of the condition. + */ + void attach(void(*fptr)(void), int threshold, RelationalOperator op) { + _threshold = threshold; + _op = op; + notify.attach(fptr); + } + + /** This method returns the size of the storage space currently allocated for + * the buffer. This value is equivalent to the one passed into the constructor. + * This value is equal or greater than the size() of the buffer. + * + * @returns the allocated size of the buffer in bytes. + */ + int capacity(); + + /** This method returns the amount of space left for writing. + * + * @returns numbers of unused bytes in buffer. + */ + int remaining(); + + /** This method returns the number of bytes available for reading. + * + * @returns number of bytes currently in buffer. + */ + int size(); + + /** This method returns whether the buffer is full. + * + * @returns true if full, otherwise false. + */ + bool isFull(); + + /** This method returns whether the buffer is empty. + * + * @returns true if empty, otherwise false. + */ + bool isEmpty(); + + /** This method clears the buffer. This is done through + * setting the internal read and write indexes to the same + * value and is therefore not an expensive operation. + */ + void clear(); + + +private: + int bufferSize; // total size of the buffer + char* buffer; // internal byte buffer as a character buffer + int readIndex; // read index for circular buffer + int writeIndex; // write index for circular buffer + int bytes; // available data + FunctionPointer notify; // function pointer used for the internal callback notification + int _threshold; // threshold for the notification + RelationalOperator _op; // operator that determines the direction of the threshold + void checkThreshold(); // private function that checks thresholds and processes notifications +}; + +} + +#endif /* MTSCIRCULARBUFFER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MTS-Lora/vendor/multitech/MTS-Utils/MTSLog.h Thu Aug 04 15:11:24 2016 -0500 @@ -0,0 +1,108 @@ +#ifndef MTSLOG_H +#define MTSLOG_H + +#include <string> + +inline const char* className(const std::string& prettyFunction) +{ + size_t colons = prettyFunction.find_last_of("::"); + if (colons == std::string::npos) + return ""; + size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1; + size_t end = colons - begin; + + return prettyFunction.substr(begin,end).c_str(); +} + +#define __CLASSNAME__ className(__PRETTY_FUNCTION__) + + +#ifdef MTS_DEBUG +#define logFatal(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::FATAL_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::FATAL_LABEL, ##__VA_ARGS__) +#define logError(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::ERROR_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::ERROR_LABEL, ##__VA_ARGS__) +#define logWarning(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::WARNING_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::WARNING_LABEL, ##__VA_ARGS__) +#define logInfo(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::INFO_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::INFO_LABEL, ##__VA_ARGS__) +#define logDebug(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::DEBUG_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::DEBUG_LABEL, ##__VA_ARGS__) +#define logTrace(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::TRACE_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::TRACE_LABEL, ##__VA_ARGS__) +#else +#define logFatal(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::FATAL_LEVEL, "[%s] " format "\r\n", mts::MTSLog::FATAL_LABEL, ##__VA_ARGS__) +#define logError(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::ERROR_LEVEL, "[%s] " format "\r\n", mts::MTSLog::ERROR_LABEL, ##__VA_ARGS__) +#define logWarning(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::WARNING_LEVEL, "[%s] " format "\r\n", mts::MTSLog::WARNING_LABEL, ##__VA_ARGS__) +#define logInfo(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::INFO_LEVEL, "[%s] " format "\r\n", mts::MTSLog::INFO_LABEL, ##__VA_ARGS__) +#define logDebug(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::DEBUG_LEVEL, "[%s] " format "\r\n", mts::MTSLog::DEBUG_LABEL, ##__VA_ARGS__) +#define logTrace(format, ...) \ + mts::MTSLog::printMessage(mts::MTSLog::TRACE_LEVEL, "[%s] " format "\r\n", mts::MTSLog::TRACE_LABEL, ##__VA_ARGS__) +#endif + +namespace mts { + +class MTSLog +{ +public: + + /** Enum of log levels. + */ + enum logLevel { + NONE_LEVEL = 0, + FATAL_LEVEL = 1, + ERROR_LEVEL = 2, + WARNING_LEVEL = 3, + INFO_LEVEL = 4, + DEBUG_LEVEL = 5, + TRACE_LEVEL = 6 + }; + + /** Print log message. + */ + static void printMessage(int level, const char* format, ...); + + /** Determine if the given level is currently printable. + */ + static bool printable(int level); + + /** Set log level + * Messages with lower priority than the current level will not be printed. + * If the level is set to NONE, no messages will print. + */ + static void setLogLevel(int level); + + /** Get the current log level. + */ + static int getLogLevel(); + + /** Get string representation of the current log level. + */ + static const char* getLogLevelString(); + + static const char* NONE_LABEL; + static const char* FATAL_LABEL; + static const char* ERROR_LABEL; + static const char* WARNING_LABEL; + static const char* INFO_LABEL; + static const char* DEBUG_LABEL; + static const char* TRACE_LABEL; + +private: + + /** Constructor + */ + MTSLog(); + + static int currentLevel; + +}; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MTS-Lora/vendor/multitech/MTS-Utils/MTSText.h Thu Aug 04 15:11:24 2016 -0500 @@ -0,0 +1,83 @@ +#ifndef MTSTEXT_H +#define MTSTEXT_H + +#include <string> +#include <vector> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +namespace mts +{ + +/** This class contains a number of static methods for manipulating strings and other +* text data. +*/ +class Text +{ +public: + /** This static method can be used to pull out a string at the next line break. A + * break can either be a newline '\n', carriage return '\r' or both. + * + * @param source the source string to look for the line break on. + * @param start the start postion within the string to begin looking for the line + * break. + * @param cursor this value will be updated with the index for the next available character + * after the line break. If a line break is not found returns -1. + * @returns the string beginning with the start index up to including the line breaks. + */ + static std::string getLine(const std::string& source, const size_t& start, size_t& cursor); + + /** This is a static method for splitting strings using a delimeter value. + * + * @param str the string to try and split. + * @param delimiter the delimeter value to split on as a character. + * @param limit the maximum number of splits. If equal to 0 it splits as amny times as possible. + * The default is 0. + * @returns an ordered vector of strings conatining the splits of the original string. + */ + static std::vector<std::string> split(const std::string& str, char delimiter, int limit = 0); + + /** This is a static method for splitting strings using a delimeter value. + * + * @param str the string to try and split. + * @param delimiter the delimeter value to split on as a string. + * @param limit the maximum number of splits. If equal to 0 it splits as amny times as possible. + * The default is 0. + * @returns an ordered vector of strings conatining the splits of the original string. + */ + static std::vector<std::string> split(const std::string& str, const std::string& delimiter, int limit = 0); + + static std::string readString(char* index, int length); + + static std::string toUpper(const std::string str); + + static std::string float2String(double val, int precision); + + static std::string bin2hexString(const std::vector<uint8_t>& data, const char* delim = "", bool leadingZeros = false, bool bytePadding = true); + + static std::string bin2hexString(const uint8_t* data, const uint32_t len, const char* delim = "", bool leadingZeros = false, bool bytePadding = true); + + static std::string bin2base64(const std::vector<uint8_t>& data); + + static std::string bin2base64(const uint8_t* data, size_t size); + + static bool base642bin(const std::string in, std::vector<uint8_t>& out); + + static void ltrim(std::string& str, const char* args); + + static void rtrim(std::string& str, const char* args); + + static void trim(std::string& str, const char* args); + +private: + // Safety for class with only static methods + Text(); + Text(const Text& other); + Text& operator=(const Text& other); +}; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MTS-Lora/vendor/multitech/MTS-Utils/Utils.h Thu Aug 04 15:11:24 2016 -0500 @@ -0,0 +1,41 @@ +#ifndef UTILS_H +#define UTILS_H + +#include <string> + +//Defines a max function that can be used. +inline int mts_max(int a, int b) { return a > b ? a : b; } + +//Defines a min function that can be used. +inline int mts_min(int a, int b) { return a < b ? a : b; } + +///An enumeration for relational operators +enum RelationalOperator { + GREATER, LESS, EQUAL, GREATER_EQUAL, LESS_EQUAL +}; + +/** A static method for getting a string representation for the RelationalOperator +* enumeration. +* +* @param relationalOperator a RelationalOperator enumeration. +* @returns the enumeration name as a string. +*/ +static inline std::string getRelationalOperatorNames(RelationalOperator relationalOperator) +{ + switch(relationalOperator) { + case GREATER: + return "GREATER"; + case LESS: + return "LESS"; + case EQUAL: + return "EQUAL"; + case GREATER_EQUAL: + return "GREATER_EQUAL"; + case LESS_EQUAL: + return "LESS_EQUAL"; + default: + return "UNKNOWN ENUM"; + } +} + +#endif
--- a/MTS-Utils/MTSCircularBuffer.h Tue Mar 29 10:25:31 2016 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -#ifndef MTSCIRCULARBUFFER_H -#define MTSCIRCULARBUFFER_H - -#include "Utils.h" - -namespace mts -{ - -/** This class provides a circular byte buffer meant for temporary storage -* during IO transactions. It contains many of the common methods you -* would expect from a circular buffer like read, write, and various -* methods for checking the size or status. It should be noted that -* this class does not include any special code for thread safety like -* a lock. In most cases this is not problematic, but is something -* to be aware of. -*/ -class MTSCircularBuffer -{ -public: - /** Creates an MTSCircularBuffer object with the specified static size. - * - * @prarm bufferSize size of the buffer in bytes. - */ - MTSCircularBuffer(int bufferSize); - - /** Destructs an MTSCircularBuffer object and frees all related resources. - */ - ~MTSCircularBuffer(); - - /** This method enables bulk reads from the buffer. If more data is - * requested then available it simply returns all remaining data within the - * buffer. - * - * @param data the buffer where data read will be added to. - * @param length the amount of data in bytes to be read into the buffer. - * @returns the total number of bytes that were read. - */ - int read(char* data, int length); - - /** This method reads a single byte from the buffer. - * - * @param data char where the read byte will be stored. - * @returns 1 if byte is read or 0 if no bytes available. - */ - int read(char& data); - - /** This method enables bulk writes to the buffer. If more data - * is requested to be written then space available the method writes - * as much data as possible and returns the actual amount written. - * - * @param data the byte array to be written. - * @param length the length of data to be written from the data paramter. - * @returns the number of bytes written to the buffer, which is 0 if - * the buffer is full. - */ - int write(const char* data, int length); - - /** This method writes a signle byte as a char to the buffer. - * - * @param data the byte to be written as a char. - * @returns 1 if the byte was written or 0 if the buffer was full. - */ - int write(char data); - - /** This method is used to setup a callback funtion when the buffer reaches - * a certain threshold. The threshold condition is checked after every read - * and write call is completed. The condition is made up of both a threshold - * value and operator. An example that would trigger a callback is if the - * threshold was 10, the operator GREATER, and there were 12 bytes added to an - * empty buffer. - * - * @param tptr a pointer to the object to be called when the condition is met. - * @param mptr a pointer to the function within the object to be called when - * the condition is met. - * @param threshold the value in bytes to be used as part of the condition. - * @param op the operator to be used in conjunction with the threshold - * as part of the condition. - */ - template<typename T> - void attach(T *tptr, void( T::*mptr)(void), int threshold, RelationalOperator op) { - _threshold = threshold; - _op = op; - notify.attach(tptr, mptr); - } - - /** This method is used to setup a callback funtion when the buffer reaches - * a certain threshold. The threshold condition is checked after every read - * and write call is completed. The condition is made up of both a threshold - * value and operator. An example that would trigger a callback is if the - * threshold was 10, the operator GREATER, and there were 12 bytes added to an - * empty buffer. - * - * @param fptr a pointer to the static function to be called when the condition - * is met. - * @param threshold the value in bytes to be used as part of the condition. - * @param op the operator to be used in conjunction with the threshold - * as part of the condition. - */ - void attach(void(*fptr)(void), int threshold, RelationalOperator op) { - _threshold = threshold; - _op = op; - notify.attach(fptr); - } - - /** This method returns the size of the storage space currently allocated for - * the buffer. This value is equivalent to the one passed into the constructor. - * This value is equal or greater than the size() of the buffer. - * - * @returns the allocated size of the buffer in bytes. - */ - int capacity(); - - /** This method returns the amount of space left for writing. - * - * @returns numbers of unused bytes in buffer. - */ - int remaining(); - - /** This method returns the number of bytes available for reading. - * - * @returns number of bytes currently in buffer. - */ - int size(); - - /** This method returns whether the buffer is full. - * - * @returns true if full, otherwise false. - */ - bool isFull(); - - /** This method returns whether the buffer is empty. - * - * @returns true if empty, otherwise false. - */ - bool isEmpty(); - - /** This method clears the buffer. This is done through - * setting the internal read and write indexes to the same - * value and is therefore not an expensive operation. - */ - void clear(); - - -private: - int bufferSize; // total size of the buffer - char* buffer; // internal byte buffer as a character buffer - int readIndex; // read index for circular buffer - int writeIndex; // write index for circular buffer - int bytes; // available data - FunctionPointer notify; // function pointer used for the internal callback notification - int _threshold; // threshold for the notification - RelationalOperator _op; // operator that determines the direction of the threshold - void checkThreshold(); // private function that checks thresholds and processes notifications -}; - -} - -#endif /* MTSCIRCULARBUFFER_H */
--- a/MTS-Utils/MTSLog.h Tue Mar 29 10:25:31 2016 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -#ifndef MTSLOG_H -#define MTSLOG_H - -#include <string> - -inline const char* className(const std::string& prettyFunction) -{ - size_t colons = prettyFunction.find_last_of("::"); - if (colons == std::string::npos) - return ""; - size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1; - size_t end = colons - begin; - - return prettyFunction.substr(begin,end).c_str(); -} - -#define __CLASSNAME__ className(__PRETTY_FUNCTION__) - - -#ifdef MTS_DEBUG -#define logFatal(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::FATAL_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::FATAL_LABEL, ##__VA_ARGS__) -#define logError(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::ERROR_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::ERROR_LABEL, ##__VA_ARGS__) -#define logWarning(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::WARNING_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::WARNING_LABEL, ##__VA_ARGS__) -#define logInfo(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::INFO_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::INFO_LABEL, ##__VA_ARGS__) -#define logDebug(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::DEBUG_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::DEBUG_LABEL, ##__VA_ARGS__) -#define logTrace(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::TRACE_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::TRACE_LABEL, ##__VA_ARGS__) -#else -#define logFatal(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::FATAL_LEVEL, "[%s] " format "\r\n", mts::MTSLog::FATAL_LABEL, ##__VA_ARGS__) -#define logError(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::ERROR_LEVEL, "[%s] " format "\r\n", mts::MTSLog::ERROR_LABEL, ##__VA_ARGS__) -#define logWarning(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::WARNING_LEVEL, "[%s] " format "\r\n", mts::MTSLog::WARNING_LABEL, ##__VA_ARGS__) -#define logInfo(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::INFO_LEVEL, "[%s] " format "\r\n", mts::MTSLog::INFO_LABEL, ##__VA_ARGS__) -#define logDebug(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::DEBUG_LEVEL, "[%s] " format "\r\n", mts::MTSLog::DEBUG_LABEL, ##__VA_ARGS__) -#define logTrace(format, ...) \ - mts::MTSLog::printMessage(mts::MTSLog::TRACE_LEVEL, "[%s] " format "\r\n", mts::MTSLog::TRACE_LABEL, ##__VA_ARGS__) -#endif - -namespace mts { - -class MTSLog -{ -public: - - /** Enum of log levels. - */ - enum logLevel { - NONE_LEVEL = 0, - FATAL_LEVEL = 1, - ERROR_LEVEL = 2, - WARNING_LEVEL = 3, - INFO_LEVEL = 4, - DEBUG_LEVEL = 5, - TRACE_LEVEL = 6 - }; - - /** Print log message. - */ - static void printMessage(int level, const char* format, ...); - - /** Determine if the given level is currently printable. - */ - static bool printable(int level); - - /** Set log level - * Messages with lower priority than the current level will not be printed. - * If the level is set to NONE, no messages will print. - */ - static void setLogLevel(int level); - - /** Get the current log level. - */ - static int getLogLevel(); - - /** Get string representation of the current log level. - */ - static const char* getLogLevelString(); - - static const char* NONE_LABEL; - static const char* FATAL_LABEL; - static const char* ERROR_LABEL; - static const char* WARNING_LABEL; - static const char* INFO_LABEL; - static const char* DEBUG_LABEL; - static const char* TRACE_LABEL; - -private: - - /** Constructor - */ - MTSLog(); - - static int currentLevel; - -}; - -} - -#endif
--- a/MTS-Utils/MTSText.h Tue Mar 29 10:25:31 2016 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -#ifndef MTSTEXT_H -#define MTSTEXT_H - -#include <string> -#include <vector> -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -namespace mts -{ - -/** This class contains a number of static methods for manipulating strings and other -* text data. -*/ -class Text -{ -public: - /** This static method can be used to pull out a string at the next line break. A - * break can either be a newline '\n', carriage return '\r' or both. - * - * @param source the source string to look for the line break on. - * @param start the start postion within the string to begin looking for the line - * break. - * @param cursor this value will be updated with the index for the next available character - * after the line break. If a line break is not found returns -1. - * @returns the string beginning with the start index up to including the line breaks. - */ - static std::string getLine(const std::string& source, const size_t& start, size_t& cursor); - - /** This is a static method for splitting strings using a delimeter value. - * - * @param str the string to try and split. - * @param delimiter the delimeter value to split on as a character. - * @param limit the maximum number of splits. If equal to 0 it splits as amny times as possible. - * The default is 0. - * @returns an ordered vector of strings conatining the splits of the original string. - */ - static std::vector<std::string> split(const std::string& str, char delimiter, int limit = 0); - - /** This is a static method for splitting strings using a delimeter value. - * - * @param str the string to try and split. - * @param delimiter the delimeter value to split on as a string. - * @param limit the maximum number of splits. If equal to 0 it splits as amny times as possible. - * The default is 0. - * @returns an ordered vector of strings conatining the splits of the original string. - */ - static std::vector<std::string> split(const std::string& str, const std::string& delimiter, int limit = 0); - - static std::string readString(char* index, int length); - - static std::string toUpper(const std::string str); - - static std::string float2String(double val, int precision); - - static std::string bin2hexString(const std::vector<uint8_t>& data, const char* delim = "", bool leadingZeros = false, bool bytePadding = true); - - static std::string bin2hexString(const uint8_t* data, const uint32_t len, const char* delim = "", bool leadingZeros = false, bool bytePadding = true); - - static std::string bin2base64(const std::vector<uint8_t>& data); - - static std::string bin2base64(const uint8_t* data, size_t size); - - static bool base642bin(const std::string in, std::vector<uint8_t>& out); - - static void ltrim(std::string& str, const char* args); - - static void rtrim(std::string& str, const char* args); - - static void trim(std::string& str, const char* args); - -private: - // Safety for class with only static methods - Text(); - Text(const Text& other); - Text& operator=(const Text& other); -}; - -} - -#endif
--- a/MTS-Utils/Utils.h Tue Mar 29 10:25:31 2016 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -#ifndef UTILS_H -#define UTILS_H - -#include <string> - -//Defines a max function that can be used. -inline int mts_max(int a, int b) { return a > b ? a : b; } - -//Defines a min function that can be used. -inline int mts_min(int a, int b) { return a < b ? a : b; } - -///An enumeration for relational operators -enum RelationalOperator { - GREATER, LESS, EQUAL, GREATER_EQUAL, LESS_EQUAL -}; - -/** A static method for getting a string representation for the RelationalOperator -* enumeration. -* -* @param relationalOperator a RelationalOperator enumeration. -* @returns the enumeration name as a string. -*/ -static inline std::string getRelationalOperatorNames(RelationalOperator relationalOperator) -{ - switch(relationalOperator) { - case GREATER: - return "GREATER"; - case LESS: - return "LESS"; - case EQUAL: - return "EQUAL"; - case GREATER_EQUAL: - return "GREATER_EQUAL"; - case LESS_EQUAL: - return "LESS_EQUAL"; - default: - return "UNKNOWN ENUM"; - } -} - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MacEvents.h Thu Aug 04 15:11:24 2016 -0500 @@ -0,0 +1,51 @@ +/** __ ___ ____ _ ______ __ ____ __ ____ + * / |/ /_ __/ / /_(_)__/_ __/__ ____/ / / __/_ _____ / /____ __ _ ___ / _/__ ____ + * / /|_/ / // / / __/ /___// / / -_) __/ _ \ _\ \/ // (_-</ __/ -_) ' \(_-< _/ // _ \/ __/ __ + * /_/ /_/\_,_/_/\__/_/ /_/ \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/ + * Copyright (C) 2015 by Multi-Tech Systems /___/ + * + * + * @author Jason Reiss + * @date 10-31-2015 + * @brief lora::MacEvents provides an interface for events from the Mac layer + * + * @details + * + */ + +#ifndef __LORA_MAC_EVENTS_H__ +#define __LORA_MAC_EVENTS_H__ + +#include "Lora.h" + +namespace lora { + + class MacEvents { + + public: + virtual ~MacEvents() {}; + + virtual void TxDone(uint8_t dr) = 0; + virtual void TxTimeout(void) = 0; + + virtual void JoinAccept(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) = 0; + virtual void JoinFailed(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) = 0; + virtual void PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot, uint8_t retries=0) = 0; + virtual void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot) = 0; + + virtual void Pong(int16_t m_rssi, int8_t m_snr, int16_t s_rssi, int8_t s_snr) = 0; + virtual void NetworkLinkCheck(int16_t m_rssi, int8_t m_snr, int8_t s_snr, uint8_t s_gateways) = 0; + + virtual void RxTimeout(uint8_t slot) = 0; + virtual void RxError(uint8_t slot) = 0; + + virtual uint8_t MeasureBattery() = 0; + + private: + + + }; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Mote.h Thu Aug 04 15:11:24 2016 -0500 @@ -0,0 +1,256 @@ +/** __ ___ ____ _ ______ __ ____ __ ____ + * / |/ /_ __/ / /_(_)__/_ __/__ ____/ / / __/_ _____ / /____ __ _ ___ / _/__ ____ + * / /|_/ / // / / __/ /___// / / -_) __/ _ \ _\ \/ // (_-</ __/ -_) ' \(_-< _/ // _ \/ __/ __ + * /_/ /_/\_,_/_/\__/_/ /_/ \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/ + * Copyright (C) 2015 by Multi-Tech Systems /___/ + * + * + * @author Jason Reiss + * @date 10-31-2015 + * @brief lora::Mote provides a user level class that abstracts the complexity of the Mac layer + * + * @details + * + */ + +#ifndef __LORA_MOTE_H__ +#define __LORA_MOTE_H__ + +#include "rtos.h" +#include "MacEvents.h" +#include <vector> + +class SxRadio; +class SxRadio1272; + +namespace lora { + + class Mac; + class ChannelPlan; + + class MoteEvents: public MacEvents { + + /** + * Fired at end of TX + * @param dr datarate used for TX + */ + virtual void TxDone(uint8_t dr); + + /** + * Fired if TX timed out + */ + virtual void TxTimeout(void); + + /** + * Fired when JoinAccept message is received and MIC is validated + * @param payload received bytes + * @param size number of received bytes + * @param rssi of received packet + * @param snr of received packet + */ + virtual void JoinAccept(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr); + + /** + * Fired when JoinAccept message is received and MIC is not valid + * @param payload received bytes + * @param size number of received bytes + * @param rssi of received packet + * @param snr of received packet + */ + virtual void JoinFailed(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr); + + /** + * Fired when non duplicate packet is received and MIC is valid + * @param port of packet + * @param payload received bytes + * @param size number of received bytes + * @param rssi of received packet + * @param snr of received packet + * @param ctrl Downlink control field of packet + * @param slot rx window packet was received + * @param retries number of attempts before ack was received + */ + virtual void PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot, uint8_t retries = 0); + + /** + * Fired when radio has received a packet, packet is not validated + * @param payload received bytes + * @param size number of received bytes + * @param rssi of received packet + * @param snr of received packet + * @param ctrl Downlink control field of packet + * @param slot rx window packet was received + */ + virtual void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot); + + /** + * Fired if rx window times out + * @param slot rx window that timed out + */ + virtual void RxTimeout(uint8_t slot); + + /** + * Fired if rx CRC error + * @param slot rx window that errored + */ + virtual void RxError(uint8_t slot); + + /** + * Fired if pong packet is received + * @param m_rssi of received packet at mote + * @param m_snr of received packet at mote + * @param s_rssi of received packet at server + * @param s_snr of received packet at server + */ + virtual void Pong(int16_t m_rssi, int8_t m_snr, int16_t s_rssi, int8_t s_snr); + + /** + * Fired if network link check answer is received + * @param m_rssi of received packet at mote + * @param m_snr of received packet at mote + * @param s_snr margin of received packet at server + * @param s_gateways number of gateways reporting the packet + */ + virtual void NetworkLinkCheck(int16_t m_rssi, int8_t m_snr, int8_t s_snr, uint8_t s_gateways); + + /** + * Callback to for device to measure the battery level and report to server + * @return battery level 0-255, 0 - external power, 1-254 level min-max, 255 device unable to measure battery + */ + virtual uint8_t MeasureBattery(); + }; + + class Mote { + public: + Mote(Settings* settings); + virtual ~Mote(); + + /** + * Indicator for network session join status + * @return true if joined to network + */ + bool Joined(); + + /** + * Send join request + * @return LORA_OK if request was sent + */ + uint8_t Join(); + + /** + * Send a packet + * @param port to send packet + * @param payload of packet + * @param size in bytes + * @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, uint8_t size); + + /** + * Configure the channel plan + * @param freqBand EU868, US915, AU915 + * @return LORA_OK + */ + uint8_t SetChannelPlan(uint8_t freqBand); + + /** + * Get the channel mask of currently enabled channels + * @return vector containing channel bit masks + */ + std::vector<uint16_t> GetChannelMask(); + + /** + * Set a 16 bit channel mask with index + * @param index of mask to set 0:0-15, 1:16-31 ... + * @param mask 16 bit mask of enabled channels + * @return true + */ + virtual uint8_t SetChannelMask(uint8_t index, uint16_t mask); + + /** + * Set the current channel group for hybrid operation 1-8 else 0 for 64 channel operation + * @param group 0-8 + */ + uint8_t SetChannelGroup(uint8_t group); + + /** + * Get the current channel group + * @return group 0-8 + */ + uint8_t GetChannelGroup(); + + /** + * Add a channel to the channel plan + * EU868 allows additional channels to be added + * Channels 0-2 are fixed default channels + * + * @param index of the channel + * @param frequency of the channel or 0 to remove channel + * @param range of datarates allowed by the channel + * @return LORA_OK if channel was added + */ + uint8_t AddChannel(uint8_t index, uint32_t frequency, lora::DatarateRange range); + + /** + * Set network mode + * Choose Public LoRaWAN mode or Private Multitech mode + * + * Public mode uses 0x34 sync word with 5/6 second join windows + * Private mode uses 0x12 sync word with 1/2 second join windows + * US915/AU915 Rx1 and Rx2 are fixed per Channel Group setting + * + * @param mode public or private + * @return LORA_OK + */ + uint8_t SetNetworkMode(uint8_t mode); + + /** + * Get a pointer to the mac layer + * @return Mac mac + */ + Mac* GetMac(); + + /** + * Get a pointer to the radio + * Can be used to read radio registers or get a random value based on RSSI + * + * @return SxRadio pointer + */ + SxRadio* GetRadio(); + + /** + * Get the current statistics for the device + * @return Statistics + */ + Statistics& GetStats(); + + /** + * Get time on air with current settings for provided payload bytes + * 13 overhead bytes will be added to payload + * @param bytes of payload data + * @return time-on-air in ms + */ + uint32_t GetTimeOnAir(uint8_t bytes); + + /** + * Call before setting device in sleep mode to place radio in sleep + */ + void Sleep(); + + protected: + SxRadio1272* _radio; + Settings* _settings; + Mac* _mac; + + private: + ChannelPlan* _plan; + MoteEvents _events; + }; + +} +#endif
Binary file libmDot.ar has changed
--- a/mDot.h Tue Mar 29 10:25:31 2016 -0500 +++ b/mDot.h Thu Aug 04 15:11:24 2016 -0500 @@ -5,17 +5,16 @@ #include "mbed.h" #include "rtos.h" +#include "Mote.h" #include <vector> #include <map> #include <string> class mDotEvent; -class LoRaMacEvent; class LoRaConfig; -class LoRaMac; -class MdotRadio; class mDot { + friend class mDotEvent; private: @@ -27,6 +26,8 @@ __WFI(); } + void initLora(); + void setLastError(const std::string& str); static bool validateBaudRate(const uint32_t& baud); @@ -61,10 +62,11 @@ static mDot* _instance; - LoRaMac* _mac; - MdotRadio* _radio; - LoRaMacEvent* _events; + lora::Mote _mote; LoRaConfig* _config; + lora::Settings _settings; + mDotEvent* _events; + Thread _idle_thread; std::string _last_error; static const uint32_t _baud_rates[]; @@ -114,7 +116,7 @@ } mdot_ret_code; enum JoinMode { - MANUAL, + MANUAL = 0, OTA, AUTO_OTA, PEER_TO_PEER @@ -158,8 +160,11 @@ }; enum FrequencyBands { - FB_868, // EU868 - FB_915 // US915 + FB_868 = 0, + FB_915 = 1, + FB_EU868 = 0, // EU868 + FB_US915 = 1, // US915 + FB_AU915 = 2 }; enum FrequencySubBands { @@ -200,7 +205,7 @@ typedef struct { int16_t fd; - char name[30]; + char name[33]; uint32_t size; } mdot_file; @@ -210,6 +215,7 @@ uint32_t Joins; uint32_t JoinFails; uint32_t MissedAcks; + uint32_t CRCErrors; } mdot_stats; typedef struct { @@ -332,6 +338,10 @@ */ bool getStandbyFlag(); + std::vector<uint16_t> getChannelMask(); + + int32_t setChannelMask(uint8_t offset, uint16_t mask); + /** Add a channel frequencies currently in use * @returns MDOT_OK */ @@ -680,6 +690,42 @@ */ uint32_t setJoinDelay(uint8_t delay); + /** Get join Rx1 datarate offset + * defaults to 0 + * @returns offset + */ + uint8_t getJoinRx1DataRateOffset(); + + /** Set join Rx1 datarate offset + * @param offset for datarate + * @return MDOT_OK if success + */ + uint32_t setJoinRx1DataRateOffset(uint8_t offset); + + /** Get join Rx2 datarate + * defaults to US:DR8, AU:DR8, EU:DR0 + * @returns datarate + */ + uint8_t getJoinRx2DataRate(); + + /** Set join Rx2 datarate + * @param datarate + * @return MDOT_OK if success + */ + uint32_t setJoinRx2DataRate(uint8_t datarate); + + /** Get join Rx2 frequency + * defaults US:923.3, AU:923.3, EU:869.525 + * @returns frequency + */ + uint32_t getJoinRx2Frequency(); + + /** Set join Rx2 frequency + * @param frequency + * @return MDOT_OK if success + */ + uint32_t setJoinRx2Frequency(uint32_t frequency); + /** Get rx delay in seconds * Defaults to 1 second * @returns number of seconds before response message is expected @@ -712,11 +758,22 @@ */ bool getDataPending(); - /** Get transmitting + /** Get ack requested + * only valid after sending data to the gateway + * @returns true if server has requested ack + */ + bool getAckRequested(); + + /** Get is transmitting indicator * @returns true if currently transmitting */ bool getIsTransmitting(); + /** Get is idle indicator + * @returns true if not currently transmitting, waiting or receiving + */ + bool getIsIdle(); + /** Set TX data rate * data rates affect maximum payload size * @param dr SF_7 - SF_12|DR0-DR7 for Europe, SF_7 - SF_10 | DR0-DR4 for United States @@ -734,7 +791,6 @@ */ uint32_t getRadioRandom(); - /** Get data rate spreading factor and bandwidth * EU868 Datarates * --------------- @@ -795,6 +851,10 @@ */ bool getTxWait(); + /** Cancel pending rx windows + */ + void cancelRxWindow(); + /** Get time on air * @returns the amount of time (in ms) it would take to send bytes bytes based on current configuration */ @@ -869,6 +929,24 @@ */ int32_t send(const std::vector<uint8_t>& data, const bool& blocking = true, const bool& highBw = false); + /** Inject mac command + * @param data a vector containing mac commands + * @returns MDOT_OK + */ + int32_t injectMacCommand(const std::vector<uint8_t>& data); + + /** + * Clear MAC command buffer to be sent in next uplink + * @returns MDOT_OK + */ + int32_t clearMacCommands(); + + /** + * Get MAC command buffer to be sent in next uplink + * @returns command bytes + */ + std::vector<uint8_t> getMacCommands(); + /** Fetch data received from the gateway * this function only checks to see if a packet has been received - it does not open a receive window * send() must be called before recv() @@ -1104,7 +1182,6 @@ int32_t setFlowControl(const bool& on); bool getFlowControl(); - // get/set serial clear on error // if enabled the data read from the serial port will be discarded if it cannot be sent or if the send fails // set function returns MDOT_OK if success @@ -1113,8 +1190,26 @@ // MTS_RADIO_DEBUG_COMMANDS + /** Disable Duty cycle + * enables or disables the duty cycle limitations + * **** ONLY TO BE USED FOR TESTINGS PURPOSES **** + * **** ALL DEPLOYABLE CODE MUST ADHERE TO LOCAL REGULATIONS **** + * **** THIS SETTING WILL NOT BE SAVED TO CONFIGURATION ***** + * @param val true to disable duty-cycle (default:false) + */ + int32_t setDisableDutyCycle(bool val); + + /** Disable Duty cycle + * **** ONLY TO BE USED FOR TESTINGS PURPOSES **** + * **** ALL DEPLOYABLE CODE MUST ADHERE TO LOCAL REGULATIONS **** + * **** THIS SETTING WILL NOT BE SAVED TO CONFIGURATION ***** + * @return true if duty-cycle is disabled (default:false) + */ + uint8_t getDisableDutyCycle(); + void openRxWindow(uint32_t timeout, uint8_t bandwidth = 0); - void sendContinuous(); + void closeRxWindow(); + void sendContinuous(bool enable=true); int32_t setDeviceId(const std::vector<uint8_t>& id); int32_t setFrequencyBand(const uint8_t& band); bool saveProtectedConfig();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mDotEvent.h Thu Aug 04 15:11:24 2016 -0500 @@ -0,0 +1,297 @@ +#ifndef MDOT_EVENT_H +#define MDOT_EVENT_H + +#include "mDot.h" +#include "MacEvents.h" +#include "MTSLog.h" +#include "MTSText.h" + +typedef union { + uint8_t Value; + struct { + uint8_t :1; + uint8_t Tx :1; + uint8_t Rx :1; + uint8_t RxData :1; + uint8_t RxSlot :2; + uint8_t LinkCheck :1; + uint8_t JoinAccept :1; + } Bits; +} LoRaMacEventFlags; + +typedef enum { + LORAMAC_EVENT_INFO_STATUS_OK = 0, + LORAMAC_EVENT_INFO_STATUS_ERROR, + LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT, + LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT, + LORAMAC_EVENT_INFO_STATUS_RX_ERROR, + LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL, + LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL, + LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL, + LORAMAC_EVENT_INFO_STATUS_MIC_FAIL, +} LoRaMacEventInfoStatus; + +/*! + * LoRaMAC event information + */ +typedef struct { + LoRaMacEventInfoStatus Status; + lora::DownlinkControl Ctrl; + bool TxAckReceived; + uint8_t TxNbRetries; + uint8_t TxDatarate; + uint8_t RxPort; + uint8_t *RxBuffer; + uint8_t RxBufferSize; + int16_t RxRssi; + uint8_t RxSnr; + uint16_t Energy; + uint8_t DemodMargin; + uint8_t NbGateways; +} LoRaMacEventInfo; + +class mDotEvent: public lora::MacEvents { + public: + + mDotEvent() + : + LinkCheckAnsReceived(false), + DemodMargin(0), + NbGateways(0), + PacketReceived(false), + RxPort(0), + RxPayloadSize(0), + PongReceived(false), + PongRssi(0), + PongSnr(0), + AckReceived(false), + TxNbRetries(0) + { + memset(&_flags, 0, sizeof(LoRaMacEventFlags)); + memset(&_info, 0, sizeof(LoRaMacEventInfo)); + } + + virtual ~mDotEvent() { + } + + virtual void MacEvent(LoRaMacEventFlags *flags, LoRaMacEventInfo *info) { + if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) { + std::string msg = "OK"; + switch (info->Status) { + case LORAMAC_EVENT_INFO_STATUS_ERROR: + msg = "ERROR"; + break; + case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT: + msg = "TX_TIMEOUT"; + break; + case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT: + msg = "RX_TIMEOUT"; + break; + case LORAMAC_EVENT_INFO_STATUS_RX_ERROR: + msg = "RX_ERROR"; + break; + case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL: + msg = "JOIN_FAIL"; + break; + case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL: + msg = "DOWNLINK_FAIL"; + break; + case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL: + msg = "ADDRESS_FAIL"; + break; + case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL: + msg = "MIC_FAIL"; + break; + default: + break; + } + logTrace("Event: %s", msg.c_str()); + + logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d", + flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept); + logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d", + info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize, + info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways); + } + } + + virtual void TxDone(uint8_t dr) { + RxPayloadSize = 0; + LinkCheckAnsReceived = false; + PacketReceived = false; + AckReceived = false; + PongReceived = false; + + logDebug("mDotEvent - TxDone"); + memset(&_flags, 0, sizeof(LoRaMacEventFlags)); + memset(&_info, 0, sizeof(LoRaMacEventInfo)); + + _flags.Bits.Tx = 1; + _info.TxDatarate = dr; + _info.Status = LORAMAC_EVENT_INFO_STATUS_OK; + Notify(); + } + + void Notify() { + MacEvent(&_flags, &_info); + } + + virtual void TxTimeout(void) { + logDebug("mDotEvent - TxTimeout"); + + _flags.Bits.Tx = 1; + _info.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT; + Notify(); + } + + virtual void JoinAccept(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) { + logDebug("mDotEvent - JoinAccept"); + + _flags.Bits.Tx = 0; + _flags.Bits.JoinAccept = 1; + _info.Status = LORAMAC_EVENT_INFO_STATUS_OK; + Notify(); + } + + virtual void JoinFailed(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) { + logDebug("mDotEvent - JoinFailed"); + + _flags.Bits.Tx = 0; + _flags.Bits.JoinAccept = 1; + _info.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL; + Notify(); + } + + virtual void PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot, uint8_t retries = 0) { + logDebug("mDotEvent - PacketRx"); + RxPort = port; + PacketReceived = true; + + memcpy(RxPayload, payload, size); + RxPayloadSize = size; + + if (ctrl.Bits.Ack) { + AckReceived = true; + } + + if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) { + std::string packet = mts::Text::bin2hexString(RxPayload, size); + logTrace("Payload: %s", packet.c_str()); + } + + _flags.Bits.Tx = 0; + _flags.Bits.Rx = 1; + _flags.Bits.RxData = size > 0; + _flags.Bits.RxSlot = slot; + _info.RxBuffer = payload; + _info.RxBufferSize = size; + _info.RxPort = port; + _info.RxRssi = rssi; + _info.RxSnr = snr; + _info.TxAckReceived = AckReceived; + _info.TxAckReceived = retries; + _info.Status = LORAMAC_EVENT_INFO_STATUS_OK; + Notify(); + } + + virtual void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot) { + logDebug("mDotEvent - RxDone"); + } + + virtual void Pong(int16_t m_rssi, int8_t m_snr, int16_t s_rssi, int8_t s_snr) { + logDebug("mDotEvent - Pong"); + PongReceived = true; + PongRssi = s_rssi; + PongSnr = s_snr; + } + + virtual void NetworkLinkCheck(int16_t m_rssi, int8_t m_snr, int8_t s_snr, uint8_t s_gateways) { + logDebug("mDotEvent - NetworkLinkCheck"); + LinkCheckAnsReceived = true; + DemodMargin = s_snr; + NbGateways = s_gateways; + + _flags.Bits.Tx = 0; + _flags.Bits.LinkCheck = 1; + _info.RxRssi = m_rssi; + _info.RxSnr = m_snr; + _info.DemodMargin = s_snr; + _info.NbGateways = s_gateways; + _info.Status = LORAMAC_EVENT_INFO_STATUS_OK; + Notify(); + } + + virtual void RxTimeout(uint8_t slot) { + // logDebug("mDotEvent - RxTimeout"); + + _flags.Bits.Tx = 0; + _flags.Bits.RxSlot = slot; + _info.Status = LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT; + Notify(); + } + + virtual void RxError(uint8_t slot) { + logDebug("mDotEvent - RxError"); + + memset(&_flags, 0, sizeof(LoRaMacEventFlags)); + memset(&_info, 0, sizeof(LoRaMacEventInfo)); + + _flags.Bits.RxSlot = slot; + _info.Status = LORAMAC_EVENT_INFO_STATUS_RX_ERROR; + Notify(); + } + + virtual uint8_t MeasureBattery(void) { + return 255; + } + + bool LinkCheckAnsReceived; + uint8_t DemodMargin; + uint8_t NbGateways; + + bool PacketReceived; + uint8_t RxPort; + uint8_t RxPayload[255]; + uint8_t RxPayloadSize; + + bool PongReceived; + int16_t PongRssi; + int16_t PongSnr; + + bool AckReceived; + uint8_t TxNbRetries; + + LoRaMacEventFlags& Flags() { + return _flags; + } + LoRaMacEventInfo& Info() { + return _info; + } + + private: + + LoRaMacEventFlags _flags; + LoRaMacEventInfo _info; + +// +// /*! +// * MAC layer event callback prototype. +// * +// * \param [IN] flags Bit field indicating the MAC events occurred +// * \param [IN] info Details about MAC events occurred +// */ +// virtual void MacEvent(LoRaMacEventFlags *flags, LoRaMacEventInfo *info) { +// logDebug("mDotEvent"); +// +// if (flags->Bits.Rx) { +// logDebug("Rx"); +// +// // Event Object must delete RxBuffer +// delete[] info->RxBuffer; +// } +// } +// + +}; + +#endif // __MDOT_EVENT_H__