lora-end-device-status.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  * Authors: Martina Capuzzo <capuzzom@dei.unipd.it>
19  * Davide Magrin <magrinda@dei.unipd.it>
20  *
21  * Modified by: Bastien Tauran <bastien.tauran@viveris.fr>
22  */
23 
24 #include "lora-end-device-status.h"
25 
26 #include "lora-beam-tag.h"
27 #include "lora-frame-header.h"
28 #include "lora-tag.h"
29 #include "lorawan-mac-header.h"
31 #include "satellite-topology.h"
32 
33 #include <ns3/command-line.h>
34 #include <ns3/log.h>
35 #include <ns3/packet.h>
36 #include <ns3/pointer.h>
37 #include <ns3/simulator.h>
38 #include <ns3/singleton.h>
39 
40 #include <algorithm>
41 #include <iostream>
42 #include <map>
43 #include <ostream>
44 #include <utility>
45 
46 namespace ns3
47 {
48 
49 NS_LOG_COMPONENT_DEFINE("LoraEndDeviceStatus");
50 
51 TypeId
53 {
54  static TypeId tid = TypeId("ns3::LoraEndDeviceStatus")
55  .SetParent<Object>()
56  .AddConstructor<LoraEndDeviceStatus>();
57  return tid;
58 }
59 
61  Ptr<LorawanMacEndDeviceClassA> endDeviceMac)
62  : m_reply(LoraEndDeviceStatus::Reply()),
63  m_endDeviceAddress(endDeviceAddress),
64  m_utAddress(endDeviceMac->GetAddress()),
65  m_receivedPacketList(ReceivedPacketList()),
66  m_mac(endDeviceMac)
67 {
68  NS_LOG_FUNCTION(endDeviceAddress);
69 }
70 
72 {
73  NS_LOG_FUNCTION_NOARGS();
74 
75  // Initialize data structure
78 }
79 
81 {
82  NS_LOG_FUNCTION_NOARGS();
83 }
84 
86 // Getters //
88 
89 uint8_t
91 {
92  NS_LOG_FUNCTION_NOARGS();
93  return m_modcod;
94 }
95 
96 uint8_t
98 {
99  NS_LOG_FUNCTION_NOARGS();
100  return m_beamId;
101 }
102 
103 uint8_t
105 {
106  NS_LOG_FUNCTION_NOARGS();
107 
109 }
110 
111 double
113 {
114  NS_LOG_FUNCTION_NOARGS();
115 
117 }
118 
119 uint8_t
121 {
122  NS_LOG_FUNCTION_NOARGS();
123 
125 }
126 
127 double
129 {
130  NS_LOG_FUNCTION_NOARGS();
132 }
133 
134 Ptr<Packet>
136 {
137  NS_LOG_FUNCTION_NOARGS();
138 
139  // Start from reply payload
140  Ptr<Packet> replyPacket;
141  if (m_reply.payload) // If it has APP data to send
142  {
143  NS_LOG_DEBUG("Crafting reply packet from existing payload");
144  replyPacket = m_reply.payload->Copy();
145  }
146  else // If no APP data needs to be sent, use an empty payload
147  {
148  NS_LOG_DEBUG("Crafting reply packet using an empty payload");
149  replyPacket = Create<Packet>(0);
150  }
151 
152  // Add headers
154  Ptr<Packet> lastPacket = GetLastPacketReceivedFromDevice()->Copy();
156  LorawanMacHeader mHdr;
157  LoraFrameHeader fHdr;
158  fHdr.SetAsUplink();
159  lastPacket->RemoveHeader(mHdr);
160  lastPacket->RemoveHeader(fHdr);
163  replyPacket->AddHeader(m_reply.frameHeader);
164  replyPacket->AddHeader(m_reply.macHeader);
165 
166  if (Singleton<SatTopology>::Get()->GetForwardLinkRegenerationMode() ==
168  {
169  SatGroundStationAddressTag groundStationAddressTag =
170  SatGroundStationAddressTag(Mac48Address::ConvertFrom(m_utAddress));
171  replyPacket->AddPacketTag(groundStationAddressTag);
172  }
173 
174  NS_LOG_DEBUG("Added MAC header" << m_reply.macHeader);
175  NS_LOG_DEBUG("Added frame header" << m_reply.frameHeader);
176 
177  return replyPacket;
178 }
179 
180 bool
182 {
183  NS_LOG_FUNCTION_NOARGS();
184 
185  return m_reply.needsReply;
186 }
187 
190 {
191  NS_LOG_FUNCTION_NOARGS();
192  return m_reply.macHeader;
193 }
194 
197 {
198  NS_LOG_FUNCTION_NOARGS();
199  return m_reply.frameHeader;
200 }
201 
202 Ptr<Packet>
204 {
205  NS_LOG_FUNCTION_NOARGS();
206  return m_reply.payload->Copy();
207 }
208 
209 Ptr<LorawanMacEndDeviceClassA>
211 {
212  return m_mac;
213 }
214 
217 {
218  NS_LOG_FUNCTION_NOARGS();
219  return m_receivedPacketList;
220 }
221 
222 void
224 {
225  NS_LOG_FUNCTION(this << modcod);
226  m_modcod = modcod;
227 }
228 
229 void
231 {
232  NS_LOG_FUNCTION(this << beamId);
233 
234  m_beamId = beamId;
235 }
236 
237 void
239 {
240  NS_LOG_FUNCTION(this << sf);
242 }
243 
244 void
246 {
247  NS_LOG_FUNCTION(this << frequency);
248  m_firstReceiveWindowFrequency = frequency;
249 }
250 
251 void
253 {
254  NS_LOG_FUNCTION(this << offset);
256 }
257 
258 void
260 {
261  NS_LOG_FUNCTION(this << frequency);
262  m_secondReceiveWindowFrequency = frequency;
263 }
264 
265 void
267 {
268  NS_LOG_FUNCTION_NOARGS();
269  m_reply.macHeader = macHeader;
270 }
271 
272 void
274 {
275  NS_LOG_FUNCTION_NOARGS();
276  m_reply.frameHeader = frameHeader;
277 }
278 
279 void
280 LoraEndDeviceStatus::SetReplyPayload(Ptr<Packet> replyPayload)
281 {
282  NS_LOG_FUNCTION(this << replyPayload);
283  m_reply.payload = replyPayload;
284 }
285 
287 // Other methods //
289 
290 void
291 LoraEndDeviceStatus::InsertReceivedPacket(Ptr<const Packet> receivedPacket,
292  const Address& gwAddress)
293 {
294  NS_LOG_FUNCTION(this << receivedPacket << gwAddress);
295 
296  // Create a copy of the packet
297  Ptr<Packet> myPacket = receivedPacket->Copy();
298 
299  // Update current parameters
300  LoraBeamTag beamTag;
301  myPacket->RemovePacketTag(beamTag);
302  SetBeamId(beamTag.GetBeamId());
303 
304  // Extract the headers
305  LorawanMacHeader macHdr;
306  myPacket->RemoveHeader(macHdr);
307 
308  LoraFrameHeader frameHdr;
309  frameHdr.SetAsUplink();
310  myPacket->RemoveHeader(frameHdr);
311 
312  // Update current parameters
313  LoraTag tag;
314  myPacket->RemovePacketTag(tag);
317  SetModcod(tag.GetModcod());
318 
319  // Update Information on the received packet
320  ReceivedPacketInfo info;
321  info.sf = tag.GetSpreadingFactor();
322  info.frequency = tag.GetFrequency();
323  info.packet = receivedPacket;
324 
325  double rcvPower = tag.GetReceivePower();
326 
327  // Perform insertion in list, also checking that the packet isn't already in
328  // the list (it could have been received by another GW already)
329 
330  // Start searching from the end
331  auto it = m_receivedPacketList.rbegin();
332  for (; it != m_receivedPacketList.rend(); it++)
333  {
334  // Get the frame counter of the current packet to compare it with the
335  // newly received one
336  Ptr<Packet> packetCopy = ((*it).first)->Copy();
337  LorawanMacHeader currentMacHdr;
338  packetCopy->RemoveHeader(currentMacHdr);
339  LoraFrameHeader currentFrameHdr;
340  frameHdr.SetAsUplink();
341  packetCopy->RemoveHeader(currentFrameHdr);
342 
343  NS_LOG_DEBUG("Received packet's frame counter: " << unsigned(frameHdr.GetFCnt())
344  << "\nCurrent packet's frame counter: "
345  << unsigned(currentFrameHdr.GetFCnt()));
346 
347  if (frameHdr.GetFCnt() == currentFrameHdr.GetFCnt())
348  {
349  NS_LOG_INFO("Packet was already received by another gateway");
350 
351  // This packet had already been received from another gateway:
352  // add this gateway's reception information.
353  GatewayList& gwList = it->second.gwList;
354 
355  PacketInfoPerGw gwInfo;
356  gwInfo.receivedTime = Simulator::Now();
357  gwInfo.rxPower = rcvPower;
358  gwInfo.gwAddress = gwAddress;
359  gwList.insert(std::pair<Address, PacketInfoPerGw>(gwAddress, gwInfo));
360 
361  NS_LOG_DEBUG("Size of gateway list: " << gwList.size());
362 
363  break; // Exit from the cycle
364  }
365  }
366  if (it == m_receivedPacketList.rend())
367  {
368  NS_LOG_INFO("Packet was received for the first time");
369  PacketInfoPerGw gwInfo;
370  gwInfo.receivedTime = Simulator::Now();
371  gwInfo.rxPower = rcvPower;
372  gwInfo.gwAddress = gwAddress;
373  info.gwList.insert(std::pair<Address, PacketInfoPerGw>(gwAddress, gwInfo));
374  m_receivedPacketList.push_back(
375  std::pair<Ptr<const Packet>, ReceivedPacketInfo>(receivedPacket, info));
376  }
377  NS_LOG_DEBUG(*this);
378 }
379 
382 {
383  NS_LOG_FUNCTION_NOARGS();
384  auto it = m_receivedPacketList.rbegin();
385  if (it != m_receivedPacketList.rend())
386  {
387  return it->second;
388  }
389  else
390  {
392  }
393 }
394 
395 Ptr<const Packet>
397 {
398  NS_LOG_FUNCTION_NOARGS();
399  auto it = m_receivedPacketList.rbegin();
400  if (it != m_receivedPacketList.rend())
401  {
402  return it->first;
403  }
404  else
405  {
406  return 0;
407  }
408 }
409 
410 void
412 {
413  NS_LOG_FUNCTION_NOARGS();
414  m_reply = Reply();
415  m_reply.needsReply = false;
416 }
417 
418 void
419 LoraEndDeviceStatus::AddMACCommand(Ptr<LorawanMacCommand> macCommand)
420 {
421  m_reply.frameHeader.AddCommand(macCommand);
422 }
423 
424 bool
426 {
427  return m_receiveWindowEvent.IsPending();
428 }
429 
430 void
432 {
433  m_receiveWindowEvent = event;
434 }
435 
436 void
438 {
439  Simulator::Cancel(m_receiveWindowEvent);
440 }
441 
442 std::map<double, Address>
444 {
445  // Create a map of the gateways
446  // Key: received power
447  // Value: address of the corresponding gateway
448  ReceivedPacketInfo info = m_receivedPacketList.back().second;
449  GatewayList gwList = info.gwList;
450 
451  std::map<double, Address> gatewayPowers;
452 
453  for (auto it = gwList.begin(); it != gwList.end(); it++)
454  {
455  Address currentGwAddress = (*it).first;
456  double currentRxPower = (*it).second.rxPower;
457  gatewayPowers.insert(std::pair<double, Address>(currentRxPower, currentGwAddress));
458  }
459 
460  return gatewayPowers;
461 }
462 
463 std::ostream&
464 operator<<(std::ostream& os, const LoraEndDeviceStatus& status)
465 {
466  os << "Total packets received: " << status.m_receivedPacketList.size() << std::endl;
467 
468  for (auto j = status.m_receivedPacketList.begin(); j != status.m_receivedPacketList.end(); j++)
469  {
470  LoraEndDeviceStatus::ReceivedPacketInfo info = (*j).second;
471  LoraEndDeviceStatus::GatewayList gatewayList = info.gwList;
472  Ptr<const Packet> pkt = (*j).first;
473  os << pkt << " " << gatewayList.size() << std::endl;
474  for (LoraEndDeviceStatus::GatewayList::iterator k = gatewayList.begin();
475  k != gatewayList.end();
476  k++)
477  {
478  LoraEndDeviceStatus::PacketInfoPerGw infoPerGw = (*k).second;
479  os << " " << infoPerGw.gwAddress << " " << infoPerGw.rxPower << std::endl;
480  }
481  }
482 
483  return os;
484 }
485 } // namespace ns3
Tag used to save various data about a packet, like its Spreading Factor and data about interference.
Definition: lora-beam-tag.h:37
uint8_t GetBeamId() const
Read which beam ID this packet was transmitted with.
This class represents the device address of a LoraWAN End Device.
This class represents the Network Server's knowledge about an End Device in the LoRaWAN network it is...
uint8_t GetBeamId(void)
Get the beam ID this device is using.
double GetFirstReceiveWindowFrequency(void)
Get the first window frequency of this device.
ReceivedPacketList GetReceivedPacketList(void)
Get the received packet list.
void AddMACCommand(Ptr< LorawanMacCommand > macCommand)
Add MAC command to the list.
Ptr< Packet > GetReplyPayload(void)
Get the data of the reply packet.
void SetSecondReceiveWindowFrequency(double frequency)
Set the second window frequency of this device.
void SetSecondReceiveWindowOffset(uint8_t offset)
Set the spreading factor this device is using in the first receive window.
void SetFirstReceiveWindowSpreadingFactor(uint8_t sf)
Set the spreading factor this device is using in the first receive window.
void SetBeamId(uint8_t beamId)
Set the beam ID this device is using.
uint8_t GetFirstReceiveWindowSpreadingFactor(void)
Get the spreading factor this device is using in the first receive window.
LorawanMacHeader GetReplyMacHeader(void)
Get the reply packet mac header.
std::list< std::pair< Ptr< const Packet >, ReceivedPacketInfo > > ReceivedPacketList
void SetReplyMacHeader(LorawanMacHeader macHeader)
Set the reply packet mac header.
bool NeedsReply(void)
Whether the end device needs a reply.
LoraEndDeviceStatus::ReceivedPacketInfo GetLastReceivedPacketInfo(void)
Return the information about the last packet that was received from the device.
uint8_t GetModcod(void)
Get the modcod this device is using.
Ptr< Packet > GetCompleteReplyPacket(void)
Get the reply packet.
void SetReplyPayload(Ptr< Packet > replyPayload)
Set the packet reply payload.
void SetReplyFrameHeader(LoraFrameHeader frameHeader)
Set the reply packet frame header.
std::map< Address, PacketInfoPerGw > GatewayList
void InitializeReply(void)
Initialize reply.
Ptr< LorawanMacEndDeviceClassA > m_mac
Pointer to the MAC layer of this device.
double GetSecondReceiveWindowFrequency(void)
Return the second window frequency of this device.
Ptr< const Packet > GetLastPacketReceivedFromDevice(void)
Return the last packet that was received from this device.
uint8_t GetSecondReceiveWindowOffset(void)
Get the offset of spreading factor this device is using in the second receive window with respect to ...
void SetModcod(uint8_t modcod)
Set the modcod this device is using.
void InsertReceivedPacket(Ptr< const Packet > receivedPacket, const Address &gwAddress)
Insert a received packet in the packet list.
bool HasReceiveWindowOpportunityScheduled()
Returns whether we already decided we will schedule a transmission to this ED.
LoraFrameHeader GetReplyFrameHeader(void)
Get the reply packet frame header.
ReceivedPacketList m_receivedPacketList
void SetFirstReceiveWindowFrequency(double frequency)
Set the first window frequency of this device.
LoraDeviceAddress m_endDeviceAddress
void SetReceiveWindowOpportunity(EventId event)
std::map< double, Address > GetPowerGatewayMap(void)
Return an ordered list of the best gateways.
Ptr< LorawanMacEndDeviceClassA > GetMac(void)
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.
uint16_t GetFCnt(void) const
Get the FCnt value.
Tag used to save various data about a packet, like its Spreading Factor and data about interference.
Definition: lora-tag.h:41
double GetFrequency(void)
Get the frequency of the packet.
Definition: lora-tag.cc:142
uint8_t GetSpreadingFactor() const
Read which Spreading Factor this packet was transmitted with.
Definition: lora-tag.cc:100
uint8_t GetModcod(void)
Get the modcod for this packet.
Definition: lora-tag.cc:160
double GetReceivePower() const
Read the power this packet arrived with.
Definition: lora-tag.cc:112
This class represents the Mac header of a LoRaWAN packet.
void SetMType(enum MType mtype)
Set the message type.
Tag to store ground station destination address.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
std::ostream & operator<<(std::ostream &os, const GeoCoordinate &coordinate)
Structure saving information regarding the packet reception in each gateway.
Time receivedTime
Time at which the packet was received by this gateway.
Address gwAddress
Address of the gateway that received the packet.
double rxPower
Reception power of the packet at this gateway.
Structure saving information regarding all packet receptions.
GatewayList gwList
List of gateways that received this packet.
Ptr< const Packet > packet
The received packet.
Structure representing the reply that the network server will send this device at the first opportuni...