add support for a Wifi sleep mode

This commit is contained in:
Stefano Avallone
2014-09-05 16:33:57 -07:00
parent d3ff87aeb2
commit bd8c6c8a32
34 changed files with 1323 additions and 59 deletions

View File

@@ -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;
}

View File

@@ -43,6 +43,15 @@ Energy Harvester
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 @@ WiFi Radio Energy Model
* ``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
#######################

View File

@@ -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 @@ WifiRadioEnergyModelHelper::WifiRadioEnergyModelHelper ()
{
m_radioEnergy.SetTypeId ("ns3::WifiRadioEnergyModel");
m_depletionCallback.Nullify ();
m_rechargedCallback.Nullify ();
}
WifiRadioEnergyModelHelper::~WifiRadioEnergyModelHelper ()
@@ -50,6 +52,38 @@ WifiRadioEnergyModelHelper::SetDepletionCallback (
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 @@ WifiRadioEnergyModelHelper::DoInstall (Ptr<NetDevice> device,
// 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;
}

View File

@@ -62,6 +62,44 @@ public:
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:
private:
ObjectFactory m_radioEnergy;
WifiRadioEnergyModel::WifiRadioEnergyDepletionCallback m_depletionCallback;
WifiRadioEnergyModel::WifiRadioEnergyRechargedCallback m_rechargedCallback;
ObjectFactory m_txCurrentModel;
};

View File

@@ -49,6 +49,16 @@ BasicEnergySource::GetTypeId (void)
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 @@ BasicEnergySource::BasicEnergySource ()
{
NS_LOG_FUNCTION (this);
m_lastUpdateTime = Seconds (0.0);
m_depleted = false;
}
BasicEnergySource::~BasicEnergySource ()
@@ -151,13 +162,19 @@ BasicEnergySource::UpdateEnergySource (void)
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 @@ BasicEnergySource::HandleEnergyDrainedEvent (void)
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

View File

@@ -117,6 +117,14 @@ private:
*/
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
@@ -130,6 +138,10 @@ private:
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

View File

@@ -93,6 +93,12 @@ public:
*/
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:
/**

View File

@@ -200,6 +200,18 @@ EnergySource::NotifyEnergyDrained (void)
}
}
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)
{

View File

@@ -222,6 +222,12 @@ protected:
*/
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

View File

@@ -45,6 +45,11 @@ LiIonEnergySource::GetTypeId (void)
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 @@ LiIonEnergySource::UpdateEnergySource (void)
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 @@ LiIonEnergySource::HandleEnergyDrainedEvent (void)
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
}
}

View File

@@ -185,6 +185,7 @@ private:
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

View File

@@ -44,6 +44,11 @@ RvBatteryModel::GetTypeId (void)
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 @@ RvBatteryModel::UpdateEnergySource (void)
}
// 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!");

View File

@@ -246,6 +246,8 @@ private:
*/
TracedValue<double> m_batteryLevel;
double m_lowBatteryTh; // low battery threshold, as a fraction of the initial energy
/**
* (1 / sampling interval) = sampling frequency
*/

View File

@@ -94,6 +94,15 @@ public:
{
}
/**
* \brief Handles energy recharged.
*
* Not implemented
*/
virtual void HandleEnergyRecharged (void)
{
}
/**
* \param current the current draw of device.
*

View File

@@ -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 @@ WifiRadioEnergyModel::GetTypeId (void)
.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 @@ WifiRadioEnergyModel::WifiRadioEnergyModel ()
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 @@ WifiRadioEnergyModel::SetSwitchingCurrentA (double switchingCurrentA)
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
@@ -197,6 +226,33 @@ WifiRadioEnergyModel::SetEnergyDepletionCallback (
m_energyDepletionCallback = callback;
}
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)
{
@@ -225,6 +281,9 @@ WifiRadioEnergyModel::ChangeState (int newState)
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 @@ WifiRadioEnergyModel::ChangeState (int newState)
// 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 @@ WifiRadioEnergyModel::HandleEnergyDepletion (void)
}
}
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 @@ WifiRadioEnergyModel::DoGetCurrentA (void) const
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 @@ WifiRadioEnergyModel::SetWifiRadioState (const WifiPhy::State state)
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 @@ WifiRadioEnergyModelPhyListener::WifiRadioEnergyModelPhyListener ()
{
NS_LOG_FUNCTION (this);
m_changeStateCallback.Nullify ();
m_updateTxCurrentCallback.Nullify ();
}
WifiRadioEnergyModelPhyListener::~WifiRadioEnergyModelPhyListener ()
@@ -347,6 +440,14 @@ WifiRadioEnergyModelPhyListener::SetChangeStateCallback (DeviceEnergyModel::Chan
m_changeStateCallback = callback;
}
void
WifiRadioEnergyModelPhyListener::SetUpdateTxCurrentCallback (UpdateTxCurrentCallback callback)
{
NS_LOG_FUNCTION (this << &callback);
NS_ASSERT (!callback.IsNull ());
m_updateTxCurrentCallback = callback;
}
void
WifiRadioEnergyModelPhyListener::NotifyRxStart (Time duration)
{
@@ -382,9 +483,14 @@ WifiRadioEnergyModelPhyListener::NotifyRxEndError (void)
}
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 @@ WifiRadioEnergyModelPhyListener::NotifySwitchingStart (Time duration)
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.
*/

View File

@@ -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 @@ namespace ns3 {
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 ();
@@ -48,6 +55,13 @@ public:
*/
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.
*
@@ -82,10 +96,11 @@ public:
* 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 @@ public:
*/
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 @@ private:
*/
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 @@ private:
* 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 @@ public:
*/
typedef Callback<void> WifiRadioEnergyDepletionCallback;
/**
* Callback type for energy recharged handling.
*/
typedef Callback<void> WifiRadioEnergyRechargedCallback;
public:
static TypeId GetTypeId (void);
WifiRadioEnergyModel ();
@@ -183,6 +244,8 @@ public:
void SetRxCurrentA (double rxCurrentA);
double GetSwitchingCurrentA (void) const;
void SetSwitchingCurrentA (double switchingCurrentA);
double GetSleepCurrentA (void) const;
void SetSleepCurrentA (double sleepCurrentA);
/**
* \returns Current state.
@@ -196,6 +259,26 @@ public:
*/
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.
*
@@ -212,6 +295,13 @@ public:
*/
virtual void HandleEnergyDepletion (void);
/**
* \brief Handles energy recharged.
*
* Implements DeviceEnergyModel::HandleEnergyRecharged
*/
virtual void HandleEnergyRecharged (void);
/**
* \returns Pointer to the PHY listener.
*/
@@ -245,6 +335,8 @@ private:
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 @@ private:
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;
};

View File

@@ -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

View File

@@ -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 */

View File

@@ -93,6 +93,7 @@ BasicEnergyUpdateTest::DoRun (void)
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 @@ BasicEnergyUpdateTest::StateSwitchTest (WifiPhy::State state)
case WifiPhy::SWITCHING:
current = devModel->GetSwitchingCurrentA ();
break;
case WifiPhy::SLEEP:
current = devModel->GetSleepCurrentA ();
break;
default:
NS_FATAL_ERROR ("Undefined radio state: " << state);
break;

View File

@@ -740,6 +740,7 @@ BatteryLifetimeTest::ConstantLoadTest (double load, Time expLifetime)
// 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 @@ BatteryLifetimeTest::VariableLoadTest (std::vector<double> loads,
// 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

View File

@@ -13,6 +13,7 @@ def build(bld):
'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 @@ def build(bld):
'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',

View File

@@ -169,6 +169,15 @@ public:
*/
virtual void HandleEnergyDepletion (void);
/**
* \brief Handles energy recharged.
*
* Not implemented
*/
virtual void HandleEnergyRecharged (void)
{
}
private:
void DoDispose (void);

View File

@@ -479,6 +479,7 @@ The PHY layer can be in one of three states:
#. 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

View File

@@ -73,7 +73,7 @@ PsrExperiment::Send (void)
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 @@ CollisionExperiment::SendA (void) const
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 @@ CollisionExperiment::SendB (void) const
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

View File

@@ -239,7 +239,7 @@ public:
{
m_dcf->NotifyRxEndErrorNow ();
}
virtual void NotifyTxStart (Time duration)
virtual void NotifyTxStart (Time duration, double txPowerDbm)
{
m_dcf->NotifyTxStartNow (duration);
}
@@ -251,6 +251,14 @@ public:
{
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 @@ DcfManager::DcfManager ()
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 @@ void
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 ();
@@ -743,6 +755,38 @@ DcfManager::NotifySwitchingStartNow (Time duration)
}
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)
{

View File

@@ -334,6 +334,14 @@ public:
* but they won't access to the medium until the end of the channel switching.
*/
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.
*
@@ -487,6 +495,7 @@ private:
Time m_lastSwitchingStart;
Time m_lastSwitchingDuration;
bool m_rxing;
bool m_sleeping;
Time m_eifsNoDifs;
EventId m_accessTimeout;
uint32_t m_slotTimeUs;

View File

@@ -270,7 +270,7 @@ public:
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 @@ public:
{
m_macLow->NotifySwitchingStartNow (duration);
}
virtual void NotifySleep (void)
{
m_macLow->NotifySleepNow ();
}
virtual void NotifyWakeup (void)
{
}
private:
ns3::MacLow *m_macLow;
};
@@ -652,6 +659,22 @@ MacLow::NotifySwitchingStartNow (Time duration)
m_listener = 0;
}
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)
{
@@ -1249,7 +1272,7 @@ MacLow::ForwardDown (Ptr<const Packet> packet, const WifiMacHeader* hdr,
", 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

View File

@@ -642,6 +642,12 @@ public:
* occurs, pending MAC transmissions (RTS, CTS, DATA and ACK) are cancelled.
*/
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).

View File

@@ -51,6 +51,7 @@ WifiPhyStateHelper::GetTypeId (void)
WifiPhyStateHelper::WifiPhyStateHelper ()
: m_rxing (false),
m_sleeping (false),
m_endTx (Seconds (0)),
m_endRx (Seconds (0)),
m_endCcaBusy (Seconds (0)),
@@ -59,6 +60,7 @@ WifiPhyStateHelper::WifiPhyStateHelper ()
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 @@ WifiPhyStateHelper::IsStateSwitching (void)
{
return (GetState () == WifiPhy::SWITCHING);
}
bool
WifiPhyStateHelper::IsStateSleep (void)
{
return (GetState () == WifiPhy::SLEEP);
}
@@ -141,6 +148,10 @@ WifiPhyStateHelper::GetDelayUntilIdle (void)
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 @@ WifiPhyStateHelper::GetLastRxStartTime (void) const
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 @@ WifiPhyStateHelper::GetState (void)
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 @@ WifiPhyStateHelper::NotifySwitchingStart (Time duration)
(*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 @@ WifiPhyStateHelper::LogPreviousIdleAndCcaBusyStates (void)
}
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 @@ WifiPhyStateHelper::SwitchToTx (Time txDuration, Ptr<const Packet> packet, WifiM
LogPreviousIdleAndCcaBusyStates ();
break;
case WifiPhy::SWITCHING:
case WifiPhy::SLEEP:
default:
NS_FATAL_ERROR ("Invalid WifiPhy state.");
break;
@@ -287,13 +319,13 @@ WifiPhyStateHelper::SwitchToTx (Time txDuration, Ptr<const Packet> packet, WifiM
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 @@ WifiPhyStateHelper::SwitchToRx (Time rxDuration)
case WifiPhy::SWITCHING:
case WifiPhy::RX:
case WifiPhy::TX:
case WifiPhy::SLEEP:
NS_FATAL_ERROR ("Invalid WifiPhy state.");
break;
}
@@ -317,13 +350,13 @@ WifiPhyStateHelper::SwitchToRx (Time rxDuration)
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 @@ WifiPhyStateHelper::SwitchToChannelSwitching (Time switchingDuration)
break;
case WifiPhy::TX:
case WifiPhy::SWITCHING:
case WifiPhy::SLEEP:
default:
NS_FATAL_ERROR ("Invalid WifiPhy state.");
break;
@@ -361,6 +395,7 @@ WifiPhyStateHelper::SwitchToChannelSwitching (Time switchingDuration)
m_previousStateChangeTime = now;
m_startSwitching = now;
m_endSwitching = now + switchingDuration;
NotifySwitchingStart (switchingDuration);
NS_ASSERT (IsStateSwitching ());
}
@@ -410,6 +445,8 @@ WifiPhyStateHelper::SwitchMaybeToCcaBusy (Time duration)
{
case WifiPhy::SWITCHING:
break;
case WifiPhy::SLEEP:
break;
case WifiPhy::IDLE:
LogPreviousIdleAndCcaBusyStates ();
break;
@@ -426,5 +463,48 @@ WifiPhyStateHelper::SwitchMaybeToCcaBusy (Time duration)
}
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

View File

@@ -99,6 +99,12 @@ public:
* \return true if the current state is SWITCHING, false otherwise
*/
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.
*
@@ -123,11 +129,11 @@ public:
*
* \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 @@ public:
* \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 @@ private:
* 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.
*
@@ -209,12 +225,21 @@ private:
* \param duration the delay to switch the channel
*/
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 @@ private:
Time m_startRx;
Time m_startCcaBusy;
Time m_startSwitching;
Time m_startSleep;
Time m_previousStateChangeTime;
Listeners m_listeners;

View File

@@ -1408,6 +1408,8 @@ std::ostream& operator<< (std::ostream& os, enum WifiPhy::State state)
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");

View File

@@ -73,6 +73,7 @@ public:
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 @@ public:
* 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 @@ public:
* 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 @@ public:
/**
* The PHY layer is switching to other channel.
*/
SWITCHING
SWITCHING,
/**
* The PHY layer is sleeping.
*/
SLEEP
};
/**
@@ -193,11 +206,12 @@ public:
/**
* \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
@@ -207,6 +221,15 @@ public:
*/
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.
*/
@@ -231,6 +254,10 @@ public:
* \return true of the current state of the PHY layer is WifiPhy::SWITCHING, false otherwise.
*/
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.
*/

View File

@@ -397,6 +397,9 @@ YansWifiPhy::SetChannelNumber (uint16_t nch)
case YansWifiPhy::IDLE:
goto switchChannel;
break;
case YansWifiPhy::SLEEP:
NS_LOG_DEBUG ("channel switching ignored in sleep mode");
break;
default:
NS_ASSERT (false);
break;
@@ -431,6 +434,59 @@ YansWifiPhy::GetChannelFrequencyMhz () const
return m_channelStartingFrequency + 5 * GetChannelNumber ();
}
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)
{
@@ -535,6 +591,10 @@ YansWifiPhy::StartReceivePacket (Ptr<Packet> packet,
goto maybeCcaBusy;
}
break;
case YansWifiPhy::SLEEP:
NS_LOG_DEBUG ("drop packet because in sleep mode");
NotifyRxDrop (packet);
break;
}
return;
@@ -553,9 +613,9 @@ maybeCcaBusy:
}
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 @@ YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiMode txMode, WifiPreamble
*/
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 @@ YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiMode txMode, WifiPreamble
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 @@ YansWifiPhy::IsStateSwitching (void)
{
return m_state->IsStateSwitching ();
}
bool
YansWifiPhy::IsStateSleep (void)
{
return m_state->IsStateSleep ();
}
Time
YansWifiPhy::GetStateDuration (void)

View File

@@ -247,14 +247,17 @@ public:
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;