A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-radio-energy-model.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010 Network Security Lab, University of Washington, Seattle.
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: Sidharth Nabar <snabar@uw.edu>, He Wu <mdzz@u.washington.edu>
18 */
19
21
23
24#include "ns3/energy-source.h"
25#include "ns3/log.h"
26#include "ns3/pointer.h"
27#include "ns3/simulator.h"
28
29namespace ns3
30{
31
32NS_LOG_COMPONENT_DEFINE("WifiRadioEnergyModel");
33
34NS_OBJECT_ENSURE_REGISTERED(WifiRadioEnergyModel);
35
36TypeId
38{
39 static TypeId tid =
40 TypeId("ns3::WifiRadioEnergyModel")
42 .SetGroupName("Energy")
43 .AddConstructor<WifiRadioEnergyModel>()
44 .AddAttribute("IdleCurrentA",
45 "The default radio Idle current in Ampere.",
46 DoubleValue(0.273), // idle mode = 273mA
49 MakeDoubleChecker<double>())
50 .AddAttribute("CcaBusyCurrentA",
51 "The default radio CCA Busy State current in Ampere.",
52 DoubleValue(0.273), // default to be the same as idle mode
55 MakeDoubleChecker<double>())
56 .AddAttribute("TxCurrentA",
57 "The radio TX current in Ampere.",
58 DoubleValue(0.380), // transmit at 0dBm = 380mA
61 MakeDoubleChecker<double>())
62 .AddAttribute("RxCurrentA",
63 "The radio RX current in Ampere.",
64 DoubleValue(0.313), // receive mode = 313mA
67 MakeDoubleChecker<double>())
68 .AddAttribute("SwitchingCurrentA",
69 "The default radio Channel Switch current in Ampere.",
70 DoubleValue(0.273), // default to be the same as idle mode
73 MakeDoubleChecker<double>())
74 .AddAttribute("SleepCurrentA",
75 "The radio Sleep current in Ampere.",
76 DoubleValue(0.033), // sleep mode = 33mA
79 MakeDoubleChecker<double>())
80 .AddAttribute("TxCurrentModel",
81 "A pointer to the attached TX current model.",
84 MakePointerChecker<WifiTxCurrentModel>())
85 .AddTraceSource(
86 "TotalEnergyConsumption",
87 "Total energy consumption of the radio device.",
89 "ns3::TracedValueCallback::Double");
90 return tid;
91}
92
94 : m_source(nullptr),
95 m_currentState(WifiPhyState::IDLE),
96 m_lastUpdateTime(Seconds(0.0)),
97 m_nPendingChangeState(0)
98{
99 NS_LOG_FUNCTION(this);
101 // set callback for WifiPhy listener
102 m_listener = std::make_shared<WifiRadioEnergyModelPhyListener>();
103 m_listener->SetChangeStateCallback(MakeCallback(&DeviceEnergyModel::ChangeState, this));
104 // set callback for updating the TX current
105 m_listener->SetUpdateTxCurrentCallback(
107}
108
110{
111 NS_LOG_FUNCTION(this);
112 m_txCurrentModel = nullptr;
113 m_listener.reset();
114}
115
116void
118{
119 NS_LOG_FUNCTION(this << source);
120 NS_ASSERT(source);
121 m_source = source;
126 this,
127 static_cast<int>(WifiPhyState::OFF));
128}
129
130double
132{
133 NS_LOG_FUNCTION(this);
134
135 Time duration = Simulator::Now() - m_lastUpdateTime;
136 NS_ASSERT(duration.IsPositive()); // check if duration is valid
137
138 // energy to decrease = current * voltage * time
139 double supplyVoltage = m_source->GetSupplyVoltage();
140 double energyToDecrease = duration.GetSeconds() * GetStateA(m_currentState) * supplyVoltage;
141
142 // notify energy source
143 m_source->UpdateEnergySource();
144
145 return m_totalEnergyConsumption + energyToDecrease;
146}
147
148double
150{
151 NS_LOG_FUNCTION(this);
152 return m_idleCurrentA;
153}
154
155void
157{
158 NS_LOG_FUNCTION(this << idleCurrentA);
159 m_idleCurrentA = idleCurrentA;
160}
161
162double
164{
165 NS_LOG_FUNCTION(this);
166 return m_ccaBusyCurrentA;
167}
168
169void
171{
172 NS_LOG_FUNCTION(this << CcaBusyCurrentA);
173 m_ccaBusyCurrentA = CcaBusyCurrentA;
174}
175
176double
178{
179 NS_LOG_FUNCTION(this);
180 return m_txCurrentA;
181}
182
183void
185{
186 NS_LOG_FUNCTION(this << txCurrentA);
187 m_txCurrentA = txCurrentA;
188}
189
190double
192{
193 NS_LOG_FUNCTION(this);
194 return m_rxCurrentA;
195}
196
197void
199{
200 NS_LOG_FUNCTION(this << rxCurrentA);
201 m_rxCurrentA = rxCurrentA;
202}
203
204double
206{
207 NS_LOG_FUNCTION(this);
208 return m_switchingCurrentA;
209}
210
211void
213{
214 NS_LOG_FUNCTION(this << switchingCurrentA);
215 m_switchingCurrentA = switchingCurrentA;
216}
217
218double
220{
221 NS_LOG_FUNCTION(this);
222 return m_sleepCurrentA;
223}
224
225void
227{
228 NS_LOG_FUNCTION(this << sleepCurrentA);
229 m_sleepCurrentA = sleepCurrentA;
230}
231
234{
235 NS_LOG_FUNCTION(this);
236 return m_currentState;
237}
238
239void
241{
242 NS_LOG_FUNCTION(this);
243 if (callback.IsNull())
244 {
245 NS_LOG_DEBUG("WifiRadioEnergyModel:Setting NULL energy depletion callback!");
246 }
247 m_energyDepletionCallback = callback;
248}
249
250void
252{
253 NS_LOG_FUNCTION(this);
254 if (callback.IsNull())
255 {
256 NS_LOG_DEBUG("WifiRadioEnergyModel:Setting NULL energy recharged callback!");
257 }
258 m_energyRechargedCallback = callback;
259}
260
261void
263{
264 m_txCurrentModel = model;
265}
266
267void
269{
271 {
272 m_txCurrentA = m_txCurrentModel->CalcTxCurrent(txPowerDbm);
273 }
274}
275
276Time
278{
279 if (state == WifiPhyState::OFF)
280 {
281 NS_FATAL_ERROR("Requested maximum remaining time for OFF state");
282 }
283 double remainingEnergy = m_source->GetRemainingEnergy();
284 double supplyVoltage = m_source->GetSupplyVoltage();
285 double current = GetStateA(state);
286 return Seconds(remainingEnergy / (current * supplyVoltage));
287}
288
289void
291{
292 WifiPhyState newPhyState{newState};
293 NS_LOG_FUNCTION(this << newPhyState);
294
296
297 if (m_nPendingChangeState > 1 && newPhyState == WifiPhyState::OFF)
298 {
299 SetWifiRadioState(newPhyState);
301 return;
302 }
303
304 if (newPhyState != WifiPhyState::OFF)
305 {
307 Time durationToOff = GetMaximumTimeInState(newPhyState);
310 this,
311 static_cast<int>(WifiPhyState::OFF));
312 }
313
314 Time duration = Simulator::Now() - m_lastUpdateTime;
315 NS_ASSERT(duration.IsPositive()); // check if duration is valid
316
317 // energy to decrease = current * voltage * time
318 double supplyVoltage = m_source->GetSupplyVoltage();
319 double energyToDecrease = duration.GetSeconds() * GetStateA(m_currentState) * supplyVoltage;
320
321 // update total energy consumption
322 m_totalEnergyConsumption += energyToDecrease;
323 NS_ASSERT(m_totalEnergyConsumption <= m_source->GetInitialEnergy());
324
325 // update last update time stamp
327
328 // notify energy source
329 m_source->UpdateEnergySource();
330
331 // in case the energy source is found to be depleted during the last update, a callback might be
332 // invoked that might cause a change in the Wifi PHY state (e.g., the PHY is put into SLEEP
333 // mode). This in turn causes a new call to this member function, with the consequence that the
334 // previous instance is resumed after the termination of the new instance. In particular, the
335 // state set by the previous instance is erroneously the final state stored in m_currentState.
336 // The check below ensures that previous instances do not change m_currentState.
337
339 {
340 // update current state & last update time stamp
341 SetWifiRadioState(newPhyState);
342
343 // some debug message
344 NS_LOG_DEBUG("WifiRadioEnergyModel:Total energy consumption is " << m_totalEnergyConsumption
345 << "J");
346 }
347
349}
350
351void
353{
354 NS_LOG_FUNCTION(this);
355 NS_LOG_DEBUG("WifiRadioEnergyModel:Energy is depleted!");
356 // invoke energy depletion callback, if set.
358 {
360 }
361}
362
363void
365{
366 NS_LOG_FUNCTION(this);
367 NS_LOG_DEBUG("WifiRadioEnergyModel:Energy is recharged!");
368 // invoke energy recharged callback, if set.
370 {
372 }
373}
374
375void
377{
378 NS_LOG_FUNCTION(this);
379 NS_LOG_DEBUG("WifiRadioEnergyModel:Energy is changed!");
381 {
386 this,
387 static_cast<int>(WifiPhyState::OFF));
388 }
389}
390
391std::shared_ptr<WifiRadioEnergyModelPhyListener>
393{
394 NS_LOG_FUNCTION(this);
395 return m_listener;
396}
397
398/*
399 * Private functions start here.
400 */
401
402void
404{
405 NS_LOG_FUNCTION(this);
406 m_source = nullptr;
408}
409
410double
412{
413 switch (state)
414 {
416 return m_idleCurrentA;
418 return m_ccaBusyCurrentA;
419 case WifiPhyState::TX:
420 return m_txCurrentA;
421 case WifiPhyState::RX:
422 return m_rxCurrentA;
424 return m_switchingCurrentA;
426 return m_sleepCurrentA;
428 return 0.0;
429 }
430 NS_FATAL_ERROR("WifiRadioEnergyModel: undefined radio state " << state);
431}
432
433double
435{
437}
438
439void
441{
442 NS_LOG_FUNCTION(this << state);
443 m_currentState = state;
444 std::string stateName;
445 switch (state)
446 {
448 stateName = "IDLE";
449 break;
451 stateName = "CCA_BUSY";
452 break;
453 case WifiPhyState::TX:
454 stateName = "TX";
455 break;
456 case WifiPhyState::RX:
457 stateName = "RX";
458 break;
460 stateName = "SWITCHING";
461 break;
463 stateName = "SLEEP";
464 break;
466 stateName = "OFF";
467 break;
468 }
469 NS_LOG_DEBUG("WifiRadioEnergyModel:Switching to state: " << stateName
470 << " at time = " << Simulator::Now());
471}
472
473// -------------------------------------------------------------------------- //
474
476{
477 NS_LOG_FUNCTION(this);
480}
481
483{
484 NS_LOG_FUNCTION(this);
485}
486
487void
490{
491 NS_LOG_FUNCTION(this << &callback);
492 NS_ASSERT(!callback.IsNull());
493 m_changeStateCallback = callback;
494}
495
496void
498{
499 NS_LOG_FUNCTION(this << &callback);
500 NS_ASSERT(!callback.IsNull());
501 m_updateTxCurrentCallback = callback;
502}
503
504void
506{
507 NS_LOG_FUNCTION(this << duration);
509 {
510 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
511 }
512 m_changeStateCallback(static_cast<int>(WifiPhyState::RX));
514}
515
516void
518{
519 NS_LOG_FUNCTION(this);
521 {
522 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
523 }
524 m_changeStateCallback(static_cast<int>(WifiPhyState::IDLE));
525}
526
527void
529{
530 NS_LOG_FUNCTION(this);
532 {
533 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
534 }
535 m_changeStateCallback(static_cast<int>(WifiPhyState::IDLE));
536}
537
538void
540{
541 NS_LOG_FUNCTION(this << duration << txPowerDbm);
543 {
544 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Update tx current callback not set!");
545 }
546 m_updateTxCurrentCallback(txPowerDbm);
548 {
549 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
550 }
551 m_changeStateCallback(static_cast<int>(WifiPhyState::TX));
552 // schedule changing state back to IDLE after TX duration
556}
557
558void
560 WifiChannelListType channelType,
561 const std::vector<Time>& /*per20MhzDurations*/)
562{
563 NS_LOG_FUNCTION(this << duration << channelType);
565 {
566 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
567 }
569 // schedule changing state back to IDLE after CCA_BUSY duration
573}
574
575void
577{
578 NS_LOG_FUNCTION(this << duration);
580 {
581 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
582 }
584 // schedule changing state back to IDLE after CCA_BUSY duration
588}
589
590void
592{
593 NS_LOG_FUNCTION(this);
595 {
596 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
597 }
600}
601
602void
604{
605 NS_LOG_FUNCTION(this);
607 {
608 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
609 }
610 m_changeStateCallback(static_cast<int>(WifiPhyState::IDLE));
611}
612
613void
615{
616 NS_LOG_FUNCTION(this);
618 {
619 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
620 }
621 m_changeStateCallback(static_cast<int>(WifiPhyState::OFF));
623}
624
625void
627{
628 NS_LOG_FUNCTION(this);
630 {
631 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
632 }
633 m_changeStateCallback(static_cast<int>(WifiPhyState::IDLE));
634}
635
636void
638{
639 NS_LOG_FUNCTION(this);
641 {
642 NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
643 }
644 m_changeStateCallback(static_cast<int>(WifiPhyState::IDLE));
645}
646
647} // namespace ns3
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:575
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
Base class for device energy models.
virtual void ChangeState(int newState)=0
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
AttributeValue implementation for Pointer.
Definition: pointer.h:48
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
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
bool IsPositive() const
Exactly equivalent to t >= 0.
Definition: nstime.h:333
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
A WiFi radio energy model.
void HandleEnergyChanged() override
Handles energy changed.
double GetCcaBusyCurrentA() const
Gets CCA busy current in Amperes.
WifiRadioEnergyDepletionCallback m_energyDepletionCallback
Energy depletion callback.
double m_idleCurrentA
idle current in Amperes
double GetStateA(WifiPhyState state) const
WifiPhyState GetCurrentState() const
double m_ccaBusyCurrentA
CCA busy current in Amperes.
void ChangeState(int newState) override
Changes state of the WifiRadioEnergyMode.
void SetCcaBusyCurrentA(double ccaBusyCurrentA)
Sets CCA busy current in Amperes.
WifiRadioEnergyRechargedCallback m_energyRechargedCallback
Energy recharged callback.
double m_sleepCurrentA
sleep current in Amperes
Ptr< EnergySource > m_source
energy source
TracedValue< double > m_totalEnergyConsumption
This variable keeps track of the total energy consumed by this model in watts.
void SetTxCurrentModel(const Ptr< WifiTxCurrentModel > model)
EventId m_switchToOffEvent
switch to off event
void DoDispose() override
Destructor implementation.
void SetRxCurrentA(double rxCurrentA)
Sets receive current in Amperes.
double GetTotalEnergyConsumption() const override
double m_txCurrentA
transmit current in Amperes
void HandleEnergyRecharged() override
Handles energy recharged.
Time m_lastUpdateTime
time stamp of previous energy update
void SetTxCurrentA(double txCurrentA)
Sets transmit current in Amperes.
double GetRxCurrentA() const
Gets receive current in Amperes.
double GetTxCurrentA() const
Gets transmit current in Amperes.
std::shared_ptr< WifiRadioEnergyModelPhyListener > m_listener
WifiPhy listener.
void HandleEnergyDepletion() override
Handles energy depletion.
static TypeId GetTypeId()
Get the type ID.
double GetIdleCurrentA() const
Gets idle current in Amperes.
void SetSwitchingCurrentA(double switchingCurrentA)
Sets switching current in Amperes.
void SetTxCurrentFromModel(double txPowerDbm)
Calls the CalcTxCurrent method of the TX current model to compute the TX current based on such model.
void SetEnergyDepletionCallback(WifiRadioEnergyDepletionCallback callback)
std::shared_ptr< WifiRadioEnergyModelPhyListener > GetPhyListener()
void SetSleepCurrentA(double sleepCurrentA)
Sets sleep current in Amperes.
double m_rxCurrentA
receive current in Amperes
WifiPhyState m_currentState
current state the radio is in
void SetWifiRadioState(const WifiPhyState state)
double GetSleepCurrentA() const
Gets sleep current in Amperes.
Time GetMaximumTimeInState(WifiPhyState state) const
Ptr< WifiTxCurrentModel > m_txCurrentModel
current model
double GetSwitchingCurrentA() const
Gets switching current in Amperes.
void SetIdleCurrentA(double idleCurrentA)
Sets idle current in Amperes.
double DoGetCurrentA() const override
void SetEnergySource(const Ptr< EnergySource > source) override
Sets pointer to EnergySource installed on node.
void SetEnergyRechargedCallback(WifiRadioEnergyRechargedCallback callback)
double m_switchingCurrentA
switching current in Amperes
uint8_t m_nPendingChangeState
pending state change
DeviceEnergyModel::ChangeStateCallback m_changeStateCallback
Change state callback used to notify the WifiRadioEnergyModel of a state change.
void NotifyTxStart(Time duration, double txPowerDbm) override
void NotifySleep() override
Notify listeners that we went to sleep.
void NotifyOff() override
Notify listeners that we went to switch off.
void NotifyRxStart(Time duration) override
void NotifyRxEndOk() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
UpdateTxCurrentCallback m_updateTxCurrentCallback
Callback used to update the TX current stored in WifiRadioEnergyModel based on the nominal TX power u...
void NotifyRxEndError() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void SetUpdateTxCurrentCallback(UpdateTxCurrentCallback callback)
Sets the update TX current callback.
void NotifySwitchingStart(Time duration) override
void SwitchToIdle()
A helper function that makes scheduling m_changeStateCallback possible.
void SetChangeStateCallback(DeviceEnergyModel::ChangeStateCallback callback)
Sets the change state callback.
void NotifyWakeup() override
Notify listeners that we woke up.
EventId m_switchToIdleEvent
switch to idle event
void NotifyOn() override
Notify listeners that we went to switch on.
void NotifyCcaBusyStart(Time duration, WifiChannelListType channelType, const std::vector< Time > &per20MhzDurations) override
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:259
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
Every class exported by the ns3 library is enclosed in the ns3 namespace.
WifiPhyState
The state of the PHY layer.
@ SWITCHING
The PHY layer is switching to other channel.
@ TX
The PHY layer is sending a packet.
@ OFF
The PHY layer is switched off.
@ IDLE
The PHY layer is IDLE.
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ SLEEP
The PHY layer is sleeping.
@ RX
The PHY layer is receiving a packet.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
@ IDLE
Channel is IDLE, no packet is being transmitted.
Definition: csma-channel.h:76