1 | package dk.deepthought.sidious.rules; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.Collection; |
5 | import java.util.Properties; |
6 | |
7 | import org.apache.commons.logging.Log; |
8 | import org.apache.commons.logging.LogFactory; |
9 | |
10 | import dk.deepthought.sidious.goalhandler.Goal; |
11 | import dk.deepthought.sidious.greenhouse.ClimaticState; |
12 | import dk.deepthought.sidious.greenhouse.SensorInput; |
13 | import dk.deepthought.sidious.services.ServiceEngine; |
14 | import dk.deepthought.sidious.supportsystem.State; |
15 | import dk.deepthought.sidious.supportsystem.Step; |
16 | import dk.deepthought.sidious.supportsystem.SuperLinkID; |
17 | import dk.deepthought.sidious.util.RuleProperty; |
18 | |
19 | /** |
20 | * This class represents the rule to facilitate a morning drop. |
21 | * <p> |
22 | * This rule will dictate a 5 to 6 degrees Celsius drop in temperature, starting |
23 | * approx. 30 min before sunrise, and maintaining this drop for two hours. |
24 | * |
25 | * @author Deepthought |
26 | * |
27 | */ |
28 | public class MorningDropRule extends Rule { |
29 | /** |
30 | * Logger for this class |
31 | */ |
32 | private static final Log logger = LogFactory.getLog(MorningDropRule.class); |
33 | |
34 | /** |
35 | * The RuleProperty of this class |
36 | */ |
37 | private static RuleProperty ruleProperty; |
38 | |
39 | /** |
40 | * The duration of the temperature drop. |
41 | */ |
42 | private final int dropDuration; |
43 | |
44 | /** |
45 | * Drop initialization time, in minutes before sunrise. |
46 | */ |
47 | private final int minutesBeforeSunrise; |
48 | |
49 | /** |
50 | * The target degrees of the drop. |
51 | */ |
52 | private final double dropTarget; |
53 | |
54 | /** |
55 | * The ID of the time sensor this Rule depends on. |
56 | */ |
57 | private final SuperLinkID timeSensorID; |
58 | |
59 | /** |
60 | * The ID of the temperature sensor this Rule depends on. |
61 | */ |
62 | private final SuperLinkID temperatureSensorID; |
63 | |
64 | /** |
65 | * The time of sunrise, represented in min after midnight. |
66 | * <p> |
67 | * XXX Should be retrieved from an external calendar/forecast. |
68 | */ |
69 | private static final int sunrise = 360; // 6 o'clock |
70 | |
71 | /** |
72 | * Constructor. |
73 | * |
74 | * @param parentID |
75 | * the id of the parent <code>PlanRequester</code> |
76 | */ |
77 | public MorningDropRule(final SuperLinkID parentID) { |
78 | if (parentID == null) { |
79 | logger.error("MorningDropRule(SuperLinkID parentID=null) " |
80 | + "- null not valid input"); |
81 | throw new IllegalArgumentException("null not valid ID"); |
82 | } |
83 | if (ruleProperty == null) { |
84 | ruleProperty = new RuleProperty(this.getClass().getSimpleName()); |
85 | } |
86 | timeSensorID = ruleProperty.getID("time_sensor_id"); |
87 | temperatureSensorID = ruleProperty.getID("temperature_sensor_id"); |
88 | dropTarget = ruleProperty.getFloat("dropTarget", 14f); |
89 | dropDuration = ruleProperty.getInt("dropDuration", 120); |
90 | minutesBeforeSunrise = ruleProperty.getInt("minutesBeforeSunrise", 30); |
91 | setParentID(parentID); |
92 | } |
93 | |
94 | /** |
95 | * Static factory for constructing a MorningDropRule with the specified |
96 | * properties. |
97 | * |
98 | * @param parentID |
99 | * the id of the parent <code>PlanRequester</code> |
100 | * @param properties |
101 | * the properties |
102 | * @return a new MorningDropRule from the given properties |
103 | */ |
104 | public static MorningDropRule constructMorningDropRule( |
105 | final SuperLinkID parentID, Properties properties) { |
106 | ruleProperty = new RuleProperty(properties); |
107 | return new MorningDropRule(parentID); |
108 | } |
109 | |
110 | /* |
111 | * (non-Javadoc) |
112 | * |
113 | * @see dk.deepthought.sidious.rules.Rule#desire(dk.deepthought.sidious.supportsystem.State, |
114 | * dk.deepthought.sidious.supportsystem.State) |
115 | */ |
116 | public double desire(State currentState, State newState, Step step) { |
117 | int newTime = (int) getSensorValue(newState, timeSensorID); |
118 | double newTemperature = getSensorValue(newState, temperatureSensorID); |
119 | if (newTime > sunrise - minutesBeforeSunrise |
120 | && newTime < sunrise + (dropDuration - minutesBeforeSunrise)) { |
121 | double desireValue = ((newTemperature - dropTarget) / dropTarget); |
122 | if (desireValue > 1) { |
123 | desireValue = 1; |
124 | } else if (desireValue < 0) { |
125 | desireValue = 0; |
126 | } |
127 | return desireValue; |
128 | } |
129 | return 0; |
130 | } |
131 | |
132 | /* |
133 | * (non-Javadoc) |
134 | * |
135 | * @see dk.deepthought.sidious.rules.Rule#getGoals() |
136 | */ |
137 | public Collection<Goal> getGoals() { |
138 | SensorInput temperatureGoal = new SensorInput(temperatureSensorID, |
139 | dropTarget); |
140 | ArrayList<SensorInput> sensors = new ArrayList<SensorInput>(); |
141 | sensors.add(temperatureGoal); |
142 | ClimaticState goalClima = new ClimaticState(sensors); |
143 | Goal goal = new Goal(goalClima, desire(goalClima, ServiceEngine |
144 | .getCurrentState(), null), getParentID()); |
145 | ArrayList<Goal> goals = new ArrayList<Goal>(); |
146 | goals.add(goal); |
147 | return goals; |
148 | } |
149 | |
150 | } |