lorawan-mac-end-device.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2017 University of Padova
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Davide Magrin <magrinda@dei.unipd.it>
19  * Martina Capuzzo <capuzzom@dei.unipd.it>
20  *
21  * Modified by: Peggy Anderson <peggy.anderson@usask.ca>
22  * Bastien Tauran <bastien.tauran@viveris.fr>
23  */
24 
25 #include "lorawan-mac-end-device.h"
26 
27 #include "lora-tag.h"
29 #include "satellite-phy.h"
30 #include "satellite-time-tag.h"
31 
32 #include <ns3/ipv4-header.h>
33 #include <ns3/log.h>
34 #include <ns3/simulator.h>
35 
36 #include <algorithm>
37 
38 namespace ns3
39 {
40 
41 NS_LOG_COMPONENT_DEFINE("LorawanMacEndDevice");
42 
43 NS_OBJECT_ENSURE_REGISTERED(LorawanMacEndDevice);
44 
45 TypeId
47 {
48  static TypeId tid =
49  TypeId("ns3::LorawanMacEndDevice")
50  .SetParent<LorawanMac>()
51  .AddTraceSource("RequiredTransmissions",
52  "Total number of transmissions required to deliver this packet",
53  MakeTraceSourceAccessor(&LorawanMacEndDevice::m_requiredTxCallback),
54  "ns3::TracedValueCallback::uint8_t")
55  .AddAttribute("DataRate",
56  "Data Rate currently employed by this end device",
57  UintegerValue(0),
58  MakeUintegerAccessor(&LorawanMacEndDevice::m_dataRate),
59  MakeUintegerChecker<uint8_t>(0, 5))
60  .AddTraceSource("DataRate",
61  "Data Rate currently employed by this end device",
62  MakeTraceSourceAccessor(&LorawanMacEndDevice::m_dataRate),
63  "ns3::TracedValueCallback::uint8_t")
64  .AddAttribute("DRControl",
65  "Whether to request the NS to control this device's Data Rate",
66  BooleanValue(),
67  MakeBooleanAccessor(&LorawanMacEndDevice::m_controlDataRate),
68  MakeBooleanChecker())
69  .AddTraceSource("TxPower",
70  "Transmission power currently employed by this end device",
71  MakeTraceSourceAccessor(&LorawanMacEndDevice::m_txPower),
72  "ns3::TracedValueCallback::Double")
73  .AddTraceSource("LastKnownLinkMargin",
74  "Last known demodulation margin in "
75  "communications between this end device "
76  "and a gateway",
77  MakeTraceSourceAccessor(&LorawanMacEndDevice::m_lastKnownLinkMargin),
78  "ns3::TracedValueCallback::Double")
79  .AddTraceSource("LastKnownGatewayCount",
80  "Last known number of gateways able to "
81  "listen to this end device",
82  MakeTraceSourceAccessor(&LorawanMacEndDevice::m_lastKnownGatewayCount),
83  "ns3::TracedValueCallback::Int")
84  .AddTraceSource("AggregatedDutyCycle",
85  "Aggregate duty cycle, in fraction form, "
86  "this end device must respect",
87  MakeTraceSourceAccessor(&LorawanMacEndDevice::m_aggregatedDutyCycle),
88  "ns3::TracedValueCallback::Double")
89  .AddAttribute("MaxTransmissions",
90  "Maximum number of transmissions for a packet",
91  IntegerValue(8),
92  MakeIntegerAccessor(&LorawanMacEndDevice::m_maxNumbTx),
93  MakeIntegerChecker<uint8_t>())
94  .AddAttribute("EnableEDDataRateAdaptation",
95  "Whether the End Device should up its Data Rate "
96  "in case it doesn't get a reply from the NS.",
97  BooleanValue(false),
98  MakeBooleanAccessor(&LorawanMacEndDevice::m_enableDRAdapt),
99  MakeBooleanChecker())
100  .AddAttribute("MType",
101  "Specify type of message will be sent by this ED.",
103  MakeEnumAccessor(&LorawanMacEndDevice::m_mType),
105  "Unconfirmed",
107  "Confirmed"));
108  return tid;
109 }
110 
112 {
113  NS_FATAL_ERROR("Default constructor not in use");
114 }
115 
116 LorawanMacEndDevice::LorawanMacEndDevice(uint32_t satId, uint32_t beamId)
117  : LorawanMac(satId, beamId),
118  m_enableDRAdapt(false),
119  m_maxNumbTx(8),
120  m_dataRate(0),
121  m_txPower(14),
122  m_codingRate(4.0 / 5),
123  // LoraWAN default
124  m_headerDisabled(0),
125  // LoraWAN default
126  m_address(LoraDeviceAddress(0)),
127  // LoraWAN default
128  m_receiveWindowDurationInSymbols(8),
129  m_gatewayUpdateCallback(),
130  // LoraWAN default
131  m_controlDataRate(false),
132  m_lastKnownLinkMargin(0),
133  m_lastKnownGatewayCount(0),
134  m_aggregatedDutyCycle(1),
135  m_mType(LorawanMacHeader::CONFIRMED_DATA_UP),
136  m_currentFCnt(0)
137 
138 {
139  NS_LOG_FUNCTION(this);
140 
141  // Initialize the random variable we'll use to decide which channel to
142  // transmit on.
143  m_uniformRV = CreateObject<UniformRandomVariable>();
144 
145  // Void the transmission event
146  m_nextTx = EventId();
147  m_nextTx.Cancel();
148 
149  // Initialize structure for retransmission parameters
152 }
153 
155 {
156  NS_LOG_FUNCTION_NOARGS();
157 }
158 
160 // Sending methods //
162 
163 void
164 LorawanMacEndDevice::Send(Ptr<Packet> packet)
165 {
166  NS_LOG_FUNCTION(this << packet);
167 
168  // If it is not possible to transmit now because of the duty cycle,
169  // or because we are receiving, schedule a tx/retx later
170  Time netxTxDelay = GetNextTransmissionDelay();
171  if (netxTxDelay != Seconds(0))
172  {
173  postponeTransmission(netxTxDelay, packet);
174  return;
175  }
176 
177  // Pick a channel on which to transmit the packet
178  Ptr<LoraLogicalChannel> txChannel = GetChannelForTx();
179 
180  if (!(txChannel && m_retxParams.retxLeft > 0))
181  {
182  if (!txChannel)
183  {
184  NS_LOG_INFO("Cannot send because of duty cycle.");
186  }
187  else
188  {
189  NS_LOG_INFO("Max number of transmission achieved: packet not transmitted.");
190  }
191  }
192  else
193  // the transmitting channel is available and we have not run out the maximum number of
194  // retransmissions
195  {
196  // Make sure we can transmit at the current power on this channel
197  NS_ASSERT_MSG(m_txPower <= m_channelHelper.GetTxPowerForChannel(txChannel),
198  " The selected power is too hight to be supported by this channel.");
199  DoSend(packet);
200  }
201 }
202 
203 void
204 LorawanMacEndDevice::postponeTransmission(Time netxTxDelay, Ptr<Packet> packet)
205 {
206  NS_LOG_FUNCTION(this);
207  // Delete previously scheduled transmissions if any.
208  Simulator::Cancel(m_nextTx);
209  m_nextTx = Simulator::Schedule(netxTxDelay, &LorawanMacEndDevice::DoSend, this, packet);
210  NS_LOG_WARN("Attempting to send, but the aggregate duty cycle won't allow it. Scheduling a tx "
211  "at a delay "
212  << netxTxDelay.GetSeconds() << ".");
213 }
214 
215 void
216 LorawanMacEndDevice::DoSend(Ptr<Packet> packet)
217 {
218  NS_LOG_FUNCTION(this);
219  // Checking if this is the transmission of a new packet
220  if (packet != m_retxParams.packet)
221  {
222  NS_LOG_DEBUG(
223  "Received a new packet from application. Resetting retransmission parameters.");
224  m_currentFCnt++;
225  NS_LOG_DEBUG("APP packet: " << packet << ".");
226 
227  // Check that MACPayload length is below the allowed maximum
228  if (packet->GetSize() > m_maxAppPayloadForDataRate.at(m_dataRate))
229  {
230  NS_LOG_WARN("Attempting to send a packet larger than the maximum allowed"
231  << " size at this DataRate (DR" << unsigned(m_dataRate)
232  << "). Transmission canceled. ");
233  return;
234  }
235 
236  // Add the Lora Frame Header to the packet
237  LoraFrameHeader frameHdr;
238  ApplyNecessaryOptions(frameHdr);
239  packet->AddHeader(frameHdr);
240  NS_LOG_INFO("Added frame header of size " << frameHdr.GetSerializedSize() << " bytes.");
241 
242  // Add the Lora Mac header to the packet
243  LorawanMacHeader macHdr;
244  ApplyNecessaryOptions(macHdr);
245  packet->AddHeader(macHdr);
246 
247  // Reset MAC command list
248  m_macCommandList.clear();
249 
251  {
252  // Call the callback to notify about the failure
253  uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
255  NS_LOG_DEBUG(" Received new packet from the application layer: stopping retransmission "
256  "procedure. Used "
257  << unsigned(txs) << " transmissions out of a maximum of "
258  << unsigned(m_maxNumbTx) << ".");
259  }
260 
261  // Reset retransmission parameters
263 
264  // If this is the first transmission of a confirmed packet, save parameters for the
265  // (possible) next retransmissions.
267  {
268  m_retxParams.packet = packet->Copy();
270  m_retxParams.waitingAck = true;
271  m_retxParams.firstAttempt = Simulator::Now();
273  m_retxParams.retxLeft - 1; // decreasing the number of retransmissions
274 
275  NS_LOG_DEBUG("Message type is " << m_mType);
276  NS_LOG_DEBUG("It is a confirmed packet. Setting retransmission parameters and "
277  "decreasing the number of transmissions left.");
278 
279  // Sent a new packet
280  NS_LOG_DEBUG("Copied packet: " << m_retxParams.packet);
282 
284  }
285  else
286  {
287  m_sentNewPacket(packet);
288  SendToPhy(packet);
289  }
290  }
291  // this is a retransmission
292  else
293  {
294  // Removing SatPhyTimeTag if it exists
295  SatPhyTimeTag satPhyTimeTag;
296  packet->RemovePacketTag(satPhyTimeTag);
297  SatPhyLinkTimeTag satPhyLinkTimeTag;
298  packet->RemovePacketTag(satPhyLinkTimeTag);
300  {
301  // Remove the headers
302  LorawanMacHeader macHdr;
303  LoraFrameHeader frameHdr;
304  packet->RemoveHeader(macHdr);
305  packet->RemoveHeader(frameHdr);
306 
307  // Add the Lora Frame Header to the packet
308  frameHdr = LoraFrameHeader();
309  ApplyNecessaryOptions(frameHdr);
310  packet->AddHeader(frameHdr);
311 
312  NS_LOG_INFO("Added frame header of size " << frameHdr.GetSerializedSize() << " bytes.");
313 
314  // Add the Lorawan Mac header to the packet
315  macHdr = LorawanMacHeader();
316  ApplyNecessaryOptions(macHdr);
317  packet->AddHeader(macHdr);
319  m_retxParams.retxLeft - 1; // decreasing the number of retransmissions
320  NS_LOG_DEBUG("Retransmitting an old packet.");
321 
323  }
324  }
325 }
326 
327 void
329 {
330 }
331 
333 // Receiving methods //
335 
336 void
338  Ptr<SatSignalParameters> /*rxParams*/)
339 {
340  Ptr<Packet> packet;
341  for (SatPhy::PacketContainer_t::iterator i = packets.begin(); i != packets.end(); i++)
342  {
343  Receive(*i);
344  }
345 }
346 
347 void
348 LorawanMacEndDevice::FailedReception(Ptr<const Packet> packet)
349 {
350 }
351 
352 void
354 {
355  NS_LOG_FUNCTION(this << frameHeader);
356 
358  {
359  if (frameHeader.GetAck())
360  {
361  NS_LOG_INFO("The message is an ACK, not waiting for it anymore.");
362 
363  NS_LOG_DEBUG("Reset retransmission variables to default values and cancel "
364  "retransmission if already scheduled.");
365 
366  uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
368  NS_LOG_DEBUG("Received ACK packet after "
369  << unsigned(txs) << " transmissions: stopping retransmission procedure. ");
370 
371  // Reset retransmission parameters
373  }
374  else
375  {
376  NS_LOG_ERROR(
377  "Received downlink message not containing an ACK while we were waiting for it!");
378  }
379  }
380 
381  std::list<Ptr<LorawanMacCommand>> commands = frameHeader.GetCommands();
382  std::list<Ptr<LorawanMacCommand>>::iterator it;
383  for (it = commands.begin(); it != commands.end(); it++)
384  {
385  NS_LOG_DEBUG("Iterating over the MAC commands...");
386  enum MacCommandType type = (*it)->GetCommandType();
387  switch (type)
388  {
389  case (LINK_CHECK_ANS): {
390  NS_LOG_DEBUG("Detected a LinkCheckAns command.");
391 
392  // Cast the command
393  Ptr<LinkCheckAns> linkCheckAns = (*it)->GetObject<LinkCheckAns>();
394 
395  // Call the appropriate function to take action
396  OnLinkCheckAns(linkCheckAns->GetMargin(), linkCheckAns->GetGwCnt());
397 
398  break;
399  }
400  case (LINK_ADR_REQ): {
401  NS_LOG_DEBUG("Detected a LinkAdrReq command.");
402 
403  // Cast the command
404  Ptr<LinkAdrReq> linkAdrReq = (*it)->GetObject<LinkAdrReq>();
405 
406  // Call the appropriate function to take action
407  OnLinkAdrReq(linkAdrReq->GetDataRate(),
408  linkAdrReq->GetTxPower(),
409  linkAdrReq->GetEnabledChannelsList(),
410  linkAdrReq->GetRepetitions());
411 
412  break;
413  }
414  case (DUTY_CYCLE_REQ): {
415  NS_LOG_DEBUG("Detected a DutyCycleReq command.");
416 
417  // Cast the command
418  Ptr<DutyCycleReq> dutyCycleReq = (*it)->GetObject<DutyCycleReq>();
419 
420  // Call the appropriate function to take action
421  OnDutyCycleReq(dutyCycleReq->GetMaximumAllowedDutyCycle());
422 
423  break;
424  }
425  case (RX_PARAM_SETUP_REQ): {
426  NS_LOG_DEBUG("Detected a RxParamSetupReq command.");
427 
428  // Cast the command
429  Ptr<RxParamSetupReq> rxParamSetupReq = (*it)->GetObject<RxParamSetupReq>();
430 
431  // Call the appropriate function to take action
432  OnRxParamSetupReq(rxParamSetupReq);
433 
434  break;
435  }
436  case (DEV_STATUS_REQ): {
437  NS_LOG_DEBUG("Detected a DevStatusReq command.");
438 
439  // Cast the command
440  Ptr<DevStatusReq> devStatusReq = (*it)->GetObject<DevStatusReq>();
441 
442  // Call the appropriate function to take action
443  OnDevStatusReq();
444 
445  break;
446  }
447  case (NEW_CHANNEL_REQ): {
448  NS_LOG_DEBUG("Detected a NewChannelReq command.");
449 
450  // Cast the command
451  Ptr<NewChannelReq> newChannelReq = (*it)->GetObject<NewChannelReq>();
452 
453  // Call the appropriate function to take action
454  OnNewChannelReq(newChannelReq->GetChannelIndex(),
455  newChannelReq->GetFrequency(),
456  newChannelReq->GetMinDataRate(),
457  newChannelReq->GetMaxDataRate());
458  break;
459  }
460  case (RX_TIMING_SETUP_REQ): {
461  break;
462  }
463  case (TX_PARAM_SETUP_REQ): {
464  break;
465  }
466  case (DL_CHANNEL_REQ): {
467  break;
468  }
469  default: {
470  NS_LOG_ERROR("CID not recognized");
471  break;
472  }
473  }
474  }
475 }
476 
477 void
479 {
480  NS_LOG_FUNCTION_NOARGS();
481 
482  frameHeader.SetAsUplink();
483  frameHeader.SetFPort(1); // TODO Use an appropriate frame port based on the application
484  frameHeader.SetAddress(m_address);
485  frameHeader.SetAdr(m_controlDataRate);
486  frameHeader.SetAdrAckReq(0); // TODO Set ADRACKREQ if a member variable is true
487 
488  // FPending does not exist in uplink messages
489  frameHeader.SetFCnt(m_currentFCnt);
490 
491  // Add listed MAC commands
492  for (const auto& command : m_macCommandList)
493  {
494  NS_LOG_INFO("Applying a MAC Command of CID " << unsigned(
495  LorawanMacCommand::GetCIDFromLorawanMacCommand(command->GetCommandType())));
496 
497  frameHeader.AddCommand(command);
498  }
499 }
500 
501 void
503 {
504  NS_LOG_FUNCTION_NOARGS();
505 
506  macHeader.SetMType(m_mType);
507  macHeader.SetMajor(1);
508 }
509 
510 void
512 {
513  m_mType = mType;
514  NS_LOG_DEBUG("Message type is set to " << mType);
515 }
516 
519 {
520  return m_mType;
521 }
522 
523 void
525 {
526 }
527 
528 Time
530 {
531  NS_LOG_FUNCTION_NOARGS();
532  return waitingTime;
533 }
534 
535 Time
537 {
538  NS_LOG_FUNCTION_NOARGS();
539 
540  // Check duty cycle //
541 
542  // Pick a random channel to transmit on
543  std::vector<Ptr<LoraLogicalChannel>> logicalChannels;
544  logicalChannels =
545  m_channelHelper.GetEnabledChannelList(); // Use a separate list to do the shuffle
546  // logicalChannels = Shuffle (logicalChannels);
547 
548  Time waitingTime = Time::Max();
549 
550  // Try every channel
551  std::vector<Ptr<LoraLogicalChannel>>::iterator it;
552  for (it = logicalChannels.begin(); it != logicalChannels.end(); ++it)
553  {
554  // Pointer to the current channel
555  Ptr<LoraLogicalChannel> logicalChannel = *it;
556  double frequency = logicalChannel->GetFrequency();
557 
558  waitingTime = std::min(waitingTime, m_channelHelper.GetWaitingTime(logicalChannel));
559 
560  NS_LOG_DEBUG("Waiting time before the next transmission in channel with frequecy "
561  << frequency << " is = " << waitingTime.GetSeconds() << ".");
562  }
563 
564  waitingTime = GetNextClassTransmissionDelay(waitingTime);
565 
566  return waitingTime;
567 }
568 
569 Ptr<LoraLogicalChannel>
571 {
572  NS_LOG_FUNCTION_NOARGS();
573 
574  // Pick a random channel to transmit on
575  std::vector<Ptr<LoraLogicalChannel>> logicalChannels;
576  logicalChannels =
577  m_channelHelper.GetEnabledChannelList(); // Use a separate list to do the shuffle
578  logicalChannels = Shuffle(logicalChannels);
579 
580  // Try every channel
581  std::vector<Ptr<LoraLogicalChannel>>::iterator it;
582  for (it = logicalChannels.begin(); it != logicalChannels.end(); ++it)
583  {
584  // Pointer to the current channel
585  Ptr<LoraLogicalChannel> logicalChannel = *it;
586  double frequency = logicalChannel->GetFrequency();
587 
588  NS_LOG_DEBUG("Frequency of the current channel: " << frequency);
589 
590  // Verify that we can send the packet
591  Time waitingTime = m_channelHelper.GetWaitingTime(logicalChannel);
592 
593  NS_LOG_DEBUG("Waiting time for current channel = " << waitingTime.GetSeconds());
594 
595  // Send immediately if we can
596  if (waitingTime == Seconds(0))
597  {
598  return *it;
599  }
600  else
601  {
602  NS_LOG_DEBUG("Packet cannot be immediately transmitted on "
603  << "the current channel because of duty cycle limitations.");
604  }
605  }
606  return 0; // In this case, no suitable channel was found
607 }
608 
609 std::vector<Ptr<LoraLogicalChannel>>
610 LorawanMacEndDevice::Shuffle(std::vector<Ptr<LoraLogicalChannel>> vector)
611 {
612  NS_LOG_FUNCTION_NOARGS();
613 
614  int size = vector.size();
615 
616  for (int i = 0; i < size; ++i)
617  {
618  uint16_t random = std::floor(m_uniformRV->GetValue(0, size));
619  Ptr<LoraLogicalChannel> temp = vector.at(random);
620  vector.at(random) = vector.at(i);
621  vector.at(i) = temp;
622  }
623 
624  return vector;
625 }
626 
628 // Setters and Getters //
630 
631 void
633 {
634  m_retxParams.waitingAck = false;
636  m_retxParams.packet = 0;
637  m_retxParams.firstAttempt = Seconds(0);
638 
639  // Cancel next retransmissions, if any
640  Simulator::Cancel(m_nextTx);
641 }
642 
643 void
645 {
646  NS_LOG_FUNCTION(this << adapt);
647  m_enableDRAdapt = adapt;
648 }
649 
650 bool
652 {
653  return m_enableDRAdapt;
654 }
655 
656 void
658 {
659  NS_LOG_FUNCTION(this << unsigned(maxNumbTx));
660  m_maxNumbTx = maxNumbTx;
661  m_retxParams.retxLeft = maxNumbTx;
662 }
663 
664 uint8_t
666 {
667  NS_LOG_FUNCTION(this);
668  return m_maxNumbTx;
669 }
670 
671 void
673 {
674  NS_LOG_FUNCTION(this << unsigned(dataRate));
675 
676  m_dataRate = dataRate;
677 }
678 
679 uint8_t
681 {
682  NS_LOG_FUNCTION(this);
683 
684  return m_dataRate;
685 }
686 
687 void
689 {
690  NS_LOG_FUNCTION(this << address);
691 
692  m_address = address;
693 }
694 
697 {
698  NS_LOG_FUNCTION(this);
699 
700  return m_address;
701 }
702 
703 void
704 LorawanMacEndDevice::OnLinkCheckAns(uint8_t margin, uint8_t gwCnt)
705 {
706  NS_LOG_FUNCTION(this << unsigned(margin) << unsigned(gwCnt));
707 
708  m_lastKnownLinkMargin = margin;
709  m_lastKnownGatewayCount = gwCnt;
710 }
711 
712 void
714  uint8_t txPower,
715  std::list<int> enabledChannels,
716  int repetitions)
717 {
718  NS_LOG_FUNCTION(this << unsigned(dataRate) << unsigned(txPower) << repetitions);
719 
720  // Three bools for three requirements before setting things up
721  bool channelMaskOk = true;
722  bool dataRateOk = true;
723  bool txPowerOk = true;
724 
725  // Check the channel mask
727  // Check whether all specified channels exist on this device
728  auto channelList = m_channelHelper.GetChannelList();
729  int channelListSize = channelList.size();
730 
731  for (auto it = enabledChannels.begin(); it != enabledChannels.end(); it++)
732  {
733  if ((*it) > channelListSize)
734  {
735  channelMaskOk = false;
736  break;
737  }
738  }
739 
740  // Check the dataRate
742  // We need to know we can use it at all
743  // To assess this, we try and convert it to a SF/BW combination and check if
744  // those values are valid. Since GetSfFromDataRate and
745  // GetBandwidthFromDataRate return 0 if the dataRate is not recognized, we
746  // can check against this.
747  uint8_t sf = GetSfFromDataRate(dataRate);
748  double bw = GetBandwidthFromDataRate(dataRate);
749  NS_LOG_DEBUG("SF: " << unsigned(sf) << ", BW: " << bw);
750  if (sf == 0 || bw == 0)
751  {
752  dataRateOk = false;
753  NS_LOG_DEBUG("Data rate non valid");
754  }
755 
756  // We need to know we can use it in at least one of the enabled channels
757  // Cycle through available channels, stop when at least one is enabled for the
758  // specified dataRate.
759  if (dataRateOk && channelMaskOk) // If false, skip the check
760  {
761  bool foundAvailableChannel = false;
762  for (auto it = enabledChannels.begin(); it != enabledChannels.end(); it++)
763  {
764  NS_LOG_DEBUG("MinDR: " << unsigned(channelList.at(*it)->GetMinimumDataRate()));
765  NS_LOG_DEBUG("MaxDR: " << unsigned(channelList.at(*it)->GetMaximumDataRate()));
766  if (channelList.at(*it)->GetMinimumDataRate() <= dataRate &&
767  channelList.at(*it)->GetMaximumDataRate() >= dataRate)
768  {
769  foundAvailableChannel = true;
770  break;
771  }
772  }
773 
774  if (!foundAvailableChannel)
775  {
776  dataRateOk = false;
777  NS_LOG_DEBUG("Available channel not found");
778  }
779  }
780 
781  // Check the txPower
783  // Check whether we can use this transmission power
784  if (GetDbmForTxPower(txPower) == 0)
785  {
786  txPowerOk = false;
787  }
788 
789  NS_LOG_DEBUG("Finished checking. "
790  << "ChannelMaskOk: " << channelMaskOk << ", "
791  << "DataRateOk: " << dataRateOk << ", "
792  << "txPowerOk: " << txPowerOk);
793 
794  // If all checks are successful, set parameters up
796  if (channelMaskOk && dataRateOk && txPowerOk)
797  {
798  // Cycle over all channels in the list
799  for (uint32_t i = 0; i < m_channelHelper.GetChannelList().size(); i++)
800  {
801  if (std::find(enabledChannels.begin(), enabledChannels.end(), i) !=
802  enabledChannels.end())
803  {
804  m_channelHelper.GetChannelList().at(i)->SetEnabledForUplink();
805  NS_LOG_DEBUG("Channel " << i << " enabled");
806  }
807  else
808  {
809  m_channelHelper.GetChannelList().at(i)->DisableForUplink();
810  NS_LOG_DEBUG("Channel " << i << " disabled");
811  }
812  }
813 
814  // Set the data rate
815  m_dataRate = dataRate;
816 
817  // Set the transmission power
818  m_txPower = GetDbmForTxPower(txPower);
819  }
820 
821  // Craft a LinkAdrAns MAC command as a response
823  m_macCommandList.push_back(CreateObject<LinkAdrAns>(txPowerOk, dataRateOk, channelMaskOk));
824 }
825 
826 void
828 {
829  NS_LOG_FUNCTION(this << dutyCycle);
830 
831  // Make sure we get a value that makes sense
832  NS_ASSERT(0 <= dutyCycle && dutyCycle < 1);
833 
834  // Set the new duty cycle value
835  m_aggregatedDutyCycle = dutyCycle;
836 
837  // Craft a DutyCycleAns as response
838  NS_LOG_INFO("Adding DutyCycleAns reply");
839  m_macCommandList.push_back(CreateObject<DutyCycleAns>());
840 }
841 
842 void
843 LorawanMacEndDevice::OnRxClassParamSetupReq(Ptr<RxParamSetupReq> rxParamSetupReq)
844 {
845 }
846 
847 void
848 LorawanMacEndDevice::OnRxParamSetupReq(Ptr<RxParamSetupReq> rxParamSetupReq)
849 {
850  NS_LOG_FUNCTION(this << rxParamSetupReq);
851 
852  // static_cast<ClassALorawanMacEndDevice*>(this)->OnRxClassParamSetupReq (rxParamSetupReq);
853  OnRxClassParamSetupReq(rxParamSetupReq);
854 }
855 
856 void
858 {
859  NS_LOG_FUNCTION(this);
860 
861  uint8_t battery = 10; // XXX Fake battery level
862  uint8_t margin = 10; // XXX Fake margin
863 
864  // Craft a RxParamSetupAns as response
865  NS_LOG_INFO("Adding DevStatusAns reply");
866  m_macCommandList.push_back(CreateObject<DevStatusAns>(battery, margin));
867 }
868 
869 void
871  double frequency,
872  uint8_t minDataRate,
873  uint8_t maxDataRate)
874 {
875  NS_LOG_FUNCTION(this);
876 
877  bool dataRateRangeOk = true; // XXX Check whether the new data rate range is ok
878  bool channelFrequencyOk = true; // XXX Check whether the frequency is ok
879 
880  // TODO Return false if one of the checks above failed
881  // TODO Create new channel in the LoraLogicalChannelHelper
882 
883  SetLogicalChannel(chIndex, frequency, minDataRate, maxDataRate);
884 
885  NS_LOG_INFO("Adding NewChannelAns reply");
886  m_macCommandList.push_back(CreateObject<NewChannelAns>(dataRateRangeOk, channelFrequencyOk));
887 }
888 
889 void
891 {
892  NS_LOG_FUNCTION(this << frequency);
893 
894  m_channelHelper.AddChannel(frequency);
895 }
896 
897 void
898 LorawanMacEndDevice::AddLogicalChannel(Ptr<LoraLogicalChannel> logicalChannel)
899 {
900  NS_LOG_FUNCTION(this << logicalChannel);
901 
902  m_channelHelper.AddChannel(logicalChannel);
903 }
904 
905 void
907  double frequency,
908  uint8_t minDataRate,
909  uint8_t maxDataRate)
910 {
911  NS_LOG_FUNCTION(this << unsigned(chIndex) << frequency << unsigned(minDataRate)
912  << unsigned(maxDataRate));
913 
915  chIndex,
916  CreateObject<LoraLogicalChannel>(frequency, minDataRate, maxDataRate));
917 }
918 
919 void
921  double endFrequency,
922  double dutyCycle,
923  double maxTxPowerDbm)
924 {
925  NS_LOG_FUNCTION_NOARGS();
926 
927  m_channelHelper.AddLoraSubBand(startFrequency, endFrequency, dutyCycle, maxTxPowerDbm);
928 }
929 
930 double
932 {
933  NS_LOG_FUNCTION_NOARGS();
934 
935  return m_aggregatedDutyCycle;
936 }
937 
938 void
939 LorawanMacEndDevice::AddLorawanMacCommand(Ptr<LorawanMacCommand> macCommand)
940 {
941  NS_LOG_FUNCTION(this << macCommand);
942 
943  m_macCommandList.push_back(macCommand);
944 }
945 
946 uint8_t
948 {
949  return m_txPower;
950 }
951 
952 void
954 {
955  NS_LOG_FUNCTION(this << &cb);
957 }
958 
959 void
960 LorawanMacEndDevice::SetGwAddress(Mac48Address gwAddress)
961 {
962  NS_LOG_FUNCTION(this << gwAddress);
963 
964  // m_gatewayUpdateCallback (gwAddress);
965  m_gwAddress = gwAddress;
966 }
967 
968 void
970 {
971  m_raChannel = raChannel;
972 }
973 
974 void
975 LorawanMacEndDevice::SetPhyRx(Ptr<SatLoraPhyRx> phyRx)
976 {
977  m_phyRx = phyRx;
978 }
979 
980 Ptr<SatLoraPhyRx>
982 {
983  return m_phyRx;
984 }
985 
986 } // namespace ns3
Implementation of the DevStatusReq LoRaWAN MAC command.
Implementation of the DutyCycleReq LoRaWAN MAC command.
This class represents the device address of a LoraWAN End Device.
This class represents the Frame header (FHDR) used in a LoraWAN network.
void SetAddress(LoraDeviceAddress address)
Set the address.
void SetAsUplink(void)
State that this is an uplink message.
void AddCommand(Ptr< LorawanMacCommand > macCommand)
Add a predefined command to the list.
void SetFCnt(uint16_t fCnt)
Set the FCnt value.
void SetAdrAckReq(bool adrAckReq)
Set the AdrAckReq value.
bool GetAck(void) const
Get the Ack bit value.
std::list< Ptr< LorawanMacCommand > > GetCommands(void)
Return a list of pointers to all the MAC commands saved in this header.
virtual uint32_t GetSerializedSize(void) const
Return the size required for serialization of this header.
void SetAdr(bool adr)
Set the Adr value.
void SetFPort(uint8_t fPort)
Set the FPort value.
Time GetWaitingTime(Ptr< LoraLogicalChannel > channel)
Get the time it is necessary to wait for before transmitting on a given channel.
void AddLoraSubBand(double firstFrequency, double lastFrequency, double dutyCycle, double maxTxPowerDbm)
Add a new LoraSubBand to this helper.
void SetChannel(uint8_t chIndex, Ptr< LoraLogicalChannel > logicalChannel)
Set a new channel at a fixed index.
void AddChannel(double frequency)
Add a new channel to the list.
std::vector< Ptr< LoraLogicalChannel > > GetChannelList(void)
Get the list of LoraLogicalChannels currently registered on this helper.
std::vector< Ptr< LoraLogicalChannel > > GetEnabledChannelList(void)
Get the list of LoraLogicalChannels currently registered on this helper that have been enabled for Up...
double GetTxPowerForChannel(Ptr< LoraLogicalChannel > logicalChannel)
Returns the maximum transmission power [dBm] that is allowed on a channel.
static uint8_t GetCIDFromLorawanMacCommand(enum MacCommandType commandType)
Get the CID that corresponds to this MAC command.
void SetDeviceAddress(LoraDeviceAddress address)
Set the network address of this device.
Time GetNextTransmissionDelay(void)
Find the minimum waiting time before the next possible transmission.
std::list< Ptr< LorawanMacCommand > > m_macCommandList
List of the MAC commands that need to be applied to the next UL packet.
uint8_t GetDataRate(void)
Get the data rate this end device is set to use.
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.
uint8_t GetMaxNumberOfTransmissions(void)
Set the maximum number of transmissions allowed.
bool m_enableDRAdapt
Enable Data Rate adaptation during the retransmission procedure.
EventId m_nextTx
The event of retransmitting a packet in a consecutive moment if an ACK is not received.
virtual void FailedReception(Ptr< const Packet > packet)
Function called by lower layers to inform this layer that reception of a packet we were locked on fai...
TracedValue< double > m_txPower
The transmission power this device is using to transmit.
TracedCallback< uint8_t, bool, Time, Ptr< Packet > > m_requiredTxCallback
The trace source fired when the transmission procedure is finished.
LorawanMacHeader::MType m_mType
The message type to apply to packets sent with the Send method.
void OnLinkCheckAns(uint8_t margin, uint8_t gwCnt)
Perform the actions that need to be taken when receiving a LinkCheckAns command.
Callback< void, Mac48Address > GatewayUpdateCallback
Callback to update gateway address after handover.
LorawanMacHeader::MType GetMType(void)
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 SetMType(LorawanMacHeader::MType mType)
Set the message type to send when the Send method is called.
bool GetDataRateAdaptation(void)
Get if data rate adaptation is enabled or not.
TracedValue< double > m_aggregatedDutyCycle
The aggregated duty cycle this device needs to respect across all sub-bands.
virtual void postponeTransmission(Time nextTxDelay, Ptr< Packet >)
Postpone transmission to the specified time and delete previously scheduled transmissions if present.
LorawanMacEndDevice::GatewayUpdateCallback m_gatewayUpdateCallback
Gateway address update callback.
void SetPhyRx(Ptr< SatLoraPhyRx > phyRx)
Ptr< LoraLogicalChannel > GetChannelForTx(void)
Find a suitable channel for transmission.
Ptr< SatLoraPhyRx > m_phyRx
Reception phy layer for Lora operations.
double GetAggregatedDutyCycle(void)
Set a value for the RX1DROffset parameter.
TracedValue< double > m_lastKnownLinkMargin
The last known link margin.
uint8_t m_maxNumbTx
Maximum number of transmission allowed.
bool m_controlDataRate
Whether this device's data rate should be controlled by the NS.
uint32_t m_raChannel
RA channel assigned to the UT.
virtual void SendToPhy(Ptr< Packet > packet)
Add headers and send a packet with the sending function of the physical layer.
Ptr< SatLoraPhyRx > GetPhyRx()
void SetDataRateAdaptation(bool adapt)
Enable data rate adaptation in the retransmitting procedure.
void OnDevStatusReq(void)
Perform the actions that need to be taken when receiving a DevStatusReq command.
Ptr< UniformRandomVariable > m_uniformRV
An uniform random variable, used by the Shuffle method to randomly reorder the channel list.
virtual void Send(Ptr< Packet > packet)
Send a packet.
void SetDataRate(uint8_t dataRate)
Set the data rate this end device will use when transmitting.
void AddLogicalChannel(double frequency)
Add a logical channel to the helper.
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.
void AddLorawanMacCommand(Ptr< LorawanMacCommand > macCommand)
Add a MAC command to the list of those that will be sent out in the next packet.
void AddLoraSubBand(double startFrequency, double endFrequency, double dutyCycle, double maxTxPowerDbm)
Add a subband to the logical channel helper.
void SetLogicalChannel(uint8_t chIndex, double frequency, uint8_t minDataRate, uint8_t maxDataRate)
Set a new logical channel in the helper.
void SetRaChannel(uint32_t raChannel)
Set RA channel assigned for this UT.
TracedValue< uint8_t > m_dataRate
The DataRate this device is using to transmit.
LoraDeviceAddress GetDeviceAddress(void)
Get the network address of this device.
TracedValue< int > m_lastKnownGatewayCount
The last known gateway count (i.e., gateways that are in communication range with this end device)
virtual void TxFinished()
Perform the actions that are required after a packet send.
void ParseCommands(LoraFrameHeader frameHeader)
Parse and take action on the commands contained on this FrameHeader.
void SetGwAddress(Mac48Address gwAddress)
Set address of the GW (or its MAC) serving this UT.
std::vector< Ptr< LoraLogicalChannel > > Shuffle(std::vector< Ptr< LoraLogicalChannel >> vector)
Randomly shuffle a Ptr<LoraLogicalChannel> vector.
virtual void resetRetransmissionParameters()
Reset retransmission parameters contained in the structure LoraRetxParams.
virtual uint8_t GetTransmissionPower(void)
Get the transmission power this end device is set to use.
void SetGatewayUpdateCallback(LorawanMacEndDevice::GatewayUpdateCallback cb)
Method to set the gateway address update callback.
LoraDeviceAddress m_address
The address of this device.
struct LoraRetxParameters m_retxParams
void ApplyNecessaryOptions(LoraFrameHeader &frameHeader)
Add the necessary options and MAC commands to the LoraFrameHeader.
virtual void Receive(Ptr< Packet > packet)=0
Receive a packet.
virtual void OnRxClassParamSetupReq(Ptr< RxParamSetupReq > rxParamSetupReq)
Perform the actions that need to be taken when receiving a RxParamSetupReq command based on the Devic...
virtual Time GetNextClassTransmissionDelay(Time waitingTime)
Find the minimum waiting time before the next possible transmission based on End Device's Class Type.
void OnDutyCycleReq(double dutyCycle)
Perform the actions that need to be taken when receiving a DutyCycleReq command.
void OnRxParamSetupReq(Ptr< RxParamSetupReq > rxParamSetupReq)
Perform the actions that need to be taken when receiving a RxParamSetupReq command.
void SetMaxNumberOfTransmissions(uint8_t maxNumbTx)
Set the maximum number of transmissions allowed.
This class represents the Mac header of a LoRaWAN packet.
void SetMajor(uint8_t major)
Set the major version of this header.
MType
The message type.
void SetMType(enum MType mtype)
Set the message type.
Class representing the LoRaWAN MAC layer.
Definition: lorawan-mac.h:47
std::vector< uint32_t > m_maxAppPayloadForDataRate
A vector holding the maximum app payload size that corresponds to a certain DataRate.
Definition: lorawan-mac.h:305
TracedCallback< Ptr< const Packet > > m_cannotSendBecauseDutyCycle
The trace source that is fired when a packet cannot be sent because of duty cycle limitations.
Definition: lorawan-mac.h:263
TracedCallback< Ptr< const Packet > > m_sentNewPacket
Trace source that is fired when a new APP layer packet arrives at the MAC layer.
Definition: lorawan-mac.h:274
uint8_t GetSfFromDataRate(uint8_t dataRate)
Get the SF corresponding to a data rate, based on this MAC's region.
Definition: lorawan-mac.cc:123
double GetDbmForTxPower(uint8_t txPower)
Get the transmission power in dBm that corresponds, in this region, to the encoded 8-bit txPower.
Definition: lorawan-mac.cc:151
LoraLogicalChannelHelper m_channelHelper
The LoraLogicalChannelHelper instance that is assigned to this MAC.
Definition: lorawan-mac.h:289
double GetBandwidthFromDataRate(uint8_t dataRate)
Get the BW corresponding to a data rate, based on this MAC's region.
Definition: lorawan-mac.cc:137
Implementation of the NewChannelReq LoRaWAN MAC command.
Implementation of the RxParamSetupReq LoRaWAN MAC command.
SatSignalParameters::PacketsInBurst_t PacketContainer_t
Define PacketContainer in SatPhy.
Definition: satellite-phy.h:78
Time tag used to identify the time when packet is enqueued at PHY on first link between GW and UT lev...
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
MacCommandType
Enum for every possible command type.
@ RX_TIMING_SETUP_REQ
@ RX_PARAM_SETUP_REQ
@ TX_PARAM_SETUP_REQ
Structure representing the parameters that will be used in the retransmission procedure.