diff --git a/src/de/tud/kom/p2psim/api/energy/EnergyComponent.java b/src/de/tud/kom/p2psim/api/energy/EnergyComponent.java index 2fe5d371aea2f24e4e7625ffb0b903f97eb6a63b..e70ccc9143c08f574ec09b4a4c6ce00543a674c4 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 59eae2e907a4d3b68ffb24ac96f6bfcc245487f9..7b6eb127b20dd8c54c265937c0e71881778dfbf2 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 b52cf76fc3f3b47a674d889e9c58a8aa7becbb74..d329998d38658ceb97efc166e8a5298866d73098 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 74a83486a3c5f4dd29f0534a7d22a69074e6de21..a2e5d65e449d3c4fa0f6fb128ed87b56a0c8da22 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 d9730004f2b0f7f21e9e7ebef1cbe5b6deb9ca13..3605170d881e32e648f6d4296d5c4c3897cd85bb 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 5cc658ab94d3ae56ad3260d547d6b7d408adf9b9..77d1e959bb776469c4c3f32aad60a7d14eabbbc7 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 81451a936086e5d682cd322668be89a87b04af53..453d9cfed4b5a50345ecb85a7ed3ce1505dedce1 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 80e790c11bd287d7711457bc8562a282d44eb057..f84869398b36c83fe523f68a30a2728104e5ed4c 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 4efd54b5c4036fc493f426d077016c0bd1053d49..edc6882a2577272694cb952df04959818b3f896a 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 42e0bc72b5df0521f9c3964016731502b6232753..de165ead91aca5c9399fe8b7218f7ec7edced6a9 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 }