]> git.basschouten.com Git - openhab-addons.git/blob
3fa2251c00c78aec31318faf6d7b10bc3a74c78f
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.ecobee.internal.action;
14
15 import java.util.Date;
16 import java.util.HashMap;
17 import java.util.Map;
18
19 import javax.measure.quantity.Temperature;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.ecobee.internal.dto.thermostat.EventDTO;
24 import org.openhab.binding.ecobee.internal.enums.AckType;
25 import org.openhab.binding.ecobee.internal.enums.FanMode;
26 import org.openhab.binding.ecobee.internal.enums.HoldType;
27 import org.openhab.binding.ecobee.internal.enums.PlugState;
28 import org.openhab.binding.ecobee.internal.enums.VentilatorMode;
29 import org.openhab.binding.ecobee.internal.function.AcknowledgeFunction;
30 import org.openhab.binding.ecobee.internal.function.ControlPlugFunction;
31 import org.openhab.binding.ecobee.internal.function.CreateVacationFunction;
32 import org.openhab.binding.ecobee.internal.function.DeleteVacationFunction;
33 import org.openhab.binding.ecobee.internal.function.ResetPreferencesFunction;
34 import org.openhab.binding.ecobee.internal.function.ResumeProgramFunction;
35 import org.openhab.binding.ecobee.internal.function.SendMessageFunction;
36 import org.openhab.binding.ecobee.internal.function.SetHoldFunction;
37 import org.openhab.binding.ecobee.internal.function.SetOccupiedFunction;
38 import org.openhab.binding.ecobee.internal.function.UpdateSensorFunction;
39 import org.openhab.binding.ecobee.internal.handler.EcobeeThermostatBridgeHandler;
40 import org.openhab.binding.ecobee.internal.handler.EcobeeUtils;
41 import org.openhab.core.automation.annotation.ActionInput;
42 import org.openhab.core.automation.annotation.ActionOutput;
43 import org.openhab.core.automation.annotation.RuleAction;
44 import org.openhab.core.library.types.QuantityType;
45 import org.openhab.core.thing.binding.ThingActions;
46 import org.openhab.core.thing.binding.ThingActionsScope;
47 import org.openhab.core.thing.binding.ThingHandler;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 /**
52  * The {@link EcobeeActions} defines the thing actions for the Ecobee binding.
53  *
54  * @author John Cocula - Initial contribution
55  * @author Mark Hilbush - Adapted for OH2/3
56  * @author Connor Petty - Proxy method for invoking actions
57  */
58 @ThingActionsScope(name = "ecobee")
59 @NonNullByDefault
60 public class EcobeeActions implements ThingActions {
61
62     private static final Logger LOGGER = LoggerFactory.getLogger(EcobeeActions.class);
63
64     private @Nullable EcobeeThermostatBridgeHandler handler;
65
66     public EcobeeActions() {
67         LOGGER.debug("EcobeeActions: EcobeeActions: Actions service created");
68     }
69
70     @Override
71     public void setThingHandler(@Nullable ThingHandler handler) {
72         if (handler instanceof EcobeeThermostatBridgeHandler) {
73             this.handler = (EcobeeThermostatBridgeHandler) handler;
74         }
75     }
76
77     @Override
78     public @Nullable ThingHandler getThingHandler() {
79         return handler;
80     }
81
82     /**
83      * The acknowledge function allows an alert to be acknowledged.
84      *
85      * @see <a
86      *      href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/Acknowledge.shtml">Acknowledge
87      *      </a>
88      */
89     @RuleAction(label = "acknowledge an alert", description = "Acknowledges an alert.")
90     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean acknowledge(
91             @ActionInput(name = "ackRef", description = "The acknowledge ref of alert") @Nullable String ackRef,
92             @ActionInput(name = "ackType", description = "The type of acknowledgement. Valid values: accept, decline, defer, unacknowledged") @Nullable String ackType,
93             @ActionInput(name = "remindMeLater", description = "(opt) Whether to remind at a later date, if this is a defer acknowledgement") @Nullable Boolean remindMeLater) {
94         LOGGER.debug("EcobeeActions: Action 'Acknowledge' called");
95         EcobeeThermostatBridgeHandler localHandler = handler;
96         if (localHandler == null) {
97             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
98             return false;
99         }
100         AcknowledgeFunction function = new AcknowledgeFunction(localHandler.getThermostatId(), ackRef,
101                 AckType.forValue(ackType), remindMeLater);
102         return localHandler.actionPerformFunction(function);
103     }
104
105     public static boolean acknowledge(ThingActions actions, @Nullable String ackRef, @Nullable String ackType,
106             @Nullable Boolean remindMeLater) {
107         return ((EcobeeActions) actions).acknowledge(ackRef, ackType, remindMeLater);
108     }
109
110     /**
111      * Control the on/off state of a plug by setting a hold on the plug.
112      *
113      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/ControlPlug.shtml">Control
114      *      Plug</a>
115      */
116     @RuleAction(label = "control a plug", description = "Control the on/off state of a plug by setting a hold on the plug.")
117     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean controlPlug(
118             @ActionInput(name = "plugName", description = "The name of the plug. Ensure each plug has a unique name.") @Nullable String plugName,
119             @ActionInput(name = "plugState", description = "The state to put the plug into. Valid values: on, off, resume.") @Nullable String plugState,
120             @ActionInput(name = "startDateTime", description = "(opt) The start date/time in thermostat time.") @Nullable Date startDateTime,
121             @ActionInput(name = "endDateTime", description = "(opt) The end date/time in thermostat time.") @Nullable Date endDateTime,
122             @ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
123             @ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours) {
124         LOGGER.debug("EcobeeActions: Action 'Control Plug' called");
125         EcobeeThermostatBridgeHandler localHandler = handler;
126         if (localHandler == null) {
127             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
128             return false;
129         }
130         ControlPlugFunction function = (new ControlPlugFunction(plugName, PlugState.forValue(plugState), startDateTime,
131                 endDateTime, (holdType == null) ? null : HoldType.forValue(holdType),
132                 (holdHours == null) ? null : Integer.valueOf(holdHours.intValue())));
133         return localHandler.actionPerformFunction(function);
134     }
135
136     public static boolean controlPlug(ThingActions actions, @Nullable String plugName, @Nullable String plugState,
137             @Nullable Date startDateTime, @Nullable Date endDateTime, @Nullable String holdType,
138             @Nullable Number holdHours) {
139         return ((EcobeeActions) actions).controlPlug(plugName, plugState, startDateTime, endDateTime, holdType,
140                 holdHours);
141     }
142
143     /**
144      * The create vacation function creates a vacation event on the thermostat.
145      *
146      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/CreateVacation.shtml">Create
147      *      Vacation</a>
148      */
149     @RuleAction(label = "create a vacation", description = "The create vacation function creates a vacation event on the thermostat.")
150     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean createVacation(
151             @ActionInput(name = "name", description = "The vacation event name. It must be unique.") @Nullable String name,
152             @ActionInput(name = "coolHoldTemp", description = "The temperature at which to set the cool vacation hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
153             @ActionInput(name = "heatHoldTemp", description = "The temperature at which to set the heat vacation hold.") @Nullable QuantityType<Temperature> heatHoldTemp,
154             @ActionInput(name = "startDateTime", description = "(opt) The start date/time in thermostat time.") @Nullable Date startDateTime,
155             @ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime,
156             @ActionInput(name = "fan", description = "(opt) The fan mode during the vacation. Values: auto, on Default: auto") @Nullable String fan,
157             @ActionInput(name = "fanMinOnTime", description = "(opt) The minimum number of minutes to run the fan each hour. Range: 0-60, Default: 0") @Nullable Number fanMinOnTime) {
158         LOGGER.debug("EcobeeActions: Action 'Create Vacation' called");
159         EcobeeThermostatBridgeHandler localHandler = handler;
160         if (localHandler == null) {
161             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
162             return false;
163         }
164         CreateVacationFunction function = new CreateVacationFunction(name, coolHoldTemp, heatHoldTemp, startDateTime,
165                 endDateTime, (fan == null) ? null : FanMode.forValue(fan),
166                 (fanMinOnTime == null) ? null : Integer.valueOf(fanMinOnTime.intValue()));
167         return localHandler.actionPerformFunction(function);
168     }
169
170     public static boolean createVacation(ThingActions actions, @Nullable String name,
171             @Nullable QuantityType<Temperature> coolHoldTemp, @Nullable QuantityType<Temperature> heatHoldTemp,
172             @Nullable Date startDateTime, @Nullable Date endDateTime, @Nullable String fan,
173             @Nullable Number fanMinOnTime) {
174         return ((EcobeeActions) actions).createVacation(name, coolHoldTemp, heatHoldTemp, startDateTime, endDateTime,
175                 fan, fanMinOnTime);
176     }
177
178     /**
179      * The delete vacation function deletes a vacation event from a thermostat.
180      *
181      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/DeleteVacation.shtml">Delete
182      *      Vacation</a>
183      */
184     @RuleAction(label = "delete a vacation", description = "The delete vacation function deletes a vacation event from a thermostat.")
185     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean deleteVacation(
186             @ActionInput(name = "name", description = "The vacation event name to delete.") @Nullable String name) {
187         LOGGER.debug("EcobeeActions: Action 'Delete Vacation' called");
188         EcobeeThermostatBridgeHandler localHandler = handler;
189         if (localHandler == null) {
190             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
191             return false;
192         }
193         DeleteVacationFunction function = new DeleteVacationFunction(name);
194         return localHandler.actionPerformFunction(function);
195     }
196
197     public static boolean deleteVacation(ThingActions actions, @Nullable String name) {
198         return ((EcobeeActions) actions).deleteVacation(name);
199     }
200
201     /**
202      * The reset preferences function sets all of the user configurable settings back to the factory default values.
203      *
204      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/ResetPreferences.shtml">Reset
205      *      Preferences</a>
206      */
207     @RuleAction(label = "reset the preferences", description = "The reset preferences function sets all of the user configurable settings back to the factory default values.")
208     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean resetPreferences() {
209         LOGGER.debug("EcobeeActions: Action 'Reset Preferences' called");
210         EcobeeThermostatBridgeHandler localHandler = handler;
211         if (localHandler == null) {
212             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
213             return false;
214         }
215         ResetPreferencesFunction function = new ResetPreferencesFunction();
216         return localHandler.actionPerformFunction(function);
217     }
218
219     public static boolean resetPreferences(ThingActions actions) {
220         return ((EcobeeActions) actions).resetPreferences();
221     }
222
223     /**
224      * The resume program function removes the currently running event.
225      *
226      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/ResumeProgram.shtml">Resume
227      *      Program</a>
228      */
229     @RuleAction(label = "resume the program", description = "Removes the currently running event providing the event is not a mandatory demand response event")
230     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean resumeProgram(
231             @ActionInput(name = "resumeAll", description = "(opt) Should the thermostat be resumed to next event (false) or to its program (true)") @Nullable Boolean resumeAll) {
232         LOGGER.debug("EcobeeActions: Action 'Resume Program' called");
233         EcobeeThermostatBridgeHandler localHandler = handler;
234         if (localHandler == null) {
235             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
236             return false;
237         }
238         ResumeProgramFunction function = new ResumeProgramFunction(resumeAll);
239         return localHandler.actionPerformFunction(function);
240     }
241
242     public static boolean resumeProgram(ThingActions actions, @Nullable Boolean resumeAll) {
243         return ((EcobeeActions) actions).resumeProgram(resumeAll);
244     }
245
246     /**
247      * The send message function allows an alert message to be sent to the thermostat.
248      *
249      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/SendMessage.shtml">Send
250      *      Message</a>
251      */
252     @RuleAction(label = "send a message", description = "The send message function allows an alert message to be sent to the thermostat.")
253     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendMessage(
254             @ActionInput(name = "text", description = "The message text to send. Text will be truncated to 500 characters if longer") @Nullable String text) {
255         LOGGER.debug("EcobeeActions: Action 'SendMessage' called");
256         EcobeeThermostatBridgeHandler localHandler = handler;
257         if (localHandler == null) {
258             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
259             return false;
260         }
261         SendMessageFunction function = new SendMessageFunction(text);
262         return localHandler.actionPerformFunction(function);
263     }
264
265     public static boolean sendMessage(ThingActions actions, @Nullable String text) {
266         return ((EcobeeActions) actions).sendMessage(text);
267     }
268
269     /**
270      * Set an indefinite hold using the supplied the cool and heat hold temperatures
271      *
272      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/SetHold.shtml">Set Hold</a>
273      */
274     @RuleAction(label = "set the thermostat into hold", description = "The set hold function sets the thermostat into a hold with the specified temperatures.")
275     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
276             @ActionInput(name = "coolHoldTemp", description = "The temperature at which to set the cool hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
277             @ActionInput(name = "heatHoldTemp", description = "The temperature at which to set the heat hold.") @Nullable QuantityType<Temperature> heatHoldTemp) {
278         if (coolHoldTemp == null || heatHoldTemp == null) {
279             throw new IllegalArgumentException("hold temperatures cannot be null");
280         }
281         Map<String, Object> params = new HashMap<String, Object>();
282         params.put("coolHoldTemp", coolHoldTemp);
283         params.put("heatHoldTemp", heatHoldTemp);
284         return setHold(params, null, null, null, null);
285     }
286
287     public static boolean setHold(ThingActions actions, @Nullable QuantityType<Temperature> coolHoldTemp,
288             @Nullable QuantityType<Temperature> heatHoldTemp) {
289         return ((EcobeeActions) actions).setHold(coolHoldTemp, heatHoldTemp);
290     }
291
292     /**
293      * Set a hold by providing the cool and heat temperatures and the number of hours.
294      */
295     @RuleAction(label = "set the thermostat into hold", description = "The set hold function sets the thermostat into a hold for the specified number of hours.")
296     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
297             @ActionInput(name = "coolHoldTemp", description = "The temperature at which to set the cool hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
298             @ActionInput(name = "heatHoldTemp", description = "The temperature at which to set the heat hold.") @Nullable QuantityType<Temperature> heatHoldTemp,
299             @ActionInput(name = "holdHours", description = "The number of hours for the hold.") @Nullable Number holdHours) {
300         if (coolHoldTemp == null || heatHoldTemp == null) {
301             throw new IllegalArgumentException("hold temperatures cannot be null");
302         }
303         if (holdHours == null) {
304             throw new IllegalArgumentException("number of hold hours is missing");
305         }
306         Map<String, Object> params = new HashMap<String, Object>();
307         params.put("coolHoldTemp", coolHoldTemp);
308         params.put("heatHoldTemp", heatHoldTemp);
309         return setHold(params, HoldType.HOLD_HOURS.toString(), holdHours, null, null);
310     }
311
312     public static boolean setHold(ThingActions actions, @Nullable QuantityType<Temperature> coolHoldTemp,
313             @Nullable QuantityType<Temperature> heatHoldTemp, @Nullable Number holdHours) {
314         return ((EcobeeActions) actions).setHold(coolHoldTemp, heatHoldTemp, holdHours);
315     }
316
317     /**
318      * Set an indefinite hold using the supplied climateRef
319      */
320     @RuleAction(label = "set the thermostat into hold", description = "The set hold function sets the thermostat into a hold with the specified climate ref.")
321     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
322             @ActionInput(name = "holdClimateRef", description = "The holdClimateRef used to set the hold.") @Nullable String holdClimateRef) {
323         EcobeeThermostatBridgeHandler localHandler = handler;
324         if (localHandler == null) {
325             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
326             return false;
327         }
328         if (holdClimateRef == null || !localHandler.isValidClimateRef(holdClimateRef)) {
329             throw new IllegalArgumentException("hold climate ref is missing or invalid");
330         }
331         Map<String, Object> params = new HashMap<String, Object>();
332         params.put("holdClimateRef", holdClimateRef);
333         return setHold(params, null, null, null, null);
334     }
335
336     public static boolean setHold(ThingActions actions, @Nullable String holdClimateRef) {
337         return ((EcobeeActions) actions).setHold(holdClimateRef);
338     }
339
340     /**
341      * Set a hold using the supplied climateRef for the supplied number of hours.
342      */
343     @RuleAction(label = "set the thermostat into hold", description = "The set hold function sets the thermostat into a hold with the specified climate ref.")
344     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
345             @ActionInput(name = "holdClimateRef", description = "The holdClimateRef used to set the hold.") @Nullable String holdClimateRef,
346             @ActionInput(name = "holdHours", description = "The number of hours for the hold.") @Nullable Number holdHours) {
347         if (holdHours == null) {
348             throw new IllegalArgumentException("number of hold hours is missing");
349         }
350         EcobeeThermostatBridgeHandler localHandler = handler;
351         if (localHandler == null) {
352             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
353             return false;
354         }
355         if (holdClimateRef == null || !localHandler.isValidClimateRef(holdClimateRef)) {
356             throw new IllegalArgumentException("hold climate ref is missing or invalid");
357         }
358         Map<String, Object> params = new HashMap<String, Object>();
359         params.put("holdClimateRef", holdClimateRef);
360         return setHold(params, HoldType.HOLD_HOURS.toString(), holdHours, null, null);
361     }
362
363     public static boolean setHold(ThingActions actions, @Nullable String holdClimateRef, @Nullable Number holdHours) {
364         return ((EcobeeActions) actions).setHold(holdClimateRef, holdHours);
365     }
366
367     /**
368      * Set a hold
369      */
370     @RuleAction(label = "set the thermostat into hold", description = "The set hold function sets the thermostat into a hold with the specified temperature or climate ref.")
371     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
372             @ActionInput(name = "coolHoldTemp", description = "(opt) The temperature at which to set the cool hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
373             @ActionInput(name = "heatHoldTemp", description = "(opt) The temperature at which to set the heat hold.") @Nullable QuantityType<Temperature> heatHoldTemp,
374             @ActionInput(name = "holdClimateRef", description = "(opt) The Climate to use as reference for setting the coolHoldTemp, heatHoldTemp and fan settings for this hold. If this value is passed the coolHoldTemp and heatHoldTemp are not required.") @Nullable String holdClimateRef,
375             @ActionInput(name = "startDateTime", description = "(opt) The start date in thermostat time.") @Nullable Date startDateTime,
376             @ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime,
377             @ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
378             @ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours) {
379         Map<String, Object> params = new HashMap<String, Object>();
380         if (coolHoldTemp != null) {
381             params.put("coolHoldTemp", coolHoldTemp);
382         }
383         if (heatHoldTemp != null) {
384             params.put("heatHoldTemp", heatHoldTemp);
385         }
386         if (holdClimateRef != null) {
387             params.put("holdClimateRef", holdClimateRef);
388         }
389         return setHold(params, holdType, holdHours, startDateTime, endDateTime);
390     }
391
392     public static boolean setHold(ThingActions actions, @Nullable QuantityType<Temperature> coolHoldTemp,
393             @Nullable QuantityType<Temperature> heatHoldTemp, @Nullable String holdClimateRef,
394             @Nullable Date startDateTime, @Nullable Date endDateTime, @Nullable String holdType,
395             @Nullable Number holdHours) {
396         return ((EcobeeActions) actions).setHold(coolHoldTemp, heatHoldTemp, holdClimateRef, startDateTime, endDateTime,
397                 holdType, holdHours);
398     }
399
400     /**
401      * Set a hold by providing a parameter map
402      */
403     @RuleAction(label = "set the thermostat into hold", description = "The set hold function sets the thermostat into a hold with the specified event parameters.")
404     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
405             @ActionInput(name = "params", description = "The map of hold parameters.") @Nullable Map<String, Object> params,
406             @ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
407             @ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours,
408             @ActionInput(name = "startDateTime", description = "(opt) The start date in thermostat time.") @Nullable Date startDateTime,
409             @ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime) {
410         LOGGER.debug("EcobeeActions: Action 'SetHold' called");
411         if (params == null) {
412             throw new IllegalArgumentException("params cannot be null");
413         }
414         EventDTO event = new EventDTO();
415         for (String key : params.keySet()) {
416             Object value = params.get(key);
417             if (value == null) {
418                 LOGGER.warn("Event field '{}' has null value, ignored.", key);
419                 continue;
420             }
421             switch (key) {
422                 case "isOccupied":
423                     event.isOccupied = ((Boolean) value);
424                     break;
425                 case "isCoolOff":
426                     event.isCoolOff = ((Boolean) value);
427                     break;
428                 case "isHeatOff":
429                     event.isHeatOff = ((Boolean) value);
430                     break;
431                 case "coolHoldTemp":
432                     event.coolHoldTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
433                     break;
434                 case "heatHoldTemp":
435                     event.heatHoldTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
436                     break;
437                 case "fan":
438                     event.fan = FanMode.forValue((String) value).toString();
439                     break;
440                 case "vent":
441                     event.vent = VentilatorMode.forValue((String) value).toString();
442                     break;
443                 case "ventilatorMinOnTime":
444                     event.ventilatorMinOnTime = ((Integer) value);
445                     break;
446                 case "isOptional":
447                     event.isOptional = ((Boolean) value);
448                     break;
449                 case "isTemperatureRelative":
450                     event.isTemperatureRelative = ((Boolean) value);
451                     break;
452                 case "coolRelativeTemp":
453                     event.coolRelativeTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
454                     break;
455                 case "heatRelativeTemp":
456                     event.heatRelativeTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
457                     break;
458                 case "isTemperatureAbsolute":
459                     event.isTemperatureAbsolute = ((Boolean) value);
460                     break;
461                 case "fanMinOnTime":
462                     event.fanMinOnTime = ((Integer) value);
463                     break;
464                 case "holdClimateRef":
465                     event.holdClimateRef = ((String) value);
466                     break;
467                 default:
468                     LOGGER.warn("Unrecognized event field '{}' with value '{}' ignored.", key, value);
469                     break;
470             }
471         }
472         EcobeeThermostatBridgeHandler localHandler = handler;
473         if (localHandler == null) {
474             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
475             return false;
476         }
477         SetHoldFunction function = new SetHoldFunction(event, (holdType == null) ? null : HoldType.forValue(holdType),
478                 (holdHours == null) ? null : holdHours.intValue(), startDateTime, endDateTime);
479         return localHandler.actionPerformFunction(function);
480     }
481
482     public static boolean setHold(ThingActions actions, @Nullable Map<String, Object> params, @Nullable String holdType,
483             @Nullable Number holdHours, @Nullable Date startDateTime, @Nullable Date endDateTime) {
484         return ((EcobeeActions) actions).setHold(params, holdType, holdHours, startDateTime, endDateTime);
485     }
486
487     /**
488      * The set occupied function may only be used by EMS thermostats. The function switches a thermostat from occupied
489      * mode to unoccupied, or vice versa.
490      *
491      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/SetOccupied.shtml">Set
492      *      Occupied</a>
493      */
494     @RuleAction(label = "switch the thermostat occupancy", description = "The function switches a thermostat from occupied mode to unoccupied, or vice versa (EMS MODELS ONLY).")
495     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setOccupied(
496             @ActionInput(name = "occupied", description = "The climate to use for the temperature, occupied (true) or unoccupied (false).") @Nullable Boolean occupied,
497             @ActionInput(name = "startDateTime", description = "(opt) The start date in thermostat time.") @Nullable Date startDateTime,
498             @ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime,
499             @ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
500             @ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours) {
501         LOGGER.debug("EcobeeActions: Action 'Set Occupied' called");
502         EcobeeThermostatBridgeHandler localHandler = handler;
503         if (localHandler == null) {
504             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
505             return false;
506         }
507         SetOccupiedFunction function = new SetOccupiedFunction(occupied, startDateTime, endDateTime,
508                 (holdType == null) ? null : HoldType.forValue(holdType),
509                 (holdHours == null) ? null : Integer.valueOf(holdHours.intValue()));
510         return localHandler.actionPerformFunction(function);
511     }
512
513     public static boolean setOccupied(ThingActions actions, @Nullable Boolean occupied, @Nullable Date startDateTime,
514             @Nullable Date endDateTime, @Nullable String holdType, @Nullable Number holdHours) {
515         return ((EcobeeActions) actions).setOccupied(occupied, startDateTime, endDateTime, holdType, holdHours);
516     }
517
518     /**
519      * The update sensor function allows the caller to update the name of an ecobee3 remote sensor.
520      *
521      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/UpdateSensor.shtml">Update
522      *      Sensor</a>
523      */
524     @RuleAction(label = "update a remote sensor name", description = "The update sensor function allows the caller to update the name of an ecobee3 remote sensor.")
525     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean updateSensor(
526             @ActionInput(name = "name", description = "The updated name to give the sensor. Has a max length of 32, but shorter is recommended.") @Nullable String name,
527             @ActionInput(name = "deviceId", description = "The deviceId for the sensor, typically this indicates the enclosure and corresponds to the ThermostatRemoteSensor.id field. For example: rs:100") @Nullable String deviceId,
528             @ActionInput(name = "sensorId", description = "The identifier for the sensor within the enclosure. Corresponds to the RemoteSensorCapability.id. For example: 1") @Nullable String sensorId) {
529         LOGGER.debug("EcobeeActions: Action 'UpdateSensor' called");
530         EcobeeThermostatBridgeHandler localHandler = handler;
531         if (localHandler == null) {
532             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
533             return false;
534         }
535         UpdateSensorFunction function = new UpdateSensorFunction(name, deviceId, sensorId);
536         return localHandler.actionPerformFunction(function);
537     }
538
539     public static boolean updateSensor(ThingActions actions, @Nullable String name, @Nullable String deviceId,
540             @Nullable String sensorId) {
541         return ((EcobeeActions) actions).updateSensor(name, deviceId, sensorId);
542     }
543
544     /**
545      * Get the alerts list. Returns a JSON string containing all the alerts.
546      */
547     @RuleAction(label = "get the alerts", description = "Get the alerts list.")
548     public @ActionOutput(name = "alerts", type = "java.lang.String") @Nullable String getAlerts() {
549         LOGGER.debug("EcobeeActions: Action 'Get Alerts' called");
550         EcobeeThermostatBridgeHandler localHandler = handler;
551         if (localHandler == null) {
552             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
553             return null;
554         }
555         return localHandler.getAlerts();
556     }
557
558     public static @Nullable String getAlerts(ThingActions actions) {
559         return ((EcobeeActions) actions).getAlerts();
560     }
561
562     /**
563      * Get the events list. Returns a JSON string contains all events.
564      */
565     @RuleAction(label = "get the events", description = "Get the events list.")
566     public @ActionOutput(name = "events", type = "java.lang.String") @Nullable String getEvents() {
567         LOGGER.debug("EcobeeActions: Action 'Get Events' called");
568         EcobeeThermostatBridgeHandler localHandler = handler;
569         if (localHandler == null) {
570             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
571             return null;
572         }
573         return localHandler.getEvents();
574     }
575
576     public static @Nullable String getEvents(ThingActions actions) {
577         return ((EcobeeActions) actions).getEvents();
578     }
579
580     /**
581      * Get a list of climates. Returns a JSON string contains all climates.
582      */
583     @RuleAction(label = "get the climates", description = "Get a list of climates.")
584     public @ActionOutput(name = "climates", type = "java.lang.String") @Nullable String getClimates() {
585         LOGGER.debug("EcobeeActions: Action 'Get Climates' called");
586         EcobeeThermostatBridgeHandler localHandler = handler;
587         if (localHandler == null) {
588             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
589             return null;
590         }
591         return localHandler.getClimates();
592     }
593
594     public static @Nullable String getClimates(ThingActions actions) {
595         return ((EcobeeActions) actions).getClimates();
596     }
597 }