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"
30 
31 #include <ns3/command-line.h>
32 #include <ns3/log.h>
33 #include <ns3/packet.h>
34 #include <ns3/pointer.h>
35 #include <ns3/simulator.h>
36 
37 #include <algorithm>
38 
39 namespace ns3
40 {
41 
42 NS_LOG_COMPONENT_DEFINE("LoraEndDeviceStatus");
43 
44 TypeId
46 {
47  static TypeId tid = TypeId("ns3::LoraEndDeviceStatus")
48  .SetParent<Object>()
49  .AddConstructor<LoraEndDeviceStatus>();
50  return tid;
51 }
52 
54  Ptr<LorawanMacEndDeviceClassA> endDeviceMac)
55  : m_reply(LoraEndDeviceStatus::Reply()),
56  m_endDeviceAddress(endDeviceAddress),
57  m_receivedPacketList(ReceivedPacketList()),
58  m_mac(endDeviceMac)
59 {
60  NS_LOG_FUNCTION(endDeviceAddress);
61 }
62 
64 {
65  NS_LOG_FUNCTION_NOARGS();
66 
67  // Initialize data structure
70 }
71 
73 {
74  NS_LOG_FUNCTION_NOARGS();
75 }
76 
78 // Getters //
80 
81 uint8_t
83 {
84  NS_LOG_FUNCTION_NOARGS();
85  return m_modcod;
86 }
87 
88 uint8_t
90 {
91  NS_LOG_FUNCTION_NOARGS();
92  return m_beamId;
93 }
94 
95 uint8_t
97 {
98  NS_LOG_FUNCTION_NOARGS();
99 
101 }
102 
103 double
105 {
106  NS_LOG_FUNCTION_NOARGS();
107 
109 }
110 
111 uint8_t
113 {
114  NS_LOG_FUNCTION_NOARGS();
115 
117 }
118 
119 double
121 {
122  NS_LOG_FUNCTION_NOARGS();
124 }
125 
126 Ptr<Packet>
128 {
129  NS_LOG_FUNCTION_NOARGS();
130 
131  // Start from reply payload
132  Ptr<Packet> replyPacket;
133  if (m_reply.payload) // If it has APP data to send
134  {
135  NS_LOG_DEBUG("Crafting reply packet from existing payload");
136  replyPacket = m_reply.payload->Copy();
137  }
138  else // If no APP data needs to be sent, use an empty payload
139  {
140  NS_LOG_DEBUG("Crafting reply packet using an empty payload");
141  replyPacket = Create<Packet>(0);
142  }
143 
144  // Add headers
146  Ptr<Packet> lastPacket = GetLastPacketReceivedFromDevice()->Copy();
148  LorawanMacHeader mHdr;
149  LoraFrameHeader fHdr;
150  fHdr.SetAsUplink();
151  lastPacket->RemoveHeader(mHdr);
152  lastPacket->RemoveHeader(fHdr);
155  replyPacket->AddHeader(m_reply.frameHeader);
156  replyPacket->AddHeader(m_reply.macHeader);
157 
158  NS_LOG_DEBUG("Added MAC header" << m_reply.macHeader);
159  NS_LOG_DEBUG("Added frame header" << m_reply.frameHeader);
160 
161  return replyPacket;
162 }
163 
164 bool
166 {
167  NS_LOG_FUNCTION_NOARGS();
168 
169  return m_reply.needsReply;
170 }
171 
174 {
175  NS_LOG_FUNCTION_NOARGS();
176  return m_reply.macHeader;
177 }
178 
181 {
182  NS_LOG_FUNCTION_NOARGS();
183  return m_reply.frameHeader;
184 }
185 
186 Ptr<Packet>
188 {
189  NS_LOG_FUNCTION_NOARGS();
190  return m_reply.payload->Copy();
191 }
192 
193 Ptr<LorawanMacEndDeviceClassA>
195 {
196  return m_mac;
197 }
198 
201 {
202  NS_LOG_FUNCTION_NOARGS();
203  return m_receivedPacketList;
204 }
205 
206 void
208 {
209  NS_LOG_FUNCTION(this << modcod);
210  m_modcod = modcod;
211 }
212 
213 void
215 {
216  NS_LOG_FUNCTION(this << beamId);
217  m_beamId = beamId;
218 }
219 
220 void
222 {
223  NS_LOG_FUNCTION(this << sf);
225 }
226 
227 void
229 {
230  NS_LOG_FUNCTION(this << frequency);
231  m_firstReceiveWindowFrequency = frequency;
232 }
233 
234 void
236 {
237  NS_LOG_FUNCTION(this << offset);
239 }
240 
241 void
243 {
244  NS_LOG_FUNCTION(this << frequency);
245  m_secondReceiveWindowFrequency = frequency;
246 }
247 
248 void
250 {
251  NS_LOG_FUNCTION_NOARGS();
252  m_reply.macHeader = macHeader;
253 }
254 
255 void
257 {
258  NS_LOG_FUNCTION_NOARGS();
259  m_reply.frameHeader = frameHeader;
260 }
261 
262 void
263 LoraEndDeviceStatus::SetReplyPayload(Ptr<Packet> replyPayload)
264 {
265  NS_LOG_FUNCTION(this << replyPayload);
266  m_reply.payload = replyPayload;
267 }
268 
270 // Other methods //
272 
273 void
274 LoraEndDeviceStatus::InsertReceivedPacket(Ptr<const Packet> receivedPacket,
275  const Address& gwAddress)
276 {
277  NS_LOG_FUNCTION(this << receivedPacket << gwAddress);
278 
279  // Create a copy of the packet
280  Ptr<Packet> myPacket = receivedPacket->Copy();
281 
282  // Update current parameters
283  LoraBeamTag beamTag;
284  myPacket->RemovePacketTag(beamTag);
285  SetBeamId(beamTag.GetBeamId());
286 
287  // Extract the headers
288  LorawanMacHeader macHdr;
289  myPacket->RemoveHeader(macHdr);
290 
291  LoraFrameHeader frameHdr;
292  frameHdr.SetAsUplink();
293  myPacket->RemoveHeader(frameHdr);
294 
295  // Update current parameters
296  LoraTag tag;
297  myPacket->RemovePacketTag(tag);
300  SetModcod(tag.GetModcod());
301 
302  // Update Information on the received packet
303  ReceivedPacketInfo info;
304  info.sf = tag.GetSpreadingFactor();
305  info.frequency = tag.GetFrequency();
306  info.packet = receivedPacket;
307 
308  double rcvPower = tag.GetReceivePower();
309 
310  // Perform insertion in list, also checking that the packet isn't already in
311  // the list (it could have been received by another GW already)
312 
313  // Start searching from the end
314  auto it = m_receivedPacketList.rbegin();
315  for (; it != m_receivedPacketList.rend(); it++)
316  {
317  // Get the frame counter of the current packet to compare it with the
318  // newly received one
319  Ptr<Packet> packetCopy = ((*it).first)->Copy();
320  LorawanMacHeader currentMacHdr;
321  packetCopy->RemoveHeader(currentMacHdr);
322  LoraFrameHeader currentFrameHdr;
323  frameHdr.SetAsUplink();
324  packetCopy->RemoveHeader(currentFrameHdr);
325 
326  NS_LOG_DEBUG("Received packet's frame counter: " << unsigned(frameHdr.GetFCnt())
327  << "\nCurrent packet's frame counter: "
328  << unsigned(currentFrameHdr.GetFCnt()));
329 
330  if (frameHdr.GetFCnt() == currentFrameHdr.GetFCnt())
331  {
332  NS_LOG_INFO("Packet was already received by another gateway");
333 
334  // This packet had already been received from another gateway:
335  // add this gateway's reception information.
336  GatewayList& gwList = it->second.gwList;
337 
338  PacketInfoPerGw gwInfo;
339  gwInfo.receivedTime = Simulator::Now();
340  gwInfo.rxPower = rcvPower;
341  gwInfo.gwAddress = gwAddress;
342  gwList.insert(std::pair<Address, PacketInfoPerGw>(gwAddress, gwInfo));
343 
344  NS_LOG_DEBUG("Size of gateway list: " << gwList.size());
345 
346  break; // Exit from the cycle
347  }
348  }
349  if (it == m_receivedPacketList.rend())
350  {
351  NS_LOG_INFO("Packet was received for the first time");
352  PacketInfoPerGw gwInfo;
353  gwInfo.receivedTime = Simulator::Now();
354  gwInfo.rxPower = rcvPower;
355  gwInfo.gwAddress = gwAddress;
356  info.gwList.insert(std::pair<Address, PacketInfoPerGw>(gwAddress, gwInfo));
357  m_receivedPacketList.push_back(
358  std::pair<Ptr<const Packet>, ReceivedPacketInfo>(receivedPacket, info));
359  }
360  NS_LOG_DEBUG(*this);
361 }
362 
365 {
366  NS_LOG_FUNCTION_NOARGS();
367  auto it = m_receivedPacketList.rbegin();
368  if (it != m_receivedPacketList.rend())
369  {
370  return it->second;
371  }
372  else
373  {
375  }
376 }
377 
378 Ptr<const Packet>
380 {
381  NS_LOG_FUNCTION_NOARGS();
382  auto it = m_receivedPacketList.rbegin();
383  if (it != m_receivedPacketList.rend())
384  {
385  return it->first;
386  }
387  else
388  {
389  return 0;
390  }
391 }
392 
393 void
395 {
396  NS_LOG_FUNCTION_NOARGS();
397  m_reply = Reply();
398  m_reply.needsReply = false;
399 }
400 
401 void
402 LoraEndDeviceStatus::AddMACCommand(Ptr<LorawanMacCommand> macCommand)
403 {
404  m_reply.frameHeader.AddCommand(macCommand);
405 }
406 
407 bool
409 {
410  return m_receiveWindowEvent.IsRunning();
411 }
412 
413 void
415 {
416  m_receiveWindowEvent = event;
417 }
418 
419 void
421 {
422  Simulator::Cancel(m_receiveWindowEvent);
423 }
424 
425 std::map<double, Address>
427 {
428  // Create a map of the gateways
429  // Key: received power
430  // Value: address of the corresponding gateway
431  ReceivedPacketInfo info = m_receivedPacketList.back().second;
432  GatewayList gwList = info.gwList;
433 
434  std::map<double, Address> gatewayPowers;
435 
436  for (auto it = gwList.begin(); it != gwList.end(); it++)
437  {
438  Address currentGwAddress = (*it).first;
439  double currentRxPower = (*it).second.rxPower;
440  gatewayPowers.insert(std::pair<double, Address>(currentRxPower, currentGwAddress));
441  }
442 
443  return gatewayPowers;
444 }
445 
446 std::ostream&
447 operator<<(std::ostream& os, const LoraEndDeviceStatus& status)
448 {
449  os << "Total packets received: " << status.m_receivedPacketList.size() << std::endl;
450 
451  for (auto j = status.m_receivedPacketList.begin(); j != status.m_receivedPacketList.end(); j++)
452  {
453  LoraEndDeviceStatus::ReceivedPacketInfo info = (*j).second;
454  LoraEndDeviceStatus::GatewayList gatewayList = info.gwList;
455  Ptr<const Packet> pkt = (*j).first;
456  os << pkt << " " << gatewayList.size() << std::endl;
457  for (LoraEndDeviceStatus::GatewayList::iterator k = gatewayList.begin();
458  k != gatewayList.end();
459  k++)
460  {
461  LoraEndDeviceStatus::PacketInfoPerGw infoPerGw = (*k).second;
462  os << " " << infoPerGw.gwAddress << " " << infoPerGw.rxPower << std::endl;
463  }
464  }
465 
466  return os;
467 }
468 } // namespace ns3
Tag used to save various data about a packet, like its Spreading Factor and data about interference.
Definition: lora-beam-tag.h:34
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:38
double GetFrequency(void)
Get the frequency of the packet.
Definition: lora-tag.cc:140
uint8_t GetSpreadingFactor() const
Read which Spreading Factor this packet was transmitted with.
Definition: lora-tag.cc:98
uint8_t GetModcod(void)
Get the modcod for this packet.
Definition: lora-tag.cc:158
double GetReceivePower() const
Read the power this packet arrived with.
Definition: lora-tag.cc:110
This class represents the Mac header of a LoRaWAN packet.
void SetMType(enum MType mtype)
Set the message type.
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...