StatelessCommunicationComponent.java 6.37 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
29
import de.tud.kom.p2psim.impl.energy.DefaultEnergyState;
import de.tud.kom.p2psim.impl.energy.models.ModularEnergyModel;
30
31
32
33
34
35
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
168
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
236
237
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
 * 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() {
		if (energyModel.turnOn(this)) {
			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;
		energyModel.switchedState(this, currentState, newState,
				timeSpentInState);
		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
		energyModel.switchedState(this, ON, IDLE, timeHP);
		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();
	}

}