18#include "ns3/simulator.h"
32 static TypeId tid =
TypeId(
"ns3::ClassAEndDeviceLorawanMac")
34 .SetGroupName(
"lorawan")
93 NS_LOG_WARN(
"Attempting to send when device is still busy, postponed by 5s.");
115 auto ldro = bool((sf == 11 || sf == 12) && bw == 125'000);
119 params.spreadingFactor = sf;
120 params.bandwidthHz = bw;
122 params.lowDataRateOptimize = ldro;
125 params.crcEnabled =
true;
154 "Busy PHY device (not in SLEEP or STANDBY state): phyState=" << phyState);
167 "Unexpected PHY state on TX conclusion: phyState=" << phyState);
187 "Unexpected PHY state on RX1 opening: phyState=" << phyState);
193 <<
", rx1DataRate=" <<
unsigned(rx1DataRate));
212 "Unexpected PHY state on RX1 closure: phyState=" << phyState);
224 "Unexpected PHY state on RX2 opening: phyState=" << phyState);
234 <<
", m_secondReceiveWindowDataRate="
254 "Unexpected PHY state on RX2 closure: phyState=" << phyState);
268 bool recv = (outcome ==
RECV || outcome ==
ACK);
270 bool gotAck = (outcome ==
ACK);
272 NS_LOG_DEBUG(
"recv=" << recv <<
", needsAck=" << needsAck <<
", gotAck=" << gotAck
273 <<
", canReTx=" << canReTx);
277 if ((!recv || (needsAck && !gotAck)) && canReTx)
281 NS_LOG_DEBUG(
"Received packet without ACK: rescheduling transmission.");
283 else if (outcome ==
FAIL)
285 NS_LOG_DEBUG(
"Reception failed: rescheduling transmission.");
287 else if (outcome ==
NONE)
289 NS_LOG_DEBUG(
"No reception initiated by PHY: rescheduling transmission.");
292 double retransmitTimeout =
m_uniformRV->GetValue(1, 3);
300 if (recv && needsAck && gotAck)
304 <<
unsigned(txs) <<
" transmissions: stopping retransmission process");
308 else if (needsAck && !gotAck && !canReTx)
311 NS_LOG_DEBUG(
"Ack failure: no more retransmission opportunities. Used "
312 <<
unsigned(txs) <<
" transmissions.");
336 "Unexpected PHY state on RX end: phyState=" << phyState);
343 packetCopy->RemoveHeader(mHdr);
349 packetCopy->RemoveHeader(fHdr);
357 NS_LOG_DEBUG(
"The message is intended for another recipient.");
377 packet->PeekPacketTag(tag);
403 "Unexpected PHY state on RX end: phyState=" << phyState);
427 bool rx1DrOffsetAck =
true;
428 bool rx2DataRateAck =
true;
429 bool channelAck =
true;
434 rx1DrOffsetAck =
false;
440 rx2DataRateAck =
false;
449 if (rx1DrOffsetAck && rx2DataRateAck && channelAck)
An identifier for simulation events.
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Simulation virtual time values and global simulation resolution.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Class representing the MAC layer of a Class A LoRaWAN device.
uint8_t m_rx1DrOffset
The RX1DROffset parameter value.
uint32_t m_firstReceiveWindowFrequencyHz
The frequency [Hz] to listen on for the first receive window.
void OpenSecondReceiveWindow()
Perform operations needed to open the second receive window.
uint8_t GetSecondReceiveWindowDataRate() const
Get the data rate that will be used in the second receive window.
Time m_receiveDelay2
The interval between when a packet is done sending and when the second receive window is opened.
ClassAEndDeviceLorawanMac()
Default constructor.
static TypeId GetTypeId()
Register this type.
void FailedReception(Ptr< const Packet > packet) override
Inform this layer that reception of a packet we were locked on failed.
uint32_t GetSecondReceiveWindowFrequency() const
Get the frequency that is used for the second receive window.
RxOutcome
Set of possible outcomes of a reception window.
@ NONE
Reception window timed out.
@ FAIL
Reception initiated but failed.
@ ACK
Correctly received a network acknowledgement.
@ RECV
Correctly received a downlink packet (no ACK).
Time GetNextClassTransmissionDelay() const override
Find the minimum wait time before the next possible transmission based on end device's Class Type sch...
void SetSecondReceiveWindowFrequency(uint32_t frequencyHz)
Set the frequency that will be used for the second receive window.
bool m_busy
Whether the MAC layer is currently busy with in the LoRaWAN Class A process of transmitting an uplink...
uint8_t m_secondReceiveWindowDataRate
The data rate to listen for during the second downlink transmission.
Time m_receiveDelay1
The interval between when a packet is done sending and when the first receive window is opened.
void CloseFirstReceiveWindow()
Perform operations needed to close the first receive window.
void SendToPhy(Ptr< Packet > packet) override
Gather PHY transmission parameters and send a packet through the LoRa physical layer.
uint32_t m_secondReceiveWindowFrequencyHz
The frequency [Hz] to listen on for the second receive window.
void TxFinished(Ptr< const Packet > packet) override
Perform actions after sending a packet.
void CloseSecondReceiveWindow()
Perform operations needed to close the second receive window.
void OnRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequencyHz) override
Perform the actions that need to be taken when receiving a RxParamSetupReq command based on the Devic...
uint8_t GetFirstReceiveWindowDataRate()
Get the data rate that will be used in the first receive window.
void ManageRetransmissions(RxOutcome outcome)
Decide whether we can retransmit based on reception outcome.
EventId m_secondReceiveWindow
The event of the second receive window opening, used to cancel the second window in case the first on...
void SetSecondReceiveWindowDataRate(uint8_t dataRate)
Set the data rate to be used in the second receive window.
void Receive(Ptr< const Packet > packet) override
Receive a packet from the lower layer.
~ClassAEndDeviceLorawanMac() override
Destructor.
void OpenFirstReceiveWindow()
Perform operations needed to open the first receive window.
@ RX_ACTIVE
The PHY layer is actively receiving a transmission after locking onto a preamble.
@ SLEEP
The PHY layer is in low-power sleep state.
@ STANDBY
The PHY layer is in standby mode.
Ptr< LogicalLoraChannel > GetRandomChannelForTx()
Find a suitable channel for transmission.
bool m_headerDisabled
Whether or not the LoRa PHY header is disabled for communications by this device.
TracedValue< double > m_txPowerDbm
The transmission ERP [dBm] this device is currently using.
void PostponeTransmission(Time nextTxDelay, Ptr< Packet > packet)
Postpone transmission to the specified time.
TracedCallback< uint8_t, bool, Time, Ptr< Packet > > m_confirmedTxOutcomeCallback
Traced Callback: confirmed transmission process outcome event.
Ptr< UniformRandomVariable > m_uniformRV
An uniform random variable, used to randomly pick from the channel list and to sample random retransm...
uint16_t m_adrAckCnt
ADRACKCnt counter of the number of consecutive uplinks without downlink reply from the server.
void ApplyMACCommands(LoraFrameHeader frameHeader)
Take action on the commands contained on this FrameHeader.
CodingRate m_codingRate
The coding rate used by this device.
EventId m_nextTx
The event of transmitting a packet at a later moment.
std::list< Ptr< MacCommand > > m_macCommandList
List of the MAC commands that need to be applied to the next UL packet.
TracedValue< uint8_t > m_dataRate
The data rate this device is using to transmit.
LoraDeviceAddress m_address
The LoRaWAN address of this device.
PacketTxContext m_txContext
Structure containing the transmission context for the last packet sent by this device,...
EndDeviceLorawanMac()
Default constructor.
double m_lastRxSnr
Record latest reception SNR measurement to provide via DevStatusAns.
uint8_t m_nbTrans
Default number of repeated transmissions of each packet.
uint8_t m_receiveWindowDurationInSymbols
The duration of reception windows in number of symbols.
uint16_t m_fCnt
Current value of the uplink frame counter.
static Time GetTimeOnAir(uint32_t phyPayloadLen, const LoraTxParameters &txParams)
Compute the total transmission time for a physical packet based on modulation parameters.
Tag used to save various data about a packet, like its Spreading Factor and data about interference.
double GetReceivePower() const
Read the power this packet arrived with.
TracedCallback< Ptr< const Packet > > m_receivedPacket
Trace source that is fired when a packet reaches the MAC layer.
ReplyDataRateMatrix m_replyDataRateMatrix
The matrix that decides the data rate the gateway will use in a reply based on the end device's sendi...
uint32_t GetBandwidthFromDataRate(uint8_t dataRate) const
Get the bandwidth corresponding to a data rate, based on this MAC's region.
uint8_t GetSfFromDataRate(uint8_t dataRate) const
Get the spreading factor corresponding to a data rate, based on this MAC's region.
Ptr< LogicalLoraChannelHelper > m_channelHelper
The LogicalLoraChannelHelper instance that is assigned to this MAC.
ReceiveCallback m_receiveCallback
! Callback to forward to upper layers
Ptr< LoraPhy > m_phy
The PHY instance that sits under this MAC layer.
int m_nPreambleSymbols
The number of symbols to use in the PHY preamble.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
@ DOWN
Downlink / Downchirp / Inverted polarity.
@ UP
Uplink / Upchirp / Normal polarity.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Time Seconds(double value)
Construct a Time in the indicated unit.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Structure to collect all parameters that are used to compute the duration of a packet (excluding payl...