A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
simple-end-device-lora-phy.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 University of Padova
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Davide Magrin <magrinda@dei.unipd.it>
18 */
19
21
22#include "lora-tag.h"
23
24#include "ns3/log.h"
25#include "ns3/simulator.h"
26
27#include <algorithm>
28
29namespace ns3
30{
31namespace lorawan
32{
33
34NS_LOG_COMPONENT_DEFINE("SimpleEndDeviceLoraPhy");
35
36NS_OBJECT_ENSURE_REGISTERED(SimpleEndDeviceLoraPhy);
37
38TypeId
40{
41 static TypeId tid = TypeId("ns3::SimpleEndDeviceLoraPhy")
43 .SetGroupName("lorawan")
44 .AddConstructor<SimpleEndDeviceLoraPhy>();
45
46 return tid;
47}
48
49// Initialize the device with some common settings.
50// These will then be changed by helpers.
52{
53}
54
56{
57}
58
59void
61 LoraTxParameters txParams,
62 double frequencyMHz,
63 double txPowerDbm)
64{
65 NS_LOG_FUNCTION(this << packet << txParams << frequencyMHz << txPowerDbm);
66
67 NS_LOG_INFO("Current state: " << m_state);
68
69 // We must be either in STANDBY or SLEEP mode to send a packet
70 if (m_state != STANDBY && m_state != SLEEP)
71 {
72 NS_LOG_INFO("Cannot send because device is currently not in STANDBY or SLEEP mode");
73 return;
74 }
75
76 // Compute the duration of the transmission
77 Time duration = GetOnAirTime(packet, txParams);
78
79 // We can send the packet: switch to the TX state
80 SwitchToTx(txPowerDbm);
81
82 // Tag the packet with information about its Spreading Factor
83 LoraTag tag;
84 packet->RemovePacketTag(tag);
85 tag.SetSpreadingFactor(txParams.sf);
86 packet->AddPacketTag(tag);
87
88 // Send the packet over the channel
89 NS_LOG_INFO("Sending the packet in the channel");
90 m_channel->Send(this, packet, txPowerDbm, txParams, duration, frequencyMHz);
91
92 // Schedule a call to signal the transmission end.
94
95 // Call the trace source
96 if (m_device)
97 {
98 m_startSending(packet, m_device->GetNode()->GetId());
99 }
100 else
101 {
102 m_startSending(packet, 0);
103 }
104}
105
106void
108 double rxPowerDbm,
109 uint8_t sf,
110 Time duration,
111 double frequencyMHz)
112{
113 NS_LOG_FUNCTION(this << packet << rxPowerDbm << unsigned(sf) << duration << frequencyMHz);
114
115 // Notify the LoraInterferenceHelper of the impinging signal, and remember
116 // the event it creates. This will be used then to correctly handle the end
117 // of reception event.
118 //
119 // We need to do this regardless of our state or frequency, since these could
120 // change (and making the interference relevant) while the interference is
121 // still incoming.
122
124 event = m_interference.Add(duration, rxPowerDbm, sf, packet, frequencyMHz);
125
126 // Switch on the current PHY state
127 switch (m_state)
128 {
129 // In the SLEEP, TX and RX cases we cannot receive the packet: we only add
130 // it to the list of interferers and do not schedule an EndReceive event for
131 // it.
132 case SLEEP: {
133 NS_LOG_INFO("Dropping packet because device is in SLEEP state");
134 break;
135 }
136 case TX: {
137 NS_LOG_INFO("Dropping packet because device is in TX state");
138 break;
139 }
140 case RX: {
141 NS_LOG_INFO("Dropping packet because device is already in RX state");
142 break;
143 }
144 // If we are in STANDBY mode, we can potentially lock on the currently
145 // incoming transmission
146 case STANDBY: {
147 // There are a series of properties the packet needs to respect in order
148 // for us to be able to lock on it:
149 // - It's on frequency we are listening on
150 // - It uses the spreading factor we are configured to look for
151 // - Its receive power is above the device sensitivity for that spreading factor
152
153 // Flag to signal whether we can receive the packet or not
154 bool canLockOnPacket = true;
155
156 // Save needed sensitivity
157 double sensitivity = EndDeviceLoraPhy::sensitivity[unsigned(sf) - 7];
158
159 // Check frequency
160 //////////////////
161 if (!IsOnFrequency(frequencyMHz))
162 {
163 NS_LOG_INFO("Packet lost because it's on frequency "
164 << frequencyMHz << " MHz and we are listening at " << m_frequency
165 << " MHz");
166
167 // Fire the trace source for this event.
168 if (m_device)
169 {
170 m_wrongFrequency(packet, m_device->GetNode()->GetId());
171 }
172 else
173 {
174 m_wrongFrequency(packet, 0);
175 }
176
177 canLockOnPacket = false;
178 }
179
180 // Check Spreading Factor
181 /////////////////////////
182 if (sf != m_sf)
183 {
184 NS_LOG_INFO("Packet lost because it's using SF"
185 << unsigned(sf) << ", while we are listening for SF" << unsigned(m_sf));
186
187 // Fire the trace source for this event.
188 if (m_device)
189 {
190 m_wrongSf(packet, m_device->GetNode()->GetId());
191 }
192 else
193 {
194 m_wrongSf(packet, 0);
195 }
196
197 canLockOnPacket = false;
198 }
199
200 // Check Sensitivity
201 ////////////////////
202 if (rxPowerDbm < sensitivity)
203 {
204 NS_LOG_INFO("Dropping packet reception of packet with sf = "
205 << unsigned(sf) << " because under the sensitivity of " << sensitivity
206 << " dBm");
207
208 // Fire the trace source for this event.
209 if (m_device)
210 {
211 m_underSensitivity(packet, m_device->GetNode()->GetId());
212 }
213 else
214 {
215 m_underSensitivity(packet, 0);
216 }
217
218 canLockOnPacket = false;
219 }
220
221 // Check if one of the above failed
222 ///////////////////////////////////
223 if (canLockOnPacket)
224 {
225 // Switch to RX state
226 // EndReceive will handle the switch back to STANDBY state
227 SwitchToRx();
228
229 // Schedule the end of the reception of the packet
230 NS_LOG_INFO("Scheduling reception of a packet. End in " << duration.GetSeconds()
231 << " seconds");
232
233 Simulator::Schedule(duration, &LoraPhy::EndReceive, this, packet, event);
234
235 // Fire the beginning of reception trace source
236 m_phyRxBeginTrace(packet);
237 }
238 }
239 }
240}
241
242void
244{
245 NS_LOG_FUNCTION(this << packet << event);
246
247 // Automatically switch to Standby in either case
249
250 // Fire the trace source
251 m_phyRxEndTrace(packet);
252
253 // Call the LoraInterferenceHelper to determine whether there was destructive
254 // interference on this event.
255 bool packetDestroyed = m_interference.IsDestroyedByInterference(event);
256
257 // Fire the trace source if packet was destroyed
258 if (packetDestroyed)
259 {
260 NS_LOG_INFO("Packet destroyed by interference");
261
262 if (m_device)
263 {
264 m_interferedPacket(packet, m_device->GetNode()->GetId());
265 }
266 else
267 {
268 m_interferedPacket(packet, 0);
269 }
270
271 // If there is one, perform the callback to inform the upper layer of the
272 // lost packet
274 {
275 m_rxFailedCallback(packet);
276 }
277 }
278 else
279 {
280 NS_LOG_INFO("Packet received correctly");
281
282 if (m_device)
283 {
284 m_successfullyReceivedPacket(packet, m_device->GetNode()->GetId());
285 }
286 else
287 {
289 }
290
291 // If there is one, perform the callback to inform the upper layer
292 if (!m_rxOkCallback.IsNull())
293 {
294 m_rxOkCallback(packet);
295 }
296 }
297}
298} // namespace lorawan
299} // namespace ns3
bool IsNull() const
Check for null implementation.
Definition: callback.h:571
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Class representing a LoRa transceiver.
bool IsOnFrequency(double frequencyMHz) override
Whether this device is listening on the specified frequency or not.
static const double sensitivity[6]
The sensitivity vector of this device to different SFs.
uint8_t m_sf
The Spreading Factor this device is listening for.
void SwitchToRx()
Switch to the RX state.
void SwitchToStandby()
Switch to the STANDBY state.
TracedValue< State > m_state
The state this PHY is currently in.
TracedCallback< Ptr< const Packet >, uint32_t > m_wrongSf
Trace source for when a packet is lost because it was using a spreading factor different from the one...
void SwitchToTx(double txPowerDbm)
Switch to the TX state.
@ RX
The PHY layer is receiving a packet.
@ TX
The PHY layer is sending a packet.
@ SLEEP
The PHY layer is sleeping.
@ STANDBY
The PHY layer is in STANDBY.
void TxFinished(Ptr< const Packet > packet) override
Signals the end of a transmission by the EndDeviceLoraPhy.
double m_frequency
The frequency this device is listening on.
TracedCallback< Ptr< const Packet >, uint32_t > m_wrongFrequency
Trace source for when a packet is lost because it was transmitted on a frequency different from the o...
Ptr< LoraInterferenceHelper::Event > Add(Time duration, double rxPower, uint8_t spreadingFactor, Ptr< Packet > packet, double frequencyMHz)
Add an event to the InterferenceHelper.
uint8_t IsDestroyedByInterference(Ptr< LoraInterferenceHelper::Event > event)
Determine whether the event was destroyed by interference or not.
TracedCallback< Ptr< const Packet > > m_phyRxEndTrace
The trace source fired when a packet reception ends.
Definition: lora-phy.h:307
LoraInterferenceHelper m_interference
The LoraInterferenceHelper associated to this PHY.
Definition: lora-phy.h:289
static Time GetOnAirTime(Ptr< Packet > packet, LoraTxParameters txParams)
Compute the time that a packet with certain characteristics will take to be transmitted.
Definition: lora-phy.cc:167
TracedCallback< Ptr< const Packet >, uint32_t > m_interferedPacket
The trace source fired when a packet cannot be correctly received because of interference.
Definition: lora-phy.h:324
RxFailedCallback m_rxFailedCallback
The callback to perform upon failed reception of a packet we were locked on.
Definition: lora-phy.h:336
virtual void EndReceive(Ptr< Packet > packet, Ptr< LoraInterferenceHelper::Event > event)=0
Finish reception of a packet.
TracedCallback< Ptr< const Packet >, uint32_t > m_successfullyReceivedPacket
The trace source fired when a packet was correctly received.
Definition: lora-phy.h:312
TracedCallback< Ptr< const Packet >, uint32_t > m_startSending
The trace source fired when a packet is sent.
Definition: lora-phy.h:296
TracedCallback< Ptr< const Packet >, uint32_t > m_underSensitivity
The trace source fired when a packet cannot be received because its power is below the sensitivity th...
Definition: lora-phy.h:318
Ptr< NetDevice > m_device
The net device this PHY is attached to.
Definition: lora-phy.h:285
TracedCallback< Ptr< const Packet > > m_phyRxBeginTrace
The trace source fired when a packet begins the reception process from the medium.
Definition: lora-phy.h:302
Ptr< LoraChannel > m_channel
The channel this PHY transmits on.
Definition: lora-phy.h:287
RxOkCallback m_rxOkCallback
The callback to perform upon correct reception of a packet.
Definition: lora-phy.h:331
Tag used to save various data about a packet, like its Spreading Factor and data about interference.
Definition: lora-tag.h:37
void SetSpreadingFactor(uint8_t sf)
Set which Spreading Factor this packet was transmitted with.
Definition: lora-tag.cc:118
Class representing a simple LoRa transceiver, with an error model based on receiver sensitivity and a...
void StartReceive(Ptr< Packet > packet, double rxPowerDbm, uint8_t sf, Time duration, double frequencyMHz) override
Start receiving a packet.
static TypeId GetTypeId()
Register this type.
void Send(Ptr< Packet > packet, LoraTxParameters txParams, double frequencyMHz, double txPowerDbm) override
Instruct the PHY to send a packet according to some parameters.
void EndReceive(Ptr< Packet > packet, Ptr< LoraInterferenceHelper::Event > event) override
Finish reception of a packet.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Structure to collect all parameters that are used to compute the duration of a packet (excluding payl...
Definition: lora-phy.h:49
uint8_t sf
Spreading Factor.
Definition: lora-phy.h:50