Loading...
Searching...
No Matches
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"
29#include "lora-gateway-status.h"
31#include "satellite-topology.h"
32
33#include "ns3/log.h"
34#include "ns3/net-device.h"
35#include "ns3/node-container.h"
36#include "ns3/packet.h"
37#include "ns3/pointer.h"
38#include "ns3/singleton.h"
39
40#include <map>
41#include <stdint.h>
42#include <utility>
43
44namespace ns3
45{
46
47NS_LOG_COMPONENT_DEFINE("LoraNetworkStatus");
48
49NS_OBJECT_ENSURE_REGISTERED(LoraNetworkStatus);
50
51TypeId
53{
54 static TypeId tid =
55 TypeId("ns3::LoraNetworkStatus").SetParent<Object>().AddConstructor<LoraNetworkStatus>();
56 return tid;
57}
58
60{
61 NS_LOG_FUNCTION_NOARGS();
62
63 m_forwardLinkRegenerationMode = Singleton<SatTopology>::Get()->GetForwardLinkRegenerationMode();
64 m_uniform = CreateObject<UniformRandomVariable>();
65}
66
68{
69 NS_LOG_FUNCTION_NOARGS();
70}
71
72void
73LoraNetworkStatus::AddNode(Ptr<LorawanMacEndDeviceClassA> edMac)
74{
75 NS_LOG_FUNCTION(this << edMac);
76
77 // Check whether this device already exists in our list
78 LoraDeviceAddress edAddress = edMac->GetDeviceAddress();
79 if (m_endDeviceStatuses.find(edAddress) == m_endDeviceStatuses.end())
80 {
81 // The device doesn't exist. Create new EndDeviceStatus
82 Ptr<LoraEndDeviceStatus> edStatus =
83 CreateObject<LoraEndDeviceStatus>(edAddress,
84 edMac->GetObject<LorawanMacEndDeviceClassA>());
85
86 // Add it to the map
88 std::pair<LoraDeviceAddress, Ptr<LoraEndDeviceStatus>>(edAddress, edStatus));
89 NS_LOG_DEBUG("Added to the list a device with address " << edAddress.Print());
90 }
91}
92
93void
94LoraNetworkStatus::AddGateway(Ptr<Node> gw, Address& address, Ptr<LoraGatewayStatus> gwStatus)
95{
96 NS_LOG_FUNCTION(this << address << gwStatus);
97
98 // Check whether this device already exists in the list
99 if (m_gatewayStatuses.find(address) == m_gatewayStatuses.end())
100 {
101 // The device doesn't exist.
102
103 // Add it to the map
104 m_gatewayStatuses.insert(std::pair<Address, Ptr<LoraGatewayStatus>>(address, gwStatus));
105 NS_LOG_DEBUG("Added to the list a gateway with address " << address);
106 }
107
108 // Get the PointToPointNetDevice
109 Ptr<PointToPointNetDevice> p2pNetDevice;
110 for (uint32_t i = 0; i < gw->GetNDevices(); i++)
111 {
112 p2pNetDevice = gw->GetDevice(i)->GetObject<PointToPointNetDevice>();
113 if (p2pNetDevice != nullptr)
114 {
115 break;
116 }
117 }
118
119 m_gws.insert(std::make_pair(gw, p2pNetDevice));
120}
121
122void
123LoraNetworkStatus::OnReceivedPacket(Ptr<const Packet> packet, const Address& gwAddress)
124{
125 NS_LOG_FUNCTION(this << packet << gwAddress);
126
127 // Create a copy of the packet
128 Ptr<Packet> myPacket = packet->Copy();
129
130 // Extract the headers
131 LorawanMacHeader macHdr;
132 myPacket->RemoveHeader(macHdr);
133 LoraFrameHeader frameHdr;
134 frameHdr.SetAsUplink();
135 myPacket->RemoveHeader(frameHdr);
136
137 // Update the correct EndDeviceStatus object
138 LoraDeviceAddress edAddr = frameHdr.GetAddress();
139 NS_LOG_DEBUG("Node address: " << edAddr);
140 m_endDeviceStatuses.at(edAddr)->InsertReceivedPacket(packet, gwAddress);
141}
142
143bool
145{
146 // Throws out of range if no device is found
147 return m_endDeviceStatuses.at(deviceAddress)->NeedsReply();
148}
149
150Address
152{
153 NS_LOG_FUNCTION(this << deviceAddress << window);
154
155 // Get the endDeviceStatus we are interested in
156 Ptr<LoraEndDeviceStatus> edStatus = m_endDeviceStatuses.at(deviceAddress);
157 double replyFrequency;
158 if (window == 1)
159 {
160 replyFrequency = edStatus->GetFirstReceiveWindowFrequency();
161 }
162 else if (window == 2)
163 {
164 replyFrequency = edStatus->GetSecondReceiveWindowFrequency();
165 }
166 else
167 {
168 NS_ABORT_MSG("Invalid window value");
169 }
170
171 // Get the list of gateways that this device can reach
172 // NOTE: At this point, we could also take into account the whole network to
173 // identify the best gateway according to various metrics. For now, we just
174 // ask the EndDeviceStatus to pick the best gateway for us via its method.
175 std::map<double, Address> gwAddresses = edStatus->GetPowerGatewayMap();
176
178 {
179 uint8_t beamToUse = edStatus->GetBeamId();
180 Ptr<Node> gateway;
181 std::vector<Address> possibleAddresses;
182 Ptr<SatLorawanNetDevice> lorawanNetDevice;
183 for (std::map<Ptr<Node>, Ptr<PointToPointNetDevice>>::iterator it = m_gws.begin();
184 it != m_gws.end();
185 it++)
186 {
187 gateway = it->first;
188 for (uint32_t i = 0; i < gateway->GetNDevices(); i++)
189 {
190 lorawanNetDevice = gateway->GetDevice(i)->GetObject<SatLorawanNetDevice>();
191 if (lorawanNetDevice != nullptr)
192 {
193 uint8_t beam = lorawanNetDevice->GetMac()->GetBeamId();
194 if (beam == beamToUse)
195 {
196 possibleAddresses.push_back(it->second->GetAddress());
197 }
198 }
199 }
200 }
201 if (possibleAddresses.size() > 0)
202 {
203 return possibleAddresses[m_uniform->GetInteger() % possibleAddresses.size()];
204 }
205 else
206 {
207 return gwAddresses.begin()->second;
208 }
209 }
210
211 // By iterating on the map in reverse, we go from the 'best'
212 // gateway, i.e. the one with the highest received power, to the
213 // worst.
214 Address bestGwAddress;
215 for (auto it = gwAddresses.rbegin(); it != gwAddresses.rend(); it++)
216 {
217 bool isAvailable =
218 m_gatewayStatuses.find(it->second)->second->IsAvailableForTransmission(replyFrequency);
219 if (isAvailable)
220 {
221 bestGwAddress = it->second;
222 break;
223 }
224 }
225
226 return bestGwAddress;
227}
228
229void
230LoraNetworkStatus::SendThroughGateway(Ptr<Packet> packet, Address gwAddress)
231{
232 NS_LOG_FUNCTION(packet << gwAddress);
233
234 m_gatewayStatuses.find(gwAddress)->second->GetNetDevice()->Send(packet, gwAddress, 0x0800);
235}
236
237Ptr<Packet>
239{
240 // Get the reply packet
241 Ptr<LoraEndDeviceStatus> edStatus = m_endDeviceStatuses.find(edAddress)->second;
242 Ptr<Packet> packet = edStatus->GetCompleteReplyPacket();
243
244 // Apply the appropriate tag
245 LoraTag tag;
246 tag.SetModcod(edStatus->GetModcod());
247 switch (windowNumber)
248 {
249 case 1: {
250 tag.SetDataRate(edStatus->GetMac()->GetFirstReceiveWindowDataRate());
251 tag.SetFrequency(edStatus->GetFirstReceiveWindowFrequency());
252 break;
253 }
254 case 2: {
255 tag.SetDataRate(edStatus->GetMac()->GetSecondReceiveWindowDataRate());
256 tag.SetFrequency(edStatus->GetSecondReceiveWindowFrequency());
257 break;
258 }
259 }
260
261 packet->AddPacketTag(tag);
262
263 // Apply the appropriate tag
264 LoraBeamTag beamTag;
265 beamTag.SetBeamId(edStatus->GetBeamId());
266 packet->AddPacketTag(beamTag);
267 return packet;
268}
269
270Ptr<LoraEndDeviceStatus>
272{
273 NS_LOG_FUNCTION(this << packet);
274
275 // Get the address
276 LorawanMacHeader mHdr;
277 LoraFrameHeader fHdr;
278 Ptr<Packet> myPacket = packet->Copy();
279 myPacket->RemoveHeader(mHdr);
280 myPacket->RemoveHeader(fHdr);
281 auto it = m_endDeviceStatuses.find(fHdr.GetAddress());
282 if (it != m_endDeviceStatuses.end())
283 {
284 return (*it).second;
285 }
286 else
287 {
288 NS_LOG_ERROR("EndDeviceStatus not found");
289 return 0;
290 }
291}
292
293Ptr<LoraEndDeviceStatus>
295{
296 NS_LOG_FUNCTION(this << address);
297
298 auto it = m_endDeviceStatuses.find(address);
299 if (it != m_endDeviceStatuses.end())
300 {
301 return (*it).second;
302 }
303 else
304 {
305 NS_LOG_ERROR("EndDeviceStatus not found");
306 return 0;
307 }
308}
309
310int
312{
313 NS_LOG_FUNCTION(this);
314
315 return m_endDeviceStatuses.size();
316}
317} // namespace ns3
Tag used to save various data about a packet, like its Spreading Factor and data about interference.
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.
std::map< Ptr< Node >, Ptr< PointToPointNetDevice > > m_gws
void AddGateway(Ptr< Node > gw, Address &address, Ptr< LoraGatewayStatus > gwStatus)
Add this gateway to the list of gateways connected to the network.
Ptr< Packet > GetReplyForDevice(LoraDeviceAddress edAddress, int windowNumber)
Get the reply for the specified device address.
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.
Ptr< UniformRandomVariable > m_uniform
SatEnums::RegenerationMode_t m_forwardLinkRegenerationMode
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: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
Class representing the MAC layer of a Class A LoRaWAN device.
This class represents the Mac header of a LoRaWAN packet.
SatLorawanNetDevice to be utilized in the UT and GW nodes for IoT configuration.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.