StatelessCommunicationComponent.java 6.39 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * 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 <http://www.gnu.org/licenses/>.
 *
 */

21
package de.tud.kom.p2psim.impl.energy.components;
22
23
24
25
26
27

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.EnergyState;
import de.tud.kom.p2psim.api.linklayer.mac.PhyType;
28
import de.tud.kom.p2psim.impl.energy.DefaultEnergyState;
29
30
31
32
33
34
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.
35
 * In the context of the {@link StateSwitchingEnergyModel} we mimic a state-aware
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
 * behavior. Please take a look at the comment in the Constructor if your
 * analyzers seem to return odd results with this component...
 * 
 * @author Bjoern Richerzhagen
 * @version 1.0, 27.02.2012
 */
public class StatelessCommunicationComponent implements
		EnergyCommunicationComponent {

	private PhyType phy;

	private EnergyEventListener energyModel;

	/**
	 * States supported by this component
	 */
	private final EnergyState ON, IDLE, OFF;

	private EnergyState currentState;

	private long lastStateChange;

	/*
	 * Parameters in µW as proposed by Feeney
	 */

	private double m_send = 1.89;

	private double b_send = 246;

	private double m_recv = 0.494;

	private double b_recv = 56.1;

	private double m_discard = -0.49;

	private double b_discard = 97.2;

	// private double m_recv_promise = 0.388;

	// private double b_recv_promise = 136;

	private double b_sendctl = 120;

	private double b_recvctl = 29;

	/**
	 * Create a stateless Component
	 * 
	 * @param phy
	 */
	public StatelessCommunicationComponent(PhyType phy) {
		this.phy = phy;

		double baseline = 808000; // 808mW as proposed by Feeney
		/*
		 * To explain the 1000 in ON-State: We want to use the Feeney model
		 * inside the State-Based models. As a state has a fixed energy
		 * consumption assigned with it we have to alter the time the component
		 * spent in the state in order to get a message-size related behavior.
		 * We calculate the energy message based and then normalize it with the
		 * energy value in this state to get the time we have to pass to the
		 * energyModel. The component is all the time in idle, we use the
		 * virtual time trick to add ON-Energy
		 * 
		 * Of course, it makes no sense to analyze the timing-values for this
		 * component - if we have no real states, we have no real time spent
		 * inside a state...
		 */
		ON = new DefaultEnergyState("ON", 1000);
		IDLE = new DefaultEnergyState("IDLE", baseline);
		OFF = new DefaultEnergyState("OFF", 0);

		this.currentState = IDLE;
		this.lastStateChange = Time.getCurrentTime();
	}

	@Override
	public void turnOff() {
		if (!currentState.equals(OFF)) {
			doStateChange(OFF);
		}
	}

	@Override
	public boolean turnOn() {
122
		if (energyModel.componentCanBeActivated(this)) {
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
			if (!currentState.equals(IDLE)) {
				doStateChange(IDLE);
			}
			return true;
		}
		return false;
	}

	@Override
	public boolean isOn() {
		return !currentState.equals(OFF);
	}

	private void doStateChange(EnergyState newState) {
		long timeSpentInState = Time.getCurrentTime() - lastStateChange;
138
		energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(currentState, timeSpentInState));
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
		currentState = newState;
		lastStateChange = Time.getCurrentTime();
	}

	/**
	 * Just to ensure that the energy calculation is correct, once you rely on
	 * the energy level in an analyzer you should call this method prior to
	 * querying the battery.
	 */
	public void doFakeStateChange() {
		doStateChange(currentState);
	}

	/**
	 * This is used to translate an absolute energy consumption into some kind
	 * of state * time like consumption (IDLE -> ACTIVE -> IDLE)
	 * 
	 * @param energyConsumed
	 */
	private void simulateHighPowerState(double energyConsumed) {
		long timeHP = (long) (energyConsumed * Time.SECOND / ON
				.getEnergyConsumption());

		// System.out.println("Simulated HP-Time would be " + timeHP);

		// switch to HP for zero seconds :)
		doStateChange(ON);

		// switch back to IDLE with fake timeHP
168
		energyModel.componentConsumedEnergy(this, calculateEnergyConsumation(ON, timeHP));
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
		currentState = IDLE;
		lastStateChange = Time.getCurrentTime();
	}

	@Override
	public void receive(long duration, Message msg, boolean isBroadcast,
			boolean isIntendedReceiver) {

		assert !currentState.equals(OFF);
		double consumedEnergy = 0;
		if (isBroadcast) {
			consumedEnergy = m_recv * msg.getSize() + b_recv;
		} else if (isIntendedReceiver) {
			// Paper: Equation 4
			consumedEnergy = b_recvctl + b_sendctl + m_recv * msg.getSize()
					+ b_recv + b_sendctl;
		} else {
			// Paper: Equation 5
			consumedEnergy = b_recvctl + b_sendctl + m_discard * msg.getSize()
					+ b_discard + b_sendctl;
		}

		simulateHighPowerState(consumedEnergy);
	}

	@Override
	public void send(long duration, Message msg, boolean isBroadcast) {

		assert !currentState.equals(OFF);
		double consumedEnergy = 0;
		if (isBroadcast) {
			consumedEnergy = m_send * msg.getSize() + b_send;
		} else {
			// Paper: Equation 3
			consumedEnergy = b_sendctl + b_recvctl + m_send * msg.getSize()
					+ b_send + b_recvctl;
		}

		simulateHighPowerState(consumedEnergy);
	}

	@Override
	public ComponentType getType() {
		return ComponentType.COMMUNICATION;
	}

	@Override
	public PhyType getPhyType() {
		return phy;
	}

	@Override
	public void setEnergyEventListener(EnergyEventListener listener) {
		energyModel = listener;
	}

	@Override
	public void eventOccurred(Object content, int type) {
		// will not happen
	}

	@Override
	public String toString() {
		return phy.toString();
	}

}