added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
32
bundles/org.openhab.binding.ecobee/.classpath
Normal file
32
bundles/org.openhab.binding.ecobee/.classpath
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
bundles/org.openhab.binding.ecobee/.project
Normal file
23
bundles/org.openhab.binding.ecobee/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.binding.ecobee</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
13
bundles/org.openhab.binding.ecobee/NOTICE
Normal file
13
bundles/org.openhab.binding.ecobee/NOTICE
Normal file
@@ -0,0 +1,13 @@
|
||||
This content is produced and maintained by the openHAB project.
|
||||
|
||||
* Project home: https://www.openhab.org
|
||||
|
||||
== Declared Project Licenses
|
||||
|
||||
This program and the accompanying materials are made available under the terms
|
||||
of the Eclipse Public License 2.0 which is available at
|
||||
https://www.eclipse.org/legal/epl-2.0/.
|
||||
|
||||
== Source Code
|
||||
|
||||
https://github.com/openhab/openhab-addons
|
||||
1274
bundles/org.openhab.binding.ecobee/README.md
Normal file
1274
bundles/org.openhab.binding.ecobee/README.md
Normal file
File diff suppressed because it is too large
Load Diff
17
bundles/org.openhab.binding.ecobee/pom.xml
Normal file
17
bundles/org.openhab.binding.ecobee/pom.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.ecobee</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: Ecobee Binding</name>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.ecobee-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-ecobee" description="Ecobee Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.ecobee/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,644 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.action;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.EventDTO;
|
||||
import org.openhab.binding.ecobee.internal.enums.AckType;
|
||||
import org.openhab.binding.ecobee.internal.enums.FanMode;
|
||||
import org.openhab.binding.ecobee.internal.enums.HoldType;
|
||||
import org.openhab.binding.ecobee.internal.enums.PlugState;
|
||||
import org.openhab.binding.ecobee.internal.enums.VentilatorMode;
|
||||
import org.openhab.binding.ecobee.internal.function.AcknowledgeFunction;
|
||||
import org.openhab.binding.ecobee.internal.function.ControlPlugFunction;
|
||||
import org.openhab.binding.ecobee.internal.function.CreateVacationFunction;
|
||||
import org.openhab.binding.ecobee.internal.function.DeleteVacationFunction;
|
||||
import org.openhab.binding.ecobee.internal.function.ResetPreferencesFunction;
|
||||
import org.openhab.binding.ecobee.internal.function.ResumeProgramFunction;
|
||||
import org.openhab.binding.ecobee.internal.function.SendMessageFunction;
|
||||
import org.openhab.binding.ecobee.internal.function.SetHoldFunction;
|
||||
import org.openhab.binding.ecobee.internal.function.SetOccupiedFunction;
|
||||
import org.openhab.binding.ecobee.internal.function.UpdateSensorFunction;
|
||||
import org.openhab.binding.ecobee.internal.handler.EcobeeThermostatBridgeHandler;
|
||||
import org.openhab.binding.ecobee.internal.handler.EcobeeUtils;
|
||||
import org.openhab.core.automation.annotation.ActionInput;
|
||||
import org.openhab.core.automation.annotation.ActionOutput;
|
||||
import org.openhab.core.automation.annotation.RuleAction;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.thing.binding.ThingActions;
|
||||
import org.openhab.core.thing.binding.ThingActionsScope;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeActions} defines the thing actions for the Ecobee binding.
|
||||
* <p>
|
||||
* <b>Note:</b>The static method <b>invokeMethod</b> handles the case where
|
||||
* the test <i>actions instanceof EcobeeActions</i> fails. This test can fail
|
||||
* due to an issue in openHAB core v2.5.0 where the {@link EcobeeActions} class
|
||||
* can be loaded by a different classloader than the <i>actions</i> instance.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapted for OH2/3
|
||||
* @author Connor Petty - Proxy method for invoking actions
|
||||
*/
|
||||
@ThingActionsScope(name = "ecobee")
|
||||
@NonNullByDefault
|
||||
public class EcobeeActions implements ThingActions, IEcobeeActions {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(EcobeeActions.class);
|
||||
|
||||
private @Nullable EcobeeThermostatBridgeHandler handler;
|
||||
|
||||
public EcobeeActions() {
|
||||
LOGGER.debug("EcobeeActions: EcobeeActions: Actions service created");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||
if (handler instanceof EcobeeThermostatBridgeHandler) {
|
||||
this.handler = (EcobeeThermostatBridgeHandler) handler;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
private static IEcobeeActions invokeMethodOf(@Nullable ThingActions actions) {
|
||||
if (actions == null) {
|
||||
throw new IllegalArgumentException("actions cannot be null");
|
||||
}
|
||||
if (actions.getClass().getName().equals(EcobeeActions.class.getName())) {
|
||||
if (actions instanceof IEcobeeActions) {
|
||||
return (IEcobeeActions) actions;
|
||||
} else {
|
||||
return (IEcobeeActions) Proxy.newProxyInstance(IEcobeeActions.class.getClassLoader(),
|
||||
new Class[] { IEcobeeActions.class }, (Object proxy, Method method, Object[] args) -> {
|
||||
Method m = actions.getClass().getDeclaredMethod(method.getName(),
|
||||
method.getParameterTypes());
|
||||
return m.invoke(actions, args);
|
||||
});
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Actions is not an instance of EcobeeActions");
|
||||
}
|
||||
|
||||
/**
|
||||
* The acknowledge function allows an alert to be acknowledged.
|
||||
*
|
||||
* @see <a
|
||||
* href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/Acknowledge.shtml">Acknowledge
|
||||
* </a>
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Acknowledge", description = "Acknowledges an alert.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean acknowledge(
|
||||
@ActionInput(name = "ackRef", description = "The acknowledge ref of alert") @Nullable String ackRef,
|
||||
@ActionInput(name = "ackType", description = "The type of acknowledgement. Valid values: accept, decline, defer, unacknowledged") @Nullable String ackType,
|
||||
@ActionInput(name = "remindMeLater", description = "(opt) Whether to remind at a later date, if this is a defer acknowledgement") @Nullable Boolean remindMeLater) {
|
||||
LOGGER.debug("EcobeeActions: Action 'Acknowledge' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
AcknowledgeFunction function = new AcknowledgeFunction(localHandler.getThermostatId(), ackRef,
|
||||
AckType.forValue(ackType), remindMeLater);
|
||||
return localHandler.actionPerformFunction(function);
|
||||
}
|
||||
|
||||
public static boolean acknowledge(@Nullable ThingActions actions, @Nullable String ackRef, @Nullable String ackType,
|
||||
@Nullable Boolean remindMeLater) {
|
||||
return invokeMethodOf(actions).acknowledge(ackRef, ackType, remindMeLater);
|
||||
}
|
||||
|
||||
/**
|
||||
* Control the on/off state of a plug by setting a hold on the plug.
|
||||
*
|
||||
* @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/ControlPlug.shtml">Control
|
||||
* Plug</a>
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Control Plug", description = "Control the on/off state of a plug by setting a hold on the plug.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean controlPlug(
|
||||
@ActionInput(name = "plugName", description = "The name of the plug. Ensure each plug has a unique name.") @Nullable String plugName,
|
||||
@ActionInput(name = "plugState", description = "The state to put the plug into. Valid values: on, off, resume.") @Nullable String plugState,
|
||||
@ActionInput(name = "startDateTime", description = "(opt) The start date/time in thermostat time.") @Nullable Date startDateTime,
|
||||
@ActionInput(name = "endDateTime", description = "(opt) The end date/time in thermostat time.") @Nullable Date endDateTime,
|
||||
@ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
|
||||
@ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours) {
|
||||
LOGGER.debug("EcobeeActions: Action 'Control Plug' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
ControlPlugFunction function = (new ControlPlugFunction(plugName, PlugState.forValue(plugState), startDateTime,
|
||||
endDateTime, (holdType == null) ? null : HoldType.forValue(holdType),
|
||||
(holdHours == null) ? null : Integer.valueOf(holdHours.intValue())));
|
||||
return localHandler.actionPerformFunction(function);
|
||||
}
|
||||
|
||||
public static boolean controlPlug(@Nullable ThingActions actions, @Nullable String plugName,
|
||||
@Nullable String plugState, @Nullable Date startDateTime, @Nullable Date endDateTime,
|
||||
@Nullable String holdType, @Nullable Number holdHours) {
|
||||
return invokeMethodOf(actions).controlPlug(plugName, plugState, startDateTime, endDateTime, holdType,
|
||||
holdHours);
|
||||
}
|
||||
|
||||
/**
|
||||
* The create vacation function creates a vacation event on the thermostat.
|
||||
*
|
||||
* @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/CreateVacation.shtml">Create
|
||||
* Vacation</a>
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Create Vacation", description = "The create vacation function creates a vacation event on the thermostat.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean createVacation(
|
||||
@ActionInput(name = "name", description = "The vacation event name. It must be unique.") @Nullable String name,
|
||||
@ActionInput(name = "coolHoldTemp", description = "The temperature at which to set the cool vacation hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@ActionInput(name = "heatHoldTemp", description = "The temperature at which to set the heat vacation hold.") @Nullable QuantityType<Temperature> heatHoldTemp,
|
||||
@ActionInput(name = "startDateTime", description = "(opt) The start date/time in thermostat time.") @Nullable Date startDateTime,
|
||||
@ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime,
|
||||
@ActionInput(name = "fan", description = "(opt) The fan mode during the vacation. Values: auto, on Default: auto") @Nullable String fan,
|
||||
@ActionInput(name = "fanMinOnTime", description = "(opt) The minimum number of minutes to run the fan each hour. Range: 0-60, Default: 0") @Nullable Number fanMinOnTime) {
|
||||
LOGGER.debug("EcobeeActions: Action 'Create Vacation' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
CreateVacationFunction function = new CreateVacationFunction(name, coolHoldTemp, heatHoldTemp, startDateTime,
|
||||
endDateTime, (fan == null) ? null : FanMode.forValue(fan),
|
||||
(fanMinOnTime == null) ? null : Integer.valueOf(fanMinOnTime.intValue()));
|
||||
return localHandler.actionPerformFunction(function);
|
||||
}
|
||||
|
||||
public static boolean createVacation(@Nullable ThingActions actions, @Nullable String name,
|
||||
@Nullable QuantityType<Temperature> coolHoldTemp, @Nullable QuantityType<Temperature> heatHoldTemp,
|
||||
@Nullable Date startDateTime, @Nullable Date endDateTime, @Nullable String fan,
|
||||
@Nullable Number fanMinOnTime) {
|
||||
return invokeMethodOf(actions).createVacation(name, coolHoldTemp, heatHoldTemp, startDateTime, endDateTime, fan,
|
||||
fanMinOnTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* The delete vacation function deletes a vacation event from a thermostat.
|
||||
*
|
||||
* @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/DeleteVacation.shtml">Delete
|
||||
* Vacation</a>
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Delete Vacation", description = "The delete vacation function deletes a vacation event from a thermostat.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean deleteVacation(
|
||||
@ActionInput(name = "name", description = "The vacation event name to delete.") @Nullable String name) {
|
||||
LOGGER.debug("EcobeeActions: Action 'Delete Vacation' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
DeleteVacationFunction function = new DeleteVacationFunction(name);
|
||||
return localHandler.actionPerformFunction(function);
|
||||
}
|
||||
|
||||
public static boolean deleteVacation(@Nullable ThingActions actions, @Nullable String name) {
|
||||
return invokeMethodOf(actions).deleteVacation(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* The reset preferences function sets all of the user configurable settings back to the factory default values.
|
||||
*
|
||||
* @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/ResetPreferences.shtml">Reset
|
||||
* Preferences</a>
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Reset Preferences", description = "The reset preferences function sets all of the user configurable settings back to the factory default values.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean resetPreferences() {
|
||||
LOGGER.debug("EcobeeActions: Action 'Reset Preferences' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
ResetPreferencesFunction function = new ResetPreferencesFunction();
|
||||
return localHandler.actionPerformFunction(function);
|
||||
}
|
||||
|
||||
public static boolean resetPreferences(@Nullable ThingActions actions) {
|
||||
return invokeMethodOf(actions).resetPreferences();
|
||||
}
|
||||
|
||||
/**
|
||||
* The resume program function removes the currently running event.
|
||||
*
|
||||
* @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/ResumeProgram.shtml">Resume
|
||||
* Program</a>
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Resume Program", description = "Removes the currently running event providing the event is not a mandatory demand response event")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean resumeProgram(
|
||||
@ActionInput(name = "resumeAll", description = "(opt) Should the thermostat be resumed to next event (false) or to its program (true)") @Nullable Boolean resumeAll) {
|
||||
LOGGER.debug("EcobeeActions: Action 'Resume Program' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
ResumeProgramFunction function = new ResumeProgramFunction(resumeAll);
|
||||
return localHandler.actionPerformFunction(function);
|
||||
}
|
||||
|
||||
public static boolean resumeProgram(@Nullable ThingActions actions, @Nullable Boolean resumeAll) {
|
||||
return invokeMethodOf(actions).resumeProgram(resumeAll);
|
||||
}
|
||||
|
||||
/**
|
||||
* The send message function allows an alert message to be sent to the thermostat.
|
||||
*
|
||||
* @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/SendMessage.shtml">Send
|
||||
* Message</a>
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Send Message", description = "The send message function allows an alert message to be sent to the thermostat.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendMessage(
|
||||
@ActionInput(name = "text", description = "The message text to send. Text will be truncated to 500 characters if longer") @Nullable String text) {
|
||||
LOGGER.debug("EcobeeActions: Action 'SendMessage' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
SendMessageFunction function = new SendMessageFunction(text);
|
||||
return localHandler.actionPerformFunction(function);
|
||||
}
|
||||
|
||||
public static boolean sendMessage(@Nullable ThingActions actions, @Nullable String text) {
|
||||
return invokeMethodOf(actions).sendMessage(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an indefinite hold using the supplied the cool and heat hold temperatures
|
||||
*
|
||||
* @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/SetHold.shtml">Set Hold</a>
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Set Hold", description = "The set hold function sets the thermostat into a hold with the specified temperatures.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
|
||||
@ActionInput(name = "coolHoldTemp", description = "The temperature at which to set the cool hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@ActionInput(name = "heatHoldTemp", description = "The temperature at which to set the heat hold.") @Nullable QuantityType<Temperature> heatHoldTemp) {
|
||||
if (coolHoldTemp == null || heatHoldTemp == null) {
|
||||
throw new IllegalArgumentException("hold temperatures cannot be null");
|
||||
}
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.put("coolHoldTemp", coolHoldTemp);
|
||||
params.put("heatHoldTemp", heatHoldTemp);
|
||||
return setHold(params, null, null, null, null);
|
||||
}
|
||||
|
||||
public static boolean setHold(@Nullable ThingActions actions, @Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@Nullable QuantityType<Temperature> heatHoldTemp) {
|
||||
return invokeMethodOf(actions).setHold(coolHoldTemp, heatHoldTemp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a hold by providing the cool and heat temperatures and the number of hours.
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Set Hold", description = "The set hold function sets the thermostat into a hold for the specified number of hours.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
|
||||
@ActionInput(name = "coolHoldTemp", description = "The temperature at which to set the cool hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@ActionInput(name = "heatHoldTemp", description = "The temperature at which to set the heat hold.") @Nullable QuantityType<Temperature> heatHoldTemp,
|
||||
@ActionInput(name = "holdHours", description = "The number of hours for the hold.") @Nullable Number holdHours) {
|
||||
if (coolHoldTemp == null || heatHoldTemp == null) {
|
||||
throw new IllegalArgumentException("hold temperatures cannot be null");
|
||||
}
|
||||
if (holdHours == null) {
|
||||
throw new IllegalArgumentException("number of hold hours is missing");
|
||||
}
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.put("coolHoldTemp", coolHoldTemp);
|
||||
params.put("heatHoldTemp", heatHoldTemp);
|
||||
params.put("holdType", HoldType.HOLD_HOURS);
|
||||
params.put("holdHours", Integer.valueOf(holdHours.intValue()));
|
||||
return setHold(params, null, null, null, null);
|
||||
}
|
||||
|
||||
public static boolean setHold(@Nullable ThingActions actions, @Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@Nullable QuantityType<Temperature> heatHoldTemp, @Nullable Number holdHours) {
|
||||
return invokeMethodOf(actions).setHold(coolHoldTemp, heatHoldTemp, holdHours);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an indefinite hold using the supplied climateRef
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Set Hold", description = "The set hold function sets the thermostat into a hold with the specified climate ref.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
|
||||
@ActionInput(name = "holdClimateRef", description = "The holdClimateRef used to set the hold.") @Nullable String holdClimateRef) {
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
if (holdClimateRef == null || !localHandler.isValidClimateRef(holdClimateRef)) {
|
||||
throw new IllegalArgumentException("hold climate ref is missing or invalid");
|
||||
}
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.put("holdClimateRef", holdClimateRef);
|
||||
return setHold(params, null, null, null, null);
|
||||
}
|
||||
|
||||
public static boolean setHold(@Nullable ThingActions actions, @Nullable String holdClimateRef) {
|
||||
return invokeMethodOf(actions).setHold(holdClimateRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a hold using the supplied climateRef for the supplied number of hours.
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Set Hold", description = "The set hold function sets the thermostat into a hold with the specified climate ref.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
|
||||
@ActionInput(name = "holdClimateRef", description = "The holdClimateRef used to set the hold.") @Nullable String holdClimateRef,
|
||||
@ActionInput(name = "holdHours", description = "The number of hours for the hold.") @Nullable Number holdHours) {
|
||||
if (holdHours == null) {
|
||||
throw new IllegalArgumentException("number of hold hours is missing");
|
||||
}
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
if (holdClimateRef == null || !localHandler.isValidClimateRef(holdClimateRef)) {
|
||||
throw new IllegalArgumentException("hold climate ref is missing or invalid");
|
||||
}
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.put("holdClimateRef", holdClimateRef);
|
||||
params.put("holdType", HoldType.HOLD_HOURS);
|
||||
params.put("holdHours", Integer.valueOf(holdHours.intValue()));
|
||||
return setHold(params, null, null, null, null);
|
||||
}
|
||||
|
||||
public static boolean setHold(@Nullable ThingActions actions, @Nullable String holdClimateRef,
|
||||
@Nullable Number holdHours) {
|
||||
return invokeMethodOf(actions).setHold(holdClimateRef, holdHours);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a hold
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Set Hold", description = "The set hold function sets the thermostat into a hold with the specified temperature or climate ref.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
|
||||
@ActionInput(name = "coolHoldTemp", description = "(opt) The temperature at which to set the cool hold.") @Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@ActionInput(name = "heatHoldTemp", description = "(opt) The temperature at which to set the heat hold.") @Nullable QuantityType<Temperature> heatHoldTemp,
|
||||
@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,
|
||||
@ActionInput(name = "startDateTime", description = "(opt) The start date in thermostat time.") @Nullable Date startDateTime,
|
||||
@ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime,
|
||||
@ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
|
||||
@ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours) {
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
if (coolHoldTemp != null) {
|
||||
params.put("coolHoldTemp", coolHoldTemp);
|
||||
}
|
||||
if (heatHoldTemp != null) {
|
||||
params.put("heatHoldTemp", heatHoldTemp);
|
||||
}
|
||||
if (holdClimateRef != null) {
|
||||
params.put("holdClimateRef", holdClimateRef);
|
||||
}
|
||||
return setHold(params, holdType, holdHours, startDateTime, endDateTime);
|
||||
}
|
||||
|
||||
public static boolean setHold(@Nullable ThingActions actions, @Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@Nullable QuantityType<Temperature> heatHoldTemp, @Nullable String holdClimateRef,
|
||||
@Nullable Date startDateTime, @Nullable Date endDateTime, @Nullable String holdType,
|
||||
@Nullable Number holdHours) {
|
||||
return invokeMethodOf(actions).setHold(coolHoldTemp, heatHoldTemp, holdClimateRef, startDateTime, endDateTime,
|
||||
holdType, holdHours);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a hold by providing a parameter map
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Set Hold", description = "The set hold function sets the thermostat into a hold with the specified event parameters.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setHold(
|
||||
@ActionInput(name = "params", description = "The map of hold parameters.") @Nullable Map<String, Object> params,
|
||||
@ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
|
||||
@ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours,
|
||||
@ActionInput(name = "startDateTime", description = "(opt) The start date in thermostat time.") @Nullable Date startDateTime,
|
||||
@ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime) {
|
||||
LOGGER.debug("EcobeeActions: Action 'SetHold' called");
|
||||
if (params == null) {
|
||||
throw new IllegalArgumentException("params cannot be null");
|
||||
}
|
||||
EventDTO event = new EventDTO();
|
||||
for (String key : params.keySet()) {
|
||||
Object value = params.get(key);
|
||||
switch (key) {
|
||||
case "isOccupied":
|
||||
event.isOccupied = ((Boolean) value);
|
||||
break;
|
||||
case "isCoolOff":
|
||||
event.isCoolOff = ((Boolean) value);
|
||||
break;
|
||||
case "isHeatOff":
|
||||
event.isHeatOff = ((Boolean) value);
|
||||
break;
|
||||
case "coolHoldTemp":
|
||||
event.coolHoldTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
|
||||
break;
|
||||
case "heatHoldTemp":
|
||||
event.heatHoldTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
|
||||
break;
|
||||
case "fan":
|
||||
event.fan = FanMode.forValue((String) value).toString();
|
||||
break;
|
||||
case "vent":
|
||||
event.vent = VentilatorMode.forValue((String) value).toString();
|
||||
break;
|
||||
case "ventilatorMinOnTime":
|
||||
event.ventilatorMinOnTime = ((Integer) value);
|
||||
break;
|
||||
case "isOptional":
|
||||
event.isOptional = ((Boolean) value);
|
||||
break;
|
||||
case "isTemperatureRelative":
|
||||
event.isTemperatureRelative = ((Boolean) value);
|
||||
break;
|
||||
case "coolRelativeTemp":
|
||||
event.coolRelativeTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
|
||||
break;
|
||||
case "heatRelativeTemp":
|
||||
event.heatRelativeTemp = EcobeeUtils.convertQuantityTypeToEcobeeTemp(value);
|
||||
break;
|
||||
case "isTemperatureAbsolute":
|
||||
event.isTemperatureAbsolute = ((Boolean) value);
|
||||
break;
|
||||
case "fanMinOnTime":
|
||||
event.fanMinOnTime = ((Integer) value);
|
||||
break;
|
||||
case "holdClimateRef":
|
||||
event.holdClimateRef = ((String) value);
|
||||
break;
|
||||
default:
|
||||
LOGGER.warn("Unrecognized event field '{}' with value '{}' ignored.", key, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
SetHoldFunction function = new SetHoldFunction(event, (holdType == null) ? null : HoldType.forValue(holdType),
|
||||
(holdHours == null) ? null : holdHours.intValue(), startDateTime, endDateTime);
|
||||
return localHandler.actionPerformFunction(function);
|
||||
}
|
||||
|
||||
public static boolean setHold(@Nullable ThingActions actions, @Nullable Map<String, Object> params,
|
||||
@Nullable String holdType, @Nullable Number holdHours, @Nullable Date startDateTime,
|
||||
@Nullable Date endDateTime) {
|
||||
return invokeMethodOf(actions).setHold(params, holdType, holdHours, startDateTime, endDateTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* The set occupied function may only be used by EMS thermostats. The function switches a thermostat from occupied
|
||||
* mode to unoccupied, or vice versa.
|
||||
*
|
||||
* @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/SetOccupied.shtml">Set
|
||||
* Occupied</a>
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Set Occupied", description = "The function switches a thermostat from occupied mode to unoccupied, or vice versa (EMS MODELS ONLY).")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean setOccupied(
|
||||
@ActionInput(name = "occupied", description = "The climate to use for the temperature, occupied (true) or unoccupied (false).") @Nullable Boolean occupied,
|
||||
@ActionInput(name = "startDateTime", description = "(opt) The start date in thermostat time.") @Nullable Date startDateTime,
|
||||
@ActionInput(name = "endDateTime", description = "(opt) The end date in thermostat time.") @Nullable Date endDateTime,
|
||||
@ActionInput(name = "holdType", description = "(opt) The hold duration type. Valid values: dateTime, nextTransition, indefinite, holdHours.") @Nullable String holdType,
|
||||
@ActionInput(name = "holdHours", description = "(opt) The number of hours to hold for, used and required if holdType='holdHours'.") @Nullable Number holdHours) {
|
||||
LOGGER.debug("EcobeeActions: Action 'Set Occupied' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
SetOccupiedFunction function = new SetOccupiedFunction(occupied, startDateTime, endDateTime,
|
||||
(holdType == null) ? null : HoldType.forValue(holdType),
|
||||
(holdHours == null) ? null : Integer.valueOf(holdHours.intValue()));
|
||||
return localHandler.actionPerformFunction(function);
|
||||
}
|
||||
|
||||
public static boolean setOccupied(@Nullable ThingActions actions, @Nullable Boolean occupied,
|
||||
@Nullable Date startDateTime, @Nullable Date endDateTime, @Nullable String holdType,
|
||||
@Nullable Number holdHours) {
|
||||
return invokeMethodOf(actions).setOccupied(occupied, startDateTime, endDateTime, holdType, holdHours);
|
||||
}
|
||||
|
||||
/**
|
||||
* The update sensor function allows the caller to update the name of an ecobee3 remote sensor.
|
||||
*
|
||||
* @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/functions/UpdateSensor.shtml">Update
|
||||
* Sensor</a>
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Update Sensor", description = "The update sensor function allows the caller to update the name of an ecobee3 remote sensor.")
|
||||
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean updateSensor(
|
||||
@ActionInput(name = "name", description = "The updated name to give the sensor. Has a max length of 32, but shorter is recommended.") @Nullable String name,
|
||||
@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,
|
||||
@ActionInput(name = "sensorId", description = "The identifier for the sensor within the enclosure. Corresponds to the RemoteSensorCapability.id. For example: 1") @Nullable String sensorId) {
|
||||
LOGGER.debug("EcobeeActions: Action 'UpdateSensor' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return false;
|
||||
}
|
||||
UpdateSensorFunction function = new UpdateSensorFunction(name, deviceId, sensorId);
|
||||
return localHandler.actionPerformFunction(function);
|
||||
}
|
||||
|
||||
public static boolean updateSensor(@Nullable ThingActions actions, @Nullable String name, @Nullable String deviceId,
|
||||
@Nullable String sensorId) {
|
||||
return invokeMethodOf(actions).updateSensor(name, deviceId, sensorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alerts list. Returns a JSON string containing all the alerts.
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Get Alerts", description = "Get the alerts list")
|
||||
public @ActionOutput(name = "alerts", type = "java.lang.String") @Nullable String getAlerts() {
|
||||
LOGGER.debug("EcobeeActions: Action 'Get Alerts' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return null;
|
||||
}
|
||||
return localHandler.getAlerts();
|
||||
}
|
||||
|
||||
public static @Nullable String getAlerts(@Nullable ThingActions actions) {
|
||||
return invokeMethodOf(actions).getAlerts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the events list. Returns a JSON string contains all events.
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Get Events", description = "Get the events list")
|
||||
public @ActionOutput(name = "events", type = "java.lang.String") @Nullable String getEvents() {
|
||||
LOGGER.debug("EcobeeActions: Action 'Get Events' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return null;
|
||||
}
|
||||
return localHandler.getEvents();
|
||||
}
|
||||
|
||||
public static @Nullable String getEvents(@Nullable ThingActions actions) {
|
||||
return invokeMethodOf(actions).getEvents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of climates. Returns a JSON string contains all climates.
|
||||
*/
|
||||
@Override
|
||||
@RuleAction(label = "Get Climates", description = "Get a list of climates")
|
||||
public @ActionOutput(name = "climates", type = "java.lang.String") @Nullable String getClimates() {
|
||||
LOGGER.debug("EcobeeActions: Action 'Get Climates' called");
|
||||
EcobeeThermostatBridgeHandler localHandler = handler;
|
||||
if (localHandler == null) {
|
||||
LOGGER.info("EcobeeActions: Action service ThingHandler is null!");
|
||||
return null;
|
||||
}
|
||||
return localHandler.getClimates();
|
||||
}
|
||||
|
||||
public static @Nullable String getClimates(@Nullable ThingActions actions) {
|
||||
return invokeMethodOf(actions).getClimates();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.action;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
|
||||
/**
|
||||
* The {@link IEcobeeActions} defines the interface for all thing actions supported by the binding.
|
||||
* These methods, parameters, and return types are explained in {@link EcobeeActions}.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface IEcobeeActions {
|
||||
|
||||
public Boolean acknowledge(@Nullable String ackRef, @Nullable String ackType, @Nullable Boolean remindMeLater);
|
||||
|
||||
public Boolean controlPlug(@Nullable String plugName, @Nullable String plugState, @Nullable Date startDateTime,
|
||||
@Nullable Date endDateTime, @Nullable String holdType, @Nullable Number holdHours);
|
||||
|
||||
public Boolean sendMessage(@Nullable String text);
|
||||
|
||||
public Boolean createVacation(@Nullable String name, @Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@Nullable QuantityType<Temperature> heatHoldTemp, @Nullable Date startDateTime, @Nullable Date endDateTime,
|
||||
@Nullable String fan, @Nullable Number fanMinOnTime);
|
||||
|
||||
public Boolean deleteVacation(@Nullable String name);
|
||||
|
||||
public Boolean resetPreferences();
|
||||
|
||||
public Boolean resumeProgram(@Nullable Boolean resumeAll);
|
||||
|
||||
public Boolean setHold(@Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@Nullable QuantityType<Temperature> heatHoldTemp);
|
||||
|
||||
public Boolean setHold(@Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@Nullable QuantityType<Temperature> heatHoldTemp, @Nullable Number holdHours);
|
||||
|
||||
public Boolean setHold(@Nullable String holdClimateRef);
|
||||
|
||||
public Boolean setHold(@Nullable String holdClimateRef, @Nullable Number holdHours);
|
||||
|
||||
public Boolean setHold(@Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@Nullable QuantityType<Temperature> heatHoldTemp, @Nullable String holdClimateRef,
|
||||
@Nullable Date startDateTime, @Nullable Date endDateTime, @Nullable String holdType,
|
||||
@Nullable Number holdHours);
|
||||
|
||||
public Boolean setHold(@Nullable Map<String, Object> params, @Nullable String holdType, @Nullable Number holdHours,
|
||||
@Nullable Date startDateTime, @Nullable Date endDateTime);
|
||||
|
||||
public Boolean setOccupied(@Nullable Boolean occupied, @Nullable Date startDateTime, @Nullable Date endDateTime,
|
||||
@Nullable String holdType, @Nullable Number holdHours);
|
||||
|
||||
public Boolean updateSensor(@Nullable String name, @Nullable String deviceId, @Nullable String sensorId);
|
||||
|
||||
public @Nullable String getAlerts();
|
||||
|
||||
public @Nullable String getEvents();
|
||||
|
||||
public @Nullable String getClimates();
|
||||
}
|
||||
@@ -0,0 +1,399 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.AlertDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.EventDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.HouseDetailsDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.LocationDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ManagementDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.RemoteSensorDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.TechnicianDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatDTO;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeBindingConstants} class defines common constants that are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EcobeeBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "ecobee";
|
||||
|
||||
// Account bridge
|
||||
public static final String THING_TYPE_ACCOUNT = "account";
|
||||
public static final ThingTypeUID UID_ACCOUNT_BRIDGE = new ThingTypeUID(BINDING_ID, THING_TYPE_ACCOUNT);
|
||||
public static final Set<ThingTypeUID> SUPPORTED_ACCOUNT_BRIDGE_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(Stream.of(UID_ACCOUNT_BRIDGE).collect(Collectors.toSet()));
|
||||
|
||||
// Thermostat bridge
|
||||
public static final String THING_TYPE_THERMOSTAT = "thermostat";
|
||||
public static final ThingTypeUID UID_THERMOSTAT_BRIDGE = new ThingTypeUID(BINDING_ID, THING_TYPE_THERMOSTAT);
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THERMOSTAT_BRIDGE_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(Stream.of(UID_THERMOSTAT_BRIDGE).collect(Collectors.toSet()));
|
||||
|
||||
// Remote sensor thing
|
||||
public static final String THING_TYPE_SENSOR = "sensor";
|
||||
public static final ThingTypeUID UID_SENSOR_THING = new ThingTypeUID(BINDING_ID, THING_TYPE_SENSOR);
|
||||
public static final Set<ThingTypeUID> SUPPORTED_SENSOR_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(Stream.of(UID_SENSOR_THING).collect(Collectors.toSet()));
|
||||
|
||||
// Collection of all supported thing types
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(
|
||||
Stream.of(UID_ACCOUNT_BRIDGE, UID_THERMOSTAT_BRIDGE, UID_SENSOR_THING).collect(Collectors.toSet()));
|
||||
|
||||
// Thermostat bridge and remote sensor thing config parameters
|
||||
public static final String CONFIG_THERMOSTAT_ID = "thermostatId";
|
||||
public static final String CONFIG_SENSOR_ID = "sensorId";
|
||||
|
||||
// Channel groups
|
||||
public static final String CHGRP_ALERT = "alerts";
|
||||
public static final String CHGRP_INFO = "info";
|
||||
public static final String CHGRP_ELECTRICITY = "electricity";
|
||||
public static final String CHGRP_EQUIPMENT_STATUS = "equipmentStatus";
|
||||
public static final String CHGRP_EVENT = "events";
|
||||
public static final String CHGRP_EXTENDED_RUNTIME = "extendedRuntime";
|
||||
public static final String CHGRP_HOUSE_DETAILS = "houseDetails";
|
||||
public static final String CHGRP_LOCATION = "location";
|
||||
public static final String CHGRP_MANAGEMENT = "management";
|
||||
public static final String CHGRP_NOTIFICATION_SETTINGS = "notificationSettings";
|
||||
public static final String CHGRP_OEM_CFG = "oemCfg";
|
||||
public static final String CHGRP_PRIVACY = "privacy";
|
||||
public static final String CHGRP_PROGRAM = "program";
|
||||
public static final String CHGRP_RUNTIME = "runtime";
|
||||
public static final String CHGRP_SETTINGS = "settings";
|
||||
public static final String CHGRP_TECHNICIAN = "technician";
|
||||
public static final String CHGRP_UTILITY = "utility";
|
||||
public static final String CHGRP_VERSION = "version";
|
||||
public static final String CHGRP_WEATHER = "weather";
|
||||
public static final String CHGRP_FORECAST = "forecast";
|
||||
|
||||
// Exclude CHGRP_INFO and CHGRP_FORECAST because they are not part of the selection object
|
||||
public static final List<String> CHANNEL_GROUPS = Stream.of(CHGRP_ALERT, CHGRP_ELECTRICITY, CHGRP_EQUIPMENT_STATUS,
|
||||
CHGRP_EVENT, CHGRP_EXTENDED_RUNTIME, CHGRP_HOUSE_DETAILS, CHGRP_LOCATION, CHGRP_MANAGEMENT,
|
||||
CHGRP_NOTIFICATION_SETTINGS, CHGRP_OEM_CFG, CHGRP_PRIVACY, CHGRP_PROGRAM, CHGRP_RUNTIME, CHGRP_SETTINGS,
|
||||
CHGRP_TECHNICIAN, CHGRP_UTILITY, CHGRP_VERSION, CHGRP_WEATHER).collect(Collectors.toList());
|
||||
|
||||
// Thermostat bridge info channels
|
||||
public static final String CH_IDENTIFIER = "identifier";
|
||||
public static final String CH_NAME = "name";
|
||||
public static final String CH_THERMOSTAT_REV = "thermostatRev";
|
||||
public static final String CH_IS_REGISTERED = "isRegistered";
|
||||
public static final String CH_MODEL_NUMBER = "modelNumber";
|
||||
public static final String CH_BRAND = "brand";
|
||||
public static final String CH_FEATURES = "features";
|
||||
public static final String CH_LAST_MODIFIED = "lastModified";
|
||||
public static final String CH_THERMOSTAT_TIME = "thermostatTime";
|
||||
public static final String CH_UTC_TIME = "utcTime";
|
||||
|
||||
// Thermostat bridge equipment status channels
|
||||
public static final String CH_EQUIPMENT_STATUS = "equipmentStatus";
|
||||
|
||||
// Thermostat bridge ALERT channels
|
||||
public static final String CH_ALERT_ACKNOWLEDGE_REF = "acknowledgeRef";
|
||||
public static final String CH_ALERT_DATE = "date";
|
||||
public static final String CH_ALERT_TIME = "time";
|
||||
public static final String CH_ALERT_SEVERITY = "severity";
|
||||
public static final String CH_ALERT_TEXT = "text";
|
||||
public static final String CH_ALERT_ALERT_NUMBER = "number";
|
||||
public static final String CH_ALERT_ALERT_TYPE = "type";
|
||||
public static final String CH_ALERT_IS_OPERATOR_ALERT = "isOperatorAlert";
|
||||
public static final String CH_ALERT_REMINDER = "reminder";
|
||||
public static final String CH_ALERT_SHOW_IDT = "showIdt";
|
||||
public static final String CH_ALERT_SHOW_WEB = "showWeb";
|
||||
public static final String CH_ALERT_SEND_EMAIL = "sendEmail";
|
||||
public static final String CH_ALERT_ACKNOWLEDGEMENT = "acknowledgement";
|
||||
public static final String CH_ALERT_REMIND_ME_LATER = "remindMeLater";
|
||||
public static final String CH_ALERT_THERMOSTAT_IDENTIFIER = "thermostatIdentifier";
|
||||
public static final String CH_ALERT_NOTIFICATION_TYPE = "notificationType";
|
||||
|
||||
// Thermostat bridge EVENT channels
|
||||
public static final String CH_EVENT_NAME = "name";
|
||||
public static final String CH_EVENT_TYPE = "type";
|
||||
public static final String CH_EVENT_RUNNING = "running";
|
||||
public static final String CH_EVENT_START_DATE = "startDate";
|
||||
public static final String CH_EVENT_START_TIME = "startTime";
|
||||
public static final String CH_EVENT_END_DATE = "endDate";
|
||||
public static final String CH_EVENT_END_TIME = "endTime";
|
||||
public static final String CH_EVENT_IS_OCCUPIED = "isOccupied";
|
||||
public static final String CH_EVENT_IS_COOL_OFF = "isCoolOff";
|
||||
public static final String CH_EVENT_IS_HEAT_OFF = "isHeatOff";
|
||||
public static final String CH_EVENT_COOL_HOLD_TEMP = "coolHoldTemp";
|
||||
public static final String CH_EVENT_HEAT_HOLD_TEMP = "heatHoldTemp";
|
||||
public static final String CH_EVENT_FAN = "fan";
|
||||
public static final String CH_EVENT_VENT = "vent";
|
||||
public static final String CH_EVENT_VENTILATOR_MIN_ON_TIME = "ventilatorMinOnTime";
|
||||
public static final String CH_EVENT_IS_OPTIONAL = "isOptional";
|
||||
public static final String CH_EVENT_IS_TEMPERATURE_RELATIVE = "isTemperatureRelative";
|
||||
public static final String CH_EVENT_COOL_RELATIVE_TEMP = "coolRelativeTemp";
|
||||
public static final String CH_EVENT_HEAT_RELATIVE_TEMP = "heatRelativeTemp";
|
||||
public static final String CH_EVENT_IS_TEMPERATURE_ABSOLUTE = "isTemperatureAbsolute";
|
||||
public static final String CH_EVENT_DUTY_CYCLE_PERCENTAGE = "dutyCyclePercentage";
|
||||
public static final String CH_EVENT_FAN_MIN_ON_TIME = "fanMinOnTime";
|
||||
public static final String CH_EVENT_OCCUPIED_SENSOR_ACTIVE = "occupiedSensorActive";
|
||||
public static final String CH_EVENT_UNOCCUPIED_SENSOR_ACTIVE = "unoccupiedSensorActive";
|
||||
public static final String CH_EVENT_DR_RAMP_UP_TEMP = "drRampUpTemp";
|
||||
public static final String CH_EVENT_DR_RAMP_UP_TIME = "drRampUpTime";
|
||||
public static final String CH_EVENT_LINK_REF = "linkRef";
|
||||
public static final String CH_EVENT_HOLD_CLIMATE_REF = "holdClimateRef";
|
||||
|
||||
// Thermostat bridge HOUSE DETAILS channels
|
||||
public static final String CH_HOUSEDETAILS_STYLE = "style";
|
||||
public static final String CH_HOUSEDETAILS_SIZE = "size";
|
||||
public static final String CH_HOUSEDETAILS_NUMBER_OF_FLOORS = "numberOfFloors";
|
||||
public static final String CH_HOUSEDETAILS_NUMBER_OF_ROOMS = "numberOfRooms";
|
||||
public static final String CH_HOUSEDETAILS_NUMBER_OF_OCCUPANTS = "numberOfOccupants";
|
||||
public static final String CH_HOUSEDETAILS_AGE = "age";
|
||||
public static final String CH_HOUSEDETAILS_WINDOW_EFFICIENCY = "windowEfficiency";
|
||||
|
||||
// Thermostat bridge LOCATION channels
|
||||
public static final String CH_TIME_ZONE_OFFSET_MINUTES = "timeZoneOffsetMinutes";
|
||||
public static final String CH_TIME_ZONE = "timeZone";
|
||||
public static final String CH_IS_DAYLIGHT_SAVING = "isDaylightSaving";
|
||||
public static final String CH_STREET_ADDRESS = "streetAddress";
|
||||
public static final String CH_CITY = "city";
|
||||
public static final String CH_PROVINCE_STATE = "provinceState";
|
||||
public static final String CH_COUNTRY = "country";
|
||||
public static final String CH_POSTAL_CODE = "postalCode";
|
||||
public static final String CH_PHONE_NUMBER = "phoneNumber";
|
||||
public static final String CH_MAP_COORDINATES = "mapCoordinates";
|
||||
|
||||
// Thermostat bridge MANAGEMENT channels
|
||||
public static final String CH_MANAGEMENT_ADMIN_CONTACT = "administrativeContact";
|
||||
public static final String CH_MANAGEMENT_BILLING_CONTACT = "billingContact";
|
||||
public static final String CH_MANAGEMENT_NAME = "name";
|
||||
public static final String CH_MANAGEMENT_PHONE = "phone";
|
||||
public static final String CH_MANAGEMENT_EMAIL = "email";
|
||||
public static final String CH_MANAGEMENT_WEB = "web";
|
||||
public static final String CH_MANAGEMENT_SHOW_ALERT_IDT = "showAlertIdt";
|
||||
public static final String CH_MANAGEMENT_SHOW_ALERT_WEB = "showAlertWeb";
|
||||
|
||||
// Thermostat bridge PROGRAM channels
|
||||
public static final String CH_PROGRAM_CURRENT_CLIMATE_REF = "currentClimateRef";
|
||||
|
||||
// Thermostat bridge RUNTIME channels
|
||||
public static final String CH_RUNTIME_REV = "runtimeRev";
|
||||
public static final String CH_CONNECTED = "connected";
|
||||
public static final String CH_FIRST_CONNECTED = "firstConnected";
|
||||
public static final String CH_CONNECT_DATE_TIME = "connectDateTime";
|
||||
public static final String CH_DISCONNECT_DATE_TIME = "disconnectDateTime";
|
||||
public static final String CH_RT_LAST_MODIFIED = "lastModified";
|
||||
public static final String CH_RT_LAST_STATUS_MODIFIED = "lastStatusModified";
|
||||
public static final String CH_RUNTIME_DATE = "runtimeDate";
|
||||
public static final String CH_RUNTIME_INTERVAL = "runtimeInterval";
|
||||
public static final String CH_ACTUAL_TEMPERATURE = "actualTemperature";
|
||||
public static final String CH_ACTUAL_HUMIDITY = "actualHumidity";
|
||||
public static final String CH_RAW_TEMPERATURE = "rawTemperature";
|
||||
public static final String CH_SHOW_ICON_MODE = "showIconMode";
|
||||
public static final String CH_DESIRED_HEAT = "desiredHeat";
|
||||
public static final String CH_DESIRED_COOL = "desiredCool";
|
||||
public static final String CH_DESIRED_HUMIDITY = "desiredHumidity";
|
||||
public static final String CH_DESIRED_DEHUMIDITY = "desiredDehumidity";
|
||||
public static final String CH_DESIRED_FAN_MODE = "desiredFanMode";
|
||||
public static final String CH_DESIRED_HEAT_RANGE_LOW = "desiredHeatRangeLow";
|
||||
public static final String CH_DESIRED_HEAT_RANGE_HIGH = "desiredHeatRangeHigh";
|
||||
public static final String CH_DESIRED_COOL_RANGE_LOW = "desiredCoolRangeLow";
|
||||
public static final String CH_DESIRED_COOL_RANGE_HIGH = "desiredCoolRangeHigh";
|
||||
|
||||
// Thermostat bridge SETTINGS channels
|
||||
public static final String CH_HVAC_MODE = "hvacMode";
|
||||
public static final String CH_LAST_SERVICE_DATE = "lastServiceDate";
|
||||
public static final String CH_SERVICE_REMIND_ME = "serviceRemindMe";
|
||||
public static final String CH_MONTHS_BETWEEN_SERVICE = "monthsBetweenService";
|
||||
public static final String CH_REMIND_ME_DATE = "remindMeDate";
|
||||
public static final String CH_VENT = "vent";
|
||||
public static final String CH_VENTILATOR_MIN_ON_TIME = "ventilatorMinOnTime";
|
||||
public static final String CH_SERVICE_REMIND_TECHNICIAN = "serviceRemindTechnician";
|
||||
public static final String CH_EI_LOCATION = "eiLocation";
|
||||
public static final String CH_COLD_TEMP_ALERT = "coldTempAlert";
|
||||
public static final String CH_COLD_TEMP_ALERT_ENABLED = "coldTempAlertEnabled";
|
||||
public static final String CH_HOT_TEMP_ALERT = "hotTempAlert";
|
||||
public static final String CH_HOT_TEMP_ALERT_ENABLED = "hotTempAlertEnabled";
|
||||
public static final String CH_COOL_STAGES = "coolStages";
|
||||
public static final String CH_HEAT_STAGES = "heatStages";
|
||||
public static final String CH_MAX_SET_BACK = "maxSetBack";
|
||||
public static final String CH_MAX_SET_FORWARD = "maxSetForward";
|
||||
public static final String CH_QUICK_SAVE_SET_BACK = "quickSaveSetBack";
|
||||
public static final String CH_QUICK_SAVE_SET_FORWARD = "quickSaveSetForward";
|
||||
public static final String CH_HAS_HEAT_PUMP = "hasHeatPump";
|
||||
public static final String CH_HAS_FORCED_AIR = "hasForcedAir";
|
||||
public static final String CH_HAS_BOILER = "hasBoiler";
|
||||
public static final String CH_HAS_HUMIDIFIER = "hasHumidifier";
|
||||
public static final String CH_HAS_ERV = "hasErv";
|
||||
public static final String CH_HAS_HRV = "hasHrv";
|
||||
public static final String CH_CONDENSATION_AVOID = "condensationAvoid";
|
||||
public static final String CH_USE_CELSIUS = "useCelsius";
|
||||
public static final String CH_USE_TIME_FORMAT_12 = "useTimeFormat12";
|
||||
public static final String CH_LOCALE = "locale";
|
||||
public static final String CH_HUMIDITY = "humidity";
|
||||
public static final String CH_HUMIDIFIER_MODE = "humidifierMode";
|
||||
public static final String CH_BACKLIGHT_ON_INTENSITY = "backlightOnIntensity";
|
||||
public static final String CH_BACKLIGHT_SLEEP_INTENSITY = "backlightSleepIntensity";
|
||||
public static final String CH_BACKLIGHT_OFF_TIME = "backlightOffTime";
|
||||
public static final String CH_SOUND_TICK_VOLUME = "soundTickVolume";
|
||||
public static final String CH_SOUND_ALERT_VOLUME = "soundAlertVolume";
|
||||
public static final String CH_COMPRESSOR_PROTECTION_MIN_TIME = "compressorProtectionMinTime";
|
||||
public static final String CH_COMPRESSOR_PROTECTION_MIN_TEMP = "compressorProtectionMinTemp";
|
||||
public static final String CH_STAGE1_HEATING_DIFFERENTIAL_TEMP = "stage1HeatingDifferentialTemp";
|
||||
public static final String CH_STAGE1_COOLING_DIFFERENTIAL_TEMP = "stage1CoolingDifferentialTemp";
|
||||
public static final String CH_STAGE1_HEATING_DISSIPATION_TIME = "stage1HeatingDissipationTime";
|
||||
public static final String CH_STAGE1_COOLING_DISSIPATION_TIME = "stage1CoolingDissipationTime";
|
||||
public static final String CH_HEAT_PUMP_REVERSAL_ON_COOL = "heatPumpReversalOnCool";
|
||||
public static final String CH_FAN_CONTROLLER_REQUIRED = "fanControlRequired";
|
||||
public static final String CH_FAN_MIN_ON_TIME = "fanMinOnTime";
|
||||
public static final String CH_HEAT_COOL_MIN_DELTA = "heatCoolMinDelta";
|
||||
public static final String CH_TEMP_CORRECTION = "tempCorrection";
|
||||
public static final String CH_HOLD_ACTION = "holdAction";
|
||||
public static final String CH_HEAT_PUMP_GROUND_WATER = "heatPumpGroundWater";
|
||||
public static final String CH_HAS_ELECTRIC = "hasElectric";
|
||||
public static final String CH_HAS_DEHUMIDIFIER = "hasDehumidifier";
|
||||
public static final String CH_DEHUMIDIFIER_MODE = "dehumidifierMode";
|
||||
public static final String CH_DEHUMIDIFIER_LEVEL = "dehumidifierLevel";
|
||||
public static final String CH_DEHUMIDIFY_WITH_AC = "dehumidifyWithAC";
|
||||
public static final String CH_DEHUMIDIFY_OVERCOOL_OFFSET = "dehumidifyOvercoolOffset";
|
||||
public static final String CH_AUTO_HEAT_COOL_FEATURE_ENABLED = "autoHeatCoolFeatureEnabled";
|
||||
public static final String CH_WIFI_OFFLINE_ALERT = "wifiOfflineAlert";
|
||||
public static final String CH_HEAT_MIN_TEMP = "heatMinTemp";
|
||||
public static final String CH_HEAT_MAX_TEMP = "heatMaxTemp";
|
||||
public static final String CH_COOL_MIN_TEMP = "coolMinTemp";
|
||||
public static final String CH_COOL_MAX_TEMP = "coolMaxTemp";
|
||||
public static final String CH_HEAT_RANGE_HIGH = "heatRangeHigh";
|
||||
public static final String CH_HEAT_RANGE_LOW = "heatRangeLow";
|
||||
public static final String CH_COOL_RANGE_HIGH = "coolRangeHigh";
|
||||
public static final String CH_COOL_RANGE_LOW = "coolRangeLow";
|
||||
public static final String CH_USER_ACCESS_CODE = "userAccessCode";
|
||||
public static final String CH_USER_ACCESS_SETTING = "userAccessSetting";
|
||||
public static final String CH_AUX_RUNTIME_ALERT = "auxRuntimeAlert";
|
||||
public static final String CH_AUX_OUTDOOR_TEMP_ALERT = "auxOutdoorTempAlert";
|
||||
public static final String CH_AUX_MAX_OUTDOOR_TEMP = "auxMaxOutdoorTemp";
|
||||
public static final String CH_AUX_RUNTIME_ALERT_NOTIFY = "auxRuntimeAlertNotify";
|
||||
public static final String CH_AUX_OUTDOOR_TEMP_ALERT_NOTIFY = "auxOutdoorTempAlertNotify";
|
||||
public static final String CH_AUX_RUNTIME_ALERT_NOTIFY_TECHNICIAN = "auxRuntimeAlertNotifyTechnician";
|
||||
public static final String CH_AUX_OUTDOOR_TEMP_ALERT_NOTIFY_TECHNICIAN = "auxOutdoorTempAlertNotifyTechnician";
|
||||
public static final String CH_DISABLE_PREHEATING = "disablePreHeating";
|
||||
public static final String CH_DISABLE_PRECOOLING = "disablePreCooling";
|
||||
public static final String CH_INSTALLER_CODE_REQUIRED = "installerCodeRequired";
|
||||
public static final String CH_DR_ACCEPT = "drAccept";
|
||||
public static final String CH_IS_RENTAL_PROPERTY = "isRentalProperty";
|
||||
public static final String CH_USE_ZONE_CONTROLLER = "useZoneController";
|
||||
public static final String CH_RANDOM_START_DELAY_COOL = "randomStartDelayCool";
|
||||
public static final String CH_RANDOM_START_DELAY_HEAT = "randomStartDelayHeat";
|
||||
public static final String CH_HUMIDITY_HIGH_ALERT = "humidityHighAlert";
|
||||
public static final String CH_HUMIDITY_LOW_ALERT = "humidityLowAlert";
|
||||
public static final String CH_DISABLE_HEAT_PUMP_ALERTS = "disableHeatPumpAlerts";
|
||||
public static final String CH_DISABLE_ALERTS_ON_IDT = "disableAlertsOnIdt";
|
||||
public static final String CH_HUMIDITY_ALERT_NOTIFY = "humidityAlertNotify";
|
||||
public static final String CH_HUMIDITY_ALERT_NOTIFY_TECHNICIAN = "humidityAlertNotifyTechnician";
|
||||
public static final String CH_TEMP_ALERT_NOTIFY = "tempAlertNotify";
|
||||
public static final String CH_TEMP_ALERT_NOTIFY_TECHNICIAN = "tempAlertNotifyTechnician";
|
||||
public static final String CH_MONTHLY_ELECTRICITY_BILL_LIMIT = "monthlyElectricityBillLimit";
|
||||
public static final String CH_ENABLE_ELECTRICITY_BILL_ALERT = "enableElectricityBillAlert";
|
||||
public static final String CH_ENABLE_PROJECTED_ELECTRICITY_BILL_ALERT = "enableProjectedElectricityBillAlert";
|
||||
public static final String CH_ELECTRICITY_BILLING_DAY_OF_MONTH = "electricityBillingDayOfMonth";
|
||||
public static final String CH_ELECTRICITY_BILL_CYCLE_MONTHS = "electricityBillCycleMonths";
|
||||
public static final String CH_ELECTRICITY_BILL_START_MONTH = "electricityBillStartMonth";
|
||||
public static final String CH_VENTILATOR_MIN_ON_TIME_HOME = "ventilatorMinOnTimeHome";
|
||||
public static final String CH_VENTILATOR_MIN_ON_TIME_AWAY = "ventilatorMinOnTimeAway";
|
||||
public static final String CH_BACKLIGHT_OFF_DURING_SLEEP = "backlightOffDuringSleep";
|
||||
public static final String CH_AUTO_AWAY = "autoAway";
|
||||
public static final String CH_SMART_CIRCULATION = "smartCirculation";
|
||||
public static final String CH_FOLLOW_ME_COMFORT = "followMeComfort";
|
||||
public static final String CH_VENTILATOR_TYPE = "ventilatorType";
|
||||
public static final String CH_IS_VENTILATOR_TIMER_ON = "isVentilatorTimerOn";
|
||||
public static final String CH_VENTILATOR_OFF_DATE_TIME = "ventilatorOffDateTime";
|
||||
public static final String CH_HAS_UV_FILTER = "hasUVFilter";
|
||||
public static final String CH_COOLING_LOCKOUT = "coolingLockout";
|
||||
public static final String CH_VENTILATOR_FREE_COOLING = "ventilatorFreeCooling";
|
||||
public static final String CH_DEHUMIDIFY_WHEN_HEATING = "dehumidifyWhenHeating";
|
||||
public static final String CH_VENTILATOR_DEHUMIDIFY = "ventilatorDehumidify";
|
||||
public static final String CH_GROUP_REF = "groupRef";
|
||||
public static final String CH_GROUP_NAME = "groupName";
|
||||
public static final String CH_GROUP_SETTING = "groupSetting";
|
||||
|
||||
// Thermostat bridge TECHNICIAN channels
|
||||
public static final String CH_TECHNICIAN_CONTRACTOR_REF = "contractorRef";
|
||||
public static final String CH_TECHNICIAN_NAME = "name";
|
||||
public static final String CH_TECHNICIAN_PHONE = "phone";
|
||||
public static final String CH_TECHNICIAN_STREET_ADDRESS = "streetAddress";
|
||||
public static final String CH_TECHNICIAN_CITY = "city";
|
||||
public static final String CH_TECHNICIAN_PROVINCE_STATE = "provinceState";
|
||||
public static final String CH_TECHNICIAN_COUNTRY = "country";
|
||||
public static final String CH_TECHNICIAN_POSTAL_CODE = "postalCode";
|
||||
public static final String CH_TECHNICIAN_EMAIL = "email";
|
||||
public static final String CH_TECHNICIAN_WEB = "web";
|
||||
|
||||
// Thermostat bridge VERSION channels
|
||||
public static final String CH_THERMOSTAT_FIRMWARE_VERSION = "thermostatFirmwareVersion";
|
||||
|
||||
// Thermostat bridge WEATHER channels
|
||||
public static final String CH_WEATHER_TIMESTAMP = "timestamp";
|
||||
public static final String CH_WEATHER_WEATHER_STATION = "weatherStation";
|
||||
|
||||
// Thermostat bridge FORECAST channels
|
||||
public static final String CH_FORECAST_WEATHER_SYMBOL = "weatherSymbol";
|
||||
public static final String CH_FORECAST_WEATHER_SYMBOL_TEXT = "weatherSymbolText";
|
||||
public static final String CH_FORECAST_DATE_TIME = "dateTime";
|
||||
public static final String CH_FORECAST_CONDITION = "condition";
|
||||
public static final String CH_FORECAST_TEMPERATURE = "temperature";
|
||||
public static final String CH_FORECAST_PRESSURE = "pressure";
|
||||
public static final String CH_FORECAST_RELATIVE_HUMIDITY = "relativeHumidity";
|
||||
public static final String CH_FORECAST_DEWPOINT = "dewpoint";
|
||||
public static final String CH_FORECAST_VISIBILITY = "visibility";
|
||||
public static final String CH_FORECAST_WIND_SPEED = "windSpeed";
|
||||
public static final String CH_FORECAST_WIND_GUST = "windGust";
|
||||
public static final String CH_FORECAST_WIND_DIRECTION = "windDirection";
|
||||
public static final String CH_FORECAST_WIND_BEARING = "windBearing";
|
||||
public static final String CH_FORECAST_POP = "pop";
|
||||
public static final String CH_FORECAST_TEMP_HIGH = "tempHigh";
|
||||
public static final String CH_FORECAST_TEMP_LOW = "tempLow";
|
||||
public static final String CH_FORECAST_SKY = "sky";
|
||||
public static final String CH_FORECAST_SKY_TEXT = "skyText";
|
||||
|
||||
// Remote sensor thing channel IDs
|
||||
public static final String CH_SENSOR_ID = "id";
|
||||
public static final String CH_SENSOR_NAME = "name";
|
||||
public static final String CH_SENSOR_TYPE = "type";
|
||||
public static final String CH_SENSOR_CODE = "code";
|
||||
public static final String CH_SENSOR_IN_USE = "inUse";
|
||||
|
||||
// Channel Type UIDs for dynamically created sensor channels
|
||||
public static final ChannelTypeUID CHANNELTYPEUID_TEMPERATURE = new ChannelTypeUID(BINDING_ID, "sensorTemperature");
|
||||
public static final ChannelTypeUID CHANNELTYPEUID_HUMIDITY = new ChannelTypeUID(BINDING_ID, "sensorHumidity");
|
||||
public static final ChannelTypeUID CHANNELTYPEUID_OCCUPANCY = new ChannelTypeUID(BINDING_ID, "sensorOccupancy");
|
||||
public static final ChannelTypeUID CHANNELTYPEUID_GENERIC = new ChannelTypeUID(BINDING_ID, "sensorGeneric");
|
||||
|
||||
public static final AlertDTO EMPTY_ALERT = new AlertDTO();
|
||||
public static final EventDTO EMPTY_EVENT = new EventDTO();
|
||||
public static final LocationDTO EMPTY_LOCATION = new LocationDTO();
|
||||
public static final HouseDetailsDTO EMPTY_HOUSEDETAILS = new HouseDetailsDTO();
|
||||
public static final ManagementDTO EMPTY_MANAGEMENT = new ManagementDTO();
|
||||
public static final TechnicianDTO EMPTY_TECHNICIAN = new TechnicianDTO();
|
||||
public static final List<RemoteSensorDTO> EMPTY_SENSORS = Collections.<RemoteSensorDTO> emptyList();
|
||||
public static final List<ThermostatDTO> EMPTY_THERMOSTATS = Collections.<ThermostatDTO> emptyList();
|
||||
|
||||
public static final String ECOBEE_BASE_URL = "https://api.ecobee.com/";
|
||||
public static final String ECOBEE_AUTHORIZE_URL = ECOBEE_BASE_URL + "authorize";
|
||||
public static final String ECOBEE_TOKEN_URL = ECOBEE_BASE_URL + "token";
|
||||
public static final String ECOBEE_SCOPE = "smartWrite";
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal;
|
||||
|
||||
import static org.openhab.binding.ecobee.internal.EcobeeBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.ecobee.internal.handler.EcobeeAccountBridgeHandler;
|
||||
import org.openhab.binding.ecobee.internal.handler.EcobeeSensorThingHandler;
|
||||
import org.openhab.binding.ecobee.internal.handler.EcobeeThermostatBridgeHandler;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthFactory;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.openhab.core.thing.type.ChannelTypeRegistry;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeHandlerFactory} is responsible for creating thing handlers
|
||||
* for the account bridge, thermostat bridge, and sensor thing.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.ecobee", service = ThingHandlerFactory.class)
|
||||
public class EcobeeHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
private final ChannelTypeRegistry channelTypeRegistry;
|
||||
private final OAuthFactory oAuthFactory;
|
||||
private final HttpClient httpClient;
|
||||
|
||||
@Activate
|
||||
public EcobeeHandlerFactory(@Reference TimeZoneProvider timeZoneProvider,
|
||||
@Reference ChannelTypeRegistry channelTypeRegistry, @Reference OAuthFactory oAuthFactory,
|
||||
@Reference HttpClientFactory httpClientFactory) {
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
this.channelTypeRegistry = channelTypeRegistry;
|
||||
this.oAuthFactory = oAuthFactory;
|
||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (SUPPORTED_ACCOUNT_BRIDGE_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||
return new EcobeeAccountBridgeHandler((Bridge) thing, oAuthFactory, httpClient);
|
||||
}
|
||||
if (SUPPORTED_THERMOSTAT_BRIDGE_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||
return new EcobeeThermostatBridgeHandler((Bridge) thing, timeZoneProvider, channelTypeRegistry);
|
||||
}
|
||||
if (SUPPORTED_SENSOR_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||
return new EcobeeSensorThingHandler(thing);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.api;
|
||||
|
||||
import static org.openhab.binding.ecobee.internal.EcobeeBindingConstants.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.ecobee.internal.dto.AbstractResponseDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.SelectionDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.SelectionType;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatRequestDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatResponseDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatUpdateRequestDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.summary.RevisionDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.summary.RevisionDTODeserializer;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.summary.RunningDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.summary.RunningDTODeserializer;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.summary.SummaryResponseDTO;
|
||||
import org.openhab.binding.ecobee.internal.function.FunctionRequest;
|
||||
import org.openhab.binding.ecobee.internal.handler.EcobeeAccountBridgeHandler;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenRefreshListener;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthClientService;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthException;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthFactory;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthResponseException;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeApi} is responsible for managing all communication with
|
||||
* the Ecobee API service.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EcobeeApi implements AccessTokenRefreshListener {
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||
.registerTypeAdapter(RevisionDTO.class, new RevisionDTODeserializer())
|
||||
.registerTypeAdapter(RunningDTO.class, new RunningDTODeserializer()).create();
|
||||
|
||||
private static final String ECOBEE_THERMOSTAT_URL = ECOBEE_BASE_URL + "1/thermostat";
|
||||
private static final String ECOBEE_THERMOSTAT_SUMMARY_URL = ECOBEE_BASE_URL + "1/thermostatSummary";
|
||||
private static final String ECOBEE_THERMOSTAT_UPDATE_URL = ECOBEE_THERMOSTAT_URL + "?format=json";
|
||||
|
||||
// These errors from the API will require an Ecobee authorization
|
||||
private static final int ECOBEE_TOKEN_EXPIRED = 14;
|
||||
private static final int ECOBEE_DEAUTHORIZED_TOKEN = 16;
|
||||
private static final int TOKEN_EXPIRES_IN_BUFFER_SECONDS = 120;
|
||||
|
||||
public static final Properties HTTP_HEADERS;
|
||||
static {
|
||||
HTTP_HEADERS = new Properties();
|
||||
HTTP_HEADERS.put("Content-Type", "application/json;charset=UTF-8");
|
||||
HTTP_HEADERS.put("User-Agent", "openhab-ecobee-api/2.0");
|
||||
}
|
||||
|
||||
public static Gson getGson() {
|
||||
return GSON;
|
||||
}
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EcobeeApi.class);
|
||||
|
||||
private final EcobeeAccountBridgeHandler bridgeHandler;
|
||||
|
||||
private final String apiKey;
|
||||
private int apiTimeout;
|
||||
private final OAuthFactory oAuthFactory;
|
||||
private final HttpClient httpClient;
|
||||
|
||||
private @NonNullByDefault({}) OAuthClientService oAuthClientService;
|
||||
private @NonNullByDefault({}) EcobeeAuth ecobeeAuth;
|
||||
|
||||
private @Nullable AccessTokenResponse accessTokenResponse;
|
||||
|
||||
public EcobeeApi(final EcobeeAccountBridgeHandler bridgeHandler, final String apiKey, final int apiTimeout,
|
||||
org.openhab.core.auth.client.oauth2.OAuthFactory oAuthFactory, HttpClient httpClient) {
|
||||
this.bridgeHandler = bridgeHandler;
|
||||
this.apiKey = apiKey;
|
||||
this.apiTimeout = apiTimeout;
|
||||
this.oAuthFactory = oAuthFactory;
|
||||
this.httpClient = httpClient;
|
||||
|
||||
createOAuthClientService();
|
||||
}
|
||||
|
||||
public void createOAuthClientService() {
|
||||
logger.debug("API: Creating OAuth Client Service");
|
||||
OAuthClientService service = oAuthFactory.createOAuthClientService(
|
||||
bridgeHandler.getThing().getUID().getAsString(), ECOBEE_TOKEN_URL, null, apiKey, "", ECOBEE_SCOPE,
|
||||
false);
|
||||
service.addAccessTokenRefreshListener(this);
|
||||
ecobeeAuth = new EcobeeAuth(bridgeHandler, apiKey, apiTimeout, service, httpClient);
|
||||
oAuthClientService = service;
|
||||
}
|
||||
|
||||
public void deleteOAuthClientService() {
|
||||
logger.debug("API: Deleting OAuth Client Service");
|
||||
oAuthClientService.removeAccessTokenRefreshListener(this);
|
||||
oAuthFactory.deleteServiceAndAccessToken(bridgeHandler.getThing().getUID().getAsString());
|
||||
}
|
||||
|
||||
public void closeOAuthClientService() {
|
||||
logger.debug("API: Closing OAuth Client Service");
|
||||
oAuthClientService.removeAccessTokenRefreshListener(this);
|
||||
oAuthFactory.ungetOAuthService(bridgeHandler.getThing().getUID().getAsString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the Ecobee authorization process is complete. This will be determined
|
||||
* by requesting an AccessTokenResponse from the OHC OAuth service. If we get a valid
|
||||
* response, then assume that the Ecobee authorization process is complete. Otherwise,
|
||||
* start the Ecobee authorization process.
|
||||
*/
|
||||
private boolean isAuthorized() {
|
||||
boolean isAuthorized = false;
|
||||
try {
|
||||
AccessTokenResponse localAccessTokenResponse = oAuthClientService.getAccessTokenResponse();
|
||||
if (localAccessTokenResponse != null) {
|
||||
logger.trace("API: Got AccessTokenResponse from OAuth service: {}", localAccessTokenResponse);
|
||||
if (localAccessTokenResponse.isExpired(LocalDateTime.now(), TOKEN_EXPIRES_IN_BUFFER_SECONDS)) {
|
||||
logger.debug("API: Token is expiring soon. Refresh it now");
|
||||
localAccessTokenResponse = oAuthClientService.refreshToken();
|
||||
}
|
||||
ecobeeAuth.setState(EcobeeAuthState.COMPLETE);
|
||||
isAuthorized = true;
|
||||
} else {
|
||||
logger.debug("API: Didn't get an AccessTokenResponse from OAuth service - doEcobeeAuthorization!!!");
|
||||
if (ecobeeAuth.isComplete()) {
|
||||
ecobeeAuth.setState(EcobeeAuthState.NEED_PIN);
|
||||
}
|
||||
}
|
||||
accessTokenResponse = localAccessTokenResponse;
|
||||
ecobeeAuth.doAuthorization();
|
||||
} catch (OAuthException | IOException | RuntimeException e) {
|
||||
logger.info("API: Got exception trying to get access token from OAuth service", e);
|
||||
} catch (EcobeeAuthException e) {
|
||||
logger.info("API: The Ecobee authorization process threw an exception", e);
|
||||
ecobeeAuth.setState(EcobeeAuthState.NEED_PIN);
|
||||
} catch (OAuthResponseException e) {
|
||||
logger.info("API: Exception getting access token: error='{}', description='{}'", e.getError(),
|
||||
e.getErrorDescription());
|
||||
// How to handle the possible error codes?
|
||||
}
|
||||
return isAuthorized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccessTokenResponse(AccessTokenResponse accessTokenResponse) {
|
||||
}
|
||||
|
||||
public @Nullable SummaryResponseDTO performThermostatSummaryQuery() {
|
||||
logger.debug("API: Perform thermostat summary query");
|
||||
if (!isAuthorized()) {
|
||||
return null;
|
||||
}
|
||||
SelectionDTO selection = new SelectionDTO();
|
||||
selection.selectionType = SelectionType.REGISTERED;
|
||||
selection.includeEquipmentStatus = Boolean.TRUE;
|
||||
String requestJson = GSON.toJson(new ThermostatRequestDTO(selection), ThermostatRequestDTO.class);
|
||||
String response = executeGet(ECOBEE_THERMOSTAT_SUMMARY_URL, requestJson);
|
||||
if (response != null) {
|
||||
try {
|
||||
SummaryResponseDTO summaryResponse = GSON.fromJson(response, SummaryResponseDTO.class);
|
||||
if (isSuccess(summaryResponse)) {
|
||||
return summaryResponse;
|
||||
}
|
||||
} catch (JsonSyntaxException e) {
|
||||
logJSException(e, response);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<ThermostatDTO> queryRegisteredThermostats() {
|
||||
return performThermostatQuery(null);
|
||||
}
|
||||
|
||||
public List<ThermostatDTO> performThermostatQuery(final @Nullable Set<String> thermostatIds) {
|
||||
logger.debug("API: Perform query on thermostat: '{}'", thermostatIds);
|
||||
if (!isAuthorized()) {
|
||||
return EMPTY_THERMOSTATS;
|
||||
}
|
||||
SelectionDTO selection = bridgeHandler.getSelection();
|
||||
selection.setThermostats(thermostatIds);
|
||||
String requestJson = GSON.toJson(new ThermostatRequestDTO(selection), ThermostatRequestDTO.class);
|
||||
String response = executeGet(ECOBEE_THERMOSTAT_URL, requestJson);
|
||||
if (response != null) {
|
||||
try {
|
||||
ThermostatResponseDTO thermostatsResponse = GSON.fromJson(response, ThermostatResponseDTO.class);
|
||||
if (isSuccess(thermostatsResponse)) {
|
||||
return thermostatsResponse.thermostatList;
|
||||
}
|
||||
} catch (JsonSyntaxException e) {
|
||||
logJSException(e, response);
|
||||
}
|
||||
}
|
||||
return EMPTY_THERMOSTATS;
|
||||
}
|
||||
|
||||
public boolean performThermostatFunction(FunctionRequest request) {
|
||||
logger.debug("API: Perform function on thermostat: '{}'", request.selection.selectionMatch);
|
||||
if (!isAuthorized()) {
|
||||
return false;
|
||||
}
|
||||
return executePost(ECOBEE_THERMOSTAT_URL, GSON.toJson(request, FunctionRequest.class));
|
||||
}
|
||||
|
||||
public boolean performThermostatUpdate(ThermostatUpdateRequestDTO request) {
|
||||
logger.debug("API: Perform update on thermostat: '{}'", request.selection.selectionMatch);
|
||||
if (!isAuthorized()) {
|
||||
return false;
|
||||
}
|
||||
return executePost(ECOBEE_THERMOSTAT_UPDATE_URL, GSON.toJson(request, ThermostatUpdateRequestDTO.class));
|
||||
}
|
||||
|
||||
private String buildQueryUrl(String baseUrl, String requestJson) throws UnsupportedEncodingException {
|
||||
final StringBuilder urlBuilder = new StringBuilder(baseUrl);
|
||||
urlBuilder.append("?json=");
|
||||
urlBuilder.append(URLEncoder.encode(requestJson, StandardCharsets.UTF_8.toString()));
|
||||
return urlBuilder.toString();
|
||||
}
|
||||
|
||||
private @Nullable String executeGet(String url, String json) {
|
||||
String response = null;
|
||||
try {
|
||||
long startTime = System.currentTimeMillis();
|
||||
logger.trace("API: Get Request json is '{}'", json);
|
||||
response = HttpUtil.executeUrl("GET", buildQueryUrl(url, json), setHeaders(), null, null, apiTimeout);
|
||||
logger.trace("API: Response took {} msec: {}", System.currentTimeMillis() - startTime, response);
|
||||
} catch (IOException e) {
|
||||
logIOException(e);
|
||||
} catch (EcobeeAuthException e) {
|
||||
logger.info("API: Unable to execute GET: {}", e.getMessage());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private boolean executePost(String url, String json) {
|
||||
try {
|
||||
logger.trace("API: Post request json is '{}'", json);
|
||||
long startTime = System.currentTimeMillis();
|
||||
String response = HttpUtil.executeUrl("POST", url, setHeaders(), new ByteArrayInputStream(json.getBytes()),
|
||||
"application/json", apiTimeout);
|
||||
logger.trace("API: Response took {} msec: {}", System.currentTimeMillis() - startTime, response);
|
||||
try {
|
||||
ThermostatResponseDTO thermostatsResponse = GSON.fromJson(response, ThermostatResponseDTO.class);
|
||||
return isSuccess(thermostatsResponse);
|
||||
} catch (JsonSyntaxException e) {
|
||||
logJSException(e, response);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logIOException(e);
|
||||
} catch (EcobeeAuthException e) {
|
||||
logger.info("API: Unable to execute POST: {}", e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void logIOException(Exception e) {
|
||||
Throwable rootCause = ExceptionUtils.getRootCause(e);
|
||||
if (rootCause instanceof TimeoutException || rootCause instanceof EOFException) {
|
||||
// These are "normal" errors and should be logged as DEBUG
|
||||
logger.debug("API: Call to Ecobee API failed with exception: {}: {}", rootCause.getClass().getSimpleName(),
|
||||
rootCause.getMessage());
|
||||
} else {
|
||||
// What's left are unexpected errors that should be logged as INFO with a full stack trace
|
||||
logger.info("API: Call to Ecobee API failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void logJSException(Exception e, String response) {
|
||||
// The API sometimes returns an HTML page complaining of an SSL error
|
||||
// Otherwise, this probably should be INFO level
|
||||
logger.debug("API: JsonSyntaxException parsing response: {}", response, e);
|
||||
}
|
||||
|
||||
private boolean isSuccess(@Nullable AbstractResponseDTO response) {
|
||||
boolean success = true;
|
||||
if (response == null) {
|
||||
logger.info("API: Ecobee API returned null response");
|
||||
success = false;
|
||||
} else if (response.status.code.intValue() != 0) {
|
||||
logger.info("API: Ecobee API returned unsuccessful status: code={}, message={}", response.status.code,
|
||||
response.status.message);
|
||||
if (response.status.code == ECOBEE_DEAUTHORIZED_TOKEN) {
|
||||
// Token has been deauthorized, so restart the authorization process from the beginning
|
||||
logger.warn("API: Reset OAuth Client Service due to deauthorized token");
|
||||
deleteOAuthClientService();
|
||||
createOAuthClientService();
|
||||
} else if (response.status.code == ECOBEE_TOKEN_EXPIRED) {
|
||||
// Check isAuthorized again to see if we can get a valid token
|
||||
logger.info("API: Unable to complete API call because token is expired");
|
||||
if (!isAuthorized()) {
|
||||
logger.warn("API: isAuthorized was NOT successful on second try");
|
||||
}
|
||||
}
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private Properties setHeaders() throws EcobeeAuthException {
|
||||
AccessTokenResponse atr = accessTokenResponse;
|
||||
if (atr == null) {
|
||||
throw new EcobeeAuthException("Can not set auth header because access token is null");
|
||||
}
|
||||
Properties headers = new Properties();
|
||||
headers.putAll(HTTP_HEADERS);
|
||||
headers.put("Authorization", "Bearer " + atr.getAccessToken());
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.api;
|
||||
|
||||
import static org.openhab.binding.ecobee.internal.EcobeeBindingConstants.*;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.HttpResponseException;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.openhab.binding.ecobee.internal.dto.oauth.AuthorizeResponseDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.oauth.TokenResponseDTO;
|
||||
import org.openhab.binding.ecobee.internal.handler.EcobeeAccountBridgeHandler;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthClientService;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthException;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeAuth} performs the initial OAuth authorization
|
||||
* with the Ecobee authorization servers. Once this process is complete, the
|
||||
* AccessTokenResponse will be imported into the OHC OAuth Client Service. At
|
||||
* that point, the OHC OAuth service will be responsible for refreshing tokens.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EcobeeAuth {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EcobeeAuth.class);
|
||||
|
||||
private final EcobeeAccountBridgeHandler bridgeHandler;
|
||||
private final String apiKey;
|
||||
private final int apiTimeout;
|
||||
private final OAuthClientService oAuthClientService;
|
||||
private final HttpClient httpClient;
|
||||
|
||||
private EcobeeAuthState state;
|
||||
|
||||
private @Nullable AuthorizeResponseDTO authResponse;
|
||||
|
||||
private long pinExpirationTime;
|
||||
|
||||
/**
|
||||
* The authorization code needed to make the first-time request
|
||||
* of the refresh and access tokens. Obtained from the call to {@code authorize()}.
|
||||
*/
|
||||
private @Nullable String code;
|
||||
|
||||
public EcobeeAuth(EcobeeAccountBridgeHandler bridgeHandler, String apiKey, int apiTimeout,
|
||||
OAuthClientService oAuthClientService, HttpClient httpClient) {
|
||||
this.apiKey = apiKey;
|
||||
this.apiTimeout = apiTimeout;
|
||||
this.oAuthClientService = oAuthClientService;
|
||||
this.httpClient = httpClient;
|
||||
this.bridgeHandler = bridgeHandler;
|
||||
pinExpirationTime = 0;
|
||||
state = EcobeeAuthState.NEED_PIN;
|
||||
}
|
||||
|
||||
public void setState(EcobeeAuthState newState) {
|
||||
if (newState != state) {
|
||||
logger.debug("EcobeeAuth: Change state from {} to {}", state, newState);
|
||||
state = newState;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return state == EcobeeAuthState.COMPLETE;
|
||||
}
|
||||
|
||||
public EcobeeAuthState doAuthorization() throws EcobeeAuthException {
|
||||
switch (state) {
|
||||
case NEED_PIN:
|
||||
authorize();
|
||||
break;
|
||||
case NEED_TOKEN:
|
||||
getTokens();
|
||||
break;
|
||||
case COMPLETE:
|
||||
bridgeHandler.updateBridgeStatus(ThingStatus.ONLINE);
|
||||
break;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the Ecobee authorize endpoint to get the authorization code and PIN
|
||||
* that will be used a) validate the application in the the Ecobee user web portal,
|
||||
* and b) make the first time request for the access and refresh tokens.
|
||||
* Warnings are suppressed to avoid the Gson.fromJson warnings.
|
||||
*/
|
||||
@SuppressWarnings({ "null", "unused" })
|
||||
private void authorize() throws EcobeeAuthException {
|
||||
logger.debug("EcobeeAuth: State is {}: Executing step: 'authorize'", state);
|
||||
StringBuilder url = new StringBuilder(ECOBEE_AUTHORIZE_URL);
|
||||
url.append("?response_type=ecobeePin");
|
||||
url.append("&client_id=").append(apiKey);
|
||||
url.append("&scope=").append(ECOBEE_SCOPE);
|
||||
|
||||
logger.trace("EcobeeAuth: Getting authorize URL={}", url);
|
||||
String response = executeUrl("GET", url.toString());
|
||||
logger.trace("EcobeeAuth: Auth response: {}", response);
|
||||
|
||||
try {
|
||||
authResponse = EcobeeApi.getGson().fromJson(response, AuthorizeResponseDTO.class);
|
||||
if (authResponse == null) {
|
||||
logger.debug("EcobeeAuth: Got null authorize response from Ecobee API");
|
||||
setState(EcobeeAuthState.NEED_PIN);
|
||||
} else {
|
||||
if (StringUtils.isNotEmpty(authResponse.error)) {
|
||||
throw new EcobeeAuthException(authResponse.error + ": " + authResponse.errorDescription);
|
||||
}
|
||||
code = authResponse.code;
|
||||
writeLogMessage(authResponse.pin, authResponse.expiresIn);
|
||||
setPinExpirationTime(authResponse.expiresIn.longValue());
|
||||
updateBridgeStatus();
|
||||
setState(EcobeeAuthState.NEED_TOKEN);
|
||||
}
|
||||
} catch (JsonSyntaxException e) {
|
||||
logger.info("EcobeeAuth: Exception while parsing authorize response: {}", e.getMessage());
|
||||
setState(EcobeeAuthState.NEED_PIN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the Ecobee token endpoint to get the access and refresh tokens. Once successfully retrieved,
|
||||
* the access and refresh tokens will be injected into the OHC OAuth service.
|
||||
* Warnings are suppressed to avoid the Gson.fromJson warnings.
|
||||
*/
|
||||
@SuppressWarnings({ "null", "unused" })
|
||||
private void getTokens() throws EcobeeAuthException {
|
||||
logger.debug("EcobeeAuth: State is {}: Executing step: 'getToken'", state);
|
||||
StringBuilder url = new StringBuilder(ECOBEE_TOKEN_URL);
|
||||
url.append("?grant_type=ecobeePin");
|
||||
url.append("&code=").append(code);
|
||||
url.append("&client_id=").append(apiKey);
|
||||
|
||||
logger.trace("EcobeeAuth: Posting token URL={}", url);
|
||||
String response = executeUrl("POST", url.toString());
|
||||
logger.trace("EcobeeAuth: Got a valid token response: {}", response);
|
||||
|
||||
TokenResponseDTO tokenResponse = EcobeeApi.getGson().fromJson(response, TokenResponseDTO.class);
|
||||
if (tokenResponse == null) {
|
||||
logger.debug("EcobeeAuth: Got null token response from Ecobee API");
|
||||
updateBridgeStatus();
|
||||
setState(isPinExpired() ? EcobeeAuthState.NEED_PIN : EcobeeAuthState.NEED_TOKEN);
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(tokenResponse.error)) {
|
||||
throw new EcobeeAuthException(tokenResponse.error + ": " + tokenResponse.errorDescription);
|
||||
}
|
||||
AccessTokenResponse accessTokenResponse = new AccessTokenResponse();
|
||||
accessTokenResponse.setRefreshToken(tokenResponse.refreshToken);
|
||||
accessTokenResponse.setAccessToken(tokenResponse.accessToken);
|
||||
accessTokenResponse.setScope(tokenResponse.scope);
|
||||
accessTokenResponse.setTokenType(tokenResponse.tokenType);
|
||||
accessTokenResponse.setExpiresIn(tokenResponse.expiresIn);
|
||||
try {
|
||||
logger.debug("EcobeeAuth: Importing AccessTokenResponse into oAuthClientService!!!");
|
||||
oAuthClientService.importAccessTokenResponse(accessTokenResponse);
|
||||
bridgeHandler.updateBridgeStatus(ThingStatus.ONLINE);
|
||||
setState(EcobeeAuthState.COMPLETE);
|
||||
return;
|
||||
} catch (OAuthException e) {
|
||||
logger.info("EcobeeAuth: Got OAuthException", e);
|
||||
// No other processing needed here
|
||||
}
|
||||
updateBridgeStatus();
|
||||
setState(isPinExpired() ? EcobeeAuthState.NEED_PIN : EcobeeAuthState.NEED_TOKEN);
|
||||
}
|
||||
|
||||
private void writeLogMessage(String pin, Integer expiresIn) {
|
||||
logger.info("#################################################################");
|
||||
logger.info("# Ecobee: U S E R I N T E R A C T I O N R E Q U I R E D !!");
|
||||
logger.info("# Go to the Ecobee web portal, then:");
|
||||
logger.info("# Enter PIN '{}' in My Apps within {} minutes.", pin, expiresIn);
|
||||
logger.info("# NOTE: All API attempts will fail in the meantime.");
|
||||
logger.info("#################################################################");
|
||||
}
|
||||
|
||||
private void updateBridgeStatus() {
|
||||
AuthorizeResponseDTO response = authResponse;
|
||||
if (response != null) {
|
||||
bridgeHandler.updateBridgeStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
String.format("Enter PIN '%s' in MyApps. PIN expires in %d minutes", response.pin,
|
||||
getMinutesUntilPinExpiration()));
|
||||
}
|
||||
}
|
||||
|
||||
private void setPinExpirationTime(long expiresIn) {
|
||||
pinExpirationTime = expiresIn + TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
private long getMinutesUntilPinExpiration() {
|
||||
return pinExpirationTime - TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
private boolean isPinExpired() {
|
||||
return getMinutesUntilPinExpiration() <= 0;
|
||||
}
|
||||
|
||||
private @Nullable String executeUrl(String method, String url) {
|
||||
Request request = httpClient.newRequest(url);
|
||||
request.timeout(apiTimeout, TimeUnit.MILLISECONDS);
|
||||
request.method(method);
|
||||
EcobeeApi.HTTP_HEADERS.forEach((k, v) -> request.header((String) k, (String) v));
|
||||
|
||||
try {
|
||||
ContentResponse contentResponse = request.send();
|
||||
switch (contentResponse.getStatus()) {
|
||||
case HttpStatus.OK_200:
|
||||
return contentResponse.getContentAsString();
|
||||
case HttpStatus.BAD_REQUEST_400:
|
||||
logger.debug("BAD REQUEST(400) response received: {}", contentResponse.getContentAsString());
|
||||
return contentResponse.getContentAsString();
|
||||
case HttpStatus.UNAUTHORIZED_401:
|
||||
logger.debug("UNAUTHORIZED(401) response received: {}", contentResponse.getContentAsString());
|
||||
return contentResponse.getContentAsString();
|
||||
case HttpStatus.NO_CONTENT_204:
|
||||
logger.debug("HTTP response 204: No content. Check configuration");
|
||||
break;
|
||||
default:
|
||||
logger.debug("HTTP {} failed: {}, {}", method, contentResponse.getStatus(),
|
||||
contentResponse.getReason());
|
||||
break;
|
||||
}
|
||||
} catch (TimeoutException e) {
|
||||
logger.debug("TimeoutException: Call to Ecobee API timed out");
|
||||
} catch (ExecutionException e) {
|
||||
if (ExceptionUtils.getRootCause(e) instanceof HttpResponseException) {
|
||||
logger.info("Awaiting entry of PIN in Ecobee portal. Expires in {} minutes",
|
||||
getMinutesUntilPinExpiration());
|
||||
} else {
|
||||
logger.debug("ExecutionException on call to Ecobee authorization API", e);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("InterruptedException on call to Ecobee authorization API: {}", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.api;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeAuthException} is thrown during the Ecobee PIN authorization process.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EcobeeAuthException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param message Ecobee error message
|
||||
*/
|
||||
public EcobeeAuthException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.api;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeAuthState} represents that steps in the Ecobee PIN
|
||||
* authorization process.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
enum EcobeeAuthState {
|
||||
/*
|
||||
* This is the initial state. It indicates that an "authorize" API call is needed to get
|
||||
* the Ecobee PIN.
|
||||
*/
|
||||
NEED_PIN,
|
||||
|
||||
/*
|
||||
* This state indicates that an Ecobee PIN request was successful, and that a "token" API
|
||||
* call is needed to complete the authorization and get the refresh and access tokens. In
|
||||
* order to get the tokens, the user must authorize the application by entering the PIN
|
||||
* into the Ecobee web portal.
|
||||
*/
|
||||
NEED_TOKEN,
|
||||
|
||||
/*
|
||||
* This state indicates that the "authorize" and "token" steps were successful.
|
||||
*/
|
||||
COMPLETE;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeAccountConfiguration} class contains fields mapping
|
||||
* to the account thing configuration parameters.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EcobeeAccountConfiguration {
|
||||
|
||||
/**
|
||||
* Ecobee API key
|
||||
*/
|
||||
public @Nullable String apiKey;
|
||||
|
||||
/**
|
||||
* Time in seconds between information refresh
|
||||
*/
|
||||
public @Nullable Integer refreshIntervalNormal;
|
||||
|
||||
/**
|
||||
* Time in seconds to wait after successful update, command or action before refresh
|
||||
*/
|
||||
public @Nullable Integer refreshIntervalQuick;
|
||||
|
||||
/**
|
||||
* Time in seconds to allow API request to complete
|
||||
*/
|
||||
public @Nullable Integer apiTimeout;
|
||||
|
||||
/*
|
||||
* Enable/disable automatic discovery
|
||||
*/
|
||||
public @Nullable Boolean discoveryEnabled;
|
||||
|
||||
/**
|
||||
* Interval with which to run the thermostat discovery process
|
||||
*/
|
||||
public @Nullable Integer discoveryInterval;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeSensorConfiguration} class contains fields mapping
|
||||
* to the sensor thing configuration parameters.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EcobeeSensorConfiguration {
|
||||
|
||||
/**
|
||||
* Id of remote sensor
|
||||
*/
|
||||
public @Nullable String sensorId;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeThermostatConfiguration} class contains fields mapping
|
||||
* to the thermostat thing configuration parameters.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EcobeeThermostatConfiguration {
|
||||
|
||||
/**
|
||||
* Thermostat ID assigned by Ecobee
|
||||
*/
|
||||
public @Nullable String thermostatId;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.ecobee.internal.EcobeeBindingConstants.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.RemoteSensorDTO;
|
||||
import org.openhab.binding.ecobee.internal.handler.EcobeeThermostatBridgeHandler;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SensorDiscoveryService} is responsible for discovering the Ecobee
|
||||
* sensors that are assigned to a thermostat.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SensorDiscoveryService extends AbstractDiscoveryService implements DiscoveryService, ThingHandlerService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SensorDiscoveryService.class);
|
||||
|
||||
private @NonNullByDefault({}) EcobeeThermostatBridgeHandler bridgeHandler;
|
||||
|
||||
public SensorDiscoveryService() {
|
||||
super(30);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||
if (handler instanceof EcobeeThermostatBridgeHandler) {
|
||||
((EcobeeThermostatBridgeHandler) handler).setDiscoveryService(this);
|
||||
bridgeHandler = (EcobeeThermostatBridgeHandler) handler;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return bridgeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
logger.debug("SensorDiscovery: Activating Ecobee sensor discovery service");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
logger.debug("SensorDiscovery: Deactivating Ecobee sensor discovery service");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypes() {
|
||||
return SUPPORTED_SENSOR_THING_TYPES_UIDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startBackgroundDiscovery() {
|
||||
logger.debug("SensorDiscovery: Performing background discovery scan for {}", bridgeHandler.getThing().getUID());
|
||||
discoverSensors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScan() {
|
||||
logger.debug("SensorDiscovery: Starting discovery scan for {}", bridgeHandler.getThing().getUID());
|
||||
discoverSensors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void abortScan() {
|
||||
super.abortScan();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void stopScan() {
|
||||
super.stopScan();
|
||||
}
|
||||
|
||||
private String buildLabel(String name) {
|
||||
return String.format("Ecobee Sensor %s", name);
|
||||
}
|
||||
|
||||
private synchronized void discoverSensors() {
|
||||
for (RemoteSensorDTO sensor : bridgeHandler.getSensors()) {
|
||||
ThingUID bridgeUID = bridgeHandler.getThing().getUID();
|
||||
ThingUID sensorUID = new ThingUID(UID_SENSOR_THING, bridgeUID, sensor.id.replace(":", "-"));
|
||||
thingDiscovered(createDiscoveryResult(sensorUID, bridgeUID, sensor));
|
||||
logger.trace("SensorDiscovery: Sensor with id '{}' and name '{}' added to Inbox with UID '{}'", sensor.id,
|
||||
sensor.name, sensorUID);
|
||||
}
|
||||
}
|
||||
|
||||
private DiscoveryResult createDiscoveryResult(ThingUID sensorUID, ThingUID bridgeUID, RemoteSensorDTO sensor) {
|
||||
Map<String, Object> properties = new HashMap<>(2);
|
||||
properties.put(CONFIG_SENSOR_ID, sensor.id);
|
||||
return DiscoveryResultBuilder.create(sensorUID).withProperties(properties)
|
||||
.withRepresentationProperty(CONFIG_SENSOR_ID).withBridge(bridgeUID).withLabel(buildLabel(sensor.name))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.ecobee.internal.EcobeeBindingConstants.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatDTO;
|
||||
import org.openhab.binding.ecobee.internal.handler.EcobeeAccountBridgeHandler;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link ThermostatDiscoveryService} is responsible for discovering the Ecobee
|
||||
* thermostats that are associated with the Ecobee Account.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ThermostatDiscoveryService extends AbstractDiscoveryService
|
||||
implements DiscoveryService, ThingHandlerService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ThermostatDiscoveryService.class);
|
||||
|
||||
private @NonNullByDefault({}) EcobeeAccountBridgeHandler bridgeHandler;
|
||||
|
||||
public ThermostatDiscoveryService() {
|
||||
super(30);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||
if (handler instanceof EcobeeAccountBridgeHandler) {
|
||||
this.bridgeHandler = (EcobeeAccountBridgeHandler) handler;
|
||||
this.bridgeHandler.setDiscoveryService(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return bridgeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
logger.debug("ThermostatDiscovery: Activating Ecobee thermostat discovery service for {}",
|
||||
bridgeHandler.getThing().getUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
logger.debug("ThermostatDiscovery: Deactivating Ecobee thermostat discovery service for {}",
|
||||
bridgeHandler.getThing().getUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypes() {
|
||||
return SUPPORTED_THERMOSTAT_BRIDGE_THING_TYPES_UIDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startBackgroundDiscovery() {
|
||||
logger.trace("ThermostatDiscovery: Performing background discovery scan for {}",
|
||||
bridgeHandler.getThing().getUID());
|
||||
discoverThermostats();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScan() {
|
||||
logger.debug("ThermostatDiscovery: Starting discovery scan for {}", bridgeHandler.getThing().getUID());
|
||||
discoverThermostats();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void abortScan() {
|
||||
super.abortScan();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void stopScan() {
|
||||
super.stopScan();
|
||||
}
|
||||
|
||||
private String buildLabel(String name) {
|
||||
return String.format("Ecobee Thermostat %s", name);
|
||||
}
|
||||
|
||||
private synchronized void discoverThermostats() {
|
||||
for (ThermostatDTO thermostat : bridgeHandler.getRegisteredThermostats()) {
|
||||
String name = thermostat.name;
|
||||
String identifier = thermostat.identifier;
|
||||
if (identifier != null && name != null) {
|
||||
ThingUID thingUID = new ThingUID(UID_THERMOSTAT_BRIDGE, bridgeHandler.getThing().getUID(),
|
||||
thermostat.identifier);
|
||||
thingDiscovered(createDiscoveryResult(thingUID, identifier, name));
|
||||
logger.trace("ThermostatDiscovery: Thermostat with id '{}' and name '{}' added to Inbox with UID '{}'",
|
||||
thermostat.identifier, thermostat.name, thingUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DiscoveryResult createDiscoveryResult(ThingUID thermostatUID, String identifier, String name) {
|
||||
Map<String, Object> properties = new HashMap<>(2);
|
||||
properties.put(CONFIG_THERMOSTAT_ID, identifier);
|
||||
return DiscoveryResultBuilder.create(thermostatUID).withProperties(properties)
|
||||
.withRepresentationProperty(CONFIG_THERMOSTAT_ID).withBridge(bridgeHandler.getThing().getUID())
|
||||
.withLabel(buildLabel(name)).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto;
|
||||
|
||||
/**
|
||||
* The {@link AbstractResponseDTO} represents the common objects included in
|
||||
* all responses.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public abstract class AbstractResponseDTO {
|
||||
|
||||
/*
|
||||
* The Page object is optional and will only appear for responses which
|
||||
* can be paged. It will not appear for responses which do not contain pageable content.
|
||||
*/
|
||||
public PageDTO page;
|
||||
|
||||
/*
|
||||
* The Status object contains the response code for the request. It will also contain
|
||||
* an appropriate message when an error occurs. The status is always returned from all
|
||||
* GET and POST calls. A non-zero code means that an error occurred. Refer to the Response
|
||||
* Codes section for details of each error which may be returned.
|
||||
*/
|
||||
public StatusDTO status;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto;
|
||||
|
||||
/**
|
||||
* The {@link AbstractSelectionDTO} represents the common objects included in
|
||||
* all requests.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class AbstractSelectionDTO {
|
||||
|
||||
/*
|
||||
* The type of match data supplied: Values: thermostats, registered, managementSet.
|
||||
*/
|
||||
public String selectionType;
|
||||
|
||||
/*
|
||||
* The match data based on selectionType (e.g. a comma-separated list of thermostat
|
||||
* idendifiers in the case of a selectionType of thermostats)
|
||||
*/
|
||||
public String selectionMatch;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto;
|
||||
|
||||
/**
|
||||
* The {@link PageDTO} is optional and will only appear for responses which
|
||||
* can be paged. It will not appear for responses which do not contain pageable content.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class PageDTO {
|
||||
|
||||
/*
|
||||
* The page retrieved or, in the case of a request parameter, the specific page requested.
|
||||
*/
|
||||
public Integer page;
|
||||
|
||||
/*
|
||||
* The total pages available.
|
||||
*/
|
||||
public Integer totalPages;
|
||||
|
||||
/*
|
||||
* The number of objects on this page.
|
||||
*/
|
||||
public Integer pageSize;
|
||||
|
||||
/*
|
||||
* The total number of objects available.
|
||||
*/
|
||||
public Integer total;
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The {@link SelectionDTO} defines the resources and information to return
|
||||
* as part of a response. The selection is required in all requests however
|
||||
* meaning of some selection fields is only meaningful to certain types of requests.
|
||||
*
|
||||
* The selectionType parameter defines the type of selection to perform. The selectionMatch
|
||||
* specifies the matching criteria for the type specified.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class SelectionDTO {
|
||||
|
||||
/*
|
||||
* The type of match data supplied: Values: thermostats, registered, managementSet.
|
||||
*/
|
||||
public SelectionType selectionType;
|
||||
|
||||
/*
|
||||
* The match data based on selectionType (e.g. a comma-separated list of thermostat
|
||||
* idendifiers in the case of a selectionType of thermostats)
|
||||
*/
|
||||
public String selectionMatch;
|
||||
|
||||
/*
|
||||
* Include the thermostat's unacknowledged alert objects. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeAlerts;
|
||||
|
||||
/*
|
||||
* Include the audio configuration for the selected Thermostat(s). If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeAudio;
|
||||
|
||||
/*
|
||||
* Include the thermostat device configuration objects. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeDevice;
|
||||
|
||||
/*
|
||||
* Include the electricity readings object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeElectricity;
|
||||
|
||||
/*
|
||||
* Include the energy configuration for the selected Thermostat(s). If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeEnergy;
|
||||
|
||||
/*
|
||||
* Include the current thermostat equipment status information. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeEquipmentStatus;
|
||||
|
||||
/*
|
||||
* Include the thermostat calendar events objects. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeEvents;
|
||||
|
||||
/*
|
||||
* Include the extended thermostat runtime object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeExtendedRuntime;
|
||||
|
||||
/*
|
||||
* Include the current thermostat house details object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeHouseDetails;
|
||||
|
||||
/*
|
||||
* Include the thermostat location object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeLocation;
|
||||
|
||||
/*
|
||||
* Include the thermostat management company object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeManagement;
|
||||
|
||||
/*
|
||||
* Include the current thermostat alert and reminders settings. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeNotificationSettings;
|
||||
|
||||
/*
|
||||
* Include the current thermostat OemCfg object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeOemCfg;
|
||||
|
||||
/*
|
||||
* Include the current thermostat privacy settings. Note: access to this object is restricted
|
||||
* to callers with implict authentication, setting this value to true without proper
|
||||
* credentials will result in an authentication exception.
|
||||
*/
|
||||
public Boolean includePrivacy;
|
||||
|
||||
/*
|
||||
* Include the thermostat program object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeProgram;
|
||||
|
||||
/*
|
||||
* Include the thermostat reminder object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeReminders;
|
||||
|
||||
/*
|
||||
* Include the thermostat runtime object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeRuntime;
|
||||
|
||||
/*
|
||||
* Include the current securitySettings object for the selected Thermostat(s). If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeSecuritySettings;
|
||||
|
||||
/*
|
||||
* Include the list of current thermostatRemoteSensor objects for the selected Thermostat(s).
|
||||
* If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeSensors;
|
||||
|
||||
/*
|
||||
* Include the thermostat settings object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeSettings;
|
||||
|
||||
/*
|
||||
* Include the thermostat technician object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeTechnician;
|
||||
|
||||
/*
|
||||
* Include the thermostat utility company object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeUtility;
|
||||
|
||||
/*
|
||||
* Include the current firmware version the Thermostat is running. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeVersion;
|
||||
|
||||
/*
|
||||
* Include the current thermostat weather forecast object. If not specified, defaults to false.
|
||||
*/
|
||||
public Boolean includeWeather;
|
||||
|
||||
public SelectionDTO() {
|
||||
selectionType = SelectionType.REGISTERED;
|
||||
}
|
||||
|
||||
public void setThermostats(Set<String> thermostatIds) {
|
||||
boolean isRegistered = thermostatIds == null || thermostatIds.isEmpty();
|
||||
selectionType = isRegistered ? SelectionType.REGISTERED : SelectionType.THERMOSTATS;
|
||||
selectionMatch = isRegistered ? "" : String.join(",", thermostatIds);
|
||||
}
|
||||
|
||||
public void setSelectionType(SelectionType selectionType) {
|
||||
this.selectionType = selectionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge this selection object with the one passed in as a parameter.
|
||||
*
|
||||
* @param selection
|
||||
* @return A SelectionDTO object representing the merged selection objects
|
||||
*/
|
||||
public SelectionDTO mergeSelection(SelectionDTO selection) {
|
||||
// Always get alerts, equipmentStatus, events, program, runtime, and sensors
|
||||
this.includeAlerts = Boolean.TRUE;
|
||||
this.includeEquipmentStatus = Boolean.TRUE;
|
||||
this.includeEvents = Boolean.TRUE;
|
||||
this.includeProgram = Boolean.TRUE;
|
||||
this.includeRuntime = Boolean.TRUE;
|
||||
this.includeSensors = Boolean.TRUE;
|
||||
|
||||
this.includeAudio = selection.includeAudio == Boolean.TRUE ? Boolean.TRUE : includeAudio;
|
||||
this.includeDevice = selection.includeDevice == Boolean.TRUE ? Boolean.TRUE : includeDevice;
|
||||
this.includeElectricity = selection.includeElectricity == Boolean.TRUE ? Boolean.TRUE : includeElectricity;
|
||||
this.includeEnergy = selection.includeEnergy == Boolean.TRUE ? Boolean.TRUE : includeEnergy;
|
||||
this.includeExtendedRuntime = selection.includeExtendedRuntime == Boolean.TRUE ? Boolean.TRUE
|
||||
: includeExtendedRuntime;
|
||||
this.includeHouseDetails = selection.includeHouseDetails == Boolean.TRUE ? Boolean.TRUE : includeHouseDetails;
|
||||
this.includeLocation = selection.includeLocation == Boolean.TRUE ? Boolean.TRUE : includeLocation;
|
||||
this.includeManagement = selection.includeManagement == Boolean.TRUE ? Boolean.TRUE : includeManagement;
|
||||
this.includeNotificationSettings = selection.includeNotificationSettings == Boolean.TRUE ? Boolean.TRUE
|
||||
: includeNotificationSettings;
|
||||
this.includeOemCfg = selection.includeOemCfg == Boolean.TRUE ? Boolean.TRUE : includeOemCfg;
|
||||
this.includePrivacy = selection.includePrivacy == Boolean.TRUE ? Boolean.TRUE : includePrivacy;
|
||||
this.includeReminders = selection.includeReminders == Boolean.TRUE ? Boolean.TRUE : includeReminders;
|
||||
this.includeSecuritySettings = selection.includeSecuritySettings == Boolean.TRUE ? Boolean.TRUE
|
||||
: includeSecuritySettings;
|
||||
this.includeSettings = selection.includeSettings == Boolean.TRUE ? Boolean.TRUE : includeSettings;
|
||||
this.includeTechnician = selection.includeTechnician == Boolean.TRUE ? Boolean.TRUE : includeTechnician;
|
||||
this.includeUtility = selection.includeUtility == Boolean.TRUE ? Boolean.TRUE : includeUtility;
|
||||
this.includeVersion = selection.includeVersion == Boolean.TRUE ? Boolean.TRUE : includeVersion;
|
||||
this.includeWeather = selection.includeWeather == Boolean.TRUE ? Boolean.TRUE : includeWeather;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("selectionType=").append(selectionType).append(",");
|
||||
sb.append("selectionMatch=").append(selectionMatch).append(",");
|
||||
sb.append("includeAlerts=").append(includeAlerts).append(",");
|
||||
sb.append("includeAudio=").append(includeAudio).append(",");
|
||||
sb.append("includeDevice=").append(includeDevice).append(",");
|
||||
sb.append("includeElectricity=").append(includeElectricity).append(",");
|
||||
sb.append("includeEnergy=").append(includeEnergy).append(",");
|
||||
sb.append("includeEquipmentStatus=").append(includeEquipmentStatus).append(",");
|
||||
sb.append("includeExtendedRuntime=").append(includeExtendedRuntime).append(",");
|
||||
sb.append("includeHouseDetails=").append(includeHouseDetails).append(",");
|
||||
sb.append("includeLocation=").append(includeLocation).append(",");
|
||||
sb.append("includeManagement=").append(includeManagement).append(",");
|
||||
sb.append("includeNotificationSettings=").append(includeNotificationSettings).append(",");
|
||||
sb.append("includeOemCfg=").append(includeOemCfg).append(",");
|
||||
sb.append("includePrivacy=").append(includePrivacy).append(",");
|
||||
sb.append("includeProgram=").append(includeProgram).append(",");
|
||||
sb.append("includeReminders=").append(includeReminders).append(",");
|
||||
sb.append("includeRuntime=").append(includeRuntime).append(",");
|
||||
sb.append("includeSecuritySettings=").append(includeSecuritySettings).append(",");
|
||||
sb.append("includeSensors=").append(includeSensors).append(",");
|
||||
sb.append("includeSettings=").append(includeSettings).append(",");
|
||||
sb.append("includeTechnician=").append(includeTechnician).append(",");
|
||||
sb.append("includeUtility=").append(includeUtility).append(",");
|
||||
sb.append("includeVersion=").append(includeVersion).append(",");
|
||||
sb.append("includeWeather=").append(includeWeather);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link SelectionType} represents the valid selection types that can be passed in
|
||||
* a SelectionDTO object.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum SelectionType {
|
||||
|
||||
/*
|
||||
* Select only those thermostats listed in the CSV match criteria. No spaces in the CSV string. There is a limit
|
||||
* of 25 identifiers per request.
|
||||
*/
|
||||
@SerializedName("thermostats")
|
||||
THERMOSTATS("thermostats"),
|
||||
|
||||
/*
|
||||
* When this is set the thermostats registered to the current user will be returned. This is only usable with
|
||||
* Smart thermostats registered to a user. It does not work on EMS thermostats and may not be used by a Utility
|
||||
* who is not the owner of thermostats.
|
||||
*/
|
||||
@SerializedName("registered")
|
||||
REGISTERED("registered"),
|
||||
|
||||
/*
|
||||
* Selects all thermostats for a given management set defined by the Management/Utility account. This is only
|
||||
* available to Management/Utility accounts. "/" is the root, represented by the "My Sets" set.
|
||||
*/
|
||||
@SerializedName("managementSet")
|
||||
MANAGEMENT_SET("managementSet");
|
||||
|
||||
private final String type;
|
||||
|
||||
private SelectionType(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static SelectionType forValue(@Nullable String v) {
|
||||
if (v != null) {
|
||||
for (SelectionType at : SelectionType.values()) {
|
||||
if (at.type.equals(v)) {
|
||||
return at;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid or null selection type: " + v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto;
|
||||
|
||||
/**
|
||||
* The {@link StatusDTO} The StatusDTO object contains the processing status of
|
||||
* the request. It will contain any relevant error information should an error
|
||||
* occur. The status object is returned with every response regardless of success or failure status. It is suitable for
|
||||
* logging request failures.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class StatusDTO {
|
||||
|
||||
/*
|
||||
* The status code for this status. Success is indicated by a code of 0.
|
||||
*/
|
||||
public Integer code;
|
||||
|
||||
/*
|
||||
* The detailed message for this status.
|
||||
*/
|
||||
public String message;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.oauth;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link AbstractAuthResponseDTO} represents the common fields returned in all auth responses.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public abstract class AbstractAuthResponseDTO {
|
||||
|
||||
/*
|
||||
* Error code.
|
||||
*/
|
||||
@SerializedName("error")
|
||||
public String error;
|
||||
|
||||
/*
|
||||
* Textual description of error.
|
||||
*/
|
||||
@SerializedName("error_description")
|
||||
public String errorDescription;
|
||||
|
||||
/*
|
||||
* URI referencing OAuth documentation.
|
||||
*/
|
||||
@SerializedName("error_uri")
|
||||
public String errorURI;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.oauth;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link AuthorizeResponseDTO} is responsible for
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class AuthorizeResponseDTO extends AbstractAuthResponseDTO {
|
||||
|
||||
/*
|
||||
* The PIN a user enters in the web portal.
|
||||
*/
|
||||
@SerializedName("ecobeePin")
|
||||
public String pin;
|
||||
|
||||
/*
|
||||
* The authorization token needed to request the access and refresh tokens.
|
||||
*/
|
||||
@SerializedName("code")
|
||||
public String code;
|
||||
|
||||
/*
|
||||
* The requested Scope from the original request. This must match the original request.
|
||||
*/
|
||||
@SerializedName("scope")
|
||||
public String scope;
|
||||
|
||||
/*
|
||||
* The number of minutes until the PIN expires. Ensure you inform the user how much time they have.
|
||||
*/
|
||||
@SerializedName("expires_in")
|
||||
public Integer expiresIn;
|
||||
|
||||
/*
|
||||
* The minimum amount of seconds which must pass between polling attempts for a token.
|
||||
*/
|
||||
@SerializedName("interval")
|
||||
public Integer interval;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.oauth;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link TokenResponseDTO} is responsible for
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class TokenResponseDTO extends AbstractAuthResponseDTO {
|
||||
|
||||
/*
|
||||
* Access token to be used in future API requests.
|
||||
*/
|
||||
@SerializedName("access_token")
|
||||
public String accessToken;
|
||||
|
||||
/*
|
||||
* Contains the string "Bearer"
|
||||
*/
|
||||
@SerializedName("token_type")
|
||||
public String tokenType;
|
||||
|
||||
/*
|
||||
* Number of seconds until the access token will expire.
|
||||
*/
|
||||
@SerializedName("expires_in")
|
||||
public Integer expiresIn;
|
||||
|
||||
/*
|
||||
* Token used to request a new access token.
|
||||
*/
|
||||
@SerializedName("refresh_token")
|
||||
public String refreshToken;
|
||||
|
||||
/*
|
||||
* Matches the scope included in the token request.
|
||||
*/
|
||||
@SerializedName("scope")
|
||||
public String scope;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link AlertDTO} The Alert object represents an alert generated either
|
||||
* by a thermostat or user which requires user attention. It may be an error,
|
||||
* or a reminder for a filter change. Alerts may not be modified directly but
|
||||
* rather they must be acknowledged using the Acknowledge Function.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class AlertDTO {
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String acknowledgeRef;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String date;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String time;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String severity;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String text;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Integer alertNumber;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String alertType;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Boolean isOperatorAlert;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String reminder;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Boolean showIdt;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Boolean showWeb;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Boolean sendEmail;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String acknowledgement;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Boolean remindMeLater;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String thermostatIdentifier;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String notificationType;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link AudioDTO} contains all the audio properties of the thermostat
|
||||
* (only applicable to ecobee4).
|
||||
*
|
||||
* All read-only except for voiceEngines.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class AudioDTO {
|
||||
|
||||
/*
|
||||
* The volume level for audio playback. This includes volume of the voice assistant. A value between 0 and 100.
|
||||
*/
|
||||
public Integer playbackVolume;
|
||||
|
||||
/*
|
||||
* Turn microphone (privacy mode) on and off.
|
||||
*/
|
||||
public Boolean microphoneEnabled;
|
||||
|
||||
/*
|
||||
* The volume level for alerts on the thermostat. A value between 0 and 10, with 0 meaning 'off' - the zero
|
||||
* value may not be honored by all ecobee versions.
|
||||
*/
|
||||
public Integer soundAlertVolume;
|
||||
|
||||
/*
|
||||
* The volume level for key presses on the thermostat. A value between 0 and 10, with 0 meaning 'off' - the
|
||||
* zero value may not be honored by all ecobee versions.
|
||||
*/
|
||||
public Integer soundTickVolume;
|
||||
|
||||
/*
|
||||
* The list of voice engines compatible with the selected thermostat.
|
||||
*/
|
||||
public List<VoiceEngineDTO> voiceEngines;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link ClimateDTO} maps to the thermostat's Climate object.
|
||||
*
|
||||
* @see <a href="https://www.ecobee.com/home/developer/api/documentation/v1/objects/Climate.shtml">Climate</a>
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ClimateDTO {
|
||||
|
||||
/*
|
||||
* The unique climate name. The name may be changed without affecting the
|
||||
* program integrity so long as uniqueness is maintained.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* The unique climate identifier. Changing the identifier is not possible
|
||||
* and it is generated on the server for each climate. If this value is
|
||||
* not supplied a new climate will be created. For the default climates
|
||||
* and existing user created climates the climateRef should be
|
||||
* supplied - see note above.
|
||||
*/
|
||||
public String climateRef;
|
||||
|
||||
/*
|
||||
* A flag indicating whether the property is occupied by persons during this climate
|
||||
*/
|
||||
public Boolean isOccupied;
|
||||
|
||||
/*
|
||||
* A flag indicating whether ecobee optimized climate settings are used by this climate.
|
||||
*/
|
||||
public Boolean isOptimized;
|
||||
|
||||
/*
|
||||
* The cooling fan mode. Default: on. Values: auto, on.
|
||||
*/
|
||||
public String coolFan;
|
||||
|
||||
/*
|
||||
* The heating fan mode. Default: on. Values: auto, on.
|
||||
*/
|
||||
public String heatFan;
|
||||
|
||||
/*
|
||||
* The ventilator mode. Default: off. Values: auto, minontime, on, off.
|
||||
*/
|
||||
public String vent;
|
||||
|
||||
/*
|
||||
* The minimum time, in minutes, to run the ventilator each hour.
|
||||
*/
|
||||
public Integer ventilatorMinOnTime;
|
||||
|
||||
/*
|
||||
* The climate owner. Default: system. Values: adHoc, demandResponse, quickSave,
|
||||
* sensorAction, switchOccupancy, system, template, user.
|
||||
*/
|
||||
public String owner;
|
||||
|
||||
/*
|
||||
* The type of climate. Default: program. Values: calendarEvent, program.
|
||||
*/
|
||||
public String type;
|
||||
|
||||
/*
|
||||
* The integer conversion of the HEX color value used to display this
|
||||
* climate on the thermostat and on the web portal.
|
||||
*/
|
||||
public Integer colour;
|
||||
|
||||
/*
|
||||
* The cool temperature for this climate.
|
||||
*/
|
||||
public Integer coolTemp;
|
||||
|
||||
/*
|
||||
* The heat temperature for this climate.
|
||||
*/
|
||||
public Integer heatTemp;
|
||||
|
||||
/*
|
||||
* The list of sensors in use for the specific climate. The sensors listed here
|
||||
* are used for temperature averaging within that climate. Only the sensorId
|
||||
* and name are listed in the climate.
|
||||
*/
|
||||
public List<RemoteSensorDTO> sensors;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link DeviceDTO} represents a device attached to the thermostat. Devices may
|
||||
* not be modified remotely, all changes must occur on the thermostat.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class DeviceDTO {
|
||||
|
||||
/*
|
||||
* A unique ID for the device.
|
||||
*/
|
||||
public Integer deviceId;
|
||||
|
||||
/*
|
||||
* The user supplied device name.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* The list of Sensor Objects associated with the device.
|
||||
*/
|
||||
public List<Object> sensors;
|
||||
|
||||
/*
|
||||
* The list of Output Objects associated with the device.
|
||||
*/
|
||||
public List<Object> outputs;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link ElectricityDTO} contains the last collected electricity usage
|
||||
* measurements for the thermostat. An electricity object is composed of
|
||||
* Electricity Devices, each of which contains readings from an Electricity Tier.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ElectricityDTO {
|
||||
|
||||
/*
|
||||
* The list of ElectricityDevice objects associated with the thermostat, each representing
|
||||
* a device such as an electric meter or remote load control.
|
||||
*/
|
||||
public List<ElectricityDeviceDTO> electricityDevices;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link ElectricityDeviceDTO} represents an energy recording device. At this time,
|
||||
* only meters are supported by the API.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ElectricityDeviceDTO {
|
||||
|
||||
/*
|
||||
* The name of the device.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* The list of Electricity Tiers containing the break down of daily electricity
|
||||
* consumption of the device for the day, broken down per pricing tier.
|
||||
*/
|
||||
public List<ElectricityTierDTO> tiers;
|
||||
|
||||
/*
|
||||
* The last date/time the reading was updated in UTC time.
|
||||
*/
|
||||
public String lastUpdate;
|
||||
|
||||
/*
|
||||
* The last three daily electricity cost reads from the device in cents with a
|
||||
* three decimal place precision.
|
||||
*/
|
||||
public List<String> cost;
|
||||
|
||||
/*
|
||||
* The last three daily electricity consumption reads from the device in KWh
|
||||
* with a three decimal place precision.
|
||||
*/
|
||||
public List<String> consumption;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link ElectricityTierDTO} is responsible for
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ElectricityTierDTO {
|
||||
|
||||
/*
|
||||
* The tier name as defined by the Utility. May be an empty string if
|
||||
* the tier is undefined or the usage falls outside the defined tiers.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* The last daily consumption reading collected. The reading format and precision
|
||||
* is to three decimal places in kWh.
|
||||
*/
|
||||
public String consumption;
|
||||
|
||||
/*
|
||||
* The daily cumulative tier cost in dollars if defined by the Utility. May
|
||||
* be an empty string if undefined.
|
||||
*/
|
||||
public String cost;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link EnergyDTO} is undefined in the Ecobee API spec.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class EnergyDTO {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import org.openhab.binding.ecobee.internal.enums.EquipmentNotificationType;
|
||||
|
||||
/**
|
||||
* The {@link EquipmentSettingDTO} represents the alert/reminder type which is associated
|
||||
* with and dependent upon specific equipment controlled by the Thermostat. It is used
|
||||
* when getting/setting the Thermostat NotificationSettings object. Note: Only the notification
|
||||
* settings for the equipment/devices currently controlled by the Thermostat are returned during
|
||||
* GET request, and only those same settings can be updated using the POST request. The type
|
||||
* corresponds to the Alert.notificationType returned when alerts are also included in the
|
||||
* selection. See Alert for more information.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class EquipmentSettingDTO {
|
||||
|
||||
/*
|
||||
* The date the filter was last changed for this equipment. String format: YYYY-MM-DD
|
||||
*/
|
||||
public String filterLastChanged;
|
||||
|
||||
/*
|
||||
* The value representing the life of the filter. This value is expressed in month or hour,
|
||||
* which is specified in the the filterLifeUnits property.
|
||||
*/
|
||||
public Integer filterLife;
|
||||
|
||||
/*
|
||||
* The units the filterLife field is measured in. Possible values are: month, hour. month
|
||||
* has a range of 1 - 12. hour has a range of 100 - 10000.
|
||||
*/
|
||||
public String filterLifeUnits;
|
||||
|
||||
/*
|
||||
* The date the reminder will be triggered. This is a read-only field and cannot be modified
|
||||
* through the API. The value is calculated and set by the thermostat.
|
||||
*/
|
||||
public String remindMeDate;
|
||||
|
||||
/*
|
||||
* Boolean value representing whether or not alerts/reminders are enabled for this
|
||||
* notification type or not.
|
||||
*/
|
||||
public Boolean enabled;
|
||||
|
||||
/*
|
||||
* The type of notification. Possible values are: hvac, furnaceFilter, humidifierFilter,
|
||||
* dehumidifierFilter, ventilator, ac, airFilter, airCleaner, uvLamp
|
||||
*/
|
||||
public EquipmentNotificationType type;
|
||||
|
||||
/*
|
||||
* Boolean value representing whether or not alerts/reminders should be sent to the
|
||||
* technician/contractor assoicated with the thermostat.
|
||||
*/
|
||||
public Boolean remindTechnician;
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link EventDTO} represents a scheduled thermostat
|
||||
* program change. All events have a start and end time during which the
|
||||
* thermostat runtime settings will be modified. Events may not be directly
|
||||
* modified, various Functions provide the capability to modify the calendar
|
||||
* events and to modify the program. The event list is sorted with events
|
||||
* ordered by whether they are currently running and the internal priority
|
||||
* of each event. It is safe to take the first event which is running and
|
||||
* show it as the currently running event. When the resume function is used,
|
||||
* events are removed in the order they are listed here.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class EventDTO {
|
||||
/*
|
||||
* The type of event. Values: hold, demandResponse, sensor, switchOccupancy,
|
||||
* vacation, quickSave, today, autoAway, autoHome
|
||||
*/
|
||||
public String type;
|
||||
|
||||
/*
|
||||
* The unique event name.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* Whether the event is currently active or not.
|
||||
*/
|
||||
public Boolean running;
|
||||
|
||||
/*
|
||||
* The event start date in thermostat local time.
|
||||
*/
|
||||
public String startDate;
|
||||
|
||||
/*
|
||||
* The event start time in thermostat local time.
|
||||
*/
|
||||
public String startTime;
|
||||
|
||||
/*
|
||||
* The event end date in thermostat local time.
|
||||
*/
|
||||
public String endDate;
|
||||
|
||||
/*
|
||||
* The event end time in thermostat local time.
|
||||
*/
|
||||
public String endTime;
|
||||
|
||||
/*
|
||||
* Whether there are persons occupying the property during the event.
|
||||
*/
|
||||
public Boolean isOccupied;
|
||||
|
||||
/*
|
||||
* Whether cooling will be turned off during the event.
|
||||
*/
|
||||
public Boolean isCoolOff;
|
||||
|
||||
/*
|
||||
* Whether heating will be turned off during the event.
|
||||
*/
|
||||
public Boolean isHeatOff;
|
||||
|
||||
/*
|
||||
* The cooling absolute temperature to set.
|
||||
*/
|
||||
public Integer coolHoldTemp;
|
||||
|
||||
/*
|
||||
* The heating absolute temperature to set.
|
||||
*/
|
||||
public Integer heatHoldTemp;
|
||||
|
||||
/*
|
||||
* The fan mode during the event. Values: auto, on Default: based on current climate and hvac mode.
|
||||
*/
|
||||
public String fan;
|
||||
|
||||
/*
|
||||
* The ventilator mode during the vent. Values: auto, minontime, on, off.
|
||||
*/
|
||||
public String vent;
|
||||
|
||||
/*
|
||||
* The minimum amount of time the ventilator equipment must stay on on each duty cycle.
|
||||
*/
|
||||
public Integer ventilatorMinOnTime;
|
||||
|
||||
/*
|
||||
* Whether this event is mandatory or the end user can cancel it.
|
||||
*/
|
||||
public Boolean isOptional;
|
||||
|
||||
/*
|
||||
* Whether the event is using a relative temperature setting to the currently
|
||||
* active program climate. See the Note at the bottom of this page for more information.
|
||||
*/
|
||||
public Boolean isTemperatureRelative;
|
||||
|
||||
/*
|
||||
* The relative cool temperature adjustment.
|
||||
*/
|
||||
public Integer coolRelativeTemp;
|
||||
|
||||
/*
|
||||
* The relative heat temperature adjustment.
|
||||
*/
|
||||
public Integer heatRelativeTemp;
|
||||
|
||||
/*
|
||||
* Whether the event uses absolute temperatures to set the values. Default:
|
||||
* true for DRs. See the Note at the bottom of this page for more information.
|
||||
*/
|
||||
public Boolean isTemperatureAbsolute;
|
||||
|
||||
/*
|
||||
* Indicates the % scheduled runtime during a Demand Response event. Valid range
|
||||
* is 0 - 100%. Default = 100, indicates no change to schedule.
|
||||
*/
|
||||
public Integer dutyCyclePercentage;
|
||||
|
||||
/*
|
||||
* The minimum number of minutes to run the fan each hour. Range: 0-60, Default: 0
|
||||
*/
|
||||
public Integer fanMinOnTime;
|
||||
|
||||
/*
|
||||
* True if this calendar event was created because of the occupied sensor.
|
||||
*/
|
||||
public Boolean occupiedSensorActive;
|
||||
|
||||
/*
|
||||
* True if this calendar event was created because of the occupied sensor.
|
||||
*/
|
||||
public Boolean unoccupiedSensorActive;
|
||||
|
||||
/*
|
||||
* Unsupported. Future feature.
|
||||
*/
|
||||
public Integer drRampUpTemp;
|
||||
|
||||
/*
|
||||
* Unsupported. Future feature.
|
||||
*/
|
||||
public Integer drRampUpTime;
|
||||
|
||||
/*
|
||||
* Unique identifier set by the server to link one or more events and alerts together.
|
||||
*/
|
||||
public String linkRef;
|
||||
|
||||
/*
|
||||
* Used for display purposes to indicate what climate (if any) is being used for the hold.
|
||||
*/
|
||||
public String holdClimateRef;
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link ExtendedRuntimeDTO} contains the last three 5 minute interval values
|
||||
* sent by the thermostat for the past 15 minutes of runtime. The interval values
|
||||
* are valuable when you are interested in analyzing the runtime data in a more
|
||||
* granular fashion, at 5 minute increments rather than the more general 15 minute
|
||||
* value from the Runtime Object. For the runtime values (i.e. heatPump, auxHeat,
|
||||
* cool, etc.) refer to the Thermostat.Settings values (hasHeatPump, heatStages,
|
||||
* coolStages) to determine whether a heat pump exists and how many stages the
|
||||
* thermostat supports. The actual temperature and humidity will also be updated
|
||||
* when the equipment state changes by the thermostat, this may occur at a frequency
|
||||
* of 3 minutes, however it is only transmitted when there is an equipment state
|
||||
* change on the thermostat.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ExtendedRuntimeDTO {
|
||||
|
||||
/*
|
||||
* The UTC timestamp of the last value read. This timestamp is updated at a 15 min
|
||||
* interval by the thermostat. For the 1st value, it is timestamp - 10 mins, for
|
||||
* the 2nd value it is timestamp - 5 mins. Consider day boundaries being straddled
|
||||
* when using these values.
|
||||
*/
|
||||
public String lastReadingTimestamp;
|
||||
|
||||
/*
|
||||
* The UTC date of the last runtime reading. Format: YYYY-MM-DD
|
||||
*/
|
||||
public String runtimeDate;
|
||||
|
||||
/*
|
||||
* The last 5 minute interval which was updated by the thermostat telemetry update.
|
||||
* Subtract 2 from this interval to obtain the beginning interval for the last 3
|
||||
* readings. Multiply by 5 mins to obtain the minutes of the day. Range: 0-287
|
||||
*/
|
||||
public Integer runtimeInterval;
|
||||
|
||||
/*
|
||||
* The last three 5 minute actual temperature readings
|
||||
*/
|
||||
public List<Integer> actualTemperature;
|
||||
|
||||
/*
|
||||
* The last three 5 minute actual humidity readings.
|
||||
*/
|
||||
public List<Integer> actualHumidity;
|
||||
|
||||
/*
|
||||
* The last three 5 minute desired heat temperature readings.
|
||||
*/
|
||||
public List<Integer> desiredHeat;
|
||||
|
||||
/*
|
||||
* The last three 5 minute desired cool temperature readings.
|
||||
*/
|
||||
public List<Integer> desiredCool;
|
||||
|
||||
/*
|
||||
* The last three 5 minute desired humidity readings.
|
||||
*/
|
||||
public List<Integer> desiredHumidity;
|
||||
|
||||
/*
|
||||
* The last three 5 minute desired de-humidification readings.
|
||||
*/
|
||||
public List<Integer> desiredDehumidity;
|
||||
|
||||
/*
|
||||
* The last three 5 minute desired Demand Management temeprature offsets.
|
||||
* This value is Demand Management adjustment value which was applied by
|
||||
* the thermostat. If the thermostat decided not to honour the adjustment,
|
||||
* it will send 0 for the interval. Compare these values with the values
|
||||
* sent in the DM message to determine whether the thermostat applied
|
||||
* the adjustment.
|
||||
*/
|
||||
public List<Integer> dmOffset;
|
||||
|
||||
/*
|
||||
* The last three 5 minute HVAC Mode reading. These values indicate which
|
||||
* stage was energized in the 5 minute interval. Values: heatStage10n,
|
||||
* heatStage20n, heatStage30n, heatOff, compressorCoolStage10n,
|
||||
* compressorCoolStage20n, compressorCoolOff, compressorHeatStage10n,
|
||||
* compressorHeatStage20n, compressorHeatOff, economyCycle.
|
||||
*/
|
||||
public List<Integer> hvacMode;
|
||||
|
||||
/*
|
||||
* The last three 5 minute HVAC Runtime values in seconds (0-300 seconds)
|
||||
* per interval. This value corresponds to the heat pump stage 1 runtime.
|
||||
*/
|
||||
public List<Integer> heatPump1;
|
||||
|
||||
/*
|
||||
* The last three 5 minute HVAC Runtime values in seconds (0-300 seconds)
|
||||
* per interval. This value corresponds to the heat pump stage 2 runtime.
|
||||
*/
|
||||
public List<Integer> heatPump2;
|
||||
|
||||
/*
|
||||
* The last three 5 minute HVAC Runtime values in seconds (0-300 seconds)
|
||||
* per interval. This value corresponds to the auxiliary heat stage 1. If
|
||||
* the thermostat does not have a heat pump, this is heat stage 1.
|
||||
*/
|
||||
public List<Integer> auxHeat1;
|
||||
|
||||
/*
|
||||
* The last three 5 minute HVAC Runtime values in seconds (0-300 seconds)
|
||||
* per interval. This value corresponds to the auxiliary heat stage 2. If
|
||||
* the thermostat does not have a heat pump, this is heat stage 2.
|
||||
*/
|
||||
public List<Integer> auxHeat2;
|
||||
|
||||
/*
|
||||
* The last three 5 minute HVAC Runtime values in seconds (0-300 seconds)
|
||||
* per interval. This value corresponds to the heat stage 3 if the thermostat
|
||||
* does not have a heat pump. Auxiliary stage 3 is not supported.
|
||||
*/
|
||||
public List<Integer> auxHeat3;
|
||||
|
||||
/*
|
||||
* The last three 5 minute HVAC Runtime values in seconds (0-300 seconds)
|
||||
* per interval. This value corresponds to the cooling stage 1.
|
||||
*/
|
||||
public List<Integer> cool1;
|
||||
|
||||
/*
|
||||
* The last three 5 minute HVAC Runtime values in seconds (0-300 seconds)
|
||||
* per interval. This value corresponds to the cooling stage 2.
|
||||
*/
|
||||
public List<Integer> cool2;
|
||||
|
||||
/*
|
||||
* The last three 5 minute fan Runtime values in seconds (0-300 seconds) per interval.
|
||||
*/
|
||||
public List<Integer> fan;
|
||||
|
||||
/*
|
||||
* The last three 5 minute humidifier Runtime values in seconds (0-300 seconds) per interval.
|
||||
*/
|
||||
public List<Integer> humidifier;
|
||||
|
||||
/*
|
||||
* The last three 5 minute de-humidifier Runtime values in seconds (0-300 seconds) per interval.
|
||||
*/
|
||||
public List<Integer> dehumidifier;
|
||||
|
||||
/*
|
||||
* The last three 5 minute economizer Runtime values in seconds (0-300 seconds) per interval.
|
||||
*/
|
||||
public List<Integer> economizer;
|
||||
|
||||
/*
|
||||
* The last three 5 minute ventilator Runtime values in seconds (0-300 seconds) per interval.
|
||||
*/
|
||||
public List<Integer> ventilator;
|
||||
|
||||
/*
|
||||
* The latest value of the current electricity bill as interpolated from the
|
||||
* thermostat's readings from a paired electricity meter.
|
||||
*/
|
||||
public List<Integer> currentElectricityBill;
|
||||
|
||||
/*
|
||||
* The latest estimate of the projected electricity bill as interpolated from the
|
||||
* thermostat's readings from a paired electricity meter.
|
||||
*/
|
||||
public List<Integer> projectedElectricityBill;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link GeneralSettingDTO} represent the General alert/reminder type. It is
|
||||
* used when getting/setting the Thermostat NotificationSettings object. The type
|
||||
* corresponds to the Alert.notificationType returned when alerts are included in
|
||||
* the selection. See Alert for more information.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class GeneralSettingDTO {
|
||||
|
||||
/*
|
||||
* Boolean value representing whether or not alerts/reminders are enabled for this notification type or not.
|
||||
*/
|
||||
public Boolean enabled;
|
||||
|
||||
/*
|
||||
* The type of notification. Possible values are: temp
|
||||
*/
|
||||
public String type;
|
||||
|
||||
/*
|
||||
* Boolean value representing whether or not alerts/reminders should be sent to the
|
||||
* technician/contractor associated with the thermostat.
|
||||
*/
|
||||
public Boolean remindTechnician;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link HouseDetailsDTO} contains contains the information about the
|
||||
* house the thermostat is installed in.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class HouseDetailsDTO {
|
||||
/*
|
||||
* The style of house. Values: other, apartment, condominium, detached,
|
||||
* loft, multiPlex, rowHouse, semiDetached, townhouse, and 0 for unknown.
|
||||
*/
|
||||
public String style;
|
||||
|
||||
/*
|
||||
* The size of the house in square feet.
|
||||
*/
|
||||
public Integer size;
|
||||
|
||||
/*
|
||||
* The number of floors or levels in the house.
|
||||
*/
|
||||
public Integer numberOfFloors;
|
||||
|
||||
/*
|
||||
* The number of rooms in the house.
|
||||
*/
|
||||
public Integer numberOfRooms;
|
||||
|
||||
/*
|
||||
* The number of occupants living in the house.
|
||||
*/
|
||||
public Integer numberOfOccupants;
|
||||
|
||||
/*
|
||||
* The age of house in years.
|
||||
*/
|
||||
public Integer age;
|
||||
|
||||
/*
|
||||
* This field defines the window efficiency of the house. Valid values
|
||||
* are in the range 1 - 7. Changing the value of this field alters the
|
||||
* settings the thermostat uses for the humidifier when in 'frost Control'
|
||||
* mode. See the NOTE above before updating this value.
|
||||
*/
|
||||
public Integer windowEfficiency;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import org.openhab.binding.ecobee.internal.enums.LimitNotificationType;
|
||||
|
||||
/**
|
||||
* The {@link LimitSettingDTO} represents the alert/reminder type which is associated
|
||||
* specific values, such as highHeat or lowHumidity. It is used when getting/setting
|
||||
* the Thermostat NotificationSettings object. The type corresponds to the
|
||||
* Alert.notificationType returned when alerts are also included in the selection.
|
||||
* See Alert for more information.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class LimitSettingDTO {
|
||||
|
||||
/*
|
||||
* The value of the limit to set. For temperatures the value is expressed as
|
||||
* degrees Fahrenheit, multipled by 10. For humidity values are expressed as
|
||||
* a percentage from 5 to 95. See here for more information.
|
||||
*/
|
||||
|
||||
public Integer limit;
|
||||
|
||||
/*
|
||||
* Boolean value representing whether or not alerts/reminders are enabled for
|
||||
* this notification type or not.
|
||||
*/
|
||||
public Boolean enabled;
|
||||
|
||||
/*
|
||||
* The type of notification. Possible values are: lowTemp, highTemp, lowHumidity,
|
||||
* highHumidity, auxHeat, auxOutdoor
|
||||
*/
|
||||
public LimitNotificationType type;
|
||||
|
||||
/*
|
||||
* Boolean value representing whether or not alerts/reminders should be sent to
|
||||
* the technician/contractor associated with the thermostat.
|
||||
*/
|
||||
public Boolean remindTechnician;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link LocationDTO} describes the physical location and coordinates of the
|
||||
* thermostat as entered by the thermostat owner. The address information is used
|
||||
* in a geocode look up to obtain the thermostat coordinates. The coordinates
|
||||
* are used to obtain accurate weather information.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class LocationDTO {
|
||||
/*
|
||||
* The timezone offset in minutes from UTC.
|
||||
*/
|
||||
public Integer timeZoneOffsetMinutes;
|
||||
|
||||
/*
|
||||
* The Olson timezone the thermostat resides in (e.g America/Toronto).
|
||||
*/
|
||||
public String timeZone;
|
||||
|
||||
/*
|
||||
* Whether the thermostat should factor in daylight savings when displaying the date and time.
|
||||
*/
|
||||
public Boolean isDaylightSaving;
|
||||
|
||||
/*
|
||||
* The thermostat location street address.
|
||||
*/
|
||||
public String streetAddress;
|
||||
|
||||
/*
|
||||
* The thermostat location city.
|
||||
*/
|
||||
public String city;
|
||||
|
||||
/*
|
||||
* The thermostat location State or Province
|
||||
*/
|
||||
public String provinceState;
|
||||
|
||||
/*
|
||||
* The thermostat location country.
|
||||
*/
|
||||
public String country;
|
||||
|
||||
/*
|
||||
* The thermostat location ZIP or Postal code.
|
||||
*/
|
||||
public String postalCode;
|
||||
|
||||
/*
|
||||
* The thermostat owner's phone number.
|
||||
*/
|
||||
public String phoneNumber;
|
||||
|
||||
/*
|
||||
* The lat/long geographic coordinates of the thermostat location.
|
||||
*/
|
||||
public String mapCoordinates;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link ManagementDTO} contains information about the management company
|
||||
* the thermostat belongs to. The Management object is read-only, it may be
|
||||
* modified in the web portal.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ManagementDTO {
|
||||
/*
|
||||
* The administrative contact name.
|
||||
*/
|
||||
public String administrativeContact;
|
||||
|
||||
/*
|
||||
* The billing contact name.
|
||||
*/
|
||||
public String billingContact;
|
||||
|
||||
/*
|
||||
* The company name.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* The phone number.
|
||||
*/
|
||||
public String phone;
|
||||
|
||||
/*
|
||||
* The contact email address.
|
||||
*/
|
||||
public String email;
|
||||
|
||||
/*
|
||||
* The company web site.
|
||||
*/
|
||||
public String web;
|
||||
|
||||
/*
|
||||
* Whether to show management alerts on the thermostat.
|
||||
*/
|
||||
public Boolean showAlertIdt;
|
||||
|
||||
/*
|
||||
* Whether to show management alerts in the web portal.
|
||||
*/
|
||||
public Boolean showAlertWeb;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link NotificationSettingsDTO} contains the configuration of the possible alerts and
|
||||
* reminders which can be generated by the Thermostat. The NotificationsSettings supports
|
||||
* retrieval through a Thermostat GET call, setting the includeNotificationSettings to
|
||||
* true in the Selection.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class NotificationSettingsDTO {
|
||||
|
||||
/*
|
||||
* The list of email addresses alerts and reminders will be sent to.
|
||||
* The full list of email addresses must be sent in any update request.
|
||||
* If any are missing from that list they will be deleted. If an empty
|
||||
* list is sent, any email addresses will be deleted.
|
||||
*/
|
||||
public List<String> emailAddresses;
|
||||
|
||||
/*
|
||||
* Boolean values representing whether or not alerts and reminders
|
||||
* will be sent to the email addresses listed above when triggered.
|
||||
*/
|
||||
public Boolean emailNotificationsEnabled;
|
||||
|
||||
/*
|
||||
* The list of equipment specific alert and reminder settings.
|
||||
*/
|
||||
public List<EquipmentSettingDTO> equipment;
|
||||
|
||||
/*
|
||||
* The list of general alert and reminder settings.
|
||||
*/
|
||||
public List<GeneralSettingDTO> general;
|
||||
|
||||
/*
|
||||
* The list of limit specific alert and reminder settings.
|
||||
*/
|
||||
public List<LimitSettingDTO> limit;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link OemCfgDTO} is undefined in the Ecobee API spec.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class OemCfgDTO {
|
||||
|
||||
public String serialNumber;
|
||||
|
||||
public Object cCfg;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link PrivacyDTO} is undefined in the Ecobee API spec.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class PrivacyDTO {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link ProgramDTO} is a container for the Schedule and its Climates. See Core Concepts for
|
||||
* details on how the program is structured. The schedule property is a two dimensional array
|
||||
* containing the climate names.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ProgramDTO {
|
||||
|
||||
/*
|
||||
* The Schedule object defining the program schedule.
|
||||
*/
|
||||
public List<List<String>> schedule;
|
||||
|
||||
/*
|
||||
* The list of Climate objects defining all the climates in the program schedule.
|
||||
*/
|
||||
public List<ClimateDTO> climates;
|
||||
|
||||
/*
|
||||
* The currently active climate, identified by its ClimateRef.
|
||||
*/
|
||||
public String currentClimateRef;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link ReminderDTO} is undefined in the Ecobee API spec.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ReminderDTO {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link RemoteSensorCapabilityDTO}represents the specific capability of a
|
||||
* sensor connected to the thermostat. For the occupancy type capability the
|
||||
* data will only show computed occupancy, as does the thermostat.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class RemoteSensorCapabilityDTO {
|
||||
/*
|
||||
* The unique sensor capability identifier. For example: 1
|
||||
*/
|
||||
public String id;
|
||||
|
||||
/*
|
||||
* The type of sensor capability. Values: adc, co2, dryContact,
|
||||
* humidity, temperature, occupancy, unknown.
|
||||
*/
|
||||
public String type;
|
||||
|
||||
/*
|
||||
* The data value for this capability, always a String. Temperature
|
||||
* values are expressed as degrees Fahrenheit, multiplied by 10. For
|
||||
* example, a temperature of 72F would be returned as the value "720".
|
||||
* Occupancy values are "true" or "false". Humidity is expressed as
|
||||
* a % value such as "45". Unknown values are returned as "unknown".
|
||||
*/
|
||||
public String value;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link RemoteSensorDTO} represents a sensor connected to the thermostat.
|
||||
* The remote sensor data will only show computed occupancy, as does the thermostat.
|
||||
* Definition - For a given sensor, computed occupancy means a sensor is occupied
|
||||
* if any motion was detected in the past 30 minutes. RemoteSensor data changes
|
||||
* trigger the runtimeRevision to be updated. The data updates are sent at an
|
||||
* interval of 3 mins maximum. This means that you should not poll quicker
|
||||
* than once every 3 mins for revision changes.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class RemoteSensorDTO {
|
||||
/*
|
||||
* The unique sensor identifier. It is composed of deviceName + deviceId
|
||||
* separated by colons, for example: rs:100
|
||||
*/
|
||||
public String id;
|
||||
|
||||
/*
|
||||
* The user assigned sensor name.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* The type of sensor. Values: thermostat, ecobee3_remote_sensor,
|
||||
* monitor_sensor, control_sensor.
|
||||
*/
|
||||
public String type;
|
||||
|
||||
/*
|
||||
* The unique 4-digit alphanumeric sensor code. For ecobee3 remote
|
||||
* sensors this corresponds to the code found on the back of the physical sensor.
|
||||
*/
|
||||
public String code;
|
||||
|
||||
/*
|
||||
* This flag indicates whether the remote sensor is currently in use
|
||||
* by a comfort setting. See Climate for more information.
|
||||
*/
|
||||
public Boolean inUse;
|
||||
|
||||
/*
|
||||
* The list of remoteSensorCapability objects for the remote sensor.
|
||||
*/
|
||||
public List<RemoteSensorCapabilityDTO> capability;
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link RuntimeDTO} represents the last known thermostat running state. This state
|
||||
* is composed from the last interval status message received from a thermostat. It is
|
||||
* also updated each time the thermostat posts configuration changes to the server.
|
||||
* The runtime object contains the last 5 minute interval value sent by the thermostat
|
||||
* for the past 15 minutes of runtime. The thermostat updates the server every 15 minutes
|
||||
* with the last three 5 minute readings. The actual temperature and humidity will also
|
||||
* be updated when the equipment state changes by the thermostat, this may occur at a
|
||||
* frequency of 3 minutes, however it is only transmitted when there is an equipment
|
||||
* state change on the thermostat. The runtime object contains two fields, desiredHeatRange
|
||||
* and desiredCoolRange, which can be queried and used to determine that any holds being
|
||||
* set through the API will not be adjusted. The API caller should check these ranges
|
||||
* before calling the setHold function to mitigate against the new set points being
|
||||
* adjusted by the server if the values are outside the acceptable ranges.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class RuntimeDTO {
|
||||
/*
|
||||
* The current runtime revision. Equivalent in meaning to the runtime
|
||||
* revision number in the thermostat summary call.
|
||||
*/
|
||||
public String runtimeRev;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is currently connected to the server.
|
||||
*/
|
||||
public Boolean connected;
|
||||
|
||||
/*
|
||||
* The UTC date/time stamp of when the thermostat first connected
|
||||
* to the ecobee server.
|
||||
*/
|
||||
public Date firstConnected;
|
||||
|
||||
/*
|
||||
* The last recorded connection date and time.
|
||||
*/
|
||||
public Date connectDateTime;
|
||||
|
||||
/*
|
||||
* The last recorded disconnection date and time.
|
||||
*/
|
||||
public Date disconnectDateTime;
|
||||
|
||||
/*
|
||||
* The UTC date/time stamp of when the thermostat was updated.
|
||||
* Format: YYYY-MM-DD HH:MM:SS
|
||||
*/
|
||||
public Date lastModified;
|
||||
|
||||
/*
|
||||
* The UTC date/time stamp of when the thermostat last posted its
|
||||
* runtime information. Format: YYYY-MM-DD HH:MM:SS
|
||||
*/
|
||||
public Date lastStatusModified;
|
||||
|
||||
/*
|
||||
* The UTC date of the last runtime reading. Format: YYYY-MM-DD
|
||||
*/
|
||||
public String runtimeDate;
|
||||
|
||||
/*
|
||||
* The last 5 minute interval which was updated by the thermostat
|
||||
* telemetry update. Subtract 2 from this interval to obtain the
|
||||
* beginning interval for the last 3 readings. Multiply by 5 mins
|
||||
* to obtain the minutes of the day. Range: 0-287
|
||||
*/
|
||||
public Integer runtimeInterval;
|
||||
|
||||
/*
|
||||
* The current temperature displayed on the thermostat.
|
||||
*/
|
||||
public Integer actualTemperature;
|
||||
|
||||
/*
|
||||
* The current humidity % shown on the thermostat.
|
||||
*/
|
||||
public Integer actualHumidity;
|
||||
|
||||
/*
|
||||
* The dry-bulb temperature recorded by the thermostat. When
|
||||
* Energy.FeelsLikeMode is set to humidex, Runtime.actualTemperature
|
||||
* will report a "feels like" temperature.
|
||||
*/
|
||||
public Integer rawTemperature;
|
||||
|
||||
/*
|
||||
* The currently displayed icon on the thermostat.
|
||||
*/
|
||||
public Integer showIconMode;
|
||||
|
||||
/*
|
||||
* The desired heat temperature as per the current running
|
||||
* program or active event.
|
||||
*/
|
||||
public Integer desiredHeat;
|
||||
|
||||
/*
|
||||
* The desired cool temperature as per the current running
|
||||
* program or active event.
|
||||
*/
|
||||
public Integer desiredCool;
|
||||
|
||||
/*
|
||||
* The desired humidity set point.
|
||||
*/
|
||||
public Integer desiredHumidity;
|
||||
|
||||
/*
|
||||
* The desired dehumidification set point.
|
||||
*/
|
||||
public Integer desiredDehumidity;
|
||||
|
||||
/*
|
||||
* The desired fan mode. Values: auto, on or null if the HVAC
|
||||
* system is off and the thermostat is not controlling a fan independently.
|
||||
*/
|
||||
public String desiredFanMode;
|
||||
|
||||
/*
|
||||
* This field provides the possible valid range for which a desiredHeat
|
||||
* setpoint can be set to. This value takes into account the thermostat
|
||||
* heat temperature limits as well the running program or active events.
|
||||
* Values are returned as an Integer array representing the canonical
|
||||
* minimum and maximim, e.g. [450,790].
|
||||
*/
|
||||
public List<Integer> desiredHeatRange;
|
||||
|
||||
/*
|
||||
* This field provides the possible valid range for which a desiredCool
|
||||
* setpoint can be set to. This value takes into account the thermostat
|
||||
* cool temperature limits as well the running program or active events.
|
||||
* Values are returned as an Integer array representing the canonical
|
||||
* minimum and maximim, e.g. [650,920].
|
||||
*/
|
||||
public List<Integer> desiredCoolRange;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link SecuritySettingsDTO} defines the security settings which a thermostat
|
||||
* may have. Currently this object stores data specific to access control. If any of
|
||||
* the XXXAccess fields are not supplied they will default to false. So to set all
|
||||
* to false where previously some were set to true the caller can either pass all
|
||||
* the XXXAccess fields explicitly, or pass none and the default will be set for each.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class SecuritySettingsDTO {
|
||||
|
||||
/*
|
||||
* The 4-digit user access code for the thermostat. The code must be set when
|
||||
* enabling access control. See the callout above for more information.
|
||||
*/
|
||||
public String userAccessCode;
|
||||
|
||||
/*
|
||||
* The flag for determing whether there are any restrictions on the thermostat
|
||||
* regarding access control. Default value is false. If all other values are
|
||||
* true this value will default to true.
|
||||
*/
|
||||
public Boolean allUserAccess;
|
||||
|
||||
/*
|
||||
* The flag for determing whether there are any restrictions on the thermostat
|
||||
* regarding access control to the Thermostat Program. Default value is false,
|
||||
* unless allUserAccess is true.
|
||||
*/
|
||||
public Boolean programAccess;
|
||||
|
||||
/*
|
||||
* The flag for determing whether there are any restrictions on the thermostat
|
||||
* regarding access control to the Thermostat system and settings. Default value
|
||||
* is false, unless allUserAccess is true.
|
||||
*/
|
||||
public Boolean detailsAccess;
|
||||
|
||||
/*
|
||||
* The flag for determing whether there are any restrictions on the thermostat
|
||||
* regarding access control to the Thermostat quick save functionality. Default
|
||||
* value is false, unless allUserAccess is true.
|
||||
*/
|
||||
public Boolean quickSaveAccess;
|
||||
|
||||
/*
|
||||
* The flag for determing whether there are any restrictions on the thermostat
|
||||
* regarding access control to the Thermostat vacation functionality. Default
|
||||
* value is false, unless allUserAccess is true.
|
||||
*/
|
||||
public Boolean vacationAccess;
|
||||
}
|
||||
@@ -0,0 +1,620 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link SettingsDTO} is responsible for
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class SettingsDTO {
|
||||
|
||||
/*
|
||||
* The current HVAC mode the thermostat is in. Values: auto, auxHeatOnly, cool, heat, off.
|
||||
*/
|
||||
public String hvacMode;
|
||||
|
||||
/*
|
||||
* The last service date of the HVAC equipment.
|
||||
*/
|
||||
public String lastServiceDate;
|
||||
|
||||
/*
|
||||
* Whether to send an alert when service is required again.
|
||||
*/
|
||||
public Boolean serviceRemindMe;
|
||||
|
||||
/*
|
||||
* The user configured monthly interval between HVAC service reminders
|
||||
*/
|
||||
public Integer monthsBetweenService;
|
||||
|
||||
/*
|
||||
* Date to be reminded about the next HVAC service date.
|
||||
*/
|
||||
public String remindMeDate;
|
||||
|
||||
/*
|
||||
* The ventilator mode. Values: auto, minontime, on, off.
|
||||
*/
|
||||
public String vent;
|
||||
|
||||
/*
|
||||
* The minimum time in minutes the ventilator is configured to run. The thermostat will always
|
||||
* guarantee that the ventilator runs for this minimum duration whenever engaged.
|
||||
*/
|
||||
public Integer ventilatorMinOnTime;
|
||||
|
||||
/*
|
||||
* Whether the technician associated with this thermostat should receive the HVAC service reminders as well.
|
||||
*/
|
||||
public Boolean serviceRemindTechnician;
|
||||
|
||||
/*
|
||||
* A note about the physical location where the SMART or EMS Equipment Interface module is located.
|
||||
*/
|
||||
public String eiLocation;
|
||||
|
||||
/*
|
||||
* The temperature at which a cold temp alert is triggered.
|
||||
*/
|
||||
public Integer coldTempAlert;
|
||||
|
||||
/*
|
||||
* Whether cold temperature alerts are enabled.
|
||||
*/
|
||||
public Boolean coldTempAlertEnabled;
|
||||
|
||||
/*
|
||||
* The temperature at which a hot temp alert is triggered.
|
||||
*/
|
||||
public Integer hotTempAlert;
|
||||
|
||||
/*
|
||||
* Whether hot temperature alerts are enabled.
|
||||
*/
|
||||
public Boolean hotTempAlertEnabled;
|
||||
|
||||
/*
|
||||
* The number of cool stages the connected HVAC equipment supports.
|
||||
*/
|
||||
public Integer coolStages;
|
||||
|
||||
/*
|
||||
* The number of heat stages the connected HVAC equipment supports.
|
||||
*/
|
||||
public Integer heatStages;
|
||||
|
||||
/*
|
||||
* The maximum automated set point set back offset allowed in degrees.
|
||||
*/
|
||||
public Integer maxSetBack;
|
||||
|
||||
/*
|
||||
* The maximum automated set point set forward offset allowed in degrees.
|
||||
*/
|
||||
public Integer maxSetForward;
|
||||
|
||||
/*
|
||||
* The set point set back offset, in degrees, configured for a quick save event.
|
||||
*/
|
||||
public Integer quickSaveSetBack;
|
||||
|
||||
/*
|
||||
* The set point set forward offset, in degrees, configured for a quick save event.
|
||||
*/
|
||||
public Integer quickSaveSetForward;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is controlling a heat pump.
|
||||
*/
|
||||
public Boolean hasHeatPump;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is controlling a forced air furnace.
|
||||
*/
|
||||
public Boolean hasForcedAir;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is controlling a boiler.
|
||||
*/
|
||||
public Boolean hasBoiler;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is controlling a humidifier.
|
||||
*/
|
||||
public Boolean hasHumidifier;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is controlling an energy recovery ventilator.
|
||||
*/
|
||||
public Boolean hasErv;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is controlling a heat recovery ventilator.
|
||||
*/
|
||||
public Boolean hasHrv;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is in frost control mode.
|
||||
*/
|
||||
public Boolean condensationAvoid;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is configured to report in degrees Celsius.
|
||||
*/
|
||||
public Boolean useCelsius;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is using 12hr time format.
|
||||
*/
|
||||
public Boolean useTimeFormat12;
|
||||
|
||||
/*
|
||||
* Multilanguage support, currently only "en" - english is supported. In future others
|
||||
* locales can be supported.
|
||||
*/
|
||||
public String locale;
|
||||
|
||||
/*
|
||||
* The minimum humidity level (in percent) set point for the humidifier
|
||||
*/
|
||||
public String humidity;
|
||||
|
||||
/*
|
||||
* The humidifier mode. Values: auto, manual, off.
|
||||
*/
|
||||
public String humidifierMode;
|
||||
|
||||
/*
|
||||
* The thermostat backlight intensity when on. A value between 0 and 10, with 0
|
||||
* meaning 'off' - the zero value may not be honored by all ecobee versions.
|
||||
*/
|
||||
public Integer backlightOnIntensity;
|
||||
|
||||
/*
|
||||
* The thermostat backlight intensity when asleep. A value between 0 and 10, with 0
|
||||
* meaning 'off' - the zero value may not be honored by all ecobee versions.
|
||||
*/
|
||||
public Integer backlightSleepIntensity;
|
||||
|
||||
/*
|
||||
* The time in seconds before the thermostat screen goes into sleep mode.
|
||||
*/
|
||||
public Integer backlightOffTime;
|
||||
|
||||
/*
|
||||
* The field is deprecated. Please use Audio.soundTickVolume.
|
||||
*/
|
||||
public Integer soundTickVolume;
|
||||
|
||||
/*
|
||||
* The field is deprecated. Please use Audio.soundAlertVolume.
|
||||
*/
|
||||
public Integer soundAlertVolume;
|
||||
|
||||
/*
|
||||
* The minimum time the compressor must be off for in order to prevent short-cycling.
|
||||
*/
|
||||
public Integer compressorProtectionMinTime;
|
||||
|
||||
/*
|
||||
* The minimum outdoor temperature that the compressor can operate at - applies
|
||||
* more to air source heat pumps than geothermal.
|
||||
*/
|
||||
public Integer compressorProtectionMinTemp;
|
||||
|
||||
/*
|
||||
* The difference between current temperature and set-point that will trigger stage 2 heating.
|
||||
*/
|
||||
public Integer stage1HeatingDifferentialTemp;
|
||||
|
||||
/*
|
||||
* The difference between current temperature and set-point that will trigger stage 2 cooling.
|
||||
*/
|
||||
public Integer stage1CoolingDifferentialTemp;
|
||||
|
||||
/*
|
||||
* The time after a heating cycle that the fan will run for to extract any heating left
|
||||
* in the system - 30 second default.
|
||||
*/
|
||||
public Integer stage1HeatingDissipationTime;
|
||||
|
||||
/*
|
||||
* The time after a cooling cycle that the fan will run for to extract any cooling left
|
||||
* in the system - 30 second default.
|
||||
*/
|
||||
public Integer stage1CoolingDissipationTime;
|
||||
|
||||
/*
|
||||
* The flag to tell if the heat pump is in heating mode or in cooling when the relay
|
||||
* is engaged. If set to zero it's heating when the reversing valve is open, cooling
|
||||
* when closed and if it's one - it's the opposite.
|
||||
*/
|
||||
public Boolean heatPumpReversalOnCool;
|
||||
|
||||
/*
|
||||
* Whether fan control by the Thermostat is required in auxiliary heating (gas/electric/boiler),
|
||||
* otherwise controlled by furnace.
|
||||
*/
|
||||
public Boolean fanControlRequired;
|
||||
|
||||
/*
|
||||
* The minimum time, in minutes, to run the fan each hour. Value from 1 to 60.
|
||||
*/
|
||||
public Integer fanMinOnTime;
|
||||
|
||||
/*
|
||||
* The minimum temperature difference between the heat and cool values. Used to ensure that when
|
||||
* thermostat is in auto mode, the heat and cool values are separated by at least this value.
|
||||
*/
|
||||
public Integer heatCoolMinDelta;
|
||||
|
||||
/*
|
||||
* The amount to adjust the temperature reading in degrees F - this value is subtracted from
|
||||
* the temperature read from the sensor.
|
||||
*/
|
||||
public Integer tempCorrection;
|
||||
|
||||
/*
|
||||
* The default end time setting the thermostat applies to user temperature holds. Values useEndTime4hour,
|
||||
* useEndTime2hour (EMS Only), nextPeriod, indefinite, askMe
|
||||
*/
|
||||
public String holdAction;
|
||||
|
||||
/*
|
||||
* Whether the Thermostat uses a geothermal / ground source heat pump.
|
||||
*/
|
||||
public Boolean heatPumpGroundWater;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is connected to an electric HVAC system.
|
||||
*/
|
||||
public Boolean hasElectric;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is connected to a dehumidifier. If true or dehumidifyOvercoolOffset > 0 then
|
||||
* allow setting dehumidifierMode and dehumidifierLevel.
|
||||
*/
|
||||
public Boolean hasDehumidifier;
|
||||
|
||||
/*
|
||||
* The dehumidifier mode. Values: on, off. If set to off then the dehumidifier will not run,
|
||||
* nor will the AC overcool run.
|
||||
*/
|
||||
public String dehumidifierMode;
|
||||
|
||||
/*
|
||||
* The dehumidification set point in percentage.
|
||||
*/
|
||||
public Integer dehumidifierLevel;
|
||||
|
||||
/*
|
||||
* Whether the thermostat should use AC overcool to dehumidify. When set to true a postive integer value
|
||||
* must be supplied for dehumidifyOvercoolOffset otherwise an API validation exception will be thrown.
|
||||
*/
|
||||
public Boolean dehumidifyWithAC;
|
||||
|
||||
/*
|
||||
* Whether the thermostat should use AC overcool to dehumidify and what that temperature offset
|
||||
* should be. A value of 0 means this feature is disabled and dehumidifyWithAC will be set to false.
|
||||
* Value represents the value in F to subract from the current set point. Values should be in the
|
||||
* range 0 - 50 and be divisible by 5.
|
||||
*/
|
||||
public Integer dehumidifyOvercoolOffset;
|
||||
|
||||
/*
|
||||
* If enabled, allows the Thermostat to be put in HVACAuto mode.
|
||||
*/
|
||||
public Boolean autoHeatCoolFeatureEnabled;
|
||||
|
||||
/*
|
||||
* Whether the alert for when wifi is offline is enabled.
|
||||
*/
|
||||
public Boolean wifiOfflineAlert;
|
||||
|
||||
/*
|
||||
* The minimum heat set point allowed by the thermostat firmware.
|
||||
*/
|
||||
public Integer heatMinTemp;
|
||||
|
||||
/*
|
||||
* The maximum heat set point allowed by the thermostat firmware.
|
||||
*/
|
||||
public Integer heatMaxTemp;
|
||||
|
||||
/*
|
||||
* The minimum cool set point allowed by the thermostat firmware.
|
||||
*/
|
||||
public Integer coolMinTemp;
|
||||
|
||||
/*
|
||||
* The maximum cool set point allowed by the thermostat firmware.
|
||||
*/
|
||||
public Integer coolMaxTemp;
|
||||
|
||||
/*
|
||||
* The maximum heat set point configured by the user's preferences.
|
||||
*/
|
||||
public Integer heatRangeHigh;
|
||||
|
||||
/*
|
||||
* The minimum heat set point configured by the user's preferences.
|
||||
*/
|
||||
public Integer heatRangeLow;
|
||||
|
||||
/*
|
||||
* The maximum cool set point configured by the user's preferences.
|
||||
*/
|
||||
public Integer coolRangeHigh;
|
||||
|
||||
/*
|
||||
* The minimum heat set point configured by the user's preferences.
|
||||
*/
|
||||
public Integer coolRangeLow;
|
||||
|
||||
/*
|
||||
* The user access code value for this thermostat. See the SecuritySettings object for more information.
|
||||
*/
|
||||
public String userAccessCode;
|
||||
|
||||
/*
|
||||
* The integer representation of the user access settings. See the SecuritySettings object for more information.
|
||||
*/
|
||||
public Integer userAccessSetting;
|
||||
|
||||
/*
|
||||
* The temperature at which an auxHeat temperature alert is triggered.
|
||||
*/
|
||||
public Integer auxRuntimeAlert;
|
||||
|
||||
/*
|
||||
* The temperature at which an auxOutdoor temperature alert is triggered.
|
||||
*/
|
||||
public Integer auxOutdoorTempAlert;
|
||||
|
||||
/*
|
||||
* The maximum outdoor temperature above which aux heat will not run.
|
||||
*/
|
||||
public Integer auxMaxOutdoorTemp;
|
||||
|
||||
/*
|
||||
* Whether the auxHeat temperature alerts are enabled.
|
||||
*/
|
||||
public Boolean auxRuntimeAlertNotify;
|
||||
|
||||
/*
|
||||
* Whether the auxOutdoor temperature alerts are enabled.
|
||||
*/
|
||||
public Boolean auxOutdoorTempAlertNotify;
|
||||
|
||||
/*
|
||||
* Whether the auxHeat temperature alerts for the technician are enabled.
|
||||
*/
|
||||
public Boolean auxRuntimeAlertNotifyTechnician;
|
||||
|
||||
/*
|
||||
* Whether the auxOutdoor temperature alerts for the technician are enabled.
|
||||
*/
|
||||
public Boolean auxOutdoorTempAlertNotifyTechnician;
|
||||
|
||||
/*
|
||||
* Whether the thermostat should use pre heating to reach the set point on time.
|
||||
*/
|
||||
public Boolean disablePreHeating;
|
||||
|
||||
/*
|
||||
* Whether the thermostat should use pre cooling to reach the set point on time.
|
||||
*/
|
||||
public Boolean disablePreCooling;
|
||||
|
||||
/*
|
||||
* Whether an installer code is required.
|
||||
*/
|
||||
public Boolean installerCodeRequired;
|
||||
|
||||
/*
|
||||
* Whether Demand Response requests are accepted by this thermostat. Possible values
|
||||
* are: always, askMe, customerSelect, defaultAccept, defaultDecline, never.
|
||||
*/
|
||||
public String drAccept;
|
||||
|
||||
/*
|
||||
* Whether the property is a rental, or not.
|
||||
*/
|
||||
public Boolean isRentalProperty;
|
||||
|
||||
/*
|
||||
* Whether to use a zone controller or not.
|
||||
*/
|
||||
public Boolean useZoneController;
|
||||
|
||||
/*
|
||||
* Whether random start delay is enabled for cooling.
|
||||
*/
|
||||
public Integer randomStartDelayCool;
|
||||
|
||||
/*
|
||||
* Whether random start delay is enabled for heating.
|
||||
*/
|
||||
public Integer randomStartDelayHeat;
|
||||
|
||||
/*
|
||||
* The humidity level to trigger a high humidity alert.
|
||||
*/
|
||||
public Integer humidityHighAlert;
|
||||
|
||||
/*
|
||||
* The humidity level to trigger a low humidity alert.
|
||||
*/
|
||||
public Integer humidityLowAlert;
|
||||
|
||||
/*
|
||||
* Whether heat pump alerts are disabled.
|
||||
*/
|
||||
public Boolean disableHeatPumpAlerts;
|
||||
|
||||
/*
|
||||
* Whether alerts are disabled from showing on the thermostat.
|
||||
*/
|
||||
public Boolean disableAlertsOnIdt;
|
||||
|
||||
/*
|
||||
* Whether humidification alerts are enabled to the thermsotat owner.
|
||||
*/
|
||||
public Boolean humidityAlertNotify;
|
||||
|
||||
/*
|
||||
* Whether humidification alerts are enabled to the technician associated with the thermsotat.
|
||||
*/
|
||||
public Boolean humidityAlertNotifyTechnician;
|
||||
|
||||
/*
|
||||
* Whether temperature alerts are enabled to the thermsotat owner.
|
||||
*/
|
||||
public Boolean tempAlertNotify;
|
||||
|
||||
/*
|
||||
* Whether temperature alerts are enabled to the technician associated with the thermostat.
|
||||
*/
|
||||
public Boolean tempAlertNotifyTechnician;
|
||||
|
||||
/*
|
||||
* The dollar amount the owner specifies for their desired maximum electricy bill.
|
||||
*/
|
||||
public Integer monthlyElectricityBillLimit;
|
||||
|
||||
/*
|
||||
* Whether electricity bill alerts are enabled.
|
||||
*/
|
||||
public Boolean enableElectricityBillAlert;
|
||||
|
||||
/*
|
||||
* Whether electricity bill projection alerts are enabled
|
||||
*/
|
||||
public Boolean enableProjectedElectricityBillAlert;
|
||||
|
||||
/*
|
||||
* The day of the month the owner's electricty usage is billed.
|
||||
*/
|
||||
public Integer electricityBillingDayOfMonth;
|
||||
|
||||
/*
|
||||
* The owners billing cycle duration in months.
|
||||
*/
|
||||
public Integer electricityBillCycleMonths;
|
||||
|
||||
/*
|
||||
* The annual start month of the owners billing cycle.
|
||||
*/
|
||||
public Integer electricityBillStartMonth;
|
||||
|
||||
/*
|
||||
* The number of minutes to run ventilator per hour when home.
|
||||
*/
|
||||
public Integer ventilatorMinOnTimeHome;
|
||||
|
||||
/*
|
||||
* The number of minutes to run ventilator per hour when away.
|
||||
*/
|
||||
public Integer ventilatorMinOnTimeAway;
|
||||
|
||||
/*
|
||||
* Determines whether or not to turn the backlight off during sleep.
|
||||
*/
|
||||
public Boolean backlightOffDuringSleep;
|
||||
|
||||
/*
|
||||
* When set to true if no occupancy motion detected thermostat will go into indefinite away
|
||||
* hold, until either the user presses resume schedule or motion is detected.
|
||||
*/
|
||||
public Boolean autoAway;
|
||||
|
||||
/*
|
||||
* When set to true if a larger than normal delta is found between sensors the fan
|
||||
* will be engaged for 15min/hour.
|
||||
*/
|
||||
public Boolean smartCirculation;
|
||||
|
||||
/*
|
||||
* When set to true if a sensor has detected presense for more than 10 minutes then
|
||||
* include that sensor in temp average. If no activity has been seen on a sensor for
|
||||
* more than 1 hour then remove this sensor from temperature average.
|
||||
*/
|
||||
public Boolean followMeComfort;
|
||||
|
||||
/*
|
||||
* This read-only field represents the type of ventilator present for the Thermostat.
|
||||
* The possible values are none, ventilator, hrv, and erv.
|
||||
*/
|
||||
public String ventilatorType;
|
||||
|
||||
/*
|
||||
* This Boolean field represents whether the ventilator timer is on or off. The default
|
||||
* value is false. If set to true the ventilatorOffDateTime is set to now() + 20 minutes.
|
||||
* If set to false the ventilatorOffDateTime is set to it's default value.
|
||||
*/
|
||||
public Boolean isVentilatorTimerOn;
|
||||
|
||||
/*
|
||||
* This read-only field represents the Date and Time the ventilator will run until.
|
||||
* The default value is 2014-01-01 00:00:00.
|
||||
*/
|
||||
public String ventilatorOffDateTime;
|
||||
|
||||
/*
|
||||
* This Boolean field represents whether the HVAC system has a UV filter. The default value is true.
|
||||
*/
|
||||
public Boolean hasUVFilter;
|
||||
|
||||
/*
|
||||
* This field represents whether to permit the cooling to operate when the Outdoor temeperature
|
||||
* is under a specific threshold, currently 55F. The default value is false.
|
||||
*/
|
||||
public Boolean coolingLockout;
|
||||
|
||||
/*
|
||||
* Whether to use the ventilator to dehumidify when climate or calendar event indicates the owner
|
||||
* is home. The default value is false.
|
||||
*/
|
||||
public Boolean ventilatorFreeCooling;
|
||||
|
||||
/*
|
||||
* This field represents whether to permit dehumidifer to operate when the heating is
|
||||
* running. The default value is false.
|
||||
*/
|
||||
public Boolean dehumidifyWhenHeating;
|
||||
|
||||
/*
|
||||
* This field represents whether or not to allow dehumification when cooling. The default value is true.
|
||||
*/
|
||||
public Boolean ventilatorDehumidify;
|
||||
|
||||
/*
|
||||
* The unique reference to the group this thermostat belongs to, if any. See GET Group request and POST
|
||||
* Group request for more information.
|
||||
*/
|
||||
public String groupRef;
|
||||
|
||||
/*
|
||||
* The name of the the group this thermostat belongs to, if any. See GET Group request and POST Group
|
||||
* request for more information.
|
||||
*/
|
||||
public String groupName;
|
||||
|
||||
/*
|
||||
* The setting value for the group this thermostat belongs to, if any. See GET Group request and POST
|
||||
* Group request for more information.
|
||||
*/
|
||||
public Integer groupSetting;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link TechnicianDTO} contains information pertaining to the technician
|
||||
* associated with a thermostat. The technician may not be modified through the API.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class TechnicianDTO {
|
||||
/*
|
||||
* The internal ecobee unique identifier for this contractor.
|
||||
*/
|
||||
public String contractorRef;
|
||||
|
||||
/*
|
||||
* The company name of the technician.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* The technician's contact phone number.
|
||||
*/
|
||||
public String phone;
|
||||
|
||||
/*
|
||||
* The technician's street address.
|
||||
*/
|
||||
public String streetAddress;
|
||||
|
||||
/*
|
||||
* The technician's city.
|
||||
*/
|
||||
public String city;
|
||||
|
||||
/*
|
||||
* The technician's State or Province.
|
||||
*/
|
||||
public String provinceState;
|
||||
|
||||
/*
|
||||
* The technician's country.
|
||||
*/
|
||||
public String country;
|
||||
|
||||
/*
|
||||
* The technician's ZIP or Postal Code.
|
||||
*/
|
||||
public String postalCode;
|
||||
|
||||
/*
|
||||
* The technician's email address.
|
||||
*/
|
||||
public String email;
|
||||
|
||||
/*
|
||||
* The technician's web site.
|
||||
*/
|
||||
public String web;
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link ThermostatDTO} is the central piece of the ecobee API. All objects
|
||||
* relate in one way or another to a real thermostat. The thermostat object
|
||||
* and its component objects define the real thermostat device.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ThermostatDTO {
|
||||
/*
|
||||
* The unique thermostat serial number.
|
||||
*/
|
||||
public String identifier;
|
||||
|
||||
/*
|
||||
* A user defined name for a thermostat.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* The current thermostat configuration revision.
|
||||
*/
|
||||
public String thermostatRev;
|
||||
|
||||
/*
|
||||
* Whether the user registered the thermostat.
|
||||
*/
|
||||
public Boolean isRegistered;
|
||||
|
||||
/*
|
||||
* The thermostat model number.
|
||||
*
|
||||
* Values: apolloSmart, apolloEms, idtSmart, idtEms, siSmart, siEms,
|
||||
* athenaSmart, athenaEms, corSmart, nikeSmart, nikeEms
|
||||
*/
|
||||
public String modelNumber;
|
||||
|
||||
/*
|
||||
* The thermostat brand.
|
||||
*/
|
||||
public String brand;
|
||||
|
||||
/*
|
||||
* The comma-separated list of the thermostat's additional features, if any.
|
||||
*/
|
||||
public String features;
|
||||
|
||||
/*
|
||||
* The last modified date time for the thermostat configuration.
|
||||
*/
|
||||
public Date lastModified;
|
||||
|
||||
/*
|
||||
* The current time in the thermostat's time zone.
|
||||
*/
|
||||
public Date thermostatTime;
|
||||
|
||||
/*
|
||||
* The current time in UTC.
|
||||
*/
|
||||
public String utcTime;
|
||||
|
||||
/*
|
||||
* The status of all equipment controlled by this Thermostat.
|
||||
* Only running equipment is listed in the CSV String.
|
||||
*
|
||||
* Values: heatPump, heatPump2, heatPump3, compCool1, compCool2,
|
||||
* auxHeat1, auxHeat2, auxHeat3, fan, humidifier, dehumidifier,
|
||||
* ventilator, economizer, compHotWater, auxHotWater.
|
||||
*
|
||||
* Note: If no equipment is currently running an empty String is returned.
|
||||
* If Settings.hasHeatPump is true, heatPump value will be returned for
|
||||
* heating, compCool for cooling, and auxHeat for aux heat.
|
||||
* If Settings.hasForcedAir or Settings.hasBoiler is true, auxHeat value
|
||||
* will be returned for heating and compCool for cooling (heatPump will
|
||||
* not show up for heating).
|
||||
*/
|
||||
public String equipmentStatus;
|
||||
|
||||
public List<AlertDTO> alerts;
|
||||
|
||||
public AudioDTO audio;
|
||||
|
||||
public List<DeviceDTO> devices;
|
||||
|
||||
public ElectricityDTO electricity;
|
||||
|
||||
public EnergyDTO energy;
|
||||
|
||||
public List<EventDTO> events;
|
||||
|
||||
public ExtendedRuntimeDTO extendedRuntime;
|
||||
|
||||
public HouseDetailsDTO houseDetails;
|
||||
|
||||
public LocationDTO location;
|
||||
|
||||
public ManagementDTO management;
|
||||
|
||||
public NotificationSettingsDTO notificationSettings;
|
||||
|
||||
public OemCfgDTO oemCfg;
|
||||
|
||||
public PrivacyDTO privacy;
|
||||
|
||||
public ProgramDTO program;
|
||||
|
||||
public List<ReminderDTO> reminders;
|
||||
|
||||
public RuntimeDTO runtime;
|
||||
|
||||
public SecuritySettingsDTO securitySettings;
|
||||
|
||||
public List<RemoteSensorDTO> remoteSensors;
|
||||
|
||||
public SettingsDTO settings;
|
||||
|
||||
public TechnicianDTO technician;
|
||||
|
||||
public UtilityDTO utility;
|
||||
|
||||
public VersionDTO version;
|
||||
|
||||
public WeatherDTO weather;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import org.openhab.binding.ecobee.internal.dto.SelectionDTO;
|
||||
|
||||
/**
|
||||
* The {@link ThermostatRequestDTO} contains the information needed to make a thermostat request.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ThermostatRequestDTO {
|
||||
|
||||
public ThermostatRequestDTO(SelectionDTO selection) {
|
||||
this.selection = selection;
|
||||
}
|
||||
|
||||
/*
|
||||
* Specifies which thermostats will be returned in the response.
|
||||
*/
|
||||
public SelectionDTO selection;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.ecobee.internal.dto.AbstractResponseDTO;
|
||||
|
||||
/**
|
||||
* The {@link ThermostatResponseDTO} contains the list of thermostats in response to a
|
||||
* thermostat request.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ThermostatResponseDTO extends AbstractResponseDTO {
|
||||
|
||||
/*
|
||||
* List of thermostats matching the selection criteria in the thermostat request.
|
||||
*/
|
||||
public List<ThermostatDTO> thermostatList;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import org.openhab.binding.ecobee.internal.dto.SelectionDTO;
|
||||
|
||||
/**
|
||||
* The {@link ThermostatUpdateRequestDTO} contains the information needed to make a
|
||||
* request to update a thermostat.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ThermostatUpdateRequestDTO {
|
||||
|
||||
public ThermostatUpdateRequestDTO(SelectionDTO selection) {
|
||||
this.selection = selection;
|
||||
}
|
||||
|
||||
/*
|
||||
* Thermostat object containing changes.
|
||||
*/
|
||||
public ThermostatDTO thermostat;
|
||||
|
||||
/*
|
||||
* Specifies the thermostat to be updated.
|
||||
*/
|
||||
public SelectionDTO selection;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link UtilityDTO} contains the Utility information the Thermostat belongs to.
|
||||
* The utility may not be modified through the API.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class UtilityDTO {
|
||||
/*
|
||||
* The Utility company name.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* The Utility company contact phone number.
|
||||
*/
|
||||
public String phone;
|
||||
|
||||
/*
|
||||
* The Utility company email address.
|
||||
*/
|
||||
public String email;
|
||||
|
||||
/*
|
||||
* The Utility company web site.
|
||||
*/
|
||||
public String web;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link VersionDTO} contains version information about the thermostat.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class VersionDTO {
|
||||
|
||||
/*
|
||||
* The thermostat firmware version number.
|
||||
*/
|
||||
public String thermostatFirmwareVersion;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
/**
|
||||
* The {@link VoiceEngineDTO} contains information about the voice assistant
|
||||
* that the selected thermostat supports.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class VoiceEngineDTO {
|
||||
|
||||
/*
|
||||
* The name of the voice engine.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* True if the voice engine is currently enabled (paired) for the ecobee account of
|
||||
* selected thermostat. You can change the flag value by using UnlinkVoiceEngine
|
||||
* thermostat function.
|
||||
*/
|
||||
public Boolean enabled;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link WeatherDTO} contains the weather and forecast information for the thermostat's location.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class WeatherDTO {
|
||||
|
||||
/*
|
||||
* The time stamp in UTC of the weather forecast
|
||||
*/
|
||||
public Date timestamp;
|
||||
|
||||
/*
|
||||
* The weather station identifier
|
||||
*/
|
||||
public String weatherStation;
|
||||
|
||||
/*
|
||||
* The list of latest weather station forecasts
|
||||
*/
|
||||
public List<WeatherForecastDTO> forecasts;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* The {@link WeatherForecastDTO} contains the weather forecast information for
|
||||
* the thermostat. The first forecast is the most accurate, later forecasts
|
||||
* become less accurate in distance and time.
|
||||
*
|
||||
* Weather Symbol Mappings
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class WeatherForecastDTO {
|
||||
|
||||
/*
|
||||
* The Integer value used to map to a weatherSymbol.
|
||||
*/
|
||||
public Integer weatherSymbol;
|
||||
|
||||
/*
|
||||
* The time stamp of the weather forecast.
|
||||
*/
|
||||
public Date dateTime;
|
||||
|
||||
/*
|
||||
* A text value representing the current weather condition.
|
||||
*/
|
||||
public String condition;
|
||||
|
||||
/*
|
||||
* The current temperature.
|
||||
*/
|
||||
public Integer temperature;
|
||||
|
||||
/*
|
||||
* The current barometric pressure.
|
||||
*/
|
||||
public Integer pressure;
|
||||
|
||||
/*
|
||||
* The current humidity.
|
||||
*/
|
||||
public Integer relativeHumidity;
|
||||
|
||||
/*
|
||||
* he dewpoint.
|
||||
*/
|
||||
public Integer dewpoint;
|
||||
|
||||
/*
|
||||
* The visibility in meters; 0 - 70,000.
|
||||
*/
|
||||
public Integer visibility;
|
||||
|
||||
/*
|
||||
* The wind speed as an integer in mph * 1000.
|
||||
*/
|
||||
public Integer windSpeed;
|
||||
|
||||
/*
|
||||
* The wind gust speed.
|
||||
*/
|
||||
public Integer windGust;
|
||||
|
||||
/*
|
||||
* The wind direction.
|
||||
*/
|
||||
public String windDirection;
|
||||
|
||||
/*
|
||||
* The wind bearing.
|
||||
*/
|
||||
public Integer windBearing;
|
||||
|
||||
/*
|
||||
* The probability of precipitation.
|
||||
*/
|
||||
public Integer pop;
|
||||
|
||||
/*
|
||||
* The predicted high temperature for the day.
|
||||
*/
|
||||
public Integer tempHigh;
|
||||
|
||||
/*
|
||||
* The predicted low temperature for the day.
|
||||
*/
|
||||
public Integer tempLow;
|
||||
|
||||
/*
|
||||
* The cloud cover condition.
|
||||
*/
|
||||
public Integer sky;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat.summary;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link RevisionDTO} contains information indicating what data
|
||||
* has changed on the thermostat(s).
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class RevisionDTO {
|
||||
|
||||
/*
|
||||
* The thermostat identifier.
|
||||
*/
|
||||
public String identifier;
|
||||
|
||||
/*
|
||||
* The thermostat name, otherwise an empty field if one is not set.
|
||||
*/
|
||||
public @Nullable String name;
|
||||
|
||||
/*
|
||||
* Whether the thermostat is currently connected to the ecobee servers.
|
||||
*/
|
||||
public @Nullable Boolean connected;
|
||||
|
||||
/*
|
||||
* Current thermostat revision. This revision is incremented whenever
|
||||
* the thermostat program, hvac mode, settings or configuration change.
|
||||
* Changes to the following objects will update the thermostat revision:
|
||||
* Settings, Program, Event, Device.
|
||||
*/
|
||||
public String thermostatRevision;
|
||||
|
||||
/*
|
||||
* Current revision of the thermostat alerts. This revision is incremented
|
||||
* whenever a new Alert is issued or an Alert is modified (acknowledged or deferred).
|
||||
*/
|
||||
public String alertsRevision;
|
||||
|
||||
/*
|
||||
* The current revision of the thermostat runtime settings. This revision is
|
||||
* incremented whenever the thermostat transmits a new status message, or
|
||||
* updates the equipment state or Remote Sensor readings. The shortest interval
|
||||
* this revision may change is 3 minutes.
|
||||
*/
|
||||
public String runtimeRevision;
|
||||
|
||||
/*
|
||||
* The current revision of the thermostat interval runtime settings. This
|
||||
* revision is incremented whenever the thermostat transmits a new status message
|
||||
* in the form of a Runtime object. The thermostat updates this on a 15 minute interval.
|
||||
*/
|
||||
public String intervalRevision;
|
||||
|
||||
public RevisionDTO() {
|
||||
identifier = "";
|
||||
thermostatRevision = "";
|
||||
alertsRevision = "";
|
||||
runtimeRevision = "";
|
||||
intervalRevision = "";
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public RevisionDTO getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasChanged(@Nullable RevisionDTO previous) {
|
||||
if (previous == null) {
|
||||
return true;
|
||||
}
|
||||
return !(thermostatRevision.equals(previous.thermostatRevision)
|
||||
&& alertsRevision.equals(previous.alertsRevision) && runtimeRevision.equals(previous.runtimeRevision)
|
||||
&& intervalRevision.equals(previous.intervalRevision));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("id:").append(identifier);
|
||||
sb.append(" tstat:").append(thermostatRevision);
|
||||
sb.append(" alert:").append(alertsRevision);
|
||||
sb.append(" rntim:").append(runtimeRevision);
|
||||
sb.append(" intrv:").append(intervalRevision);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat.summary;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
/**
|
||||
* The {@link RevisionDTODeserializer} is responsible for
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class RevisionDTODeserializer implements JsonDeserializer<@Nullable RevisionDTO> {
|
||||
|
||||
@Override
|
||||
public @Nullable RevisionDTO deserialize(@Nullable JsonElement json, @Nullable Type typeOfT,
|
||||
@Nullable JsonDeserializationContext context) throws JsonParseException {
|
||||
if (json == null || typeOfT == null || context == null) {
|
||||
return null;
|
||||
}
|
||||
String[] fields = json.getAsString().split(":");
|
||||
if (fields.length < 7) {
|
||||
throw new JsonParseException("unable to parse RevisionList");
|
||||
}
|
||||
RevisionDTO revisionList = new RevisionDTO();
|
||||
revisionList.identifier = fields[0];
|
||||
revisionList.name = fields[1];
|
||||
revisionList.connected = "true".equals(fields[2]);
|
||||
revisionList.thermostatRevision = fields[3];
|
||||
revisionList.alertsRevision = fields[4];
|
||||
revisionList.runtimeRevision = fields[5];
|
||||
revisionList.intervalRevision = fields[6];
|
||||
return revisionList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat.summary;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link RunningDTO} contains information indicating what equipment
|
||||
* is running.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class RunningDTO {
|
||||
|
||||
/*
|
||||
* The thermostat identifier.
|
||||
*/
|
||||
public String identifier;
|
||||
|
||||
/*
|
||||
* If no equipment is currently running no data is returned. Possible values
|
||||
* are: heatPump, heatPump2, heatPump3, compCool1, compCool2, auxHeat1,
|
||||
* auxHeat2, auxHeat3, fan, humidifier, dehumidifier, ventilator, economizer,
|
||||
* compHotWater, auxHotWater.
|
||||
*/
|
||||
public final Set<String> runningEquipment;
|
||||
|
||||
public RunningDTO() {
|
||||
identifier = "";
|
||||
runningEquipment = new HashSet<>();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public RunningDTO getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasChanged(@Nullable RunningDTO previous) {
|
||||
if (previous == null) {
|
||||
return true;
|
||||
}
|
||||
return !runningEquipment.equals(previous.runningEquipment);
|
||||
}
|
||||
|
||||
public boolean isIdle() {
|
||||
return runningEquipment.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isHeating() {
|
||||
return runningEquipment.contains("heatPump") || runningEquipment.contains("heatPump2")
|
||||
|| runningEquipment.contains("heatPump3") || runningEquipment.contains("auxHeat1")
|
||||
|| runningEquipment.contains("auxHeat2") || runningEquipment.contains("auxHeat3");
|
||||
}
|
||||
|
||||
public boolean isCooling() {
|
||||
return runningEquipment.contains("compCool1") || runningEquipment.contains("compCool2");
|
||||
}
|
||||
|
||||
public boolean isRunning(final String equipment) {
|
||||
return runningEquipment.contains(equipment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat.summary;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
/**
|
||||
* The {@link RunningDTODeserializer} is responsible for
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class RunningDTODeserializer implements JsonDeserializer<@Nullable RunningDTO> {
|
||||
|
||||
@Override
|
||||
public @Nullable RunningDTO deserialize(@Nullable JsonElement json, @Nullable Type typeOfT,
|
||||
@Nullable JsonDeserializationContext context) throws JsonParseException {
|
||||
if (json == null || typeOfT == null || context == null) {
|
||||
return null;
|
||||
}
|
||||
String[] fields = json.getAsString().split(":");
|
||||
if (fields.length < 1) {
|
||||
throw new JsonParseException("unable to parse StatusList");
|
||||
}
|
||||
RunningDTO statusList = new RunningDTO();
|
||||
statusList.identifier = fields[0];
|
||||
if (fields.length >= 2) {
|
||||
for (String equip : fields[1].split(",")) {
|
||||
if (equip.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
statusList.runningEquipment.add(equip);
|
||||
}
|
||||
}
|
||||
return statusList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.dto.thermostat.summary;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ecobee.internal.dto.AbstractResponseDTO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link SummaryResponseDTO} contains the
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SummaryResponseDTO extends AbstractResponseDTO {
|
||||
|
||||
private final transient Logger logger = LoggerFactory.getLogger(SummaryResponseDTO.class);
|
||||
|
||||
/*
|
||||
* Number of thermostats listed in the Revision List.
|
||||
*/
|
||||
public @Nullable Integer thermostatCount;
|
||||
|
||||
/*
|
||||
* The list of CSV revision values.
|
||||
*/
|
||||
public @Nullable List<RevisionDTO> revisionList;
|
||||
|
||||
/*
|
||||
* The list of CSV status values.
|
||||
*/
|
||||
@SerializedName("statusList")
|
||||
public @Nullable List<RunningDTO> runningList;
|
||||
|
||||
public boolean hasChanged(@Nullable SummaryResponseDTO previousSummary) {
|
||||
if (previousSummary == null) {
|
||||
logger.debug("SummaryResponse: No previous summary");
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean changed = false;
|
||||
if (revisionHasChanged(previousSummary.revisionList)) {
|
||||
changed = true;
|
||||
}
|
||||
if (runningHasChanged(previousSummary.runningList)) {
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
private boolean revisionHasChanged(@Nullable List<RevisionDTO> previousList) {
|
||||
List<RevisionDTO> currentList = revisionList;
|
||||
if (previousList == null || currentList == null) {
|
||||
logger.debug("SummaryResponse: Previous and/or current revision list is null");
|
||||
return true;
|
||||
}
|
||||
// Check to see if there are different thermostat Ids in current vs previous
|
||||
Set<String> previousIds = previousList.stream().map(RevisionDTO::getId).collect(Collectors.toSet());
|
||||
Set<String> currentIds = currentList.stream().map(RevisionDTO::getId).collect(Collectors.toSet());
|
||||
if (!previousIds.equals(currentIds)) {
|
||||
logger.debug("SummaryResponse: Thermostat id maps are different");
|
||||
logger.trace(" : Curr: {}", Arrays.toString(currentIds.toArray()));
|
||||
logger.trace(" : Prev: {}", Arrays.toString(previousIds.toArray()));
|
||||
return true;
|
||||
}
|
||||
// Create a map of each thermostat id with its RevisionDTO object
|
||||
Map<String, RevisionDTO> previousMap = previousList.stream()
|
||||
.collect(Collectors.toMap(RevisionDTO::getId, RevisionDTO::getThis));
|
||||
// Go through list of current RevisionDTOs to see if something has changed
|
||||
for (RevisionDTO current : currentList) {
|
||||
RevisionDTO previous = previousMap.get(current.getId());
|
||||
if (current.hasChanged(previous)) {
|
||||
logger.debug("SummaryResponse: Revisions has changed");
|
||||
logger.trace(" : Curr: {}", current.toString());
|
||||
logger.trace(" : Prev: {}", previous.toString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean runningHasChanged(@Nullable List<RunningDTO> previousList) {
|
||||
List<RunningDTO> currentList = runningList;
|
||||
if (previousList == null || currentList == null) {
|
||||
logger.debug("SummaryResponse: Previous and/or current running list is null");
|
||||
return true;
|
||||
}
|
||||
// Check to see if there are different thermostat Ids in current vs previous
|
||||
Set<String> previousIds = previousList.stream().map(RunningDTO::getId).collect(Collectors.toSet());
|
||||
Set<String> currentIds = currentList.stream().map(RunningDTO::getId).collect(Collectors.toSet());
|
||||
if (!previousIds.equals(currentIds)) {
|
||||
logger.debug("SummaryResponse: Thermostat id maps are different");
|
||||
logger.trace(" : Curr: {}", Arrays.toString(currentIds.toArray()));
|
||||
logger.trace(" : Prev: {}", Arrays.toString(previousIds.toArray()));
|
||||
return true;
|
||||
}
|
||||
// Create a map of each thermostat id with its RunningDTO object
|
||||
Map<String, RunningDTO> previousMap = previousList.stream()
|
||||
.collect(Collectors.toMap(RunningDTO::getId, RunningDTO::getThis));
|
||||
// Go through list of current RunningDTOs to see if something has changed
|
||||
for (RunningDTO current : currentList) {
|
||||
RunningDTO previous = previousMap.get(current.getId());
|
||||
if (current.hasChanged(previous)) {
|
||||
logger.debug("SummaryResponse: Running Equipment has changed");
|
||||
logger.trace(" : Curr: {}", current.toString());
|
||||
logger.trace(" : Prev: {}", previous.toString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.enums;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link AckType} represents the types of alert acknowledgements.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum AckType {
|
||||
|
||||
@SerializedName("accept")
|
||||
ACCEPT("accept"),
|
||||
|
||||
@SerializedName("decline")
|
||||
DECLINE("decline"),
|
||||
|
||||
@SerializedName("defer")
|
||||
DEFER("defer"),
|
||||
|
||||
@SerializedName("unacknowledged")
|
||||
UNACKNOWLEDGED("unacknowledged");
|
||||
|
||||
private final String type;
|
||||
|
||||
private AckType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static AckType forValue(@Nullable String v) {
|
||||
if (v != null) {
|
||||
for (AckType at : AckType.values()) {
|
||||
if (at.type.equals(v)) {
|
||||
return at;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid or null ack type: " + v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.enums;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link EquipmentNotificationType} represents the types of equipment notifications.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum EquipmentNotificationType {
|
||||
|
||||
@SerializedName("hvac")
|
||||
HVAC("hvac"),
|
||||
|
||||
@SerializedName("furnaceFilter")
|
||||
FURNACE_FILTER("furnaceFilter"),
|
||||
|
||||
@SerializedName("humidifierFilter")
|
||||
HUMIDIFIER_FILTER("humidifierFilter"),
|
||||
|
||||
@SerializedName("dehumidifierFilter")
|
||||
DEHUNIDIFIER_FILTER("dehumidifierFilter"),
|
||||
|
||||
@SerializedName("ventilator")
|
||||
VENTILATOR("ventilator"),
|
||||
|
||||
@SerializedName("ac")
|
||||
AC("ac"),
|
||||
|
||||
@SerializedName("airFilter")
|
||||
AIR_FILTER("airFilter"),
|
||||
|
||||
@SerializedName("airCleaner")
|
||||
AIR_CLEANER("airCleaner"),
|
||||
|
||||
@SerializedName("uvLamp")
|
||||
UV_LAMP("uvLamp");
|
||||
|
||||
private final String mode;
|
||||
|
||||
private EquipmentNotificationType(String mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public static EquipmentNotificationType forValue(@Nullable String v) {
|
||||
if (v != null) {
|
||||
for (EquipmentNotificationType vm : EquipmentNotificationType.values()) {
|
||||
if (vm.mode.equals(v)) {
|
||||
return vm;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid vent: " + v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.mode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.enums;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link FanMode} represents the possible fan modes.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum FanMode {
|
||||
|
||||
@SerializedName("auto")
|
||||
AUTO("auto"),
|
||||
|
||||
@SerializedName("on")
|
||||
ON("on");
|
||||
|
||||
private final String mode;
|
||||
|
||||
private FanMode(final String mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public static FanMode forValue(String v) {
|
||||
for (FanMode fm : FanMode.values()) {
|
||||
if (fm.mode.equals(v)) {
|
||||
return fm;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid fan mode: " + v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.mode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.enums;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link HoldType} represents the possible hold types.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum HoldType {
|
||||
|
||||
/**
|
||||
* Use the provided startDate, startTime, endDate and endTime for the event.
|
||||
* If start date/time is not provided, it will be assumed to be right now.
|
||||
* End date/time is required.
|
||||
*/
|
||||
@SerializedName("dateTime")
|
||||
DATE_TIME("dateTime"),
|
||||
|
||||
/**
|
||||
* The end date/time will be set to the next climate transition in the program.
|
||||
*/
|
||||
@SerializedName("nextTransition")
|
||||
NEXT_TRANSITION("nextTransition"),
|
||||
|
||||
/**
|
||||
* The hold will not end and require to be cancelled explicitly.
|
||||
*/
|
||||
@SerializedName("indefinite")
|
||||
INDEFINITE("indefinite"),
|
||||
|
||||
/**
|
||||
* Use the value in the holdHours parameter to set the end date/time for the event.
|
||||
*/
|
||||
@SerializedName("holdHours")
|
||||
HOLD_HOURS("holdHours");
|
||||
|
||||
private final String type;
|
||||
|
||||
private HoldType(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static HoldType forValue(String v) {
|
||||
for (HoldType ht : HoldType.values()) {
|
||||
if (ht.type.equals(v)) {
|
||||
return ht;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid hold type: " + v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.enums;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link LimitNotificationType} represents the types of limit notifications.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum LimitNotificationType {
|
||||
|
||||
@SerializedName("lowTemp")
|
||||
LOW_TEMP("lowTemp"),
|
||||
|
||||
@SerializedName("highTemp")
|
||||
HIGH_TEMP("highTemp"),
|
||||
|
||||
@SerializedName("lowHumidity")
|
||||
LOW_HUMIDITY("lowHumidity"),
|
||||
|
||||
@SerializedName("highHumidity")
|
||||
HIGH_HUMIDITY("highHumidity"),
|
||||
|
||||
@SerializedName("auxHeat")
|
||||
AUX_HEAT("auxHeat"),
|
||||
|
||||
@SerializedName("auxOutdoor")
|
||||
AUX_OUTDOOR("auxOutdoor");
|
||||
|
||||
private final String mode;
|
||||
|
||||
private LimitNotificationType(String mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public static LimitNotificationType forValue(@Nullable String v) {
|
||||
if (v != null) {
|
||||
for (LimitNotificationType vm : LimitNotificationType.values()) {
|
||||
if (vm.mode.equals(v)) {
|
||||
return vm;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid vent: " + v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.mode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.enums;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link PlugState} defines the possible plug states.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum PlugState {
|
||||
|
||||
/**
|
||||
* Sets the plug into the on state for the start/end period specified.
|
||||
* Creates a plug hold in the on state.
|
||||
*/
|
||||
@SerializedName("on")
|
||||
ON("on"),
|
||||
|
||||
/**
|
||||
* Sets the plug into the off state for the start/end period specified.
|
||||
* Creates a plug hold in the off state.
|
||||
*/
|
||||
@SerializedName("off")
|
||||
OFF("off"),
|
||||
|
||||
/**
|
||||
* Causes the plug to resume its regular program and to follow it. Removes
|
||||
* the currently active plug hold, if no hold is currently running, nothing
|
||||
* happens. No other optional properties are used.
|
||||
*/
|
||||
@SerializedName("resume")
|
||||
RESUME("resume");
|
||||
|
||||
private final String state;
|
||||
|
||||
private PlugState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public static PlugState forValue(@Nullable String v) {
|
||||
if (v != null) {
|
||||
for (PlugState ps : PlugState.values()) {
|
||||
if (ps.state.equals(v)) {
|
||||
return ps;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid plug state: " + v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.state;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.enums;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link VentilatorMode} defines the possible ventilator modes.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum VentilatorMode {
|
||||
|
||||
@SerializedName("auto")
|
||||
AUTO("auto"),
|
||||
|
||||
@SerializedName("minontime")
|
||||
MIN_ON_TIME("minontime"),
|
||||
|
||||
@SerializedName("on")
|
||||
ON("on"),
|
||||
|
||||
@SerializedName("off")
|
||||
OFF("off");
|
||||
|
||||
private final String mode;
|
||||
|
||||
private VentilatorMode(String mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public static VentilatorMode forValue(@Nullable String v) {
|
||||
if (v != null) {
|
||||
for (VentilatorMode vm : VentilatorMode.values()) {
|
||||
if (vm.mode.equals(v)) {
|
||||
return vm;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid vent: " + v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.mode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
|
||||
/**
|
||||
* The {@link AbstractFunction} defines the base class used by all
|
||||
* thermostat functions.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class AbstractFunction {
|
||||
|
||||
@Expose(serialize = false)
|
||||
protected static final DateFormat YMD = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
@Expose(serialize = false)
|
||||
protected static final DateFormat HMS = new SimpleDateFormat("HH:mm:ss");
|
||||
|
||||
public String type;
|
||||
|
||||
public Map<String, Object> params;
|
||||
|
||||
public AbstractFunction(String type) {
|
||||
this.type = type;
|
||||
this.params = new HashMap<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ecobee.internal.enums.AckType;
|
||||
|
||||
/**
|
||||
* The acknowledge function allows an alert to be acknowledged.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class AcknowledgeFunction extends AbstractFunction {
|
||||
|
||||
public AcknowledgeFunction(@Nullable String thermostatIdentifier, @Nullable String ackRef,
|
||||
@Nullable AckType ackType, @Nullable Boolean remindMeLater) {
|
||||
super("acknowledge");
|
||||
|
||||
if (thermostatIdentifier == null || ackRef == null || ackType == null) {
|
||||
throw new IllegalArgumentException("thermostatIdentifier, ackRef and ackType are required.");
|
||||
}
|
||||
params.put("thermostatIdentifier", thermostatIdentifier);
|
||||
params.put("ackRef", ackRef);
|
||||
params.put("ackType", ackType);
|
||||
if (remindMeLater != null) {
|
||||
params.put("remindMeLater", remindMeLater);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ecobee.internal.enums.HoldType;
|
||||
import org.openhab.binding.ecobee.internal.enums.PlugState;
|
||||
|
||||
/**
|
||||
* Control the on/off state of a plug by setting a hold on the plug. Creates a hold for the on or off state of the plug
|
||||
* for the specified duration. Note that an event is created regardless of whether the program is in the same state as
|
||||
* the requested state.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class ControlPlugFunction extends AbstractFunction {
|
||||
|
||||
public ControlPlugFunction(@Nullable String plugName, @Nullable PlugState plugState, @Nullable Date startDateTime,
|
||||
@Nullable Date endDateTime, @Nullable HoldType holdType, @Nullable Integer holdHours) {
|
||||
super("controlPlug");
|
||||
|
||||
if (plugName == null || plugState == null) {
|
||||
throw new IllegalArgumentException("plugName and plugState arguments are required.");
|
||||
}
|
||||
if (holdType == HoldType.DATE_TIME && endDateTime == null) {
|
||||
throw new IllegalArgumentException("End date/time is required for dateTime hold type.");
|
||||
}
|
||||
if (holdType == HoldType.HOLD_HOURS && holdHours == null) {
|
||||
throw new IllegalArgumentException("holdHours must be specified when using holdHours hold type.");
|
||||
}
|
||||
params.put("plugName", plugName);
|
||||
params.put("plugState", plugState);
|
||||
if (startDateTime != null) {
|
||||
params.put("startDate", YMD.format(startDateTime));
|
||||
params.put("startTime", HMS.format(startDateTime));
|
||||
}
|
||||
if (endDateTime != null) {
|
||||
params.put("endDate", YMD.format(endDateTime));
|
||||
params.put("endTime", HMS.format(endDateTime));
|
||||
}
|
||||
if (holdType != null) {
|
||||
params.put("holdType", holdType);
|
||||
}
|
||||
if (holdHours != null) {
|
||||
params.put("holdHours", holdHours);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ecobee.internal.enums.FanMode;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
|
||||
/**
|
||||
* The create vacation function creates a vacation event on the thermostat. If the
|
||||
* start/end date/times are not provided for the vacation event, the vacation event
|
||||
* will begin immediately and last 14 days. If both the coolHoldTemp and heatHoldTemp
|
||||
* parameters provided to this function have the same value, and the Thermostat is
|
||||
* in auto mode, then the two values will be adjusted during processing to be
|
||||
* separated by the value stored in Thermostat.Settings#heatCoolMinDelta.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class CreateVacationFunction extends AbstractFunction {
|
||||
|
||||
public CreateVacationFunction(@Nullable String name, @Nullable QuantityType<Temperature> coolHoldTemp,
|
||||
@Nullable QuantityType<Temperature> heatHoldTemp, @Nullable Date startDateTime, @Nullable Date endDateTime,
|
||||
@Nullable FanMode fan, @Nullable Integer fanMinOnTime) {
|
||||
super("createVacation");
|
||||
|
||||
if (name == null || coolHoldTemp == null || heatHoldTemp == null) {
|
||||
throw new IllegalArgumentException("name, coolHoldTemp and heatHoldTemp arguments are required.");
|
||||
}
|
||||
params.put("name", name);
|
||||
|
||||
QuantityType<Temperature> convertedCoolHoldTemp = coolHoldTemp.toUnit(ImperialUnits.FAHRENHEIT);
|
||||
QuantityType<Temperature> convertedHeatHoldTemp = heatHoldTemp.toUnit(ImperialUnits.FAHRENHEIT);
|
||||
if (convertedCoolHoldTemp == null || convertedHeatHoldTemp == null) {
|
||||
throw new IllegalArgumentException("coolHoldTemp or heatHoldTemp are not proper QuantityTypes");
|
||||
}
|
||||
params.put("coolHoldTemp", Integer.valueOf(convertedCoolHoldTemp.intValue()));
|
||||
params.put("heatHoldTemp", Integer.valueOf(convertedHeatHoldTemp.intValue()));
|
||||
|
||||
if (startDateTime != null) {
|
||||
params.put("startDate", YMD.format(startDateTime));
|
||||
params.put("startTime", HMS.format(startDateTime));
|
||||
}
|
||||
if (endDateTime != null) {
|
||||
params.put("endDate", YMD.format(endDateTime));
|
||||
params.put("endTime", HMS.format(endDateTime));
|
||||
}
|
||||
if (fan != null) {
|
||||
params.put("fan", fan);
|
||||
}
|
||||
if (fanMinOnTime != null) {
|
||||
// doc says String not Integer for fanMinOnTime parameter (@watou)
|
||||
params.put("fanMinOnTime", fanMinOnTime.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The delete vacation function deletes a vacation event from a thermostat. This is the
|
||||
* only way to cancel a vacation event. This method is able to remove vacation
|
||||
* events not yet started and scheduled in the future.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class DeleteVacationFunction extends AbstractFunction {
|
||||
|
||||
public DeleteVacationFunction(@Nullable String name) {
|
||||
super("deleteVacation");
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("name argument is required.");
|
||||
}
|
||||
params.put("name", name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ecobee.internal.dto.SelectionDTO;
|
||||
|
||||
/**
|
||||
* The {@link FunctionRequest} encapsulates functions that are to be sent to the
|
||||
* Ecobee API.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FunctionRequest {
|
||||
|
||||
public FunctionRequest(SelectionDTO selection) {
|
||||
this.selection = selection;
|
||||
}
|
||||
|
||||
public SelectionDTO selection;
|
||||
|
||||
public @Nullable List<AbstractFunction> functions;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The reset preferences function sets all of the user configurable settings back to
|
||||
* the factory default values. This function call will not only reset the top level
|
||||
* thermostat settings such as hvacMode, lastServiceDate and vent, but also all of
|
||||
* the user configurable fields of the thermostat.settings and thermostat.program
|
||||
* objects. Note that this does not reset all values. For example, the installer
|
||||
* settings and wifi details remain untouched.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class ResetPreferencesFunction extends AbstractFunction {
|
||||
|
||||
public ResetPreferencesFunction() {
|
||||
super("resetPreferences");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The resume program function removes the currently running event providing the event
|
||||
* is not a mandatory demand response event. The top active event is removed from the
|
||||
* stack and the thermostat resumes its program, or enters the next event in the stack
|
||||
* if one exists. This function may need to be called multiple times in order to resume all
|
||||
* events. Sending 3 resume functions in a row will resume the thermostat to its program
|
||||
* in all instances. Note that vacation events cannot be resumed, you must delete the
|
||||
* vacation event using the DeleteVacationFunction.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class ResumeProgramFunction extends AbstractFunction {
|
||||
|
||||
public ResumeProgramFunction(@Nullable Boolean resumeAll) {
|
||||
super("resumeProgram");
|
||||
if (resumeAll != null) {
|
||||
params.put("resumeAll", resumeAll);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The send message function allows an alert message to be sent to the thermostat. The
|
||||
* message properties are same as those of the Alert object.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class SendMessageFunction extends AbstractFunction {
|
||||
|
||||
public SendMessageFunction(final @Nullable String text) {
|
||||
super("sendMessage");
|
||||
if (text == null) {
|
||||
throw new IllegalArgumentException("text is required.");
|
||||
}
|
||||
params.put("text", text);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.EventDTO;
|
||||
import org.openhab.binding.ecobee.internal.enums.HoldType;
|
||||
|
||||
/**
|
||||
* The set hold function sets the thermostat into a hold with the specified temperature.
|
||||
* Creates a hold for the specified duration. Note that an event is created regardless
|
||||
* of whether the program is in the same state as the requested state. There is also
|
||||
* support for creating a hold by passing a holdClimateRef request parameter/value pair
|
||||
* to this function (See Event). When an existing and valid Thermostat.Climate#climateRef
|
||||
* value is passed to this function, the coolHoldTemp, heatHoldTemp and fan mode from
|
||||
* that Thermostat.Climate are used in the creation of the hold event. The values from
|
||||
* that Climate will take precedence over any coolHoldTemp, heatHoldTemp, and fan
|
||||
* mode parameters passed into this function separately. To resume from a hold and
|
||||
* return to the program, use the ResumeProgramFunction.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class SetHoldFunction extends AbstractFunction {
|
||||
|
||||
public SetHoldFunction(@Nullable EventDTO event, @Nullable HoldType holdType, @Nullable Integer holdHours,
|
||||
@Nullable Date startDateTime, @Nullable Date endDateTime) {
|
||||
super("setHold");
|
||||
|
||||
if (event == null) {
|
||||
throw new IllegalArgumentException("event must not be null");
|
||||
}
|
||||
if (holdType == HoldType.HOLD_HOURS && holdHours == null) {
|
||||
throw new IllegalArgumentException("holdHours must be specified when holdType='holdHours'");
|
||||
} else if (holdType == HoldType.DATE_TIME && endDateTime == null) {
|
||||
throw new IllegalArgumentException("endDateTime must be specified when holdType='dateTime'");
|
||||
}
|
||||
if (event.holdClimateRef == null) {
|
||||
if (Boolean.TRUE.equals(event.isTemperatureAbsolute) && Boolean.TRUE.equals(event.isTemperatureRelative)) {
|
||||
throw new IllegalArgumentException("cannot set both absolute and relative temperatures");
|
||||
}
|
||||
if (Boolean.TRUE.equals(event.isTemperatureAbsolute)
|
||||
&& (event.coolHoldTemp == null || event.heatHoldTemp == null)) {
|
||||
throw new IllegalArgumentException(
|
||||
"coolHoldTemp and heatHoldTemp must be specified when 'isTemperatureAbsolute' is true");
|
||||
}
|
||||
if (Boolean.TRUE.equals(event.isTemperatureRelative)
|
||||
&& (event.coolRelativeTemp == null || event.heatRelativeTemp == null)) {
|
||||
throw new IllegalArgumentException(
|
||||
"coolRelativeTemp and heatRelativeTemp must be specified when 'isTemperatureRelative' is true");
|
||||
}
|
||||
}
|
||||
// Make parameters from the input event
|
||||
if (event.isOccupied != null) {
|
||||
params.put("isOccupied", event.isOccupied);
|
||||
}
|
||||
if (event.isCoolOff != null) {
|
||||
params.put("isCoolOff", event.isCoolOff);
|
||||
}
|
||||
if (event.isHeatOff != null) {
|
||||
params.put("isHeatOff", event.isHeatOff);
|
||||
}
|
||||
if (event.coolHoldTemp != null) {
|
||||
params.put("coolHoldTemp", event.coolHoldTemp);
|
||||
}
|
||||
if (event.heatHoldTemp != null) {
|
||||
params.put("heatHoldTemp", event.heatHoldTemp);
|
||||
}
|
||||
if (event.fan != null) {
|
||||
params.put("fan", event.fan);
|
||||
}
|
||||
if (event.vent != null) {
|
||||
params.put("vent", event.vent);
|
||||
}
|
||||
if (event.ventilatorMinOnTime != null) {
|
||||
params.put("ventilatorMinOnTime", event.ventilatorMinOnTime);
|
||||
}
|
||||
if (event.isOptional != null) {
|
||||
params.put("isOptional", event.isOptional);
|
||||
}
|
||||
if (event.isTemperatureRelative != null) {
|
||||
params.put("isTemperatureRelative", event.isTemperatureRelative);
|
||||
}
|
||||
if (event.coolRelativeTemp != null) {
|
||||
params.put("coolRelativeTemp", event.coolRelativeTemp);
|
||||
}
|
||||
if (event.heatRelativeTemp != null) {
|
||||
params.put("heatRelativeTemp", event.heatRelativeTemp);
|
||||
}
|
||||
if (event.isTemperatureAbsolute != null) {
|
||||
params.put("isTemperatureAbsolute", event.isTemperatureAbsolute);
|
||||
}
|
||||
if (event.fanMinOnTime != null) {
|
||||
params.put("fanMinOnTime", event.fanMinOnTime);
|
||||
}
|
||||
if (event.holdClimateRef != null) {
|
||||
params.put("holdClimateRef", event.holdClimateRef);
|
||||
}
|
||||
|
||||
// Make parameters from the holdType and hold options
|
||||
if (holdType != null) {
|
||||
params.put("holdType", holdType);
|
||||
}
|
||||
if (holdHours != null) {
|
||||
params.put("holdHours", holdHours);
|
||||
}
|
||||
if (startDateTime != null) {
|
||||
params.put("startDate", YMD.format(startDateTime));
|
||||
params.put("startTime", HMS.format(startDateTime));
|
||||
}
|
||||
if (endDateTime != null) {
|
||||
params.put("endDate", YMD.format(endDateTime));
|
||||
params.put("endTime", HMS.format(endDateTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ecobee.internal.enums.HoldType;
|
||||
|
||||
/**
|
||||
* The set occupied function may only be used by EMS thermostats. The function switches a
|
||||
* thermostat from occupied mode to unoccupied, or vice versa. If used on a Smart thermostat,
|
||||
* the function will throw an error. Switch occupancy events are treated as Holds.
|
||||
* There may only be one Switch Occupancy at one time, and the new event will replace any previous event.
|
||||
* Note that an occupancy event is created regardless what the program on the thermostat is set
|
||||
* to. For example, if the program is currently unoccupied and you set occupied=false, an
|
||||
* occupancy event will be created using the heat/cool settings of the unoccupied program
|
||||
* climate. If your intent is to go back to the program and remove the occupancy event,
|
||||
* use ResumeProgramFunction instead.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class SetOccupiedFunction extends AbstractFunction {
|
||||
|
||||
public SetOccupiedFunction(@Nullable Boolean occupied, @Nullable Date startDateTime, @Nullable Date endDateTime,
|
||||
@Nullable HoldType holdType, @Nullable Integer holdHours) {
|
||||
super("setOccupied"); // not in doc; assuming
|
||||
|
||||
if (occupied == null) {
|
||||
throw new IllegalArgumentException("occupied state is required.");
|
||||
}
|
||||
params.put("occupied", occupied);
|
||||
|
||||
if (startDateTime != null) {
|
||||
params.put("startDate", YMD.format(startDateTime));
|
||||
params.put("startTime", HMS.format(startDateTime));
|
||||
}
|
||||
if (endDateTime != null) {
|
||||
params.put("endDate", YMD.format(endDateTime));
|
||||
params.put("endTime", HMS.format(endDateTime));
|
||||
}
|
||||
|
||||
if (holdType == HoldType.HOLD_HOURS && holdHours == null) {
|
||||
throw new IllegalArgumentException("holdHours must be specified when holdType='holdHours'");
|
||||
}
|
||||
if (holdType == HoldType.DATE_TIME && endDateTime == null) {
|
||||
throw new IllegalArgumentException("endDateTime must be specific when holdType='dateTime'");
|
||||
}
|
||||
|
||||
if (holdType != null) {
|
||||
params.put("holdType", holdType);
|
||||
}
|
||||
if (holdHours != null) {
|
||||
params.put("holdHours", holdHours);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.function;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The update sensor function allows the caller to update the name of an ecobee3 remote sensor.
|
||||
* Each ecobee3 remote sensor "enclosure" contains two distinct sensors types temperature
|
||||
* and occupancy. Only one of the sensors is required in the request. Both of the sensors'
|
||||
* names will be updated to ensure consistency as they are part of the same remote sensor
|
||||
* enclosure. This also reflects accurately what happens on the Thermostat itself. Note: This
|
||||
* function is restricted to the ecobee3 thermostat model only.
|
||||
*
|
||||
* @author John Cocula - Initial contribution
|
||||
* @author Mark Hilbush - Adapt for OH2/3
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class UpdateSensorFunction extends AbstractFunction {
|
||||
|
||||
public UpdateSensorFunction(@Nullable final String name, @Nullable final String deviceId,
|
||||
@Nullable final String sensorId) {
|
||||
super("updateSensor");
|
||||
|
||||
if (name == null || deviceId == null || sensorId == null) {
|
||||
throw new IllegalArgumentException("name, deviceId and sensorId arguments are required.");
|
||||
}
|
||||
params.put("name", name);
|
||||
params.put("deviceId", deviceId);
|
||||
params.put("sensorId", sensorId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.handler;
|
||||
|
||||
import static org.openhab.binding.ecobee.internal.EcobeeBindingConstants.CONFIG_THERMOSTAT_ID;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.ecobee.internal.api.EcobeeApi;
|
||||
import org.openhab.binding.ecobee.internal.config.EcobeeAccountConfiguration;
|
||||
import org.openhab.binding.ecobee.internal.discovery.ThermostatDiscoveryService;
|
||||
import org.openhab.binding.ecobee.internal.dto.SelectionDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatUpdateRequestDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.summary.SummaryResponseDTO;
|
||||
import org.openhab.binding.ecobee.internal.function.FunctionRequest;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthFactory;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeAccountBridgeHandler} is responsible for managing
|
||||
* communication with the Ecobee API.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EcobeeAccountBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
private static final int REFRESH_STARTUP_DELAY_SECONDS = 3;
|
||||
private static final int REFRESH_INTERVAL_SECONDS = 1;
|
||||
private static final int DISCOVERY_INTERVAL_SECONDS = 300;
|
||||
private static final int DISCOVERY_INITIAL_DELAY_SECONDS = 10;
|
||||
private static final int DEFAULT_REFRESH_INTERVAL_NORMAL_SECONDS = 20;
|
||||
private static final int DEFAULT_REFRESH_INTERVAL_QUICK_SECONDS = 5;
|
||||
private static final int DEFAULT_API_TIMEOUT_SECONDS = 20;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EcobeeAccountBridgeHandler.class);
|
||||
|
||||
private final OAuthFactory oAuthFactory;
|
||||
private final HttpClient httpClient;
|
||||
|
||||
private @NonNullByDefault({}) EcobeeApi api;
|
||||
private @NonNullByDefault({}) String apiKey;
|
||||
private int refreshIntervalNormal;
|
||||
private int refreshIntervalQuick;
|
||||
private int apiTimeout;
|
||||
private boolean discoveryEnabled;
|
||||
private int discoveryInterval;
|
||||
|
||||
private final Map<String, EcobeeThermostatBridgeHandler> thermostatHandlers = new ConcurrentHashMap<>();
|
||||
private final Set<String> thermostatIds = new CopyOnWriteArraySet<>();
|
||||
|
||||
private @Nullable Future<?> refreshThermostatsJob;
|
||||
private final AtomicInteger refreshThermostatsCounter = new AtomicInteger(REFRESH_STARTUP_DELAY_SECONDS);
|
||||
private final AtomicInteger discoveryCounter = new AtomicInteger(DISCOVERY_INITIAL_DELAY_SECONDS);
|
||||
private @Nullable ThermostatDiscoveryService discoveryService;
|
||||
|
||||
private @Nullable SummaryResponseDTO previousSummary;
|
||||
|
||||
public EcobeeAccountBridgeHandler(final Bridge bridge, OAuthFactory oAuthFactory, HttpClient httpClient) {
|
||||
super(bridge);
|
||||
this.oAuthFactory = oAuthFactory;
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("AccountBridge: Initializing");
|
||||
|
||||
EcobeeAccountConfiguration config = getConfigAs(EcobeeAccountConfiguration.class);
|
||||
apiKey = config.apiKey;
|
||||
|
||||
Integer value;
|
||||
value = config.refreshIntervalNormal;
|
||||
refreshIntervalNormal = value == null ? DEFAULT_REFRESH_INTERVAL_NORMAL_SECONDS : value;
|
||||
|
||||
value = config.refreshIntervalQuick;
|
||||
refreshIntervalQuick = value == null ? DEFAULT_REFRESH_INTERVAL_QUICK_SECONDS : value;
|
||||
|
||||
value = config.apiTimeout;
|
||||
apiTimeout = (value == null ? DEFAULT_API_TIMEOUT_SECONDS : value) * 1000;
|
||||
|
||||
Boolean booleanValue = config.discoveryEnabled;
|
||||
discoveryEnabled = booleanValue == null ? false : booleanValue.booleanValue();
|
||||
logger.debug("AccountBridge: Thermostat and sensor discovery is {}", discoveryEnabled ? "enabled" : "disabled");
|
||||
|
||||
value = config.discoveryInterval;
|
||||
discoveryInterval = value == null ? DISCOVERY_INTERVAL_SECONDS : value;
|
||||
|
||||
api = new EcobeeApi(this, apiKey, apiTimeout, oAuthFactory, httpClient);
|
||||
|
||||
scheduleRefreshJob();
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING, "Checking authorization");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
cancelRefreshJob();
|
||||
api.closeOAuthClientService();
|
||||
logger.debug("AccountBridge: Disposing");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Collections.singleton(ThermostatDiscoveryService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerInitialized(ThingHandler thermostatHandler, Thing thermostatThing) {
|
||||
String thermostatId = (String) thermostatThing.getConfiguration().get(CONFIG_THERMOSTAT_ID);
|
||||
thermostatHandlers.put(thermostatId, (EcobeeThermostatBridgeHandler) thermostatHandler);
|
||||
thermostatIds.add(thermostatId);
|
||||
scheduleQuickPoll();
|
||||
logger.debug("AccountBridge: Adding thermostat handler for {} with id {}", thermostatThing.getUID(),
|
||||
thermostatId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerDisposed(ThingHandler thermostatHandler, Thing thermostatThing) {
|
||||
String thermostatId = (String) thermostatThing.getConfiguration().get(CONFIG_THERMOSTAT_ID);
|
||||
thermostatHandlers.remove(thermostatId);
|
||||
thermostatIds.remove(thermostatId);
|
||||
logger.debug("AccountBridge: Removing thermostat handler for {} with id {}", thermostatThing.getUID(),
|
||||
thermostatId);
|
||||
}
|
||||
|
||||
public void setDiscoveryService(ThermostatDiscoveryService discoveryService) {
|
||||
this.discoveryService = discoveryService;
|
||||
}
|
||||
|
||||
public boolean isDiscoveryEnabled() {
|
||||
return discoveryEnabled;
|
||||
}
|
||||
|
||||
public void updateBridgeStatus(ThingStatus status) {
|
||||
updateStatus(status);
|
||||
}
|
||||
|
||||
public void updateBridgeStatus(ThingStatus status, ThingStatusDetail statusDetail, String statusMessage) {
|
||||
updateStatus(status, statusDetail, statusMessage);
|
||||
}
|
||||
|
||||
public boolean performThermostatFunction(FunctionRequest request) {
|
||||
boolean success = api.performThermostatFunction(request);
|
||||
if (success) {
|
||||
scheduleQuickPoll();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public boolean performThermostatUpdate(ThermostatUpdateRequestDTO request) {
|
||||
boolean success = api.performThermostatUpdate(request);
|
||||
if (success) {
|
||||
scheduleQuickPoll();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public SelectionDTO getSelection() {
|
||||
SelectionDTO mergedSelection = new SelectionDTO();
|
||||
for (EcobeeThermostatBridgeHandler handler : new ArrayList<EcobeeThermostatBridgeHandler>(
|
||||
thermostatHandlers.values())) {
|
||||
SelectionDTO selection = handler.getSelection();
|
||||
logger.trace("AccountBridge: Thermostat {} selection: {}", handler.getThing().getUID(), selection);
|
||||
mergedSelection.mergeSelection(selection);
|
||||
}
|
||||
return mergedSelection;
|
||||
}
|
||||
|
||||
public void markOnline() {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
|
||||
public List<ThermostatDTO> getRegisteredThermostats() {
|
||||
return api.queryRegisteredThermostats();
|
||||
}
|
||||
|
||||
/*
|
||||
* The refresh job
|
||||
* - updates the thermostat channels on the refresh interval set in the thermostat thing config, and
|
||||
* - runs the thermostat discovery on the refresh interval set in the thing config
|
||||
*
|
||||
* The thermostat update process involves first running a thermostat summary transaction to
|
||||
* determine if any thermostat data has changed since the last summary. If any change is detected,
|
||||
* a full query of the thermostats is performed.
|
||||
*/
|
||||
private void refresh() {
|
||||
refreshThermostats();
|
||||
discoverThermostats();
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
private void refreshThermostats() {
|
||||
if (refreshThermostatsCounter.getAndDecrement() == 0) {
|
||||
refreshThermostatsCounter.set(refreshIntervalNormal);
|
||||
SummaryResponseDTO summary = api.performThermostatSummaryQuery();
|
||||
if (summary != null && summary.hasChanged(previousSummary) && !thermostatIds.isEmpty()) {
|
||||
for (ThermostatDTO thermostat : api.performThermostatQuery(thermostatIds)) {
|
||||
EcobeeThermostatBridgeHandler handler = thermostatHandlers.get(thermostat.identifier);
|
||||
if (handler != null) {
|
||||
handler.updateChannels(thermostat);
|
||||
}
|
||||
}
|
||||
}
|
||||
previousSummary = summary;
|
||||
}
|
||||
}
|
||||
|
||||
private void discoverThermostats() {
|
||||
if (isDiscoveryEnabled()) {
|
||||
if (discoveryCounter.getAndDecrement() == 0) {
|
||||
discoveryCounter.set(discoveryInterval);
|
||||
ThermostatDiscoveryService localDiscoveryService = discoveryService;
|
||||
if (localDiscoveryService != null) {
|
||||
logger.debug("AccountBridge: Running thermostat discovery");
|
||||
localDiscoveryService.startBackgroundDiscovery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleQuickPoll() {
|
||||
if (refreshThermostatsCounter.get() > refreshIntervalQuick) {
|
||||
logger.debug("AccountBridge: Scheduling quick poll");
|
||||
refreshThermostatsCounter.set(refreshIntervalQuick);
|
||||
forceFullNextPoll();
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleRefreshJob() {
|
||||
logger.debug("AccountBridge: Scheduling thermostat refresh job");
|
||||
cancelRefreshJob();
|
||||
refreshThermostatsCounter.set(0);
|
||||
refreshThermostatsJob = scheduler.scheduleWithFixedDelay(this::refresh, REFRESH_STARTUP_DELAY_SECONDS,
|
||||
REFRESH_INTERVAL_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void cancelRefreshJob() {
|
||||
Future<?> localRefreshThermostatsJob = refreshThermostatsJob;
|
||||
if (localRefreshThermostatsJob != null) {
|
||||
forceFullNextPoll();
|
||||
localRefreshThermostatsJob.cancel(true);
|
||||
logger.debug("AccountBridge: Canceling thermostat refresh job");
|
||||
}
|
||||
}
|
||||
|
||||
private void forceFullNextPoll() {
|
||||
previousSummary = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.handler;
|
||||
|
||||
import static org.openhab.binding.ecobee.internal.EcobeeBindingConstants.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.ecobee.internal.config.EcobeeSensorConfiguration;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.RemoteSensorCapabilityDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.RemoteSensorDTO;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeSensorThingHandler} is responsible for updating the channels associated
|
||||
* with an Ecobee remote sensor.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EcobeeSensorThingHandler extends BaseThingHandler {
|
||||
|
||||
public static final String CAPABILITY_ADC = "adc";
|
||||
public static final String CAPABILITY_CO2 = "co2";
|
||||
public static final String CAPABILITY_DRY_CONTACT = "dryContact";
|
||||
public static final String CAPABILITY_HUMIDITY = "humidity";
|
||||
public static final String CAPABILITY_OCCUPANCY = "occupancy";
|
||||
public static final String CAPABILITY_TEMPERATURE = "temperature";
|
||||
public static final String CAPABILITY_UNKNOWN = "unknown";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EcobeeSensorThingHandler.class);
|
||||
|
||||
private @NonNullByDefault({}) String sensorId;
|
||||
|
||||
private Map<String, State> stateCache = new ConcurrentHashMap<>();
|
||||
|
||||
public EcobeeSensorThingHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
sensorId = getConfigAs(EcobeeSensorConfiguration.class).sensorId;
|
||||
logger.debug("SensorThing: Initializing sensor '{}'", sensorId);
|
||||
clearSavedState();
|
||||
updateStatus(EcobeeUtils.isBridgeOnline(getBridge()) ? ThingStatus.ONLINE : ThingStatus.OFFLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("SensorThing: Disposing sensor '{}'", sensorId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
State state = stateCache.get(channelUID.getId());
|
||||
if (state != null) {
|
||||
updateState(channelUID.getId(), state);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateChannels(RemoteSensorDTO sensor) {
|
||||
logger.debug("SensorThing: Updating channels for sensor '{}({})'", sensor.id, sensor.name);
|
||||
updateChannel(CH_SENSOR_ID, EcobeeUtils.undefOrString(sensor.id));
|
||||
updateChannel(CH_SENSOR_NAME, EcobeeUtils.undefOrString(sensor.name));
|
||||
updateChannel(CH_SENSOR_TYPE, EcobeeUtils.undefOrString(sensor.type));
|
||||
updateChannel(CH_SENSOR_CODE, EcobeeUtils.undefOrString(sensor.code));
|
||||
updateChannel(CH_SENSOR_IN_USE, EcobeeUtils.undefOrOnOff(sensor.inUse));
|
||||
for (RemoteSensorCapabilityDTO capability : sensor.capability) {
|
||||
updateCapabilityChannels(capability);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCapabilityChannels(RemoteSensorCapabilityDTO capability) {
|
||||
ChannelUID uid = new ChannelUID(thing.getUID(), capability.type);
|
||||
Channel channel = thing.getChannel(uid);
|
||||
if (channel == null) {
|
||||
logger.debug("SensorThing: Create channel '{}'", uid);
|
||||
ThingBuilder thingBuilder;
|
||||
thingBuilder = editThing();
|
||||
channel = ChannelBuilder.create(uid, getAcceptedItemType(capability.type))
|
||||
.withLabel("Sensor " + WordUtils.capitalize(capability.type))
|
||||
.withType(getChannelTypeUID(capability.type)).build();
|
||||
thingBuilder.withChannel(channel);
|
||||
updateThing(thingBuilder.build());
|
||||
}
|
||||
logger.trace("Capability '{}' has type '{}' with value '{}'", capability.id, capability.type, capability.value);
|
||||
updateCapabilityState(capability.type, capability.value);
|
||||
}
|
||||
|
||||
// adc, co2, dryContact, humidity, temperature, occupancy, unknown.
|
||||
private String getAcceptedItemType(String capabilityType) {
|
||||
String acceptedItemType;
|
||||
switch (capabilityType) {
|
||||
case CAPABILITY_TEMPERATURE:
|
||||
acceptedItemType = "Number:Temperature";
|
||||
break;
|
||||
case CAPABILITY_HUMIDITY:
|
||||
acceptedItemType = "Number:Dimensionless";
|
||||
break;
|
||||
case CAPABILITY_OCCUPANCY:
|
||||
acceptedItemType = "Switch";
|
||||
break;
|
||||
case CAPABILITY_ADC:
|
||||
case CAPABILITY_CO2:
|
||||
case CAPABILITY_DRY_CONTACT:
|
||||
case CAPABILITY_UNKNOWN:
|
||||
default:
|
||||
acceptedItemType = "String";
|
||||
break;
|
||||
}
|
||||
return acceptedItemType;
|
||||
}
|
||||
|
||||
private ChannelTypeUID getChannelTypeUID(String capabilityType) {
|
||||
ChannelTypeUID channelTypeUID;
|
||||
switch (capabilityType) {
|
||||
case CAPABILITY_TEMPERATURE:
|
||||
channelTypeUID = CHANNELTYPEUID_TEMPERATURE;
|
||||
break;
|
||||
case CAPABILITY_HUMIDITY:
|
||||
channelTypeUID = CHANNELTYPEUID_HUMIDITY;
|
||||
break;
|
||||
case CAPABILITY_OCCUPANCY:
|
||||
channelTypeUID = CHANNELTYPEUID_OCCUPANCY;
|
||||
break;
|
||||
case CAPABILITY_ADC:
|
||||
case CAPABILITY_CO2:
|
||||
case CAPABILITY_DRY_CONTACT:
|
||||
case CAPABILITY_UNKNOWN:
|
||||
default:
|
||||
channelTypeUID = CHANNELTYPEUID_GENERIC;
|
||||
break;
|
||||
}
|
||||
return channelTypeUID;
|
||||
}
|
||||
|
||||
private void updateCapabilityState(String capabilityType, String value) {
|
||||
State state;
|
||||
switch (capabilityType) {
|
||||
case CAPABILITY_TEMPERATURE:
|
||||
try {
|
||||
state = EcobeeUtils.undefOrTemperature(Integer.parseInt(value));
|
||||
} catch (NumberFormatException e) {
|
||||
state = UnDefType.UNDEF;
|
||||
}
|
||||
break;
|
||||
case CAPABILITY_HUMIDITY:
|
||||
try {
|
||||
state = EcobeeUtils.undefOrQuantity(Integer.parseInt(value), SmartHomeUnits.PERCENT);
|
||||
} catch (NumberFormatException e) {
|
||||
state = UnDefType.UNDEF;
|
||||
}
|
||||
break;
|
||||
case CAPABILITY_OCCUPANCY:
|
||||
state = EcobeeUtils.undefOrOnOff("true".equals(value));
|
||||
break;
|
||||
case CAPABILITY_ADC:
|
||||
case CAPABILITY_CO2:
|
||||
case CAPABILITY_DRY_CONTACT:
|
||||
case CAPABILITY_UNKNOWN:
|
||||
default:
|
||||
state = EcobeeUtils.undefOrString(value);
|
||||
break;
|
||||
}
|
||||
updateChannel(capabilityType, state);
|
||||
}
|
||||
|
||||
private void updateChannel(String channelId, State state) {
|
||||
updateState(channelId, state);
|
||||
stateCache.put(channelId, state);
|
||||
}
|
||||
|
||||
private void clearSavedState() {
|
||||
stateCache.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,957 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.handler;
|
||||
|
||||
import static org.openhab.binding.ecobee.internal.EcobeeBindingConstants.*;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ecobee.action.EcobeeActions;
|
||||
import org.openhab.binding.ecobee.internal.api.EcobeeApi;
|
||||
import org.openhab.binding.ecobee.internal.config.EcobeeThermostatConfiguration;
|
||||
import org.openhab.binding.ecobee.internal.discovery.SensorDiscoveryService;
|
||||
import org.openhab.binding.ecobee.internal.dto.SelectionDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.AlertDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ClimateDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.EventDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.HouseDetailsDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.LocationDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ManagementDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ProgramDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.RemoteSensorDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.RuntimeDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.SettingsDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.TechnicianDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatUpdateRequestDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.VersionDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.WeatherDTO;
|
||||
import org.openhab.binding.ecobee.internal.dto.thermostat.WeatherForecastDTO;
|
||||
import org.openhab.binding.ecobee.internal.function.AbstractFunction;
|
||||
import org.openhab.binding.ecobee.internal.function.FunctionRequest;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.thing.type.ChannelType;
|
||||
import org.openhab.core.thing.type.ChannelTypeRegistry;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeThermostatBridgeHandler} is the handler for an Ecobee thermostat.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EcobeeThermostatBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
private static final int SENSOR_DISCOVERY_STARTUP_DELAY_SECONDS = 30;
|
||||
private static final int SENSOR_DISCOVERY_INTERVAL_SECONDS = 300;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EcobeeThermostatBridgeHandler.class);
|
||||
|
||||
private TimeZoneProvider timeZoneProvider;
|
||||
private ChannelTypeRegistry channelTypeRegistry;
|
||||
|
||||
private @NonNullByDefault({}) String thermostatId;
|
||||
|
||||
private final Map<String, EcobeeSensorThingHandler> sensorHandlers = new ConcurrentHashMap<>();
|
||||
|
||||
private @Nullable Future<?> discoverSensorsJob;
|
||||
private @Nullable SensorDiscoveryService discoveryService;
|
||||
|
||||
private @Nullable ThermostatDTO savedThermostat;
|
||||
private @Nullable List<RemoteSensorDTO> savedSensors;
|
||||
private List<String> validClimateRefs = new CopyOnWriteArrayList<>();
|
||||
private Map<String, State> stateCache = new ConcurrentHashMap<>();
|
||||
private Map<ChannelUID, Boolean> channelReadOnlyMap = new HashMap<>();
|
||||
private Map<Integer, String> symbolMap = new HashMap<>();
|
||||
private Map<Integer, String> skyMap = new HashMap<>();
|
||||
|
||||
public EcobeeThermostatBridgeHandler(Bridge bridge, TimeZoneProvider timeZoneProvider,
|
||||
ChannelTypeRegistry channelTypeRegistry) {
|
||||
super(bridge);
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
this.channelTypeRegistry = channelTypeRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
thermostatId = getConfigAs(EcobeeThermostatConfiguration.class).thermostatId;
|
||||
logger.debug("ThermostatBridge: Initializing thermostat '{}'", thermostatId);
|
||||
initializeWeatherMaps();
|
||||
initializeReadOnlyChannels();
|
||||
clearSavedState();
|
||||
scheduleDiscoveryJob();
|
||||
updateStatus(EcobeeUtils.isBridgeOnline(getBridge()) ? ThingStatus.ONLINE : ThingStatus.OFFLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
cancelDiscoveryJob();
|
||||
logger.debug("ThermostatBridge: Disposing thermostat '{}'", thermostatId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerInitialized(ThingHandler sensorHandler, Thing sensorThing) {
|
||||
String sensorId = (String) sensorThing.getConfiguration().get(CONFIG_SENSOR_ID);
|
||||
sensorHandlers.put(sensorId, (EcobeeSensorThingHandler) sensorHandler);
|
||||
logger.debug("ThermostatBridge: Saving sensor handler for {} with id {}", sensorThing.getUID(), sensorId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerDisposed(ThingHandler sensorHandler, Thing sensorThing) {
|
||||
String sensorId = (String) sensorThing.getConfiguration().get(CONFIG_SENSOR_ID);
|
||||
sensorHandlers.remove(sensorId);
|
||||
logger.debug("ThermostatBridge: Removing sensor handler for {} with id {}", sensorThing.getUID(), sensorId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
State state = stateCache.get(channelUID.getId());
|
||||
if (state != null) {
|
||||
updateState(channelUID.getId(), state);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (isChannelReadOnly(channelUID)) {
|
||||
logger.debug("Can't apply command '{}' to '{}' because channel is readonly", command, channelUID.getId());
|
||||
return;
|
||||
}
|
||||
scheduler.execute(() -> {
|
||||
handleThermostatCommand(channelUID, command);
|
||||
});
|
||||
}
|
||||
|
||||
public void setDiscoveryService(SensorDiscoveryService discoveryService) {
|
||||
this.discoveryService = discoveryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the AccountBridgeHandler to create a Selection that
|
||||
* includes only the Ecobee objects for which there's at least one
|
||||
* item linked to one of that object's channels.
|
||||
*
|
||||
* @return Selection
|
||||
*/
|
||||
public SelectionDTO getSelection() {
|
||||
final SelectionDTO selection = new SelectionDTO();
|
||||
for (String group : CHANNEL_GROUPS) {
|
||||
for (Channel channel : thing.getChannelsOfGroup(group)) {
|
||||
if (isLinked(channel.getUID())) {
|
||||
try {
|
||||
Field field = selection.getClass().getField("include" + WordUtils.capitalize(group));
|
||||
logger.trace("ThermostatBridge: Thermostat thing '{}' including object '{}' in selection",
|
||||
thing.getUID(), field.getName());
|
||||
field.set(selection, Boolean.TRUE);
|
||||
break;
|
||||
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException
|
||||
| SecurityException e) {
|
||||
logger.debug("ThermostatBridge: Exception setting selection for group '{}'", group, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
|
||||
public List<RemoteSensorDTO> getSensors() {
|
||||
List<RemoteSensorDTO> localSavedSensors = savedSensors;
|
||||
return localSavedSensors == null ? EMPTY_SENSORS : localSavedSensors;
|
||||
}
|
||||
|
||||
public @Nullable String getAlerts() {
|
||||
ThermostatDTO thermostat = savedThermostat;
|
||||
if (thermostat != null && thermostat.alerts != null) {
|
||||
return EcobeeApi.getGson().toJson(thermostat.alerts);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public @Nullable String getEvents() {
|
||||
ThermostatDTO thermostat = savedThermostat;
|
||||
if (thermostat != null && thermostat.events != null) {
|
||||
return EcobeeApi.getGson().toJson(thermostat.events);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public @Nullable String getClimates() {
|
||||
ThermostatDTO thermostat = savedThermostat;
|
||||
if (thermostat != null && thermostat.program != null && thermostat.program.climates != null) {
|
||||
return EcobeeApi.getGson().toJson(thermostat.program.climates);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isValidClimateRef(String climateRef) {
|
||||
return validClimateRefs.contains(climateRef);
|
||||
}
|
||||
|
||||
public String getThermostatId() {
|
||||
return thermostatId;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by EcobeeActions to perform a thermostat function
|
||||
*/
|
||||
public boolean actionPerformFunction(AbstractFunction function) {
|
||||
logger.debug("ThermostatBridge: Perform function '{}' on thermostat {}", function.type, thermostatId);
|
||||
SelectionDTO selection = new SelectionDTO();
|
||||
selection.setThermostats(Collections.singleton(thermostatId));
|
||||
FunctionRequest request = new FunctionRequest(selection);
|
||||
request.functions = Collections.singletonList(function);
|
||||
EcobeeAccountBridgeHandler handler = getBridgeHandler();
|
||||
if (handler != null) {
|
||||
return handler.performThermostatFunction(request);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Collections.unmodifiableList(
|
||||
Stream.of(EcobeeActions.class, SensorDiscoveryService.class).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public void updateChannels(ThermostatDTO thermostat) {
|
||||
logger.debug("ThermostatBridge: Updating channels for thermostat id {}", thermostat.identifier);
|
||||
savedThermostat = thermostat;
|
||||
updateAlert(thermostat.alerts);
|
||||
updateHouseDetails(thermostat.houseDetails);
|
||||
updateInfo(thermostat);
|
||||
updateEquipmentStatus(thermostat);
|
||||
updateLocation(thermostat.location);
|
||||
updateManagement(thermostat.management);
|
||||
updateProgram(thermostat.program);
|
||||
updateEvent(thermostat.events);
|
||||
updateRemoteSensors(thermostat.remoteSensors);
|
||||
updateRuntime(thermostat.runtime);
|
||||
updateSettings(thermostat.settings);
|
||||
updateTechnician(thermostat.technician);
|
||||
updateVersion(thermostat.version);
|
||||
updateWeather(thermostat.weather);
|
||||
savedSensors = thermostat.remoteSensors;
|
||||
}
|
||||
|
||||
private void handleThermostatCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("Got command '{}' for channel '{}' of thing '{}'", command, channelUID, getThing().getUID());
|
||||
String channelId = channelUID.getIdWithoutGroup();
|
||||
String groupId = channelUID.getGroupId();
|
||||
if (groupId == null) {
|
||||
logger.info("Can't handle command because channel's groupId is null");
|
||||
return;
|
||||
}
|
||||
ThermostatDTO thermostat = new ThermostatDTO();
|
||||
Field field;
|
||||
try {
|
||||
switch (groupId) {
|
||||
case CHGRP_INFO:
|
||||
field = thermostat.getClass().getField(channelId);
|
||||
setField(field, thermostat, command);
|
||||
break;
|
||||
case CHGRP_SETTINGS:
|
||||
SettingsDTO settings = new SettingsDTO();
|
||||
field = settings.getClass().getField(channelId);
|
||||
setField(field, settings, command);
|
||||
thermostat.settings = settings;
|
||||
break;
|
||||
case CHGRP_LOCATION:
|
||||
LocationDTO location = new LocationDTO();
|
||||
field = location.getClass().getField(channelId);
|
||||
setField(field, location, command);
|
||||
thermostat.location = location;
|
||||
break;
|
||||
case CHGRP_HOUSE_DETAILS:
|
||||
HouseDetailsDTO houseDetails = new HouseDetailsDTO();
|
||||
field = houseDetails.getClass().getField(channelId);
|
||||
setField(field, houseDetails, command);
|
||||
thermostat.houseDetails = houseDetails;
|
||||
break;
|
||||
default:
|
||||
// All other groups contain only read-only fields
|
||||
return;
|
||||
}
|
||||
performThermostatUpdate(thermostat);
|
||||
} catch (NoSuchFieldException | SecurityException e) {
|
||||
logger.info("Unable to get field for '{}.{}'", groupId, channelId);
|
||||
}
|
||||
}
|
||||
|
||||
private void setField(Field field, Object object, Command command) {
|
||||
logger.info("Setting field '{}.{}' to value '{}'", object.getClass().getSimpleName().toLowerCase(),
|
||||
field.getName(), command);
|
||||
Class<?> fieldClass = field.getType();
|
||||
try {
|
||||
boolean success = false;
|
||||
if (String.class.isAssignableFrom(fieldClass)) {
|
||||
if (command instanceof StringType) {
|
||||
logger.debug("Set field of type String to value of StringType");
|
||||
field.set(object, command.toString());
|
||||
success = true;
|
||||
}
|
||||
} else if (Integer.class.isAssignableFrom(fieldClass)) {
|
||||
if (command instanceof DecimalType) {
|
||||
logger.debug("Set field of type Integer to value of DecimalType");
|
||||
field.set(object, Integer.valueOf(((DecimalType) command).intValue()));
|
||||
success = true;
|
||||
} else if (command instanceof QuantityType) {
|
||||
Unit<?> unit = ((QuantityType<?>) command).getUnit();
|
||||
logger.debug("Set field of type Integer to value of QuantityType with unit {}", unit);
|
||||
if (unit.equals(ImperialUnits.FAHRENHEIT) || unit.equals(SIUnits.CELSIUS)) {
|
||||
QuantityType<?> quantity = ((QuantityType<?>) command).toUnit(ImperialUnits.FAHRENHEIT);
|
||||
if (quantity != null) {
|
||||
field.set(object, quantity.intValue() * 10);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (Boolean.class.isAssignableFrom(fieldClass)) {
|
||||
if (command instanceof OnOffType) {
|
||||
logger.debug("Set field of type Boolean to value of OnOffType");
|
||||
field.set(object, command == OnOffType.ON);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
logger.info("Don't know how to convert command of type '{}' to {}.{}",
|
||||
command.getClass().getSimpleName(), object.getClass().getSimpleName(), field.getName());
|
||||
}
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
logger.info("Unable to set field '{}.{}' to value '{}'", object.getClass().getSimpleName(), field.getName(),
|
||||
command, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateInfo(ThermostatDTO thermostat) {
|
||||
final String grp = CHGRP_INFO + "#";
|
||||
updateChannel(grp + CH_IDENTIFIER, EcobeeUtils.undefOrString(thermostat.identifier));
|
||||
updateChannel(grp + CH_NAME, EcobeeUtils.undefOrString(thermostat.name));
|
||||
updateChannel(grp + CH_THERMOSTAT_REV, EcobeeUtils.undefOrString(thermostat.thermostatRev));
|
||||
updateChannel(grp + CH_IS_REGISTERED, EcobeeUtils.undefOrOnOff(thermostat.isRegistered));
|
||||
updateChannel(grp + CH_MODEL_NUMBER, EcobeeUtils.undefOrString(thermostat.modelNumber));
|
||||
updateChannel(grp + CH_BRAND, EcobeeUtils.undefOrString(thermostat.brand));
|
||||
updateChannel(grp + CH_FEATURES, EcobeeUtils.undefOrString(thermostat.features));
|
||||
updateChannel(grp + CH_LAST_MODIFIED, EcobeeUtils.undefOrDate(thermostat.lastModified, timeZoneProvider));
|
||||
updateChannel(grp + CH_THERMOSTAT_TIME, EcobeeUtils.undefOrDate(thermostat.thermostatTime, timeZoneProvider));
|
||||
}
|
||||
|
||||
private void updateEquipmentStatus(ThermostatDTO thermostat) {
|
||||
final String grp = CHGRP_EQUIPMENT_STATUS + "#";
|
||||
updateChannel(grp + CH_EQUIPMENT_STATUS, EcobeeUtils.undefOrString(thermostat.equipmentStatus));
|
||||
}
|
||||
|
||||
private void updateRuntime(@Nullable RuntimeDTO runtime) {
|
||||
if (runtime == null) {
|
||||
return;
|
||||
}
|
||||
final String grp = CHGRP_RUNTIME + "#";
|
||||
updateChannel(grp + CH_RUNTIME_REV, EcobeeUtils.undefOrString(runtime.runtimeRev));
|
||||
updateChannel(grp + CH_CONNECTED, EcobeeUtils.undefOrOnOff(runtime.connected));
|
||||
updateChannel(grp + CH_FIRST_CONNECTED, EcobeeUtils.undefOrDate(runtime.firstConnected, timeZoneProvider));
|
||||
updateChannel(grp + CH_CONNECT_DATE_TIME, EcobeeUtils.undefOrDate(runtime.connectDateTime, timeZoneProvider));
|
||||
updateChannel(grp + CH_DISCONNECT_DATE_TIME,
|
||||
EcobeeUtils.undefOrDate(runtime.disconnectDateTime, timeZoneProvider));
|
||||
updateChannel(grp + CH_RT_LAST_MODIFIED, EcobeeUtils.undefOrDate(runtime.lastModified, timeZoneProvider));
|
||||
updateChannel(grp + CH_RT_LAST_STATUS_MODIFIED,
|
||||
EcobeeUtils.undefOrDate(runtime.lastStatusModified, timeZoneProvider));
|
||||
updateChannel(grp + CH_RUNTIME_DATE, EcobeeUtils.undefOrString(runtime.runtimeDate));
|
||||
updateChannel(grp + CH_RUNTIME_INTERVAL, EcobeeUtils.undefOrDecimal(runtime.runtimeInterval));
|
||||
updateChannel(grp + CH_ACTUAL_TEMPERATURE, EcobeeUtils.undefOrTemperature(runtime.actualTemperature));
|
||||
updateChannel(grp + CH_ACTUAL_HUMIDITY,
|
||||
EcobeeUtils.undefOrQuantity(runtime.actualHumidity, SmartHomeUnits.PERCENT));
|
||||
updateChannel(grp + CH_RAW_TEMPERATURE, EcobeeUtils.undefOrTemperature(runtime.rawTemperature));
|
||||
updateChannel(grp + CH_SHOW_ICON_MODE, EcobeeUtils.undefOrDecimal(runtime.showIconMode));
|
||||
updateChannel(grp + CH_DESIRED_HEAT, EcobeeUtils.undefOrTemperature(runtime.desiredHeat));
|
||||
updateChannel(grp + CH_DESIRED_COOL, EcobeeUtils.undefOrTemperature(runtime.desiredCool));
|
||||
updateChannel(grp + CH_DESIRED_HUMIDITY,
|
||||
EcobeeUtils.undefOrQuantity(runtime.desiredHumidity, SmartHomeUnits.PERCENT));
|
||||
updateChannel(grp + CH_DESIRED_DEHUMIDITY,
|
||||
EcobeeUtils.undefOrQuantity(runtime.desiredDehumidity, SmartHomeUnits.PERCENT));
|
||||
updateChannel(grp + CH_DESIRED_FAN_MODE, EcobeeUtils.undefOrString(runtime.desiredFanMode));
|
||||
if (runtime.desiredHeatRange != null && runtime.desiredHeatRange.size() == 2) {
|
||||
updateChannel(grp + CH_DESIRED_HEAT_RANGE_LOW,
|
||||
EcobeeUtils.undefOrTemperature(runtime.desiredHeatRange.get(0)));
|
||||
updateChannel(grp + CH_DESIRED_HEAT_RANGE_HIGH,
|
||||
EcobeeUtils.undefOrTemperature(runtime.desiredHeatRange.get(1)));
|
||||
}
|
||||
if (runtime.desiredCoolRange != null && runtime.desiredCoolRange.size() == 2) {
|
||||
updateChannel(grp + CH_DESIRED_COOL_RANGE_LOW,
|
||||
EcobeeUtils.undefOrTemperature(runtime.desiredCoolRange.get(0)));
|
||||
updateChannel(grp + CH_DESIRED_COOL_RANGE_HIGH,
|
||||
EcobeeUtils.undefOrTemperature(runtime.desiredCoolRange.get(1)));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSettings(@Nullable SettingsDTO settings) {
|
||||
if (settings == null) {
|
||||
return;
|
||||
}
|
||||
final String grp = CHGRP_SETTINGS + "#";
|
||||
updateChannel(grp + CH_HVAC_MODE, EcobeeUtils.undefOrString(settings.hvacMode));
|
||||
updateChannel(grp + CH_LAST_SERVICE_DATE, EcobeeUtils.undefOrString(settings.lastServiceDate));
|
||||
updateChannel(grp + CH_SERVICE_REMIND_ME, EcobeeUtils.undefOrOnOff(settings.serviceRemindMe));
|
||||
updateChannel(grp + CH_MONTHS_BETWEEN_SERVICE, EcobeeUtils.undefOrDecimal(settings.monthsBetweenService));
|
||||
updateChannel(grp + CH_REMIND_ME_DATE, EcobeeUtils.undefOrString(settings.remindMeDate));
|
||||
updateChannel(grp + CH_VENT, EcobeeUtils.undefOrString(settings.vent));
|
||||
updateChannel(grp + CH_VENTILATOR_MIN_ON_TIME, EcobeeUtils.undefOrDecimal(settings.ventilatorMinOnTime));
|
||||
updateChannel(grp + CH_SERVICE_REMIND_TECHNICIAN, EcobeeUtils.undefOrOnOff(settings.serviceRemindTechnician));
|
||||
updateChannel(grp + CH_EI_LOCATION, EcobeeUtils.undefOrString(settings.eiLocation));
|
||||
updateChannel(grp + CH_COLD_TEMP_ALERT, EcobeeUtils.undefOrTemperature(settings.coldTempAlert));
|
||||
updateChannel(grp + CH_COLD_TEMP_ALERT_ENABLED, EcobeeUtils.undefOrOnOff(settings.coldTempAlertEnabled));
|
||||
updateChannel(grp + CH_HOT_TEMP_ALERT, EcobeeUtils.undefOrTemperature(settings.hotTempAlert));
|
||||
updateChannel(grp + CH_HOT_TEMP_ALERT_ENABLED, EcobeeUtils.undefOrOnOff(settings.hotTempAlertEnabled));
|
||||
updateChannel(grp + CH_COOL_STAGES, EcobeeUtils.undefOrDecimal(settings.coolStages));
|
||||
updateChannel(grp + CH_HEAT_STAGES, EcobeeUtils.undefOrDecimal(settings.heatStages));
|
||||
updateChannel(grp + CH_MAX_SET_BACK, EcobeeUtils.undefOrDecimal(settings.maxSetBack));
|
||||
updateChannel(grp + CH_MAX_SET_FORWARD, EcobeeUtils.undefOrDecimal(settings.maxSetForward));
|
||||
updateChannel(grp + CH_QUICK_SAVE_SET_BACK, EcobeeUtils.undefOrDecimal(settings.quickSaveSetBack));
|
||||
updateChannel(grp + CH_QUICK_SAVE_SET_FORWARD, EcobeeUtils.undefOrDecimal(settings.quickSaveSetForward));
|
||||
updateChannel(grp + CH_HAS_HEAT_PUMP, EcobeeUtils.undefOrOnOff(settings.hasHeatPump));
|
||||
updateChannel(grp + CH_HAS_FORCED_AIR, EcobeeUtils.undefOrOnOff(settings.hasForcedAir));
|
||||
updateChannel(grp + CH_HAS_BOILER, EcobeeUtils.undefOrOnOff(settings.hasBoiler));
|
||||
updateChannel(grp + CH_HAS_HUMIDIFIER, EcobeeUtils.undefOrOnOff(settings.hasHumidifier));
|
||||
updateChannel(grp + CH_HAS_ERV, EcobeeUtils.undefOrOnOff(settings.hasErv));
|
||||
updateChannel(grp + CH_HAS_HRV, EcobeeUtils.undefOrOnOff(settings.hasHrv));
|
||||
updateChannel(grp + CH_CONDENSATION_AVOID, EcobeeUtils.undefOrOnOff(settings.condensationAvoid));
|
||||
updateChannel(grp + CH_USE_CELSIUS, EcobeeUtils.undefOrOnOff(settings.useCelsius));
|
||||
updateChannel(grp + CH_USE_TIME_FORMAT_12, EcobeeUtils.undefOrOnOff(settings.useTimeFormat12));
|
||||
updateChannel(grp + CH_LOCALE, EcobeeUtils.undefOrString(settings.locale));
|
||||
updateChannel(grp + CH_HUMIDITY, EcobeeUtils.undefOrString(settings.humidity));
|
||||
updateChannel(grp + CH_HUMIDIFIER_MODE, EcobeeUtils.undefOrString(settings.humidifierMode));
|
||||
updateChannel(grp + CH_BACKLIGHT_ON_INTENSITY, EcobeeUtils.undefOrDecimal(settings.backlightOnIntensity));
|
||||
updateChannel(grp + CH_BACKLIGHT_SLEEP_INTENSITY, EcobeeUtils.undefOrDecimal(settings.backlightSleepIntensity));
|
||||
updateChannel(grp + CH_BACKLIGHT_OFF_TIME, EcobeeUtils.undefOrDecimal(settings.backlightOffTime));
|
||||
updateChannel(grp + CH_SOUND_TICK_VOLUME, EcobeeUtils.undefOrDecimal(settings.soundTickVolume));
|
||||
updateChannel(grp + CH_SOUND_ALERT_VOLUME, EcobeeUtils.undefOrDecimal(settings.soundAlertVolume));
|
||||
updateChannel(grp + CH_COMPRESSOR_PROTECTION_MIN_TIME,
|
||||
EcobeeUtils.undefOrDecimal(settings.compressorProtectionMinTime));
|
||||
updateChannel(grp + CH_COMPRESSOR_PROTECTION_MIN_TEMP,
|
||||
EcobeeUtils.undefOrTemperature(settings.compressorProtectionMinTemp));
|
||||
updateChannel(grp + CH_STAGE1_HEATING_DIFFERENTIAL_TEMP,
|
||||
EcobeeUtils.undefOrDecimal(settings.stage1HeatingDifferentialTemp));
|
||||
updateChannel(grp + CH_STAGE1_COOLING_DIFFERENTIAL_TEMP,
|
||||
EcobeeUtils.undefOrDecimal(settings.stage1CoolingDifferentialTemp));
|
||||
updateChannel(grp + CH_STAGE1_HEATING_DISSIPATION_TIME,
|
||||
EcobeeUtils.undefOrDecimal(settings.stage1HeatingDissipationTime));
|
||||
updateChannel(grp + CH_STAGE1_COOLING_DISSIPATION_TIME,
|
||||
EcobeeUtils.undefOrDecimal(settings.stage1CoolingDissipationTime));
|
||||
updateChannel(grp + CH_HEAT_PUMP_REVERSAL_ON_COOL, EcobeeUtils.undefOrOnOff(settings.heatPumpReversalOnCool));
|
||||
updateChannel(grp + CH_FAN_CONTROLLER_REQUIRED, EcobeeUtils.undefOrOnOff(settings.fanControlRequired));
|
||||
updateChannel(grp + CH_FAN_MIN_ON_TIME, EcobeeUtils.undefOrDecimal(settings.fanMinOnTime));
|
||||
updateChannel(grp + CH_HEAT_COOL_MIN_DELTA, EcobeeUtils.undefOrDecimal(settings.heatCoolMinDelta));
|
||||
updateChannel(grp + CH_TEMP_CORRECTION, EcobeeUtils.undefOrDecimal(settings.tempCorrection));
|
||||
updateChannel(grp + CH_HOLD_ACTION, EcobeeUtils.undefOrString(settings.holdAction));
|
||||
updateChannel(grp + CH_HEAT_PUMP_GROUND_WATER, EcobeeUtils.undefOrOnOff(settings.heatPumpGroundWater));
|
||||
updateChannel(grp + CH_HAS_ELECTRIC, EcobeeUtils.undefOrOnOff(settings.hasElectric));
|
||||
updateChannel(grp + CH_HAS_DEHUMIDIFIER, EcobeeUtils.undefOrOnOff(settings.hasDehumidifier));
|
||||
updateChannel(grp + CH_DEHUMIDIFIER_MODE, EcobeeUtils.undefOrString(settings.dehumidifierMode));
|
||||
updateChannel(grp + CH_DEHUMIDIFIER_LEVEL, EcobeeUtils.undefOrDecimal(settings.dehumidifierLevel));
|
||||
updateChannel(grp + CH_DEHUMIDIFY_WITH_AC, EcobeeUtils.undefOrOnOff(settings.dehumidifyWithAC));
|
||||
updateChannel(grp + CH_DEHUMIDIFY_OVERCOOL_OFFSET,
|
||||
EcobeeUtils.undefOrDecimal(settings.dehumidifyOvercoolOffset));
|
||||
updateChannel(grp + CH_AUTO_HEAT_COOL_FEATURE_ENABLED,
|
||||
EcobeeUtils.undefOrOnOff(settings.autoHeatCoolFeatureEnabled));
|
||||
updateChannel(grp + CH_WIFI_OFFLINE_ALERT, EcobeeUtils.undefOrOnOff(settings.wifiOfflineAlert));
|
||||
updateChannel(grp + CH_HEAT_MIN_TEMP, EcobeeUtils.undefOrTemperature(settings.heatMinTemp));
|
||||
updateChannel(grp + CH_HEAT_MAX_TEMP, EcobeeUtils.undefOrTemperature(settings.heatMaxTemp));
|
||||
updateChannel(grp + CH_COOL_MIN_TEMP, EcobeeUtils.undefOrTemperature(settings.coolMinTemp));
|
||||
updateChannel(grp + CH_COOL_MAX_TEMP, EcobeeUtils.undefOrTemperature(settings.coolMaxTemp));
|
||||
updateChannel(grp + CH_HEAT_RANGE_HIGH, EcobeeUtils.undefOrTemperature(settings.heatRangeHigh));
|
||||
updateChannel(grp + CH_HEAT_RANGE_LOW, EcobeeUtils.undefOrTemperature(settings.heatRangeLow));
|
||||
updateChannel(grp + CH_COOL_RANGE_HIGH, EcobeeUtils.undefOrTemperature(settings.coolRangeHigh));
|
||||
updateChannel(grp + CH_COOL_RANGE_LOW, EcobeeUtils.undefOrTemperature(settings.coolRangeLow));
|
||||
updateChannel(grp + CH_USER_ACCESS_CODE, EcobeeUtils.undefOrString(settings.userAccessCode));
|
||||
updateChannel(grp + CH_USER_ACCESS_SETTING, EcobeeUtils.undefOrDecimal(settings.userAccessSetting));
|
||||
updateChannel(grp + CH_AUX_RUNTIME_ALERT, EcobeeUtils.undefOrDecimal(settings.auxRuntimeAlert));
|
||||
updateChannel(grp + CH_AUX_OUTDOOR_TEMP_ALERT, EcobeeUtils.undefOrTemperature(settings.auxOutdoorTempAlert));
|
||||
updateChannel(grp + CH_AUX_MAX_OUTDOOR_TEMP, EcobeeUtils.undefOrTemperature(settings.auxMaxOutdoorTemp));
|
||||
updateChannel(grp + CH_AUX_RUNTIME_ALERT_NOTIFY, EcobeeUtils.undefOrOnOff(settings.auxRuntimeAlertNotify));
|
||||
updateChannel(grp + CH_AUX_OUTDOOR_TEMP_ALERT_NOTIFY,
|
||||
EcobeeUtils.undefOrOnOff(settings.auxOutdoorTempAlertNotify));
|
||||
updateChannel(grp + CH_AUX_RUNTIME_ALERT_NOTIFY_TECHNICIAN,
|
||||
EcobeeUtils.undefOrOnOff(settings.auxRuntimeAlertNotifyTechnician));
|
||||
updateChannel(grp + CH_AUX_OUTDOOR_TEMP_ALERT_NOTIFY_TECHNICIAN,
|
||||
EcobeeUtils.undefOrOnOff(settings.auxOutdoorTempAlertNotifyTechnician));
|
||||
updateChannel(grp + CH_DISABLE_PREHEATING, EcobeeUtils.undefOrOnOff(settings.disablePreHeating));
|
||||
updateChannel(grp + CH_DISABLE_PRECOOLING, EcobeeUtils.undefOrOnOff(settings.disablePreCooling));
|
||||
updateChannel(grp + CH_INSTALLER_CODE_REQUIRED, EcobeeUtils.undefOrOnOff(settings.installerCodeRequired));
|
||||
updateChannel(grp + CH_DR_ACCEPT, EcobeeUtils.undefOrString(settings.drAccept));
|
||||
updateChannel(grp + CH_IS_RENTAL_PROPERTY, EcobeeUtils.undefOrOnOff(settings.isRentalProperty));
|
||||
updateChannel(grp + CH_USE_ZONE_CONTROLLER, EcobeeUtils.undefOrOnOff(settings.useZoneController));
|
||||
updateChannel(grp + CH_RANDOM_START_DELAY_COOL, EcobeeUtils.undefOrDecimal(settings.randomStartDelayCool));
|
||||
updateChannel(grp + CH_RANDOM_START_DELAY_HEAT, EcobeeUtils.undefOrDecimal(settings.randomStartDelayHeat));
|
||||
updateChannel(grp + CH_HUMIDITY_HIGH_ALERT,
|
||||
EcobeeUtils.undefOrQuantity(settings.humidityHighAlert, SmartHomeUnits.PERCENT));
|
||||
updateChannel(grp + CH_HUMIDITY_LOW_ALERT,
|
||||
EcobeeUtils.undefOrQuantity(settings.humidityLowAlert, SmartHomeUnits.PERCENT));
|
||||
updateChannel(grp + CH_DISABLE_HEAT_PUMP_ALERTS, EcobeeUtils.undefOrOnOff(settings.disableHeatPumpAlerts));
|
||||
updateChannel(grp + CH_DISABLE_ALERTS_ON_IDT, EcobeeUtils.undefOrOnOff(settings.disableAlertsOnIdt));
|
||||
updateChannel(grp + CH_HUMIDITY_ALERT_NOTIFY, EcobeeUtils.undefOrOnOff(settings.humidityAlertNotify));
|
||||
updateChannel(grp + CH_HUMIDITY_ALERT_NOTIFY_TECHNICIAN,
|
||||
EcobeeUtils.undefOrOnOff(settings.humidityAlertNotifyTechnician));
|
||||
updateChannel(grp + CH_TEMP_ALERT_NOTIFY, EcobeeUtils.undefOrOnOff(settings.tempAlertNotify));
|
||||
updateChannel(grp + CH_TEMP_ALERT_NOTIFY_TECHNICIAN,
|
||||
EcobeeUtils.undefOrOnOff(settings.tempAlertNotifyTechnician));
|
||||
updateChannel(grp + CH_MONTHLY_ELECTRICITY_BILL_LIMIT,
|
||||
EcobeeUtils.undefOrDecimal(settings.monthlyElectricityBillLimit));
|
||||
updateChannel(grp + CH_ENABLE_ELECTRICITY_BILL_ALERT,
|
||||
EcobeeUtils.undefOrOnOff(settings.enableElectricityBillAlert));
|
||||
updateChannel(grp + CH_ENABLE_PROJECTED_ELECTRICITY_BILL_ALERT,
|
||||
EcobeeUtils.undefOrOnOff(settings.enableProjectedElectricityBillAlert));
|
||||
updateChannel(grp + CH_ELECTRICITY_BILLING_DAY_OF_MONTH,
|
||||
EcobeeUtils.undefOrDecimal(settings.electricityBillingDayOfMonth));
|
||||
updateChannel(grp + CH_ELECTRICITY_BILL_CYCLE_MONTHS,
|
||||
EcobeeUtils.undefOrDecimal(settings.electricityBillCycleMonths));
|
||||
updateChannel(grp + CH_ELECTRICITY_BILL_START_MONTH,
|
||||
EcobeeUtils.undefOrDecimal(settings.electricityBillStartMonth));
|
||||
updateChannel(grp + CH_VENTILATOR_MIN_ON_TIME_HOME,
|
||||
EcobeeUtils.undefOrDecimal(settings.ventilatorMinOnTimeHome));
|
||||
updateChannel(grp + CH_VENTILATOR_MIN_ON_TIME_AWAY,
|
||||
EcobeeUtils.undefOrDecimal(settings.ventilatorMinOnTimeAway));
|
||||
updateChannel(grp + CH_BACKLIGHT_OFF_DURING_SLEEP, EcobeeUtils.undefOrOnOff(settings.backlightOffDuringSleep));
|
||||
updateChannel(grp + CH_AUTO_AWAY, EcobeeUtils.undefOrOnOff(settings.autoAway));
|
||||
updateChannel(grp + CH_SMART_CIRCULATION, EcobeeUtils.undefOrOnOff(settings.smartCirculation));
|
||||
updateChannel(grp + CH_FOLLOW_ME_COMFORT, EcobeeUtils.undefOrOnOff(settings.followMeComfort));
|
||||
updateChannel(grp + CH_VENTILATOR_TYPE, EcobeeUtils.undefOrString(settings.ventilatorType));
|
||||
updateChannel(grp + CH_IS_VENTILATOR_TIMER_ON, EcobeeUtils.undefOrOnOff(settings.isVentilatorTimerOn));
|
||||
updateChannel(grp + CH_VENTILATOR_OFF_DATE_TIME, EcobeeUtils.undefOrString(settings.ventilatorOffDateTime));
|
||||
updateChannel(grp + CH_HAS_UV_FILTER, EcobeeUtils.undefOrOnOff(settings.hasUVFilter));
|
||||
updateChannel(grp + CH_COOLING_LOCKOUT, EcobeeUtils.undefOrOnOff(settings.coolingLockout));
|
||||
updateChannel(grp + CH_VENTILATOR_FREE_COOLING, EcobeeUtils.undefOrOnOff(settings.ventilatorFreeCooling));
|
||||
updateChannel(grp + CH_DEHUMIDIFY_WHEN_HEATING, EcobeeUtils.undefOrOnOff(settings.dehumidifyWhenHeating));
|
||||
updateChannel(grp + CH_VENTILATOR_DEHUMIDIFY, EcobeeUtils.undefOrOnOff(settings.ventilatorDehumidify));
|
||||
updateChannel(grp + CH_GROUP_REF, EcobeeUtils.undefOrString(settings.groupRef));
|
||||
updateChannel(grp + CH_GROUP_NAME, EcobeeUtils.undefOrString(settings.groupName));
|
||||
updateChannel(grp + CH_GROUP_SETTING, EcobeeUtils.undefOrDecimal(settings.groupSetting));
|
||||
}
|
||||
|
||||
private void updateProgram(@Nullable ProgramDTO program) {
|
||||
if (program == null) {
|
||||
return;
|
||||
}
|
||||
final String grp = CHGRP_PROGRAM + "#";
|
||||
updateChannel(grp + CH_PROGRAM_CURRENT_CLIMATE_REF, EcobeeUtils.undefOrString(program.currentClimateRef));
|
||||
if (program.climates != null) {
|
||||
saveValidClimateRefs(program.climates);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveValidClimateRefs(List<ClimateDTO> climates) {
|
||||
validClimateRefs.clear();
|
||||
for (ClimateDTO climate : climates) {
|
||||
validClimateRefs.add(climate.climateRef);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAlert(@Nullable List<AlertDTO> alerts) {
|
||||
AlertDTO firstAlert;
|
||||
if (alerts == null || alerts.isEmpty()) {
|
||||
firstAlert = EMPTY_ALERT;
|
||||
} else {
|
||||
firstAlert = alerts.get(0);
|
||||
}
|
||||
final String grp = CHGRP_ALERT + "#";
|
||||
updateChannel(grp + CH_ALERT_ACKNOWLEDGE_REF, EcobeeUtils.undefOrString(firstAlert.acknowledgeRef));
|
||||
updateChannel(grp + CH_ALERT_DATE, EcobeeUtils.undefOrString(firstAlert.date));
|
||||
updateChannel(grp + CH_ALERT_TIME, EcobeeUtils.undefOrString(firstAlert.time));
|
||||
updateChannel(grp + CH_ALERT_SEVERITY, EcobeeUtils.undefOrString(firstAlert.severity));
|
||||
updateChannel(grp + CH_ALERT_TEXT, EcobeeUtils.undefOrString(firstAlert.text));
|
||||
updateChannel(grp + CH_ALERT_ALERT_NUMBER, EcobeeUtils.undefOrDecimal(firstAlert.alertNumber));
|
||||
updateChannel(grp + CH_ALERT_ALERT_TYPE, EcobeeUtils.undefOrString(firstAlert.alertType));
|
||||
updateChannel(grp + CH_ALERT_IS_OPERATOR_ALERT, EcobeeUtils.undefOrOnOff(firstAlert.isOperatorAlert));
|
||||
updateChannel(grp + CH_ALERT_REMINDER, EcobeeUtils.undefOrString(firstAlert.reminder));
|
||||
updateChannel(grp + CH_ALERT_SHOW_IDT, EcobeeUtils.undefOrOnOff(firstAlert.showIdt));
|
||||
updateChannel(grp + CH_ALERT_SHOW_WEB, EcobeeUtils.undefOrOnOff(firstAlert.showWeb));
|
||||
updateChannel(grp + CH_ALERT_SEND_EMAIL, EcobeeUtils.undefOrOnOff(firstAlert.sendEmail));
|
||||
updateChannel(grp + CH_ALERT_ACKNOWLEDGEMENT, EcobeeUtils.undefOrString(firstAlert.acknowledgement));
|
||||
updateChannel(grp + CH_ALERT_REMIND_ME_LATER, EcobeeUtils.undefOrOnOff(firstAlert.remindMeLater));
|
||||
updateChannel(grp + CH_ALERT_THERMOSTAT_IDENTIFIER, EcobeeUtils.undefOrString(firstAlert.thermostatIdentifier));
|
||||
updateChannel(grp + CH_ALERT_NOTIFICATION_TYPE, EcobeeUtils.undefOrString(firstAlert.notificationType));
|
||||
}
|
||||
|
||||
private void updateEvent(@Nullable List<EventDTO> events) {
|
||||
EventDTO runningEvent = EMPTY_EVENT;
|
||||
if (events != null && !events.isEmpty()) {
|
||||
for (EventDTO event : events) {
|
||||
if (event.running) {
|
||||
runningEvent = event;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
final String grp = CHGRP_EVENT + "#";
|
||||
updateChannel(grp + CH_EVENT_NAME, EcobeeUtils.undefOrString(runningEvent.name));
|
||||
updateChannel(grp + CH_EVENT_TYPE, EcobeeUtils.undefOrString(runningEvent.type));
|
||||
updateChannel(grp + CH_EVENT_RUNNING, EcobeeUtils.undefOrOnOff(runningEvent.running));
|
||||
updateChannel(grp + CH_EVENT_START_DATE, EcobeeUtils.undefOrString(runningEvent.startDate));
|
||||
updateChannel(grp + CH_EVENT_START_TIME, EcobeeUtils.undefOrString(runningEvent.startTime));
|
||||
updateChannel(grp + CH_EVENT_END_DATE, EcobeeUtils.undefOrString(runningEvent.endDate));
|
||||
updateChannel(grp + CH_EVENT_END_TIME, EcobeeUtils.undefOrString(runningEvent.endTime));
|
||||
updateChannel(grp + CH_EVENT_IS_OCCUPIED, EcobeeUtils.undefOrOnOff(runningEvent.isOccupied));
|
||||
updateChannel(grp + CH_EVENT_IS_COOL_OFF, EcobeeUtils.undefOrOnOff(runningEvent.isCoolOff));
|
||||
updateChannel(grp + CH_EVENT_IS_HEAT_OFF, EcobeeUtils.undefOrOnOff(runningEvent.isHeatOff));
|
||||
updateChannel(grp + CH_EVENT_COOL_HOLD_TEMP, EcobeeUtils.undefOrTemperature(runningEvent.coolHoldTemp));
|
||||
updateChannel(grp + CH_EVENT_HEAT_HOLD_TEMP, EcobeeUtils.undefOrTemperature(runningEvent.heatHoldTemp));
|
||||
updateChannel(grp + CH_EVENT_FAN, EcobeeUtils.undefOrString(runningEvent.fan));
|
||||
updateChannel(grp + CH_EVENT_VENT, EcobeeUtils.undefOrString(runningEvent.vent));
|
||||
updateChannel(grp + CH_EVENT_VENTILATOR_MIN_ON_TIME,
|
||||
EcobeeUtils.undefOrDecimal(runningEvent.ventilatorMinOnTime));
|
||||
updateChannel(grp + CH_EVENT_IS_OPTIONAL, EcobeeUtils.undefOrOnOff(runningEvent.isOptional));
|
||||
updateChannel(grp + CH_EVENT_IS_TEMPERATURE_RELATIVE,
|
||||
EcobeeUtils.undefOrOnOff(runningEvent.isTemperatureRelative));
|
||||
updateChannel(grp + CH_EVENT_COOL_RELATIVE_TEMP, EcobeeUtils.undefOrDecimal(runningEvent.coolRelativeTemp));
|
||||
updateChannel(grp + CH_EVENT_HEAT_RELATIVE_TEMP, EcobeeUtils.undefOrDecimal(runningEvent.heatRelativeTemp));
|
||||
updateChannel(grp + CH_EVENT_IS_TEMPERATURE_ABSOLUTE,
|
||||
EcobeeUtils.undefOrOnOff(runningEvent.isTemperatureAbsolute));
|
||||
updateChannel(grp + CH_EVENT_DUTY_CYCLE_PERCENTAGE,
|
||||
EcobeeUtils.undefOrDecimal(runningEvent.dutyCyclePercentage));
|
||||
updateChannel(grp + CH_EVENT_FAN_MIN_ON_TIME, EcobeeUtils.undefOrDecimal(runningEvent.fanMinOnTime));
|
||||
updateChannel(grp + CH_EVENT_OCCUPIED_SENSOR_ACTIVE,
|
||||
EcobeeUtils.undefOrOnOff(runningEvent.occupiedSensorActive));
|
||||
updateChannel(grp + CH_EVENT_UNOCCUPIED_SENSOR_ACTIVE,
|
||||
EcobeeUtils.undefOrOnOff(runningEvent.unoccupiedSensorActive));
|
||||
updateChannel(grp + CH_EVENT_DR_RAMP_UP_TEMP, EcobeeUtils.undefOrDecimal(runningEvent.drRampUpTemp));
|
||||
updateChannel(grp + CH_EVENT_DR_RAMP_UP_TIME, EcobeeUtils.undefOrDecimal(runningEvent.drRampUpTime));
|
||||
updateChannel(grp + CH_EVENT_LINK_REF, EcobeeUtils.undefOrString(runningEvent.linkRef));
|
||||
updateChannel(grp + CH_EVENT_HOLD_CLIMATE_REF, EcobeeUtils.undefOrString(runningEvent.holdClimateRef));
|
||||
}
|
||||
|
||||
private void updateWeather(@Nullable WeatherDTO weather) {
|
||||
if (weather == null || weather.forecasts == null) {
|
||||
return;
|
||||
}
|
||||
final String weatherGrp = CHGRP_WEATHER + "#";
|
||||
updateChannel(weatherGrp + CH_WEATHER_TIMESTAMP, EcobeeUtils.undefOrDate(weather.timestamp, timeZoneProvider));
|
||||
updateChannel(weatherGrp + CH_WEATHER_WEATHER_STATION, EcobeeUtils.undefOrString(weather.weatherStation));
|
||||
|
||||
for (int index = 0; index < weather.forecasts.size(); index++) {
|
||||
final String grp = CHGRP_FORECAST + String.format("%d", index) + "#";
|
||||
WeatherForecastDTO forecast = weather.forecasts.get(index);
|
||||
if (forecast != null) {
|
||||
updateChannel(grp + CH_FORECAST_WEATHER_SYMBOL, EcobeeUtils.undefOrDecimal(forecast.weatherSymbol));
|
||||
updateChannel(grp + CH_FORECAST_WEATHER_SYMBOL_TEXT,
|
||||
EcobeeUtils.undefOrString(symbolMap.get(forecast.weatherSymbol)));
|
||||
updateChannel(grp + CH_FORECAST_DATE_TIME,
|
||||
EcobeeUtils.undefOrDate(forecast.dateTime, timeZoneProvider));
|
||||
updateChannel(grp + CH_FORECAST_CONDITION, EcobeeUtils.undefOrString(forecast.condition));
|
||||
updateChannel(grp + CH_FORECAST_TEMPERATURE, EcobeeUtils.undefOrTemperature(forecast.temperature));
|
||||
updateChannel(grp + CH_FORECAST_PRESSURE,
|
||||
EcobeeUtils.undefOrQuantity(forecast.pressure, ImperialUnits.INCH_OF_MERCURY));
|
||||
updateChannel(grp + CH_FORECAST_RELATIVE_HUMIDITY,
|
||||
EcobeeUtils.undefOrQuantity(forecast.relativeHumidity, SmartHomeUnits.PERCENT));
|
||||
updateChannel(grp + CH_FORECAST_DEWPOINT, EcobeeUtils.undefOrTemperature(forecast.dewpoint));
|
||||
updateChannel(grp + CH_FORECAST_VISIBILITY,
|
||||
EcobeeUtils.undefOrQuantity(forecast.visibility, SIUnits.METRE));
|
||||
updateChannel(grp + CH_FORECAST_WIND_SPEED,
|
||||
EcobeeUtils.undefOrQuantity(forecast.windSpeed, ImperialUnits.MILES_PER_HOUR));
|
||||
updateChannel(grp + CH_FORECAST_WIND_GUST,
|
||||
EcobeeUtils.undefOrQuantity(forecast.windGust, ImperialUnits.MILES_PER_HOUR));
|
||||
updateChannel(grp + CH_FORECAST_WIND_DIRECTION, EcobeeUtils.undefOrString(forecast.windDirection));
|
||||
updateChannel(grp + CH_FORECAST_WIND_BEARING,
|
||||
EcobeeUtils.undefOrQuantity(forecast.windBearing, SmartHomeUnits.DEGREE_ANGLE));
|
||||
updateChannel(grp + CH_FORECAST_POP, EcobeeUtils.undefOrQuantity(forecast.pop, SmartHomeUnits.PERCENT));
|
||||
updateChannel(grp + CH_FORECAST_TEMP_HIGH, EcobeeUtils.undefOrTemperature(forecast.tempHigh));
|
||||
updateChannel(grp + CH_FORECAST_TEMP_LOW, EcobeeUtils.undefOrTemperature(forecast.tempLow));
|
||||
updateChannel(grp + CH_FORECAST_SKY, EcobeeUtils.undefOrDecimal(forecast.sky));
|
||||
updateChannel(grp + CH_FORECAST_SKY_TEXT, EcobeeUtils.undefOrString(skyMap.get(forecast.sky)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateVersion(@Nullable VersionDTO version) {
|
||||
if (version == null) {
|
||||
return;
|
||||
}
|
||||
final String grp = CHGRP_VERSION + "#";
|
||||
updateChannel(grp + CH_THERMOSTAT_FIRMWARE_VERSION,
|
||||
EcobeeUtils.undefOrString(version.thermostatFirmwareVersion));
|
||||
}
|
||||
|
||||
private void updateLocation(@Nullable LocationDTO loc) {
|
||||
LocationDTO location = EMPTY_LOCATION;
|
||||
if (loc != null) {
|
||||
location = loc;
|
||||
}
|
||||
final String grp = CHGRP_LOCATION + "#";
|
||||
updateChannel(grp + CH_TIME_ZONE_OFFSET_MINUTES, EcobeeUtils.undefOrDecimal(location.timeZoneOffsetMinutes));
|
||||
updateChannel(grp + CH_TIME_ZONE, EcobeeUtils.undefOrString(location.timeZone));
|
||||
updateChannel(grp + CH_IS_DAYLIGHT_SAVING, EcobeeUtils.undefOrOnOff(location.isDaylightSaving));
|
||||
updateChannel(grp + CH_STREET_ADDRESS, EcobeeUtils.undefOrString(location.streetAddress));
|
||||
updateChannel(grp + CH_CITY, EcobeeUtils.undefOrString(location.city));
|
||||
updateChannel(grp + CH_PROVINCE_STATE, EcobeeUtils.undefOrString(location.provinceState));
|
||||
updateChannel(grp + CH_COUNTRY, EcobeeUtils.undefOrString(location.country));
|
||||
updateChannel(grp + CH_POSTAL_CODE, EcobeeUtils.undefOrString(location.postalCode));
|
||||
updateChannel(grp + CH_PHONE_NUMBER, EcobeeUtils.undefOrString(location.phoneNumber));
|
||||
updateChannel(grp + CH_MAP_COORDINATES, EcobeeUtils.undefOrPoint(location.mapCoordinates));
|
||||
}
|
||||
|
||||
private void updateHouseDetails(@Nullable HouseDetailsDTO hd) {
|
||||
HouseDetailsDTO houseDetails = EMPTY_HOUSEDETAILS;
|
||||
if (hd != null) {
|
||||
houseDetails = hd;
|
||||
}
|
||||
final String grp = CHGRP_HOUSE_DETAILS + "#";
|
||||
updateChannel(grp + CH_HOUSEDETAILS_STYLE, EcobeeUtils.undefOrString(houseDetails.style));
|
||||
updateChannel(grp + CH_HOUSEDETAILS_SIZE, EcobeeUtils.undefOrDecimal(houseDetails.size));
|
||||
updateChannel(grp + CH_HOUSEDETAILS_NUMBER_OF_FLOORS, EcobeeUtils.undefOrDecimal(houseDetails.numberOfFloors));
|
||||
updateChannel(grp + CH_HOUSEDETAILS_NUMBER_OF_ROOMS, EcobeeUtils.undefOrDecimal(houseDetails.numberOfRooms));
|
||||
updateChannel(grp + CH_HOUSEDETAILS_NUMBER_OF_OCCUPANTS,
|
||||
EcobeeUtils.undefOrDecimal(houseDetails.numberOfOccupants));
|
||||
updateChannel(grp + CH_HOUSEDETAILS_AGE, EcobeeUtils.undefOrDecimal(houseDetails.age));
|
||||
updateChannel(grp + CH_HOUSEDETAILS_WINDOW_EFFICIENCY,
|
||||
EcobeeUtils.undefOrDecimal(houseDetails.windowEfficiency));
|
||||
}
|
||||
|
||||
private void updateManagement(@Nullable ManagementDTO mgmt) {
|
||||
ManagementDTO management = EMPTY_MANAGEMENT;
|
||||
if (mgmt != null) {
|
||||
management = mgmt;
|
||||
}
|
||||
final String grp = CHGRP_MANAGEMENT + "#";
|
||||
updateChannel(grp + CH_MANAGEMENT_ADMIN_CONTACT, EcobeeUtils.undefOrString(management.administrativeContact));
|
||||
updateChannel(grp + CH_MANAGEMENT_BILLING_CONTACT, EcobeeUtils.undefOrString(management.billingContact));
|
||||
updateChannel(grp + CH_MANAGEMENT_NAME, EcobeeUtils.undefOrString(management.name));
|
||||
updateChannel(grp + CH_MANAGEMENT_PHONE, EcobeeUtils.undefOrString(management.phone));
|
||||
updateChannel(grp + CH_MANAGEMENT_EMAIL, EcobeeUtils.undefOrString(management.email));
|
||||
updateChannel(grp + CH_MANAGEMENT_WEB, EcobeeUtils.undefOrString(management.web));
|
||||
updateChannel(grp + CH_MANAGEMENT_SHOW_ALERT_IDT, EcobeeUtils.undefOrOnOff(management.showAlertIdt));
|
||||
updateChannel(grp + CH_MANAGEMENT_SHOW_ALERT_WEB, EcobeeUtils.undefOrOnOff(management.showAlertWeb));
|
||||
}
|
||||
|
||||
private void updateTechnician(@Nullable TechnicianDTO tech) {
|
||||
TechnicianDTO technician = EMPTY_TECHNICIAN;
|
||||
if (tech != null) {
|
||||
technician = tech;
|
||||
}
|
||||
final String grp = CHGRP_TECHNICIAN + "#";
|
||||
updateChannel(grp + CH_TECHNICIAN_CONTRACTOR_REF, EcobeeUtils.undefOrString(technician.contractorRef));
|
||||
updateChannel(grp + CH_TECHNICIAN_NAME, EcobeeUtils.undefOrString(technician.name));
|
||||
updateChannel(grp + CH_TECHNICIAN_PHONE, EcobeeUtils.undefOrString(technician.phone));
|
||||
updateChannel(grp + CH_TECHNICIAN_STREET_ADDRESS, EcobeeUtils.undefOrString(technician.streetAddress));
|
||||
updateChannel(grp + CH_TECHNICIAN_CITY, EcobeeUtils.undefOrString(technician.city));
|
||||
updateChannel(grp + CH_TECHNICIAN_PROVINCE_STATE, EcobeeUtils.undefOrString(technician.provinceState));
|
||||
updateChannel(grp + CH_TECHNICIAN_COUNTRY, EcobeeUtils.undefOrString(technician.country));
|
||||
updateChannel(grp + CH_TECHNICIAN_POSTAL_CODE, EcobeeUtils.undefOrString(technician.postalCode));
|
||||
updateChannel(grp + CH_TECHNICIAN_EMAIL, EcobeeUtils.undefOrString(technician.email));
|
||||
updateChannel(grp + CH_TECHNICIAN_WEB, EcobeeUtils.undefOrString(technician.web));
|
||||
}
|
||||
|
||||
private void updateChannel(String channelId, State state) {
|
||||
updateState(channelId, state);
|
||||
stateCache.put(channelId, state);
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
private void updateRemoteSensors(@Nullable List<RemoteSensorDTO> remoteSensors) {
|
||||
if (remoteSensors == null) {
|
||||
return;
|
||||
}
|
||||
logger.debug("ThermostatBridge: Thermostat '{}' has {} remote sensors", thermostatId, remoteSensors.size());
|
||||
for (RemoteSensorDTO sensor : remoteSensors) {
|
||||
EcobeeSensorThingHandler handler = sensorHandlers.get(sensor.id);
|
||||
if (handler != null) {
|
||||
logger.debug("ThermostatBridge: Sending data to sensor handler '{}({})' of type '{}'", sensor.id,
|
||||
sensor.name, sensor.type);
|
||||
handler.updateChannels(sensor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void performThermostatUpdate(ThermostatDTO thermostat) {
|
||||
SelectionDTO selection = new SelectionDTO();
|
||||
selection.setThermostats(Collections.singleton(thermostatId));
|
||||
ThermostatUpdateRequestDTO request = new ThermostatUpdateRequestDTO(selection);
|
||||
request.thermostat = thermostat;
|
||||
EcobeeAccountBridgeHandler handler = getBridgeHandler();
|
||||
if (handler != null) {
|
||||
handler.performThermostatUpdate(request);
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleDiscoveryJob() {
|
||||
logger.debug("ThermostatBridge: Scheduling sensor discovery job");
|
||||
cancelDiscoveryJob();
|
||||
discoverSensorsJob = scheduler.scheduleWithFixedDelay(this::discoverSensors,
|
||||
SENSOR_DISCOVERY_STARTUP_DELAY_SECONDS, SENSOR_DISCOVERY_INTERVAL_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void cancelDiscoveryJob() {
|
||||
Future<?> localDiscoverSensorsJob = discoverSensorsJob;
|
||||
if (localDiscoverSensorsJob != null) {
|
||||
localDiscoverSensorsJob.cancel(true);
|
||||
logger.debug("ThermostatBridge: Canceling sensor discovery job");
|
||||
}
|
||||
}
|
||||
|
||||
private void discoverSensors() {
|
||||
EcobeeAccountBridgeHandler handler = getBridgeHandler();
|
||||
if (handler != null && handler.isDiscoveryEnabled()) {
|
||||
SensorDiscoveryService localDiscoveryService = discoveryService;
|
||||
if (localDiscoveryService != null) {
|
||||
logger.debug("ThermostatBridge: Running sensor discovery");
|
||||
localDiscoveryService.startBackgroundDiscovery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable EcobeeAccountBridgeHandler getBridgeHandler() {
|
||||
EcobeeAccountBridgeHandler handler = null;
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
handler = (EcobeeAccountBridgeHandler) bridge.getHandler();
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
private boolean isChannelReadOnly(ChannelUID channelUID) {
|
||||
Boolean isReadOnly = channelReadOnlyMap.get(channelUID);
|
||||
return isReadOnly != null ? isReadOnly : true;
|
||||
}
|
||||
|
||||
private void clearSavedState() {
|
||||
savedThermostat = null;
|
||||
savedSensors = null;
|
||||
stateCache.clear();
|
||||
}
|
||||
|
||||
private void initializeReadOnlyChannels() {
|
||||
channelReadOnlyMap.clear();
|
||||
for (Channel channel : thing.getChannels()) {
|
||||
ChannelTypeUID channelTypeUID = channel.getChannelTypeUID();
|
||||
if (channelTypeUID != null) {
|
||||
ChannelType channelType = channelTypeRegistry.getChannelType(channelTypeUID, null);
|
||||
if (channelType != null) {
|
||||
channelReadOnlyMap.putIfAbsent(channel.getUID(), channelType.getState().isReadOnly());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeWeatherMaps() {
|
||||
initializeSymbolMap();
|
||||
initializeSkyMap();
|
||||
}
|
||||
|
||||
private void initializeSymbolMap() {
|
||||
symbolMap.clear();
|
||||
symbolMap.put(-2, "NO SYMBOL");
|
||||
symbolMap.put(0, "SUNNY");
|
||||
symbolMap.put(1, "FEW CLOUDS");
|
||||
symbolMap.put(2, "PARTLY CLOUDY");
|
||||
symbolMap.put(3, "MOSTLY CLOUDY");
|
||||
symbolMap.put(4, "OVERCAST");
|
||||
symbolMap.put(5, "DRIZZLE");
|
||||
symbolMap.put(6, "RAIN");
|
||||
symbolMap.put(7, "FREEZING RAIN");
|
||||
symbolMap.put(8, "SHOWERS");
|
||||
symbolMap.put(9, "HAIL");
|
||||
symbolMap.put(10, "SNOW");
|
||||
symbolMap.put(11, "FLURRIES");
|
||||
symbolMap.put(12, "FREEZING SNOW");
|
||||
symbolMap.put(13, "BLIZZARD");
|
||||
symbolMap.put(14, "PELLETS");
|
||||
symbolMap.put(15, "THUNDERSTORM");
|
||||
symbolMap.put(16, "WINDY");
|
||||
symbolMap.put(17, "TORNADO");
|
||||
symbolMap.put(18, "FOG");
|
||||
symbolMap.put(19, "HAZE");
|
||||
symbolMap.put(20, "SMOKE");
|
||||
symbolMap.put(21, "DUST");
|
||||
}
|
||||
|
||||
private void initializeSkyMap() {
|
||||
skyMap.clear();
|
||||
skyMap.put(1, "SUNNY");
|
||||
skyMap.put(2, "CLEAR");
|
||||
skyMap.put(3, "MOSTLY SUNNY");
|
||||
skyMap.put(4, "MOSTLY CLEAR");
|
||||
skyMap.put(5, "HAZY SUNSHINE");
|
||||
skyMap.put(6, "HAZE");
|
||||
skyMap.put(7, "PASSING CLOUDS");
|
||||
skyMap.put(8, "MORE SUN THAN CLOUDS");
|
||||
skyMap.put(9, "SCATTERED CLOUDS");
|
||||
skyMap.put(10, "PARTLY CLOUDY");
|
||||
skyMap.put(11, "A MIXTURE OF SUN AND CLOUDS");
|
||||
skyMap.put(12, "HIGH LEVEL CLOUDS");
|
||||
skyMap.put(13, "MORE CLOUDS THAN SUN");
|
||||
skyMap.put(14, "PARTLY SUNNY");
|
||||
skyMap.put(15, "BROKEN CLOUDS");
|
||||
skyMap.put(16, "MOSTLY CLOUDY");
|
||||
skyMap.put(17, "CLOUDY");
|
||||
skyMap.put(18, "OVERCAST");
|
||||
skyMap.put(19, "LOW CLOUDS");
|
||||
skyMap.put(20, "LIGHT FOG");
|
||||
skyMap.put(21, "FOG");
|
||||
skyMap.put(22, "DENSE FOG");
|
||||
skyMap.put(23, "ICE FOG");
|
||||
skyMap.put(24, "SANDSTORM");
|
||||
skyMap.put(25, "DUSTSTORM");
|
||||
skyMap.put(26, "INCREASING CLOUDINESS");
|
||||
skyMap.put(27, "DECREASING CLOUDINESS");
|
||||
skyMap.put(28, "CLEARING SKIES");
|
||||
skyMap.put(29, "BREAKS OF SUN LATE");
|
||||
skyMap.put(30, "EARLY FOG FOLLOWED BY SUNNY SKIES");
|
||||
skyMap.put(31, "AFTERNOON CLOUDS");
|
||||
skyMap.put(32, "MORNING CLOUDS");
|
||||
skyMap.put(33, "SMOKE");
|
||||
skyMap.put(34, "LOW LEVEL HAZE");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.ecobee.internal.handler;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.measure.Unit;
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PointType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* The {@link EcobeeUtils} contains utility methods used by the
|
||||
* thing handler and the bridge handler.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class EcobeeUtils {
|
||||
|
||||
private static final int UNKNOWN_VALUE = -5002;
|
||||
|
||||
/*
|
||||
* Checks to see if a bridge is online.
|
||||
*/
|
||||
public static boolean isBridgeOnline(@Nullable Bridge bridge) {
|
||||
boolean bridgeStatus = false;
|
||||
if (bridge != null && bridge.getStatus() == ThingStatus.ONLINE) {
|
||||
bridgeStatus = true;
|
||||
}
|
||||
return bridgeStatus;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the state to the passed value. If value is null, set the state to UNDEF
|
||||
*/
|
||||
public static State undefOrOnOff(@Nullable Boolean value) {
|
||||
return value == null ? UnDefType.UNDEF : (value.booleanValue() ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
|
||||
public static State undefOrString(@Nullable String value) {
|
||||
return value == null ? UnDefType.UNDEF : new StringType(value);
|
||||
}
|
||||
|
||||
public static State undefOrDecimal(@Nullable Number value) {
|
||||
return (value == null || isUnknown(value)) ? UnDefType.UNDEF : new DecimalType(value.doubleValue());
|
||||
}
|
||||
|
||||
public static State undefOrQuantity(@Nullable Number value, Unit<?> unit) {
|
||||
return (value == null || isUnknown(value)) ? UnDefType.UNDEF : new QuantityType<>(value, unit);
|
||||
}
|
||||
|
||||
public static State undefOrTemperature(@Nullable Number value) {
|
||||
return (value == null || isUnknown(value)) ? UnDefType.UNDEF
|
||||
: new QuantityType<>(value.doubleValue() / 10.0, ImperialUnits.FAHRENHEIT);
|
||||
}
|
||||
|
||||
public static State undefOrPoint(@Nullable String value) {
|
||||
return value == null ? UnDefType.UNDEF : new PointType(value);
|
||||
}
|
||||
|
||||
public static State undefOrDate(@Nullable Date date, TimeZoneProvider timeZoneProvider) {
|
||||
return date == null ? UnDefType.UNDEF
|
||||
: new DateTimeType(ZonedDateTime.ofInstant(date.toInstant(), timeZoneProvider.getTimeZone()));
|
||||
}
|
||||
|
||||
private static boolean isUnknown(Number value) {
|
||||
return value.intValue() == UNKNOWN_VALUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a QuantityType<Temperature> to the internal format used by the Ecobee API.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Integer convertQuantityTypeToEcobeeTemp(Object value) {
|
||||
if (value instanceof QuantityType<?>) {
|
||||
QuantityType<Temperature> convertedTemp = ((QuantityType<Temperature>) value)
|
||||
.toUnit(ImperialUnits.FAHRENHEIT);
|
||||
if (convertedTemp != null) {
|
||||
return Integer.valueOf(convertedTemp.intValue() * 10);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("temperature is not a QuantityType");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="ecobee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>Ecobee Binding</name>
|
||||
<description>This is the binding for Ecobee smart thermostats.</description>
|
||||
<author>Mark Hilbush</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,52 @@
|
||||
<config-description:config-descriptions
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
|
||||
|
||||
<config-description uri="thing-type:ecobee:account">
|
||||
<parameter name="apiKey" type="text" required="true">
|
||||
<label>API Key</label>
|
||||
<description>Enter the API key</description>
|
||||
<context>password</context>
|
||||
</parameter>
|
||||
<parameter name="refreshIntervalNormal" type="integer" min="2" required="false" unit="s">
|
||||
<label>Refresh Interval (Normal)</label>
|
||||
<description>Specifies the refresh interval in seconds</description>
|
||||
<default>30</default>
|
||||
</parameter>
|
||||
<parameter name="refreshIntervalQuick" type="integer" min="2" required="false" unit="s">
|
||||
<label>Refresh Interval (Quick)</label>
|
||||
<description>Specifies time in seconds to wait after successful update, command or action before refresh</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
<parameter name="apiTimeout" type="integer" min="2" required="false" unit="s">
|
||||
<label>API Timeout</label>
|
||||
<description>Time in seconds to allow API request to complete</description>
|
||||
<default>22</default>
|
||||
</parameter>
|
||||
<parameter name="discoveryEnabled" type="boolean" required="false">
|
||||
<label>Discovery Enabled</label>
|
||||
<description>Enable/disable automatic discovery</description>
|
||||
<default>true</default>
|
||||
</parameter>
|
||||
<parameter name="discoveryInterval" type="integer" min="60" required="false" unit="s">
|
||||
<label>Thermostat Discovery Interval</label>
|
||||
<description>Specifies time in seconds in which the binding will attempt to discover thermostats</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:ecobee:thermostat">
|
||||
<parameter name="thermostatId" type="text" required="true">
|
||||
<label>Thermostat ID</label>
|
||||
<description>Thermostat ID assigned to this thermostat by Ecobee</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:ecobee:sensor">
|
||||
<parameter name="sensorId" type="text" required="true">
|
||||
<label>Sensor Id</label>
|
||||
<description>Id assigned to this sensor (e.g. rs:101)</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</config-description:config-descriptions>
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user