/* * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab * * This file is part of PeerfactSim.KOM. * * PeerfactSim.KOM is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * PeerfactSim.KOM 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 PeerfactSim.KOM. If not, see . * */ package de.tud.kom.p2psim.impl.energy.components; 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.EnergyModel; 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.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 EnergyCommunicationComponent { private PhyType phy; private EnergyEventListener energyModel; /** * The different states of this energy component. */ private final EnergyState IDLE, TX, RX, RAMP_TX, RAMP_RX, TAIL_TX, TAIL_RX; private final long RAMP_RX_DURATION = 1994 * Simulator.MILLISECOND_UNIT; private final long TAIL_RX_DURATION = 3132 * Simulator.MILLISECOND_UNIT; private final long RAMP_TX_DURATION = 3096 * Simulator.MILLISECOND_UNIT; private final long TAIL_TX_DURATION = 4796 * Simulator.MILLISECOND_UNIT; private int tailCounter; /** * Represents the state, this energy component is currently in. */ private EnergyState currentState; /** * Represents the time, when the energy component entered the current energy * state. */ private long lastStateChange; public SmartphoneCellularCommunicationEnergyComponent(PhyType phy) { this.phy = phy; IDLE = new DefaultEnergyState("IDLE", 0); TX = new DefaultEnergyState("TX", 1.105 * 1000000); RAMP_TX = new DefaultEnergyState("RAMP_TX", 0.749 * 1000000); TAIL_TX = new DefaultEnergyState("TAIL_TX", 0.563 * 1000000); RX = new DefaultEnergyState("RX", 0.786 * 1000000); RAMP_RX = new DefaultEnergyState("RAMP_RX", 0.505 * 1000000); TAIL_RX = new DefaultEnergyState("TAIL_RX", 0.483 * 1000000); tailCounter = 0; currentState = IDLE; lastStateChange = 0; } @Override public ComponentType getType() { return ComponentType.COMMUNICATION; } @Override public boolean turnOff() { if (!currentState.equals(IDLE)) { doStateChange(IDLE); } tailCounter++; return true; } @Override public boolean turnOn() { return true; } @Override public boolean isOn() { if (energyModel.componentCanBeActivated(this)) { doFakeStateChange(); return true; } return false; } @Override public void setEnergyEventListener(EnergyEventListener listener) { this.energyModel = listener; } @Override public void eventOccurred(Object content, int type) { if (type == tailCounter) { assert currentState.equals(TAIL_RX) || currentState.equals(TAIL_TX) : "Assert1 SmartphoneCellularCommunicationEnergy"; long timeInTailState = Simulator.getCurrentTime() - lastStateChange; if((TAIL_RX_DURATION-timeInTailState)!=0 && currentState.equals(TAIL_RX)) Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.WARN, TAIL_RX_DURATION +" vs. " + timeInTailState); if((TAIL_TX_DURATION-timeInTailState)!=0 && currentState.equals(TAIL_TX)) Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.WARN,TAIL_TX_DURATION +" vs. " + timeInTailState); assert timeInTailState==TAIL_TX_DURATION || currentState.equals(TAIL_RX) : "Assert2 SmartphoneCellularCommunicationEnergy"; // assert timeInTailState==TAIL_TX_DURATION || timeInTailState==TAIL_RX_DURATION : "Assert2 SmartphoneCellularCommunicationEnergy"; Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG, Simulator.getFormattedTime(Simulator.getCurrentTime()) + " " + ((EnergyModel) energyModel).getHost().getHostId() + " consumed " + (currentState.getEnergyConsumption() * (timeInTailState / (double) Simulator.SECOND_UNIT)) + " uJ in State " + currentState.getName() + " after spending " + (timeInTailState / (double) Simulator.SECOND_UNIT) + " sec there."); energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeInTailState)); tailCounter++; currentState = IDLE; lastStateChange = Simulator.getCurrentTime(); } } @Override public PhyType getPhyType() { return phy; } @Override public void send(long duration, Message msg, boolean isBroadcast) { if (currentState.equals(IDLE)) { /* * Consume the energy for being in the ramp state. There is not * explicit ramp state, because the node immediately sends the * message. However, the energy for the ramp state before sending is * consumed. */ energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(RAMP_TX, RAMP_TX_DURATION)); } else { assert currentState.equals(TAIL_RX) || currentState.equals(TAIL_TX); long timeInTailState = Simulator.getCurrentTime() - (lastStateChange + duration); Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG, Simulator.getFormattedTime(Simulator.getCurrentTime()) + " " + ((EnergyModel) energyModel).getHost().getHostId() + " consumed " + (currentState.getEnergyConsumption() * (timeInTailState / (double) Simulator.SECOND_UNIT)) + " uJ in State " + currentState.getName() + " after spending " + (timeInTailState / (double) Simulator.SECOND_UNIT) + " sec there before starting a transmission."); energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeInTailState)); tailCounter++; } /* * Consume the energy for the transmission of data. */ energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(TX, duration)); Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG, Simulator.getFormattedTime(Simulator.getCurrentTime()) + " " + ((EnergyModel) energyModel).getHost().getHostId() + " consumed " + (TX.getEnergyConsumption() * (duration / (double) Simulator.SECOND_UNIT)) + " uJ in State " + TX.getName() + " after spending " + (duration / (double) Simulator.SECOND_UNIT) + " sec there."); /* * Jump into the tail state and trigger the event to consume the energy * for the tail state after the given amount of time if no message must * be sent or received in the meantime. */ currentState = TAIL_TX; lastStateChange = Simulator.getCurrentTime(); Simulator.getScheduler().scheduleIn(TAIL_TX_DURATION, this, TAIL_TX, tailCounter); } @Override public void receive(long duration, Message msg, boolean isBroadcast, boolean isIntendedReceiver) { if(currentState.equals(IDLE)){ /* * Consume the energy for being in the ramp state. There is not * explicit ramp state, because the node immediately receives the * message. However, the energy for the ramp state before receiving * is consumed. */ energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(RAMP_RX, RAMP_RX_DURATION)); } else { assert currentState.equals(TAIL_RX) || currentState.equals(TAIL_TX); long timeInTailState = Simulator.getCurrentTime() + duration - lastStateChange; Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG,Simulator.getCurrentTime() + " " + ((EnergyModel) energyModel).getHost().getHostId() + " consumed " + (currentState.getEnergyConsumption() * (timeInTailState / (double) Simulator.SECOND_UNIT)) + " uJ in State " + currentState.getName() + " after spending " + (timeInTailState / (double) Simulator.SECOND_UNIT) + " sec there before receiving a message."); energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeInTailState)); tailCounter++; } /* * Consume the energy for the receiption of data. */ energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(RX, duration)); Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG,Simulator.getCurrentTime() + " " + ((EnergyModel) energyModel).getHost().getHostId() + " consumed " + (RX.getEnergyConsumption() * (duration / (double) Simulator.SECOND_UNIT)) + " uJ in State " + RX.getName() + " after spending " + (duration / (double) Simulator.SECOND_UNIT) + " sec there."); currentState = TAIL_RX; lastStateChange = Simulator.getCurrentTime(); Simulator.getScheduler().scheduleIn(TAIL_RX_DURATION, this, TAIL_RX, tailCounter); } @Override public void doFakeStateChange() { doStateChange(currentState); } private void doStateChange(EnergyState newState){ long timeSpentInState = Simulator.getCurrentTime() - lastStateChange; Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG,Simulator.getFormattedTime(Simulator.getCurrentTime()) + " " + ((EnergyModel) energyModel).getHost().getHostId() + " consumed " + (currentState.getEnergyConsumption() * (timeSpentInState/ (double) Simulator.SECOND_UNIT)) + " uJ in State " + currentState.getName() + " after spending " + (timeSpentInState / (double) Simulator.SECOND_UNIT) + " sec there."); energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeSpentInState)); currentState = newState; if(!currentState.equals(TAIL_RX) && !currentState.equals(TAIL_TX)) lastStateChange = Simulator.getCurrentTime(); } }