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