lorawan-mac-end-device-class-a.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  * qiuyukang <b612n@qq.com>
23  * Bastien Tauran <bastien.tauran@viveris.fr>
24  */
25 
27 
28 #include "lora-tag.h"
29 #include "lorawan-mac-end-device.h"
32 #include "satellite-phy.h"
33 
34 #include <ns3/log.h>
35 #include <ns3/pointer.h>
36 
37 #include <algorithm>
38 
39 namespace ns3
40 {
41 
42 NS_LOG_COMPONENT_DEFINE("LorawanMacEndDeviceClassA");
43 
44 NS_OBJECT_ENSURE_REGISTERED(LorawanMacEndDeviceClassA);
45 
46 TypeId
48 {
49  static TypeId tid =
50  TypeId("ns3::LorawanMacEndDeviceClassA")
51  .SetParent<LorawanMacEndDevice>()
52  .AddAttribute("FirstWindowDelay",
53  "Time to wait between end of message transmission and opening of first "
54  "reception window",
55  TimeValue(Seconds(1)),
57  MakeTimeChecker())
58  .AddAttribute("SecondWindowDelay",
59  "Time to wait between end of message transmission and opening of second "
60  "reception window",
61  TimeValue(Seconds(2)),
63  MakeTimeChecker())
64  .AddAttribute("FirstWindowDuration",
65  "Duration of first reception window",
66  TimeValue(MilliSeconds(100)),
68  MakeTimeChecker())
69  .AddAttribute("SecondWindowDuration",
70  "Duration of second reception window",
71  TimeValue(MilliSeconds(100)),
73  MakeTimeChecker())
74  .AddConstructor<LorawanMacEndDeviceClassA>();
75  return tid;
76 }
77 
78 TypeId
80 {
81  return GetTypeId();
82 }
83 
85 {
86  NS_FATAL_ERROR("Default constructor not in use");
87 }
88 
90  uint32_t satId,
91  uint32_t beamId,
92  Ptr<SatSuperframeSeq> seq)
93  : LorawanMacEndDevice(node, satId, beamId),
94  m_superframeSeq(seq),
95  m_firstWindowDelay(Seconds(1)),
96  m_secondWindowDelay(Seconds(2)),
97  m_firstWindowDuration(MilliSeconds(100)),
98  m_secondWindowDuration(MilliSeconds(100)),
99  m_rx1DrOffset(0)
100 {
101  NS_LOG_FUNCTION(this);
102 
103  ObjectBase::ConstructSelf(AttributeConstructionList());
104 
106  "Second window must open after first one is closed");
107 
108  // Void the two receiveWindow events
109  m_closeFirstWindow = EventId();
110  m_closeFirstWindow.Cancel();
111  m_closeSecondWindow = EventId();
112  m_closeSecondWindow.Cancel();
113  m_secondReceiveWindow = EventId();
114  m_secondReceiveWindow.Cancel();
115 }
116 
118 {
119  NS_LOG_FUNCTION_NOARGS();
120 }
121 
123 // Sending methods //
125 
126 void
127 LorawanMacEndDeviceClassA::SendToPhy(Ptr<Packet> packetToSend)
128 {
130  // Add headers, prepare TX parameters and send the packet
132  NS_LOG_FUNCTION(this << packetToSend);
133 
134  NS_LOG_DEBUG("PacketToSend: " << packetToSend);
135 
136  if (DynamicCast<SatLoraPhyTx>(m_phy->GetPhyTx())->IsTransmitting())
137  {
138  // Device already transmitting!
139  NS_LOG_WARN("End Device is already transmitting. Aborting.");
140  return;
141  }
142 
143  // Data Rate Adaptation as in LoRaWAN specification, V1.0.2 (2016)
145  (m_retxParams.retxLeft % 2 == 0))
146  {
147  m_txPower = 14; // Reset transmission power
148  m_dataRate = m_dataRate - 1;
149  }
150 
152  {
153  SatMacTimeTag satMacTag;
154  packetToSend->RemovePacketTag(
155  satMacTag); // If packet is retransmitted, it already has a tag, updating it
156  packetToSend->AddPacketTag(SatMacTimeTag(Simulator::Now()));
157 
158  // Add a SatAddressTag tag with this device's address as the source address.
159  packetToSend->AddByteTag(SatAddressTag(m_nodeInfo->GetMacAddress()));
160 
161  // Add a SatDevTimeTag tag for packet delay computation at the receiver end.
162  SatDevTimeTag satDevTag;
163  packetToSend->RemovePacketTag(satDevTag);
164  packetToSend->AddPacketTag(SatDevTimeTag(Simulator::Now()));
165  }
166 
167  uint32_t allocationChannel = 0; // TODO is really zero here ?
168  Ptr<SatSuperframeConf> superframeConf =
170  uint8_t frameId = superframeConf->GetRaChannelFrameId(allocationChannel);
171  Ptr<SatFrameConf> frameConf = superframeConf->GetFrameConf(frameId);
172  Ptr<SatTimeSlotConf> timeSlotConf = frameConf->GetTimeSlotConf(0);
173  Ptr<SatWaveform> wf =
174  m_superframeSeq->GetWaveformConf()->GetWaveform(timeSlotConf->GetWaveFormId());
175 
177  txInfo.modCod = wf->GetModCod();
178  txInfo.fecBlockSizeInBytes = wf->GetPayloadInBytes();
179  txInfo.packetType = m_packetType;
181  txInfo.waveformId = wf->GetWaveformId();
182  // txInfo.crdsaUniquePacketId = m_crdsaUniquePacketId; // reuse the crdsaUniquePacketId to
183  // identify ESSA frames
184 
185  // Craft LoraTxParameters object
186  LoraTxParameters params;
187  params.sf = GetSfFromDataRate(m_dataRate);
189  params.codingRate = SatUtils::GetCodingRate(wf->GetModCod());
191  params.nPreamble = m_nPreambleSymbols;
192  params.crcEnabled = 1;
194 
195  // Pick a channel on which to transmit the packet
196  Ptr<LoraLogicalChannel> txChannel = GetChannelForTx();
197  double frequency = txChannel->GetFrequency();
198  LoraTag tag;
199  packetToSend->RemovePacketTag(tag);
200  tag.SetFrequency(frequency);
201  tag.SetDataRate(m_dataRate);
202  tag.SetModcod(wf->GetModCod());
203  packetToSend->AddPacketTag(tag);
204 
205  SatMacTag mTag;
206  packetToSend->RemovePacketTag(mTag);
207  if (m_isRegenerative)
208  {
209  mTag.SetDestAddress(Mac48Address::ConvertFrom(m_satelliteAddress));
210  }
211  else
212  {
214  }
215  mTag.SetSourceAddress(Mac48Address::ConvertFrom(m_device->GetAddress()));
216  packetToSend->AddPacketTag(mTag);
217 
218  SatAddressE2ETag addressE2ETag;
219  packetToSend->RemovePacketTag(addressE2ETag);
220  addressE2ETag.SetE2EDestAddress(m_gwAddress);
221  addressE2ETag.SetE2ESourceAddress(Mac48Address::ConvertFrom(m_device->GetAddress()));
222  packetToSend->AddPacketTag(addressE2ETag);
223 
224  if (m_isRegenerative)
225  {
226  SatGroundStationAddressTag groundStationAddressTag;
227  packetToSend->RemovePacketTag(groundStationAddressTag);
228  groundStationAddressTag = SatGroundStationAddressTag(m_gwAddress);
229  packetToSend->AddPacketTag(groundStationAddressTag);
230  }
231 
233  packets.push_back(packetToSend);
234 
235  uint32_t carrierId = 0;
236 
237  // Compute packet duration
238  Time duration = GetOnAirTime(packetToSend, params);
239 
240  m_phyRx->SwitchToTx();
241  m_phy->SendPdu(packets, carrierId, duration, txInfo);
242 
243  NS_LOG_DEBUG("PacketToSend: " << packetToSend);
244 
246  // Register packet transmission for duty cycle
248 
249  // Register the sent packet into the DutyCycleHelper
250  m_channelHelper.AddEvent(duration, txChannel);
251 
253  // Prepare for the downlink //
255 
256  // Switch the PHY to the channel so that it will listen here for downlink
257  m_phyRx->SetFrequency(txChannel->GetFrequency());
258 
259  // Instruct the PHY on the right Spreading Factor to listen for during the window
260  // create a SetReplyDataRate function?
261  uint8_t replyDataRate = GetFirstReceiveWindowDataRate();
262  NS_LOG_DEBUG("m_dataRate: " << unsigned(m_dataRate)
263  << ", m_rx1DrOffset: " << unsigned(m_rx1DrOffset)
264  << ", replyDataRate: " << unsigned(replyDataRate) << ".");
265 
266  m_phyRx->SetSpreadingFactor(GetSfFromDataRate(replyDataRate));
267 }
268 
270 // Receiving methods //
272 
273 void
275 {
276  NS_LOG_FUNCTION(this << packet);
277 
278  // We add good address and not broadcast for traces
279  SatMacTag macTag;
280  packet->RemovePacketTag(macTag);
281  macTag.SetDestAddress(m_nodeInfo->GetMacAddress());
282  packet->AddPacketTag(macTag);
283 
284  SatAddressE2ETag addressE2ETag;
285  packet->RemovePacketTag(addressE2ETag);
286  addressE2ETag.SetE2EDestAddress(m_nodeInfo->GetMacAddress());
287  packet->AddPacketTag(addressE2ETag);
288 
290  packets.push_back(packet);
291  RxTraces(packets);
292 
293  m_phyRx->SwitchToStandby();
294 
295  // Work on a copy of the packet
296  Ptr<Packet> packetCopy = packet->Copy();
297 
298  SatMacTag mTag;
299  packetCopy->RemovePacketTag(mTag);
300 
301  // Remove the Mac Header to get some information
302  LorawanMacHeader mHdr;
303  packetCopy->RemoveHeader(mHdr);
304 
305  NS_LOG_DEBUG("Mac Header: " << mHdr);
306 
307  // Only keep analyzing the packet if it's downlink
308  if (!mHdr.IsUplink())
309  {
310  NS_LOG_INFO("Found a downlink packet.");
311 
312  // Remove the Frame Header
313  LoraFrameHeader fHdr;
314  fHdr.SetAsDownlink();
315  packetCopy->RemoveHeader(fHdr);
316 
317  NS_LOG_DEBUG("Frame Header: " << fHdr);
318 
319  // Determine whether this packet is for us
320  bool messageForUs = (m_address == fHdr.GetAddress());
321 
322  if (messageForUs)
323  {
324  NS_LOG_INFO("The message is for us!");
325 
326  // If it exists, cancel the second receive window event
327  // THIS WILL BE GetReceiveWindow()
328  Simulator::Cancel(m_secondReceiveWindow);
329 
330  // Parse the MAC commands
331  ParseCommands(fHdr);
332 
333  // Call the trace source
334  m_receivedPacket(packet);
335  }
336  else
337  {
338  NS_LOG_DEBUG("The message is intended for another recipient.");
339 
340  // In this case, we are either receiving in the first receive window
341  // and finishing reception inside the second one, or receiving a
342  // packet in the second receive window and finding out, after the
343  // fact, that the packet is not for us. In either case, if we no
344  // longer have any retransmissions left, we declare failure.
345  if (m_retxParams.waitingAck && m_secondReceiveWindow.IsExpired())
346  {
347  if (m_retxParams.retxLeft == 0)
348  {
349  uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
351  false,
354  NS_LOG_DEBUG("Failure: no more retransmissions left. Used "
355  << unsigned(txs) << " transmissions.");
356 
357  // Reset retransmission parameters
359  }
360  else // Reschedule
361  {
362  this->Send(m_retxParams.packet);
363  NS_LOG_INFO("We have " << unsigned(m_retxParams.retxLeft)
364  << " retransmissions left: rescheduling transmission.");
365  }
366  }
367  }
368  }
369  else if (m_retxParams.waitingAck && m_secondReceiveWindow.IsExpired())
370  {
371  NS_LOG_INFO("The packet we are receiving is in uplink.");
372  if (m_retxParams.retxLeft > 0)
373  {
374  this->Send(m_retxParams.packet);
375  NS_LOG_INFO("We have " << unsigned(m_retxParams.retxLeft)
376  << " retransmissions left: rescheduling transmission.");
377  }
378  else
379  {
380  uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
382  NS_LOG_DEBUG("Failure: no more retransmissions left. Used " << unsigned(txs)
383  << " transmissions.");
384 
385  // Reset retransmission parameters
387  }
388  }
389 
390  m_phyRx->SwitchToSleep();
391 }
392 
393 void
395 {
396  NS_LOG_FUNCTION(this << packet);
397 
398  // Switch to sleep after a failed reception
399  m_phyRx->SwitchToSleep();
400 
401  if (m_secondReceiveWindow.IsExpired() && m_retxParams.waitingAck)
402  {
403  if (m_retxParams.retxLeft > 0)
404  {
405  this->Send(m_retxParams.packet);
406  NS_LOG_INFO("We have " << unsigned(m_retxParams.retxLeft)
407  << " retransmissions left: rescheduling transmission.");
408  }
409  else
410  {
411  uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
413  NS_LOG_DEBUG("Failure: no more retransmissions left. Used " << unsigned(txs)
414  << " transmissions.");
415 
416  // Reset retransmission parameters
418  }
419  }
420 }
421 
422 void
424 {
425  NS_LOG_FUNCTION_NOARGS();
426 
427  m_phyRx->SwitchToStandby();
428 
429  // Schedule the opening of the first receive window
430  Simulator::Schedule(m_firstWindowDelay,
432  this);
433 
434  // Schedule the opening of the second receive window
435  m_secondReceiveWindow = Simulator::Schedule(m_secondWindowDelay,
437  this);
438 
439  // Switch the PHY to sleep
440  m_phyRx->SwitchToSleep();
441 }
442 
443 void
445 {
446  switch (randomAccessModel)
447  {
448  case SatEnums::RA_MODEL_OFF: {
450  break;
451  }
454  break;
455  }
460  break;
461  }
464  break;
465  }
466  }
467 }
468 
469 void
471 {
472  NS_LOG_FUNCTION_NOARGS();
473 
474  // Set Phy in Standby mode
475  m_phyRx->SwitchToStandby();
476 
477  // Schedule return to sleep after "at least the time required by the end
478  // device's radio transceiver to effectively detect a downlink preamble"
479  // (LoraWAN specification)
480  m_closeFirstWindow = Simulator::Schedule(m_firstWindowDuration,
482  this);
483 }
484 
485 void
487 {
488  NS_LOG_FUNCTION_NOARGS();
489 
490  // Check the Phy layer's state:
491  // - RX -> We are receiving a preamble.
492  // - STANDBY -> Nothing was received.
493  // - SLEEP -> We have received a packet.
494  // We should never be in TX or SLEEP mode at this point
495  switch (m_phyRx->GetState())
496  {
497  case SatLoraPhyRx::TX:
498  NS_ABORT_MSG("PHY was in TX mode when attempting to "
499  << "close a receive window.");
500  break;
501  case SatLoraPhyRx::RX:
502  // PHY is receiving: let it finish. The Receive method will switch it back to SLEEP.
503  break;
504  case SatLoraPhyRx::SLEEP:
505  // PHY has received, and the MAC's Receive already put the device to sleep
506  break;
508  // Turn PHY layer to SLEEP
509  m_phyRx->SwitchToSleep();
510  break;
511  }
512 }
513 
514 void
516 {
517  NS_LOG_FUNCTION_NOARGS();
518 
519  // Check for receiver status: if it's locked on a packet, don't open this
520  // window at all.
521  if (m_phyRx->GetState() == SatLoraPhyRx::RX)
522  {
523  NS_LOG_INFO("Won't open second receive window since we are in RX mode.");
524  return;
525  }
526 
527  // Set Phy in Standby mode
528  m_phyRx->SwitchToStandby();
529 
530  // Switch to appropriate channel and data rate
531  NS_LOG_INFO("Using parameters: " << m_secondReceiveWindowFrequency << "Hz, DR"
532  << unsigned(m_secondReceiveWindowDataRate));
533 
536 
537  // Schedule return to sleep after "at least the time required by the end
538  // device's radio transceiver to effectively detect a downlink preamble"
539  // (LoraWAN specification)
540  m_closeSecondWindow = Simulator::Schedule(m_secondWindowDuration,
542  this);
543 }
544 
545 void
547 {
548  NS_LOG_FUNCTION_NOARGS();
549 
550  // NS_ASSERT (m_phyRx->m_state != SatLoraPhyRx::TX &&
551  // m_phyRx->m_state != SatLoraPhyRx::SLEEP);
552 
553  // Check the Phy layer's state:
554  // - RX -> We have received a preamble.
555  // - STANDBY -> Nothing was detected.
556  switch (m_phyRx->GetState())
557  {
558  case SatLoraPhyRx::TX:
559  break;
560  case SatLoraPhyRx::SLEEP:
561  break;
562  case SatLoraPhyRx::RX:
563  // PHY is receiving: let it finish
564  NS_LOG_DEBUG("PHY is receiving: Receive will handle the result.");
565  return;
567  // Turn PHY layer to sleep
568  m_phyRx->SwitchToSleep();
569  break;
570  }
571 
573  {
574  NS_LOG_DEBUG("No reception initiated by PHY: rescheduling transmission.");
575  if (m_retxParams.retxLeft > 0)
576  {
577  NS_LOG_INFO("We have " << unsigned(m_retxParams.retxLeft)
578  << " retransmissions left: rescheduling transmission.");
579  this->Send(m_retxParams.packet);
580  }
581 
582  else if (m_retxParams.retxLeft == 0 && m_phyRx->GetState() != SatLoraPhyRx::RX)
583  {
584  uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
586  NS_LOG_DEBUG("Failure: no more retransmissions left. Used " << unsigned(txs)
587  << " transmissions.");
588 
589  // Reset retransmission parameters
591  }
592 
593  else
594  {
595  NS_ABORT_MSG("The number of retransmissions left is negative ! ");
596  }
597  }
598  else
599  {
600  uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft);
602  NS_LOG_INFO(
603  "We have " << unsigned(m_retxParams.retxLeft)
604  << " transmissions left. We were not transmitting confirmed messages.");
605 
606  // Reset retransmission parameters
608  }
609 }
610 
612 // Getters and Setters //
614 
615 Time
617 {
618  NS_LOG_FUNCTION_NOARGS();
619 
620  // This is a new packet from APP; it can not be sent until the end of the
621  // second receive window (if the second recieve window has not closed yet)
623  {
624  if (!m_closeFirstWindow.IsExpired() || !m_closeSecondWindow.IsExpired() ||
625  !m_secondReceiveWindow.IsExpired())
626  {
627  NS_LOG_WARN("Attempting to send when there are receive windows:"
628  << " Transmission postponed.");
629  // Compute the duration of a single symbol for the second receive window DR
630  double tSym = pow(2, GetSfFromDataRate(GetSecondReceiveWindowDataRate())) /
632  // Compute the closing time of the second receive window
633  Time endSecondRxWindow = Time(m_secondReceiveWindow.GetTs()) +
634  Seconds(m_receiveWindowDurationInSymbols * tSym);
635 
636  NS_LOG_DEBUG("Duration until endSecondRxWindow for new transmission:"
637  << (endSecondRxWindow - Simulator::Now()).GetSeconds());
638  waitingTime = std::max(waitingTime, endSecondRxWindow - Simulator::Now());
639  }
640  }
641  // This is a retransmitted packet, it can not be sent until the end of
642  // ACK_TIMEOUT (this timer starts when the second receive window was open)
643  else
644  {
645  double ack_timeout = m_uniformRV->GetValue(1, 3);
646  // Compute the duration until ACK_TIMEOUT (It may be a negative number, but it doesn't
647  // matter.)
648  Time retransmitWaitingTime =
649  Time(m_secondReceiveWindow.GetTs()) - Simulator::Now() + Seconds(ack_timeout);
650 
651  NS_LOG_DEBUG("ack_timeout:" << ack_timeout << " retransmitWaitingTime:"
652  << retransmitWaitingTime.GetSeconds());
653  waitingTime = std::max(waitingTime, retransmitWaitingTime);
654  }
655 
656  return waitingTime;
657 }
658 
659 uint8_t
661 {
663 }
664 
665 void
667 {
669 }
670 
671 uint8_t
673 {
675 }
676 
677 void
679 {
680  m_secondReceiveWindowFrequency = frequencyMHz;
681 }
682 
683 double
685 {
687 }
688 
690 // MAC command methods //
692 
693 void
694 LorawanMacEndDeviceClassA::OnRxClassParamSetupReq(Ptr<RxParamSetupReq> rxParamSetupReq)
695 {
696  NS_LOG_FUNCTION(this << rxParamSetupReq);
697 
698  bool offsetOk = true;
699  bool dataRateOk = true;
700 
701  uint8_t rx1DrOffset = rxParamSetupReq->GetRx1DrOffset();
702  uint8_t rx2DataRate = rxParamSetupReq->GetRx2DataRate();
703  double frequency = rxParamSetupReq->GetFrequency();
704 
705  NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) << frequency);
706 
707  // Check that the desired offset is valid
708  if (!(0 <= rx1DrOffset && rx1DrOffset <= 5))
709  {
710  offsetOk = false;
711  }
712 
713  // Check that the desired data rate is valid
714  if (GetSfFromDataRate(rx2DataRate) == 0 || GetBandwidthFromDataRate(rx2DataRate) == 0)
715  {
716  dataRateOk = false;
717  }
718 
719  // For now, don't check for validity of frequency
720  m_secondReceiveWindowDataRate = rx2DataRate;
721  m_rx1DrOffset = rx1DrOffset;
722  m_secondReceiveWindowFrequency = frequency;
723 
724  // Craft a RxParamSetupAns as response
725  NS_LOG_INFO("Adding RxParamSetupAns reply");
726  m_macCommandList.push_back(CreateObject<RxParamSetupAns>(offsetOk, dataRateOk, true));
727 }
728 
729 } /* namespace ns3 */
This class represents the Frame header (FHDR) used in a LoraWAN network.
void SetAsDownlink(void)
State that this is a downlink message.
LoraDeviceAddress GetAddress(void) const
Get this header's device address value.
void AddEvent(Time duration, Ptr< LoraLogicalChannel > channel)
Register the transmission of a packet.
Tag used to save various data about a packet, like its Spreading Factor and data about interference.
Definition: lora-tag.h:41
void SetDataRate(uint8_t dataRate)
Set the data rate for this packet.
Definition: lora-tag.cc:154
void SetFrequency(double frequency)
Set the frequency of the packet.
Definition: lora-tag.cc:136
void SetModcod(uint8_t modcod)
Set the modcod for this packet.
Definition: lora-tag.cc:166
EventId m_secondReceiveWindow
The event of the second receive window opening.
uint8_t GetFirstReceiveWindowDataRate(void)
Get the Data Rate that will be used in the first receive window.
Time m_secondWindowDelay
Time to wait between end of message transmission and opening of second reception window.
virtual void TxFinished()
Perform the actions that are required after a packet send.
SatEnums::PacketType_t m_packetType
Packet type used on RTN channel.
virtual void OnRxClassParamSetupReq(Ptr< RxParamSetupReq > rxParamSetupReq)
Perform the actions that need to be taken when receiving a RxParamSetupReq command based on the Devic...
virtual void SendToPhy(Ptr< Packet > packet)
Add headers and send a packet with the sending function of the physical layer.
Time m_secondWindowDuration
Duration of second reception window.
virtual Time GetNextClassTransmissionDelay(Time waitingTime)
Find the minimum waiting time before the next possible transmission based on End Device's Class Type.
Time m_firstWindowDuration
Duration of first reception window.
double GetSecondReceiveWindowFrequency(void)
Get the frequency that is used for the second receive window.
Ptr< SatSuperframeSeq > m_superframeSeq
Used superframe sequence for the return link.
EventId m_closeSecondWindow
The event of the closing the second receive window.
void CloseFirstReceiveWindow(void)
Perform operations needed to close the first receive window.
void OpenFirstReceiveWindow(void)
Perform operations needed to open the first receive window.
void OpenSecondReceiveWindow(void)
Perform operations needed to open the second receive window.
void SetSecondReceiveWindowDataRate(uint8_t dataRate)
Set the Data Rate to be used in the second receive window.
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...
void SetSecondReceiveWindowFrequency(double frequencyMHz)
Set the frequency that will be used for the second receive window.
void CloseSecondReceiveWindow(void)
Perform operations needed to close the second receive window.
uint8_t m_rx1DrOffset
The RX1DROffset parameter value.
double m_secondReceiveWindowFrequency
The frequency to listen on for the second receive window.
virtual void Receive(Ptr< Packet > packet)
Receive a packet.
Time m_firstWindowDelay
Time to wait between end of message transmission and opening of first reception window.
EventId m_closeFirstWindow
The event of the closing the first receive window.
uint8_t GetSecondReceiveWindowDataRate(void)
Get the Data Rate that will be used in the second receive window.
void SetRaModel(SatEnums::RandomAccessModel_t randomAccessModel)
Set the random access model.
uint8_t m_secondReceiveWindowDataRate
The Data Rate to listen for during the second downlink transmission.
Class representing the MAC layer of a LoRaWAN device.
std::list< Ptr< LorawanMacCommand > > m_macCommandList
List of the MAC commands that need to be applied to the next UL packet.
bool m_enableDRAdapt
Enable Data Rate adaptation during the retransmission procedure.
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.
Ptr< LoraLogicalChannel > GetChannelForTx(void)
Find a suitable channel for transmission.
Ptr< SatLoraPhyRx > m_phyRx
Reception phy layer for Lora operations.
Mac48Address m_gwAddress
Gateway address used in case of transparent satellite.
uint8_t m_receiveWindowDurationInSymbols
The duration of a receive window in number of symbols.
uint8_t m_maxNumbTx
Maximum number of transmission allowed.
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.
TracedValue< uint8_t > m_dataRate
The DataRate this device is using to transmit.
void ParseCommands(LoraFrameHeader frameHeader)
Parse and take action on the commands contained on this FrameHeader.
virtual void resetRetransmissionParameters()
Reset retransmission parameters contained in the structure LoraRetxParams.
bool m_isRegenerative
Tell if satellite is regenerative.
bool m_headerDisabled
Whether or not the header is disabled for communications by this device.
LoraDeviceAddress m_address
The address of this device.
struct LoraRetxParameters m_retxParams
This class represents the Mac header of a LoRaWAN packet.
bool IsUplink(void) const
Check whether this header is for an uplink message.
TracedCallback< Ptr< const Packet > > m_receivedPacket
Trace source that is fired when a packet reaches the MAC layer.
Definition: lorawan-mac.h:270
ReplyDataRateMatrix m_replyDataRateMatrix
The matrix that decides the DR the GW will use in a reply based on the ED's sending DR and on the val...
Definition: lorawan-mac.h:323
int m_nPreambleSymbols
The number of symbols to use in the PHY preamble.
Definition: lorawan-mac.h:312
Time GetOnAirTime(Ptr< Packet > packet, LoraTxParameters txParams)
Compute the time that a packet with certain characteristics will take to be transmitted.
Definition: lorawan-mac.cc:169
Ptr< SatPhy > m_phy
The PHY instance that sits under this MAC layer.
Definition: lorawan-mac.h:281
uint8_t GetSfFromDataRate(uint8_t dataRate)
Get the SF corresponding to a data rate, based on this MAC's region.
Definition: lorawan-mac.cc:128
Ptr< NetDevice > m_device
The device this MAC layer is installed on.
Definition: lorawan-mac.h:286
LoraLogicalChannelHelper m_channelHelper
The LoraLogicalChannelHelper instance that is assigned to this MAC.
Definition: lorawan-mac.h:291
double GetBandwidthFromDataRate(uint8_t dataRate)
Get the BW corresponding to a data rate, based on this MAC's region.
Definition: lorawan-mac.cc:142
This class implements a tag that carries the satellite MAC of GW and UT.
void SetE2ESourceAddress(Mac48Address e2eSourceAddress)
Set E2E source MAC address.
void SetE2EDestAddress(Mac48Address e2eDestAddress)
Set E2E destination MAC address.
This class implements a tag that carries the MAC address of the sender of the packet.
Time tag used to identify the time when packet is enqueued at device level.
RandomAccessModel_t
The defined random access models.
Tag to store ground station destination address.
@ SLEEP
The PHY layer is sleeping.
@ TX
The PHY layer is sending a packet.
@ RX
The PHY layer is receiving a packet.
@ STANDBY
The PHY layer is in STANDBY.
void RxTraces(SatPhy::PacketContainer_t packets)
Invoke the Rx trace source for each received packet.
bool m_isStatisticsTagsEnabled
EnableStatisticsTags attribute.
Address m_satelliteAddress
MAC address of satellite on other side of the link.
Ptr< SatNodeInfo > m_nodeInfo
Node info containing node related information, such as node type, node id and MAC address (of the Sat...
This class implements a tag that carries the satellite MAC specific information, such as source and d...
void SetDestAddress(Mac48Address dest)
Set destination MAC address.
void SetSourceAddress(Mac48Address source)
Set source MAC address.
Time tag used to identify the time when packet is enqueued at MAC level.
SatSignalParameters::PacketsInBurst_t PacketContainer_t
Define PacketContainer in SatPhy.
Definition: satellite-phy.h:79
static double GetCodingRate(SatEnums::SatModcod_t modcod)
Gets the coding rate of a certain MODCOD.
constexpr uint8_t SUPERFRAME_SEQUENCE
Used superframe sequence in the RTN link.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
Structure to collect all parameters that are used to compute the duration of a packet (excluding payl...
bool lowDataRateOptimizationEnabled
Whether Low Data Rate Optimization is enabled.
uint32_t nPreamble
Number of preamble symbols.
bool headerDisabled
Whether to use implicit header mode.
uint8_t sf
Spreading Factor.
double bandwidthHz
Bandwidth in Hz.
bool crcEnabled
Whether Cyclic Redundancy Check is enabled.
Struct for storing the packet specific Tx information.