lora-network-status.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2018 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: Davide Magrin <magrinda@dei.unipd.it>
19  * Martina Capuzzo <capuzzom@dei.unipd.it>
20  *
21  * Modified by: Bastien Tauran <bastien.tauran@viveris.fr>
22  */
23 
24 #include "lora-network-status.h"
25 
26 #include "lora-beam-tag.h"
27 #include "lora-device-address.h"
28 #include "lora-end-device-status.h"
29 #include "lora-gateway-status.h"
30 
31 #include <ns3/log.h>
32 #include <ns3/net-device.h>
33 #include <ns3/node-container.h>
34 #include <ns3/packet.h>
35 #include <ns3/pointer.h>
36 
37 namespace ns3
38 {
39 
40 NS_LOG_COMPONENT_DEFINE("LoraNetworkStatus");
41 
42 NS_OBJECT_ENSURE_REGISTERED(LoraNetworkStatus);
43 
44 TypeId
46 {
47  static TypeId tid = TypeId("ns3::LoraNetworkStatus").AddConstructor<LoraNetworkStatus>();
48  return tid;
49 }
50 
52 {
53  NS_LOG_FUNCTION_NOARGS();
54 }
55 
57 {
58  NS_LOG_FUNCTION_NOARGS();
59 }
60 
61 void
62 LoraNetworkStatus::AddNode(Ptr<LorawanMacEndDeviceClassA> edMac)
63 {
64  NS_LOG_FUNCTION(this << edMac);
65 
66  // Check whether this device already exists in our list
67  LoraDeviceAddress edAddress = edMac->GetDeviceAddress();
68  if (m_endDeviceStatuses.find(edAddress) == m_endDeviceStatuses.end())
69  {
70  // The device doesn't exist. Create new EndDeviceStatus
71  Ptr<LoraEndDeviceStatus> edStatus =
72  CreateObject<LoraEndDeviceStatus>(edAddress,
73  edMac->GetObject<LorawanMacEndDeviceClassA>());
74 
75  // Add it to the map
76  m_endDeviceStatuses.insert(
77  std::pair<LoraDeviceAddress, Ptr<LoraEndDeviceStatus>>(edAddress, edStatus));
78  NS_LOG_DEBUG("Added to the list a device with address " << edAddress.Print());
79  }
80 }
81 
82 void
83 LoraNetworkStatus::AddGateway(Address& address, Ptr<LoraGatewayStatus> gwStatus)
84 {
85  NS_LOG_FUNCTION(this << address << gwStatus);
86 
87  // Check whether this device already exists in the list
88  if (m_gatewayStatuses.find(address) == m_gatewayStatuses.end())
89  {
90  // The device doesn't exist.
91 
92  // Add it to the map
93  m_gatewayStatuses.insert(std::pair<Address, Ptr<LoraGatewayStatus>>(address, gwStatus));
94  NS_LOG_DEBUG("Added to the list a gateway with address " << address);
95  }
96 }
97 
98 void
99 LoraNetworkStatus::OnReceivedPacket(Ptr<const Packet> packet, const Address& gwAddress)
100 {
101  NS_LOG_FUNCTION(this << packet << gwAddress);
102 
103  // Create a copy of the packet
104  Ptr<Packet> myPacket = packet->Copy();
105 
106  // Extract the headers
107  LorawanMacHeader macHdr;
108  myPacket->RemoveHeader(macHdr);
109  LoraFrameHeader frameHdr;
110  frameHdr.SetAsUplink();
111  myPacket->RemoveHeader(frameHdr);
112 
113  // Update the correct EndDeviceStatus object
114  LoraDeviceAddress edAddr = frameHdr.GetAddress();
115  NS_LOG_DEBUG("Node address: " << edAddr);
116  m_endDeviceStatuses.at(edAddr)->InsertReceivedPacket(packet, gwAddress);
117 }
118 
119 bool
121 {
122  // Throws out of range if no device is found
123  return m_endDeviceStatuses.at(deviceAddress)->NeedsReply();
124 }
125 
126 Address
128 {
129  NS_LOG_FUNCTION(this << deviceAddress << window);
130 
131  // Get the endDeviceStatus we are interested in
132  Ptr<LoraEndDeviceStatus> edStatus = m_endDeviceStatuses.at(deviceAddress);
133  double replyFrequency;
134  if (window == 1)
135  {
136  replyFrequency = edStatus->GetFirstReceiveWindowFrequency();
137  }
138  else if (window == 2)
139  {
140  replyFrequency = edStatus->GetSecondReceiveWindowFrequency();
141  }
142  else
143  {
144  NS_ABORT_MSG("Invalid window value");
145  }
146 
147  // Get the list of gateways that this device can reach
148  // NOTE: At this point, we could also take into account the whole network to
149  // identify the best gateway according to various metrics. For now, we just
150  // ask the EndDeviceStatus to pick the best gateway for us via its method.
151  std::map<double, Address> gwAddresses = edStatus->GetPowerGatewayMap();
152 
153  // By iterating on the map in reverse, we go from the 'best'
154  // gateway, i.e. the one with the highest received power, to the
155  // worst.
156  Address bestGwAddress;
157  for (auto it = gwAddresses.rbegin(); it != gwAddresses.rend(); it++)
158  {
159  bool isAvailable =
160  m_gatewayStatuses.find(it->second)->second->IsAvailableForTransmission(replyFrequency);
161  if (isAvailable)
162  {
163  bestGwAddress = it->second;
164  break;
165  }
166  }
167 
168  return bestGwAddress;
169 }
170 
171 void
172 LoraNetworkStatus::SendThroughGateway(Ptr<Packet> packet, Address gwAddress)
173 {
174  NS_LOG_FUNCTION(packet << gwAddress);
175 
176  m_gatewayStatuses.find(gwAddress)->second->GetNetDevice()->Send(packet, gwAddress, 0x0800);
177 }
178 
179 Ptr<Packet>
181 {
182  // Get the reply packet
183  Ptr<LoraEndDeviceStatus> edStatus = m_endDeviceStatuses.find(edAddress)->second;
184  Ptr<Packet> packet = edStatus->GetCompleteReplyPacket();
185 
186  // Apply the appropriate tag
187  LoraTag tag;
188  tag.SetModcod(edStatus->GetModcod());
189  switch (windowNumber)
190  {
191  case 1:
192  tag.SetDataRate(edStatus->GetMac()->GetFirstReceiveWindowDataRate());
193  tag.SetFrequency(edStatus->GetFirstReceiveWindowFrequency());
194  break;
195  case 2:
196  tag.SetDataRate(edStatus->GetMac()->GetSecondReceiveWindowDataRate());
197  tag.SetFrequency(edStatus->GetSecondReceiveWindowFrequency());
198  break;
199  }
200 
201  packet->AddPacketTag(tag);
202 
203  // Apply the appropriate tag
204  LoraBeamTag beamTag;
205  beamTag.SetBeamId(edStatus->GetBeamId());
206  packet->AddPacketTag(beamTag);
207  return packet;
208 }
209 
210 Ptr<LoraEndDeviceStatus>
211 LoraNetworkStatus::GetEndDeviceStatus(Ptr<const Packet> packet)
212 {
213  NS_LOG_FUNCTION(this << packet);
214 
215  // Get the address
216  LorawanMacHeader mHdr;
217  LoraFrameHeader fHdr;
218  Ptr<Packet> myPacket = packet->Copy();
219  myPacket->RemoveHeader(mHdr);
220  myPacket->RemoveHeader(fHdr);
221  auto it = m_endDeviceStatuses.find(fHdr.GetAddress());
222  if (it != m_endDeviceStatuses.end())
223  {
224  return (*it).second;
225  }
226  else
227  {
228  NS_LOG_ERROR("EndDeviceStatus not found");
229  return 0;
230  }
231 }
232 
233 Ptr<LoraEndDeviceStatus>
235 {
236  NS_LOG_FUNCTION(this << address);
237 
238  auto it = m_endDeviceStatuses.find(address);
239  if (it != m_endDeviceStatuses.end())
240  {
241  return (*it).second;
242  }
243  else
244  {
245  NS_LOG_ERROR("EndDeviceStatus not found");
246  return 0;
247  }
248 }
249 
250 int
252 {
253  NS_LOG_FUNCTION(this);
254 
255  return m_endDeviceStatuses.size();
256 }
257 } // 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
void SetBeamId(uint8_t beamId)
Set which beamId this packet was transmitted with.
This class represents the device address of a LoraWAN End Device.
std::string Print(void) const
Print the address bit-by-bit to a human-readable string.
This class represents the Frame header (FHDR) used in a LoraWAN network.
void SetAsUplink(void)
State that this is an uplink message.
LoraDeviceAddress GetAddress(void) const
Get this header's device address value.
This class represents the knowledge about the state of the network that is available at the Network S...
void AddNode(Ptr< LorawanMacEndDeviceClassA > edMac)
Add a device to the ones that are tracked by this LoraNetworkStatus object.
void OnReceivedPacket(Ptr< const Packet > packet, const Address &gwaddress)
Update network status on the received packet.
Ptr< Packet > GetReplyForDevice(LoraDeviceAddress edAddress, int windowNumber)
Get the reply for the specified device address.
void AddGateway(Address &address, Ptr< LoraGatewayStatus > gwStatus)
Add this gateway to the list of gateways connected to the network.
Address GetBestGatewayForDevice(LoraDeviceAddress deviceAddress, int window)
Return whether we have a gateway that is available to send a reply to the specified device.
static TypeId GetTypeId(void)
Ptr< LoraEndDeviceStatus > GetEndDeviceStatus(Ptr< const Packet > packet)
Get the EndDeviceStatus for the device that sent a packet.
bool NeedsReply(LoraDeviceAddress deviceAddress)
Return whether the specified device needs a reply.
int CountEndDevices(void)
Return the number of end devices currently managed by the server.
void SendThroughGateway(Ptr< Packet > packet, Address gwAddress)
Send a packet through a Gateway.
std::map< Address, Ptr< LoraGatewayStatus > > m_gatewayStatuses
std::map< LoraDeviceAddress, Ptr< LoraEndDeviceStatus > > m_endDeviceStatuses
Tag used to save various data about a packet, like its Spreading Factor and data about interference.
Definition: lora-tag.h:38
void SetDataRate(uint8_t dataRate)
Set the data rate for this packet.
Definition: lora-tag.cc:152
void SetFrequency(double frequency)
Set the frequency of the packet.
Definition: lora-tag.cc:134
void SetModcod(uint8_t modcod)
Set the modcod for this packet.
Definition: lora-tag.cc:164
Class representing the MAC layer of a Class A LoRaWAN device.
This class represents the Mac header of a LoRaWAN packet.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.