--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/wireless/wifi-sleep.cc Fri Sep 05 16:33:57 2014 -0700
@@ -0,0 +1,247 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 The Boeing Company
+ * 2014 Universita' degli Studi di Napoli "Federico II"
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+//
+// This script configures two nodes on an 802.11b physical layer, with
+// 802.11b NICs in adhoc mode. One of the nodes generates on-off traffic
+// destined to the other node.
+//
+// The purpose is to test the energy depletion on the nodes and the
+// activation of the callback that puts a node in the sleep state when
+// its energy is depleted. Furthermore, this script can be used to test
+// the available policies for updating the transmit current based on
+// the nominal tx power used to transmit each frame.
+//
+// There are a number of command-line options available to control
+// the default behavior. The list of available command-line options
+// can be listed with the following command:
+// ./waf --run "wifi-sleep --help"
+//
+// Note that all ns-3 attributes (not just the ones exposed in the below
+// script) can be changed at command line; see the documentation.
+//
+// This script can also be helpful to put the Wifi layer into verbose
+// logging mode; this command will turn on all wifi logging:
+//
+// ./waf --run "wifi-sleep --verbose=1"
+//
+// When you are done, you will notice four trace files in your directory:
+// two for the remaining energy on each node and two for the state transitions
+// of each node.
+//
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/config-store-module.h"
+#include "ns3/wifi-module.h"
+#include "ns3/internet-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/energy-module.h"
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <string>
+#include <sstream>
+
+NS_LOG_COMPONENT_DEFINE ("WifiSleep");
+
+using namespace ns3;
+
+template <int node>
+void RemainingEnergyTrace (double oldValue, double newValue)
+{
+ std::stringstream ss;
+ ss << "energy_" << node << ".log";
+
+ static std::fstream f (ss.str().c_str(), std::ios::out);
+
+ f << Simulator::Now().GetSeconds() << " remaining energy=" << newValue << std::endl;
+}
+
+template <int node>
+void PhyStateTrace (std::string context, Time start, Time duration, enum WifiPhy::State state)
+{
+ std::stringstream ss;
+ ss << "state_" << node << ".log";
+
+ static std::fstream f (ss.str().c_str(), std::ios::out);
+
+ f << Simulator::Now().GetSeconds() << " state=" << state << " start=" << start << " duration=" << duration << std::endl;
+}
+
+
+
+int main (int argc, char *argv[])
+{
+ std::string dataRate = "1Mbps";
+ uint32_t packetSize = 1000; // bytes
+ double duration = 10.0; // seconds
+ double initialEnergy = 7.5; // joule
+ double voltage = 3.0; // volts
+ double txPowerStart = 0.0; // dbm
+ double txPowerEnd = 15.0; // dbm
+ uint32_t nTxPowerLevels = 16;
+ uint32_t txPowerLevel = 0;
+ double idleCurrent = 0.273; // Ampere
+ double txCurrent = 0.380; // Ampere
+ bool verbose = false;
+
+
+ CommandLine cmd;
+
+ cmd.AddValue ("dataRate", "Data rate", dataRate);
+ cmd.AddValue ("packetSize", "size of application packet sent", packetSize);
+ cmd.AddValue ("duration", "duration (seconds) of the experiment", duration);
+ cmd.AddValue ("initialEnergy", "Initial Energy (Joule) of each node", initialEnergy);
+ cmd.AddValue ("voltage", "Supply voltage (Joule)", voltage);
+ cmd.AddValue ("txPowerStart", "Minimum available transmission level (dbm)", txPowerStart);
+ cmd.AddValue ("txPowerEnd", "Maximum available transmission level (dbm)", txPowerEnd);
+ cmd.AddValue ("nTxPowerLevels", "Number of transmission power levels available between txPowerStart and txPowerEnd included", nTxPowerLevels);
+ cmd.AddValue ("txPowerLevel", "Transmission power level", txPowerLevel);
+ cmd.AddValue ("idleCurrent", "The radio Idle current in Ampere", idleCurrent);
+ cmd.AddValue ("txCurrent", "The radio Tx current in Ampere", txCurrent);
+ cmd.AddValue ("verbose", "turn on all WifiNetDevice log components", verbose);
+
+ cmd.Parse (argc, argv);
+
+
+ NodeContainer c;
+ c.Create (2);
+
+ // The below set of helpers will help us to put together the wifi NICs we want
+ WifiHelper wifi;
+ if (verbose)
+ {
+ wifi.EnableLogComponents (); // Turn on all Wifi logging
+ }
+ wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
+
+ YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+ // ns-3 supports RadioTap and Prism tracing extensions for 802.11b
+ wifiPhy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
+
+ wifiPhy.Set ("TxPowerStart", DoubleValue (txPowerStart));
+ wifiPhy.Set ("TxPowerEnd", DoubleValue (txPowerEnd));
+ wifiPhy.Set ("TxPowerLevels", UintegerValue (nTxPowerLevels));
+
+ YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+ wifiPhy.SetChannel (wifiChannel.Create ());
+
+ // Add a non-QoS upper mac, and set the selected tx power level
+ NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
+ wifi.SetRemoteStationManager ("ns3::ArfWifiManager", "DefaultTxPowerLevel", UintegerValue (txPowerLevel));
+ // Set it to adhoc mode
+ wifiMac.SetType ("ns3::AdhocWifiMac");
+ NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, c);
+
+ MobilityHelper mobility;
+ Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+ positionAlloc->Add (Vector (0.0, 0.0, 0.0));
+ positionAlloc->Add (Vector (10.0, 0.0, 0.0));
+ mobility.SetPositionAllocator (positionAlloc);
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+ mobility.Install (c);
+
+ InternetStackHelper internet;
+ internet.Install (c);
+
+ Ipv4AddressHelper ipv4;
+ NS_LOG_INFO ("Assign IP Addresses.");
+ ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer i = ipv4.Assign (devices);
+
+ ApplicationContainer apps;
+
+ std::string transportProto = std::string("ns3::UdpSocketFactory");
+ OnOffHelper onOff(transportProto, InetSocketAddress (Ipv4Address ("10.1.1.2"), 9000));
+
+ onOff.SetAttribute ("DataRate", DataRateValue (DataRate (dataRate)));
+ onOff.SetAttribute ("PacketSize", UintegerValue (packetSize));
+ onOff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0.001]"));
+
+ apps = onOff.Install (c.Get (0));
+
+ apps.Start (Seconds (0.01));
+ apps.Stop (Seconds (duration));
+
+ // Create a packet sink to receive these packets
+ PacketSinkHelper sink (transportProto, InetSocketAddress (Ipv4Address::GetAny (), 9001));
+ apps = sink.Install (c.Get (1));
+ apps.Start (Seconds (0.01));
+ apps.Stop (Seconds (duration));
+
+ // Energy sources
+ EnergySourceContainer eSources;
+ BasicEnergySourceHelper basicSourceHelper;
+ WifiRadioEnergyModelHelper radioEnergyHelper;
+
+ basicSourceHelper.Set ("BasicEnergySourceInitialEnergyJ", DoubleValue (initialEnergy));
+ basicSourceHelper.Set ("BasicEnergySupplyVoltageV", DoubleValue (voltage));
+
+ radioEnergyHelper.Set ("IdleCurrentA", DoubleValue (idleCurrent));
+ radioEnergyHelper.Set ("TxCurrentA", DoubleValue (txCurrent));
+
+ // compute the efficiency of the power amplifier (eta) assuming that the provided value for tx current
+ // corresponds to the minimum tx power level
+ double eta = WifiTxCurrentModel::DbmToW (txPowerStart) / ((txCurrent - idleCurrent) * voltage);
+
+ radioEnergyHelper.SetTxCurrentModel ("ns3::LinearWifiTxCurrentModel",
+ "Voltage", DoubleValue (voltage),
+ "IdleCurrent", DoubleValue (idleCurrent),
+ "Eta", DoubleValue (eta));
+
+ // install an energy source on each node
+ for (NodeContainer::Iterator n = c.Begin(); n != c.End(); n++)
+ {
+ eSources.Add (basicSourceHelper.Install (*n));
+
+ Ptr<WifiNetDevice> wnd;
+
+ for (uint32_t i = 0; i < (*n)->GetNDevices (); ++i)
+ {
+ wnd = (*n)->GetDevice (i)->GetObject<WifiNetDevice> ();
+ // if it is a WifiNetDevice
+ if (wnd != 0)
+ {
+ // this device draws power from the last created energy source
+ radioEnergyHelper.Install (wnd, eSources.Get (eSources.GetN()-1));
+ }
+ }
+ }
+
+ // Tracing
+ eSources.Get (0)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<0>));
+ eSources.Get (1)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<1>));
+
+ Config::Connect ("/NodeList/0/DeviceList/*/Phy/State/State", MakeCallback (&PhyStateTrace<0>));
+ Config::Connect ("/NodeList/1/DeviceList/*/Phy/State/State", MakeCallback (&PhyStateTrace<1>));
+
+// wifiPhy.EnablePcap ("wifi-sleep", devices);
+
+ Simulator::Stop (Seconds(duration+1));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return 0;
+}
+
--- a/src/energy/doc/energy.rst Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/doc/energy.rst Fri Sep 05 16:33:57 2014 -0700
@@ -43,6 +43,15 @@
The energy harvester represents the elements that harvest energy from the environment and recharge the Energy Source to which it is connected. The energy harvester includes the complete implementation of the actual energy harvesting device (e.g., a solar panel) and the environment (e.g., the solar radiation). This means that in implementing an energy harvester, the energy contribution of the environment and the additional energy requirements of the energy harvesting device such as the conversion efficiency and the internal power consumption of the device needs to be jointly modeled.
+WiFi Radio Energy Model
+#######################
+
+The WiFi Radio Energy Model is the energy consumption model of a Wifi net device. It provides a state for each of the available states of the PHY layer: Idle, CcaBusy, Tx, Rx, ChannelSwitch, Sleep. Each of such states is associated with a value (in Ampere) of the current draw (see below for the corresponding attribute names). A Wifi Radio Energy Model PHY Listener is registered to the Wifi PHY in order to be notified of every Wifi PHY state transition. At every transition, the energy consumed in the previous state is computed and the energy source is notified in order to update its remaining energy.
+
+The Wifi Tx Current Model gives the possibility to compute the current draw in the transmit state as a function of the nominal tx power (in dBm), as observed in several experimental measurements. To this purpose, the Wifi Radio Energy Model PHY Listener is notified of the nominal tx power used to transmit the current frame and passes such a value to the Wifi Tx Current Model which takes care of updating the current draw in the Tx state. Hence, the energy consumption is correctly computed even if the Wifi Remote Station Manager performs per-frame power control. Currently, a Linear Wifi Tx Current Model is implemented which computes the tx current as a linear function (according to parameters that can be specified by the user) of the nominal tx power in dBm.
+
+The Wifi Radio Energy Model offers the possibility to specify a callback that is invoked when the energy source is depleted. If such a callback is not specified when the Wifi Radio Energy Model Helper is used to install the model on a device, a callback is implicitly made so that the Wifi PHY is put in the SLEEP mode (hence no frame is transmitted nor received afterwards) when the energy source is depleted. Likewise, it is possible to specify a callback that is invoked when the energy source is recharged (which might occur in case an energy harvester is connected to the energy source). If such a callback is not specified when the Wifi Radio Energy Model Helper is used to install the model on a device, a callback is implicitly made so that the Wifi PHY is resumed from the SLEEP mode when the energy source is recharged.
+
Future Work
***********
@@ -131,6 +140,8 @@
* ``TxCurrentA``: The radio Tx current in Ampere.
* ``RxCurrentA``: The radio Rx current in Ampere.
* ``SwitchingCurrentA``: The default radio Channel Switch current in Ampere.
+* ``SleepCurrentA``: The radio Sleep current in Ampere.
+* ``TxCurrentModel``: A pointer to the attached tx current model.
Basic Energy Harvester
#######################
--- a/src/energy/helper/wifi-radio-energy-model-helper.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/helper/wifi-radio-energy-model-helper.cc Fri Sep 05 16:33:57 2014 -0700
@@ -24,6 +24,7 @@
#include "ns3/wifi-net-device.h"
#include "ns3/config.h"
#include "ns3/names.h"
+#include "ns3/wifi-tx-current-model.h"
namespace ns3 {
@@ -31,6 +32,7 @@
{
m_radioEnergy.SetTypeId ("ns3::WifiRadioEnergyModel");
m_depletionCallback.Nullify ();
+ m_rechargedCallback.Nullify ();
}
WifiRadioEnergyModelHelper::~WifiRadioEnergyModelHelper ()
@@ -50,6 +52,38 @@
m_depletionCallback = callback;
}
+void
+WifiRadioEnergyModelHelper::SetRechargedCallback (
+ WifiRadioEnergyModel::WifiRadioEnergyRechargedCallback callback)
+{
+ m_rechargedCallback = callback;
+}
+
+void
+WifiRadioEnergyModelHelper::SetTxCurrentModel (std::string name,
+ std::string n0, const AttributeValue& v0,
+ std::string n1, const AttributeValue& v1,
+ std::string n2, const AttributeValue& v2,
+ std::string n3, const AttributeValue& v3,
+ std::string n4, const AttributeValue& v4,
+ std::string n5, const AttributeValue& v5,
+ std::string n6, const AttributeValue& v6,
+ std::string n7, const AttributeValue& v7)
+{
+ ObjectFactory factory;
+ factory.SetTypeId (name);
+ factory.Set (n0, v0);
+ factory.Set (n1, v1);
+ factory.Set (n2, v2);
+ factory.Set (n3, v3);
+ factory.Set (n4, v4);
+ factory.Set (n5, v5);
+ factory.Set (n6, v6);
+ factory.Set (n7, v7);
+ m_txCurrentModel = factory;
+}
+
+
/*
* Private function starts here.
*/
@@ -72,13 +106,37 @@
// set energy source pointer
model->SetEnergySource (source);
// set energy depletion callback
- model->SetEnergyDepletionCallback (m_depletionCallback);
+ // if none is specified, make a callback to WifiPhy::SetSleepMode
+ Ptr<WifiNetDevice> wifiDevice = DynamicCast<WifiNetDevice> (device);
+ Ptr<WifiPhy> wifiPhy = wifiDevice->GetPhy ();
+ if (m_depletionCallback.IsNull ())
+ {
+ model->SetEnergyDepletionCallback (MakeCallback (&WifiPhy::SetSleepMode, wifiPhy));
+ }
+ else
+ {
+ model->SetEnergyDepletionCallback (m_depletionCallback);
+ }
+ // set energy recharged callback
+ // if none is specified, make a callback to WifiPhy::ResumeFromSleep
+ if (m_rechargedCallback.IsNull ())
+ {
+ model->SetEnergyRechargedCallback (MakeCallback (&WifiPhy::ResumeFromSleep, wifiPhy));
+ }
+ else
+ {
+ model->SetEnergyRechargedCallback (m_rechargedCallback);
+ }
// add model to device model list in energy source
source->AppendDeviceEnergyModel (model);
// create and register energy model phy listener
- Ptr<WifiNetDevice> wifiDevice = DynamicCast<WifiNetDevice> (device);
- Ptr<WifiPhy> wifiPhy = wifiDevice->GetPhy ();
wifiPhy->RegisterListener (model->GetPhyListener ());
+ //
+ if (m_txCurrentModel.GetTypeId ().GetUid ())
+ {
+ Ptr<WifiTxCurrentModel> txcurrent = m_txCurrentModel.Create<WifiTxCurrentModel> ();
+ model->SetTxCurrentModel (txcurrent);
+ }
return model;
}
--- a/src/energy/helper/wifi-radio-energy-model-helper.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/helper/wifi-radio-energy-model-helper.h Fri Sep 05 16:33:57 2014 -0700
@@ -62,6 +62,44 @@
void SetDepletionCallback (
WifiRadioEnergyModel::WifiRadioEnergyDepletionCallback callback);
+ /**
+ * \param callback Callback function for energy recharged handling.
+ *
+ * Sets the callback to be invoked when energy is recharged.
+ */
+ void SetRechargedCallback (
+ WifiRadioEnergyModel::WifiRadioEnergyRechargedCallback callback);
+
+ /**
+ * \param name the name of the model to set
+ * \param n0 the name of the attribute to set
+ * \param v0 the value of the attribute to set
+ * \param n1 the name of the attribute to set
+ * \param v1 the value of the attribute to set
+ * \param n2 the name of the attribute to set
+ * \param v2 the value of the attribute to set
+ * \param n3 the name of the attribute to set
+ * \param v3 the value of the attribute to set
+ * \param n4 the name of the attribute to set
+ * \param v4 the value of the attribute to set
+ * \param n5 the name of the attribute to set
+ * \param v5 the value of the attribute to set
+ * \param n6 the name of the attribute to set
+ * \param v6 the value of the attribute to set
+ * \param n7 the name of the attribute to set
+ * \param v7 the value of the attribute to set
+ *
+ * Configure a propagation delay for this channel.
+ */
+ void SetTxCurrentModel (std::string name,
+ std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+ std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+ std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+ std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+ std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+ std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+ std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+ std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
private:
/**
@@ -76,6 +114,8 @@
private:
ObjectFactory m_radioEnergy;
WifiRadioEnergyModel::WifiRadioEnergyDepletionCallback m_depletionCallback;
+ WifiRadioEnergyModel::WifiRadioEnergyRechargedCallback m_rechargedCallback;
+ ObjectFactory m_txCurrentModel;
};
--- a/src/energy/model/basic-energy-source.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/basic-energy-source.cc Fri Sep 05 16:33:57 2014 -0700
@@ -49,6 +49,16 @@
MakeDoubleAccessor (&BasicEnergySource::SetSupplyVoltage,
&BasicEnergySource::GetSupplyVoltage),
MakeDoubleChecker<double> ())
+ .AddAttribute ("BasicEnergyLowBatteryThreshold",
+ "Low battery threshold for basic energy source.",
+ DoubleValue (0.10), // as a fraction of the initial energy
+ MakeDoubleAccessor (&BasicEnergySource::m_lowBatteryTh),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("BasicEnergyHighBatteryThreshold",
+ "High battery threshold for basic energy source.",
+ DoubleValue (0.15), // as a fraction of the initial energy
+ MakeDoubleAccessor (&BasicEnergySource::m_highBatteryTh),
+ MakeDoubleChecker<double> ())
.AddAttribute ("PeriodicEnergyUpdateInterval",
"Time between two consecutive periodic energy updates.",
TimeValue (Seconds (1.0)),
@@ -66,6 +76,7 @@
{
NS_LOG_FUNCTION (this);
m_lastUpdateTime = Seconds (0.0);
+ m_depleted = false;
}
BasicEnergySource::~BasicEnergySource ()
@@ -151,13 +162,19 @@
CalculateRemainingEnergy ();
- if (m_remainingEnergyJ <= 0)
+ m_lastUpdateTime = Simulator::Now ();
+
+ if (!m_depleted && m_remainingEnergyJ <= m_lowBatteryTh * m_initialEnergyJ)
{
+ m_depleted = true;
HandleEnergyDrainedEvent ();
- return; // stop periodic update
}
- m_lastUpdateTime = Simulator::Now ();
+ if (m_depleted && m_remainingEnergyJ > m_highBatteryTh * m_initialEnergyJ)
+ {
+ m_depleted = false;
+ HandleEnergyRechargedEvent ();
+ }
m_energyUpdateEvent = Simulator::Schedule (m_energyUpdateInterval,
&BasicEnergySource::UpdateEnergySource,
@@ -188,7 +205,18 @@
NS_LOG_FUNCTION (this);
NS_LOG_DEBUG ("BasicEnergySource:Energy depleted!");
NotifyEnergyDrained (); // notify DeviceEnergyModel objects
- m_remainingEnergyJ = 0; // energy never goes below 0
+ if (m_remainingEnergyJ <= 0)
+ {
+ m_remainingEnergyJ = 0; // energy never goes below 0
+ }
+}
+
+void
+BasicEnergySource::HandleEnergyRechargedEvent (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG ("BasicEnergySource:Energy recharged!");
+ NotifyEnergyRecharged (); // notify DeviceEnergyModel objects
}
void
--- a/src/energy/model/basic-energy-source.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/basic-energy-source.h Fri Sep 05 16:33:57 2014 -0700
@@ -118,6 +118,14 @@
void HandleEnergyDrainedEvent (void);
/**
+ * Handles the remaining energy exceeding the high threshold after it went
+ * below the low threshold. This function notifies all the energy models
+ * aggregated to the node about the energy being recharged. Each energy model
+ * is then responsible for its own handler.
+ */
+ void HandleEnergyRechargedEvent (void);
+
+ /**
* Calculates remaining energy. This function uses the total current from all
* device models to calculate the amount of energy to decrease. The energy to
* decrease is given by:
@@ -130,6 +138,10 @@
private:
double m_initialEnergyJ; // initial energy, in Joules
double m_supplyVoltageV; // supply voltage, in Volts
+ double m_lowBatteryTh; // low battery threshold, as a fraction of the initial energy
+ double m_highBatteryTh; // high battery threshold, as a fraction of the initial energy
+ bool m_depleted; // set to true when the remaining energy goes below the low threshold,
+ // set to false again when the remaining energy exceeds the high threshold
TracedValue<double> m_remainingEnergyJ; // remaining energy, in Joules
EventId m_energyUpdateEvent; // energy update event
Time m_lastUpdateTime; // last update time
--- a/src/energy/model/device-energy-model.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/device-energy-model.h Fri Sep 05 16:33:57 2014 -0700
@@ -93,6 +93,12 @@
*/
virtual void HandleEnergyDepletion (void) = 0;
+ /**
+ * This function is called by the EnergySource object when energy stored in
+ * the energy source is recharged. Should be implemented by child classes.
+ */
+ virtual void HandleEnergyRecharged (void) = 0;
+
private:
/**
--- a/src/energy/model/energy-source.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/energy-source.cc Fri Sep 05 16:33:57 2014 -0700
@@ -201,6 +201,18 @@
}
void
+EnergySource::NotifyEnergyRecharged (void)
+{
+ NS_LOG_FUNCTION (this);
+ // notify all device energy models installed on node
+ DeviceEnergyModelContainer::Iterator i;
+ for (i = m_models.Begin (); i != m_models.End (); i++)
+ {
+ (*i)->HandleEnergyRecharged ();
+ }
+}
+
+void
EnergySource::BreakDeviceEnergyModelRefCycle (void)
{
NS_LOG_FUNCTION (this);
--- a/src/energy/model/energy-source.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/energy-source.h Fri Sep 05 16:33:57 2014 -0700
@@ -223,6 +223,12 @@
void NotifyEnergyDrained (void);
/**
+ * This function notifies all DeviceEnergyModel of energy recharged event. It
+ * is called by the child EnergySource class when energy source is recharged.
+ */
+ void NotifyEnergyRecharged (void);
+
+ /**
* This function is called to break reference cycle between EnergySource and
* DeviceEnergyModel. Child of the EnergySource base class must call this
* function in their implementation of DoDispose to make sure the reference
--- a/src/energy/model/li-ion-energy-source.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/li-ion-energy-source.cc Fri Sep 05 16:33:57 2014 -0700
@@ -45,6 +45,11 @@
MakeDoubleAccessor (&LiIonEnergySource::SetInitialEnergy,
&LiIonEnergySource::GetInitialEnergy),
MakeDoubleChecker<double> ())
+ .AddAttribute ("LiIonEnergyLowBatteryThreshold",
+ "Low battery threshold for LiIon energy source.",
+ DoubleValue (0.10), // as a fraction of the initial energy
+ MakeDoubleAccessor (&LiIonEnergySource::m_lowBatteryTh),
+ MakeDoubleChecker<double> ())
.AddAttribute ("InitialCellVoltage",
"Initial (maximum) voltage of the cell (fully charged).",
DoubleValue (4.05), // in Volts
@@ -219,14 +224,14 @@
CalculateRemainingEnergy ();
- if (m_remainingEnergyJ <= 0)
+ m_lastUpdateTime = Simulator::Now ();
+
+ if (m_remainingEnergyJ <= m_lowBatteryTh * m_initialEnergyJ)
{
HandleEnergyDrainedEvent ();
return; // stop periodic update
}
- m_lastUpdateTime = Simulator::Now ();
-
m_energyUpdateEvent = Simulator::Schedule (m_energyUpdateInterval,
&LiIonEnergySource::UpdateEnergySource,
this);
@@ -259,7 +264,10 @@
NS_LOG_DEBUG ("LiIonEnergySource:Energy depleted at node #" <<
GetNode ()->GetId ());
NotifyEnergyDrained (); // notify DeviceEnergyModel objects
- m_remainingEnergyJ = 0; // energy never goes below 0
+ if (m_remainingEnergyJ <= 0)
+ {
+ m_remainingEnergyJ = 0; // energy never goes below 0
+ }
}
--- a/src/energy/model/li-ion-energy-source.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/li-ion-energy-source.h Fri Sep 05 16:33:57 2014 -0700
@@ -185,6 +185,7 @@
TracedValue<double> m_remainingEnergyJ; // remaining energy, in Joules
double m_drainedCapacity; // capacity drained from the cell, in Ah
double m_supplyVoltageV; // actual voltage of the cell
+ double m_lowBatteryTh; // low battery threshold, as a fraction of the initial energy
EventId m_energyUpdateEvent; // energy update event
Time m_lastUpdateTime; // last update time
Time m_energyUpdateInterval; // energy update interval
--- a/src/energy/model/rv-battery-model.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/rv-battery-model.cc Fri Sep 05 16:33:57 2014 -0700
@@ -44,6 +44,11 @@
MakeTimeAccessor (&RvBatteryModel::SetSamplingInterval,
&RvBatteryModel::GetSamplingInterval),
MakeTimeChecker ())
+ .AddAttribute ("RvBatteryModelLowBatteryThreshold",
+ "Low battery threshold.",
+ DoubleValue (0.10), // as a fraction of the initial energy
+ MakeDoubleAccessor (&RvBatteryModel::m_lowBatteryTh),
+ MakeDoubleChecker<double> ())
.AddAttribute ("RvBatteryModelOpenCircuitVoltage",
"RV battery model open circuit voltage.",
DoubleValue (4.1),
@@ -164,7 +169,7 @@
}
// check if battery is dead.
- if (calculatedAlpha >= m_alpha)
+ if (m_batteryLevel <= m_lowBatteryTh)
{
m_lifetime = Simulator::Now ();
NS_LOG_DEBUG ("RvBatteryModel:Battery is dead!");
--- a/src/energy/model/rv-battery-model.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/rv-battery-model.h Fri Sep 05 16:33:57 2014 -0700
@@ -246,6 +246,8 @@
*/
TracedValue<double> m_batteryLevel;
+ double m_lowBatteryTh; // low battery threshold, as a fraction of the initial energy
+
/**
* (1 / sampling interval) = sampling frequency
*/
--- a/src/energy/model/simple-device-energy-model.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/simple-device-energy-model.h Fri Sep 05 16:33:57 2014 -0700
@@ -95,6 +95,15 @@
}
/**
+ * \brief Handles energy recharged.
+ *
+ * Not implemented
+ */
+ virtual void HandleEnergyRecharged (void)
+ {
+ }
+
+ /**
* \param current the current draw of device.
*
* Set the actual current draw of the device.
--- a/src/energy/model/wifi-radio-energy-model.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/wifi-radio-energy-model.cc Fri Sep 05 16:33:57 2014 -0700
@@ -22,8 +22,10 @@
#include "ns3/double.h"
#include "ns3/simulator.h"
#include "ns3/trace-source-accessor.h"
+#include "ns3/pointer.h"
#include "energy-source.h"
#include "wifi-radio-energy-model.h"
+#include "wifi-tx-current-model.h"
NS_LOG_COMPONENT_DEFINE ("WifiRadioEnergyModel");
@@ -39,34 +41,44 @@
.AddConstructor<WifiRadioEnergyModel> ()
.AddAttribute ("IdleCurrentA",
"The default radio Idle current in Ampere.",
- DoubleValue (0.000426), // idle mode = 426uA
+ DoubleValue (0.273), // idle mode = 273mA
MakeDoubleAccessor (&WifiRadioEnergyModel::SetIdleCurrentA,
&WifiRadioEnergyModel::GetIdleCurrentA),
MakeDoubleChecker<double> ())
.AddAttribute ("CcaBusyCurrentA",
"The default radio CCA Busy State current in Ampere.",
- DoubleValue (0.000426), // default to be the same as idle mode
+ DoubleValue (0.273), // default to be the same as idle mode
MakeDoubleAccessor (&WifiRadioEnergyModel::SetCcaBusyCurrentA,
&WifiRadioEnergyModel::GetCcaBusyCurrentA),
MakeDoubleChecker<double> ())
.AddAttribute ("TxCurrentA",
"The radio Tx current in Ampere.",
- DoubleValue (0.0174), // transmit at 0dBm = 17.4mA
+ DoubleValue (0.380), // transmit at 0dBm = 380mA
MakeDoubleAccessor (&WifiRadioEnergyModel::SetTxCurrentA,
&WifiRadioEnergyModel::GetTxCurrentA),
MakeDoubleChecker<double> ())
.AddAttribute ("RxCurrentA",
"The radio Rx current in Ampere.",
- DoubleValue (0.0197), // receive mode = 19.7mA
+ DoubleValue (0.313), // receive mode = 313mA
MakeDoubleAccessor (&WifiRadioEnergyModel::SetRxCurrentA,
&WifiRadioEnergyModel::GetRxCurrentA),
MakeDoubleChecker<double> ())
.AddAttribute ("SwitchingCurrentA",
"The default radio Channel Switch current in Ampere.",
- DoubleValue (0.000426), // default to be the same as idle mode
+ DoubleValue (0.273), // default to be the same as idle mode
MakeDoubleAccessor (&WifiRadioEnergyModel::SetSwitchingCurrentA,
&WifiRadioEnergyModel::GetSwitchingCurrentA),
MakeDoubleChecker<double> ())
+ .AddAttribute ("SleepCurrentA",
+ "The radio Sleep current in Ampere.",
+ DoubleValue (0.033), // sleep mode = 33mA
+ MakeDoubleAccessor (&WifiRadioEnergyModel::SetSleepCurrentA,
+ &WifiRadioEnergyModel::GetSleepCurrentA),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("TxCurrentModel", "A pointer to the attached tx current model.",
+ PointerValue (),
+ MakePointerAccessor (&WifiRadioEnergyModel::m_txCurrentModel),
+ MakePointerChecker<WifiTxCurrentModel> ())
.AddTraceSource ("TotalEnergyConsumption",
"Total energy consumption of the radio device.",
MakeTraceSourceAccessor (&WifiRadioEnergyModel::m_totalEnergyConsumption))
@@ -79,11 +91,15 @@
NS_LOG_FUNCTION (this);
m_currentState = WifiPhy::IDLE; // initially IDLE
m_lastUpdateTime = Seconds (0.0);
+ m_nPendingChangeState = 0;
+ m_isSupersededChangeState = false;
m_energyDepletionCallback.Nullify ();
m_source = NULL;
// set callback for WifiPhy listener
m_listener = new WifiRadioEnergyModelPhyListener;
m_listener->SetChangeStateCallback (MakeCallback (&DeviceEnergyModel::ChangeState, this));
+ // set callback for updating the tx current
+ m_listener->SetUpdateTxCurrentCallback (MakeCallback (&WifiRadioEnergyModel::SetTxCurrentFromModel, this));
}
WifiRadioEnergyModel::~WifiRadioEnergyModel ()
@@ -177,6 +193,19 @@
m_switchingCurrentA = switchingCurrentA;
}
+double
+WifiRadioEnergyModel::GetSleepCurrentA (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return m_sleepCurrentA;
+}
+
+void
+WifiRadioEnergyModel::SetSleepCurrentA (double sleepCurrentA)
+{
+ NS_LOG_FUNCTION (this << sleepCurrentA);
+ m_sleepCurrentA = sleepCurrentA;
+}
WifiPhy::State
WifiRadioEnergyModel::GetCurrentState (void) const
@@ -198,6 +227,33 @@
}
void
+WifiRadioEnergyModel::SetEnergyRechargedCallback (
+ WifiRadioEnergyRechargedCallback callback)
+{
+ NS_LOG_FUNCTION (this);
+ if (callback.IsNull ())
+ {
+ NS_LOG_DEBUG ("WifiRadioEnergyModel:Setting NULL energy recharged callback!");
+ }
+ m_energyRechargedCallback = callback;
+}
+
+void
+WifiRadioEnergyModel::SetTxCurrentModel (Ptr<WifiTxCurrentModel> model)
+{
+ m_txCurrentModel = model;
+}
+
+void
+WifiRadioEnergyModel::SetTxCurrentFromModel (double txPowerDbm)
+{
+ if (m_txCurrentModel)
+ {
+ m_txCurrentA = m_txCurrentModel->CalcTxCurrent (txPowerDbm);
+ }
+}
+
+void
WifiRadioEnergyModel::ChangeState (int newState)
{
NS_LOG_FUNCTION (this << newState);
@@ -225,6 +281,9 @@
case WifiPhy::SWITCHING:
energyToDecrease = duration.GetSeconds () * m_switchingCurrentA * supplyVoltage;
break;
+ case WifiPhy::SLEEP:
+ energyToDecrease = duration.GetSeconds () * m_sleepCurrentA * supplyVoltage;
+ break;
default:
NS_FATAL_ERROR ("WifiRadioEnergyModel:Undefined radio state: " << m_currentState);
}
@@ -235,15 +294,31 @@
// update last update time stamp
m_lastUpdateTime = Simulator::Now ();
+ m_nPendingChangeState++;
+
// notify energy source
m_source->UpdateEnergySource ();
- // update current state & last update time stamp
- SetWifiRadioState ((WifiPhy::State) newState);
+ // in case the energy source is found to be depleted during the last update, a callback might be
+ // invoked that might cause a change in the Wifi PHY state (e.g., the PHY is put into SLEEP mode).
+ // This in turn causes a new call to this member function, with the consequence that the previous
+ // instance is resumed after the termination of the new instance. In particular, the state set
+ // by the previous instance is erroneously the final state stored in m_currentState. The check below
+ // ensures that previous instances do not change m_currentState.
- // some debug message
- NS_LOG_DEBUG ("WifiRadioEnergyModel:Total energy consumption is " <<
- m_totalEnergyConsumption << "J");
+ if (!m_isSupersededChangeState)
+ {
+ // update current state & last update time stamp
+ SetWifiRadioState ((WifiPhy::State) newState);
+
+ // some debug message
+ NS_LOG_DEBUG ("WifiRadioEnergyModel:Total energy consumption is " <<
+ m_totalEnergyConsumption << "J");
+ }
+
+ m_isSupersededChangeState = (m_nPendingChangeState > 1);
+
+ m_nPendingChangeState--;
}
void
@@ -258,6 +333,18 @@
}
}
+void
+WifiRadioEnergyModel::HandleEnergyRecharged (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG ("WifiRadioEnergyModel:Energy is recharged!");
+ // invoke energy recharged callback, if set.
+ if (!m_energyRechargedCallback.IsNull ())
+ {
+ m_energyRechargedCallback ();
+ }
+}
+
WifiRadioEnergyModelPhyListener *
WifiRadioEnergyModel::GetPhyListener (void)
{
@@ -293,6 +380,8 @@
return m_rxCurrentA;
case WifiPhy::SWITCHING:
return m_switchingCurrentA;
+ case WifiPhy::SLEEP:
+ return m_sleepCurrentA;
default:
NS_FATAL_ERROR ("WifiRadioEnergyModel:Undefined radio state:" << m_currentState);
}
@@ -321,6 +410,9 @@
case WifiPhy::SWITCHING:
stateName = "SWITCHING";
break;
+ case WifiPhy::SLEEP:
+ stateName = "SLEEP";
+ break;
}
NS_LOG_DEBUG ("WifiRadioEnergyModel:Switching to state: " << stateName <<
" at time = " << Simulator::Now ());
@@ -332,6 +424,7 @@
{
NS_LOG_FUNCTION (this);
m_changeStateCallback.Nullify ();
+ m_updateTxCurrentCallback.Nullify ();
}
WifiRadioEnergyModelPhyListener::~WifiRadioEnergyModelPhyListener ()
@@ -348,6 +441,14 @@
}
void
+WifiRadioEnergyModelPhyListener::SetUpdateTxCurrentCallback (UpdateTxCurrentCallback callback)
+{
+ NS_LOG_FUNCTION (this << &callback);
+ NS_ASSERT (!callback.IsNull ());
+ m_updateTxCurrentCallback = callback;
+}
+
+void
WifiRadioEnergyModelPhyListener::NotifyRxStart (Time duration)
{
NS_LOG_FUNCTION (this << duration);
@@ -382,9 +483,14 @@
}
void
-WifiRadioEnergyModelPhyListener::NotifyTxStart (Time duration)
+WifiRadioEnergyModelPhyListener::NotifyTxStart (Time duration, double txPowerDbm)
{
- NS_LOG_FUNCTION (this << duration);
+ NS_LOG_FUNCTION (this << duration << txPowerDbm);
+ if (m_updateTxCurrentCallback.IsNull ())
+ {
+ NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Update tx current callback not set!");
+ }
+ m_updateTxCurrentCallback (txPowerDbm);
if (m_changeStateCallback.IsNull ())
{
NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Change state callback not set!");
@@ -423,6 +529,29 @@
m_switchToIdleEvent = Simulator::Schedule (duration, &WifiRadioEnergyModelPhyListener::SwitchToIdle, this);
}
+void
+WifiRadioEnergyModelPhyListener::NotifySleep (void)
+{
+ NS_LOG_FUNCTION (this);
+ if (m_changeStateCallback.IsNull ())
+ {
+ NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Change state callback not set!");
+ }
+ m_changeStateCallback (WifiPhy::SLEEP);
+ m_switchToIdleEvent.Cancel ();
+}
+
+void
+WifiRadioEnergyModelPhyListener::NotifyWakeup(void)
+{
+ NS_LOG_FUNCTION (this);
+ if (m_changeStateCallback.IsNull ())
+ {
+ NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Change state callback not set!");
+ }
+ m_changeStateCallback (WifiPhy::IDLE);
+}
+
/*
* Private function state here.
*/
--- a/src/energy/model/wifi-radio-energy-model.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/model/wifi-radio-energy-model.h Fri Sep 05 16:33:57 2014 -0700
@@ -29,6 +29,8 @@
namespace ns3 {
+class WifiTxCurrentModel;
+
/**
* \ingroup energy
* A WifiPhy listener class for notifying the WifiRadioEnergyModel of Wifi radio
@@ -38,6 +40,11 @@
class WifiRadioEnergyModelPhyListener : public WifiPhyListener
{
public:
+ /**
+ * Callback type for updating the transmit current based on the nominal tx power.
+ */
+ typedef Callback<void, double> UpdateTxCurrentCallback;
+
WifiRadioEnergyModelPhyListener ();
virtual ~WifiRadioEnergyModelPhyListener ();
@@ -49,6 +56,13 @@
void SetChangeStateCallback (DeviceEnergyModel::ChangeStateCallback callback);
/**
+ * \brief Sets the update tx current callback.
+ *
+ * \param callback Update tx current callback.
+ */
+ void SetUpdateTxCurrentCallback (UpdateTxCurrentCallback callback);
+
+ /**
* \brief Switches the WifiRadioEnergyModel to RX state.
*
* \param duration the expected duration of the packet reception.
@@ -82,10 +96,11 @@
* IDLE after TX duration.
*
* \param duration the expected transmission duration.
+ * \param txPowerDbm the nominal tx power in dBm
*
* Defined in ns3::WifiPhyListener
*/
- virtual void NotifyTxStart (Time duration);
+ virtual void NotifyTxStart (Time duration, double txPowerDbm);
/**
* \param duration the expected busy duration.
@@ -101,6 +116,16 @@
*/
virtual void NotifySwitchingStart (Time duration);
+ /**
+ * Defined in ns3::WifiPhyListener
+ */
+ virtual void NotifySleep (void);
+
+ /**
+ * Defined in ns3::WifiPhyListener
+ */
+ virtual void NotifyWakeup (void);
+
private:
/**
* A helper function that makes scheduling m_changeStateCallback possible.
@@ -114,6 +139,12 @@
*/
DeviceEnergyModel::ChangeStateCallback m_changeStateCallback;
+ /**
+ * Callback used to update the tx current stored in WifiRadioEnergyModel based on
+ * the nominal tx power used to transmit the current frame.
+ */
+ UpdateTxCurrentCallback m_updateTxCurrentCallback;
+
EventId m_switchToIdleEvent;
};
@@ -138,9 +169,34 @@
* object. The EnergySource object will query this model for the total current.
* Then the EnergySource object uses the total current to calculate energy.
*
- * Default values for power consumption are based on CC2420 radio chip, with
- * supply voltage as 2.5V and currents as 17.4 mA (TX), 18.8 mA (RX), 20 uA
- * (sleep) and 426 uA (idle).
+ * Default values for power consumption are based on measurements reported in:
+ *
+ * Daniel Halperin, Ben Greenstein, Anmol Sheth, David Wetherall,
+ * "Demystifying 802.11n power consumption", Proceedings of HotPower'10
+ *
+ * Power consumption in Watts (single antenna):
+ *
+ * \f$ P_{tx} = 1.14 \f$ (transmit at 0dBm)
+ *
+ * \f$ P_{rx} = 0.94 \f$
+ *
+ * \f$ P_{idle} = 0.82 \f$
+ *
+ * \f$ P_{sleep} = 0.10 \f$
+ *
+ * Hence, considering the default supply voltage of 3.0 V for the basic energy
+ * source, the default current values in Ampere are:
+ *
+ * \f$ I_{tx} = 0.380 \f$
+ *
+ * \f$ I_{rx} = 0.313 \f$
+ *
+ * \f$ I_{idle} = 0.273 \f$
+ *
+ * \f$ I_{sleep} = 0.033 \f$
+ *
+ * The dependence of the power consumption in transmission mode on the nominal
+ * transmit power can also be achieved through a wifi tx current model.
*
*/
class WifiRadioEnergyModel : public DeviceEnergyModel
@@ -151,6 +207,11 @@
*/
typedef Callback<void> WifiRadioEnergyDepletionCallback;
+ /**
+ * Callback type for energy recharged handling.
+ */
+ typedef Callback<void> WifiRadioEnergyRechargedCallback;
+
public:
static TypeId GetTypeId (void);
WifiRadioEnergyModel ();
@@ -183,6 +244,8 @@
void SetRxCurrentA (double rxCurrentA);
double GetSwitchingCurrentA (void) const;
void SetSwitchingCurrentA (double switchingCurrentA);
+ double GetSleepCurrentA (void) const;
+ void SetSleepCurrentA (double sleepCurrentA);
/**
* \returns Current state.
@@ -197,6 +260,26 @@
void SetEnergyDepletionCallback (WifiRadioEnergyDepletionCallback callback);
/**
+ * \param callback Callback function.
+ *
+ * Sets callback for energy recharged handling.
+ */
+ void SetEnergyRechargedCallback (WifiRadioEnergyRechargedCallback callback);
+
+ /**
+ * \param model the model used to compute the wifi tx current.
+ */
+ void SetTxCurrentModel (Ptr<WifiTxCurrentModel> model);
+
+ /**
+ * \brief Calls the CalcTxCurrent method of the tx current model to
+ * compute the tx current based on such model
+ *
+ * \param txPowerDbm the nominal tx power in dBm
+ */
+ void SetTxCurrentFromModel (double txPowerDbm);
+
+ /**
* \brief Changes state of the WifiRadioEnergyMode.
*
* \param newState New state the wifi radio is in.
@@ -213,6 +296,13 @@
virtual void HandleEnergyDepletion (void);
/**
+ * \brief Handles energy recharged.
+ *
+ * Implements DeviceEnergyModel::HandleEnergyRecharged
+ */
+ virtual void HandleEnergyRecharged (void);
+
+ /**
* \returns Pointer to the PHY listener.
*/
WifiRadioEnergyModelPhyListener * GetPhyListener (void);
@@ -245,6 +335,8 @@
double m_idleCurrentA;
double m_ccaBusyCurrentA;
double m_switchingCurrentA;
+ double m_sleepCurrentA;
+ Ptr<WifiTxCurrentModel> m_txCurrentModel;
// This variable keeps track of the total energy consumed by this model.
TracedValue<double> m_totalEnergyConsumption;
@@ -253,9 +345,15 @@
WifiPhy::State m_currentState; // current state the radio is in
Time m_lastUpdateTime; // time stamp of previous energy update
+ uint8_t m_nPendingChangeState;
+ bool m_isSupersededChangeState;
+
// Energy depletion callback
WifiRadioEnergyDepletionCallback m_energyDepletionCallback;
+ // Energy recharged callback
+ WifiRadioEnergyRechargedCallback m_energyRechargedCallback;
+
// WifiPhy listener
WifiRadioEnergyModelPhyListener *m_listener;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/energy/model/wifi-tx-current-model.cc Fri Sep 05 16:33:57 2014 -0700
@@ -0,0 +1,142 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Universita' degli Studi di Napoli "Federico II"
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Stefano Avallone <stefano.avallone@unina.it>
+ */
+
+#include "wifi-tx-current-model.h"
+#include "ns3/log.h"
+#include "ns3/boolean.h"
+#include "ns3/double.h"
+#include "ns3/string.h"
+#include "ns3/pointer.h"
+#include <cmath>
+
+NS_LOG_COMPONENT_DEFINE ("WifiTxCurrentModel");
+
+namespace ns3 {
+
+// ------------------------------------------------------------------------- //
+
+NS_OBJECT_ENSURE_REGISTERED (WifiTxCurrentModel);
+
+TypeId
+WifiTxCurrentModel::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::WifiTxCurrentModel")
+ .SetParent<Object> ()
+ ;
+ return tid;
+}
+
+WifiTxCurrentModel::WifiTxCurrentModel()
+{
+}
+
+WifiTxCurrentModel::~WifiTxCurrentModel()
+{
+}
+
+double
+WifiTxCurrentModel::DbmToW (double dbm)
+{
+ double mW = std::pow (10.0, dbm / 10.0);
+ return mW / 1000.0;
+}
+
+// ------------------------------------------------------------------------- //
+
+NS_OBJECT_ENSURE_REGISTERED (LinearWifiTxCurrentModel);
+
+TypeId
+LinearWifiTxCurrentModel::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::LinearWifiTxCurrentModel")
+ .SetParent<WifiTxCurrentModel> ()
+ .AddConstructor<LinearWifiTxCurrentModel> ()
+ .AddAttribute ("Eta", "The efficiency of the power amplifier.",
+ DoubleValue (0.10),
+ MakeDoubleAccessor (&LinearWifiTxCurrentModel::SetEta,
+ &LinearWifiTxCurrentModel::GetEta),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("Voltage", "The supply voltage (in Volts).",
+ DoubleValue (3.0),
+ MakeDoubleAccessor (&LinearWifiTxCurrentModel::SetVoltage,
+ &LinearWifiTxCurrentModel::GetVoltage),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("IdleCurrent", "The current in the IDLE state (in Watts).",
+ DoubleValue (0.273333),
+ MakeDoubleAccessor (&LinearWifiTxCurrentModel::SetIdleCurrent,
+ &LinearWifiTxCurrentModel::GetIdleCurrent),
+ MakeDoubleChecker<double> ())
+ ;
+ return tid;
+}
+
+LinearWifiTxCurrentModel::LinearWifiTxCurrentModel ()
+{
+}
+
+LinearWifiTxCurrentModel::~LinearWifiTxCurrentModel()
+{
+}
+
+void
+LinearWifiTxCurrentModel::SetEta (double eta)
+{
+ m_eta = eta;
+}
+
+void
+LinearWifiTxCurrentModel::SetVoltage (double voltage)
+{
+ m_voltage = voltage;
+}
+
+void
+LinearWifiTxCurrentModel::SetIdleCurrent (double idleCurrent)
+{
+ m_idleCurrent = idleCurrent;
+}
+
+double
+LinearWifiTxCurrentModel::GetEta (void) const
+{
+ return m_eta;
+}
+
+double
+LinearWifiTxCurrentModel::GetVoltage (void) const
+{
+ return m_voltage;
+}
+
+double
+LinearWifiTxCurrentModel::GetIdleCurrent (void) const
+{
+ return m_idleCurrent;
+}
+
+double
+LinearWifiTxCurrentModel::CalcTxCurrent (double txPowerDbm) const
+{
+ return DbmToW (txPowerDbm) / (m_voltage * m_eta) + m_idleCurrent;
+}
+
+// ------------------------------------------------------------------------- //
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/energy/model/wifi-tx-current-model.h Fri Sep 05 16:33:57 2014 -0700
@@ -0,0 +1,142 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Universita' degli Studi di Napoli "Federico II"
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Stefano Avallone <stefano.avallone@unina.it>
+ */
+
+#ifndef WIFI_TX_CURRENT_MODEL_H
+#define WIFI_TX_CURRENT_MODEL_H
+
+#include "ns3/object.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup energy
+ *
+ * \brief Modelize the transmit current as a function of the transmit power and mode
+ *
+ */
+class WifiTxCurrentModel : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+
+ WifiTxCurrentModel ();
+ virtual ~WifiTxCurrentModel ();
+
+ /**
+ * \param txPowerDbm the nominal tx power in dBm
+ * \returns the transmit current (in Ampere)
+ */
+ virtual double CalcTxCurrent (double txPowerDbm) const = 0;
+
+ /**
+ * Convert from dBm to Watts.
+ *
+ * \param dbm the power in dBm
+ * \return the equivalent Watts for the given dBm
+ */
+ static double DbmToW (double dbm);
+};
+
+/**
+ * \ingroup energy
+ *
+ * \brief a linear model of the Wifi transmit current
+ *
+ * This model assumes that the transmit current is a linear function
+ * of the nominal transmit power used to send the frame.
+ * In particular, the power absorbed during the transmission of a frame \f$ W_{tx} \f$
+ * is given by the power absorbed by the power amplifier \f$ W_{pa} \f$ plus the power
+ * absorbed by the RF subsystem. The latter is assumed to be the same as the power
+ * absorbed in the IDLE state \f$ W_{idle} \f$.
+ *
+ * The efficiency \f$ \eta \f$ of the power amplifier is given by
+ * \f$ \eta = \frac{P_{tx}}{W_{pa}} \f$, where \f$ P_{tx} \f$ is the output power, i.e.,
+ * the nominal transmit power. Hence, \f$ W_{pa} = \frac{P_{tx}}{\eta} \f$
+ *
+ * It turns out that \f$ W_{tx} = \frac{P_{tx}}{\eta} + W_{idle} \f$. By dividing both
+ * sides by the supply voltage \f$ V \f$: \f$ I_{tx} = \frac{P_{tx}}{V \cdot \eta} + I_{idle} \f$,
+ * where \f$ I_{tx} \f$ and \f$ I_{idle} \f$ are, respectively, the transmit current and
+ * the idle current.
+ *
+ * For more information, refer to:
+ * Francesco Ivan Di Piazza, Stefano Mangione, and Ilenia Tinnirello.
+ * "On the Effects of Transmit Power Control on the Energy Consumption of WiFi Network Cards",
+ * Proceedings of ICST QShine 2009, pp. 463--475
+ *
+ * If the tx current corresponding to a given nominal transmit power is known, the efficiency
+ * of the power amplifier is given by the above formula:
+ * \f$ \eta = \frac{P_{tx}}{(I_{tx}-I_{idle})\cdot V} \f$
+ *
+ */
+class LinearWifiTxCurrentModel : public WifiTxCurrentModel
+{
+public:
+ static TypeId GetTypeId (void);
+
+ LinearWifiTxCurrentModel ();
+ virtual ~LinearWifiTxCurrentModel ();
+
+ /**
+ * \param eta (dimension-less)
+ *
+ * Set the power amplifier efficiency.
+ */
+ void SetEta (double eta);
+
+ /**
+ * \param voltage (Volts)
+ *
+ * Set the supply voltage.
+ */
+ void SetVoltage (double voltage);
+
+ /**
+ * \param idleCurrent (Ampere)
+ *
+ * Set the current in the IDLE state.
+ */
+ void SetIdleCurrent (double idleCurrent);
+
+ /**
+ * \return the power amplifier efficiency.
+ */
+ double GetEta (void) const;
+
+ /**
+ * \return the supply voltage.
+ */
+ double GetVoltage (void) const;
+
+ /**
+ * \return the current in the IDLE state.
+ */
+ double GetIdleCurrent (void) const;
+
+ double CalcTxCurrent (double txPowerDbm) const;
+
+private:
+ double m_eta;
+ double m_voltage;
+ double m_idleCurrent;
+};
+
+} // namespace ns3
+
+#endif /* WIFI_TX_CURRENT_MODEL_H */
--- a/src/energy/test/basic-energy-model-test.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/test/basic-energy-model-test.cc Fri Sep 05 16:33:57 2014 -0700
@@ -93,6 +93,7 @@
NS_TEST_ASSERT_MSG_EQ (StateSwitchTest (WifiPhy::TX), false, "Problem with state switch test (WifiPhy tx).");
NS_TEST_ASSERT_MSG_EQ (StateSwitchTest (WifiPhy::RX), false, "Problem with state switch test (WifiPhy rx).");
NS_TEST_ASSERT_MSG_EQ (StateSwitchTest (WifiPhy::SWITCHING), false, "Problem with state switch test (WifiPhy switching).");
+ NS_TEST_ASSERT_MSG_EQ (StateSwitchTest (WifiPhy::SLEEP), false, "Problem with state switch test (WifiPhy sleep).");
}
bool
@@ -178,6 +179,9 @@
case WifiPhy::SWITCHING:
current = devModel->GetSwitchingCurrentA ();
break;
+ case WifiPhy::SLEEP:
+ current = devModel->GetSleepCurrentA ();
+ break;
default:
NS_FATAL_ERROR ("Undefined radio state: " << state);
break;
--- a/src/energy/test/rv-battery-model-test.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/test/rv-battery-model-test.cc Fri Sep 05 16:33:57 2014 -0700
@@ -740,6 +740,7 @@
// Set alpha & beta values
rvModelHelper.Set ("RvBatteryModelAlphaValue", DoubleValue (m_alpha));
rvModelHelper.Set ("RvBatteryModelBetaValue", DoubleValue (m_beta));
+ rvModelHelper.Set ("RvBatteryModelLowBatteryThreshold", DoubleValue (0.0));
// install source
EnergySourceContainer sources = rvModelHelper.Install (c);
// device energy model
@@ -827,6 +828,7 @@
// Set alpha & beta values
rvModelHelper.Set ("RvBatteryModelAlphaValue", DoubleValue (m_alpha));
rvModelHelper.Set ("RvBatteryModelBetaValue", DoubleValue (m_beta));
+ rvModelHelper.Set ("RvBatteryModelLowBatteryThreshold", DoubleValue (0.0));
// install source
EnergySourceContainer sources = rvModelHelper.Install (c);
// device energy model
--- a/src/energy/wscript Fri Sep 05 15:38:55 2014 -0700
+++ b/src/energy/wscript Fri Sep 05 16:33:57 2014 -0700
@@ -13,6 +13,7 @@
'model/simple-device-energy-model.cc',
'model/energy-harvester.cc',
'model/basic-energy-harvester.cc',
+ 'model/wifi-tx-current-model.cc',
'helper/energy-source-container.cc',
'helper/energy-model-helper.cc',
'helper/basic-energy-source-helper.cc',
@@ -44,6 +45,7 @@
'model/simple-device-energy-model.h',
'model/energy-harvester.h',
'model/basic-energy-harvester.h',
+ 'model/wifi-tx-current-model.h',
'helper/energy-source-container.h',
'helper/energy-model-helper.h',
'helper/basic-energy-source-helper.h',
--- a/src/uan/model/acoustic-modem-energy-model.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/uan/model/acoustic-modem-energy-model.h Fri Sep 05 16:33:57 2014 -0700
@@ -169,6 +169,15 @@
*/
virtual void HandleEnergyDepletion (void);
+ /**
+ * \brief Handles energy recharged.
+ *
+ * Not implemented
+ */
+ virtual void HandleEnergyRecharged (void)
+ {
+ }
+
private:
void DoDispose (void);
--- a/src/wifi/doc/wifi.rst Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/doc/wifi.rst Fri Sep 05 16:33:57 2014 -0700
@@ -479,6 +479,7 @@
#. RX: the PHY is synchronized on a signal and is waiting until it has received
its last bit to forward it to the MAC.
#. IDLE: the PHY is not in the TX or RX states.
+#. SLEEP: the PHY is in a power save mode and cannot send nor receive frames.
When the first bit of a new packet is received while the PHY is not IDLE (that
is, it is already synchronized on the reception of another earlier packet or it
--- a/src/wifi/examples/wifi-phy-test.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/examples/wifi-phy-test.cc Fri Sep 05 16:33:57 2014 -0700
@@ -73,7 +73,7 @@
WifiTxVector txVector;
txVector.SetTxPowerLevel (m_input.txPowerLevel);
txVector.SetMode (mode);
- m_tx->SendPacket (p, mode, WIFI_PREAMBLE_SHORT, txVector);
+ m_tx->SendPacket (p, txVector, WIFI_PREAMBLE_SHORT);
}
void
@@ -178,8 +178,7 @@
WifiTxVector txVector;
txVector.SetTxPowerLevel (m_input.txPowerLevelA);
txVector.SetMode (WifiMode (m_input.txModeA));
- m_txA->SendPacket (p, WifiMode (m_input.txModeA),
- WIFI_PREAMBLE_SHORT, txVector);
+ m_txA->SendPacket (p, txVector, WIFI_PREAMBLE_SHORT);
}
void
@@ -190,8 +189,7 @@
WifiTxVector txVector;
txVector.SetTxPowerLevel (m_input.txPowerLevelB);
txVector.SetMode (WifiMode (m_input.txModeB));
- m_txB->SendPacket (p, WifiMode (m_input.txModeB),
- WIFI_PREAMBLE_SHORT, txVector);
+ m_txB->SendPacket (p, txVector, WIFI_PREAMBLE_SHORT);
}
void
--- a/src/wifi/model/dcf-manager.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/model/dcf-manager.cc Fri Sep 05 16:33:57 2014 -0700
@@ -239,7 +239,7 @@
{
m_dcf->NotifyRxEndErrorNow ();
}
- virtual void NotifyTxStart (Time duration)
+ virtual void NotifyTxStart (Time duration, double txPowerDbm)
{
m_dcf->NotifyTxStartNow (duration);
}
@@ -251,6 +251,14 @@
{
m_dcf->NotifySwitchingStartNow (duration);
}
+ virtual void NotifySleep (void)
+ {
+ m_dcf->NotifySleepNow ();
+ }
+ virtual void NotifyWakeup (void)
+ {
+ m_dcf->NotifyWakeupNow ();
+ }
private:
ns3::DcfManager *m_dcf; //!< DcfManager to forward events to
};
@@ -275,6 +283,7 @@
m_lastSwitchingStart (MicroSeconds (0)),
m_lastSwitchingDuration (MicroSeconds (0)),
m_rxing (false),
+ m_sleeping (false),
m_slotTimeUs (0),
m_sifs (Seconds (0.0)),
m_phyListener (0),
@@ -423,6 +432,9 @@
DcfManager::RequestAccess (DcfState *state)
{
NS_LOG_FUNCTION (this << state);
+ // Deny access if in sleep mode
+ if (m_sleeping)
+ return;
UpdateBackoff ();
NS_ASSERT (!state->IsAccessRequested ());
state->NotifyAccessRequested ();
@@ -744,6 +756,38 @@
}
void
+DcfManager::NotifySleepNow (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_sleeping = true;
+ // Cancel timeout
+ if (m_accessTimeout.IsRunning ())
+ {
+ m_accessTimeout.Cancel ();
+ }
+}
+
+void
+DcfManager::NotifyWakeupNow (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_sleeping = false;
+ // Reset backoffs
+ for (States::iterator i = m_states.begin (); i != m_states.end (); i++)
+ {
+ DcfState *state = *i;
+ uint32_t remainingSlots = state->GetBackoffSlots ();
+ if (remainingSlots > 0)
+ {
+ state->UpdateBackoffSlotsNow (remainingSlots, Simulator::Now ());
+ NS_ASSERT (state->GetBackoffSlots () == 0);
+ }
+ state->ResetCw ();
+ state->m_accessRequested = false;
+ }
+}
+
+void
DcfManager::NotifyNavResetNow (Time duration)
{
NS_LOG_FUNCTION (this << duration);
--- a/src/wifi/model/dcf-manager.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/model/dcf-manager.h Fri Sep 05 16:33:57 2014 -0700
@@ -335,6 +335,14 @@
*/
void NotifySwitchingStartNow (Time duration);
/**
+ * Notify the DCF that the device has been put in sleep mode.
+ */
+ void NotifySleepNow (void);
+ /**
+ * Notify the DCF that the device has been resumed from sleep mode.
+ */
+ void NotifyWakeupNow (void);
+ /**
* \param duration the value of the received NAV.
*
* Called at end of rx
@@ -487,6 +495,7 @@
Time m_lastSwitchingStart;
Time m_lastSwitchingDuration;
bool m_rxing;
+ bool m_sleeping;
Time m_eifsNoDifs;
EventId m_accessTimeout;
uint32_t m_slotTimeUs;
--- a/src/wifi/model/mac-low.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/model/mac-low.cc Fri Sep 05 16:33:57 2014 -0700
@@ -270,7 +270,7 @@
virtual void NotifyRxEndError (void)
{
}
- virtual void NotifyTxStart (Time duration)
+ virtual void NotifyTxStart (Time duration, double txPowerDbm)
{
}
virtual void NotifyMaybeCcaBusyStart (Time duration)
@@ -280,6 +280,13 @@
{
m_macLow->NotifySwitchingStartNow (duration);
}
+ virtual void NotifySleep (void)
+ {
+ m_macLow->NotifySleepNow ();
+ }
+ virtual void NotifyWakeup (void)
+ {
+ }
private:
ns3::MacLow *m_macLow;
};
@@ -653,6 +660,22 @@
}
void
+MacLow::NotifySleepNow (void)
+{
+ NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
+ m_stationManager->Reset ();
+ CancelAllEvents ();
+ if (m_navCounterResetCtsMissed.IsRunning ())
+ {
+ m_navCounterResetCtsMissed.Cancel ();
+ }
+ m_lastNavStart = Simulator::Now ();
+ m_lastNavDuration = Seconds (0);
+ m_currentPacket = 0;
+ m_listener = 0;
+}
+
+void
MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiMode txMode, WifiPreamble preamble)
{
NS_LOG_FUNCTION (this << packet << rxSnr << txMode << preamble);
@@ -1249,7 +1272,7 @@
", mode=" << txVector.GetMode() <<
", duration=" << hdr->GetDuration () <<
", seq=0x" << std::hex << m_currentHdr.GetSequenceControl () << std::dec);
- m_phy->SendPacket (packet, txVector.GetMode(), preamble, txVector);
+ m_phy->SendPacket (packet, txVector, preamble);
}
void
--- a/src/wifi/model/mac-low.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/model/mac-low.h Fri Sep 05 16:33:57 2014 -0700
@@ -643,6 +643,12 @@
*/
void NotifySwitchingStartNow (Time duration);
/**
+ * This method is typically invoked by the PhyMacLowListener to notify
+ * the MAC layer that the device has been put into sleep mode. When the device is put
+ * into sleep mode, pending MAC transmissions (RTS, CTS, DATA and ACK) are cancelled.
+ */
+ void NotifySleepNow (void);
+ /**
* \param respHdr Add block ack response from originator (action
* frame).
* \param originator Address of peer station involved in block ack
--- a/src/wifi/model/wifi-phy-state-helper.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/model/wifi-phy-state-helper.cc Fri Sep 05 16:33:57 2014 -0700
@@ -51,6 +51,7 @@
WifiPhyStateHelper::WifiPhyStateHelper ()
: m_rxing (false),
+ m_sleeping (false),
m_endTx (Seconds (0)),
m_endRx (Seconds (0)),
m_endCcaBusy (Seconds (0)),
@@ -59,6 +60,7 @@
m_startRx (Seconds (0)),
m_startCcaBusy (Seconds (0)),
m_startSwitching (Seconds (0)),
+ m_startSleep (Seconds (0)),
m_previousStateChangeTime (Seconds (0))
{
NS_LOG_FUNCTION (this);
@@ -110,6 +112,11 @@
{
return (GetState () == WifiPhy::SWITCHING);
}
+bool
+WifiPhyStateHelper::IsStateSleep (void)
+{
+ return (GetState () == WifiPhy::SLEEP);
+}
@@ -141,6 +148,10 @@
case WifiPhy::IDLE:
retval = Seconds (0);
break;
+ case WifiPhy::SLEEP:
+ NS_FATAL_ERROR ("Cannot determine when the device will wake up.");
+ retval = Seconds (0);
+ break;
default:
NS_FATAL_ERROR ("Invalid WifiPhy state.");
retval = Seconds (0);
@@ -159,7 +170,11 @@
enum WifiPhy::State
WifiPhyStateHelper::GetState (void)
{
- if (m_endTx > Simulator::Now ())
+ if (m_sleeping)
+ {
+ return WifiPhy::SLEEP;
+ }
+ else if (m_endTx > Simulator::Now ())
{
return WifiPhy::TX;
}
@@ -183,11 +198,11 @@
void
-WifiPhyStateHelper::NotifyTxStart (Time duration)
+WifiPhyStateHelper::NotifyTxStart (Time duration, double txPowerDbm)
{
for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
{
- (*i)->NotifyTxStart (duration);
+ (*i)->NotifyTxStart (duration, txPowerDbm);
}
}
void
@@ -230,6 +245,23 @@
(*i)->NotifySwitchingStart (duration);
}
}
+void
+WifiPhyStateHelper::NotifySleep (void)
+{
+ for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
+ {
+ (*i)->NotifySleep ();
+ }
+}
+void
+WifiPhyStateHelper::NotifyWakeup (void)
+{
+ for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
+ {
+ (*i)->NotifyWakeup ();
+ }
+}
+
void
WifiPhyStateHelper::LogPreviousIdleAndCcaBusyStates (void)
@@ -252,11 +284,10 @@
}
void
-WifiPhyStateHelper::SwitchToTx (Time txDuration, Ptr<const Packet> packet, WifiMode txMode,
- WifiPreamble preamble, uint8_t txPower)
+WifiPhyStateHelper::SwitchToTx (Time txDuration, Ptr<const Packet> packet, double txPowerDbm,
+ WifiTxVector txVector, WifiPreamble preamble)
{
- m_txTrace (packet, txMode, preamble, txPower);
- NotifyTxStart (txDuration);
+ m_txTrace (packet, txVector.GetMode(), preamble, txVector.GetTxPowerLevel());
Time now = Simulator::Now ();
switch (GetState ())
{
@@ -279,6 +310,7 @@
LogPreviousIdleAndCcaBusyStates ();
break;
case WifiPhy::SWITCHING:
+ case WifiPhy::SLEEP:
default:
NS_FATAL_ERROR ("Invalid WifiPhy state.");
break;
@@ -287,13 +319,13 @@
m_previousStateChangeTime = now;
m_endTx = now + txDuration;
m_startTx = now;
+ NotifyTxStart (txDuration, txPowerDbm);
}
void
WifiPhyStateHelper::SwitchToRx (Time rxDuration)
{
NS_ASSERT (IsStateIdle () || IsStateCcaBusy ());
NS_ASSERT (!m_rxing);
- NotifyRxStart (rxDuration);
Time now = Simulator::Now ();
switch (GetState ())
{
@@ -310,6 +342,7 @@
case WifiPhy::SWITCHING:
case WifiPhy::RX:
case WifiPhy::TX:
+ case WifiPhy::SLEEP:
NS_FATAL_ERROR ("Invalid WifiPhy state.");
break;
}
@@ -317,13 +350,13 @@
m_rxing = true;
m_startRx = now;
m_endRx = now + rxDuration;
+ NotifyRxStart (rxDuration);
NS_ASSERT (IsStateRx ());
}
void
WifiPhyStateHelper::SwitchToChannelSwitching (Time switchingDuration)
{
- NotifySwitchingStart (switchingDuration);
Time now = Simulator::Now ();
switch (GetState ())
{
@@ -347,6 +380,7 @@
break;
case WifiPhy::TX:
case WifiPhy::SWITCHING:
+ case WifiPhy::SLEEP:
default:
NS_FATAL_ERROR ("Invalid WifiPhy state.");
break;
@@ -361,6 +395,7 @@
m_previousStateChangeTime = now;
m_startSwitching = now;
m_endSwitching = now + switchingDuration;
+ NotifySwitchingStart (switchingDuration);
NS_ASSERT (IsStateSwitching ());
}
@@ -410,6 +445,8 @@
{
case WifiPhy::SWITCHING:
break;
+ case WifiPhy::SLEEP:
+ break;
case WifiPhy::IDLE:
LogPreviousIdleAndCcaBusyStates ();
break;
@@ -426,5 +463,48 @@
}
m_endCcaBusy = std::max (m_endCcaBusy, now + duration);
}
+void
+WifiPhyStateHelper::SwitchToSleep (void)
+{
+ Time now = Simulator::Now ();
+ switch (GetState ())
+ {
+ case WifiPhy::IDLE:
+ LogPreviousIdleAndCcaBusyStates ();
+ break;
+ case WifiPhy::CCA_BUSY:
+ {
+ Time ccaStart = Max (m_endRx, m_endTx);
+ ccaStart = Max (ccaStart, m_startCcaBusy);
+ ccaStart = Max (ccaStart, m_endSwitching);
+ m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
+ } break;
+ case WifiPhy::RX:
+ case WifiPhy::SWITCHING:
+ case WifiPhy::TX:
+ case WifiPhy::SLEEP:
+ NS_FATAL_ERROR ("Invalid WifiPhy state.");
+ break;
+ }
+ m_previousStateChangeTime = now;
+ m_sleeping = true;
+ m_startSleep = now;
+ NotifySleep ();
+ NS_ASSERT (IsStateSleep ());
+}
+void
+WifiPhyStateHelper::SwitchFromSleep (Time duration)
+{
+ NS_ASSERT (IsStateSleep ());
+ Time now = Simulator::Now ();
+ m_stateLogger (m_startSleep, now - m_startSleep, WifiPhy::SLEEP);
+ m_previousStateChangeTime = now;
+ m_sleeping = false;
+ NotifyWakeup ();
+ // update m_endCcaBusy after the sleep period
+ m_endCcaBusy = std::max (m_endCcaBusy, now + duration);
+ if (m_endCcaBusy > now)
+ NotifyMaybeCcaBusyStart (m_endCcaBusy - now);
+}
} // namespace ns3
--- a/src/wifi/model/wifi-phy-state-helper.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/model/wifi-phy-state-helper.h Fri Sep 05 16:33:57 2014 -0700
@@ -100,6 +100,12 @@
*/
bool IsStateSwitching (void);
/**
+ * Check whether the current state is SLEEP.
+ *
+ * \return true if the current state is SLEEP, false otherwise
+ */
+ bool IsStateSleep (void);
+ /**
* Return the elapsed time of the current state.
*
* \return the elapsed time of the current state
@@ -123,11 +129,11 @@
*
* \param txDuration the duration of the TX
* \param packet the packet
- * \param txMode the transmission mode of the packet
+ * \param txPowerDbm the nominal tx power in dBm
+ * \param txVector the tx vector of the packet
* \param preamble the preamble of the packet
- * \param txPower the transmission power
*/
- void SwitchToTx (Time txDuration, Ptr<const Packet> packet, WifiMode txMode, WifiPreamble preamble, uint8_t txPower);
+ void SwitchToTx (Time txDuration, Ptr<const Packet> packet, double txPowerDbm, WifiTxVector txVector, WifiPreamble preamble);
/**
* Switch state to RX for the given duration.
*
@@ -162,6 +168,16 @@
* \param duration the duration of CCA busy state
*/
void SwitchMaybeToCcaBusy (Time duration);
+ /**
+ * Switch to sleep mode.
+ */
+ void SwitchToSleep (void);
+ /**
+ * Switch from sleep mode.
+ *
+ * \param duration the duration of CCA busy state
+ */
+ void SwitchFromSleep (Time duration);
TracedCallback<Time,Time,enum WifiPhy::State> m_stateLogger;
private:
@@ -179,9 +195,9 @@
* Notify all WifiPhyListener that the transmission has started for the given duration.
*
* \param duration the duration of the transmission
+ * \param txPowerDbm the nominal tx power in dBm
*/
- void NotifyTxStart (Time duration);
- //void NotifyWakeup (void);
+ void NotifyTxStart (Time duration, double txPowerDbm);
/**
* Notify all WifiPhyListener that the reception has started for the given duration.
*
@@ -210,11 +226,20 @@
*/
void NotifySwitchingStart (Time duration);
/**
+ * Notify all WifiPhyListener that we are going to sleep
+ */
+ void NotifySleep (void);
+ /**
+ * Notify all WifiPhyListener that we woke up
+ */
+ void NotifyWakeup (void);
+ /**
* Switch the state from RX.
*/
void DoSwitchFromRx (void);
bool m_rxing;
+ bool m_sleeping;
Time m_endTx;
Time m_endRx;
Time m_endCcaBusy;
@@ -223,6 +248,7 @@
Time m_startRx;
Time m_startCcaBusy;
Time m_startSwitching;
+ Time m_startSleep;
Time m_previousStateChangeTime;
Listeners m_listeners;
--- a/src/wifi/model/wifi-phy.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/model/wifi-phy.cc Fri Sep 05 16:33:57 2014 -0700
@@ -1408,6 +1408,8 @@
return (os << "RX");
case WifiPhy::SWITCHING:
return (os << "SWITCHING");
+ case WifiPhy::SLEEP:
+ return (os << "SLEEP");
default:
NS_FATAL_ERROR ("Invalid WifiPhy state");
return (os << "INVALID");
--- a/src/wifi/model/wifi-phy.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/model/wifi-phy.h Fri Sep 05 16:33:57 2014 -0700
@@ -73,6 +73,7 @@
virtual void NotifyRxEndError (void) = 0;
/**
* \param duration the expected transmission duration.
+ * \param txPowerDbm the nominal tx power in dBm
*
* We are about to send the first bit of the packet.
* We do not send any event to notify the end of
@@ -80,7 +81,7 @@
* channel implicitely reverts to the idle state
* unless they have received a cca busy report.
*/
- virtual void NotifyTxStart (Time duration) = 0;
+ virtual void NotifyTxStart (Time duration, double txPowerDbm) = 0;
/**
* \param duration the expected busy duration.
@@ -106,6 +107,14 @@
* channel implicitely reverts to the idle or busy states.
*/
virtual void NotifySwitchingStart (Time duration) = 0;
+ /**
+ * Notify listeners that we went to sleep
+ */
+ virtual void NotifySleep (void) = 0;
+ /**
+ * Notify listeners that we woke up
+ */
+ virtual void NotifyWakeup (void) = 0;
};
@@ -141,7 +150,11 @@
/**
* The PHY layer is switching to other channel.
*/
- SWITCHING
+ SWITCHING,
+ /**
+ * The PHY layer is sleeping.
+ */
+ SLEEP
};
/**
@@ -193,11 +206,12 @@
/**
* \param packet the packet to send
* \param mode the transmission mode to use to send this packet
+ * \param txvector the txvector that has tx parameters such as mode, the transmission mode to use to send
+ * this packet, and txPowerLevel, a power level to use to send this packet. The real transmission
+ * power is calculated as txPowerMin + txPowerLevel * (txPowerMax - txPowerMin) / nTxLevels
* \param preamble the type of preamble to use to send this packet.
- * \param txvector the txvector that has tx parameters as txPowerLevel a power level to use to send this packet. The real
- * transmission power is calculated as txPowerMin + txPowerLevel * (txPowerMax - txPowerMin) / nTxLevels
*/
- virtual void SendPacket (Ptr<const Packet> packet, WifiMode mode, enum WifiPreamble preamble, WifiTxVector txvector) = 0;
+ virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txvector, enum WifiPreamble preamble) = 0;
/**
* \param listener the new listener
@@ -208,6 +222,15 @@
virtual void RegisterListener (WifiPhyListener *listener) = 0;
/**
+ * Put in sleep mode.
+ */
+ virtual void SetSleepMode (void) = 0;
+ /**
+ * Resume from sleep mode.
+ */
+ virtual void ResumeFromSleep (void) = 0;
+
+ /**
* \return true of the current state of the PHY layer is WifiPhy::IDLE, false otherwise.
*/
virtual bool IsStateIdle (void) = 0;
@@ -232,6 +255,10 @@
*/
virtual bool IsStateSwitching (void) = 0;
/**
+ * \return true if the current state of the PHY layer is WifiPhy::SLEEP, false otherwise.
+ */
+ virtual bool IsStateSleep (void) = 0;
+ /**
* \return the amount of time since the current state has started.
*/
virtual Time GetStateDuration (void) = 0;
--- a/src/wifi/model/yans-wifi-phy.cc Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/model/yans-wifi-phy.cc Fri Sep 05 16:33:57 2014 -0700
@@ -397,6 +397,9 @@
case YansWifiPhy::IDLE:
goto switchChannel;
break;
+ case YansWifiPhy::SLEEP:
+ NS_LOG_DEBUG ("channel switching ignored in sleep mode");
+ break;
default:
NS_ASSERT (false);
break;
@@ -432,6 +435,59 @@
}
void
+YansWifiPhy::SetSleepMode (void)
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state->GetState ())
+ {
+ case YansWifiPhy::TX:
+ NS_LOG_DEBUG ("setting sleep mode postponed until end of current transmission");
+ Simulator::Schedule (GetDelayUntilIdle (), &YansWifiPhy::SetSleepMode, this);
+ break;
+ case YansWifiPhy::RX:
+ NS_LOG_DEBUG ("setting sleep mode postponed until end of current reception");
+ Simulator::Schedule (GetDelayUntilIdle (), &YansWifiPhy::SetSleepMode, this);
+ break;
+ case YansWifiPhy::SWITCHING:
+ NS_LOG_DEBUG ("setting sleep mode postponed until end of channel switching");
+ Simulator::Schedule (GetDelayUntilIdle (), &YansWifiPhy::SetSleepMode, this);
+ break;
+ case YansWifiPhy::CCA_BUSY:
+ case YansWifiPhy::IDLE:
+ NS_LOG_DEBUG ("setting sleep mode");
+ m_state->SwitchToSleep ();
+ break;
+ case YansWifiPhy::SLEEP:
+ NS_LOG_DEBUG ("already in sleep mode");
+ break;
+ default:
+ NS_ASSERT (false);
+ break;
+ }
+}
+
+void
+YansWifiPhy::ResumeFromSleep (void)
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state->GetState ())
+ {
+ case YansWifiPhy::TX:
+ case YansWifiPhy::RX:
+ case YansWifiPhy::IDLE:
+ case YansWifiPhy::CCA_BUSY:
+ case YansWifiPhy::SWITCHING:
+ NS_LOG_DEBUG ("not in sleep mode, there is nothing to resume");
+ break;
+ case YansWifiPhy::SLEEP:
+ NS_LOG_DEBUG ("resuming from sleep mode");
+ Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaMode1ThresholdW);
+ m_state->SwitchFromSleep (delayUntilCcaEnd);
+ break;
+ }
+}
+
+void
YansWifiPhy::SetReceiveOkCallback (RxOkCallback callback)
{
m_state->SetReceiveOkCallback (callback);
@@ -535,6 +591,10 @@
goto maybeCcaBusy;
}
break;
+ case YansWifiPhy::SLEEP:
+ NS_LOG_DEBUG ("drop packet because in sleep mode");
+ NotifyRxDrop (packet);
+ break;
}
return;
@@ -553,9 +613,9 @@
}
void
-YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiMode txMode, WifiPreamble preamble, WifiTxVector txVector)
+YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble)
{
- NS_LOG_FUNCTION (this << packet << txMode << preamble << (uint32_t)txVector.GetTxPowerLevel());
+ NS_LOG_FUNCTION (this << packet << txVector.GetMode() << preamble << (uint32_t)txVector.GetTxPowerLevel());
/* Transmission can happen if:
* - we are syncing on a packet. It is the responsability of the
* MAC layer to avoid doing this but the PHY does nothing to
@@ -564,6 +624,13 @@
*/
NS_ASSERT (!m_state->IsStateTx () && !m_state->IsStateSwitching ());
+ if (m_state->IsStateSleep ())
+ {
+ NS_LOG_DEBUG ("Dropping packet because in sleep mode");
+ NotifyTxDrop (packet);
+ return;
+ }
+
Time txDuration = CalculateTxDuration (packet->GetSize (), txVector, preamble);
if (m_state->IsStateRx ())
{
@@ -574,7 +641,7 @@
uint32_t dataRate500KbpsUnits = txVector.GetMode().GetDataRate () * txVector.GetNss() / 500000;
bool isShortPreamble = (WIFI_PREAMBLE_SHORT == preamble);
NotifyMonitorSniffTx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, isShortPreamble, txVector.GetTxPowerLevel());
- m_state->SwitchToTx (txDuration, packet, txVector.GetMode(), preamble, txVector.GetTxPowerLevel());
+ m_state->SwitchToTx (txDuration, packet, GetPowerDbm (txVector.GetTxPowerLevel()), txVector, preamble);
m_channel->Send (this, packet, GetPowerDbm ( txVector.GetTxPowerLevel()) + m_txGainDb, txVector, preamble);
}
@@ -748,6 +815,11 @@
{
return m_state->IsStateSwitching ();
}
+bool
+YansWifiPhy::IsStateSleep (void)
+{
+ return m_state->IsStateSleep ();
+}
Time
YansWifiPhy::GetStateDuration (void)
--- a/src/wifi/model/yans-wifi-phy.h Fri Sep 05 15:38:55 2014 -0700
+++ b/src/wifi/model/yans-wifi-phy.h Fri Sep 05 16:33:57 2014 -0700
@@ -247,14 +247,17 @@
virtual uint32_t GetNTxPower (void) const;
virtual void SetReceiveOkCallback (WifiPhy::RxOkCallback callback);
virtual void SetReceiveErrorCallback (WifiPhy::RxErrorCallback callback);
- virtual void SendPacket (Ptr<const Packet> packet, WifiMode mode, enum WifiPreamble preamble, WifiTxVector txvector);
+ virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txvector, enum WifiPreamble preamble);
virtual void RegisterListener (WifiPhyListener *listener);
+ virtual void SetSleepMode (void);
+ virtual void ResumeFromSleep (void);
virtual bool IsStateCcaBusy (void);
virtual bool IsStateIdle (void);
virtual bool IsStateBusy (void);
virtual bool IsStateRx (void);
virtual bool IsStateTx (void);
virtual bool IsStateSwitching (void);
+ virtual bool IsStateSleep (void);
virtual Time GetStateDuration (void);
virtual Time GetDelayUntilIdle (void);
virtual Time GetLastRxStartTime (void) const;