From 1b7dd60567156f3df9c03f0784c0407fd26849f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Wed, 10 Jan 2018 17:43:54 +0100 Subject: [PATCH] wifi: (fixes #2809) Stop wifi devices when energy is depleted --- RELEASE_NOTES | 1 + src/energy/model/basic-energy-source.cc | 24 +++--- src/energy/model/device-energy-model.h | 6 ++ src/energy/model/energy-source.cc | 12 +++ src/energy/model/energy-source.h | 6 ++ src/energy/model/simple-device-energy-model.h | 9 +++ src/uan/model/acoustic-modem-energy-model.cc | 8 ++ src/uan/model/acoustic-modem-energy-model.h | 9 ++- .../helper/wifi-radio-energy-model-helper.cc | 20 ++--- src/wifi/model/mac-low.cc | 10 ++- src/wifi/model/wifi-phy-tag.cc | 17 +++- src/wifi/model/wifi-phy-tag.h | 9 ++- src/wifi/model/wifi-phy.cc | 78 ++++++++++++++++--- src/wifi/model/wifi-phy.h | 36 +++++++-- src/wifi/model/wifi-radio-energy-model.cc | 68 +++++++++++++++- src/wifi/model/wifi-radio-energy-model.h | 16 ++++ src/wifi/test/spectrum-wifi-phy-test.cc | 2 +- 17 files changed, 280 insertions(+), 51 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 4907aa361..c373fb09b 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -39,6 +39,7 @@ Bugs fixed - Bug 2766 - core: Modify logging for int64x64 to avoid stack overflow - Bug 2768 - lte: LteUeNetDevice has a null MAC address - Bug 2807 - energy: GetTotalEnergyConsumption is not updated correctly +- Bug 2809 - wifi: Wifi doesn't fully stop when energy is depleted - Bug 2820 - wifi: segmentation fault when Rrpaa wifi manager is used - Bug 2824 - ICMP opcode fr fragment timeout drop is wrong - Bug 2828 - OLSR simple P2P example produces wrong results diff --git a/src/energy/model/basic-energy-source.cc b/src/energy/model/basic-energy-source.cc index 2a05042a8..0a662b16d 100644 --- a/src/energy/model/basic-energy-source.cc +++ b/src/energy/model/basic-energy-source.cc @@ -162,6 +162,7 @@ BasicEnergySource::UpdateEnergySource (void) m_energyUpdateEvent.Cancel (); + double remainingEnergy = m_remainingEnergyJ; CalculateRemainingEnergy (); m_lastUpdateTime = Simulator::Now (); @@ -171,12 +172,15 @@ BasicEnergySource::UpdateEnergySource (void) m_depleted = true; HandleEnergyDrainedEvent (); } - - if (m_depleted && m_remainingEnergyJ > m_highBatteryTh * m_initialEnergyJ) + else if (m_depleted && m_remainingEnergyJ > m_highBatteryTh * m_initialEnergyJ) { m_depleted = false; HandleEnergyRechargedEvent (); } + else if (m_remainingEnergyJ != remainingEnergy) + { + NotifyEnergyChanged (); + } m_energyUpdateEvent = Simulator::Schedule (m_energyUpdateInterval, &BasicEnergySource::UpdateEnergySource, @@ -223,19 +227,11 @@ BasicEnergySource::CalculateRemainingEnergy (void) NS_LOG_FUNCTION (this); double totalCurrentA = CalculateTotalCurrent (); Time duration = Simulator::Now () - m_lastUpdateTime; - NS_ASSERT (duration.GetSeconds () >= 0); + NS_ASSERT (duration.IsPositive ()); // energy = current * voltage * time - double energyToDecreaseJ = totalCurrentA * m_supplyVoltageV * duration.GetSeconds (); - - if (m_remainingEnergyJ < energyToDecreaseJ) - { - m_remainingEnergyJ = 0; // energy never goes below 0 - } - else - { - m_remainingEnergyJ -= energyToDecreaseJ; - } - + double energyToDecreaseJ = (totalCurrentA * m_supplyVoltageV * duration.GetNanoSeconds ()) / 1e9; + NS_ASSERT (m_remainingEnergyJ >= energyToDecreaseJ); + m_remainingEnergyJ -= energyToDecreaseJ; NS_LOG_DEBUG ("BasicEnergySource:Remaining energy = " << m_remainingEnergyJ); } diff --git a/src/energy/model/device-energy-model.h b/src/energy/model/device-energy-model.h index edea8962e..c6460a749 100644 --- a/src/energy/model/device-energy-model.h +++ b/src/energy/model/device-energy-model.h @@ -99,6 +99,12 @@ public: */ virtual void HandleEnergyRecharged (void) = 0; + /** + * This function is called by the EnergySource object when energy stored in + * the energy source is changed. Should be implemented by child classes. + */ + virtual void HandleEnergyChanged (void) = 0; + private: /** diff --git a/src/energy/model/energy-source.cc b/src/energy/model/energy-source.cc index 14f8517f4..253f5dd9a 100644 --- a/src/energy/model/energy-source.cc +++ b/src/energy/model/energy-source.cc @@ -212,6 +212,18 @@ EnergySource::NotifyEnergyRecharged (void) } } +void +EnergySource::NotifyEnergyChanged (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)->HandleEnergyChanged (); + } +} + void EnergySource::BreakDeviceEnergyModelRefCycle (void) { diff --git a/src/energy/model/energy-source.h b/src/energy/model/energy-source.h index 722468def..4a224dbfb 100644 --- a/src/energy/model/energy-source.h +++ b/src/energy/model/energy-source.h @@ -228,6 +228,12 @@ protected: */ void NotifyEnergyRecharged (void); + /** + * This function notifies all DeviceEnergyModel of energy changed event. It + * is called by the child EnergySource class when energy source is changed. + */ + void NotifyEnergyChanged (void); + /** * This function is called to break reference cycle between EnergySource and * DeviceEnergyModel. Child of the EnergySource base class must call this diff --git a/src/energy/model/simple-device-energy-model.h b/src/energy/model/simple-device-energy-model.h index 772271dfb..01d25b763 100644 --- a/src/energy/model/simple-device-energy-model.h +++ b/src/energy/model/simple-device-energy-model.h @@ -103,6 +103,15 @@ public: { } + /** + * \brief Handles energy changed. + * + * Not implemented + */ + virtual void HandleEnergyChanged (void) + { + } + /** * \param current the current draw of device. * diff --git a/src/uan/model/acoustic-modem-energy-model.cc b/src/uan/model/acoustic-modem-energy-model.cc index fad79165e..d119b3418 100644 --- a/src/uan/model/acoustic-modem-energy-model.cc +++ b/src/uan/model/acoustic-modem-energy-model.cc @@ -288,6 +288,14 @@ AcousticModemEnergyModel::HandleEnergyRecharged (void) SetMicroModemState(UanPhy::IDLE); } +void +AcousticModemEnergyModel::HandleEnergyChanged (void) +{ + NS_LOG_FUNCTION (this); + //Not implemented +} + + /* * Private functions start here. */ diff --git a/src/uan/model/acoustic-modem-energy-model.h b/src/uan/model/acoustic-modem-energy-model.h index d996e5559..8b121bc0a 100644 --- a/src/uan/model/acoustic-modem-energy-model.h +++ b/src/uan/model/acoustic-modem-energy-model.h @@ -175,16 +175,21 @@ public: virtual void ChangeState (int newState); /** - * Handles energy depletion. + * \brief Handles energy depletion. */ virtual void HandleEnergyDepletion (void); /** * \brief Handles energy recharged. + */ + virtual void HandleEnergyRecharged (void); + + /** + * \brief Handles energy changed. * * Not implemented */ - virtual void HandleEnergyRecharged (void); + virtual void HandleEnergyChanged (void); private: diff --git a/src/wifi/helper/wifi-radio-energy-model-helper.cc b/src/wifi/helper/wifi-radio-energy-model-helper.cc index ee98ac931..55d448f88 100644 --- a/src/wifi/helper/wifi-radio-energy-model-helper.cc +++ b/src/wifi/helper/wifi-radio-energy-model-helper.cc @@ -99,32 +99,32 @@ WifiRadioEnergyModelHelper::DoInstall (Ptr device, Ptr node = device->GetNode (); Ptr model = m_radioEnergy.Create ()->GetObject (); NS_ASSERT (model != NULL); - // set energy source pointer - model->SetEnergySource (source); + // set energy depletion callback - // if none is specified, make a callback to WifiPhy::SetSleepMode + // if none is specified, make a callback to WifiPhy::SetOffMode Ptr wifiDevice = DynamicCast (device); Ptr wifiPhy = wifiDevice->GetPhy (); + wifiPhy->SetWifiRadioEnergyModel (model); if (m_depletionCallback.IsNull ()) { - model->SetEnergyDepletionCallback (MakeCallback (&WifiPhy::SetSleepMode, wifiPhy)); + model->SetEnergyDepletionCallback (MakeCallback (&WifiPhy::SetOffMode, 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 + // if none is specified, make a callback to WifiPhy::ResumeFromOff + //TODO: ResumeFromOff not supported yet + //model->SetEnergyRechargedCallback (MakeCallback (&WifiPhy::ResumeFromOff, wifiPhy)); + if (!m_rechargedCallback.IsNull ()) { model->SetEnergyRechargedCallback (m_rechargedCallback); } // add model to device model list in energy source source->AppendDeviceEnergyModel (model); + // set energy source pointer + model->SetEnergySource (source); // create and register energy model phy listener wifiPhy->RegisterListener (model->GetPhyListener ()); // diff --git a/src/wifi/model/mac-low.cc b/src/wifi/model/mac-low.cc index 614a63035..9932aa103 100644 --- a/src/wifi/model/mac-low.cc +++ b/src/wifi/model/mac-low.cc @@ -460,6 +460,12 @@ MacLow::StartTransmission (Ptr packet, MacLowTransmissionParameters params, Ptr dca) { + if (m_phy->IsStateOff ()) + { + NS_LOG_DEBUG ("Cannot start TX because device is OFF"); + return; + } + NS_LOG_FUNCTION (this << packet << hdr << params << dca); /* m_currentPacket is not NULL because someone started * a transmission and was interrupted before one of: @@ -572,8 +578,8 @@ MacLow::StartTransmission (Ptr packet, } } - /* When this method completes, we have taken ownership of the medium. */ - NS_ASSERT (m_phy->IsStateTx ()); + /* When this method completes, either we have taken ownership of the medium or the device switched off in the meantime. */ + NS_ASSERT (m_phy->IsStateTx () || m_phy->IsStateOff ()); } bool diff --git a/src/wifi/model/wifi-phy-tag.cc b/src/wifi/model/wifi-phy-tag.cc index 70def7024..f210d0ef3 100644 --- a/src/wifi/model/wifi-phy-tag.cc +++ b/src/wifi/model/wifi-phy-tag.cc @@ -40,7 +40,7 @@ WifiPhyTag::GetInstanceTypeId (void) const uint32_t WifiPhyTag::GetSerializedSize (void) const { - return (sizeof (WifiTxVector) + 2); + return (sizeof (WifiTxVector) + 2 + 1); } void @@ -48,6 +48,7 @@ WifiPhyTag::Serialize (TagBuffer i) const { i.Write ((uint8_t *)&m_wifiTxVector, sizeof (WifiTxVector)); i.WriteU16 (m_mpduType); + i.WriteU8 (m_frameComplete); } void @@ -55,20 +56,22 @@ WifiPhyTag::Deserialize (TagBuffer i) { i.Read ((uint8_t *)&m_wifiTxVector, sizeof (WifiTxVector)); m_mpduType = static_cast (i.ReadU16 ()); + m_frameComplete = i.ReadU8 (); } void WifiPhyTag::Print (std::ostream &os) const { - os << m_wifiTxVector << " " << m_mpduType; + os << m_wifiTxVector << " " << m_mpduType << " " << m_frameComplete; } WifiPhyTag::WifiPhyTag () { } -WifiPhyTag::WifiPhyTag (WifiTxVector txVector, MpduType mpdutype) +WifiPhyTag::WifiPhyTag (WifiTxVector txVector, MpduType mpdutype, uint8_t frameComplete) : m_wifiTxVector (txVector), - m_mpduType (mpdutype) + m_mpduType (mpdutype), + m_frameComplete (frameComplete) { } @@ -84,4 +87,10 @@ WifiPhyTag::GetMpduType (void) const return m_mpduType; } +uint8_t +WifiPhyTag::GetFrameComplete (void) const +{ + return m_frameComplete; +} + } // namespace ns3 diff --git a/src/wifi/model/wifi-phy-tag.h b/src/wifi/model/wifi-phy-tag.h index 7df8d9853..fd81b4851 100644 --- a/src/wifi/model/wifi-phy-tag.h +++ b/src/wifi/model/wifi-phy-tag.h @@ -50,8 +50,9 @@ public: * Constructor * \param txVector the WifiTxVector * \param mpdutype the mpduType + * \param frameComplete the frameComplete */ - WifiPhyTag (WifiTxVector txVector, MpduType mpdutype); + WifiPhyTag (WifiTxVector txVector, MpduType mpdutype, uint8_t frameComplete); /** * Getter for WifiTxVector parameter * \return the WifiTxVector @@ -62,6 +63,11 @@ public: * \return mpduType the mpduType */ MpduType GetMpduType (void) const; + /** + * Getter for frameComplete parameter + * \return the frameComplete parameter, i.e. 0 if the frame is not complete, 1 otherwise. + */ + uint8_t GetFrameComplete (void) const; // From class Tag uint32_t GetSerializedSize (void) const; @@ -73,6 +79,7 @@ public: private: WifiTxVector m_wifiTxVector; ///< wifi transmit vector MpduType m_mpduType; ///< MPDU type + uint8_t m_frameComplete; ///< Used to indicate that TX stopped sending before the end of the frame }; } // namespace ns3 diff --git a/src/wifi/model/wifi-phy.cc b/src/wifi/model/wifi-phy.cc index 1b2e929b5..82fd72f7e 100644 --- a/src/wifi/model/wifi-phy.cc +++ b/src/wifi/model/wifi-phy.cc @@ -31,6 +31,7 @@ #include "ampdu-tag.h" #include "wifi-utils.h" #include "frame-capture-model.h" +#include "wifi-radio-energy-model.h" namespace ns3 { @@ -372,7 +373,8 @@ WifiPhy::WifiPhy () m_initialChannelNumber (0), m_totalAmpduSize (0), m_totalAmpduNumSymbols (0), - m_currentEvent (0) + m_currentEvent (0), + m_wifiRadioEnergyModel (0) { NS_LOG_FUNCTION (this); m_random = CreateObject (); @@ -705,6 +707,12 @@ WifiPhy::GetFrameCaptureModel (void) const { return m_frameCaptureModel; } + +void +WifiPhy::SetWifiRadioEnergyModel (const Ptr wifiRadioEnergyModel) +{ + m_wifiRadioEnergyModel = wifiRadioEnergyModel; +} double WifiPhy::GetPowerDbm (uint8_t power) const @@ -1598,6 +1606,28 @@ WifiPhy::SetSleepMode (void) } } +void +WifiPhy::SetOffMode (void) +{ + NS_LOG_FUNCTION (this); + switch (m_state->GetState ()) + { + case WifiPhy::RX: + m_endPlcpRxEvent.Cancel (); + m_endRxEvent.Cancel (); + case WifiPhy::TX: + case WifiPhy::SWITCHING: + case WifiPhy::CCA_BUSY: + case WifiPhy::IDLE: + case WifiPhy::SLEEP: + m_state->SwitchToOff (); + break; + default: + NS_ASSERT (false); + break; + } +} + void WifiPhy::ResumeFromSleep (void) { @@ -2328,7 +2358,17 @@ WifiPhy::SendPacket (Ptr packet, WifiTxVector txVector, MpduType m Ptr newPacket = packet->Copy (); // obtain non-const Packet WifiPhyTag oldtag; newPacket->RemovePacketTag (oldtag); - WifiPhyTag tag (txVector, mpdutype); + if (m_state->GetState () == WifiPhy::OFF) + { + NS_LOG_DEBUG ("Transmission canceled because device is OFF"); + return; + } + uint8_t isFrameComplete = 1; + if (m_wifiRadioEnergyModel != 0 && m_wifiRadioEnergyModel->GetMaximumTimeInState (WifiPhy::TX) < txDuration) + { + isFrameComplete = 0; + } + WifiPhyTag tag (txVector, mpdutype, isFrameComplete); newPacket->AddPacketTag (tag); StartTx (newPacket, txVector, txDuration); @@ -2339,6 +2379,12 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr packet, double rxPowerW, Tim { //This function should be later split to check separately whether plcp preamble and plcp header can be successfully received. //Note: plcp preamble reception is not yet modeled. + if (m_state->GetState () == WifiPhy::OFF) + { + NS_LOG_DEBUG ("Cannot start RX because device is OFF"); + return; + } + NS_LOG_FUNCTION (this << packet << WToDbm (rxPowerW) << rxDuration); Time endRx = Simulator::Now () + rxDuration; @@ -2350,6 +2396,14 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr packet, double rxPowerW, Tim return; } + if (tag.GetFrameComplete () == 0) + { + NS_LOG_DEBUG ("drop packet because of incomplete frame"); + NotifyRxDrop (packet); + m_plcpSuccess = false; + return; + } + WifiTxVector txVector = tag.GetWifiTxVector (); if (txVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT @@ -3493,47 +3547,53 @@ WifiPhy::GetMcs (uint8_t mcs) const } bool -WifiPhy::IsStateCcaBusy (void) +WifiPhy::IsStateCcaBusy (void) const { return m_state->IsStateCcaBusy (); } bool -WifiPhy::IsStateIdle (void) +WifiPhy::IsStateIdle (void) const { return m_state->IsStateIdle (); } bool -WifiPhy::IsStateBusy (void) +WifiPhy::IsStateBusy (void) const { return m_state->IsStateBusy (); } bool -WifiPhy::IsStateRx (void) +WifiPhy::IsStateRx (void) const { return m_state->IsStateRx (); } bool -WifiPhy::IsStateTx (void) +WifiPhy::IsStateTx (void) const { return m_state->IsStateTx (); } bool -WifiPhy::IsStateSwitching (void) +WifiPhy::IsStateSwitching (void) const { return m_state->IsStateSwitching (); } bool -WifiPhy::IsStateSleep (void) +WifiPhy::IsStateSleep (void) const { return m_state->IsStateSleep (); } +bool +WifiPhy::IsStateOff (void) const +{ + return m_state->IsStateOff (); +} + Time WifiPhy::GetStateDuration (void) { diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index 2705d1dab..ea291401e 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -49,6 +49,11 @@ class WifiPhyStateHelper; */ class FrameCaptureModel; +/** + * WifiRadioEnergyModel class + */ +class WifiRadioEnergyModel; + /** * This enumeration defines the type of an MPDU. */ @@ -312,35 +317,44 @@ public: * Resume from sleep mode. */ void ResumeFromSleep (void); + /** + * Put in off mode. + */ + void SetOffMode (void); /** * \return true of the current state of the PHY layer is WifiPhy::IDLE, false otherwise. */ - bool IsStateIdle (void); + bool IsStateIdle (void) const; /** * \return true of the current state of the PHY layer is WifiPhy::CCA_BUSY, false otherwise. */ - bool IsStateCcaBusy (void); + bool IsStateCcaBusy (void) const; /** * \return true of the current state of the PHY layer is not WifiPhy::IDLE, false otherwise. */ - bool IsStateBusy (void); + bool IsStateBusy (void) const; /** * \return true of the current state of the PHY layer is WifiPhy::RX, false otherwise. */ - bool IsStateRx (void); + bool IsStateRx (void) const; /** * \return true of the current state of the PHY layer is WifiPhy::TX, false otherwise. */ - bool IsStateTx (void); + bool IsStateTx (void) const; /** * \return true of the current state of the PHY layer is WifiPhy::SWITCHING, false otherwise. */ - bool IsStateSwitching (void); + bool IsStateSwitching (void) const; /** * \return true if the current state of the PHY layer is WifiPhy::SLEEP, false otherwise. */ - bool IsStateSleep (void); + bool IsStateSleep (void) const; + /** + * \return true if the current state of the PHY layer is WifiPhy::OFF, false otherwise. + */ + bool IsStateOff (void) const ; + /** * \return the amount of time since the current state has started. */ @@ -1609,6 +1623,13 @@ public: */ Ptr GetFrameCaptureModel (void) const; + /** + * Sets the wifi radio energy model. + * + * \param wifiRadioEnergyModel the wifi radio energy model + */ + void SetWifiRadioEnergyModel (const Ptr wifiRadioEnergyModel); + /** * \return the channel width */ @@ -1965,6 +1986,7 @@ private: Ptr m_currentEvent; //!< Hold the current event Ptr m_frameCaptureModel; //!< Frame capture model + Ptr m_wifiRadioEnergyModel; //!< Wifi radio energy model }; /** diff --git a/src/wifi/model/wifi-radio-energy-model.cc b/src/wifi/model/wifi-radio-energy-model.cc index f13417c56..3d2b53133 100644 --- a/src/wifi/model/wifi-radio-energy-model.cc +++ b/src/wifi/model/wifi-radio-energy-model.cc @@ -113,6 +113,9 @@ WifiRadioEnergyModel::SetEnergySource (const Ptr source) NS_LOG_FUNCTION (this << source); NS_ASSERT (source != NULL); m_source = source; + m_switchToOffEvent.Cancel (); + Time durationToOff = GetMaximumTimeInState (m_currentState); + m_switchToOffEvent = Simulator::Schedule (durationToOff, &WifiRadioEnergyModel::ChangeState, this, WifiPhy::OFF); } double @@ -146,6 +149,9 @@ WifiRadioEnergyModel::GetTotalEnergyConsumption (void) const case WifiPhy::SLEEP: energyToDecrease = duration.GetSeconds () * m_sleepCurrentA * supplyVoltage; break; + case WifiPhy::OFF: + energyToDecrease = 0; + break; default: NS_FATAL_ERROR ("WifiRadioEnergyModel:Undefined radio state: " << m_currentState); } @@ -286,6 +292,38 @@ WifiRadioEnergyModel::SetTxCurrentFromModel (double txPowerDbm) } } +Time +WifiRadioEnergyModel::GetMaximumTimeInState (int state) const +{ + Time remainingTime; + double remainingEnergy = m_source->GetRemainingEnergy(); + double supplyVoltage = m_source->GetSupplyVoltage (); + switch (state) + { + case WifiPhy::IDLE: + remainingTime = NanoSeconds (1e9 * (remainingEnergy / (m_idleCurrentA * supplyVoltage))); + break; + case WifiPhy::CCA_BUSY: + remainingTime = NanoSeconds (1e9 * (remainingEnergy / (m_ccaBusyCurrentA * supplyVoltage))); + break; + case WifiPhy::TX: + remainingTime = NanoSeconds (1e9 * (remainingEnergy / (m_txCurrentA * supplyVoltage))); + break; + case WifiPhy::RX: + remainingTime = NanoSeconds (1e9 * (remainingEnergy / (m_rxCurrentA * supplyVoltage))); + break; + case WifiPhy::SWITCHING: + remainingTime = NanoSeconds (1e9 * (remainingEnergy / (m_switchingCurrentA * supplyVoltage))); + break; + case WifiPhy::SLEEP: + remainingTime = NanoSeconds (1e9 * (remainingEnergy / (m_sleepCurrentA * supplyVoltage))); + break; + default: + NS_FATAL_ERROR ("WifiRadioEnergyModel: undefined radio state " << state); + } + return remainingTime; +} + void WifiRadioEnergyModel::ChangeState (int newState) { @@ -293,6 +331,20 @@ WifiRadioEnergyModel::ChangeState (int newState) m_nPendingChangeState++; + if (m_nPendingChangeState > 1 && newState == WifiPhy::OFF) + { + SetWifiRadioState ((WifiPhy::State) newState); + m_nPendingChangeState--; + return; + } + + if (newState != WifiPhy::OFF) + { + m_switchToOffEvent.Cancel (); + Time durationToOff = GetMaximumTimeInState (newState); + m_switchToOffEvent = Simulator::Schedule (durationToOff, &WifiRadioEnergyModel::ChangeState, this, WifiPhy::OFF); + } + Time duration = Simulator::Now () - m_lastUpdateTime; NS_ASSERT (duration.IsPositive ()); // check if duration is valid @@ -328,6 +380,7 @@ WifiRadioEnergyModel::ChangeState (int newState) // update total energy consumption m_totalEnergyConsumption += energyToDecrease; + NS_ASSERT (m_totalEnergyConsumption <= m_source->GetInitialEnergy ()); // update last update time stamp m_lastUpdateTime = Simulator::Now (); @@ -342,7 +395,7 @@ WifiRadioEnergyModel::ChangeState (int newState) // 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. - if (m_nPendingChangeState <= 1) + if (m_nPendingChangeState <= 1 && m_currentState != WifiPhy::OFF) { // update current state & last update time stamp SetWifiRadioState ((WifiPhy::State) newState); @@ -379,6 +432,19 @@ WifiRadioEnergyModel::HandleEnergyRecharged (void) } } +void +WifiRadioEnergyModel::HandleEnergyChanged (void) +{ + NS_LOG_FUNCTION (this); + NS_LOG_DEBUG ("WifiRadioEnergyModel:Energy is changed!"); + if (m_currentState != WifiPhy::OFF) + { + m_switchToOffEvent.Cancel (); + Time durationToOff = GetMaximumTimeInState (m_currentState); + m_switchToOffEvent = Simulator::Schedule (durationToOff, &WifiRadioEnergyModel::ChangeState, this, WifiPhy::OFF); + } +} + WifiRadioEnergyModelPhyListener * WifiRadioEnergyModel::GetPhyListener (void) { diff --git a/src/wifi/model/wifi-radio-energy-model.h b/src/wifi/model/wifi-radio-energy-model.h index eaf7f100f..587d5d6f7 100644 --- a/src/wifi/model/wifi-radio-energy-model.h +++ b/src/wifi/model/wifi-radio-energy-model.h @@ -354,6 +354,13 @@ public: */ void ChangeState (int newState); + /** + * \param state the wifi state + * + * \returns the time the radio can stay in that state based on the remaining energy. + */ + Time GetMaximumTimeInState (int state) const; + /** * \brief Handles energy depletion. * @@ -368,6 +375,13 @@ public: */ void HandleEnergyRecharged (void); + /** + * \brief Handles energy changed. + * + * Implements DeviceEnergyModel::HandleEnergyChanged + */ + void HandleEnergyChanged (void); + /** * \returns Pointer to the PHY listener. */ @@ -420,6 +434,8 @@ private: /// WifiPhy listener WifiRadioEnergyModelPhyListener *m_listener; + + EventId m_switchToOffEvent; ///< switch to off event }; } // namespace ns3 diff --git a/src/wifi/test/spectrum-wifi-phy-test.cc b/src/wifi/test/spectrum-wifi-phy-test.cc index 89ac27759..67e09b9db 100644 --- a/src/wifi/test/spectrum-wifi-phy-test.cc +++ b/src/wifi/test/spectrum-wifi-phy-test.cc @@ -113,7 +113,7 @@ SpectrumWifiPhyBasicTest::MakeSignal (double txPowerWatts) pkt->AddHeader (hdr); pkt->AddTrailer (trailer); - WifiPhyTag tag (txVector, mpdutype); + WifiPhyTag tag (txVector, mpdutype, 1); pkt->AddPacketTag (tag); Ptr txPowerSpectrum = WifiSpectrumValueHelper::CreateOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, txPowerWatts, GUARD_WIDTH); Ptr txParams = Create ();