Energy support for UAN module and Li-Ion energy model
authorAndrea Sacco <andrea.sacco85@gmail.com>
Tue, 21 Dec 2010 21:44:11 -0800
changeset 6715 ba60c821ad35
parent 6714 5f772405b80c
child 6716 e2c0e6a51e58
Energy support for UAN module and Li-Ion energy model
RELEASE_NOTES
src/contrib/energy/examples/li-ion-energy-source.cc
src/contrib/energy/examples/wscript
src/contrib/energy/model/li-ion-energy-source.cc
src/contrib/energy/model/li-ion-energy-source.h
src/contrib/energy/model/simple-device-energy-model.cc
src/contrib/energy/model/simple-device-energy-model.h
src/contrib/energy/test/li-ion-energy-source-test.cc
src/contrib/energy/wscript
src/devices/uan/doc/uan.h
src/devices/uan/helper/acoustic-modem-energy-model-helper.cc
src/devices/uan/helper/acoustic-modem-energy-model-helper.h
src/devices/uan/helper/uan-helper.cc
src/devices/uan/helper/uan-helper.h
src/devices/uan/model/acoustic-modem-energy-model.cc
src/devices/uan/model/acoustic-modem-energy-model.h
src/devices/uan/model/uan-phy-dual.cc
src/devices/uan/model/uan-phy-dual.h
src/devices/uan/model/uan-phy-gen.cc
src/devices/uan/model/uan-phy-gen.h
src/devices/uan/model/uan-phy.h
src/devices/uan/wscript
--- a/RELEASE_NOTES	Tue Dec 21 16:13:14 2010 -0800
+++ b/RELEASE_NOTES	Tue Dec 21 21:44:11 2010 -0800
@@ -79,6 +79,13 @@
 
    - New methods to print IPv4 routing tables to an output stream.
 
+   - Energy support for UAN module and Li-Ion energy model.
+     Now each network node can have an associated energy source
+     from which it consumes energy. The user can specify a custom
+     energy model for the underwater transducer, with default values
+     set for WHOI acoustic transducer. Li-Ion battery model added
+     into energy models folder.
+
 Bugs fixed
 ----------
 The following lists many of the bugs fixed or small feature additions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/energy/examples/li-ion-energy-source.cc	Tue Dec 21 21:44:11 2010 -0800
@@ -0,0 +1,102 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Andrea Sacco
+ *
+ * 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: Andrea Sacco <andrea.sacco85@gmail.com>
+ */
+
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/simple-device-energy-model.h"
+#include "ns3/li-ion-energy-source.h"
+#include "ns3/energy-source-container.h"
+
+using namespace ns3;
+
+/**
+ * In this simple example, we show how to create and drain energy from a
+ * LiIonEnergySource.
+ * We make a series of discharge calls to the energy source class with
+ * different current drain and duration until all the energy is depleted
+ * from the cell.
+ *
+ * Every 20 seconds it is printed out the actual cell voltage to verify
+ * that it follows the discharge curve of the datasheet [1].
+ *
+ * At the end of the example it is verified that after the energy depletion
+ * call, the cell voltage is below the threshold voltage.
+ *
+ * References:
+ * [1] Panasonic CGR18650DA Datasheet, http://www.panasonic.com/industrial/includes/pdf/Panasonic_LiIon_CGR18650DA.pdf
+ */
+
+static void
+PrintCellInfo (Ptr<LiIonEnergySource> es)
+{
+  std::cout << "At " << Simulator::Now ().GetSeconds () << " Cell voltage: " << es->GetSupplyVoltage () << " V Remaining Capacity: " <<
+  es->GetRemainingEnergy () / (3.6 * 3600) << " Ah" << std::endl;
+
+  if (!Simulator::IsFinished ())
+    {
+      Simulator::Schedule (Seconds (20),
+                           &PrintCellInfo,
+                           es);
+    }
+}
+
+int
+main (int argc, char **argv)
+{
+  // uncomment below to see the energy consumption details
+  // LogComponentEnable ("LiIonEnergySource", LOG_LEVEL_DEBUG);
+
+  Ptr<Node> node = CreateObject<Node> ();
+
+  Ptr<SimpleDeviceEnergyModel> sem = CreateObject<SimpleDeviceEnergyModel> ();
+  Ptr<EnergySourceContainer> esCont = CreateObject<EnergySourceContainer> ();
+  Ptr<LiIonEnergySource> es = CreateObject<LiIonEnergySource> ();
+  esCont->Add (es);
+  es->SetNode (node);
+  sem->SetEnergySource (es);
+  es->AppendDeviceEnergyModel (sem);
+  sem->SetNode (node);
+  node->AggregateObject (esCont);
+
+  Time now = Simulator::Now ();
+
+  // discharge at 2.33 A for 1700 seconds
+  sem->SetCurrentA (2.33);
+  now += Seconds (1701);
+
+
+  // discharge at 4.66 A for 628 seconds
+  Simulator::Schedule (now,
+                       &SimpleDeviceEnergyModel::SetCurrentA,
+                       sem,
+                       4.66);
+  now += Seconds (600);
+
+  PrintCellInfo (es);
+
+  Simulator::Stop (now);
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  // the cell voltage should be under 3.3v
+  DoubleValue v;
+  es->GetAttribute ("ThresholdVoltage", v);
+  NS_ASSERT (es->GetSupplyVoltage () <= v.Get ());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/energy/examples/wscript	Tue Dec 21 21:44:11 2010 -0800
@@ -0,0 +1,5 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    obj = bld.create_ns3_program('li-ion-energy-source', ['core', 'simulator', 'energy'])
+    obj.source = 'li-ion-energy-source.cc'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/energy/model/li-ion-energy-source.cc	Tue Dec 21 21:44:11 2010 -0800
@@ -0,0 +1,307 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Andrea Sacco
+ *
+ * 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: Andrea Sacco <andrea.sacco85@gmail.com>
+ */
+
+#include "li-ion-energy-source.h"
+#include "ns3/log.h"
+#include "ns3/assert.h"
+#include "ns3/double.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/simulator.h"
+
+#include <cmath>
+
+NS_LOG_COMPONENT_DEFINE ("LiIonEnergySource");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LiIonEnergySource);
+
+TypeId
+LiIonEnergySource::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::LiIonEnergySource")
+    .SetParent<EnergySource> ()
+    .AddConstructor<LiIonEnergySource> ()
+    .AddAttribute ("LiIonEnergySourceInitialEnergyJ",
+                   "Initial energy stored in basic energy source.",
+                   DoubleValue (31752.0),  // in Joules
+                   MakeDoubleAccessor (&LiIonEnergySource::SetInitialEnergy,
+                                       &LiIonEnergySource::GetInitialEnergy),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("IntialCellVoltage",
+                   "Initial (maximum) voltage of the cell (fully charged).",
+                   DoubleValue (4.05), // in Volts
+                   MakeDoubleAccessor (&LiIonEnergySource::SetInitialSupplyVoltage,
+                                       &LiIonEnergySource::GetSupplyVoltage),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("NominalCellVoltage",
+                   "Nominal voltage of the cell.",
+                   DoubleValue (3.6),  // in Volts
+                   MakeDoubleAccessor (&LiIonEnergySource::m_eNom),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("ExpCellVoltage",
+                   "Cell voltage at the end of the exponential zone.",
+                   DoubleValue (3.6),  // in Volts
+                   MakeDoubleAccessor (&LiIonEnergySource::m_eExp),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RatedCapacity",
+                   "Rated capacity of the cell.",
+                   DoubleValue (2.45),   // in Ah
+                   MakeDoubleAccessor (&LiIonEnergySource::m_qRated),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("NomCapacity",
+                   "Cell capacity at the end of the nominal zone.",
+                   DoubleValue (1.1),  // in Ah
+                   MakeDoubleAccessor (&LiIonEnergySource::m_qNom),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("ExpCapacity",
+                   "Cell Capacity at the end of the exponential zone.",
+                   DoubleValue (1.2),  // in Ah
+                   MakeDoubleAccessor (&LiIonEnergySource::m_qExp),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("InternalResistance",
+                   "Internal resistance of the cell",
+                   DoubleValue (0.083),  // in Ohms
+                   MakeDoubleAccessor (&LiIonEnergySource::m_internalResistance),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TypCurrent",
+                   "Typical discharge current used to fit the curves",
+                   DoubleValue (2.33), // in A
+                   MakeDoubleAccessor (&LiIonEnergySource::m_typCurrent),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("ThresholdVoltage",
+                   "Minimum threshold voltage to consider the battery depleted.",
+                   DoubleValue (3.3), // in Volts
+                   MakeDoubleAccessor (&LiIonEnergySource::m_minVoltTh),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("PeriodicEnergyUpdateInterval",
+                   "Time between two consecutive periodic energy updates.",
+                   TimeValue (Seconds (1.0)),
+                   MakeTimeAccessor (&LiIonEnergySource::SetEnergyUpdateInterval,
+                                     &LiIonEnergySource::GetEnergyUpdateInterval),
+                   MakeTimeChecker ())
+    .AddTraceSource ("RemainingEnergy",
+                     "Remaining energy at BasicEnergySource.",
+                     MakeTraceSourceAccessor (&LiIonEnergySource::m_remainingEnergyJ))
+  ;
+  return tid;
+}
+
+LiIonEnergySource::LiIonEnergySource ()
+  : m_drainedCapacity (0.0),
+    m_lastUpdateTime (Seconds (0.0))
+{
+}
+
+LiIonEnergySource::~LiIonEnergySource ()
+{
+}
+
+void
+LiIonEnergySource::SetInitialEnergy (double initialEnergyJ)
+{
+  NS_LOG_FUNCTION (this << initialEnergyJ);
+  NS_ASSERT (initialEnergyJ >= 0);
+  m_initialEnergyJ = initialEnergyJ;
+  // set remaining energy to be initial energy
+  m_remainingEnergyJ = m_initialEnergyJ;
+}
+
+double
+LiIonEnergySource::GetInitialEnergy (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_initialEnergyJ;
+}
+
+void
+LiIonEnergySource::SetInitialSupplyVoltage (double supplyVoltageV)
+{
+  m_eFull = supplyVoltageV;
+  m_supplyVoltageV = supplyVoltageV;
+}
+
+double
+LiIonEnergySource::GetSupplyVoltage (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_supplyVoltageV;
+}
+
+void
+LiIonEnergySource::SetEnergyUpdateInterval (Time interval)
+{
+  NS_LOG_FUNCTION (this);
+  m_energyUpdateInterval = interval;
+}
+
+Time
+LiIonEnergySource::GetEnergyUpdateInterval (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_energyUpdateInterval;
+}
+
+double
+LiIonEnergySource::GetRemainingEnergy (void)
+{
+  NS_LOG_FUNCTION (this);
+  // update energy source to get the latest remaining energy.
+  UpdateEnergySource ();
+  return m_remainingEnergyJ;
+}
+
+double
+LiIonEnergySource::GetEnergyFraction (void)
+{
+  NS_LOG_FUNCTION (this);
+  // update energy source to get the latest remaining energy.
+  UpdateEnergySource ();
+  return m_remainingEnergyJ / m_initialEnergyJ;
+}
+
+void
+LiIonEnergySource::DecreaseRemainingEnergy (double energyJ)
+{
+  NS_LOG_FUNCTION (this << energyJ);
+  NS_ASSERT (energyJ >= 0);
+  m_remainingEnergyJ -= energyJ;
+
+  // check if remaining energy is 0
+  if (m_supplyVoltageV <= m_minVoltTh)
+    {
+      HandleEnergyDrainedEvent ();
+    }
+}
+
+void
+LiIonEnergySource::IncreaseRemainingEnergy (double energyJ)
+{
+  NS_LOG_FUNCTION (this << energyJ);
+  NS_ASSERT (energyJ >= 0);
+  m_remainingEnergyJ += energyJ;
+}
+
+void
+LiIonEnergySource::UpdateEnergySource (void)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("LiIonEnergySource:Updating remaining energy at node #" <<
+                GetNode ()->GetId ());
+
+  // do not update if simulation has finished
+  if (Simulator::IsFinished ())
+    {
+      return;
+    }
+
+  m_energyUpdateEvent.Cancel ();
+
+  CalculateRemainingEnergy ();
+
+  if (m_remainingEnergyJ <= 0)
+    {
+      HandleEnergyDrainedEvent ();
+      return; // stop periodic update
+    }
+
+  m_lastUpdateTime = Simulator::Now ();
+
+  m_energyUpdateEvent = Simulator::Schedule (m_energyUpdateInterval,
+                                             &LiIonEnergySource::UpdateEnergySource,
+                                             this);
+}
+
+/*
+ * Private functions start here.
+ */
+void
+LiIonEnergySource::DoStart (void)
+{
+  NS_LOG_FUNCTION (this);
+  UpdateEnergySource ();  // start periodic update
+}
+
+void
+LiIonEnergySource::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+  // calculate remaining energy at the end of simulation
+  CalculateRemainingEnergy ();
+  BreakDeviceEnergyModelRefCycle ();  // break reference cycle
+}
+
+
+void
+LiIonEnergySource::HandleEnergyDrainedEvent (void)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("LiIonEnergySource:Energy depleted at node #" <<
+                GetNode ()->GetId ());
+  NotifyEnergyDrained (); // notify DeviceEnergyModel objects
+  m_remainingEnergyJ = 0; // energy never goes below 0
+}
+
+
+void
+LiIonEnergySource::CalculateRemainingEnergy (void)
+{
+  NS_LOG_FUNCTION (this);
+  double totalCurrentA = CalculateTotalCurrent ();
+  Time duration = Simulator::Now () - m_lastUpdateTime;
+  NS_ASSERT (duration.GetSeconds () >= 0);
+  // energy = current * voltage * time
+  double energyToDecreaseJ = totalCurrentA * m_supplyVoltageV * duration.GetSeconds ();
+  m_remainingEnergyJ -= energyToDecreaseJ;
+  m_drainedCapacity += (totalCurrentA * duration.GetSeconds () / 3600);
+  // update the supply voltage
+  m_supplyVoltageV = GetVoltage (totalCurrentA);
+  NS_LOG_DEBUG ("LiIonEnergySource:Remaining energy = " << m_remainingEnergyJ);
+}
+
+double
+LiIonEnergySource::GetVoltage (double i) const
+{
+  NS_LOG_FUNCTION (this << i);
+
+  // integral of i in dt, drained capacity in Ah
+  double it = m_drainedCapacity;
+
+  // empirical factors
+  double A = m_eFull - m_eExp;
+  double B = 3 / m_qExp;
+
+  // slope of the polarization curve
+  double K = std::abs ( (m_eFull - m_eNom + A * (exp (-B * m_qNom) - 1)) * (m_qRated - m_qNom) / m_qNom);
+
+  // constant voltage
+  double E0 = m_eFull + K + m_internalResistance * m_typCurrent - A;
+
+  double E = E0 - K * m_qRated / (m_qRated - it) + A * exp (-B * it);
+
+  // cell voltage
+  double V = E - m_internalResistance * i;
+
+  NS_LOG_DEBUG ("Voltage: " << V << " with E: " << E);
+
+  return V;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/energy/model/li-ion-energy-source.h	Tue Dec 21 21:44:11 2010 -0800
@@ -0,0 +1,202 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Andrea Sacco
+ *
+ * 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: Andrea Sacco <andrea.sacco85@gmail.com>
+ */
+
+#ifndef LI_ION_ENERGY_SOURCE
+#define LI_ION_ENERGY_SOURCE
+
+#include "ns3/traced-value.h"
+#include "ns3/energy-source.h"
+#include "ns3/nstime.h"
+#include "ns3/event-id.h"
+
+namespace ns3 {
+
+/**
+ * \brief Model a generic Lithium Ion Battery basing on [1][2].
+ *
+ * The model can be fitted to any type of Li-Ion Battery, simply changing the
+ * model parameters.
+ * The default values are fitted for the Panasonic CGR18650DA Li-Ion Battery [3].
+ *
+ * The energy is drained as defined from the EnergySource interface but, this class
+ * consider the non-linear behaviour of Li-Ion cell. Each time energy is drained from
+ * the cell, the class evaluates the discharge curve to get the actual cell's voltage,
+ * accordingly to State of Charge (SOC) and current's drain.
+ *
+ * If the actual voltage of the cell goes below the minimum threshold voltage, the
+ * cell is considered depleted and the energy drained event fired up.
+ *
+ *
+ * The model requires several parameters to approximates the discharge curves:
+ * - IntialCellVoltage, maximum voltage of the fully charged cell
+ * - NominalCellVoltage, nominal cell's voltage, is used to determine the end of the
+ *   nominal zone.
+ * - ExpCellVoltage, cell's voltage at the end of the exponential zone
+ * - RatedCapacity, rated capacity of the cell, in Ah
+ * - NomCapacity, cell's capacity at the end of the nominal zone, in Ah
+ * - ExpCapacity, cell's capacity at the end of the exponential zone, in Ah
+ * - InternalResistance, internal resistance of the cell, in Ohms
+ * - TypCurrent, typical discharge current value, used during the fitting process, in Ah
+ * - ThresholdVoltage, minimum threshold voltage below which the cell is considered
+ *   depleted
+ *
+ * For a complete reference of the energy source model and model's fitting please refer
+ * to <a href="http://www.nsnam.org/wiki/index.php/GSOC2010UANFramework">UAN Framework</a>
+ * page and <a href="http://www.nsnam.org/wiki/index.php/Li-Ion_model_fitting">Li-Ion model
+ * fitting</a> page.
+ *
+ * References:
+ * [1] C. M. Shepherd, "Design of Primary and Secondary Cells - Part 3. Battery discharge equation," U.S. Naval Research Laboratory, 1963
+ * [2] Tremblay, O.; Dessaint, L.-A.; Dekkiche, A.-I., "A Generic Battery Model for the Dynamic Simulation of Hybrid Electric Vehicles," Ecole de Technologie Superieure, Universite du Quebec, 2007
+ * [3] http://www.panasonic.com/industrial/includes/pdf/Panasonic_LiIon_CGR18650DA.pdf
+ */
+class LiIonEnergySource : public EnergySource
+{
+public:
+  static TypeId GetTypeId (void);
+  LiIonEnergySource ();
+  virtual ~LiIonEnergySource ();
+
+  /**
+   * \return Initial energy stored in energy source, in Joules.
+   *
+   * Implements GetInitialEnergy.
+   */
+  virtual double GetInitialEnergy (void) const;
+
+  /**
+   * \param initialEnergyJ Initial energy, in Joules
+   *
+   * Implements SetInitialEnergy. Note that initial energy is assumed to be set
+   * before simulation starts and is set only once per simulation.
+   */
+  void SetInitialEnergy (double initialEnergyJ);
+
+  /**
+   * \returns Supply voltage at the energy source.
+   *
+   * Implements GetSupplyVoltage.
+   */
+  virtual double GetSupplyVoltage (void) const;
+
+  /**
+   * \param supplyVoltageV Initial Supply voltage at the energy source, in Volts.
+   *
+   * Sets the initial supply voltage of the energy source.
+   * To be called only once.
+   */
+  void SetInitialSupplyVoltage (double supplyVoltageV);
+
+  /**
+   * \return Remaining energy in energy source, in Joules
+   *
+   * Implements GetRemainingEnergy.
+   */
+  virtual double GetRemainingEnergy (void);
+
+  /**
+   * \returns Energy fraction.
+   *
+   * Implements GetEnergyFraction.
+   */
+  virtual double GetEnergyFraction (void);
+
+  /**
+   * \param energyJ Amount of energy (in Joules) to decrease from energy source.
+   *
+   * Implements DecreaseRemainingEnergy.
+   */
+  virtual void DecreaseRemainingEnergy (double energyJ);
+
+  /**
+   * \param energyJ Amount of energy (in Joules) to increase from energy source.
+   *
+   * Implements IncreaseRemainingEnergy.
+   */
+  virtual void IncreaseRemainingEnergy (double energyJ);
+
+  /**
+   * Implements UpdateEnergySource.
+   */
+  virtual void UpdateEnergySource (void);
+
+  /**
+   * \param interval Energy update interval.
+   *
+   * This function sets the interval between each energy update.
+   */
+  void SetEnergyUpdateInterval (Time interval);
+
+  /**
+   * \returns The interval between each energy update.
+   */
+  Time GetEnergyUpdateInterval (void) const;
+private:
+  void DoStart (void);
+  void DoDispose (void);
+
+  /**
+   * Handles the remaining energy going to zero event. This function notifies
+   * all the energy models aggregated to the node about the energy being
+   * depleted. Each energy model is then responsible for its own handler.
+   */
+  void HandleEnergyDrainedEvent (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:
+   *    energy to decrease = total current * supply voltage * time duration
+   * This function subtracts the calculated energy to decrease from remaining
+   * energy.
+   */
+  void CalculateRemainingEnergy (void);
+
+  /**
+   *  \param current the actual discharge current value.
+   *
+   *  Get the cell voltage in function of the discharge current.
+   *  It consider different discharge curves for different discharge currents
+   *  and the remaining energy of the cell.
+   */
+  double GetVoltage (double current) const;
+
+private:
+  double m_initialEnergyJ;                // initial energy, in Joules
+  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
+  EventId m_energyUpdateEvent;            // energy update event
+  Time m_lastUpdateTime;                  // last update time
+  Time m_energyUpdateInterval;            // energy update interval
+  double m_eFull;                         // initial voltage of the cell, in Volts
+  double m_eNom;                          // nominal voltage of the cell, in Volts
+  double m_eExp;                          // cell voltage at the end of the exponential zone, in Volts
+  double m_internalResistance;            // internal resistance of the cell, in Ohms
+  double m_qRated;                        // rated capacity of the cell, in Ah
+  double m_qNom;                          // cell capacity at the end of the nominal zone, in Ah
+  double m_qExp;                          // capacity value at the end of the exponential zone, in Ah
+  double m_typCurrent;                    // typical discharge current used to fit the curves
+  double m_minVoltTh;                     // minimum threshold voltage to consider the battery depleted
+};
+
+} // namespace ns3
+
+#endif /* LI_ION_ENERGY_SOURCE */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/energy/model/simple-device-energy-model.cc	Tue Dec 21 21:44:11 2010 -0800
@@ -0,0 +1,92 @@
+#include "ns3/simulator.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/energy-source.h"
+#include "simple-device-energy-model.h"
+
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (SimpleDeviceEnergyModel);
+
+TypeId
+SimpleDeviceEnergyModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::SimpleDeviceEnergyModel")
+    .SetParent<DeviceEnergyModel> ()
+    .AddConstructor<SimpleDeviceEnergyModel> ()
+    .AddTraceSource ("TotalEnergyConsumption",
+                     "Total energy consumption of the radio device.",
+                     MakeTraceSourceAccessor (&SimpleDeviceEnergyModel::m_totalEnergyConsumption))
+  ;
+  return tid;
+}
+
+SimpleDeviceEnergyModel::SimpleDeviceEnergyModel ()
+{
+  m_lastUpdateTime = Seconds (0.0);
+  m_actualCurrentA = 0.0;
+  m_source = 0;
+}
+
+SimpleDeviceEnergyModel::~SimpleDeviceEnergyModel ()
+{
+}
+
+void
+SimpleDeviceEnergyModel::SetEnergySource (Ptr<EnergySource> source)
+{
+  NS_ASSERT (source != NULL);
+  m_source = source;
+}
+
+void
+SimpleDeviceEnergyModel::SetNode (Ptr<Node> node)
+{
+  NS_ASSERT (node != NULL);
+  m_node = node;
+}
+
+Ptr<Node>
+SimpleDeviceEnergyModel::GetNode () const
+{
+  return m_node;
+}
+
+double
+SimpleDeviceEnergyModel::GetTotalEnergyConsumption (void) const
+{
+  return m_totalEnergyConsumption;
+}
+
+void
+SimpleDeviceEnergyModel::SetCurrentA (double current)
+{
+  Time duration = Simulator::Now () - m_lastUpdateTime;
+
+  double energyToDecrease = 0.0;
+  double supplyVoltage = m_source->GetSupplyVoltage ();
+  energyToDecrease = duration.GetSeconds () * current * supplyVoltage;
+
+  // update total energy consumption
+  m_totalEnergyConsumption += energyToDecrease;
+  // update last update time stamp
+  m_lastUpdateTime = Simulator::Now ();
+  // notify energy source
+  m_source->UpdateEnergySource ();
+  // update the current drain
+  m_actualCurrentA = current;
+}
+
+void
+SimpleDeviceEnergyModel::DoDispose (void)
+{
+  m_source = 0;
+}
+
+double
+SimpleDeviceEnergyModel::DoGetCurrentA (void) const
+{
+  return m_actualCurrentA;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/energy/model/simple-device-energy-model.h	Tue Dec 21 21:44:11 2010 -0800
@@ -0,0 +1,106 @@
+/*
+ * simple-device-energy-model.h
+ *
+ *  Created on: 09/ago/2010
+ *      Author: socket
+ */
+#ifndef SIMPLE_DEVICE_ENERGY_MODEL_H_
+#define SIMPLE_DEVICE_ENERGY_MODEL_H_
+
+#include "ns3/device-energy-model.h"
+#include "ns3/nstime.h"
+#include "ns3/traced-value.h"
+
+namespace ns3 {
+
+/**
+ *
+ * A simple device energy model where current drain can be set by the user.
+ *
+ * It is supposed to be used as a testing model for energy sources.
+ */
+class SimpleDeviceEnergyModel : public DeviceEnergyModel
+{
+public:
+  static TypeId GetTypeId (void);
+  SimpleDeviceEnergyModel ();
+  virtual ~SimpleDeviceEnergyModel ();
+
+  /**
+   * \brief Sets pointer to node.
+   *
+   * \param node Pointer to node.
+   *
+   * Implements DeviceEnergyModel::SetNode.
+   */
+  virtual void SetNode (Ptr<Node> node);
+
+  /**
+   * \brief Gets pointer to node.
+   *
+   * \returns Pointer to node.
+   *
+   * Implements DeviceEnergyModel::GetNode.
+   */
+  virtual Ptr<Node> GetNode (void) const;
+
+  /**
+   * \brief Sets pointer to EnergySouce installed on node.
+   *
+   * \param source Pointer to EnergySource installed on node.
+   *
+   * Implements DeviceEnergyModel::SetEnergySource.
+   */
+  virtual void SetEnergySource (Ptr<EnergySource> source);
+
+  /**
+   * \returns Total energy consumption of the vehicle.
+   *
+   * Implements DeviceEnergyModel::GetTotalEnergyConsumption.
+   */
+  virtual double GetTotalEnergyConsumption (void) const;
+
+  /**
+   * \param newState New state the device is in.
+   *
+   * Not implemented
+   */
+  virtual void ChangeState (int newState)
+  {
+  }
+
+  /**
+   * \brief Handles energy depletion.
+   *
+   * Not implemented
+   */
+  virtual void HandleEnergyDepletion (void)
+  {
+  }
+
+  /**
+   * \param current the current draw of device.
+   *
+   * Set the actual current draw of the device.
+   */
+  void SetCurrentA (double current);
+private:
+  void DoDispose (void);
+
+  /**
+   * \returns Current draw of device, at current state.
+   *
+   * Implements DeviceEnergyModel::GetCurrentA.
+   */
+  virtual double DoGetCurrentA (void) const;
+
+  Time m_lastUpdateTime;
+  double m_actualCurrentA;
+  Ptr<EnergySource> m_source;
+  Ptr<Node> m_node;
+  TracedValue<double> m_totalEnergyConsumption;
+};
+
+} // namespace ns3
+
+#endif /* SIMPLE_DEVICE_ENERGY_MODEL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/energy/test/li-ion-energy-source-test.cc	Tue Dec 21 21:44:11 2010 -0800
@@ -0,0 +1,98 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Andrea Sacco
+ *
+ * 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: Andrea Sacco <andrea.sacco85@gmail.com>
+ */
+
+#include "ns3/log.h"
+#include "ns3/test.h"
+#include "ns3/simple-device-energy-model.h"
+#include "ns3/li-ion-energy-source.h"
+#include "ns3/node.h"
+#include "ns3/simulator.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("LiIonEnergySourceTestSuite");
+
+class LiIonEnergyTestCase : public TestCase
+{
+public:
+  LiIonEnergyTestCase ();
+  ~LiIonEnergyTestCase ();
+
+  bool DoRun (void);
+
+  double m_simTime;
+  Ptr<Node> m_node;
+};
+
+LiIonEnergyTestCase::LiIonEnergyTestCase ()
+  : TestCase ("Li-Ion energy source test case")
+{
+}
+
+LiIonEnergyTestCase::~LiIonEnergyTestCase ()
+{
+  m_node = 0;
+}
+
+bool
+LiIonEnergyTestCase::DoRun ()
+{
+  m_node = CreateObject<Node> ();
+
+  Ptr<SimpleDeviceEnergyModel> sem = CreateObject<SimpleDeviceEnergyModel> ();
+  Ptr<LiIonEnergySource> es = CreateObject<LiIonEnergySource> ();
+
+  es->SetNode (m_node);
+  sem->SetEnergySource (es);
+  es->AppendDeviceEnergyModel (sem);
+  m_node->AggregateObject (es);
+
+  Time now = Simulator::Now ();
+
+  // discharge at 2.33 A for 1700 seconds
+  sem->SetCurrentA (2.33);
+  now += Seconds (1701);
+
+  Simulator::Stop (now);
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  NS_TEST_ASSERT_MSG_EQ_TOL (es->GetSupplyVoltage (), 3.6, 1.0e-3,
+                             "Incorrect consumed energy!");
+
+  return false;
+}
+
+class LiIonEnergySourceTestSuite : public TestSuite
+{
+public:
+  LiIonEnergySourceTestSuite ();
+};
+
+LiIonEnergySourceTestSuite::LiIonEnergySourceTestSuite ()
+  : TestSuite ("li-ion-energy-source", UNIT)
+{
+  AddTestCase (new LiIonEnergyTestCase);
+}
+
+// create an instance of the test suite
+LiIonEnergySourceTestSuite g_liIonEnergySourceTestSuite;
+
+} // namespace ns3
--- a/src/contrib/energy/wscript	Tue Dec 21 16:13:14 2010 -0800
+++ b/src/contrib/energy/wscript	Tue Dec 21 21:44:11 2010 -0800
@@ -6,9 +6,11 @@
         'model/wifi-radio-energy-model.cc',
         'model/energy-source.cc',
         'model/basic-energy-source.cc',
+        'model/li-ion-energy-source.cc',
         'model/rv-battery-model.cc',
         'model/device-energy-model.cc',
         'model/device-energy-model-container.cc',
+        'model/simple-device-energy-model.cc',
         'helper/energy-source-container.cc',
         'helper/energy-model-helper.cc',
         'helper/basic-energy-source-helper.cc',
@@ -16,6 +18,7 @@
         'helper/rv-battery-model-helper.cc',
         'test/basic-energy-model-test.cc',
         'test/rv-battery-model-test.cc',
+        'test/li-ion-energy-source-test.cc',
         ]
     headers = bld.new_task_gen('ns3header')
     headers.module = 'energy'
@@ -23,12 +26,17 @@
         'model/wifi-radio-energy-model.h',
         'model/energy-source.h',
         'model/basic-energy-source.h',
+        'model/li-ion-energy-source.h',
         'model/rv-battery-model.h',
         'model/device-energy-model.h',
         'model/device-energy-model-container.h',
+        'model/simple-device-energy-model.h',
         'helper/energy-source-container.h',
         'helper/energy-model-helper.h',
         'helper/basic-energy-source-helper.h',
         'helper/wifi-radio-energy-model-helper.h',
         'helper/rv-battery-model-helper.h',
         ]
+
+    if (bld.env['ENABLE_EXAMPLES']):
+      bld.add_subdirs('examples')
--- a/src/devices/uan/doc/uan.h	Tue Dec 21 16:13:14 2010 -0800
+++ b/src/devices/uan/doc/uan.h	Tue Dec 21 21:44:11 2010 -0800
@@ -22,11 +22,12 @@
  * \ingroup devices
  * \defgroup UAN UAN Models
  *
- * \section UanOverview UAN Module Overview
+ * \section UanOverview UAN Framework Overview
  *
- * The main goal of the UAN Model is to enable researchers to
+ * The main goal of the UAN Framework is to enable researchers to
  * model a variety of underwater network scenarios.  The UAN model
- * is broken into three main parts:  The channel, PHY,  and MAC models.
+ * is broken into four main parts:  The channel, PHY, MAC and
+ * Autonomous Underwater Vehicle (AUV) models.
  *
  *
  * \section UanPropOverview UAN Propagation Models
@@ -178,5 +179,26 @@
  *
  * c) Simple ALOHA (ns3::UanMacAloha)  Nodes transmit at will.
  *
+ * \section UanAUV  UAN AUV Model Overview
+ *
+ * Since AUVs are one of the main components of an underwater networking application, we have included
+ * two models of the most used AUVs, the Seaglider and the REMUS.
+ *
+ * An AUV model includes a mobility model that reproduces the navigation capabilities of the AUV, two energy model
+ * that reproduce the energy consumption of the AUV and the communication device.
+ *
+ * a) mobility models are ns3::RemusMobilityModel and ns3::GliderMobilityModel
+ *
+ * b) auv energy models are ns3::RemusEnergyModel and ns3::GliderEnergyModel. Those models, interacting
+ * with the associated mobility models, keep track of an AUV navigation energy consumption. The energy
+ * consumption varies accordingly to the navigation parameter such as speed (in case of REMUS) and
+ * buoyancy and vertical speed (in case of Seaglider)
+ *
+ * c) transducer energy model is ns3::AcousticModemEnergyModel, it keeps track of the energy consumed
+ * by the acoustic transducer accordingly to its state. The specific energy consumption values are the ones of
+ * the WHOI Micro Modem.
+ *
+ * For a complete description of AUV mobility models, energy models, energy sources and examples please refer to
+ * the <a href="http://www.nsnam.org/wiki/index.php/GSOC2010UANFramework">wiki page</a>
  *
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/uan/helper/acoustic-modem-energy-model-helper.cc	Tue Dec 21 21:44:11 2010 -0800
@@ -0,0 +1,93 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Andrea Sacco
+ *
+ * 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: Author: Andrea Sacco <andrea.sacco85@gmail.com>
+ */
+
+#include "acoustic-modem-energy-model-helper.h"
+#include "ns3/basic-energy-source-helper.h"
+#include "ns3/uan-phy.h"
+#include "ns3/uan-net-device.h"
+#include "ns3/config.h"
+#include "ns3/names.h"
+
+namespace ns3 {
+
+AcousticModemEnergyModelHelper::AcousticModemEnergyModelHelper ()
+{
+  m_modemEnergy.SetTypeId ("ns3::AcousticModemEnergyModel");
+  m_depletionCallback.Nullify ();
+}
+
+AcousticModemEnergyModelHelper::~AcousticModemEnergyModelHelper ()
+{
+}
+
+void
+AcousticModemEnergyModelHelper::Set (std::string name, const AttributeValue &v)
+{
+  m_modemEnergy.Set (name, v);
+}
+
+void
+AcousticModemEnergyModelHelper::SetDepletionCallback (
+  AcousticModemEnergyModel::AcousticModemEnergyDepletionCallback callback)
+{
+  m_depletionCallback = callback;
+}
+
+/*
+ * Private function starts here.
+ */
+
+Ptr<DeviceEnergyModel>
+AcousticModemEnergyModelHelper::DoInstall (Ptr<NetDevice> device,
+                                           Ptr<EnergySource> source) const
+{
+  NS_ASSERT (device != NULL);
+  NS_ASSERT (source != NULL);
+  // check if device is UanNetDevice
+  std::string deviceName = device->GetInstanceTypeId ().GetName ();
+  if (deviceName.compare ("ns3::UanNetDevice") != 0)
+    {
+      NS_FATAL_ERROR ("NetDevice type is not UanNetDevice!");
+    }
+  Ptr<Node> node = device->GetNode ();
+  Ptr<AcousticModemEnergyModel> model = m_modemEnergy.Create<AcousticModemEnergyModel> ();
+  NS_ASSERT (model != NULL);
+  // set node pointer
+  model->SetNode (node);
+  // set energy source pointer
+  model->SetEnergySource (source);
+  // get phy layer
+  Ptr<UanNetDevice> uanDevice = DynamicCast<UanNetDevice> (device);
+  Ptr<UanPhy> uanPhy = uanDevice->GetPhy ();
+  // set energy depletion callback
+  model->SetEnergyDepletionCallback (m_depletionCallback);
+  // add model to device model list in energy source
+  source->AppendDeviceEnergyModel (model);
+  // set node pointer
+  source->SetNode (node);
+  // create and install energy model callback
+  DeviceEnergyModel::ChangeStateCallback cb;
+  cb = MakeCallback (&DeviceEnergyModel::ChangeState, model);
+  uanPhy->SetEnergyModelCallback (cb);
+
+  return model;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/uan/helper/acoustic-modem-energy-model-helper.h	Tue Dec 21 21:44:11 2010 -0800
@@ -0,0 +1,81 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+* Copyright (c) 2010 Andrea Sacco
+*
+* 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: Author: Andrea Sacco <andrea.sacco85@gmail.com>
+*/
+
+#ifndef ACOUSTIC_MODEM_ENERGY_MODEL_HELPER_H
+#define ACOUSTIC_MODEM_ENERGY_MODEL_HELPER_H
+
+#include "ns3/energy-model-helper.h"
+#include "ns3/acoustic-modem-energy-model.h"
+
+namespace ns3 {
+
+/**
+ * \brief Assign AcousticModemEnergyModel to uan devices.
+ *
+ * This installer installs AcousticModemEnergyModel for only UanNetDevice objects.
+ */
+class AcousticModemEnergyModelHelper : public DeviceEnergyModelHelper
+{
+public:
+  /**
+   * Construct a helper which is used to add a radio energy model to a node
+   */
+  AcousticModemEnergyModelHelper ();
+
+  /**
+   * Destroy an AcousticModemEnergy Helper
+   */
+  ~AcousticModemEnergyModelHelper ();
+
+  /**
+   * \param name the name of the attribute to set
+   * \param v the value of the attribute
+   *
+   * Sets an attribute of the underlying energy model object.
+   */
+  void Set (std::string name, const AttributeValue &v);
+
+  /**
+   * \param callback Callback function for energy depletion handling.
+   *
+   * Sets the callback to be invoked when energy is depleted.
+   */
+  void SetDepletionCallback (
+    AcousticModemEnergyModel::AcousticModemEnergyDepletionCallback callback);
+
+
+private:
+  /**
+   * \param device Pointer to the NetDevice to install DeviceEnergyModel.
+   *
+   * Implements DeviceEnergyModel::Install.
+   */
+  virtual Ptr<DeviceEnergyModel> DoInstall (Ptr<NetDevice> device,
+                                            Ptr<EnergySource> source) const;
+
+private:
+  ObjectFactory m_modemEnergy;
+  AcousticModemEnergyModel::AcousticModemEnergyDepletionCallback m_depletionCallback;
+
+};
+
+} // namespace ns3
+
+#endif /* ACOUSTIC_MODEM_ENERGY_MODEL_HELPER_H */
--- a/src/devices/uan/helper/uan-helper.cc	Tue Dec 21 16:13:14 2010 -0800
+++ b/src/devices/uan/helper/uan-helper.cc	Tue Dec 21 21:44:11 2010 -0800
@@ -40,18 +40,17 @@
 #include <sstream>
 #include <string>
 
-NS_LOG_COMPONENT_DEFINE("UanHelper");
-namespace ns3
-{
+NS_LOG_COMPONENT_DEFINE ("UanHelper");
+namespace ns3 {
 
 static void AsciiPhyTxEvent (std::ostream *os, std::string context,
-    Ptr<const Packet> packet, double txPowerDb, UanTxMode mode)
+                             Ptr<const Packet> packet, double txPowerDb, UanTxMode mode)
 {
   *os << "+ " << Simulator::Now ().GetSeconds () << " " << context << " " << *packet << std::endl;
 }
 
 static void AsciiPhyRxOkEvent (std::ostream *os, std::string context,
-    Ptr<const Packet> packet, double snr, UanTxMode mode)
+                               Ptr<const Packet> packet, double snr, UanTxMode mode)
 {
   *os << "r " << Simulator::Now ().GetSeconds () << " " << context << " " << *packet << std::endl;
 }
@@ -190,9 +189,8 @@
 NetDeviceContainer
 UanHelper::Install (NodeContainer c) const
 {
-
   Ptr<UanChannel> channel = CreateObject<UanChannel> ();
-  Ptr<UanNoiseModelDefault> noise =CreateObject<UanNoiseModelDefault> ();
+  Ptr<UanNoiseModelDefault> noise = CreateObject<UanNoiseModelDefault> ();
   channel->SetPropagationModel (CreateObject<UanPropModelIdeal> ());
   channel->SetNoiseModel (noise);
 
@@ -206,23 +204,33 @@
   for (NodeContainer::Iterator i = c.Begin (); i != c.End (); i++)
     {
       Ptr<Node> node = *i;
-      Ptr<UanNetDevice> device = CreateObject<UanNetDevice> ();
 
-      Ptr<UanMac> mac = m_mac.Create<UanMac> ();
-      Ptr<UanPhy> phy = m_phy.Create<UanPhy> ();
-      Ptr<UanTransducer> trans = m_transducer.Create<UanTransducer> ();
+      Ptr<UanNetDevice> device = Install (node, channel);
 
-      mac->SetAddress (UanAddress::Allocate ());
-      device->SetMac (mac);
-      device->SetPhy (phy);
-      device->SetTransducer(trans);
-      device->SetChannel (channel);
-
-      node->AddDevice (device);
       devices.Add (device);
-      NS_LOG_DEBUG ("node="<<node<<", mob="<<node->GetObject<MobilityModel> ());
+      NS_LOG_DEBUG ("node=" << node << ", mob=" << node->GetObject<MobilityModel> ());
     }
   return devices;
 }
 
-} //end namespace ns3
+Ptr<UanNetDevice>
+UanHelper::Install (Ptr<Node> node, Ptr<UanChannel> channel) const
+{
+  Ptr<UanNetDevice> device = CreateObject<UanNetDevice> ();
+
+  Ptr<UanMac> mac = m_mac.Create<UanMac> ();
+  Ptr<UanPhy> phy = m_phy.Create<UanPhy> ();
+  Ptr<UanTransducer> trans = m_transducer.Create<UanTransducer> ();
+
+  mac->SetAddress (UanAddress::Allocate ());
+  device->SetMac (mac);
+  device->SetPhy (phy);
+  device->SetTransducer (trans);
+  device->SetChannel (channel);
+
+  node->AddDevice (device);
+
+  return device;
+}
+
+} // end namespace ns3
--- a/src/devices/uan/helper/uan-helper.h	Tue Dec 21 16:13:14 2010 -0800
+++ b/src/devices/uan/helper/uan-helper.h	Tue Dec 21 21:44:11 2010 -0800
@@ -27,17 +27,17 @@
 #include "ns3/object-factory.h"
 #include "ns3/node-container.h"
 #include "ns3/net-device-container.h"
+#include "ns3/uan-net-device.h"
 
-namespace ns3
-{
+namespace ns3 {
 
 class UanChannel;
 
 class UanHelper
 {
 public:
-  UanHelper();
-  virtual ~UanHelper();
+  UanHelper ();
+  virtual ~UanHelper ();
 
   /**
    * \param type the type of ns3::UanMac to create.
@@ -128,14 +128,14 @@
    * in the requested transducer.
    */
   void SetTransducer (std::string type,
-               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 ());
+                      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 ());
   /**
    * \param os output stream
    * \param nodeid the id of the node to generate ascii output for.
@@ -205,7 +205,21 @@
    */
   NetDeviceContainer Install (NodeContainer c, Ptr<UanChannel> channel) const;
 
+  /**
+   * \param node a node where to install the uan components
+   *
+   * Create a default uan stack with:
+   * - default channel, ideal propagation and default noise model
+   * - default physical layer, with UanPhyGen
+   * - default transducer, half duplex acoustic modem with UanTransducerHd
+   * - default MAC layer, with UanMacAloha
+   *
+   * Channel, physical layer, transducer and mac layer are added to the
+   * UanNetDevice and then added to the node.
+   */
+  Ptr<UanNetDevice> Install (Ptr<Node> node, Ptr<UanChannel> channel) const;
 private:
+  ObjectFactory m_device;
   ObjectFactory m_mac;
   ObjectFactory m_phy;
   ObjectFactory m_transducer;
@@ -213,6 +227,6 @@
 };
 
 
-} //end namespace ns3
+} // end namespace ns3
 
 #endif /* UANHELPER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/uan/model/acoustic-modem-energy-model.cc	Tue Dec 21 21:44:11 2010 -0800
@@ -0,0 +1,335 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Andrea Sacco
+ *
+ * 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: Andrea Sacco <andrea.sacco85@gmail.com>
+ */
+
+#include "ns3/log.h"
+#include "ns3/double.h"
+#include "ns3/simulator.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/energy-source.h"
+#include "ns3/uan-phy.h"
+#include "ns3/uan-net-device.h"
+#include "acoustic-modem-energy-model.h"
+
+NS_LOG_COMPONENT_DEFINE ("AcousticModemEnergyModel");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (AcousticModemEnergyModel);
+
+TypeId
+AcousticModemEnergyModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::AcousticModemEnergyModel")
+    .SetParent<DeviceEnergyModel> ()
+    .AddConstructor<AcousticModemEnergyModel> ()
+    .AddAttribute ("TxPowerW",
+                   "The modem Tx power in Watts",
+                   DoubleValue (50),
+                   MakeDoubleAccessor (&AcousticModemEnergyModel::SetTxPowerW,
+                                       &AcousticModemEnergyModel::GetTxPowerW),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RxPowerW",
+                   "The modem Rx power in Watts",
+                   DoubleValue (0.158),
+                   MakeDoubleAccessor (&AcousticModemEnergyModel::SetRxPowerW,
+                                       &AcousticModemEnergyModel::GetRxPowerW),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("IdlePowerW",
+                   "The modem Idle power in Watts",
+                   DoubleValue (0.158),
+                   MakeDoubleAccessor (&AcousticModemEnergyModel::SetIdlePowerW,
+                                       &AcousticModemEnergyModel::GetIdlePowerW),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("SleepPowerW",
+                   "The modem Sleep power in Watts",
+                   DoubleValue (0.0058),
+                   MakeDoubleAccessor (&AcousticModemEnergyModel::SetSleepPowerW,
+                                       &AcousticModemEnergyModel::GetSleepPowerW),
+                   MakeDoubleChecker<double> ())
+    .AddTraceSource ("TotalEnergyConsumption",
+                     "Total energy consumption of the modem device.",
+                     MakeTraceSourceAccessor (&AcousticModemEnergyModel::m_totalEnergyConsumption))
+  ;
+  return tid;
+}
+
+AcousticModemEnergyModel::AcousticModemEnergyModel ()
+{
+  NS_LOG_FUNCTION (this);
+  m_currentState = UanPhy::IDLE;  // initially IDLE
+  m_lastUpdateTime = Seconds (0.0);
+  m_energyDepletionCallback.Nullify ();
+  m_node = 0;
+  m_source = 0;
+}
+
+AcousticModemEnergyModel::~AcousticModemEnergyModel ()
+{
+}
+
+void
+AcousticModemEnergyModel::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION (this << node);
+  NS_ASSERT (node != 0);
+  m_node = node;
+}
+
+Ptr<Node>
+AcousticModemEnergyModel::GetNode (void) const
+{
+  return m_node;
+}
+
+void
+AcousticModemEnergyModel::SetEnergySource (Ptr<EnergySource> source)
+{
+  NS_LOG_FUNCTION (this << source);
+  NS_ASSERT (source != 0);
+  m_source = source;
+}
+
+double
+AcousticModemEnergyModel::GetTotalEnergyConsumption (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_totalEnergyConsumption;
+}
+
+double
+AcousticModemEnergyModel::GetTxPowerW (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_txPowerW;
+}
+
+void
+AcousticModemEnergyModel::SetTxPowerW (double txPowerW)
+{
+  NS_LOG_FUNCTION (this << txPowerW);
+  m_txPowerW = txPowerW;
+}
+
+double
+AcousticModemEnergyModel::GetRxPowerW (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_rxPowerW;
+}
+
+void
+AcousticModemEnergyModel::SetRxPowerW (double rxPowerW)
+{
+  NS_LOG_FUNCTION (this << rxPowerW);
+  m_rxPowerW = rxPowerW;
+}
+
+double
+AcousticModemEnergyModel::GetIdlePowerW (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_idlePowerW;
+}
+
+void
+AcousticModemEnergyModel::SetIdlePowerW (double idlePowerW)
+{
+  NS_LOG_FUNCTION (this << idlePowerW);
+  m_idlePowerW = idlePowerW;
+}
+
+double
+AcousticModemEnergyModel::GetSleepPowerW (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_sleepPowerW;
+}
+
+void
+AcousticModemEnergyModel::SetSleepPowerW (double sleepPowerW)
+{
+  NS_LOG_FUNCTION (this << sleepPowerW);
+  m_sleepPowerW = sleepPowerW;
+}
+
+int
+AcousticModemEnergyModel::GetCurrentState (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_currentState;
+}
+
+void
+AcousticModemEnergyModel::SetEnergyDepletionCallback (
+  AcousticModemEnergyDepletionCallback callback)
+{
+  NS_LOG_FUNCTION (this);
+  if (callback.IsNull ())
+    {
+      NS_LOG_DEBUG ("AcousticModemEnergyModel:Setting NULL energy depletion callback!");
+    }
+  m_energyDepletionCallback = callback;
+}
+
+void
+AcousticModemEnergyModel::ChangeState (int newState)
+{
+  NS_LOG_FUNCTION (this << newState);
+  // NS_ASSERT (IsStateTransitionValid ((MicroModemState) newState));
+
+  Time duration = Simulator::Now () - m_lastUpdateTime;
+  NS_ASSERT (duration.GetNanoSeconds () >= 0); // check if duration is valid
+
+  // energy to decrease = current * voltage * time
+  double energyToDecrease = 0.0;
+  double supplyVoltage = m_source->GetSupplyVoltage ();
+  switch (m_currentState)
+    {
+    case UanPhy::TX:
+      energyToDecrease = duration.GetSeconds () * m_txPowerW * supplyVoltage;
+      break;
+    case UanPhy::RX:
+      energyToDecrease = duration.GetSeconds () * m_rxPowerW * supplyVoltage;
+      break;
+    case UanPhy::IDLE:
+      energyToDecrease = duration.GetSeconds () * m_idlePowerW * supplyVoltage;
+      break;
+    case UanPhy::SLEEP:
+      energyToDecrease = duration.GetSeconds () * m_sleepPowerW * supplyVoltage;
+      break;
+    default:
+      NS_FATAL_ERROR ("AcousticModemEnergyModel:Undefined radio state!");
+    }
+
+  // update total energy consumption
+  m_totalEnergyConsumption += energyToDecrease;
+
+  // update last update time stamp
+  m_lastUpdateTime = Simulator::Now ();
+
+  // notify energy source
+  m_source->UpdateEnergySource ();
+
+  // update current state & last update time stamp
+  SetMicroModemState (newState);
+
+  // some debug message
+  NS_LOG_DEBUG ("AcousticModemEnergyModel:Total energy consumption at node #" <<
+                m_node->GetId () << " is " << m_totalEnergyConsumption << "J");
+}
+
+void
+AcousticModemEnergyModel::HandleEnergyDepletion (void)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("AcousticModemEnergyModel:Energy is depleted at node #" <<
+                m_node->GetId ());
+  // invoke energy depletion callback, if set.
+  if (!m_energyDepletionCallback.IsNull ())
+    {
+      m_energyDepletionCallback ();
+    }
+  // invoke the phy energy depletion handler
+  Ptr<UanNetDevice> dev = m_node->GetDevice (0)->GetObject<UanNetDevice> ();
+  dev->GetPhy ()->EnergyDepletionHandler ();
+}
+
+/*
+ * Private functions start here.
+ */
+
+void
+AcousticModemEnergyModel::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_node = 0;
+  m_source = 0;
+  m_energyDepletionCallback.Nullify ();
+}
+
+double
+AcousticModemEnergyModel::DoGetCurrentA (void) const
+{
+  NS_LOG_FUNCTION (this);
+
+  double supplyVoltage = m_source->GetSupplyVoltage ();
+  NS_ASSERT (supplyVoltage != 0.0);
+  double stateCurrent = 0.0;
+  switch (m_currentState)
+    {
+    case UanPhy::TX:
+      stateCurrent = m_txPowerW / supplyVoltage;
+      break;
+    case UanPhy::RX:
+      stateCurrent = m_rxPowerW / supplyVoltage;
+      break;
+    case UanPhy::IDLE:
+      stateCurrent = m_idlePowerW / supplyVoltage;
+      break;
+    case UanPhy::SLEEP:
+      stateCurrent = m_sleepPowerW / supplyVoltage;
+      break;
+    default:
+      NS_FATAL_ERROR ("AcousticModemEnergyModel:Undefined radio state!");
+    }
+
+  return stateCurrent;
+}
+
+bool
+AcousticModemEnergyModel::IsStateTransitionValid (const int destState)
+{
+  NS_LOG_FUNCTION (this << destState);
+  return true;
+}
+
+void
+AcousticModemEnergyModel::SetMicroModemState (const int state)
+{
+  NS_LOG_FUNCTION (this);
+  if (IsStateTransitionValid (state))
+    {
+      m_currentState = state;
+      std::string stateName;
+      switch (state)
+        {
+        case UanPhy::TX:
+          stateName = "TX";
+          break;
+        case UanPhy::RX:
+          stateName = "RX";
+          break;
+        case UanPhy::IDLE:
+          stateName = "IDLE";
+          break;
+        case UanPhy::SLEEP:
+          stateName = "SLEEP";
+          break;
+        }
+      NS_LOG_DEBUG ("AcousticModemEnergyModel:Switching to state: " << stateName <<
+                    " at time = " << Simulator::Now ());
+    }
+  else
+    {
+      NS_FATAL_ERROR ("AcousticModemEnergyModel:Invalid state transition!");
+    }
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/uan/model/acoustic-modem-energy-model.h	Tue Dec 21 21:44:11 2010 -0800
@@ -0,0 +1,229 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Andrea Sacco
+ *
+ * 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: Andrea Sacco <andrea.sacco85@gmail.com>
+ */
+
+#ifndef ACOUSTIC_MODEM_ENERGY_MODEL_H
+#define ACOUSTIC_MODEM_ENERGY_MODEL_H
+
+#include "ns3/device-energy-model.h"
+#include "ns3/nstime.h"
+#include "ns3/event-id.h"
+#include "ns3/traced-value.h"
+
+namespace ns3 {
+
+/**
+ * \brief WHOI micro-modem energy model
+ *
+ * Basing on the Device Energy Model interface, has been implemented a specific
+ * energy model for the WHOI micro modem. The class follows pretty closely the
+ * RadioEnergyModel class as the transducer behaviour is pretty close to the one
+ * of a wifi radio, with identical states (rx, tx, idle, sleep).
+ *
+ * The power consumption values implemented into the model are as follows [1]:
+ *
+ * Modem State   Power Consumption
+ * TX            50 W
+ * RX            158 mW
+ * Idle          158 mW
+ * Sleep         5.8 mW
+ *
+ * References:
+ * [1] Freitag et al., The whoi micro-modem: an acoustic communications and navigation system for multiple platforms,
+ *     in In Proc. IEEE OCEANS05 Conf, 2005.
+ *     URL: http://ieeexplore.ieee.org/iel5/10918/34367/01639901.pdf
+ */
+class AcousticModemEnergyModel : public DeviceEnergyModel
+{
+public:
+  /**
+   * Callback type for energy depletion handling.
+   */
+  typedef Callback<void> AcousticModemEnergyDepletionCallback;
+
+public:
+  static TypeId GetTypeId (void);
+  AcousticModemEnergyModel ();
+  virtual ~AcousticModemEnergyModel ();
+
+  /**
+   * \brief Sets pointer to node.
+   *
+   * \param node Pointer to node.
+   *
+   * Implements DeviceEnergyModel::SetNode.
+   */
+  virtual void SetNode (Ptr<Node> node);
+
+  /**
+   * \brief Gets pointer to node.
+   *
+   * \return Pointer to node.
+   *
+   * Implements DeviceEnergyModel::GetNode.
+   */
+  virtual Ptr<Node> GetNode (void) const;
+
+  /**
+   * \brief Sets pointer to EnergySouce installed on node.
+   *
+   * \param source Pointer to EnergySource installed on node.
+   *
+   * Implements DeviceEnergyModel::SetEnergySource.
+   */
+  virtual void SetEnergySource (Ptr<EnergySource> source);
+
+  /**
+   * \return Total energy consumption of the modem
+   *
+   * Implements DeviceEnergyModel::GetTotalEnergyConsumption.
+   */
+  virtual double GetTotalEnergyConsumption (void) const;
+
+  /**
+   *
+   * \return The transmission power of the modem in Watts
+   */
+  double GetTxPowerW (void) const;
+
+  /**
+   * Set the transmission power of the modem
+   *
+   * \param txPowerW Transmission power of the modem in watts
+   */
+  void SetTxPowerW (double txPowerW);
+
+  /**
+   *
+   * \return The receiving power of the modem in Watts
+   */
+  double GetRxPowerW (void) const;
+
+  /**
+   * Set the receiving power of the modem
+   *
+   * \param rxPowerW Receiving power of the modem in watts
+   */
+  void SetRxPowerW (double rxPowerW);
+
+  /**
+   *
+   * \return The idle power of the modem in Watts
+   */
+  double GetIdlePowerW (void) const;
+
+  /**
+   * Set the idle power of the modem
+   *
+   * \param idlePowerW Idle power of the modem in watts
+   */
+  void SetIdlePowerW (double idlePowerW);
+
+  /**
+   *
+   * \return The sleep power of the modem in Watts
+   */
+  double GetSleepPowerW (void) const;
+
+  /**
+   * Set the sleep power of the modem
+   *
+   * \param sleepPowerW Sleep power of the modem in watts
+   */
+  void SetSleepPowerW (double sleepPowerW);
+
+  /**
+   * \return Current state.
+   */
+  int GetCurrentState (void) const;
+
+  /**
+   * \param callback Callback function.
+   *
+   * Sets callback for energy depletion handling.
+   */
+  void SetEnergyDepletionCallback (AcousticModemEnergyDepletionCallback callback);
+
+  /**
+   * \brief Changes state of the AcousticModemEnergyModel.
+   *
+   * \param newState New state the modem is in.
+   *
+   * Implements DeviceEnergyModel::ChangeState.
+   */
+  virtual void ChangeState (int newState);
+
+  /**
+   * \brief Handles energy depletion.
+   *
+   * Implements DeviceEnergyModel::HandleEnergyDepletion
+   */
+  virtual void HandleEnergyDepletion (void);
+
+
+private:
+  void DoDispose (void);
+
+  /**
+   * \returns Current draw of device, at current state.
+   *
+   * Implements DeviceEnergyModel::GetCurrentA.
+   */
+  virtual double DoGetCurrentA (void) const;
+
+  /**
+   * \param destState Modem state to switch to.
+   * \return True if the transition is allowed.
+   *
+   * This function checks if a given modem state transition is allowed.
+   */
+  bool IsStateTransitionValid (const int destState);
+
+  /**
+   * \param currentState New state the modem is currently in.
+   *
+   * Sets current state. This function is private so that only the energy model
+   * can change its own state.
+   */
+  void SetMicroModemState (const int state);
+
+private:
+  Ptr<Node> m_node;
+  Ptr<EnergySource> m_source;
+
+  // Member variables for power consumption in different modem states.
+  double m_txPowerW;
+  double m_rxPowerW;
+  double m_idlePowerW;
+  double m_sleepPowerW;
+
+  // This variable keeps track of the total energy consumed by this model.
+  TracedValue<double> m_totalEnergyConsumption;
+
+  // State variables.
+  int m_currentState;  // current state the modem is in
+  Time m_lastUpdateTime;          // time stamp of previous energy update
+
+  // energy depletion callback
+  AcousticModemEnergyDepletionCallback m_energyDepletionCallback;
+};
+
+} // namespace ns3
+
+#endif /* ACOUSTIC_MODEM_ENERGY_MODEL_H */
--- a/src/devices/uan/model/uan-phy-dual.cc	Tue Dec 21 16:13:14 2010 -0800
+++ b/src/devices/uan/model/uan-phy-dual.cc	Tue Dec 21 21:44:11 2010 -0800
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Author: Leonard Tracy <lentracy@gmail.com>
+ *         Andrea Sacco <andrea.sacco85@gmail.com>
  */
 
 #include "uan-phy.h"
@@ -234,6 +235,18 @@
 }
 
 void
+UanPhyDual::SetEnergyModelCallback (DeviceEnergyModel::ChangeStateCallback callback)
+{
+  NS_LOG_DEBUG ("Not Implemented");
+}
+
+void
+UanPhyDual::EnergyDepletionHandler ()
+{
+  NS_LOG_DEBUG ("Not Implemented");
+}
+
+void
 UanPhyDual::SendPacket (Ptr<Packet> pkt, uint32_t modeNum)
 {
   if (modeNum <= m_phy1->GetNModes () - 1)
@@ -443,7 +456,11 @@
 {
   return m_phy2->IsStateTx ();
 }
-
+bool
+UanPhyDual::IsStateSleep (void)
+{
+  return m_phy1->IsStateSleep () && m_phy2->IsStateSleep ();
+}
 bool
 UanPhyDual::IsStateIdle (void)
 {
@@ -452,7 +469,7 @@
 bool
 UanPhyDual::IsStateBusy (void)
 {
-  return !IsStateIdle ();
+  return !IsStateIdle () || !IsStateSleep ();
 }
 bool
 UanPhyDual::IsStateRx (void)
--- a/src/devices/uan/model/uan-phy-dual.h	Tue Dec 21 16:13:14 2010 -0800
+++ b/src/devices/uan/model/uan-phy-dual.h	Tue Dec 21 21:44:11 2010 -0800
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Author: Leonard Tracy <lentracy@gmail.com>
+ *         Andrea Sacco <andrea.sacco85@gmail.com>
  */
 
 #ifndef UANPHYDUAL_H
@@ -76,6 +77,8 @@
 
   static TypeId GetTypeId ();
 
+  virtual void SetEnergyModelCallback (DeviceEnergyModel::ChangeStateCallback callback);
+  virtual void EnergyDepletionHandler (void);
   virtual void SendPacket (Ptr<Packet> pkt, uint32_t modeNum);
 
   /**
@@ -98,6 +101,7 @@
   virtual double GetTxPowerDb (void);
   virtual double GetRxThresholdDb (void);
   virtual double GetCcaThresholdDb (void);
+  virtual bool IsStateSleep (void);
   virtual bool IsStateIdle (void);
   virtual bool IsStateBusy (void);
   virtual bool IsStateRx (void);
--- a/src/devices/uan/model/uan-phy-gen.cc	Tue Dec 21 16:13:14 2010 -0800
+++ b/src/devices/uan/model/uan-phy-gen.cc	Tue Dec 21 21:44:11 2010 -0800
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Author: Leonard Tracy <lentracy@gmail.com>
+ *         Andrea Sacco <andrea.sacco85@gmail.com>
  */
 
 #include "uan-phy-gen.h"
@@ -32,6 +33,8 @@
 #include "ns3/node.h"
 #include "ns3/uinteger.h"
 #include "ns3/random-variable.h"
+#include "ns3/energy-source-container.h"
+#include "ns3/acoustic-modem-energy-model.h"
 
 
 NS_LOG_COMPONENT_DEFINE ("UanPhyGen");
@@ -353,9 +356,10 @@
     m_rxThreshDb (0),
     m_ccaThreshDb (0),
     m_pktRx (0),
-    m_cleared (false)
+    m_cleared (false),
+    m_disabled (false)
 {
-
+  m_energyCallback.Nullify ();
 }
 
 UanPhyGen::~UanPhyGen ()
@@ -409,6 +413,7 @@
 UanPhyGen::DoDispose ()
 {
   Clear ();
+  m_energyCallback.Nullify ();
   UanPhy::DoDispose ();
 }
 
@@ -477,9 +482,43 @@
 }
 
 void
+UanPhyGen::SetEnergyModelCallback (DeviceEnergyModel::ChangeStateCallback cb)
+{
+  NS_LOG_FUNCTION (this);
+  m_energyCallback = cb;
+}
+
+void
+UanPhyGen::UpdatePowerConsumption (const State state)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (!m_energyCallback.IsNull ())
+    {
+      m_energyCallback (state);
+    }
+}
+
+void
+UanPhyGen::EnergyDepletionHandler ()
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("Energy depleted at node " << m_device->GetNode ()->GetId () <<
+                ", stopping rx/tx activities");
+
+  m_disabled = true;
+}
+
+void
 UanPhyGen::SendPacket (Ptr<Packet> pkt, uint32_t modeNum)
 {
   NS_LOG_DEBUG ("PHY " << m_mac->GetAddress () << ": Transmitting packet");
+  if (m_disabled)
+    {
+      NS_LOG_DEBUG ("Energy depleted, node cannot transmit any packet. Dropping.");
+      return;
+    }
+
   if (m_state == TX)
     {
       NS_LOG_DEBUG ("PHY requested to TX while already Transmitting.  Dropping packet.");
@@ -496,6 +535,7 @@
 
   m_transducer->Transmit (Ptr<UanPhy> (this), pkt, m_txPwrDb, txMode);
   m_state = TX;
+  UpdatePowerConsumption (TX);
   double txdelay = pkt->GetSize () * 8.0 / txMode.GetDataRateBps ();
   Simulator::Schedule (Seconds (txdelay), &UanPhyGen::TxEndEvent, this);
   NS_LOG_DEBUG ("PHY " << m_mac->GetAddress () << " notifying listeners");
@@ -516,6 +556,7 @@
     {
       m_state = IDLE;
     }
+  UpdatePowerConsumption (IDLE);
 }
 
 void
@@ -528,6 +569,12 @@
 void
 UanPhyGen::StartRxPacket (Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode, UanPdp pdp)
 {
+  if (m_disabled)
+    {
+      NS_LOG_DEBUG ("Energy depleted, node cannot receive any packet. Dropping.");
+      return;
+    }
+
   switch (m_state)
     {
     case TX:
@@ -566,6 +613,7 @@
         if (newsinr > m_rxThreshDb)
           {
             m_state = RX;
+            UpdatePowerConsumption (RX);
             m_rxRecvPwrDb = rxPowerDb;
             m_minRxSinrDb = newsinr;
             m_pktRx = pkt;
@@ -579,6 +627,9 @@
 
       }
       break;
+    case SLEEP:
+      NS_FATAL_ERROR ("SLEEP state handling not yet implemented!");
+      break;
     }
 
   if (m_state == IDLE && GetInterferenceDb ( (Ptr<Packet>) 0) > m_ccaThreshDb)
@@ -605,6 +656,7 @@
   else
     {
       m_state = IDLE;
+      UpdatePowerConsumption (IDLE);
     }
 
   UniformVariable pg;
@@ -643,8 +695,11 @@
 {
   m_recErrCb = cb;
 }
-
-
+bool
+UanPhyGen::IsStateSleep (void)
+{
+  return m_state == SLEEP;
+}
 bool
 UanPhyGen::IsStateIdle (void)
 {
@@ -653,7 +708,7 @@
 bool
 UanPhyGen::IsStateBusy (void)
 {
-  return m_state != IDLE;
+  return !IsStateIdle () || !IsStateSleep ();
 }
 bool
 UanPhyGen::IsStateRx (void)
--- a/src/devices/uan/model/uan-phy-gen.h	Tue Dec 21 16:13:14 2010 -0800
+++ b/src/devices/uan/model/uan-phy-gen.h	Tue Dec 21 21:44:11 2010 -0800
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Author: Leonard Tracy <lentracy@gmail.com>
+ *         Andrea Sacco <andrea.sacco85@gmail.com>
  */
 
 #ifndef UANPHYGEN_H
@@ -25,6 +26,7 @@
 #include "uan-phy.h"
 #include "ns3/traced-callback.h"
 #include "ns3/nstime.h"
+#include "ns3/device-energy-model.h"
 #include <list>
 
 namespace ns3 {
@@ -63,13 +65,13 @@
   static TypeId GetTypeId (void);
 
   /**
-   * 
-   * This implementation uses calculations 
-   * for binary FSK modulation coded by a rate 1/2 convolutional code 
-   * with constraint length = 9 and a viterbi decoder and finally a CRC capable 
+   *
+   * This implementation uses calculations
+   * for binary FSK modulation coded by a rate 1/2 convolutional code
+   * with constraint length = 9 and a viterbi decoder and finally a CRC capable
    * of correcting one bit error.  These equations can be found in
    * the book, Digital Communications, by Proakis (Any version I think)
-   * 
+   *
    * \param pkt Packet which is under consideration
    * \param sinrDb SINR at receiver
    * \param mode TX mode used to transmit packet
@@ -94,10 +96,10 @@
   UanPhyCalcSinrDefault ();
   virtual ~UanPhyCalcSinrDefault ();
   static TypeId GetTypeId (void);
-  /** 
+  /**
    * This implementation simply adds all arriving signal power
    * and assumes it acts identically to additional noise.
-   * 
+   *
    * \param pkt Packet which is under consideration
    * \param arrTime Arrival time of packet pkt
    * \param rxPowerDb Received signal power at receiver
@@ -166,11 +168,14 @@
   static UanModesList GetDefaultModes (void);
 
   static TypeId GetTypeId (void);
+  virtual void SetEnergyModelCallback (DeviceEnergyModel::ChangeStateCallback cb);
+  virtual void EnergyDepletionHandler (void);
   virtual void SendPacket (Ptr<Packet> pkt, uint32_t modeNum);
   virtual void RegisterListener (UanPhyListener *listener);
   virtual void StartRxPacket (Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode, UanPdp pdp);
   virtual void SetReceiveOkCallback (RxOkCallback cb);
   virtual void SetReceiveErrorCallback (RxErrCallback cb);
+  virtual bool IsStateSleep (void);
   virtual bool IsStateIdle (void);
   virtual bool IsStateBusy (void);
   virtual bool IsStateRx (void);
@@ -219,7 +224,6 @@
   double m_rxThreshDb;
   double m_ccaThreshDb;
 
-
   Ptr<Packet> m_pktRx;
   double m_minRxSinrDb;
   double m_rxRecvPwrDb;
@@ -228,7 +232,9 @@
   UanTxMode m_pktRxMode;
 
   bool m_cleared;
+  bool m_disabled;
 
+  DeviceEnergyModel::ChangeStateCallback m_energyCallback;
   TracedCallback<Ptr<const Packet>, double, UanTxMode > m_rxOkLogger;
   TracedCallback<Ptr<const Packet>, double, UanTxMode > m_rxErrLogger;
   TracedCallback<Ptr<const Packet>, double, UanTxMode > m_txLogger;
@@ -240,6 +246,7 @@
   double KpToDb (double kp);
   void RxEndEvent (Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode);
   void TxEndEvent ();
+  void UpdatePowerConsumption (const State state);
 
   void NotifyListenersRxStart (void);
   void NotifyListenersRxGood (void);
--- a/src/devices/uan/model/uan-phy.h	Tue Dec 21 16:13:14 2010 -0800
+++ b/src/devices/uan/model/uan-phy.h	Tue Dec 21 21:44:11 2010 -0800
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Author: Leonard Tracy <lentracy@gmail.com>
+ *         Andrea Sacco <andrea.sacco85@gmail.com>
  */
 
 
@@ -27,6 +28,7 @@
 #include "ns3/uan-tx-mode.h"
 #include "ns3/uan-prop-model.h"
 #include "ns3/uan-transducer.h"
+#include "ns3/device-energy-model.h"
 
 namespace ns3 {
 
@@ -68,7 +70,7 @@
 
   /**
    * \param db dB value
-   * \returns kilopascals 
+   * \returns kilopascals
    * \brief Converts dB re 1 uPa to kilopascals
    */
   inline double DbToKp (double db) const
@@ -84,7 +86,7 @@
   {
     return 10 * log10 (kp);
   }
-  
+
 };
 
 /**
@@ -123,7 +125,9 @@
 class UanPhyListener
 {
 public:
-  virtual ~UanPhyListener () {}
+  virtual ~UanPhyListener ()
+  {
+  }
   /**
    * \brief Function called when Phy object begins receiving packet
    */
@@ -159,9 +163,10 @@
 class UanPhy : public Object
 {
 public:
-  /// Enum defining possible Phy states
-  enum State {
-    IDLE, CCABUSY, RX, TX
+  // / Enum defining possible Phy states
+  enum State
+  {
+    IDLE, CCABUSY, RX, TX, SLEEP
   };
 
   /**
@@ -178,6 +183,18 @@
   typedef Callback<void, Ptr<Packet>, double > RxErrCallback;
 
   /**
+   * \param callback DeviceEnergyModel change state callback.
+   *
+   * This function sets the DeviceEnergyModel callback for UanPhy device. Must
+   * be implemented by UanPhy child classes.
+   */
+  virtual void SetEnergyModelCallback (DeviceEnergyModel::ChangeStateCallback callback) = 0;
+  /**
+   * This function handles the energy depletion event. Must
+   * be implemented by UanPhy child classes.
+   */
+  virtual void EnergyDepletionHandler (void) = 0;
+  /**
    * \param pkt  Packet to transmit
    * \param modeNum  Index of mode in SupportedModes list to use for transmission
    */
@@ -250,7 +267,11 @@
    * \returns Threshold signal strength in dB to enter CCA busy mode
    */
   virtual double GetCcaThresholdDb (void) = 0;
-
+  /**
+   *
+   * \returns True if Phy is SLEEP
+   */
+  virtual bool IsStateSleep (void) = 0;
   /**
    *
    * \returns True if Phy is IDLE
--- a/src/devices/uan/wscript	Tue Dec 21 16:13:14 2010 -0800
+++ b/src/devices/uan/wscript	Tue Dec 21 21:44:11 2010 -0800
@@ -1,13 +1,13 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
 def build(bld):
-    module = bld.create_ns3_module('uan', ['node'])
+    module = bld.create_ns3_module('uan', ['node', 'energy'])
     module.source = [
         'model/uan-channel.cc',
         'model/uan-phy-gen.cc',
         'model/uan-transducer-hd.cc',
         'model/uan-address.cc',
-	      'model/uan-net-device.cc',
+	    'model/uan-net-device.cc',
         'model/uan-tx-mode.cc',
         'model/uan-prop-model.cc',
         'model/uan-prop-model-ideal.cc',
@@ -22,7 +22,9 @@
         'model/uan-mac-rc-gw.cc',
         'model/uan-phy.cc',
         'model/uan-noise-model.cc',
+        'model/acoustic-modem-energy-model.cc',
         'helper/uan-helper.cc',
+        'helper/acoustic-modem-energy-model-helper.cc',
         'test/uan-test.cc',
         ]
     headers = bld.new_task_gen('ns3header')
@@ -48,7 +50,9 @@
         'model/uan-phy-dual.h',
         'model/uan-header-rc.h',
         'model/uan-mac-rc.h',
+        'model/acoustic-modem-energy-model.h',
         'helper/uan-helper.h',
+        'helper/acoustic-modem-energy-model-helper.h',
         'model/uan-mac-rc-gw.h',
         ]