]> git.basschouten.com Git - openhab-addons.git/blob
fbf788f119a1182ada7e52719980f81f77e97fef
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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(@Nullable ThingActions actions, @Nullable String ackRef, @Nullable String ackType,
106             @Nullable Boolean remindMeLater) {
107         if (actions instanceof EcobeeActions) {
108             return ((EcobeeActions) actions).acknowledge(ackRef, ackType, remindMeLater);
109         } else {
110             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
111         }
112     }
113
114     /**
115      * Control the on/off state of a plug by setting a hold on the plug.
116      *
117      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/ControlPlug.shtml">Control
118      *      Plug</a>
119      */
120     @RuleAction(label = "control a plug", description = "Control the on/off state of a plug by setting a hold on the plug.")
121     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean controlPlug(
122             @ActionInput(name = "plugName", description = "The name of the plug. Ensure each plug has a unique name.") @Nullable String plugName,
123             @ActionInput(name = "plugState", description = "The state to put the plug into. Valid values: on, off, resume.") @Nullable String plugState,
124             @ActionInput(name = "startDateTime", description = "(opt) The start date/time in thermostat time.") @Nullable Date startDateTime,
125             @ActionInput(name = "endDateTime", description = "(opt) The end date/time in thermostat time.") @Nullable Date endDateTime,
126             @ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
127             @ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours) {
128         LOGGER.debug("EcobeeActions: Action 'Control Plug' called");
129         EcobeeThermostatBridgeHandler localHandler = handler;
130         if (localHandler == null) {
131             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
132             return false;
133         }
134         ControlPlugFunction function = (new ControlPlugFunction(plugName, PlugState.forValue(plugState), startDateTime,
135                 endDateTime, (holdType == null) ? null : HoldType.forValue(holdType),
136                 (holdHours == null) ? null : Integer.valueOf(holdHours.intValue())));
137         return localHandler.actionPerformFunction(function);
138     }
139
140     public static boolean controlPlug(@Nullable ThingActions actions, @Nullable String plugName,
141             @Nullable String plugState, @Nullable Date startDateTime, @Nullable Date endDateTime,
142             @Nullable String holdType, @Nullable Number holdHours) {
143         if (actions instanceof EcobeeActions) {
144             return ((EcobeeActions) actions).controlPlug(plugName, plugState, startDateTime, endDateTime, holdType,
145                     holdHours);
146         } else {
147             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
148         }
149     }
150
151     /**
152      * The create vacation function creates a vacation event on the thermostat.
153      *
154      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/CreateVacation.shtml">Create
155      *      Vacation</a>
156      */
157     @RuleAction(label = "create a vacation", description = "The create vacation function creates a vacation event on the thermostat.")
158     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean createVacation(
159             @ActionInput(name = "name", description = "The vacation event name. It must be unique.") @Nullable String name,
160             @ActionInput(name = "coolHoldTemp", description = "The temperature at which to set the cool vacation hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
161             @ActionInput(name = "heatHoldTemp", description = "The temperature at which to set the heat vacation hold.") @Nullable QuantityType<Temperature> heatHoldTemp,
162             @ActionInput(name = "startDateTime", description = "(opt) The start date/time in thermostat time.") @Nullable Date startDateTime,
163             @ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime,
164             @ActionInput(name = "fan", description = "(opt) The fan mode during the vacation. Values: auto, on Default: auto") @Nullable String fan,
165             @ActionInput(name = "fanMinOnTime", description = "(opt) The minimum number of minutes to run the fan each hour. Range: 0-60, Default: 0") @Nullable Number fanMinOnTime) {
166         LOGGER.debug("EcobeeActions: Action 'Create Vacation' called");
167         EcobeeThermostatBridgeHandler localHandler = handler;
168         if (localHandler == null) {
169             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
170             return false;
171         }
172         CreateVacationFunction function = new CreateVacationFunction(name, coolHoldTemp, heatHoldTemp, startDateTime,
173                 endDateTime, (fan == null) ? null : FanMode.forValue(fan),
174                 (fanMinOnTime == null) ? null : Integer.valueOf(fanMinOnTime.intValue()));
175         return localHandler.actionPerformFunction(function);
176     }
177
178     public static boolean createVacation(@Nullable ThingActions actions, @Nullable String name,
179             @Nullable QuantityType<Temperature> coolHoldTemp, @Nullable QuantityType<Temperature> heatHoldTemp,
180             @Nullable Date startDateTime, @Nullable Date endDateTime, @Nullable String fan,
181             @Nullable Number fanMinOnTime) {
182         if (actions instanceof EcobeeActions) {
183             return ((EcobeeActions) actions).createVacation(name, coolHoldTemp, heatHoldTemp, startDateTime,
184                     endDateTime, fan, fanMinOnTime);
185         } else {
186             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
187         }
188     }
189
190     /**
191      * The delete vacation function deletes a vacation event from a thermostat.
192      *
193      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/DeleteVacation.shtml">Delete
194      *      Vacation</a>
195      */
196     @RuleAction(label = "delete a vacation", description = "The delete vacation function deletes a vacation event from a thermostat.")
197     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean deleteVacation(
198             @ActionInput(name = "name", description = "The vacation event name to delete.") @Nullable String name) {
199         LOGGER.debug("EcobeeActions: Action 'Delete Vacation' called");
200         EcobeeThermostatBridgeHandler localHandler = handler;
201         if (localHandler == null) {
202             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
203             return false;
204         }
205         DeleteVacationFunction function = new DeleteVacationFunction(name);
206         return localHandler.actionPerformFunction(function);
207     }
208
209     public static boolean deleteVacation(@Nullable ThingActions actions, @Nullable String name) {
210         if (actions instanceof EcobeeActions) {
211             return ((EcobeeActions) actions).deleteVacation(name);
212         } else {
213             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
214         }
215     }
216
217     /**
218      * The reset preferences function sets all of the user configurable settings back to the factory default values.
219      *
220      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/ResetPreferences.shtml">Reset
221      *      Preferences</a>
222      */
223     @RuleAction(label = "reset the preferences", description = "The reset preferences function sets all of the user configurable settings back to the factory default values.")
224     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean resetPreferences() {
225         LOGGER.debug("EcobeeActions: Action 'Reset Preferences' called");
226         EcobeeThermostatBridgeHandler localHandler = handler;
227         if (localHandler == null) {
228             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
229             return false;
230         }
231         ResetPreferencesFunction function = new ResetPreferencesFunction();
232         return localHandler.actionPerformFunction(function);
233     }
234
235     public static boolean resetPreferences(@Nullable ThingActions actions) {
236         if (actions instanceof EcobeeActions) {
237             return ((EcobeeActions) actions).resetPreferences();
238         } else {
239             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
240         }
241     }
242
243     /**
244      * The resume program function removes the currently running event.
245      *
246      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/ResumeProgram.shtml">Resume
247      *      Program</a>
248      */
249     @RuleAction(label = "resume the program", description = "Removes the currently running event providing the event is not a mandatory demand response event")
250     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean resumeProgram(
251             @ActionInput(name = "resumeAll", description = "(opt) Should the thermostat be resumed to next event (false) or to its program (true)") @Nullable Boolean resumeAll) {
252         LOGGER.debug("EcobeeActions: Action 'Resume Program' called");
253         EcobeeThermostatBridgeHandler localHandler = handler;
254         if (localHandler == null) {
255             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
256             return false;
257         }
258         ResumeProgramFunction function = new ResumeProgramFunction(resumeAll);
259         return localHandler.actionPerformFunction(function);
260     }
261
262     public static boolean resumeProgram(@Nullable ThingActions actions, @Nullable Boolean resumeAll) {
263         if (actions instanceof EcobeeActions) {
264             return ((EcobeeActions) actions).resumeProgram(resumeAll);
265         } else {
266             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
267         }
268     }
269
270     /**
271      * The send message function allows an alert message to be sent to the thermostat.
272      *
273      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/SendMessage.shtml">Send
274      *      Message</a>
275      */
276     @RuleAction(label = "send a message", description = "The send message function allows an alert message to be sent to the thermostat.")
277     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendMessage(
278             @ActionInput(name = "text", description = "The message text to send. Text will be truncated to 500 characters if longer") @Nullable String text) {
279         LOGGER.debug("EcobeeActions: Action 'SendMessage' called");
280         EcobeeThermostatBridgeHandler localHandler = handler;
281         if (localHandler == null) {
282             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
283             return false;
284         }
285         SendMessageFunction function = new SendMessageFunction(text);
286         return localHandler.actionPerformFunction(function);
287     }
288
289     public static boolean sendMessage(@Nullable ThingActions actions, @Nullable String text) {
290         if (actions instanceof EcobeeActions) {
291             return ((EcobeeActions) actions).sendMessage(text);
292         } else {
293             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
294         }
295     }
296
297     /**
298      * Set an indefinite hold using the supplied the cool and heat hold temperatures
299      *
300      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/SetHold.shtml">Set Hold</a>
301      */
302     @RuleAction(label = "set the thermostat into hold", description = "The set hold function sets the thermostat into a hold with the specified temperatures.")
303     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
304             @ActionInput(name = "coolHoldTemp", description = "The temperature at which to set the cool hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
305             @ActionInput(name = "heatHoldTemp", description = "The temperature at which to set the heat hold.") @Nullable QuantityType<Temperature> heatHoldTemp) {
306         if (coolHoldTemp == null || heatHoldTemp == null) {
307             throw new IllegalArgumentException("hold temperatures cannot be null");
308         }
309         Map<String, Object> params = new HashMap<String, Object>();
310         params.put("coolHoldTemp", coolHoldTemp);
311         params.put("heatHoldTemp", heatHoldTemp);
312         return setHold(params, null, null, null, null);
313     }
314
315     public static boolean setHold(@Nullable ThingActions actions, @Nullable QuantityType<Temperature> coolHoldTemp,
316             @Nullable QuantityType<Temperature> heatHoldTemp) {
317         if (actions instanceof EcobeeActions) {
318             return ((EcobeeActions) actions).setHold(coolHoldTemp, heatHoldTemp);
319         } else {
320             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
321         }
322     }
323
324     /**
325      * Set a hold by providing the cool and heat temperatures and the number of hours.
326      */
327     @RuleAction(label = "set the thermostat into hold", description = "The set hold function sets the thermostat into a hold for the specified number of hours.")
328     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
329             @ActionInput(name = "coolHoldTemp", description = "The temperature at which to set the cool hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
330             @ActionInput(name = "heatHoldTemp", description = "The temperature at which to set the heat hold.") @Nullable QuantityType<Temperature> heatHoldTemp,
331             @ActionInput(name = "holdHours", description = "The number of hours for the hold.") @Nullable Number holdHours) {
332         if (coolHoldTemp == null || heatHoldTemp == null) {
333             throw new IllegalArgumentException("hold temperatures cannot be null");
334         }
335         if (holdHours == null) {
336             throw new IllegalArgumentException("number of hold hours is missing");
337         }
338         Map<String, Object> params = new HashMap<String, Object>();
339         params.put("coolHoldTemp", coolHoldTemp);
340         params.put("heatHoldTemp", heatHoldTemp);
341         params.put("holdType", HoldType.HOLD_HOURS);
342         params.put("holdHours", Integer.valueOf(holdHours.intValue()));
343         return setHold(params, null, null, null, null);
344     }
345
346     public static boolean setHold(@Nullable ThingActions actions, @Nullable QuantityType<Temperature> coolHoldTemp,
347             @Nullable QuantityType<Temperature> heatHoldTemp, @Nullable Number holdHours) {
348         if (actions instanceof EcobeeActions) {
349             return ((EcobeeActions) actions).setHold(coolHoldTemp, heatHoldTemp, holdHours);
350         } else {
351             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
352         }
353     }
354
355     /**
356      * Set an indefinite hold using the supplied climateRef
357      */
358     @RuleAction(label = "set the thermostat into hold", description = "The set hold function sets the thermostat into a hold with the specified climate ref.")
359     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
360             @ActionInput(name = "holdClimateRef", description = "The holdClimateRef used to set the hold.") @Nullable String holdClimateRef) {
361         EcobeeThermostatBridgeHandler localHandler = handler;
362         if (localHandler == null) {
363             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
364             return false;
365         }
366         if (holdClimateRef == null || !localHandler.isValidClimateRef(holdClimateRef)) {
367             throw new IllegalArgumentException("hold climate ref is missing or invalid");
368         }
369         Map<String, Object> params = new HashMap<String, Object>();
370         params.put("holdClimateRef", holdClimateRef);
371         return setHold(params, null, null, null, null);
372     }
373
374     public static boolean setHold(@Nullable ThingActions actions, @Nullable String holdClimateRef) {
375         if (actions instanceof EcobeeActions) {
376             return ((EcobeeActions) actions).setHold(holdClimateRef);
377         } else {
378             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
379         }
380     }
381
382     /**
383      * Set a hold using the supplied climateRef for the supplied number of hours.
384      */
385     @RuleAction(label = "set the thermostat into hold", description = "The set hold function sets the thermostat into a hold with the specified climate ref.")
386     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
387             @ActionInput(name = "holdClimateRef", description = "The holdClimateRef used to set the hold.") @Nullable String holdClimateRef,
388             @ActionInput(name = "holdHours", description = "The number of hours for the hold.") @Nullable Number holdHours) {
389         if (holdHours == null) {
390             throw new IllegalArgumentException("number of hold hours is missing");
391         }
392         EcobeeThermostatBridgeHandler localHandler = handler;
393         if (localHandler == null) {
394             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
395             return false;
396         }
397         if (holdClimateRef == null || !localHandler.isValidClimateRef(holdClimateRef)) {
398             throw new IllegalArgumentException("hold climate ref is missing or invalid");
399         }
400         Map<String, Object> params = new HashMap<String, Object>();
401         params.put("holdClimateRef", holdClimateRef);
402         params.put("holdType", HoldType.HOLD_HOURS);
403         params.put("holdHours", Integer.valueOf(holdHours.intValue()));
404         return setHold(params, null, null, null, null);
405     }
406
407     public static boolean setHold(@Nullable ThingActions actions, @Nullable String holdClimateRef,
408             @Nullable Number holdHours) {
409         if (actions instanceof EcobeeActions) {
410             return ((EcobeeActions) actions).setHold(holdClimateRef, holdHours);
411         } else {
412             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
413         }
414     }
415
416     /**
417      * Set a hold
418      */
419     @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.")
420     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
421             @ActionInput(name = "coolHoldTemp", description = "(opt) The temperature at which to set the cool hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
422             @ActionInput(name = "heatHoldTemp", description = "(opt) The temperature at which to set the heat hold.") @Nullable QuantityType<Temperature> heatHoldTemp,
423             @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,
424             @ActionInput(name = "startDateTime", description = "(opt) The start date in thermostat time.") @Nullable Date startDateTime,
425             @ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime,
426             @ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
427             @ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours) {
428         Map<String, Object> params = new HashMap<String, Object>();
429         if (coolHoldTemp != null) {
430             params.put("coolHoldTemp", coolHoldTemp);
431         }
432         if (heatHoldTemp != null) {
433             params.put("heatHoldTemp", heatHoldTemp);
434         }
435         if (holdClimateRef != null) {
436             params.put("holdClimateRef", holdClimateRef);
437         }
438         return setHold(params, holdType, holdHours, startDateTime, endDateTime);
439     }
440
441     public static boolean setHold(@Nullable ThingActions actions, @Nullable QuantityType<Temperature> coolHoldTemp,
442             @Nullable QuantityType<Temperature> heatHoldTemp, @Nullable String holdClimateRef,
443             @Nullable Date startDateTime, @Nullable Date endDateTime, @Nullable String holdType,
444             @Nullable Number holdHours) {
445         if (actions instanceof EcobeeActions) {
446             return ((EcobeeActions) actions).setHold(coolHoldTemp, heatHoldTemp, holdClimateRef, startDateTime,
447                     endDateTime, holdType, holdHours);
448         } else {
449             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
450         }
451     }
452
453     /**
454      * Set a hold by providing a parameter map
455      */
456     @RuleAction(label = "set the thermostat into hold", description = "The set hold function sets the thermostat into a hold with the specified event parameters.")
457     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
458             @ActionInput(name = "params", description = "The map of hold parameters.") @Nullable Map<String, Object> params,
459             @ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
460             @ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours,
461             @ActionInput(name = "startDateTime", description = "(opt) The start date in thermostat time.") @Nullable Date startDateTime,
462             @ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime) {
463         LOGGER.debug("EcobeeActions: Action 'SetHold' called");
464         if (params == null) {
465             throw new IllegalArgumentException("params cannot be null");
466         }
467         EventDTO event = new EventDTO();
468         for (String key : params.keySet()) {
469             Object value = params.get(key);
470             switch (key) {
471                 case "isOccupied":
472                     event.isOccupied = ((Boolean) value);
473                     break;
474                 case "isCoolOff":
475                     event.isCoolOff = ((Boolean) value);
476                     break;
477                 case "isHeatOff":
478                     event.isHeatOff = ((Boolean) value);
479                     break;
480                 case "coolHoldTemp":
481                     event.coolHoldTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
482                     break;
483                 case "heatHoldTemp":
484                     event.heatHoldTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
485                     break;
486                 case "fan":
487                     event.fan = FanMode.forValue((String) value).toString();
488                     break;
489                 case "vent":
490                     event.vent = VentilatorMode.forValue((String) value).toString();
491                     break;
492                 case "ventilatorMinOnTime":
493                     event.ventilatorMinOnTime = ((Integer) value);
494                     break;
495                 case "isOptional":
496                     event.isOptional = ((Boolean) value);
497                     break;
498                 case "isTemperatureRelative":
499                     event.isTemperatureRelative = ((Boolean) value);
500                     break;
501                 case "coolRelativeTemp":
502                     event.coolRelativeTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
503                     break;
504                 case "heatRelativeTemp":
505                     event.heatRelativeTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
506                     break;
507                 case "isTemperatureAbsolute":
508                     event.isTemperatureAbsolute = ((Boolean) value);
509                     break;
510                 case "fanMinOnTime":
511                     event.fanMinOnTime = ((Integer) value);
512                     break;
513                 case "holdClimateRef":
514                     event.holdClimateRef = ((String) value);
515                     break;
516                 default:
517                     LOGGER.warn("Unrecognized event field '{}' with value '{}' ignored.", key, value);
518                     break;
519             }
520         }
521         EcobeeThermostatBridgeHandler localHandler = handler;
522         if (localHandler == null) {
523             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
524             return false;
525         }
526         SetHoldFunction function = new SetHoldFunction(event, (holdType == null) ? null : HoldType.forValue(holdType),
527                 (holdHours == null) ? null : holdHours.intValue(), startDateTime, endDateTime);
528         return localHandler.actionPerformFunction(function);
529     }
530
531     public static boolean setHold(@Nullable ThingActions actions, @Nullable Map<String, Object> params,
532             @Nullable String holdType, @Nullable Number holdHours, @Nullable Date startDateTime,
533             @Nullable Date endDateTime) {
534         if (actions instanceof EcobeeActions) {
535             return ((EcobeeActions) actions).setHold(params, holdType, holdHours, startDateTime, endDateTime);
536         } else {
537             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
538         }
539     }
540
541     /**
542      * The set occupied function may only be used by EMS thermostats. The function switches a thermostat from occupied
543      * mode to unoccupied, or vice versa.
544      *
545      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/SetOccupied.shtml">Set
546      *      Occupied</a>
547      */
548     @RuleAction(label = "switch the thermostat occupancy", description = "The function switches a thermostat from occupied mode to unoccupied, or vice versa (EMS MODELS ONLY).")
549     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setOccupied(
550             @ActionInput(name = "occupied", description = "The climate to use for the temperature, occupied (true) or unoccupied (false).") @Nullable Boolean occupied,
551             @ActionInput(name = "startDateTime", description = "(opt) The start date in thermostat time.") @Nullable Date startDateTime,
552             @ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime,
553             @ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
554             @ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours) {
555         LOGGER.debug("EcobeeActions: Action 'Set Occupied' called");
556         EcobeeThermostatBridgeHandler localHandler = handler;
557         if (localHandler == null) {
558             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
559             return false;
560         }
561         SetOccupiedFunction function = new SetOccupiedFunction(occupied, startDateTime, endDateTime,
562                 (holdType == null) ? null : HoldType.forValue(holdType),
563                 (holdHours == null) ? null : Integer.valueOf(holdHours.intValue()));
564         return localHandler.actionPerformFunction(function);
565     }
566
567     public static boolean setOccupied(@Nullable ThingActions actions, @Nullable Boolean occupied,
568             @Nullable Date startDateTime, @Nullable Date endDateTime, @Nullable String holdType,
569             @Nullable Number holdHours) {
570         if (actions instanceof EcobeeActions) {
571             return ((EcobeeActions) actions).setOccupied(occupied, startDateTime, endDateTime, holdType, holdHours);
572         } else {
573             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
574         }
575     }
576
577     /**
578      * The update sensor function allows the caller to update the name of an ecobee3 remote sensor.
579      *
580      * @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/UpdateSensor.shtml">Update
581      *      Sensor</a>
582      */
583     @RuleAction(label = "update a remote sensor name", description = "The update sensor function allows the caller to update the name of an ecobee3 remote sensor.")
584     public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean updateSensor(
585             @ActionInput(name = "name", description = "The updated name to give the sensor. Has a max length of 32, but shorter is recommended.") @Nullable String name,
586             @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,
587             @ActionInput(name = "sensorId", description = "The identifier for the sensor within the enclosure. Corresponds to the RemoteSensorCapability.id. For example: 1") @Nullable String sensorId) {
588         LOGGER.debug("EcobeeActions: Action 'UpdateSensor' called");
589         EcobeeThermostatBridgeHandler localHandler = handler;
590         if (localHandler == null) {
591             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
592             return false;
593         }
594         UpdateSensorFunction function = new UpdateSensorFunction(name, deviceId, sensorId);
595         return localHandler.actionPerformFunction(function);
596     }
597
598     public static boolean updateSensor(@Nullable ThingActions actions, @Nullable String name, @Nullable String deviceId,
599             @Nullable String sensorId) {
600         if (actions instanceof EcobeeActions) {
601             return ((EcobeeActions) actions).updateSensor(name, deviceId, sensorId);
602         } else {
603             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
604         }
605     }
606
607     /**
608      * Get the alerts list. Returns a JSON string containing all the alerts.
609      */
610     @RuleAction(label = "get the alerts", description = "Get the alerts list.")
611     public @ActionOutput(name = "alerts", type = "java.lang.String") @Nullable String getAlerts() {
612         LOGGER.debug("EcobeeActions: Action 'Get Alerts' called");
613         EcobeeThermostatBridgeHandler localHandler = handler;
614         if (localHandler == null) {
615             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
616             return null;
617         }
618         return localHandler.getAlerts();
619     }
620
621     public static @Nullable String getAlerts(@Nullable ThingActions actions) {
622         if (actions instanceof EcobeeActions) {
623             return ((EcobeeActions) actions).getAlerts();
624         } else {
625             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
626         }
627     }
628
629     /**
630      * Get the events list. Returns a JSON string contains all events.
631      */
632     @RuleAction(label = "get the events", description = "Get the events list.")
633     public @ActionOutput(name = "events", type = "java.lang.String") @Nullable String getEvents() {
634         LOGGER.debug("EcobeeActions: Action 'Get Events' called");
635         EcobeeThermostatBridgeHandler localHandler = handler;
636         if (localHandler == null) {
637             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
638             return null;
639         }
640         return localHandler.getEvents();
641     }
642
643     public static @Nullable String getEvents(@Nullable ThingActions actions) {
644         if (actions instanceof EcobeeActions) {
645             return ((EcobeeActions) actions).getEvents();
646         } else {
647             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
648         }
649     }
650
651     /**
652      * Get a list of climates. Returns a JSON string contains all climates.
653      */
654     @RuleAction(label = "get the climates", description = "Get a list of climates.")
655     public @ActionOutput(name = "climates", type = "java.lang.String") @Nullable String getClimates() {
656         LOGGER.debug("EcobeeActions: Action 'Get Climates' called");
657         EcobeeThermostatBridgeHandler localHandler = handler;
658         if (localHandler == null) {
659             LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
660             return null;
661         }
662         return localHandler.getClimates();
663     }
664
665     public static @Nullable String getClimates(@Nullable ThingActions actions) {
666         if (actions instanceof EcobeeActions) {
667             return ((EcobeeActions) actions).getClimates();
668         } else {
669             throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
670         }
671     }
672 }