001 package dk.deepthought.sidious.rules;
002
003 import java.util.ArrayList;
004 import java.util.Collection;
005 import java.util.Properties;
006
007 import org.apache.commons.logging.Log;
008 import org.apache.commons.logging.LogFactory;
009
010 import dk.deepthought.sidious.goalhandler.Goal;
011 import dk.deepthought.sidious.greenhouse.ClimaticState;
012 import dk.deepthought.sidious.greenhouse.SensorInput;
013 import dk.deepthought.sidious.services.ServiceEngine;
014 import dk.deepthought.sidious.supportsystem.State;
015 import dk.deepthought.sidious.supportsystem.Step;
016 import dk.deepthought.sidious.supportsystem.SuperLinkID;
017 import dk.deepthought.sidious.util.RuleProperty;
018
019 /**
020 * This class represents the rule to facilitate a morning drop.
021 * <p>
022 * This rule will dictate a 5 to 6 degrees Celsius drop in temperature, starting
023 * approx. 30 min before sunrise, and maintaining this drop for two hours.
024 *
025 * @author Deepthought
026 *
027 */
028 public class MorningDropRule extends Rule {
029 /**
030 * Logger for this class
031 */
032 private static final Log logger = LogFactory.getLog(MorningDropRule.class);
033
034 /**
035 * The RuleProperty of this class
036 */
037 private static RuleProperty ruleProperty;
038
039 /**
040 * The duration of the temperature drop.
041 */
042 private final int dropDuration;
043
044 /**
045 * Drop initialization time, in minutes before sunrise.
046 */
047 private final int minutesBeforeSunrise;
048
049 /**
050 * The target degrees of the drop.
051 */
052 private final double dropTarget;
053
054 /**
055 * The ID of the time sensor this Rule depends on.
056 */
057 private final SuperLinkID timeSensorID;
058
059 /**
060 * The ID of the temperature sensor this Rule depends on.
061 */
062 private final SuperLinkID temperatureSensorID;
063
064 /**
065 * The time of sunrise, represented in min after midnight.
066 * <p>
067 * XXX Should be retrieved from an external calendar/forecast.
068 */
069 private static final int sunrise = 360; // 6 o'clock
070
071 /**
072 * Constructor.
073 *
074 * @param parentID
075 * the id of the parent <code>PlanRequester</code>
076 */
077 public MorningDropRule(final SuperLinkID parentID) {
078 if (parentID == null) {
079 logger.error("MorningDropRule(SuperLinkID parentID=null) "
080 + "- null not valid input");
081 throw new IllegalArgumentException("null not valid ID");
082 }
083 if (ruleProperty == null) {
084 ruleProperty = new RuleProperty(this.getClass().getSimpleName());
085 }
086 timeSensorID = ruleProperty.getID("time_sensor_id");
087 temperatureSensorID = ruleProperty.getID("temperature_sensor_id");
088 dropTarget = ruleProperty.getFloat("dropTarget", 14f);
089 dropDuration = ruleProperty.getInt("dropDuration", 120);
090 minutesBeforeSunrise = ruleProperty.getInt("minutesBeforeSunrise", 30);
091 setParentID(parentID);
092 }
093
094 /**
095 * Static factory for constructing a MorningDropRule with the specified
096 * properties.
097 *
098 * @param parentID
099 * 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 }
|