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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Davide Magrin <magrinda@dei.unipd.it>
7 */
8
10
11#include "lora-tag.h"
12
13#include "ns3/log.h"
14#include "ns3/simulator.h"
15
16#include <algorithm>
17
18namespace ns3
19{
20namespace lorawan
21{
22
23NS_LOG_COMPONENT_DEFINE("SimpleEndDeviceLoraPhy");
24
25NS_OBJECT_ENSURE_REGISTERED(SimpleEndDeviceLoraPhy);
26
27TypeId
29{
30 static TypeId tid = TypeId("ns3::SimpleEndDeviceLoraPhy")
32 .SetGroupName("lorawan")
33 .AddConstructor<SimpleEndDeviceLoraPhy>();
34
35 return tid;
36}
37
38// Initialize the device with some common settings.
39// These will then be changed by helpers.
43
47
48void
50 LoraTxParameters txParams,
51 uint32_t frequencyHz,
52 double txPowerDbm)
53{
54 NS_LOG_FUNCTION(this << packet << txParams << frequencyHz << txPowerDbm);
55
56 NS_LOG_INFO("Current state: " << m_state);
57
58 // We must be either in STANDBY or SLEEP mode to send a packet
59 if (m_state != STANDBY && m_state != SLEEP)
60 {
61 NS_LOG_INFO("Cannot send because device is currently not in STANDBY or SLEEP mode");
62 return;
63 }
64
65 // Compute the duration of the transmission
66 Time duration = GetOnAirTime(packet, txParams);
67
68 // We can send the packet: switch to the TX state
69 SwitchToTx(txPowerDbm);
70
71 // Tag the packet with information about its Spreading Factor
72 LoraTag tag;
73 packet->RemovePacketTag(tag);
74 tag.SetSpreadingFactor(txParams.sf);
75 packet->AddPacketTag(tag);
76
77 // Send the packet over the channel
78 NS_LOG_INFO("Sending the packet in the channel");
79 m_channel->Send(this, packet, txPowerDbm, txParams, duration, frequencyHz);
80
81 // Schedule a call to signal the transmission end.
83
84 // Call the trace source
85 if (m_device)
86 {
87 m_startSending(packet, m_device->GetNode()->GetId());
88 }
89 else
90 {
91 m_startSending(packet, 0);
92 }
93}
94
95void
97 double rxPowerDbm,
98 uint8_t sf,
99 Time duration,
100 uint32_t frequencyHz)
101{
102 NS_LOG_FUNCTION(this << packet << rxPowerDbm << unsigned(sf) << duration << frequencyHz);
103
104 // Notify the LoraInterferenceHelper of the impinging signal, and remember
105 // the event it creates. This will be used then to correctly handle the end
106 // of reception event.
107 //
108 // We need to do this regardless of our state or frequency, since these could
109 // change (and making the interference relevant) while the interference is
110 // still incoming.
111
113 event = m_interference.Add(duration, rxPowerDbm, sf, packet, frequencyHz);
114
115 // Switch on the current PHY state
116 switch (m_state)
117 {
118 // In the SLEEP, TX and RX cases we cannot receive the packet: we only add
119 // it to the list of interferers and do not schedule an EndReceive event for
120 // it.
121 case SLEEP: {
122 NS_LOG_INFO("Dropping packet because device is in SLEEP state");
123 break;
124 }
125 case TX: {
126 NS_LOG_INFO("Dropping packet because device is in TX state");
127 break;
128 }
129 case RX: {
130 NS_LOG_INFO("Dropping packet because device is already in RX state");
131 break;
132 }
133 // If we are in STANDBY mode, we can potentially lock on the currently
134 // incoming transmission
135 case STANDBY: {
136 // There are a series of properties the packet needs to respect in order
137 // for us to be able to lock on it:
138 // - It's on frequency we are listening on
139 // - It uses the spreading factor we are configured to look for
140 // - Its receive power is above the device sensitivity for that spreading factor
141
142 // Flag to signal whether we can receive the packet or not
143 bool canLockOnPacket = true;
144
145 // Save needed sensitivity
146 double sensitivity = EndDeviceLoraPhy::sensitivity[unsigned(sf) - 7];
147
148 // Check frequency
149 //////////////////
150 if (!IsOnFrequency(frequencyHz))
151 {
152 NS_LOG_INFO("Packet lost because it's on frequency "
153 << frequencyHz << " Hz and we are listening at " << m_frequencyHz << " Hz");
154
155 // Fire the trace source for this event.
156 if (m_device)
157 {
158 m_wrongFrequency(packet, m_device->GetNode()->GetId());
159 }
160 else
161 {
162 m_wrongFrequency(packet, 0);
163 }
164
165 canLockOnPacket = false;
166 }
167
168 // Check Spreading Factor
169 /////////////////////////
170 if (sf != m_sf)
171 {
172 NS_LOG_INFO("Packet lost because it's using SF"
173 << unsigned(sf) << ", while we are listening for SF" << unsigned(m_sf));
174
175 // Fire the trace source for this event.
176 if (m_device)
177 {
178 m_wrongSf(packet, m_device->GetNode()->GetId());
179 }
180 else
181 {
182 m_wrongSf(packet, 0);
183 }
184
185 canLockOnPacket = false;
186 }
187
188 // Check Sensitivity
189 ////////////////////
190 if (rxPowerDbm < sensitivity)
191 {
192 NS_LOG_INFO("Dropping packet reception of packet with sf = "
193 << unsigned(sf) << " because under the sensitivity of " << sensitivity
194 << " dBm");
195
196 // Fire the trace source for this event.
197 if (m_device)
198 {
199 m_underSensitivity(packet, m_device->GetNode()->GetId());
200 }
201 else
202 {
203 m_underSensitivity(packet, 0);
204 }
205
206 canLockOnPacket = false;
207 }
208
209 // Check if one of the above failed
210 ///////////////////////////////////
211 if (canLockOnPacket)
212 {
213 // Switch to RX state
214 // EndReceive will handle the switch back to STANDBY state
215 SwitchToRx();
216
217 // Schedule the end of the reception of the packet
218 NS_LOG_INFO("Scheduling reception of a packet. End in " << duration.As(Time::S));
219
220 Simulator::Schedule(duration, &LoraPhy::EndReceive, this, packet, event);
221
222 // Fire the beginning of reception trace source
223 m_phyRxBeginTrace(packet);
224 }
225 }
226 }
227}
228
229void
231{
232 NS_LOG_FUNCTION(this << packet << event);
233
234 // Automatically switch to Standby in either case
236
237 // Fire the trace source
238 m_phyRxEndTrace(packet);
239
240 // Call the LoraInterferenceHelper to determine whether there was destructive
241 // interference on this event.
242 bool packetDestroyed = m_interference.IsDestroyedByInterference(event);
243
244 // Fire the trace source if packet was destroyed
245 if (packetDestroyed)
246 {
247 NS_LOG_INFO("Packet destroyed by interference");
248
249 if (m_device)
250 {
251 m_interferedPacket(packet, m_device->GetNode()->GetId());
252 }
253 else
254 {
255 m_interferedPacket(packet, 0);
256 }
257
258 // If there is one, perform the callback to inform the upper layer of the
259 // lost packet
261 {
262 m_rxFailedCallback(packet);
263 }
264 }
265 else
266 {
267 NS_LOG_INFO("Packet received correctly");
268
269 if (m_device)
270 {
271 m_successfullyReceivedPacket(packet, m_device->GetNode()->GetId());
272 }
273 else
274 {
276 }
277
278 // If there is one, perform the callback to inform the upper layer
279 if (!m_rxOkCallback.IsNull())
280 {
281 LoraTag tag;
282 packet->RemovePacketTag(tag);
283 tag.SetReceivePower(event->GetRxPowerdBm());
284 tag.SetFrequency(event->GetFrequency());
285 packet->AddPacketTag(tag);
286 m_rxOkCallback(packet);
287 }
288 }
289}
290} // namespace lorawan
291} // namespace ns3
bool IsNull() const
Check for null implementation.
Definition callback.h:555
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:404
@ S
second
Definition nstime.h:105
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Class representing a LoRa transceiver.
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.
bool IsOnFrequency(uint32_t frequencyHz) override
Whether this device is listening on the specified frequency or not.
void SwitchToRx()
Switch to the RX state.
void SwitchToStandby()
Switch to the STANDBY state.
uint32_t m_frequencyHz
The frequency [Hz] this device is listening on.
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.
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, uint32_t frequencyHz)
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:296
LoraInterferenceHelper m_interference
The LoraInterferenceHelper associated to this PHY.
Definition lora-phy.h:278
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:156
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:313
RxFailedCallback m_rxFailedCallback
The callback to perform upon failed reception of a packet we were locked on.
Definition lora-phy.h:325
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:301
TracedCallback< Ptr< const Packet >, uint32_t > m_startSending
The trace source fired when a packet is sent.
Definition lora-phy.h:285
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:307
Ptr< NetDevice > m_device
The net device this PHY is attached to.
Definition lora-phy.h:274
TracedCallback< Ptr< const Packet > > m_phyRxBeginTrace
The trace source fired when a packet begins the reception process from the medium.
Definition lora-phy.h:291
Ptr< LoraChannel > m_channel
The channel this PHY transmits on.
Definition lora-phy.h:276
RxOkCallback m_rxOkCallback
The callback to perform upon correct reception of a packet.
Definition lora-phy.h:320
Tag used to save various data about a packet, like its Spreading Factor and data about interference.
Definition lora-tag.h:26
void SetFrequency(uint32_t frequencyHz)
Set the frequency of the packet.
Definition lora-tag.cc:119
void SetSpreadingFactor(uint8_t sf)
Set which Spreading Factor this packet was transmitted with.
Definition lora-tag.cc:107
void SetReceivePower(double receivePower)
Set the power this packet was received with.
Definition lora-tag.cc:113
Class representing a simple LoRa transceiver, with an error model based on receiver sensitivity and a...
void Send(Ptr< Packet > packet, LoraTxParameters txParams, uint32_t frequencyHz, double txPowerDbm) override
Instruct the PHY to send a packet according to some parameters.
static TypeId GetTypeId()
Register this type.
void StartReceive(Ptr< Packet > packet, double rxPowerDbm, uint8_t sf, Time duration, uint32_t frequencyHz) override
Start receiving a packet.
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:191
#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:264
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
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:38
uint8_t sf
Spreading Factor.
Definition lora-phy.h:39