29#include "ns3/simulator.h"
46 TypeId(
"ns3::EndDeviceLorawanMac")
48 .SetGroupName(
"lorawan")
49 .AddTraceSource(
"RequiredTransmissions",
50 "Total number of transmissions required to deliver this packet",
52 "ns3::TracedValueCallback::uint8_t")
53 .AddAttribute(
"DataRate",
54 "Data rate currently employed by this end device",
57 MakeUintegerChecker<uint8_t>(0, 5))
58 .AddTraceSource(
"DataRate",
59 "Data rate currently employed by this end device",
61 "ns3::TracedValueCallback::uint8_t")
64 "Whether to request the network server to control this device's data rate",
68 .AddTraceSource(
"TxPower",
69 "Transmission power currently employed by this end device",
71 "ns3::TracedValueCallback::Double")
72 .AddTraceSource(
"LastKnownLinkMargin",
73 "Last known demodulation margin in "
74 "communications between this end device "
77 "ns3::TracedValueCallback::Double")
78 .AddTraceSource(
"LastKnownGatewayCount",
79 "Last known number of gateways able to "
80 "listen to this end device",
82 "ns3::TracedValueCallback::Int")
83 .AddTraceSource(
"AggregatedDutyCycle",
84 "Aggregate duty cycle, in fraction form, "
85 "this end device must respect",
87 "ns3::TracedValueCallback::Double")
88 .AddAttribute(
"MaxTransmissions",
89 "Maximum number of transmissions for a packet",
92 MakeIntegerChecker<uint8_t>())
93 .AddAttribute(
"EnableEDDataRateAdaptation",
94 "Whether the end device should up its data rate "
95 "in case it doesn't get a reply from the network server.",
99 .AddAttribute(
"MType",
100 "Specify type of message will be sent by this end device.",
107 .AddConstructor<EndDeviceLorawanMac>();
112 : m_enableDRAdapt(false),
118 m_headerDisabled(false),
122 m_receiveWindowDurationInSymbols(8),
124 m_controlDataRate(false),
125 m_lastKnownLinkMargin(0),
126 m_lastKnownGatewayCount(0),
127 m_aggregatedDutyCycle(1),
135 m_uniformRV = CreateObject<UniformRandomVariable>();
181 NS_LOG_INFO(
"Max number of transmission achieved: packet not transmitted.");
190 " The selected power is too high to be supported by this channel.");
202 NS_LOG_WARN(
"Attempting to send, but the aggregate duty cycle won't allow it. Scheduling a tx "
215 "Received a new packet from application. Resetting retransmission parameters.");
222 packet->AddHeader(frameHdr);
229 NS_LOG_WARN(
"Attempting to send a packet larger than the maximum allowed"
230 <<
" size at this Data Rate (DR" <<
unsigned(
m_dataRate)
231 <<
"). Transmission canceled.");
238 packet->AddHeader(macHdr);
248 NS_LOG_DEBUG(
" Received new packet from the application layer: stopping retransmission "
250 <<
unsigned(txs) <<
" transmissions out of a maximum of "
269 NS_LOG_DEBUG(
"It is a confirmed packet. Setting retransmission parameters and "
270 "decreasing the number of transmissions left.");
296 packet->RemoveHeader(macHdr);
297 packet->RemoveHeader(frameHdr);
302 packet->AddHeader(frameHdr);
309 packet->AddHeader(macHdr);
348 NS_LOG_INFO(
"The message is an ACK, not waiting for it anymore.");
350 NS_LOG_DEBUG(
"Reset retransmission variables to default values and cancel "
351 "retransmission if already scheduled.");
356 <<
unsigned(txs) <<
" transmissions: stopping retransmission procedure. ");
364 "Received downlink message not containing an ACK while we were waiting for it!");
368 std::list<Ptr<MacCommand>> commands = frameHeader.
GetCommands();
369 std::list<Ptr<MacCommand>>::iterator it;
370 for (it = commands.begin(); it != commands.end(); it++)
383 OnLinkCheckAns(linkCheckAns->GetMargin(), linkCheckAns->GetGwCnt());
395 linkAdrReq->GetTxPower(),
396 linkAdrReq->GetEnabledChannelsList(),
397 linkAdrReq->GetRepetitions());
442 newChannelReq->GetFrequency(),
443 newChannelReq->GetMinDataRate(),
444 newChannelReq->GetMaxDataRate());
525 std::vector<Ptr<LogicalLoraChannel>> logicalChannels;
533 std::vector<Ptr<LogicalLoraChannel>>::iterator it;
534 for (it = logicalChannels.begin(); it != logicalChannels.end(); ++it)
538 double frequency = logicalChannel->GetFrequency();
542 NS_LOG_DEBUG(
"Waiting time before the next transmission in channel with frequency "
543 << frequency <<
" is = " << waitingTime.
GetSeconds() <<
".");
557 std::vector<Ptr<LogicalLoraChannel>> logicalChannels;
560 logicalChannels =
Shuffle(logicalChannels);
563 std::vector<Ptr<LogicalLoraChannel>>::iterator it;
564 for (it = logicalChannels.begin(); it != logicalChannels.end(); ++it)
568 double frequency = logicalChannel->GetFrequency();
570 NS_LOG_DEBUG(
"Frequency of the current channel: " << frequency);
584 NS_LOG_DEBUG(
"Packet cannot be immediately transmitted on "
585 <<
"the current channel because of duty cycle limitations.");
591std::vector<Ptr<LogicalLoraChannel>>
596 int size = vector.size();
598 for (
int i = 0; i < size; ++i)
602 vector.at(random) = vector.at(i);
697 std::list<int> enabledChannels,
700 NS_LOG_FUNCTION(
this <<
unsigned(dataRate) <<
unsigned(txPower) << repetitions);
703 bool channelMaskOk =
true;
704 bool dataRateOk =
true;
705 bool txPowerOk =
true;
711 int channelListSize = channelList.size();
713 for (
auto it = enabledChannels.begin(); it != enabledChannels.end(); it++)
715 if ((*it) > channelListSize)
717 channelMaskOk =
false;
731 if (sf == 0 || bw == 0)
740 if (dataRateOk && channelMaskOk)
742 bool foundAvailableChannel =
false;
743 for (
auto it = enabledChannels.begin(); it != enabledChannels.end(); it++)
745 NS_LOG_DEBUG(
"MinDR: " <<
unsigned(channelList.at(*it)->GetMinimumDataRate()));
746 NS_LOG_DEBUG(
"MaxDR: " <<
unsigned(channelList.at(*it)->GetMaximumDataRate()));
747 if (channelList.at(*it)->GetMinimumDataRate() <= dataRate &&
748 channelList.at(*it)->GetMaximumDataRate() >= dataRate)
750 foundAvailableChannel =
true;
755 if (!foundAvailableChannel)
771 <<
"ChannelMaskOk: " << channelMaskOk <<
", "
772 <<
"DataRateOk: " << dataRateOk <<
", "
773 <<
"txPowerOk: " << txPowerOk);
777 if (channelMaskOk && dataRateOk && txPowerOk)
782 if (std::find(enabledChannels.begin(), enabledChannels.end(), i) !=
783 enabledChannels.end())
804 m_macCommandList.emplace_back(CreateObject<LinkAdrAns>(txPowerOk, dataRateOk, channelMaskOk));
813 NS_ASSERT(0 <= dutyCycle && dutyCycle < 1);
842 uint8_t battery = 10;
858 bool dataRateRangeOk =
true;
859 bool channelFrequencyOk =
true;
867 m_macCommandList.emplace_back(CreateObject<NewChannelAns>(dataRateRangeOk, channelFrequencyOk));
892 NS_LOG_FUNCTION(
this <<
unsigned(chIndex) << frequency <<
unsigned(minDataRate)
893 <<
unsigned(maxDataRate));
897 CreateObject<LogicalLoraChannel>(frequency, minDataRate, maxDataRate));
904 double maxTxPowerDbm)
Hold variables of type enum.
An identifier for simulation events.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Hold a signed integer type.
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.
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
static Time Now()
Return the current simulation virtual time.
Simulation virtual time values and global simulation resolution.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
Implementation of the DevStatusReq LoRaWAN MAC command.
Implementation of the DutyCycleReq LoRaWAN MAC command.
LorawanMacHeader::MType m_mType
The message type to apply to packets sent with the Send method.
uint8_t m_maxNumbTx
Default number of unacknowledged redundant transmissions of each packet.
TracedValue< int > m_lastKnownGatewayCount
The last known gateway count (i.e., gateways that are in communication range with this end device).
bool GetDataRateAdaptation() const
Get if data rate adaptation is enabled or not.
void SetLogicalChannel(uint8_t chIndex, double frequency, uint8_t minDataRate, uint8_t maxDataRate)
Set a new logical channel in the helper.
void FailedReception(Ptr< const Packet > packet) override
Function called by lower layers to inform this layer that reception of a packet we were locked on fai...
virtual void OnRxClassParamSetupReq(Ptr< RxParamSetupReq > rxParamSetupReq)
Perform the actions that need to be taken when receiving a RxParamSetupReq command based on the Devic...
void AddSubBand(double startFrequency, double endFrequency, double dutyCycle, double maxTxPowerDbm)
Add a subband to the logical channel helper.
bool m_controlDataRate
Whether this device's data rate should be controlled by the network server.
~EndDeviceLorawanMac() override
Destructor.
virtual void postponeTransmission(Time nextTxDelay, Ptr< Packet > packet)
Postpone transmission to the specified time and delete previously scheduled transmissions if present.
virtual void SendToPhy(Ptr< Packet > packet)
Add headers and send a packet with the sending function of the physical layer.
Ptr< LogicalLoraChannel > GetChannelForTx()
Find a suitable channel for transmission.
void OnDutyCycleReq(double dutyCycle)
Perform the actions that need to be taken when receiving a DutyCycleReq command.
TracedValue< double > m_txPower
The transmission power this device is using to transmit.
bool m_enableDRAdapt
Enable data rate adaptation (ADR) during the retransmission procedure.
void TxFinished(Ptr< const Packet > packet) override
Perform the actions that are required after a packet send.
Ptr< UniformRandomVariable > m_uniformRV
An uniform random variable, used by the Shuffle method to randomly reorder the channel list.
void OnRxParamSetupReq(Ptr< RxParamSetupReq > rxParamSetupReq)
Perform the actions that need to be taken when receiving a RxParamSetupReq command.
static TypeId GetTypeId()
Register this type.
TracedValue< double > m_aggregatedDutyCycle
The aggregated duty cycle this device needs to respect across all sub-bands.
double GetAggregatedDutyCycle()
**
void Receive(Ptr< const Packet > packet) override
Receive a packet.
void SetMType(LorawanMacHeader::MType mType)
Set the message type to send when the Send method is called.
virtual void resetRetransmissionParameters()
Reset retransmission parameters contained in the structure LoraRetxParams.
virtual Time GetNextClassTransmissionDelay(Time waitingTime)
Find the minimum waiting time before the next possible transmission based on end device's Class Type.
void ParseCommands(LoraFrameHeader frameHeader)
Parse and take action on the commands contained on this FrameHeader.
void ApplyNecessaryOptions(LoraFrameHeader &frameHeader)
Add the necessary options and MAC commands to the LoraFrameHeader.
TracedCallback< uint8_t, bool, Time, Ptr< Packet > > m_requiredTxCallback
The trace source fired when the transmission procedure is finished.
virtual uint8_t GetTransmissionPower()
Get the transmission power this end device is set to use.
uint8_t GetMaxNumberOfTransmissions()
Get the max number of unacknowledged redundant transmissions of each packet.
void SetDataRateAdaptation(bool adapt)
Enable data rate adaptation in the retransmitting procedure.
void OnLinkCheckAns(uint8_t margin, uint8_t gwCnt)
Perform the actions that need to be taken when receiving a LinkCheckAns command.
EventId m_nextTx
The event of retransmitting a packet in a consecutive moment if an ACK is not received.
void OnLinkAdrReq(uint8_t dataRate, uint8_t txPower, std::list< int > enabledChannels, int repetitions)
Perform the actions that need to be taken when receiving a LinkAdrReq command.
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 address of this device.
void Send(Ptr< Packet > packet) override
Send a packet.
uint16_t m_currentFCnt
current value of the device frame counter.
EndDeviceLorawanMac()
Default constructor.
void AddMacCommand(Ptr< MacCommand > macCommand)
Add a MAC command to the list of those that will be sent out in the next packet.
void SetMaxNumberOfTransmissions(uint8_t maxNumbTx)
Set the max number of unacknowledged redundant transmissions of each packet.
TracedValue< double > m_lastKnownLinkMargin
The last known link margin.
void AddLogicalChannel(double frequency)
Add a logical channel to the helper.
Time GetNextTransmissionDelay()
Find the base minimum waiting time before the next possible transmission.
std::vector< Ptr< LogicalLoraChannel > > Shuffle(std::vector< Ptr< LogicalLoraChannel > > vector)
Randomly shuffle a Ptr<LogicalLoraChannel> vector.
LorawanMacHeader::MType GetMType()
Get the message type to send when the Send method is called.
virtual void DoSend(Ptr< Packet > packet)
Checking if we are performing the transmission of a new packet or a retransmission,...
void OnDevStatusReq()
Perform the actions that need to be taken when receiving a DevStatusReq command.
LoraDeviceAddress GetDeviceAddress()
Get the network address of this device.
void OnNewChannelReq(uint8_t chIndex, double frequency, uint8_t minDataRate, uint8_t maxDataRate)
Perform the actions that need to be taken when receiving a NewChannelReq command.
void SetDataRate(uint8_t dataRate)
Set the data rate this end device will use when transmitting.
uint8_t GetDataRate()
Get the data rate this end device is set to use.
void SetDeviceAddress(LoraDeviceAddress address)
Set the network address of this device.
struct LoraRetxParameters m_retxParams
Structure containing the retransmission parameters for this device.
Implementation of the LinkAdrReq LoRaWAN MAC command.
Implementation of the LinkCheckAns LoRaWAN MAC command.
double GetTxPowerForChannel(Ptr< LogicalLoraChannel > logicalChannel)
Returns the maximum transmission power [dBm] that is allowed on a channel.
void SetChannel(uint8_t chIndex, Ptr< LogicalLoraChannel > logicalChannel)
Set a new channel at a fixed index.
std::vector< Ptr< LogicalLoraChannel > > GetChannelList()
Get the list of LogicalLoraChannels currently registered on this helper.
std::vector< Ptr< LogicalLoraChannel > > GetEnabledChannelList()
Get the list of LogicalLoraChannels currently registered on this helper that have been enabled for Up...
void AddSubBand(double firstFrequency, double lastFrequency, double dutyCycle, double maxTxPowerDbm)
Add a new SubBand to this helper.
Time GetWaitingTime(Ptr< LogicalLoraChannel > channel)
Get the time it is necessary to wait for before transmitting on a given channel.
void AddChannel(double frequency)
Add a new channel to the list.
This class represents the device address of a LoraWAN end device.
Class representing the LoRaWAN MAC layer.
TracedCallback< Ptr< const Packet > > m_cannotSendBecauseDutyCycle
The trace source that is fired when a packet cannot be sent because of duty cycle limitations.
std::vector< uint32_t > m_maxAppPayloadForDataRate
A vector holding the maximum app payload size that corresponds to a certain data rate.
double GetDbmForTxPower(uint8_t txPower)
Get the transmission power in dBm that corresponds, in this region, to the encoded 8-bit txPower.
uint8_t GetSfFromDataRate(uint8_t dataRate)
Get the spreading factor corresponding to a data rate, based on this MAC's region.
double GetBandwidthFromDataRate(uint8_t dataRate)
Get the bandwidth corresponding to a data rate, based on this MAC's region.
LogicalLoraChannelHelper m_channelHelper
The LogicalLoraChannelHelper instance that is assigned to this MAC.
TracedCallback< Ptr< const Packet > > m_sentNewPacket
Trace source that is fired when a new APP layer packet arrives at the MAC layer.
static uint8_t GetCIDFromMacCommand(enum MacCommandType commandType)
Get the CID that corresponds to a type of MAC command.
Implementation of the NewChannelReq LoRaWAN MAC command.
Implementation of the RxParamSetupReq LoRaWAN MAC command.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
#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.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time Seconds(double value)
Construct a Time in the indicated unit.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
MacCommandType
Enum for every possible command type.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Structure representing the parameters that will be used in the retransmission procedure.
bool waitingAck
Whether the packet requires explicit acknowledgment.
uint8_t retxLeft
Number of retransmission attempts left.
Time firstAttempt
Timestamp of the first transmission of the packet.
Ptr< Packet > packet
A pointer to the packet being retransmitted.