1 | package dk.deepthought.sidious.greenhouse; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.Collection; |
5 | |
6 | import net.jcip.annotations.Immutable; |
7 | |
8 | import org.apache.commons.logging.Log; |
9 | import org.apache.commons.logging.LogFactory; |
10 | |
11 | import dk.deepthought.sidious.supportsystem.Adjustable; |
12 | import dk.deepthought.sidious.supportsystem.State; |
13 | import dk.deepthought.sidious.supportsystem.SuperLinkID; |
14 | import dk.deepthought.sidious.supportsystem.SystemSettings; |
15 | |
16 | /** |
17 | * This class implements the abstraction of a setpoint of the heater. |
18 | * |
19 | * @author Deepthought |
20 | * |
21 | */ |
22 | @Immutable |
23 | public final class HeaterSetPoint implements Adjustable { |
24 | |
25 | private static final Log logger = LogFactory.getLog(HeaterSetPoint.class); |
26 | |
27 | /** |
28 | * The setting of this setpoint. |
29 | */ |
30 | private final double setting; |
31 | |
32 | /** |
33 | * Id of the temperature sensor. |
34 | */ |
35 | private final SuperLinkID temperatureID; |
36 | |
37 | /** |
38 | * Id of the humidity sensor. |
39 | */ |
40 | private final SuperLinkID humidityID; |
41 | |
42 | private static final double FACTOR_PER_MINUTE = 0.1; |
43 | |
44 | /** |
45 | * Internal enum to describe possible adjustments. |
46 | */ |
47 | private enum HeaterStep { |
48 | UP(1f), DOWN(-1f); |
49 | |
50 | private double increment; |
51 | |
52 | HeaterStep(double increment) { |
53 | this.increment = increment; |
54 | } |
55 | |
56 | public double getIncrement() { |
57 | return increment; |
58 | } |
59 | } |
60 | |
61 | /** |
62 | * Creates a new <code>HeaterSetPoint</code> with the specified setting. |
63 | * |
64 | * @param setting |
65 | * the setting |
66 | */ |
67 | public HeaterSetPoint(final double setting) { |
68 | humidityID = SystemSettings.getHumidityID(); |
69 | temperatureID = SystemSettings.getTemperatureID(); |
70 | this.setting = setting; |
71 | } |
72 | |
73 | /* |
74 | * (non-Javadoc) |
75 | * |
76 | * @see dk.deepthought.sidious.supportsystem.Adjustable#consequence(dk.deepthought.sidious.supportsystem.State, |
77 | * dk.deepthought.sidious.supportsystem.Step) |
78 | */ |
79 | public State consequence(State state) { |
80 | if (logger.isDebugEnabled()) { |
81 | logger.debug("consequence(State state=" + state |
82 | + ") - start - setting=" + setting); |
83 | } |
84 | if (!(state instanceof ClimaticState)) { |
85 | String fail = "Input state must be a climatic state. - state=" + state; |
86 | logger.error(fail); |
87 | throw new IllegalArgumentException(fail); |
88 | } |
89 | int timestep = SystemSettings.getTimestep(); |
90 | ClimaticState climaticState = (ClimaticState) state; |
91 | Collection<SensorInput> sensors = climaticState.getSensors(); |
92 | Collection<SensorInput> newSensors = new ArrayList<SensorInput>(); |
93 | // When temperature increases, humidity decreases |
94 | for (SensorInput input : sensors) { |
95 | if (input.getID().equals(temperatureID)) { |
96 | double temperature = input.getValue(); |
97 | double delta = setting - temperature; |
98 | double newValue = temperature + timestep * FACTOR_PER_MINUTE |
99 | * delta; |
100 | newSensors.add(input.newInstanceWithNewValue(newValue)); |
101 | } else if (input.getID().equals(humidityID)) { |
102 | double decreaseFactor = decreaseFactor(input.getValue()); |
103 | newSensors.add(input.newInstanceWithNewValue(decreaseFactor)); |
104 | } else { |
105 | newSensors.add(input); |
106 | } |
107 | } |
108 | State returnState = new ClimaticState(newSensors); |
109 | if (logger.isDebugEnabled()) { |
110 | logger.debug("consequence(State state=" + state |
111 | + ") - end - return value=" + returnState); |
112 | } |
113 | return returnState; |
114 | } |
115 | |
116 | /** |
117 | * Calculates the humidity decrease factor with respect to the increase in |
118 | * temperature. |
119 | * |
120 | * @param humidity |
121 | * value of humidity |
122 | * @return the decrease factor |
123 | */ |
124 | private double decreaseFactor(double humidity) { |
125 | //FIXME WTF?!? |
126 | //Vi sammenligner humidity med setting af heater?!? |
127 | double delta = setting - humidity; |
128 | double factor = -delta * 0.01 + humidity; |
129 | return factor; |
130 | } |
131 | |
132 | /* |
133 | * (non-Javadoc) |
134 | * |
135 | * @see dk.deepthought.sidious.supportsystem.Adjustable#possibleAdjustments() |
136 | */ |
137 | public Collection<Adjustable> possibleAdjustments() { |
138 | if (logger.isDebugEnabled()) { |
139 | logger.debug("possibleAdjustments() - start"); |
140 | } |
141 | |
142 | Collection<Adjustable> setpoints = new ArrayList<Adjustable>(); |
143 | for (HeaterStep possibleDirection : HeaterStep.values()) { |
144 | double result = setting + possibleDirection.getIncrement(); |
145 | assert result != Float.MAX_VALUE : "result exceeded Float.MAX_VALUE"; |
146 | setpoints.add(new HeaterSetPoint(result)); |
147 | } |
148 | logger.debug(setpoints.size() + " possible adjustments created"); |
149 | return setpoints; |
150 | } |
151 | |
152 | /* |
153 | * (non-Javadoc) |
154 | * |
155 | * @see dk.deepthought.sidious.supportsystem.Adjustable#getID() |
156 | */ |
157 | public SuperLinkID getID() { |
158 | return SystemSettings.getHeaterSetPointID(); |
159 | } |
160 | |
161 | /* |
162 | * (non-Javadoc) |
163 | * |
164 | * @see dk.deepthought.sidious.supportsystem.Adjustable#getSetting() |
165 | */ |
166 | public double getSetting() { |
167 | return setting; |
168 | } |
169 | |
170 | |
171 | |
172 | /* (non-Javadoc) |
173 | * @see java.lang.Object#hashCode() |
174 | */ |
175 | @Override |
176 | public int hashCode() { |
177 | final int PRIME = 31; |
178 | int result = 1; |
179 | long temp; |
180 | temp = Double.doubleToLongBits(setting); |
181 | result = PRIME * result + (int) (temp ^ (temp >>> 32)); |
182 | return result; |
183 | } |
184 | |
185 | /* (non-Javadoc) |
186 | * @see java.lang.Object#equals(java.lang.Object) |
187 | */ |
188 | @Override |
189 | public boolean equals(Object obj) { |
190 | if (this == obj) |
191 | return true; |
192 | if (obj == null) |
193 | return false; |
194 | if (getClass() != obj.getClass()) |
195 | return false; |
196 | final HeaterSetPoint other = (HeaterSetPoint) obj; |
197 | if (Double.doubleToLongBits(setting) != Double.doubleToLongBits(other.setting)) |
198 | return false; |
199 | return true; |
200 | } |
201 | |
202 | /* |
203 | * (non-Javadoc) |
204 | * |
205 | * @see java.lang.Object#toString() |
206 | */ |
207 | @Override |
208 | public String toString() { |
209 | return getClass().getSimpleName() + "[setting=" + setting + "]"; |
210 | } |
211 | |
212 | } |