[ojelectronics] Add discovery; enable writable properties (#9168)
* Add methods to update via Command; Add discovery * add vacation channels; rework README * Fixed code review issues: Corrected TimeZone-Handling Signed-off-by: Christian Kittel <ckittel@gmx.de>
This commit is contained in:
parent
20e03c257a
commit
8d389b7e2e
|
@ -1,8 +1,6 @@
|
||||||
# OJElectronics Binding
|
# OJElectronics Binding
|
||||||
|
|
||||||
With this binding it is possible to connect [OWD5/MWD5 Thermostat](https://www.ojelectronics.com/business-areas/wifi-thermostat-owd5-prod400) of OJ Electronics.
|
With this binding it is possible to connect [OWD5/MWD5 Thermostat](https://ojelectronics.com/floorheating/products/wifi-thermostat-owd5/) of OJ Electronics.
|
||||||
|
|
||||||
At this moment all information is read only.
|
|
||||||
|
|
||||||
## Supported Things
|
## Supported Things
|
||||||
|
|
||||||
|
@ -15,9 +13,7 @@ There are two things:
|
||||||
|
|
||||||
## Discovery
|
## Discovery
|
||||||
|
|
||||||
Not supported at the moment.
|
After the ojcloud bridge is succesfully initialized all thermostats will be discovered.
|
||||||
|
|
||||||
## Thing Configuration
|
|
||||||
|
|
||||||
### OJ Electronics Bridge configuration (ojcloud)
|
### OJ Electronics Bridge configuration (ojcloud)
|
||||||
|
|
||||||
|
@ -54,7 +50,9 @@ Not supported at the moment.
|
||||||
| comfortEndTime | Date time | Date and time when the thermostat switchs back from comfort mode to automatic mode |
|
| comfortEndTime | Date time | Date and time when the thermostat switchs back from comfort mode to automatic mode |
|
||||||
| boostEndTime | Date time | Date and time when the thermostat switchs back from boost mode to automatic mode |
|
| boostEndTime | Date time | Date and time when the thermostat switchs back from boost mode to automatic mode |
|
||||||
| manualModeSetpoint | Number:Temperature | Target temperature of the manual mode |
|
| manualModeSetpoint | Number:Temperature | Target temperature of the manual mode |
|
||||||
| vacationEnabled | Switch | Vacation is enabled |
|
| vacationEnabled | Contact | Vacation is enabled |
|
||||||
|
| vacationBeginDay | Date time | Vacation start date |
|
||||||
|
| vacationEndDay | Date time | Vacation end date |
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
|
|
@ -44,4 +44,6 @@ public class BindingConstants {
|
||||||
public static final String CHANNEL_OWD5_BOOSTENDTIME = "boostEndTime";
|
public static final String CHANNEL_OWD5_BOOSTENDTIME = "boostEndTime";
|
||||||
public static final String CHANNEL_OWD5_MANUALSETPOINT = "manualSetpoint";
|
public static final String CHANNEL_OWD5_MANUALSETPOINT = "manualSetpoint";
|
||||||
public static final String CHANNEL_OWD5_VACATIONENABLED = "vacationEnabled";
|
public static final String CHANNEL_OWD5_VACATIONENABLED = "vacationEnabled";
|
||||||
|
public static final String CHANNEL_OWD5_VACATIONBEGINDAY = "vacationBeginDay";
|
||||||
|
public static final String CHANNEL_OWD5_VACATIONENDDAY = "vacationEndDay";
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.ojelectronics.internal;
|
package org.openhab.binding.ojelectronics.internal;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -20,15 +22,18 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
import org.openhab.binding.ojelectronics.internal.config.OJElectronicsBridgeConfiguration;
|
import org.openhab.binding.ojelectronics.internal.config.OJElectronicsBridgeConfiguration;
|
||||||
import org.openhab.binding.ojelectronics.internal.models.groups.GroupContentResponseModel;
|
import org.openhab.binding.ojelectronics.internal.models.groups.GroupContentResponseModel;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.services.OJDiscoveryService;
|
||||||
import org.openhab.binding.ojelectronics.internal.services.RefreshGroupContentService;
|
import org.openhab.binding.ojelectronics.internal.services.RefreshGroupContentService;
|
||||||
import org.openhab.binding.ojelectronics.internal.services.RefreshService;
|
import org.openhab.binding.ojelectronics.internal.services.RefreshService;
|
||||||
import org.openhab.binding.ojelectronics.internal.services.SignInService;
|
import org.openhab.binding.ojelectronics.internal.services.SignInService;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.services.UpdateService;
|
||||||
import org.openhab.core.thing.Bridge;
|
import org.openhab.core.thing.Bridge;
|
||||||
import org.openhab.core.thing.ChannelUID;
|
import org.openhab.core.thing.ChannelUID;
|
||||||
import org.openhab.core.thing.ThingStatus;
|
import org.openhab.core.thing.ThingStatus;
|
||||||
import org.openhab.core.thing.ThingStatusDetail;
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||||
import org.openhab.core.thing.binding.BridgeHandler;
|
import org.openhab.core.thing.binding.BridgeHandler;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||||
import org.openhab.core.types.Command;
|
import org.openhab.core.types.Command;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -45,10 +50,18 @@ public class OJCloudHandler extends BaseBridgeHandler implements BridgeHandler {
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
|
|
||||||
private @Nullable RefreshService refreshService;
|
private @Nullable RefreshService refreshService;
|
||||||
|
private @Nullable UpdateService updateService;
|
||||||
private @Nullable SignInService signInService;
|
private @Nullable SignInService signInService;
|
||||||
private OJElectronicsBridgeConfiguration configuration;
|
private OJElectronicsBridgeConfiguration configuration;
|
||||||
private @Nullable ScheduledFuture<?> signTask;
|
private @Nullable ScheduledFuture<?> signTask;
|
||||||
|
private @Nullable OJDiscoveryService discoveryService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of {@link OJCloudHandler}
|
||||||
|
*
|
||||||
|
* @param bridge {@link Bridge}
|
||||||
|
* @param httpClient HttpClient
|
||||||
|
*/
|
||||||
public OJCloudHandler(Bridge bridge, HttpClient httpClient) {
|
public OJCloudHandler(Bridge bridge, HttpClient httpClient) {
|
||||||
super(bridge);
|
super(bridge);
|
||||||
this.httpClient = httpClient;
|
this.httpClient = httpClient;
|
||||||
|
@ -100,9 +113,8 @@ public class OJCloudHandler extends BaseBridgeHandler implements BridgeHandler {
|
||||||
private void handleRefreshDone(@Nullable GroupContentResponseModel groupContentResponse,
|
private void handleRefreshDone(@Nullable GroupContentResponseModel groupContentResponse,
|
||||||
@Nullable String errorMessage) {
|
@Nullable String errorMessage) {
|
||||||
logger.trace("OJElectronicsCloudHandler.handleRefreshDone({})", groupContentResponse);
|
logger.trace("OJElectronicsCloudHandler.handleRefreshDone({})", groupContentResponse);
|
||||||
|
|
||||||
if (groupContentResponse != null && groupContentResponse.errorCode == 0) {
|
if (groupContentResponse != null && groupContentResponse.errorCode == 0) {
|
||||||
new RefreshGroupContentService(groupContentResponse.groupContents, getThing().getThings()).handle();
|
internalRefreshDone(groupContentResponse);
|
||||||
} else {
|
} else {
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
(errorMessage == null) ? "Wrong or no result model; Refreshing stoppped" : errorMessage);
|
(errorMessage == null) ? "Wrong or no result model; Refreshing stoppped" : errorMessage);
|
||||||
|
@ -113,6 +125,18 @@ public class OJCloudHandler extends BaseBridgeHandler implements BridgeHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void internalRefreshDone(GroupContentResponseModel groupContentResponse) {
|
||||||
|
new RefreshGroupContentService(groupContentResponse.groupContents, getThing().getThings()).handle();
|
||||||
|
final OJDiscoveryService discoveryService = this.discoveryService;
|
||||||
|
if (discoveryService != null) {
|
||||||
|
discoveryService.setScanResultForDiscovery(groupContentResponse.groupContents);
|
||||||
|
}
|
||||||
|
final UpdateService updateService = this.updateService;
|
||||||
|
if (updateService != null) {
|
||||||
|
updateService.updateAllThermostats(getThing().getThings());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleSignInDone(String sessionId) {
|
private void handleSignInDone(String sessionId) {
|
||||||
logger.trace("OJElectronicsCloudHandler.handleSignInDone({})", sessionId);
|
logger.trace("OJElectronicsCloudHandler.handleSignInDone({})", sessionId);
|
||||||
if (refreshService == null) {
|
if (refreshService == null) {
|
||||||
|
@ -125,9 +149,11 @@ public class OJCloudHandler extends BaseBridgeHandler implements BridgeHandler {
|
||||||
|
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
}
|
}
|
||||||
|
this.updateService = new UpdateService(configuration, httpClient, sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleUnauthorized() {
|
private void handleUnauthorized() {
|
||||||
|
logger.trace("OJElectronicsCloudHandler.handleUnauthorized()");
|
||||||
final RefreshService refreshService = this.refreshService;
|
final RefreshService refreshService = this.refreshService;
|
||||||
if (refreshService != null) {
|
if (refreshService != null) {
|
||||||
refreshService.stop();
|
refreshService.stop();
|
||||||
|
@ -136,6 +162,7 @@ public class OJCloudHandler extends BaseBridgeHandler implements BridgeHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleUnauthorizedWhileSignIn() {
|
private void handleUnauthorizedWhileSignIn() {
|
||||||
|
logger.trace("OJElectronicsCloudHandler.handleUnauthorizedWhileSignIn()");
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||||
"Could not sign in. Check user name and password.");
|
"Could not sign in. Check user name and password.");
|
||||||
final RefreshService refreshService = this.refreshService;
|
final RefreshService refreshService = this.refreshService;
|
||||||
|
@ -145,6 +172,7 @@ public class OJCloudHandler extends BaseBridgeHandler implements BridgeHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleConnectionLost() {
|
private void handleConnectionLost() {
|
||||||
|
logger.trace("OJElectronicsCloudHandler.handleConnectionLost()");
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||||
final RefreshService refreshService = this.refreshService;
|
final RefreshService refreshService = this.refreshService;
|
||||||
if (refreshService != null) {
|
if (refreshService != null) {
|
||||||
|
@ -156,4 +184,13 @@ public class OJCloudHandler extends BaseBridgeHandler implements BridgeHandler {
|
||||||
private void restartRefreshServiceAsync(long delayInSeconds) {
|
private void restartRefreshServiceAsync(long delayInSeconds) {
|
||||||
signTask = scheduler.schedule(this::ensureSignIn, delayInSeconds, TimeUnit.SECONDS);
|
signTask = scheduler.schedule(this::ensureSignIn, delayInSeconds, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDiscoveryService(OJDiscoveryService ojDiscoveryService) {
|
||||||
|
this.discoveryService = ojDiscoveryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||||
|
return Collections.singleton(OJDiscoveryService.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,13 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.ojelectronics.internal;
|
package org.openhab.binding.ojelectronics.internal;
|
||||||
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@ -23,7 +27,8 @@ import javax.measure.quantity.Temperature;
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.ojelectronics.internal.config.OJElectronicsThermostatConfiguration;
|
import org.openhab.binding.ojelectronics.internal.config.OJElectronicsThermostatConfiguration;
|
||||||
import org.openhab.binding.ojelectronics.internal.models.groups.Thermostat;
|
import org.openhab.binding.ojelectronics.internal.models.Thermostat;
|
||||||
|
import org.openhab.core.i18n.TimeZoneProvider;
|
||||||
import org.openhab.core.library.types.DateTimeType;
|
import org.openhab.core.library.types.DateTimeType;
|
||||||
import org.openhab.core.library.types.DecimalType;
|
import org.openhab.core.library.types.DecimalType;
|
||||||
import org.openhab.core.library.types.OpenClosedType;
|
import org.openhab.core.library.types.OpenClosedType;
|
||||||
|
@ -36,6 +41,8 @@ import org.openhab.core.thing.ThingStatus;
|
||||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||||
import org.openhab.core.types.Command;
|
import org.openhab.core.types.Command;
|
||||||
import org.openhab.core.types.RefreshType;
|
import org.openhab.core.types.RefreshType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link ThermostatHandler} is responsible for handling commands, which are
|
* The {@link ThermostatHandler} is responsible for handling commands, which are
|
||||||
|
@ -46,19 +53,28 @@ import org.openhab.core.types.RefreshType;
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class ThermostatHandler extends BaseThingHandler {
|
public class ThermostatHandler extends BaseThingHandler {
|
||||||
|
|
||||||
private final String serialNumber;
|
|
||||||
private @Nullable Thermostat currentThermostat;
|
|
||||||
private static final Map<Integer, String> REGULATION_MODES = createRegulationMap();
|
private static final Map<Integer, String> REGULATION_MODES = createRegulationMap();
|
||||||
|
private static final Map<String, Integer> REVERSE_REGULATION_MODES = createRegulationReverseMap();
|
||||||
|
|
||||||
|
private final String serialNumber;
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(ThermostatHandler.class);
|
||||||
private final Map<String, Consumer<Thermostat>> channelrefreshActions = createChannelRefreshActionMap();
|
private final Map<String, Consumer<Thermostat>> channelrefreshActions = createChannelRefreshActionMap();
|
||||||
|
private final Map<String, Consumer<Command>> updateThermostatValueActions = createUpdateThermostatValueActionMap();
|
||||||
|
private final TimeZoneProvider timeZoneProvider;
|
||||||
|
|
||||||
|
private LinkedList<AbstractMap.SimpleImmutableEntry<String, Command>> updatedValues = new LinkedList<>();
|
||||||
|
private @Nullable Thermostat currentThermostat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of {@link ThermostatHandler}
|
* Creates a new instance of {@link ThermostatHandler}
|
||||||
*
|
*
|
||||||
* @param thing Thing
|
* @param thing Thing
|
||||||
|
* @param timeZoneProvider Time zone
|
||||||
*/
|
*/
|
||||||
public ThermostatHandler(Thing thing) {
|
public ThermostatHandler(Thing thing, TimeZoneProvider timeZoneProvider) {
|
||||||
super(thing);
|
super(thing);
|
||||||
serialNumber = getConfigAs(OJElectronicsThermostatConfiguration.class).serialNumber;
|
serialNumber = getConfigAs(OJElectronicsThermostatConfiguration.class).serialNumber;
|
||||||
|
this.timeZoneProvider = timeZoneProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,7 +94,14 @@ public class ThermostatHandler extends BaseThingHandler {
|
||||||
if (command instanceof RefreshType) {
|
if (command instanceof RefreshType) {
|
||||||
final Thermostat thermostat = currentThermostat;
|
final Thermostat thermostat = currentThermostat;
|
||||||
if (thermostat != null && channelrefreshActions.containsKey(channelUID.getId())) {
|
if (thermostat != null && channelrefreshActions.containsKey(channelUID.getId())) {
|
||||||
channelrefreshActions.get(channelUID.getId()).accept(thermostat);
|
final @Nullable Consumer<Thermostat> consumer = channelrefreshActions.get(channelUID.getId());
|
||||||
|
if (consumer != null) {
|
||||||
|
consumer.accept(thermostat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
synchronized (this) {
|
||||||
|
updatedValues.add(new AbstractMap.SimpleImmutableEntry<String, Command>(channelUID.getId(), command));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,19 +124,65 @@ public class ThermostatHandler extends BaseThingHandler {
|
||||||
channelrefreshActions.forEach((channelUID, action) -> action.accept(thermostat));
|
channelrefreshActions.forEach((channelUID, action) -> action.accept(thermostat));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a {@link Thermostat} with changed values or null if nothing has changed
|
||||||
|
*
|
||||||
|
* @return The changed {@link Thermostat}
|
||||||
|
*/
|
||||||
|
public @Nullable Thermostat tryHandleAndGetUpdatedThermostat() {
|
||||||
|
final LinkedList<SimpleImmutableEntry<String, Command>> updatedValues = this.updatedValues;
|
||||||
|
if (updatedValues.size() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
this.updatedValues = new LinkedList<>();
|
||||||
|
updatedValues.forEach(item -> {
|
||||||
|
if (updateThermostatValueActions.containsKey(item.getKey())) {
|
||||||
|
final @Nullable Consumer<Command> consumer = updateThermostatValueActions.get(item.getKey());
|
||||||
|
if (consumer != null) {
|
||||||
|
consumer.accept(item.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return currentThermostat;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateManualSetpoint(Thermostat thermostat) {
|
private void updateManualSetpoint(Thermostat thermostat) {
|
||||||
updateState(BindingConstants.CHANNEL_OWD5_MANUALSETPOINT,
|
updateState(BindingConstants.CHANNEL_OWD5_MANUALSETPOINT,
|
||||||
new QuantityType<Temperature>(thermostat.manualModeSetpoint / (double) 100, SIUnits.CELSIUS));
|
new QuantityType<Temperature>(thermostat.manualModeSetpoint / (double) 100, SIUnits.CELSIUS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateManualSetpoint(Command command) {
|
||||||
|
if (command instanceof QuantityType<?>) {
|
||||||
|
currentThermostat.manualModeSetpoint = (int) (((QuantityType<?>) command).floatValue() * 100);
|
||||||
|
} else {
|
||||||
|
logger.warn("Unable to set value {}", command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateBoostEndTime(Thermostat thermostat) {
|
private void updateBoostEndTime(Thermostat thermostat) {
|
||||||
updateState(BindingConstants.CHANNEL_OWD5_BOOSTENDTIME,
|
updateState(BindingConstants.CHANNEL_OWD5_BOOSTENDTIME, new DateTimeType(
|
||||||
new DateTimeType(ZonedDateTime.ofInstant(thermostat.boostEndTime.toInstant(), ZoneId.systemDefault())));
|
ZonedDateTime.ofInstant(thermostat.boostEndTime.toInstant(), timeZoneProvider.getTimeZone())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBoostEndTime(Command command) {
|
||||||
|
if (command instanceof DateTimeType) {
|
||||||
|
currentThermostat.boostEndTime = Date.from(((DateTimeType) command).getZonedDateTime().toInstant());
|
||||||
|
} else {
|
||||||
|
logger.warn("Unable to set value {}", command);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateComfortEndTime(Thermostat thermostat) {
|
private void updateComfortEndTime(Thermostat thermostat) {
|
||||||
updateState(BindingConstants.CHANNEL_OWD5_COMFORTENDTIME, new DateTimeType(
|
updateState(BindingConstants.CHANNEL_OWD5_COMFORTENDTIME, new DateTimeType(
|
||||||
ZonedDateTime.ofInstant(thermostat.comfortEndTime.toInstant(), ZoneId.systemDefault())));
|
ZonedDateTime.ofInstant(thermostat.comfortEndTime.toInstant(), timeZoneProvider.getTimeZone())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateComfortEndTime(Command command) {
|
||||||
|
if (command instanceof DateTimeType) {
|
||||||
|
currentThermostat.comfortEndTime = Date.from(((DateTimeType) command).getZonedDateTime().toInstant());
|
||||||
|
} else {
|
||||||
|
logger.warn("Unable to set value {}", command);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateComfortSetpoint(Thermostat thermostat) {
|
private void updateComfortSetpoint(Thermostat thermostat) {
|
||||||
|
@ -121,11 +190,30 @@ public class ThermostatHandler extends BaseThingHandler {
|
||||||
new QuantityType<Temperature>(thermostat.comfortSetpoint / (double) 100, SIUnits.CELSIUS));
|
new QuantityType<Temperature>(thermostat.comfortSetpoint / (double) 100, SIUnits.CELSIUS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateComfortSetpoint(Command command) {
|
||||||
|
if (command instanceof QuantityType<?>) {
|
||||||
|
currentThermostat.comfortSetpoint = (int) (((QuantityType<?>) command).floatValue() * 100);
|
||||||
|
} else {
|
||||||
|
logger.warn("Unable to set value {}", command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateRegulationMode(Thermostat thermostat) {
|
private void updateRegulationMode(Thermostat thermostat) {
|
||||||
updateState(BindingConstants.CHANNEL_OWD5_REGULATIONMODE,
|
updateState(BindingConstants.CHANNEL_OWD5_REGULATIONMODE,
|
||||||
StringType.valueOf(getRegulationMode(thermostat.regulationMode)));
|
StringType.valueOf(getRegulationMode(thermostat.regulationMode)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateRegulationMode(Command command) {
|
||||||
|
if (command instanceof StringType && (REVERSE_REGULATION_MODES.containsKey(command.toString().toLowerCase()))) {
|
||||||
|
final @Nullable Integer mode = REVERSE_REGULATION_MODES.get(command.toString().toLowerCase());
|
||||||
|
if (mode != null) {
|
||||||
|
currentThermostat.regulationMode = mode;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warn("Unable to set value {}", command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateThermostatName(Thermostat thermostat) {
|
private void updateThermostatName(Thermostat thermostat) {
|
||||||
updateState(BindingConstants.CHANNEL_OWD5_THERMOSTATNAME, StringType.valueOf(thermostat.thermostatName));
|
updateState(BindingConstants.CHANNEL_OWD5_THERMOSTATNAME, StringType.valueOf(thermostat.thermostatName));
|
||||||
}
|
}
|
||||||
|
@ -158,6 +246,43 @@ public class ThermostatHandler extends BaseThingHandler {
|
||||||
updateState(BindingConstants.CHANNEL_OWD5_GROUPNAME, StringType.valueOf(thermostat.groupName));
|
updateState(BindingConstants.CHANNEL_OWD5_GROUPNAME, StringType.valueOf(thermostat.groupName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateVacationEnabled(Thermostat thermostat) {
|
||||||
|
updateState(BindingConstants.CHANNEL_OWD5_VACATIONENABLED,
|
||||||
|
thermostat.online ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateVacationBeginDay(Thermostat thermostat) {
|
||||||
|
updateState(BindingConstants.CHANNEL_OWD5_VACATIONBEGINDAY,
|
||||||
|
new DateTimeType(
|
||||||
|
ZonedDateTime.ofInstant(thermostat.vacationBeginDay.toInstant(), timeZoneProvider.getTimeZone())
|
||||||
|
.truncatedTo(ChronoUnit.DAYS)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateVacationBeginDay(Command command) {
|
||||||
|
if (command instanceof DateTimeType) {
|
||||||
|
currentThermostat.vacationBeginDay = Date
|
||||||
|
.from(((DateTimeType) command).getZonedDateTime().toInstant().truncatedTo(ChronoUnit.DAYS));
|
||||||
|
} else {
|
||||||
|
logger.warn("Unable to set value {}", command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateVacationEndDay(Thermostat thermostat) {
|
||||||
|
updateState(BindingConstants.CHANNEL_OWD5_VACATIONENDDAY,
|
||||||
|
new DateTimeType(
|
||||||
|
ZonedDateTime.ofInstant(thermostat.vacationEndDay.toInstant(), timeZoneProvider.getTimeZone())
|
||||||
|
.truncatedTo(ChronoUnit.DAYS)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateVacationEndDay(Command command) {
|
||||||
|
if (command instanceof DateTimeType) {
|
||||||
|
currentThermostat.vacationEndDay = Date
|
||||||
|
.from(((DateTimeType) command).getZonedDateTime().toInstant().truncatedTo(ChronoUnit.DAYS));
|
||||||
|
} else {
|
||||||
|
logger.warn("Unable to set value {}", command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private @Nullable String getRegulationMode(int regulationMode) {
|
private @Nullable String getRegulationMode(int regulationMode) {
|
||||||
return REGULATION_MODES.get(regulationMode);
|
return REGULATION_MODES.get(regulationMode);
|
||||||
}
|
}
|
||||||
|
@ -174,6 +299,18 @@ public class ThermostatHandler extends BaseThingHandler {
|
||||||
return map;
|
return map;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static Map<String, Integer> createRegulationReverseMap() {
|
||||||
|
HashMap<String, Integer> map = new HashMap<>();
|
||||||
|
map.put("auto", 1);
|
||||||
|
map.put("comfort", 2);
|
||||||
|
map.put("manual", 3);
|
||||||
|
map.put("vacation", 4);
|
||||||
|
map.put("frostprotection", 6);
|
||||||
|
map.put("boost", 8);
|
||||||
|
map.put("eco", 9);
|
||||||
|
return map;
|
||||||
|
};
|
||||||
|
|
||||||
private Map<String, Consumer<Thermostat>> createChannelRefreshActionMap() {
|
private Map<String, Consumer<Thermostat>> createChannelRefreshActionMap() {
|
||||||
HashMap<String, Consumer<Thermostat>> map = new HashMap<>();
|
HashMap<String, Consumer<Thermostat>> map = new HashMap<>();
|
||||||
map.put(BindingConstants.CHANNEL_OWD5_GROUPNAME, this::updateGroupName);
|
map.put(BindingConstants.CHANNEL_OWD5_GROUPNAME, this::updateGroupName);
|
||||||
|
@ -188,6 +325,21 @@ public class ThermostatHandler extends BaseThingHandler {
|
||||||
map.put(BindingConstants.CHANNEL_OWD5_COMFORTENDTIME, this::updateComfortEndTime);
|
map.put(BindingConstants.CHANNEL_OWD5_COMFORTENDTIME, this::updateComfortEndTime);
|
||||||
map.put(BindingConstants.CHANNEL_OWD5_BOOSTENDTIME, this::updateBoostEndTime);
|
map.put(BindingConstants.CHANNEL_OWD5_BOOSTENDTIME, this::updateBoostEndTime);
|
||||||
map.put(BindingConstants.CHANNEL_OWD5_MANUALSETPOINT, this::updateManualSetpoint);
|
map.put(BindingConstants.CHANNEL_OWD5_MANUALSETPOINT, this::updateManualSetpoint);
|
||||||
|
map.put(BindingConstants.CHANNEL_OWD5_VACATIONENABLED, this::updateVacationEnabled);
|
||||||
|
map.put(BindingConstants.CHANNEL_OWD5_VACATIONBEGINDAY, this::updateVacationBeginDay);
|
||||||
|
map.put(BindingConstants.CHANNEL_OWD5_VACATIONENDDAY, this::updateVacationEndDay);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Consumer<Command>> createUpdateThermostatValueActionMap() {
|
||||||
|
HashMap<String, Consumer<Command>> map = new HashMap<>();
|
||||||
|
map.put(BindingConstants.CHANNEL_OWD5_REGULATIONMODE, this::updateRegulationMode);
|
||||||
|
map.put(BindingConstants.CHANNEL_OWD5_MANUALSETPOINT, this::updateManualSetpoint);
|
||||||
|
map.put(BindingConstants.CHANNEL_OWD5_BOOSTENDTIME, this::updateBoostEndTime);
|
||||||
|
map.put(BindingConstants.CHANNEL_OWD5_COMFORTENDTIME, this::updateComfortEndTime);
|
||||||
|
map.put(BindingConstants.CHANNEL_OWD5_COMFORTSETPOINT, this::updateComfortSetpoint);
|
||||||
|
map.put(BindingConstants.CHANNEL_OWD5_VACATIONBEGINDAY, this::updateVacationBeginDay);
|
||||||
|
map.put(BindingConstants.CHANNEL_OWD5_VACATIONENDDAY, this::updateVacationEndDay);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,15 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.core.i18n.TimeZoneProvider;
|
||||||
import org.openhab.core.thing.Thing;
|
import org.openhab.core.thing.Thing;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||||
import org.openhab.core.thing.binding.ThingHandler;
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link ThermostatHandlerFactory} is responsible for creating {@link OJElectronicsThermostatHandler}.
|
* The {@link ThermostatHandlerFactory} is responsible for creating {@link OJElectronicsThermostatHandler}.
|
||||||
|
@ -36,6 +39,17 @@ import org.osgi.service.component.annotations.Component;
|
||||||
public class ThermostatHandlerFactory extends BaseThingHandlerFactory {
|
public class ThermostatHandlerFactory extends BaseThingHandlerFactory {
|
||||||
|
|
||||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_OWD5);
|
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_OWD5);
|
||||||
|
private final TimeZoneProvider timeZoneProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new factory
|
||||||
|
*
|
||||||
|
* @param httpClientFactory Factory for HttpClient
|
||||||
|
*/
|
||||||
|
@Activate
|
||||||
|
public ThermostatHandlerFactory(@Reference TimeZoneProvider timeZoneProvider) {
|
||||||
|
this.timeZoneProvider = timeZoneProvider;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supported things of this factory.
|
* Supported things of this factory.
|
||||||
|
@ -50,7 +64,7 @@ public class ThermostatHandlerFactory extends BaseThingHandlerFactory {
|
||||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||||
|
|
||||||
if (THING_TYPE_OWD5.equals(thingTypeUID)) {
|
if (THING_TYPE_OWD5.equals(thingTypeUID)) {
|
||||||
return new ThermostatHandler(thing);
|
return new ThermostatHandler(thing, timeZoneProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -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.ojelectronics.internal.common;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
import com.google.gson.FieldNamingPolicy;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for Gson
|
||||||
|
*
|
||||||
|
* @author Christian Kittel - Initial Contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public final class OJGSonBuilder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a correct initialized {@link Gson}
|
||||||
|
*
|
||||||
|
* @return {@link GSon}
|
||||||
|
*/
|
||||||
|
public static Gson getGSon() {
|
||||||
|
return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).setPrettyPrinting()
|
||||||
|
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.ojelectronics.internal.models;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base model for all requests
|
||||||
|
*
|
||||||
|
* @author Christian Kittel - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public abstract class RequestModelBase {
|
||||||
|
|
||||||
|
@SerializedName("APIKEY")
|
||||||
|
public String apiKey = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add API-Key
|
||||||
|
*
|
||||||
|
* @param apiKey API-Key
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
public RequestModelBase withApiKey(String apiKey) {
|
||||||
|
this.apiKey = apiKey;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.ojelectronics.internal.models;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base model for all responses
|
||||||
|
*
|
||||||
|
* @author Christian Kittel - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public abstract class ResponseModelBase {
|
||||||
|
|
||||||
|
public int errorCode;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* 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.ojelectronics.internal.models;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response model without additional properties
|
||||||
|
*
|
||||||
|
* @author Christian Kittel - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SimpleResponseModel extends ResponseModelBase {
|
||||||
|
}
|
|
@ -10,12 +10,13 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.ojelectronics.internal.models.groups;
|
package org.openhab.binding.ojelectronics.internal.models;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.groups.Schedule;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
|
@ -17,6 +17,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.Thermostat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model for content of a group
|
* Model for content of a group
|
||||||
|
|
|
@ -16,6 +16,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.ResponseModelBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model for the response of a content group
|
* Model for the response of a content group
|
||||||
|
@ -23,9 +24,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
* @author Christian Kittel - Initial contribution
|
* @author Christian Kittel - Initial contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class GroupContentResponseModel {
|
public class GroupContentResponseModel extends ResponseModelBase {
|
||||||
|
|
||||||
public List<GroupContent> groupContents = new ArrayList<GroupContent>();
|
public List<GroupContent> groupContents = new ArrayList<GroupContent>();
|
||||||
|
|
||||||
public int errorCode;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.ojelectronics.internal.models.thermostat;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.RequestModelBase;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.Thermostat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for updating a thermostat
|
||||||
|
*
|
||||||
|
* @author Christian Kittel - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class UpdateThermostatRequestModel extends RequestModelBase {
|
||||||
|
|
||||||
|
public UpdateThermostatRequestModel(Thermostat thermostat) {
|
||||||
|
setThermostat = thermostat;
|
||||||
|
thermostatID = thermostat.serialNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thermostat setThermostat;
|
||||||
|
|
||||||
|
public String thermostatID;
|
||||||
|
}
|
|
@ -13,8 +13,7 @@
|
||||||
package org.openhab.binding.ojelectronics.internal.models.userprofile;
|
package org.openhab.binding.ojelectronics.internal.models.userprofile;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.RequestModelBase;
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model for signing sin
|
* Model for signing sin
|
||||||
|
@ -22,10 +21,7 @@ import com.google.gson.annotations.SerializedName;
|
||||||
* @author Christian Kittel - Initial contribution
|
* @author Christian Kittel - Initial contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class PostSignInQueryModel {
|
public class PostSignInQueryModel extends RequestModelBase {
|
||||||
|
|
||||||
@SerializedName("APIKEY")
|
|
||||||
public String apiKey = "";
|
|
||||||
|
|
||||||
public String userName = "";
|
public String userName = "";
|
||||||
|
|
||||||
|
@ -35,17 +31,6 @@ public class PostSignInQueryModel {
|
||||||
|
|
||||||
public int clientSWVersion;
|
public int clientSWVersion;
|
||||||
|
|
||||||
/**
|
|
||||||
* Add API-Key
|
|
||||||
*
|
|
||||||
* @param apiKey API-Key
|
|
||||||
* @return Model
|
|
||||||
*/
|
|
||||||
public PostSignInQueryModel withApiKey(String apiKey) {
|
|
||||||
this.apiKey = apiKey;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add User-Name
|
* Add User-Name
|
||||||
*
|
*
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package org.openhab.binding.ojelectronics.internal.models.userprofile;
|
package org.openhab.binding.ojelectronics.internal.models.userprofile;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.ResponseModelBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response-Model after signing in
|
* Response-Model after signing in
|
||||||
|
@ -20,26 +21,9 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
* @author Christian Kittel - Initial Contribution
|
* @author Christian Kittel - Initial Contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class PostSignInResponseModel {
|
public class PostSignInResponseModel extends ResponseModelBase {
|
||||||
|
|
||||||
public String sessionId = "";
|
public String sessionId = "";
|
||||||
|
|
||||||
public String userName = "";
|
public String userName = "";
|
||||||
|
|
||||||
public int errorCode;
|
|
||||||
|
|
||||||
public PostSignInResponseModel withSessionId(String sessionId) {
|
|
||||||
this.sessionId = sessionId;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PostSignInResponseModel withUserName(String userName) {
|
|
||||||
this.userName = userName;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PostSignInResponseModel withErrorCode(int errorCode) {
|
|
||||||
this.errorCode = errorCode;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/**
|
||||||
|
* 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.ojelectronics.internal.services;
|
||||||
|
|
||||||
|
import static org.openhab.binding.ojelectronics.internal.BindingConstants.*;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.OJCloudHandler;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.groups.GroupContent;
|
||||||
|
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||||
|
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.osgi.service.component.annotations.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DiscoveryService for OJ Components
|
||||||
|
*
|
||||||
|
* @author Christian Kittel - Initial Contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.ojelectronics")
|
||||||
|
public final class OJDiscoveryService extends AbstractDiscoveryService
|
||||||
|
implements DiscoveryService, ThingHandlerService {
|
||||||
|
|
||||||
|
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_OJCLOUD);
|
||||||
|
private @Nullable OJCloudHandler bridgeHandler;
|
||||||
|
private @Nullable Collection<GroupContent> groupContents;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of {@link OJDiscoveryService}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public OJDiscoveryService() throws IllegalArgumentException {
|
||||||
|
super(SUPPORTED_THING_TYPES_UIDS, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the scan result for discovering
|
||||||
|
*
|
||||||
|
* @param groupContents Content from API
|
||||||
|
*/
|
||||||
|
public void setScanResultForDiscovery(List<GroupContent> groupContents) {
|
||||||
|
this.groupContents = groupContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startScan() {
|
||||||
|
final OJCloudHandler bridgeHandler = this.bridgeHandler;
|
||||||
|
final Collection<GroupContent> groupContents = this.groupContents;
|
||||||
|
if (groupContents != null && bridgeHandler != null) {
|
||||||
|
groupContents.stream().flatMap(content -> content.thermostats.stream())
|
||||||
|
.forEach(thermostat -> thingDiscovered(bridgeHandler.getThing().getUID(), thermostat.serialNumber));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||||
|
if (handler instanceof OJCloudHandler) {
|
||||||
|
final OJCloudHandler bridgeHandler = (OJCloudHandler) handler;
|
||||||
|
this.bridgeHandler = bridgeHandler;
|
||||||
|
bridgeHandler.setDiscoveryService(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable ThingHandler getThingHandler() {
|
||||||
|
return bridgeHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deactivate() {
|
||||||
|
super.deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void thingDiscovered(ThingUID bridgeUID, String serialNumber) {
|
||||||
|
thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_TYPE_OWD5, bridgeUID, serialNumber))
|
||||||
|
.withBridge(bridgeUID).withRepresentationProperty("serialNumber")
|
||||||
|
.withProperty("serialNumber", serialNumber).withLabel("Thermostat " + serialNumber).build());
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,8 +16,8 @@ import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.openhab.binding.ojelectronics.internal.ThermostatHandler;
|
import org.openhab.binding.ojelectronics.internal.ThermostatHandler;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.Thermostat;
|
||||||
import org.openhab.binding.ojelectronics.internal.models.groups.GroupContent;
|
import org.openhab.binding.ojelectronics.internal.models.groups.GroupContent;
|
||||||
import org.openhab.binding.ojelectronics.internal.models.groups.Thermostat;
|
|
||||||
import org.openhab.core.thing.Thing;
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,14 +25,13 @@ import org.eclipse.jetty.client.api.Result;
|
||||||
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
||||||
import org.eclipse.jetty.http.HttpMethod;
|
import org.eclipse.jetty.http.HttpMethod;
|
||||||
import org.eclipse.jetty.http.HttpStatus;
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.common.OJGSonBuilder;
|
||||||
import org.openhab.binding.ojelectronics.internal.config.OJElectronicsBridgeConfiguration;
|
import org.openhab.binding.ojelectronics.internal.config.OJElectronicsBridgeConfiguration;
|
||||||
import org.openhab.binding.ojelectronics.internal.models.groups.GroupContentResponseModel;
|
import org.openhab.binding.ojelectronics.internal.models.groups.GroupContentResponseModel;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.gson.FieldNamingPolicy;
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,7 +45,7 @@ public final class RefreshService implements AutoCloseable {
|
||||||
private final OJElectronicsBridgeConfiguration config;
|
private final OJElectronicsBridgeConfiguration config;
|
||||||
private final Logger logger = LoggerFactory.getLogger(RefreshService.class);
|
private final Logger logger = LoggerFactory.getLogger(RefreshService.class);
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
private final Gson gson = createGson();
|
private final Gson gson = OJGSonBuilder.getGSon();
|
||||||
|
|
||||||
private final ScheduledExecutorService schedulerService;
|
private final ScheduledExecutorService schedulerService;
|
||||||
|
|
||||||
|
@ -62,6 +61,7 @@ public final class RefreshService implements AutoCloseable {
|
||||||
*
|
*
|
||||||
* @param config Configuration of the bridge
|
* @param config Configuration of the bridge
|
||||||
* @param httpClient HTTP client
|
* @param httpClient HTTP client
|
||||||
|
* @param updateService Service to update the thermostat in the cloud
|
||||||
*/
|
*/
|
||||||
public RefreshService(OJElectronicsBridgeConfiguration config, HttpClient httpClient,
|
public RefreshService(OJElectronicsBridgeConfiguration config, HttpClient httpClient,
|
||||||
ScheduledExecutorService schedulerService) {
|
ScheduledExecutorService schedulerService) {
|
||||||
|
@ -103,11 +103,6 @@ public final class RefreshService implements AutoCloseable {
|
||||||
this.scheduler = null;
|
this.scheduler = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Gson createGson() {
|
|
||||||
return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).setPrettyPrinting()
|
|
||||||
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refresh() {
|
private void refresh() {
|
||||||
final String sessionId = this.sessionId;
|
final String sessionId = this.sessionId;
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
|
@ -124,6 +119,8 @@ public final class RefreshService implements AutoCloseable {
|
||||||
if (unauthorized != null) {
|
if (unauthorized != null) {
|
||||||
unauthorized.run();
|
unauthorized.run();
|
||||||
}
|
}
|
||||||
|
} else if (result.getResponse().getStatus() == HttpStatus.FORBIDDEN_403) {
|
||||||
|
handleConnectionLost();
|
||||||
} else {
|
} else {
|
||||||
handleRefreshDone(getContentAsString());
|
handleRefreshDone(getContentAsString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,13 @@ import org.eclipse.jetty.client.api.Result;
|
||||||
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
||||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||||
import org.eclipse.jetty.http.HttpHeader;
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.common.OJGSonBuilder;
|
||||||
import org.openhab.binding.ojelectronics.internal.config.OJElectronicsBridgeConfiguration;
|
import org.openhab.binding.ojelectronics.internal.config.OJElectronicsBridgeConfiguration;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.RequestModelBase;
|
||||||
import org.openhab.binding.ojelectronics.internal.models.userprofile.PostSignInQueryModel;
|
import org.openhab.binding.ojelectronics.internal.models.userprofile.PostSignInQueryModel;
|
||||||
import org.openhab.binding.ojelectronics.internal.models.userprofile.PostSignInResponseModel;
|
import org.openhab.binding.ojelectronics.internal.models.userprofile.PostSignInResponseModel;
|
||||||
|
|
||||||
import com.google.gson.FieldNamingPolicy;
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the sign in process.
|
* Handles the sign in process.
|
||||||
|
@ -38,7 +38,7 @@ import com.google.gson.GsonBuilder;
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class SignInService {
|
public class SignInService {
|
||||||
|
|
||||||
private final Gson gson = createGson();
|
private final Gson gson = OJGSonBuilder.getGSon();
|
||||||
|
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
private final OJElectronicsBridgeConfiguration config;
|
private final OJElectronicsBridgeConfiguration config;
|
||||||
|
@ -79,7 +79,7 @@ public class SignInService {
|
||||||
}
|
}
|
||||||
PostSignInResponseModel signInModel = gson.fromJson(getContentAsString(),
|
PostSignInResponseModel signInModel = gson.fromJson(getContentAsString(),
|
||||||
PostSignInResponseModel.class);
|
PostSignInResponseModel.class);
|
||||||
if (signInModel.errorCode != 0 || signInModel.sessionId.equals("")) {
|
if (signInModel == null || signInModel.errorCode != 0 || signInModel.sessionId.equals("")) {
|
||||||
unauthorized.run();
|
unauthorized.run();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -88,12 +88,8 @@ public class SignInService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Gson createGson() {
|
private RequestModelBase getPostSignInQueryModel() {
|
||||||
return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).setPrettyPrinting().create();
|
return new PostSignInQueryModel().withClientSWVersion(config.softwareVersion).withCustomerId(config.customerId)
|
||||||
}
|
.withUserName(config.userName).withPassword(config.password).withApiKey(config.apiKey);
|
||||||
|
|
||||||
private PostSignInQueryModel getPostSignInQueryModel() {
|
|
||||||
return new PostSignInQueryModel().withApiKey(config.apiKey).withClientSWVersion(config.softwareVersion)
|
|
||||||
.withCustomerId(config.customerId).withUserName(config.userName).withPassword(config.password);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
/**
|
||||||
|
* 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.ojelectronics.internal.services;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.eclipse.jetty.client.api.Request;
|
||||||
|
import org.eclipse.jetty.client.api.Result;
|
||||||
|
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
||||||
|
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||||
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.ThermostatHandler;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.common.OJGSonBuilder;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.config.OJElectronicsBridgeConfiguration;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.SimpleResponseModel;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.Thermostat;
|
||||||
|
import org.openhab.binding.ojelectronics.internal.models.thermostat.UpdateThermostatRequestModel;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the update of the devices of a session
|
||||||
|
*
|
||||||
|
* @author Christian Kittel - Initial Contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public final class UpdateService {
|
||||||
|
|
||||||
|
private final Gson gson = OJGSonBuilder.getGSon();
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(UpdateService.class);
|
||||||
|
|
||||||
|
private final String sessionId;
|
||||||
|
private final HttpClient httpClient;
|
||||||
|
private final OJElectronicsBridgeConfiguration configuration;
|
||||||
|
|
||||||
|
public UpdateService(OJElectronicsBridgeConfiguration configuration, HttpClient httpClient, String sessionId) {
|
||||||
|
this.configuration = configuration;
|
||||||
|
this.httpClient = httpClient;
|
||||||
|
this.sessionId = sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends all changes of all {@link ThermostatHandler} to the API
|
||||||
|
*
|
||||||
|
* @param things
|
||||||
|
*/
|
||||||
|
public void updateAllThermostats(List<Thing> things) {
|
||||||
|
things.stream().filter(thing -> thing.getHandler() instanceof ThermostatHandler)
|
||||||
|
.map(thing -> (ThermostatHandler) thing.getHandler())
|
||||||
|
.map(handler -> handler.tryHandleAndGetUpdatedThermostat()).forEach(this::updateThermostat);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateThermostat(@Nullable Thermostat thermostat) {
|
||||||
|
if (thermostat == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Request request = httpClient.POST(configuration.apiUrl + "/Thermostat/UpdateThermostat")
|
||||||
|
.param("sessionid", sessionId).header(HttpHeader.CONTENT_TYPE, "application/json")
|
||||||
|
.content(new StringContentProvider(
|
||||||
|
gson.toJson(new UpdateThermostatRequestModel(thermostat).withApiKey(configuration.apiKey))));
|
||||||
|
|
||||||
|
request.send(new BufferingResponseListener() {
|
||||||
|
@Override
|
||||||
|
public void onComplete(@Nullable Result result) {
|
||||||
|
if (result != null) {
|
||||||
|
logger.trace("onComplete {}", result);
|
||||||
|
if (result.isFailed()) {
|
||||||
|
logger.warn("updateThermostat failed {}", thermostat);
|
||||||
|
}
|
||||||
|
SimpleResponseModel responseModel = gson.fromJson(getContentAsString(), SimpleResponseModel.class);
|
||||||
|
if (responseModel == null) {
|
||||||
|
logger.warn("updateThermostat failed with empty result {}", thermostat);
|
||||||
|
} else if (responseModel.errorCode != 0) {
|
||||||
|
logger.warn("updateThermostat failed with errorCode {} {}", responseModel.errorCode,
|
||||||
|
thermostat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,3 +36,5 @@ channel-type.ojelectronics.comfortEndTime.label = Komfort-Endzeit
|
||||||
channel-type.ojelectronics.boostEndTime.label = Boost Endzeit
|
channel-type.ojelectronics.boostEndTime.label = Boost Endzeit
|
||||||
channel-type.ojelectronics.manualSetpoint.label = manuelle Endzeit
|
channel-type.ojelectronics.manualSetpoint.label = manuelle Endzeit
|
||||||
channel-type.ojelectronics.vacationEnabled.label = Urlausbmodus aktiviert
|
channel-type.ojelectronics.vacationEnabled.label = Urlausbmodus aktiviert
|
||||||
|
channel-type.ojelectronics.vacationBeginDay.label = Start des Urlausbmodus
|
||||||
|
channel-type.ojelectronics.vacationEndDay.label = Ende des Urlausbmodus
|
||||||
|
|
|
@ -68,10 +68,13 @@
|
||||||
<channel id="boostEndTime" typeId="boostEndTime"/>
|
<channel id="boostEndTime" typeId="boostEndTime"/>
|
||||||
<channel id="manualSetpoint" typeId="manualSetpoint"/>
|
<channel id="manualSetpoint" typeId="manualSetpoint"/>
|
||||||
<channel id="vacationEnabled" typeId="vacationEnabled"/>
|
<channel id="vacationEnabled" typeId="vacationEnabled"/>
|
||||||
|
<channel id="vacationBeginDay" typeId="vacationBeginDay"/>
|
||||||
|
<channel id="vacationEndDay" typeId="vacationEndDay"/>
|
||||||
</channels>
|
</channels>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="vendor">OJ Electronics</property>
|
<property name="vendor">OJ Electronics</property>
|
||||||
</properties>
|
</properties>
|
||||||
|
<representation-property>serialNumber</representation-property>
|
||||||
<config-description>
|
<config-description>
|
||||||
<parameter name="serialNumber" type="text" required="true">
|
<parameter name="serialNumber" type="text" required="true">
|
||||||
<label>Serial Number</label>
|
<label>Serial Number</label>
|
||||||
|
@ -119,7 +122,7 @@
|
||||||
<channel-type id="regulationMode">
|
<channel-type id="regulationMode">
|
||||||
<item-type>String</item-type>
|
<item-type>String</item-type>
|
||||||
<label>Regulation Mode</label>
|
<label>Regulation Mode</label>
|
||||||
<state readOnly="true">
|
<state>
|
||||||
<options>
|
<options>
|
||||||
<option value="auto">Auto</option>
|
<option value="auto">Auto</option>
|
||||||
<option value="comfort">Comfort</option>
|
<option value="comfort">Comfort</option>
|
||||||
|
@ -135,27 +138,33 @@
|
||||||
<item-type>Number:Temperature</item-type>
|
<item-type>Number:Temperature</item-type>
|
||||||
<label>Comfort Set Point Temperature</label>
|
<label>Comfort Set Point Temperature</label>
|
||||||
<category>Temperature</category>
|
<category>Temperature</category>
|
||||||
<state pattern="%.1f %unit%" readOnly="true"/>
|
<state pattern="%.1f %unit%"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
<channel-type id="comfortEndTime">
|
<channel-type id="comfortEndTime">
|
||||||
<item-type>DateTime</item-type>
|
<item-type>DateTime</item-type>
|
||||||
<label>End Time of Comfort Mode</label>
|
<label>End Time of Comfort Mode</label>
|
||||||
<state readOnly="true"/>
|
|
||||||
</channel-type>
|
</channel-type>
|
||||||
<channel-type id="boostEndTime">
|
<channel-type id="boostEndTime">
|
||||||
<item-type>DateTime</item-type>
|
<item-type>DateTime</item-type>
|
||||||
<label>End Time of Boost Mode</label>
|
<label>End Time of Boost Mode</label>
|
||||||
<state readOnly="true"/>
|
|
||||||
</channel-type>
|
</channel-type>
|
||||||
<channel-type id="manualSetpoint">
|
<channel-type id="manualSetpoint">
|
||||||
<item-type>Number:Temperature</item-type>
|
<item-type>Number:Temperature</item-type>
|
||||||
<label>Manual Set Point Temperature</label>
|
<label>Manual Set Point Temperature</label>
|
||||||
<category>Temperature</category>
|
<category>Temperature</category>
|
||||||
<state pattern="%.1f %unit%" readOnly="true"/>
|
<state pattern="%.1f %unit%"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
<channel-type id="vacationEnabled">
|
<channel-type id="vacationEnabled">
|
||||||
<item-type>Switch</item-type>
|
<item-type>Switch</item-type>
|
||||||
<label>Vacation Mode Enabled</label>
|
<label>Vacation Mode Enabled</label>
|
||||||
<state readOnly="true"/>
|
<state readOnly="true"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
<channel-type id="vacationBeginDay">
|
||||||
|
<item-type>Switch</item-type>
|
||||||
|
<label>Vacation Begin Day</label>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="vacationEndDay">
|
||||||
|
<item-type>Switch</item-type>
|
||||||
|
<label>Vacation End Day</label>
|
||||||
|
</channel-type>
|
||||||
</thing:thing-descriptions>
|
</thing:thing-descriptions>
|
||||||
|
|
Loading…
Reference in New Issue