From 3c2239a03bca280f670fc2e75fb6fb0d6637ee79 Mon Sep 17 00:00:00 2001 From: Julian Zobel Date: Fri, 7 Sep 2018 16:09:11 +0200 Subject: [PATCH] Refactored the way that energy consumation is calculated for the energy models. Now the consumation is calculated on every energy component for itself, since the state change is of no interest to the energy model. Makes the process easier. Monitor logging can now be added to the respective energy components, if that is wished again (was removed from the energy model anyways!). --- .../p2psim/api/energy/EnergyComponent.java | 5 ++ .../impl/energy/EnergyModelFactory.java | 46 +++++++++++++++---- .../components/ActuatorEnergyComponent.java | 10 ++-- .../components/OneStateEnergyComponent.java | 6 ++- ...eCellularCommunicationEnergyComponent.java | 32 +++++++------ ...martphoneCommunicationEnergyComponent.java | 16 ++++--- .../StateEnergyCommunicationComponent.java | 9 ++-- .../StatelessCommunicationComponent.java | 10 ++-- .../energy/models/AbstractEnergyModel.java | 34 +++++++++++++- .../impl/linklayer/mac/AbstractMacLayer.java | 4 +- 10 files changed, 123 insertions(+), 49 deletions(-) diff --git a/src/de/tud/kom/p2psim/api/energy/EnergyComponent.java b/src/de/tud/kom/p2psim/api/energy/EnergyComponent.java index 2fe5d371..e70ccc91 100644 --- a/src/de/tud/kom/p2psim/api/energy/EnergyComponent.java +++ b/src/de/tud/kom/p2psim/api/energy/EnergyComponent.java @@ -21,6 +21,7 @@ package de.tud.kom.p2psim.api.energy; import de.tudarmstadt.maki.simonstrator.api.EventHandler; +import de.tudarmstadt.maki.simonstrator.api.Time; /** * A component that consumes energy (ie. a radio or a GPS-receiver). @@ -72,5 +73,9 @@ public interface EnergyComponent extends EventHandler { * @param listener */ public void setEnergyEventListener(EnergyEventListener listener); + + default double calculateEnergyConsumation(EnergyState state, long timeInState) { + return state.getEnergyConsumption() * ( (double) timeInState / (double) Time.SECOND); + } } diff --git a/src/de/tud/kom/p2psim/impl/energy/EnergyModelFactory.java b/src/de/tud/kom/p2psim/impl/energy/EnergyModelFactory.java index 59eae2e9..7b6eb127 100644 --- a/src/de/tud/kom/p2psim/impl/energy/EnergyModelFactory.java +++ b/src/de/tud/kom/p2psim/impl/energy/EnergyModelFactory.java @@ -28,7 +28,7 @@ import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.energy.EnergyConfiguration; import de.tud.kom.p2psim.api.energy.EnergyModel; import de.tud.kom.p2psim.api.scenario.ConfigurationException; -import de.tud.kom.p2psim.impl.energy.models.ModularEnergyModel; +import de.tud.kom.p2psim.impl.energy.models.ComponentBasedEnergyModel; import de.tudarmstadt.maki.simonstrator.api.Host; import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.Monitor.Level; @@ -61,6 +61,10 @@ public class EnergyModelFactory implements HostComponentFactory { */ private boolean configurationsUsed = false; + private boolean useRandomBatteryStartConfiguration = false; + private double minimumStartEnergyLevel = 0.3; + + private Battery batteryModel = new SimpleBattery(186480000, 186480000); /** @@ -80,16 +84,24 @@ public class EnergyModelFactory implements HostComponentFactory { + "Add at least one child element pointing to an EnergyConfiguration."); } configurationsUsed = true; + + Battery bat; + + if(useRandomBatteryStartConfiguration) + { + // clone the battery from the provided model + // FIXME Different Capacities for different nodes. + double percentageOfFullBattery = (1 - random.nextDouble()); + if(percentageOfFullBattery < minimumStartEnergyLevel) + percentageOfFullBattery = minimumStartEnergyLevel; + double initialEnergy = batteryModel.getMaximumEnergyLevel() * percentageOfFullBattery; + bat = new SimpleBattery(batteryModel.getMaximumEnergyLevel(), initialEnergy); + } + else { + bat = batteryModel.clone(); + } - // clone the battery from the provided model - // FIXME Different Capacities for different nodes. - double percentageOfFullBattery = (1 - random.nextDouble()); - if(percentageOfFullBattery < 0.3) - percentageOfFullBattery = 0.3; - double initialEnergy = 186480000 * percentageOfFullBattery; - Battery bat = new SimpleBattery(186480000, initialEnergy); -// Battery bat = batteryModel.clone(); - EnergyModel em = new ModularEnergyModel(host, bat); + EnergyModel em = new ComponentBasedEnergyModel(host, bat); for (EnergyConfiguration config : energyConfigurations) { em.registerComponent(config.getConfiguredEnergyComponent(host)); @@ -129,5 +141,19 @@ public class EnergyModelFactory implements HostComponentFactory { energyConfigurations.add(energyConfig); } + private void setMinimumStartEnergyLevel(double level) { + if(level > 1.0) { + this.minimumStartEnergyLevel = 1.0; + } + else if(level < 0.0) { + this.minimumStartEnergyLevel = 0.0; + } + else { + this.minimumStartEnergyLevel = level; + } + } + private void setUseRandomBatteryStartConfiguration(boolean randomStart) { + this.useRandomBatteryStartConfiguration = randomStart; + } } diff --git a/src/de/tud/kom/p2psim/impl/energy/components/ActuatorEnergyComponent.java b/src/de/tud/kom/p2psim/impl/energy/components/ActuatorEnergyComponent.java index b52cf76f..d329998d 100644 --- a/src/de/tud/kom/p2psim/impl/energy/components/ActuatorEnergyComponent.java +++ b/src/de/tud/kom/p2psim/impl/energy/components/ActuatorEnergyComponent.java @@ -20,12 +20,15 @@ package de.tud.kom.p2psim.impl.energy.components; +import de.tud.kom.p2psim.api.analyzer.EnergyAnalyzer; import de.tud.kom.p2psim.api.energy.ComponentType; import de.tud.kom.p2psim.api.energy.EnergyComponent; import de.tud.kom.p2psim.api.energy.EnergyEventListener; import de.tud.kom.p2psim.api.energy.EnergyState; import de.tud.kom.p2psim.impl.energy.DefaultEnergyState; +import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.Time; +import de.tudarmstadt.maki.simonstrator.api.component.core.MonitorComponent.AnalyzerNotAvailableException; public class ActuatorEnergyComponent implements EnergyComponent { @@ -54,11 +57,10 @@ public class ActuatorEnergyComponent implements EnergyComponent { public void doStateChange(EnergyState newState) { - // FIXME TODO long timeSpentInState = Time.getCurrentTime() - lastStateChange; - energyModel.switchedState(this, currentState, newState, - timeSpentInState); + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeSpentInState)); + currentState = newState; lastStateChange = Time.getCurrentTime(); @@ -107,4 +109,6 @@ public class ActuatorEnergyComponent implements EnergyComponent { public EnergyState getCurrentState() { return currentState; } + + } diff --git a/src/de/tud/kom/p2psim/impl/energy/components/OneStateEnergyComponent.java b/src/de/tud/kom/p2psim/impl/energy/components/OneStateEnergyComponent.java index 74a83486..a2e5d65e 100644 --- a/src/de/tud/kom/p2psim/impl/energy/components/OneStateEnergyComponent.java +++ b/src/de/tud/kom/p2psim/impl/energy/components/OneStateEnergyComponent.java @@ -67,8 +67,10 @@ public class OneStateEnergyComponent implements EnergyComponent { @Override public void eventOccurred(Object content, int type) { if (isOn()) { - energyModel.switchedState(this, state, state, Time.SECOND); - if (energyModel.turnOn(this)) { + double consumedEnergy = state.getEnergyConsumption() * Time.SECOND; + energyModel.componentConsumedEnergy(this, consumedEnergy); + + if (energyModel.componentCanBeActivated(this)) { Event.scheduleWithDelay(Time.SECOND, this, null, 0); } else { this.turnOff(); diff --git a/src/de/tud/kom/p2psim/impl/energy/components/SmartphoneCellularCommunicationEnergyComponent.java b/src/de/tud/kom/p2psim/impl/energy/components/SmartphoneCellularCommunicationEnergyComponent.java index d9730004..3605170d 100644 --- a/src/de/tud/kom/p2psim/impl/energy/components/SmartphoneCellularCommunicationEnergyComponent.java +++ b/src/de/tud/kom/p2psim/impl/energy/components/SmartphoneCellularCommunicationEnergyComponent.java @@ -30,6 +30,7 @@ import de.tud.kom.p2psim.impl.energy.DefaultEnergyState; import de.tud.kom.p2psim.impl.simengine.Simulator; import de.tudarmstadt.maki.simonstrator.api.Message; import de.tudarmstadt.maki.simonstrator.api.Monitor; +import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Monitor.Level; public class SmartphoneCellularCommunicationEnergyComponent implements @@ -102,7 +103,7 @@ EnergyCommunicationComponent { @Override public boolean isOn() { - if (energyModel.turnOn(this)) { + if (energyModel.componentCanBeActivated(this)) { doFakeStateChange(); return true; } @@ -139,8 +140,8 @@ EnergyCommunicationComponent { + " after spending " + (timeInTailState / (double) Simulator.SECOND_UNIT) + " sec there."); - energyModel - .switchedState(this, currentState, null, timeInTailState); + + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeInTailState)); tailCounter++; currentState = IDLE; lastStateChange = Simulator.getCurrentTime(); @@ -161,7 +162,7 @@ EnergyCommunicationComponent { * message. However, the energy for the ramp state before sending is * consumed. */ - energyModel.switchedState(this, RAMP_TX, null, RAMP_TX_DURATION); + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(RAMP_TX, RAMP_TX_DURATION)); } else { assert currentState.equals(TAIL_RX) || currentState.equals(TAIL_TX); @@ -176,15 +177,16 @@ EnergyCommunicationComponent { + " after spending " + (timeInTailState / (double) Simulator.SECOND_UNIT) + " sec there before starting a transmission."); - energyModel - .switchedState(this, currentState, null, timeInTailState); + + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeInTailState)); tailCounter++; } /* * Consume the energy for the transmission of data. */ - energyModel.switchedState(this, TX, null, duration); + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(TX, duration)); + Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG, Simulator.getFormattedTime(Simulator.getCurrentTime()) + " " + ((EnergyModel) energyModel).getHost().getHostId() @@ -214,7 +216,8 @@ EnergyCommunicationComponent { * message. However, the energy for the ramp state before receiving * is consumed. */ - energyModel.switchedState(this, RAMP_RX, null, RAMP_RX_DURATION); + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(RAMP_RX, RAMP_RX_DURATION)); + } else { assert currentState.equals(TAIL_RX) || currentState.equals(TAIL_TX); @@ -229,14 +232,16 @@ EnergyCommunicationComponent { + " after spending " + (timeInTailState / (double) Simulator.SECOND_UNIT) + " sec there before receiving a message."); - energyModel - .switchedState(this, currentState, null, timeInTailState); + + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeInTailState)); + tailCounter++; } /* * Consume the energy for the receiption of data. */ - energyModel.switchedState(this, RX, null, duration); + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(RX, duration)); + Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG,Simulator.getCurrentTime() + " " + ((EnergyModel) energyModel).getHost().getHostId() @@ -266,8 +271,9 @@ EnergyCommunicationComponent { + " uJ in State " + currentState.getName() + " after spending " + (timeSpentInState / (double) Simulator.SECOND_UNIT) + " sec there."); - energyModel.switchedState(this, currentState, newState, - timeSpentInState); + + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeSpentInState)); + currentState = newState; if(!currentState.equals(TAIL_RX) && !currentState.equals(TAIL_TX)) lastStateChange = Simulator.getCurrentTime(); diff --git a/src/de/tud/kom/p2psim/impl/energy/components/SmartphoneCommunicationEnergyComponent.java b/src/de/tud/kom/p2psim/impl/energy/components/SmartphoneCommunicationEnergyComponent.java index 5cc658ab..77d1e959 100644 --- a/src/de/tud/kom/p2psim/impl/energy/components/SmartphoneCommunicationEnergyComponent.java +++ b/src/de/tud/kom/p2psim/impl/energy/components/SmartphoneCommunicationEnergyComponent.java @@ -97,7 +97,7 @@ public class SmartphoneCommunicationEnergyComponent implements @Override public boolean turnOn() { - if (energyModel.turnOn(this)) { + if (energyModel.componentCanBeActivated(this)) { if (!currentState.equals(IDLE)) { doStateChange(IDLE); } @@ -139,8 +139,9 @@ public class SmartphoneCommunicationEnergyComponent implements + (SEND.getEnergyConsumption() * (duration/ (double) Simulator.SECOND_UNIT)) + " uJ in State " + SEND.getName() + " after spending " + (duration / (double) Simulator.SECOND_UNIT) + " sec there."); - energyModel.switchedState(this, SEND, null, - duration); + + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(SEND, duration)); + } @Override @@ -159,8 +160,9 @@ public class SmartphoneCommunicationEnergyComponent implements + " after spending " + (duration / (double) Simulator.SECOND_UNIT) + " sec there."); - energyModel.switchedState(this, RECEIVE, null, - duration); + + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(RECEIVE, duration)); + } public void doFakeStateChange() { @@ -181,8 +183,8 @@ public class SmartphoneCommunicationEnergyComponent implements + " after spending " + (timeSpentInState / (double) Simulator.SECOND_UNIT) + " sec there."); - energyModel.switchedState(this, currentState, newState, - timeSpentInState); + + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeSpentInState)); currentState = newState; lastStateChange = Simulator.getCurrentTime(); } diff --git a/src/de/tud/kom/p2psim/impl/energy/components/StateEnergyCommunicationComponent.java b/src/de/tud/kom/p2psim/impl/energy/components/StateEnergyCommunicationComponent.java index 81451a93..453d9cfe 100644 --- a/src/de/tud/kom/p2psim/impl/energy/components/StateEnergyCommunicationComponent.java +++ b/src/de/tud/kom/p2psim/impl/energy/components/StateEnergyCommunicationComponent.java @@ -95,7 +95,7 @@ public class StateEnergyCommunicationComponent implements @Override public boolean turnOn() { - if (energyModel.turnOn(this)) { + if (energyModel.componentCanBeActivated(this)) { if (!currentState.equals(IDLE)) { doStateChange(IDLE); } @@ -112,8 +112,7 @@ public class StateEnergyCommunicationComponent implements private void doStateChange(EnergyState newState) { long timeSpentInState = Time.getCurrentTime() - lastStateChange; timeSpentInState = Math.max(0, timeSpentInState); - energyModel.switchedState(this, currentState, newState, - timeSpentInState); + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeSpentInState)); currentState = newState; lastStateChange = Time.getCurrentTime(); } @@ -135,7 +134,7 @@ public class StateEnergyCommunicationComponent implements doStateChange(RECV); // we do this change manually, because we can save the event for the end // receive! - energyModel.switchedState(this, RECV, IDLE, duration); + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(RECV, duration)); currentState = IDLE; lastStateChange = Time.getCurrentTime() + duration; } @@ -147,7 +146,7 @@ public class StateEnergyCommunicationComponent implements doStateChange(SEND); // we do this change manually, because we can save the event for the end // receive! - energyModel.switchedState(this, SEND, IDLE, duration); + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(SEND, duration)); currentState = IDLE; lastStateChange = Time.getCurrentTime() + duration; } diff --git a/src/de/tud/kom/p2psim/impl/energy/components/StatelessCommunicationComponent.java b/src/de/tud/kom/p2psim/impl/energy/components/StatelessCommunicationComponent.java index 80e790c1..f8486939 100644 --- a/src/de/tud/kom/p2psim/impl/energy/components/StatelessCommunicationComponent.java +++ b/src/de/tud/kom/p2psim/impl/energy/components/StatelessCommunicationComponent.java @@ -26,14 +26,13 @@ import de.tud.kom.p2psim.api.energy.EnergyEventListener; import de.tud.kom.p2psim.api.energy.EnergyState; import de.tud.kom.p2psim.api.linklayer.mac.PhyType; import de.tud.kom.p2psim.impl.energy.DefaultEnergyState; -import de.tud.kom.p2psim.impl.energy.models.ModularEnergyModel; import de.tudarmstadt.maki.simonstrator.api.Message; import de.tudarmstadt.maki.simonstrator.api.Time; /** * This is the implementation of a communication component that does not care * about a state - it just consumes energy as soon as something is being sent. - * In the context of the {@link ModularEnergyModel} we mimic a state-aware + * In the context of the {@link StateSwitchingEnergyModel} we mimic a state-aware * behavior. Please take a look at the comment in the Constructor if your * analyzers seem to return odd results with this component... * @@ -120,7 +119,7 @@ public class StatelessCommunicationComponent implements @Override public boolean turnOn() { - if (energyModel.turnOn(this)) { + if (energyModel.componentCanBeActivated(this)) { if (!currentState.equals(IDLE)) { doStateChange(IDLE); } @@ -136,8 +135,7 @@ public class StatelessCommunicationComponent implements private void doStateChange(EnergyState newState) { long timeSpentInState = Time.getCurrentTime() - lastStateChange; - energyModel.switchedState(this, currentState, newState, - timeSpentInState); + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeSpentInState)); currentState = newState; lastStateChange = Time.getCurrentTime(); } @@ -167,7 +165,7 @@ public class StatelessCommunicationComponent implements doStateChange(ON); // switch back to IDLE with fake timeHP - energyModel.switchedState(this, ON, IDLE, timeHP); + energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(ON, timeHP)); currentState = IDLE; lastStateChange = Time.getCurrentTime(); } diff --git a/src/de/tud/kom/p2psim/impl/energy/models/AbstractEnergyModel.java b/src/de/tud/kom/p2psim/impl/energy/models/AbstractEnergyModel.java index 4efd54b5..edc6882a 100644 --- a/src/de/tud/kom/p2psim/impl/energy/models/AbstractEnergyModel.java +++ b/src/de/tud/kom/p2psim/impl/energy/models/AbstractEnergyModel.java @@ -24,14 +24,17 @@ import java.util.List; import java.util.Set; import java.util.Vector; +import de.tud.kom.p2psim.api.analyzer.EnergyAnalyzer; import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.energy.ComponentType; import de.tud.kom.p2psim.api.energy.EnergyComponent; import de.tud.kom.p2psim.api.energy.EnergyInfo; import de.tud.kom.p2psim.api.energy.EnergyModel; import de.tud.kom.p2psim.impl.energy.Battery; +import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID; import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException; +import de.tudarmstadt.maki.simonstrator.api.component.core.MonitorComponent.AnalyzerNotAvailableException; import de.tudarmstadt.maki.simonstrator.api.component.sensor.battery.BatterySensor; import de.tudarmstadt.maki.simonstrator.api.component.sis.SiSComponent; import de.tudarmstadt.maki.simonstrator.api.component.sis.SiSDataCallback; @@ -40,6 +43,13 @@ import de.tudarmstadt.maki.simonstrator.api.component.sis.SiSInformationProvider import de.tudarmstadt.maki.simonstrator.api.component.sis.exception.InformationNotAvailableException; import de.tudarmstadt.maki.simonstrator.api.component.sis.type.SiSTypes; +/** + * The default functionalities for energy models, composed of different + * {@link EnergyComponent}s and configured via the factory. + * + * @author Julian Zobel + * @version 1.0, 07.09.2018 + */ public abstract class AbstractEnergyModel implements EnergyModel, BatterySensor, EnergyInfo { protected SimHost host; @@ -183,5 +193,27 @@ public abstract class AbstractEnergyModel implements EnergyModel, BatterySensor, "You are not supposed to reset this component."); } - + protected void monitorEnergyConsumation(EnergyComponent component, double consumedEnergy) { + /* + * TODO Refactor the Energy-Analyzer to support EnergyComponents + * directly, rather than strings. + */ + try { + Monitor.get(EnergyAnalyzer.class).consumeEnergy(getHost(), + consumedEnergy, component); + } catch (AnalyzerNotAvailableException e1) { + // + } + } + + protected void monitorEmptyBattery() { + /* + * Battery is now empty. + */ + try { + Monitor.get(EnergyAnalyzer.class).batteryIsEmpty(getHost()); + } catch (AnalyzerNotAvailableException e) { + // + } + } } diff --git a/src/de/tud/kom/p2psim/impl/linklayer/mac/AbstractMacLayer.java b/src/de/tud/kom/p2psim/impl/linklayer/mac/AbstractMacLayer.java index 42e0bc72..de165ead 100644 --- a/src/de/tud/kom/p2psim/impl/linklayer/mac/AbstractMacLayer.java +++ b/src/de/tud/kom/p2psim/impl/linklayer/mac/AbstractMacLayer.java @@ -31,7 +31,7 @@ import de.tud.kom.p2psim.api.analyzer.MessageAnalyzer.Reason; import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.energy.ComponentType; import de.tud.kom.p2psim.api.energy.EnergyCommunicationComponent; -import de.tud.kom.p2psim.api.energy.EnergyEventListener; +import de.tud.kom.p2psim.api.energy.OldEnergyEventListener; import de.tud.kom.p2psim.api.linklayer.LinkLayerMessage; import de.tud.kom.p2psim.api.linklayer.LinkMessageEvent; import de.tud.kom.p2psim.api.linklayer.LinkMessageListener; @@ -985,7 +985,7 @@ public abstract class AbstractMacLayer implements MacLayer { } @Override - public void setEnergyEventListener(EnergyEventListener listener) { + public void setEnergyEventListener(OldEnergyEventListener listener) { // not interested } -- GitLab