A Discrete-Event Network Simulator
API
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 
22 #include "wifi-tx-current-model.h"
23 
24 #include "ns3/energy-source.h"
25 #include "ns3/log.h"
26 #include "ns3/pointer.h"
27 #include "ns3/simulator.h"
28 
29 namespace ns3
30 {
31 
32 NS_LOG_COMPONENT_DEFINE("WifiRadioEnergyModel");
33 
34 NS_OBJECT_ENSURE_REGISTERED(WifiRadioEnergyModel);
35 
36 TypeId
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.",
82  PointerValue(),
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 
116 void
118 {
119  NS_LOG_FUNCTION(this << source);
120  NS_ASSERT(source);
121  m_source = source;
123  Time durationToOff = GetMaximumTimeInState(m_currentState);
124  m_switchToOffEvent = Simulator::Schedule(durationToOff,
126  this,
128 }
129 
130 double
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 
148 double
150 {
151  NS_LOG_FUNCTION(this);
152  return m_idleCurrentA;
153 }
154 
155 void
157 {
158  NS_LOG_FUNCTION(this << idleCurrentA);
159  m_idleCurrentA = idleCurrentA;
160 }
161 
162 double
164 {
165  NS_LOG_FUNCTION(this);
166  return m_ccaBusyCurrentA;
167 }
168 
169 void
171 {
172  NS_LOG_FUNCTION(this << CcaBusyCurrentA);
173  m_ccaBusyCurrentA = CcaBusyCurrentA;
174 }
175 
176 double
178 {
179  NS_LOG_FUNCTION(this);
180  return m_txCurrentA;
181 }
182 
183 void
185 {
186  NS_LOG_FUNCTION(this << txCurrentA);
187  m_txCurrentA = txCurrentA;
188 }
189 
190 double
192 {
193  NS_LOG_FUNCTION(this);
194  return m_rxCurrentA;
195 }
196 
197 void
199 {
200  NS_LOG_FUNCTION(this << rxCurrentA);
201  m_rxCurrentA = rxCurrentA;
202 }
203 
204 double
206 {
207  NS_LOG_FUNCTION(this);
208  return m_switchingCurrentA;
209 }
210 
211 void
213 {
214  NS_LOG_FUNCTION(this << switchingCurrentA);
215  m_switchingCurrentA = switchingCurrentA;
216 }
217 
218 double
220 {
221  NS_LOG_FUNCTION(this);
222  return m_sleepCurrentA;
223 }
224 
225 void
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 
239 void
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 
250 void
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 
261 void
263 {
264  m_txCurrentModel = model;
265 }
266 
267 void
269 {
270  if (m_txCurrentModel)
271  {
272  m_txCurrentA = m_txCurrentModel->CalcTxCurrent(txPowerDbm);
273  }
274 }
275 
276 Time
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 
289 void
291 {
292  NS_LOG_FUNCTION(this << newState);
293 
295 
296  if (m_nPendingChangeState > 1 && newState == WifiPhyState::OFF)
297  {
298  SetWifiRadioState((WifiPhyState)newState);
300  return;
301  }
302 
303  if (newState != WifiPhyState::OFF)
304  {
306  Time durationToOff = GetMaximumTimeInState(newState);
307  m_switchToOffEvent = Simulator::Schedule(durationToOff,
309  this,
311  }
312 
313  Time duration = Simulator::Now() - m_lastUpdateTime;
314  NS_ASSERT(duration.IsPositive()); // check if duration is valid
315 
316  // energy to decrease = current * voltage * time
317  double supplyVoltage = m_source->GetSupplyVoltage();
318  double energyToDecrease = duration.GetSeconds() * GetStateA(m_currentState) * supplyVoltage;
319 
320  // update total energy consumption
321  m_totalEnergyConsumption += energyToDecrease;
322  NS_ASSERT(m_totalEnergyConsumption <= m_source->GetInitialEnergy());
323 
324  // update last update time stamp
326 
327  // notify energy source
328  m_source->UpdateEnergySource();
329 
330  // in case the energy source is found to be depleted during the last update, a callback might be
331  // invoked that might cause a change in the Wifi PHY state (e.g., the PHY is put into SLEEP
332  // mode). This in turn causes a new call to this member function, with the consequence that the
333  // previous instance is resumed after the termination of the new instance. In particular, the
334  // state set by the previous instance is erroneously the final state stored in m_currentState.
335  // The check below ensures that previous instances do not change m_currentState.
336 
338  {
339  // update current state & last update time stamp
340  SetWifiRadioState((WifiPhyState)newState);
341 
342  // some debug message
343  NS_LOG_DEBUG("WifiRadioEnergyModel:Total energy consumption is " << m_totalEnergyConsumption
344  << "J");
345  }
346 
348 }
349 
350 void
352 {
353  NS_LOG_FUNCTION(this);
354  NS_LOG_DEBUG("WifiRadioEnergyModel:Energy is depleted!");
355  // invoke energy depletion callback, if set.
357  {
359  }
360 }
361 
362 void
364 {
365  NS_LOG_FUNCTION(this);
366  NS_LOG_DEBUG("WifiRadioEnergyModel:Energy is recharged!");
367  // invoke energy recharged callback, if set.
369  {
371  }
372 }
373 
374 void
376 {
377  NS_LOG_FUNCTION(this);
378  NS_LOG_DEBUG("WifiRadioEnergyModel:Energy is changed!");
380  {
382  Time durationToOff = GetMaximumTimeInState(m_currentState);
383  m_switchToOffEvent = Simulator::Schedule(durationToOff,
385  this,
387  }
388 }
389 
390 std::shared_ptr<WifiRadioEnergyModelPhyListener>
392 {
393  NS_LOG_FUNCTION(this);
394  return m_listener;
395 }
396 
397 /*
398  * Private functions start here.
399  */
400 
401 void
403 {
404  NS_LOG_FUNCTION(this);
405  m_source = nullptr;
407 }
408 
409 double
411 {
412  switch (state)
413  {
414  case WifiPhyState::IDLE:
415  return m_idleCurrentA;
417  return m_ccaBusyCurrentA;
418  case WifiPhyState::TX:
419  return m_txCurrentA;
420  case WifiPhyState::RX:
421  return m_rxCurrentA;
423  return m_switchingCurrentA;
424  case WifiPhyState::SLEEP:
425  return m_sleepCurrentA;
426  case WifiPhyState::OFF:
427  return 0.0;
428  }
429  NS_FATAL_ERROR("WifiRadioEnergyModel: undefined radio state " << state);
430 }
431 
432 double
434 {
435  return GetStateA(m_currentState);
436 }
437 
438 void
440 {
441  NS_LOG_FUNCTION(this << state);
442  m_currentState = state;
443  std::string stateName;
444  switch (state)
445  {
446  case WifiPhyState::IDLE:
447  stateName = "IDLE";
448  break;
450  stateName = "CCA_BUSY";
451  break;
452  case WifiPhyState::TX:
453  stateName = "TX";
454  break;
455  case WifiPhyState::RX:
456  stateName = "RX";
457  break;
459  stateName = "SWITCHING";
460  break;
461  case WifiPhyState::SLEEP:
462  stateName = "SLEEP";
463  break;
464  case WifiPhyState::OFF:
465  stateName = "OFF";
466  break;
467  }
468  NS_LOG_DEBUG("WifiRadioEnergyModel:Switching to state: " << stateName
469  << " at time = " << Simulator::Now());
470 }
471 
472 // -------------------------------------------------------------------------- //
473 
475 {
476  NS_LOG_FUNCTION(this);
479 }
480 
482 {
483  NS_LOG_FUNCTION(this);
484 }
485 
486 void
489 {
490  NS_LOG_FUNCTION(this << &callback);
491  NS_ASSERT(!callback.IsNull());
492  m_changeStateCallback = callback;
493 }
494 
495 void
497 {
498  NS_LOG_FUNCTION(this << &callback);
499  NS_ASSERT(!callback.IsNull());
500  m_updateTxCurrentCallback = callback;
501 }
502 
503 void
505 {
506  NS_LOG_FUNCTION(this << duration);
508  {
509  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
510  }
513 }
514 
515 void
517 {
518  NS_LOG_FUNCTION(this);
520  {
521  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
522  }
524 }
525 
526 void
528 {
529  NS_LOG_FUNCTION(this);
531  {
532  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
533  }
535 }
536 
537 void
539 {
540  NS_LOG_FUNCTION(this << duration << txPowerDbm);
542  {
543  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Update tx current callback not set!");
544  }
545  m_updateTxCurrentCallback(txPowerDbm);
547  {
548  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
549  }
551  // schedule changing state back to IDLE after TX duration
555 }
556 
557 void
559  WifiChannelListType channelType,
560  const std::vector<Time>& /*per20MhzDurations*/)
561 {
562  NS_LOG_FUNCTION(this << duration << channelType);
564  {
565  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
566  }
568  // schedule changing state back to IDLE after CCA_BUSY duration
572 }
573 
574 void
576 {
577  NS_LOG_FUNCTION(this << duration);
579  {
580  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
581  }
583  // schedule changing state back to IDLE after CCA_BUSY duration
587 }
588 
589 void
591 {
592  NS_LOG_FUNCTION(this);
594  {
595  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
596  }
599 }
600 
601 void
603 {
604  NS_LOG_FUNCTION(this);
606  {
607  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
608  }
610 }
611 
612 void
614 {
615  NS_LOG_FUNCTION(this);
617  {
618  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
619  }
622 }
623 
624 void
626 {
627  NS_LOG_FUNCTION(this);
629  {
630  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
631  }
633 }
634 
635 void
637 {
638  NS_LOG_FUNCTION(this);
640  {
641  NS_FATAL_ERROR("WifiRadioEnergyModelPhyListener:Change state callback not set!");
642  }
644 }
645 
646 } // 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
Hold objects of type Ptr<T>.
Definition: pointer.h:37
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:931
A WiFi radio energy model.
double GetStateA(int state) const
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
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.
Time GetMaximumTimeInState(int state) const
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.
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
#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.
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
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43
@ IDLE
Channel is IDLE, no packet is being transmitted.
Definition: csma-channel.h:76
WifiPhyState
The state of the PHY layer.
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ SWITCHING
The PHY layer is switching to other channel.
@ RX
The PHY layer is receiving a packet.
@ TX
The PHY layer is sending a packet.
@ OFF
The PHY layer is switched off.
@ SLEEP
The PHY layer is sleeping.
@ IDLE
The PHY layer is IDLE.