mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[miele] Migrate start channel to full DateTime channel and add end channel (#13393)
* Migrate start/finish channels to full DateTime channels * Unmark start and duration as advanced channels * Add end channel Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
parent
96b77ed541
commit
af0ac6e474
@ -125,6 +125,7 @@ Channels available for each appliance type are listed below.
|
||||
| phase | String | Read | Current phase of the program running on the appliance |
|
||||
| rawPhase | Number | Read | Current phase of the program running on the appliance as raw number |
|
||||
| start | DateTime | Read | Programmed start time of the program |
|
||||
| end | DateTime | Read | End time of the program (programmed or running) |
|
||||
| duration | DateTime | Read | Duration of the program running on the appliance |
|
||||
| elapsed | DateTime | Read | Time elapsed in the program running on the appliance |
|
||||
| finish | DateTime | Read | Time to finish the program running on the appliance |
|
||||
@ -237,6 +238,7 @@ Channels available for each appliance type are listed below.
|
||||
| phase | String | Read | Current phase of the program running on the appliance |
|
||||
| rawPhase | Number | Read | Current phase of the program running on the appliance as raw number |
|
||||
| start | DateTime | Read | Programmed start time of the program |
|
||||
| end | DateTime | Read | End time of the program (programmed or running) |
|
||||
| duration | DateTime | Read | Duration of the program running on the appliance |
|
||||
| elapsed | DateTime | Read | Time elapsed in the program running on the appliance |
|
||||
| finish | DateTime | Read | Time to finish the program running on the appliance |
|
||||
@ -279,6 +281,7 @@ See oven.
|
||||
| phase | String | Read | Current phase of the program running on the appliance |
|
||||
| rawPhase | Number | Read | Current phase of the program running on the appliance as raw number |
|
||||
| start | DateTime | Read | Programmed start time of the program |
|
||||
| end | DateTime | Read | End time of the program (programmed or running) |
|
||||
| duration | DateTime | Read | Duration of the program running on the appliance |
|
||||
| elapsed | DateTime | Read | Time elapsed in the program running on the appliance |
|
||||
| finish | DateTime | Read | Time to finish the program running on the appliance |
|
||||
@ -343,6 +346,7 @@ See oven.
|
||||
| phase | String | Read | Current phase of the program running on the appliance |
|
||||
| rawPhase | Number | Read | Current phase of the program running on the appliance as raw number |
|
||||
| start | DateTime | Read | Programmed start time of the program |
|
||||
| end | DateTime | Read | End time of the program (programmed or running) |
|
||||
| duration | DateTime | Read | Duration of the program running on the appliance |
|
||||
| elapsed | DateTime | Read | Time elapsed in the program running on the appliance |
|
||||
| finish | DateTime | Read | Time to finish the program running on the appliance |
|
||||
|
@ -42,6 +42,8 @@ public class MieleBindingConstants {
|
||||
public static final String PROGRAM_ID_PROPERTY_NAME = "programId";
|
||||
public static final String PHASE_PROPERTY_NAME = "phase";
|
||||
public static final String RAW_PHASE_PROPERTY_NAME = "rawPhase";
|
||||
public static final String START_TIME_PROPERTY_NAME = "startTime";
|
||||
public static final String FINISH_TIME_PROPERTY_NAME = "finishTime";
|
||||
|
||||
// Shared Channel ID's
|
||||
public static final String STATE_TEXT_CHANNEL_ID = "state";
|
||||
@ -53,6 +55,9 @@ public class MieleBindingConstants {
|
||||
public static final String SUPERCOOL_CHANNEL_ID = "supercool";
|
||||
public static final String SUPERFREEZE_CHANNEL_ID = "superfreeze";
|
||||
public static final String SWITCH_CHANNEL_ID = "switch";
|
||||
public static final String START_CHANNEL_ID = "start";
|
||||
public static final String END_CHANNEL_ID = "end";
|
||||
public static final String FINISH_CHANNEL_ID = "finish";
|
||||
public static final String POWER_CONSUMPTION_CHANNEL_ID = "powerConsumption";
|
||||
public static final String WATER_CONSUMPTION_CHANNEL_ID = "waterConsumption";
|
||||
|
||||
|
@ -39,6 +39,7 @@ import org.openhab.binding.miele.internal.handler.WashingMachineHandler;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
@ -73,16 +74,18 @@ public class MieleHandlerFactory extends BaseThingHandlerFactory {
|
||||
private final HttpClient httpClient;
|
||||
private final TranslationProvider i18nProvider;
|
||||
private final LocaleProvider localeProvider;
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
|
||||
private Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
|
||||
|
||||
@Activate
|
||||
public MieleHandlerFactory(@Reference final HttpClientFactory httpClientFactory,
|
||||
final @Reference TranslationProvider i18nProvider, final @Reference LocaleProvider localeProvider,
|
||||
ComponentContext componentContext) {
|
||||
final @Reference TimeZoneProvider timeZoneProvider, ComponentContext componentContext) {
|
||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||
this.i18nProvider = i18nProvider;
|
||||
this.localeProvider = localeProvider;
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -113,31 +116,31 @@ public class MieleHandlerFactory extends BaseThingHandlerFactory {
|
||||
return handler;
|
||||
} else if (MieleApplianceHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
|
||||
if (thing.getThingTypeUID().equals(THING_TYPE_HOOD)) {
|
||||
return new HoodHandler(thing, i18nProvider, localeProvider);
|
||||
return new HoodHandler(thing, i18nProvider, localeProvider, timeZoneProvider);
|
||||
}
|
||||
if (thing.getThingTypeUID().equals(THING_TYPE_FRIDGEFREEZER)) {
|
||||
return new FridgeFreezerHandler(thing, i18nProvider, localeProvider);
|
||||
return new FridgeFreezerHandler(thing, i18nProvider, localeProvider, timeZoneProvider);
|
||||
}
|
||||
if (thing.getThingTypeUID().equals(THING_TYPE_FRIDGE)) {
|
||||
return new FridgeHandler(thing, i18nProvider, localeProvider);
|
||||
return new FridgeHandler(thing, i18nProvider, localeProvider, timeZoneProvider);
|
||||
}
|
||||
if (thing.getThingTypeUID().equals(THING_TYPE_OVEN)) {
|
||||
return new OvenHandler(thing, i18nProvider, localeProvider);
|
||||
return new OvenHandler(thing, i18nProvider, localeProvider, timeZoneProvider);
|
||||
}
|
||||
if (thing.getThingTypeUID().equals(THING_TYPE_HOB)) {
|
||||
return new HobHandler(thing, i18nProvider, localeProvider);
|
||||
return new HobHandler(thing, i18nProvider, localeProvider, timeZoneProvider);
|
||||
}
|
||||
if (thing.getThingTypeUID().equals(THING_TYPE_WASHINGMACHINE)) {
|
||||
return new WashingMachineHandler(thing, i18nProvider, localeProvider);
|
||||
return new WashingMachineHandler(thing, i18nProvider, localeProvider, timeZoneProvider);
|
||||
}
|
||||
if (thing.getThingTypeUID().equals(THING_TYPE_DRYER)) {
|
||||
return new TumbleDryerHandler(thing, i18nProvider, localeProvider);
|
||||
return new TumbleDryerHandler(thing, i18nProvider, localeProvider, timeZoneProvider);
|
||||
}
|
||||
if (thing.getThingTypeUID().equals(THING_TYPE_DISHWASHER)) {
|
||||
return new DishWasherHandler(thing, i18nProvider, localeProvider);
|
||||
return new DishWasherHandler(thing, i18nProvider, localeProvider, timeZoneProvider);
|
||||
}
|
||||
if (thing.getThingTypeUID().equals(THING_TYPE_COFFEEMACHINE)) {
|
||||
return new CoffeeMachineHandler(thing, i18nProvider, localeProvider);
|
||||
return new CoffeeMachineHandler(thing, i18nProvider, localeProvider, timeZoneProvider);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.miele.internal;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* {@link TimeStabilizer} keeps a cache of historic timestamp values in order to
|
||||
* provide moving average calculations to smooth out short-term fluctuations.
|
||||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TimeStabilizer {
|
||||
|
||||
private final static int SLIDING_SECONDS = 300;
|
||||
private final static int MAX_FLUCTUATION_SECONDS = 180;
|
||||
|
||||
private final Deque<Item> cache = new ConcurrentLinkedDeque<Item>();
|
||||
|
||||
private class Item {
|
||||
public Instant start;
|
||||
public Instant end;
|
||||
public Instant instant;
|
||||
|
||||
public Item(Instant instant, Instant start, Instant end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.instant = instant;
|
||||
}
|
||||
}
|
||||
|
||||
public TimeStabilizer() {
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public Instant apply(Instant value) {
|
||||
return this.apply(value, Instant.now());
|
||||
}
|
||||
|
||||
public Instant apply(Instant value, Instant now) {
|
||||
if (cache.isEmpty()) {
|
||||
cache.add(new Item(value, now, now));
|
||||
return value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Item first = cache.getFirst();
|
||||
@Nullable
|
||||
Item last = cache.getLast();
|
||||
last.end = now;
|
||||
|
||||
Instant windowStart = now.minusSeconds(SLIDING_SECONDS);
|
||||
Instant start = first.start;
|
||||
Instant base = first.instant;
|
||||
long weightedDiffFromBase = 0;
|
||||
final Iterator<Item> it = cache.iterator();
|
||||
while (it.hasNext()) {
|
||||
Item current = it.next();
|
||||
|
||||
if (current.end.isBefore(windowStart)) {
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
if (current.start.isBefore(windowStart) && current.end.isAfter(windowStart)) {
|
||||
// Truncate last item before sliding window.
|
||||
start = current.start = windowStart;
|
||||
}
|
||||
long secs = current.start.until(current.end, ChronoUnit.SECONDS);
|
||||
weightedDiffFromBase += base.until(current.instant, ChronoUnit.SECONDS) * secs;
|
||||
}
|
||||
|
||||
Instant average = base.plusSeconds(weightedDiffFromBase / start.until(now, ChronoUnit.SECONDS));
|
||||
if (value.isBefore(average.minusSeconds(MAX_FLUCTUATION_SECONDS))
|
||||
|| value.isAfter(average.plusSeconds(MAX_FLUCTUATION_SECONDS))) {
|
||||
cache.clear();
|
||||
average = value;
|
||||
}
|
||||
|
||||
cache.add(new Item(value, now, now));
|
||||
|
||||
return average;
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
@ -42,8 +43,9 @@ public class CoffeeMachineHandler extends MieleApplianceHandler<CoffeeMachineCha
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CoffeeMachineHandler.class);
|
||||
|
||||
public CoffeeMachineHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
|
||||
super(thing, i18nProvider, localeProvider, CoffeeMachineChannelSelector.class,
|
||||
public CoffeeMachineHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider,
|
||||
TimeZoneProvider timeZoneProvider) {
|
||||
super(thing, i18nProvider, localeProvider, timeZoneProvider, CoffeeMachineChannelSelector.class,
|
||||
MIELE_DEVICE_CLASS_COFFEE_SYSTEM);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
@ -54,8 +55,10 @@ public class DishWasherHandler extends MieleApplianceHandler<DishwasherChannelSe
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DishWasherHandler.class);
|
||||
|
||||
public DishWasherHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
|
||||
super(thing, i18nProvider, localeProvider, DishwasherChannelSelector.class, MIELE_DEVICE_CLASS_DISHWASHER);
|
||||
public DishWasherHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider,
|
||||
TimeZoneProvider timeZoneProvider) {
|
||||
super(thing, i18nProvider, localeProvider, timeZoneProvider, DishwasherChannelSelector.class,
|
||||
MIELE_DEVICE_CLASS_DISHWASHER);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -73,20 +73,8 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
||||
}
|
||||
},
|
||||
PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false, false),
|
||||
START_TIME("startTime", "start", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
try {
|
||||
date.setTime(Long.valueOf(s) * 60000);
|
||||
} catch (Exception e) {
|
||||
date.setTime(0);
|
||||
}
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
START_TIME("", START_CHANNEL_ID, DateTimeType.class, false, false),
|
||||
END_TIME("", END_CHANNEL_ID, DateTimeType.class, false, false),
|
||||
DURATION("duration", "duration", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
@ -115,20 +103,7 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
FINISH_TIME("finishTime", "finish", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
try {
|
||||
date.setTime(Long.valueOf(s) * 60000);
|
||||
} catch (Exception e) {
|
||||
date.setTime(0);
|
||||
}
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
FINISH_TIME("", FINISH_CHANNEL_ID, DateTimeType.class, false, false),
|
||||
DOOR("signalDoor", "door", OpenClosedType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
|
@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
@ -42,8 +43,9 @@ public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerCha
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FridgeFreezerHandler.class);
|
||||
|
||||
public FridgeFreezerHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
|
||||
super(thing, i18nProvider, localeProvider, FridgeFreezerChannelSelector.class,
|
||||
public FridgeFreezerHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider,
|
||||
TimeZoneProvider timeZoneProvider) {
|
||||
super(thing, i18nProvider, localeProvider, timeZoneProvider, FridgeFreezerChannelSelector.class,
|
||||
MIELE_DEVICE_CLASS_FRIDGE_FREEZER);
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
@ -43,8 +44,10 @@ public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector>
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FridgeHandler.class);
|
||||
|
||||
public FridgeHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
|
||||
super(thing, i18nProvider, localeProvider, FridgeChannelSelector.class, MIELE_DEVICE_CLASS_FRIDGE);
|
||||
public FridgeHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider,
|
||||
TimeZoneProvider timeZoneProvider) {
|
||||
super(thing, i18nProvider, localeProvider, timeZoneProvider, FridgeChannelSelector.class,
|
||||
MIELE_DEVICE_CLASS_FRIDGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -16,6 +16,7 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEV
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
@ -31,8 +32,9 @@ import org.openhab.core.types.Command;
|
||||
@NonNullByDefault
|
||||
public class HobHandler extends MieleApplianceHandler<HobChannelSelector> {
|
||||
|
||||
public HobHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
|
||||
super(thing, i18nProvider, localeProvider, HobChannelSelector.class, MIELE_DEVICE_CLASS_HOB);
|
||||
public HobHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider,
|
||||
TimeZoneProvider timeZoneProvider) {
|
||||
super(thing, i18nProvider, localeProvider, timeZoneProvider, HobChannelSelector.class, MIELE_DEVICE_CLASS_HOB);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,6 +17,7 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEV
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
@ -41,8 +42,10 @@ public class HoodHandler extends MieleApplianceHandler<HoodChannelSelector> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HoodHandler.class);
|
||||
|
||||
public HoodHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
|
||||
super(thing, i18nProvider, localeProvider, HoodChannelSelector.class, MIELE_DEVICE_CLASS_HOOD);
|
||||
public HoodHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider,
|
||||
TimeZoneProvider timeZoneProvider) {
|
||||
super(thing, i18nProvider, localeProvider, timeZoneProvider, HoodChannelSelector.class,
|
||||
MIELE_DEVICE_CLASS_HOOD);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -14,6 +14,10 @@ package org.openhab.binding.miele.internal.handler;
|
||||
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.HashMap;
|
||||
import java.util.IllformedLocaleException;
|
||||
import java.util.Locale;
|
||||
@ -24,12 +28,15 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.TimeStabilizer;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceClassObject;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.api.dto.HomeDevice;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
@ -43,6 +50,7 @@ import org.openhab.core.thing.binding.ThingHandler;
|
||||
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;
|
||||
|
||||
@ -79,19 +87,25 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
||||
protected TranslationProvider i18nProvider;
|
||||
protected LocaleProvider localeProvider;
|
||||
protected MieleTranslationProvider translationProvider;
|
||||
private TimeZoneProvider timeZoneProvider;
|
||||
private TimeStabilizer startTimeStabilizer;
|
||||
private TimeStabilizer finishTimeStabilizer;
|
||||
private Class<E> selectorType;
|
||||
protected String modelID;
|
||||
|
||||
protected Map<String, String> metaDataCache = new HashMap<>();
|
||||
|
||||
public MieleApplianceHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider,
|
||||
Class<E> selectorType, String modelID) {
|
||||
TimeZoneProvider timeZoneProvider, Class<E> selectorType, String modelID) {
|
||||
super(thing);
|
||||
this.i18nProvider = i18nProvider;
|
||||
this.localeProvider = localeProvider;
|
||||
this.selectorType = selectorType;
|
||||
this.modelID = modelID;
|
||||
this.translationProvider = new MieleTranslationProvider(i18nProvider, localeProvider);
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
this.startTimeStabilizer = new TimeStabilizer();
|
||||
this.finishTimeStabilizer = new TimeStabilizer();
|
||||
}
|
||||
|
||||
public ApplianceChannelSelector getValueSelectorFromChannelID(String valueSelectorText)
|
||||
@ -180,6 +194,8 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
||||
}
|
||||
applianceId = null;
|
||||
}
|
||||
startTimeStabilizer.clear();
|
||||
finishTimeStabilizer.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -242,6 +258,7 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
||||
metaDataCache.put(new StringBuilder().append(dp.Name).toString().trim(), metadata);
|
||||
}
|
||||
|
||||
ThingUID thingUid = getThing().getUID();
|
||||
if (EXTENDED_DEVICE_STATE_PROPERTY_NAME.equals(dp.Name)) {
|
||||
if (!dp.Value.isEmpty()) {
|
||||
byte[] extendedStateBytes = DeviceUtil.stringToBytes(dp.Value);
|
||||
@ -252,6 +269,13 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (START_TIME_PROPERTY_NAME.equals(dp.Name)) {
|
||||
updateStateFromTime(new ChannelUID(thingUid, START_CHANNEL_ID), dp.Value, startTimeStabilizer);
|
||||
return;
|
||||
} else if (FINISH_TIME_PROPERTY_NAME.equals(dp.Name)) {
|
||||
updateDurationState(new ChannelUID(thingUid, FINISH_CHANNEL_ID), dp.Value);
|
||||
updateStateFromTime(new ChannelUID(thingUid, END_CHANNEL_ID), dp.Value, finishTimeStabilizer);
|
||||
return;
|
||||
}
|
||||
|
||||
ApplianceChannelSelector selector = null;
|
||||
@ -265,7 +289,6 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
||||
|
||||
if (selector != null) {
|
||||
String channelId = selector.getChannelID();
|
||||
ThingUID thingUid = getThing().getUID();
|
||||
State state = selector.getState(dpValue, dmd, this.translationProvider);
|
||||
if (selector.isProperty()) {
|
||||
String value = state.toString();
|
||||
@ -289,6 +312,40 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
||||
updateState(channelUid, state);
|
||||
}
|
||||
|
||||
private void updateStateFromTime(ChannelUID channelUid, String value, TimeStabilizer stabilizer) {
|
||||
try {
|
||||
long minutesFromNow = Long.valueOf(value);
|
||||
if (minutesFromNow > 0) {
|
||||
Instant rawTime = Instant.now().truncatedTo(ChronoUnit.MINUTES).plusSeconds(minutesFromNow * 60);
|
||||
ZonedDateTime correctedTime = stabilizer.apply(rawTime).atZone(timeZoneProvider.getTimeZone());
|
||||
ZonedDateTime truncatedTime = correctedTime.truncatedTo(ChronoUnit.MINUTES);
|
||||
logger.trace("Update state of {} from {} -> '{}' -> '{}' to '{}'", channelUid, minutesFromNow, rawTime,
|
||||
correctedTime, truncatedTime);
|
||||
updateState(channelUid, new DateTimeType(truncatedTime));
|
||||
return;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// Fall through.
|
||||
}
|
||||
updateState(channelUid, UnDefType.UNDEF);
|
||||
stabilizer.clear();
|
||||
}
|
||||
|
||||
private void updateDurationState(ChannelUID channelUid, String value) {
|
||||
try {
|
||||
long minutesFromNow = Long.valueOf(value);
|
||||
if (minutesFromNow > 0) {
|
||||
ZonedDateTime remaining = ZonedDateTime.ofInstant(Instant.ofEpochSecond(minutesFromNow * 60),
|
||||
ZoneId.of("UTC"));
|
||||
updateState(channelUid, new DateTimeType(remaining.withZoneSameLocal(timeZoneProvider.getTimeZone())));
|
||||
return;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// Fall through.
|
||||
}
|
||||
updateState(channelUid, UnDefType.UNDEF);
|
||||
}
|
||||
|
||||
protected void updateSwitchOnOffFromState(DeviceProperty dp) {
|
||||
if (!STATE_PROPERTY_NAME.equals(dp.Name)) {
|
||||
return;
|
||||
|
@ -68,20 +68,8 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
||||
}
|
||||
},
|
||||
PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false),
|
||||
START_TIME("startTime", "start", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
try {
|
||||
date.setTime(Long.valueOf(s) * 60000);
|
||||
} catch (Exception e) {
|
||||
date.setTime(0);
|
||||
}
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
START_TIME("", START_CHANNEL_ID, DateTimeType.class, false),
|
||||
END_TIME("", END_CHANNEL_ID, DateTimeType.class, false),
|
||||
DURATION("duration", "duration", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
@ -110,20 +98,7 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
FINISH_TIME("finishTime", "finish", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
try {
|
||||
date.setTime(Long.valueOf(s) * 60000);
|
||||
} catch (Exception e) {
|
||||
date.setTime(0);
|
||||
}
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
FINISH_TIME("", FINISH_CHANNEL_ID, DateTimeType.class, false),
|
||||
TARGET_TEMP("targetTemperature", "target", QuantityType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
|
@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
@ -43,8 +44,10 @@ public class OvenHandler extends MieleApplianceHandler<OvenChannelSelector> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(OvenHandler.class);
|
||||
|
||||
public OvenHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
|
||||
super(thing, i18nProvider, localeProvider, OvenChannelSelector.class, MIELE_DEVICE_CLASS_OVEN);
|
||||
public OvenHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider,
|
||||
TimeZoneProvider timeZoneProvider) {
|
||||
super(thing, i18nProvider, localeProvider, timeZoneProvider, OvenChannelSelector.class,
|
||||
MIELE_DEVICE_CLASS_OVEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -73,20 +73,8 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
||||
}
|
||||
},
|
||||
PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false),
|
||||
START_TIME("startTime", "start", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
try {
|
||||
date.setTime(Long.valueOf(s) * 60000);
|
||||
} catch (Exception e) {
|
||||
date.setTime(0);
|
||||
}
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
START_TIME("", START_CHANNEL_ID, DateTimeType.class, false),
|
||||
END_TIME("", END_CHANNEL_ID, DateTimeType.class, false),
|
||||
DURATION("duration", "duration", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
@ -115,20 +103,7 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
FINISH_TIME("finishTime", "finish", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
try {
|
||||
date.setTime(Long.valueOf(s) * 60000);
|
||||
} catch (Exception e) {
|
||||
date.setTime(0);
|
||||
}
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
FINISH_TIME("", FINISH_CHANNEL_ID, DateTimeType.class, false),
|
||||
DRYING_STEP("dryingStep", "step", DecimalType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
|
@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
@ -43,8 +44,10 @@ public class TumbleDryerHandler extends MieleApplianceHandler<TumbleDryerChannel
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(TumbleDryerHandler.class);
|
||||
|
||||
public TumbleDryerHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
|
||||
super(thing, i18nProvider, localeProvider, TumbleDryerChannelSelector.class, MIELE_DEVICE_CLASS_TUMBLE_DRYER);
|
||||
public TumbleDryerHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider,
|
||||
TimeZoneProvider timeZoneProvider) {
|
||||
super(thing, i18nProvider, localeProvider, timeZoneProvider, TumbleDryerChannelSelector.class,
|
||||
MIELE_DEVICE_CLASS_TUMBLE_DRYER);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,20 +74,8 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
||||
}
|
||||
},
|
||||
PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false, false),
|
||||
START_TIME("startTime", "start", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
try {
|
||||
date.setTime(Long.valueOf(s) * 60000);
|
||||
} catch (Exception e) {
|
||||
date.setTime(0);
|
||||
}
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
START_TIME("", START_CHANNEL_ID, DateTimeType.class, false, false),
|
||||
END_TIME("", END_CHANNEL_ID, DateTimeType.class, false, false),
|
||||
DURATION("duration", "duration", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
@ -116,20 +104,7 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
FINISH_TIME("finishTime", "finish", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
try {
|
||||
date.setTime(Long.valueOf(s) * 60000);
|
||||
} catch (Exception e) {
|
||||
date.setTime(0);
|
||||
}
|
||||
return getState(dateFormatter.format(date));
|
||||
}
|
||||
},
|
||||
FINISH_TIME("", FINISH_CHANNEL_ID, DateTimeType.class, false, false),
|
||||
TARGET_TEMP("targetTemperature", "target", QuantityType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
|
@ -22,6 +22,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
@ -54,8 +55,9 @@ public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineC
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WashingMachineHandler.class);
|
||||
|
||||
public WashingMachineHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
|
||||
super(thing, i18nProvider, localeProvider, WashingMachineChannelSelector.class,
|
||||
public WashingMachineHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider,
|
||||
TimeZoneProvider timeZoneProvider) {
|
||||
super(thing, i18nProvider, localeProvider, timeZoneProvider, WashingMachineChannelSelector.class,
|
||||
MIELE_DEVICE_CLASS_WASHING_MACHINE);
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,8 @@ channel-type.miele.duration.state.pattern = %1$tH:%1$tM
|
||||
channel-type.miele.elapsed.label = Elapsed Time
|
||||
channel-type.miele.elapsed.description = Time elapsed in the program running on the appliance
|
||||
channel-type.miele.elapsed.state.pattern = %1$tH:%1$tM
|
||||
channel-type.miele.end.label = End Time
|
||||
channel-type.miele.end.description = End time of the program (programmed or running)
|
||||
channel-type.miele.finish.label = Finish Time
|
||||
channel-type.miele.finish.description = Time to finish the program running on the appliance
|
||||
channel-type.miele.finish.state.pattern = %1$tH:%1$tM
|
||||
@ -97,7 +99,6 @@ channel-type.miele.spinningspeed.label = Spinning Speed
|
||||
channel-type.miele.spinningspeed.description = Spinning speed in the program running on the appliance
|
||||
channel-type.miele.start.label = Start Time
|
||||
channel-type.miele.start.description = Programmed start time of the program
|
||||
channel-type.miele.start.state.pattern = %1$tH:%1$tM
|
||||
channel-type.miele.state.label = State
|
||||
channel-type.miele.state.description = Current status of the appliance
|
||||
channel-type.miele.step.label = Step
|
||||
@ -132,7 +133,7 @@ offline.configuration-error.invalid-ip-multicast-interface = Invalid IP address
|
||||
offline.configuration-error.invalid-language = Invalid language: {0}
|
||||
offline.configuration-error.uid-not-set = Appliance ID is not set
|
||||
|
||||
# Discovery result
|
||||
# discovery result
|
||||
|
||||
discovery.xgw3000.label = Miele XGW 3000
|
||||
|
||||
@ -170,7 +171,6 @@ miele.program.dishwasher.extra-quiet = Extra Quiet
|
||||
miele.program.dishwasher.hygiene = Hygiene
|
||||
miele.program.dishwasher.quickpowerwash = QuickPowerWash
|
||||
miele.program.dishwasher.tall-items = Tall items
|
||||
|
||||
miele.program.tumbledryer.automatic-plus = Automatic Plus
|
||||
miele.program.tumbledryer.cottons = Cottons
|
||||
miele.program.tumbledryer.cottons-hygiene = Cottons hygiene
|
||||
@ -196,7 +196,6 @@ miele.program.tumbledryer.basket-programme = Basket programme
|
||||
miele.program.tumbledryer.smoothing = Smoothing
|
||||
miele.program.tumbledryer.cottons-auto-load-control = Cottons, auto load control
|
||||
miele.program.tumbledryer.minimum-iron-auto-load-control = Minimum iron, auto load control
|
||||
|
||||
miele.program.washingmachine.cottons = Cottons
|
||||
miele.program.washingmachine.minimum-iron = Minimum iron
|
||||
miele.program.washingmachine.delicates = Delicates
|
||||
@ -233,7 +232,6 @@ miele.phase.dishwasher.rinses = Rinses
|
||||
miele.phase.dishwasher.final-rinse = Final rinse
|
||||
miele.phase.dishwasher.drying = Drying
|
||||
miele.phase.dishwasher.finished = Finished
|
||||
|
||||
miele.phase.oven.heating = Heating
|
||||
miele.phase.oven.temp-hold = Temp. hold
|
||||
miele.phase.oven.door-open = Door Open
|
||||
@ -243,7 +241,6 @@ miele.phase.oven.searing-phase = Searing phase
|
||||
miele.phase.oven.defrost = Defrost
|
||||
miele.phase.oven.cooling-down = Cooling down
|
||||
miele.phase.oven.energy-save-phase = Energy save phase
|
||||
|
||||
miele.phase.tumbledryer.programme-running = Programme running
|
||||
miele.phase.tumbledryer.drying = Drying
|
||||
miele.phase.tumbledryer.drying-machine-iron = Drying Machine iron
|
||||
@ -252,7 +249,6 @@ miele.phase.tumbledryer.drying-normal = Drying Normal
|
||||
miele.phase.tumbledryer.drying-normal-plus = Drying Normal+
|
||||
miele.phase.tumbledryer.cooling-down = Cooling down
|
||||
miele.phase.tumbledryer.finished = Finished
|
||||
|
||||
miele.phase.washingmachine.pre-wash = Pre-wash
|
||||
miele.phase.washingmachine.washing = Washing
|
||||
miele.phase.washingmachine.rinses = Rinses
|
||||
|
@ -53,15 +53,23 @@
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="start" advanced="true">
|
||||
<channel-type id="start">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Start Time</label>
|
||||
<description>Programmed start time of the program</description>
|
||||
<category>Time</category>
|
||||
<state readOnly="true" pattern="%1$tH:%1$tM"></state>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="duration" advanced="true">
|
||||
<channel-type id="end">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>End Time</label>
|
||||
<description>End time of the program (programmed or running)</description>
|
||||
<category>Time</category>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="duration">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Duration</label>
|
||||
<description>Duration of the program running on the appliance</description>
|
||||
|
@ -21,6 +21,7 @@
|
||||
<channel id="phase" typeId="phase"/>
|
||||
<channel id="rawPhase" typeId="rawPhase"/>
|
||||
<channel id="start" typeId="start"/>
|
||||
<channel id="end" typeId="end"/>
|
||||
<channel id="duration" typeId="duration"/>
|
||||
<channel id="elapsed" typeId="elapsed"/>
|
||||
<channel id="finish" typeId="finish"/>
|
||||
|
@ -22,6 +22,7 @@
|
||||
<channel id="phase" typeId="phase"/>
|
||||
<channel id="rawPhase" typeId="rawPhase"/>
|
||||
<channel id="start" typeId="start"/>
|
||||
<channel id="end" typeId="end"/>
|
||||
<channel id="duration" typeId="duration"/>
|
||||
<channel id="elapsed" typeId="elapsed"/>
|
||||
<channel id="finish" typeId="finish"/>
|
||||
|
@ -22,6 +22,7 @@
|
||||
<channel id="phase" typeId="phase"/>
|
||||
<channel id="rawPhase" typeId="rawPhase"/>
|
||||
<channel id="start" typeId="start"/>
|
||||
<channel id="end" typeId="end"/>
|
||||
<channel id="duration" typeId="duration"/>
|
||||
<channel id="elapsed" typeId="elapsed"/>
|
||||
<channel id="finish" typeId="finish"/>
|
||||
|
@ -22,6 +22,7 @@
|
||||
<channel id="phase" typeId="phase"/>
|
||||
<channel id="rawPhase" typeId="rawPhase"/>
|
||||
<channel id="start" typeId="start"/>
|
||||
<channel id="end" typeId="end"/>
|
||||
<channel id="duration" typeId="duration"/>
|
||||
<channel id="elapsed" typeId="elapsed"/>
|
||||
<channel id="finish" typeId="finish"/>
|
||||
|
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.miele.internal;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link TimeStabilizer}.
|
||||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TimeStabilizerTest {
|
||||
|
||||
private @NonNullByDefault({}) TimeStabilizer stabilizer;
|
||||
|
||||
@BeforeEach
|
||||
public void initialize() {
|
||||
stabilizer = new TimeStabilizer();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenLongestPeriodIsFloorThenWeightedAverageIsLess() {
|
||||
assertThat(stabilizer.apply(getInstantOf("02:00:00"), getInstantOf("22:00:00")),
|
||||
is(equalTo(getInstantOf("02:00:00"))));
|
||||
assertThat(stabilizer.apply(getInstantOf("02:01:00"), getInstantOf("22:00:31")),
|
||||
is(equalTo(getInstantOf("02:00:00"))));
|
||||
assertThat(stabilizer.apply(getInstantOf("02:00:00"), getInstantOf("22:01:00")),
|
||||
is(equalTo(getInstantOf("02:00:29"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenLongestPeriodIsCeilThenWeightedAverageIsMore() {
|
||||
assertThat(stabilizer.apply(getInstantOf("02:00:00"), getInstantOf("22:00:00")),
|
||||
is(equalTo(getInstantOf("02:00:00"))));
|
||||
assertThat(stabilizer.apply(getInstantOf("02:01:00"), getInstantOf("22:00:29")),
|
||||
is(equalTo(getInstantOf("02:00:00"))));
|
||||
assertThat(stabilizer.apply(getInstantOf("02:00:00"), getInstantOf("22:01:00")),
|
||||
is(equalTo(getInstantOf("02:00:31"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenTooMuchFluctuationThenAverageIsDisregarded() {
|
||||
assertThat(stabilizer.apply(getInstantOf("02:00:00"), getInstantOf("22:00:00")),
|
||||
is(equalTo(getInstantOf("02:00:00"))));
|
||||
assertThat(stabilizer.apply(getInstantOf("02:03:00"), getInstantOf("22:03:00")),
|
||||
is(equalTo(getInstantOf("02:00:00"))));
|
||||
assertThat(stabilizer.apply(getInstantOf("02:04:00"), getInstantOf("22:03:00")),
|
||||
is(equalTo(getInstantOf("02:04:00"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOutsideSlidingWindowThenValueIsDisregarded() {
|
||||
assertThat(stabilizer.apply(getInstantOf("02:00:00"), getInstantOf("22:00:00")),
|
||||
is(equalTo(getInstantOf("02:00:00"))));
|
||||
assertThat(stabilizer.apply(getInstantOf("02:01:00"), getInstantOf("22:10:00")),
|
||||
is(equalTo(getInstantOf("02:00:00"))));
|
||||
assertThat(stabilizer.apply(getInstantOf("02:02:00"), getInstantOf("22:15:00")),
|
||||
is(equalTo(getInstantOf("02:00:30"))));
|
||||
assertThat(stabilizer.apply(getInstantOf("02:02:00"), getInstantOf("22:15:01")),
|
||||
is(equalTo(getInstantOf("02:01:00"))));
|
||||
}
|
||||
|
||||
private Instant getInstantOf(String time) {
|
||||
Clock clock = Clock.fixed(Instant.parse("2022-09-13T" + time + "Z"), ZoneId.of("UTC"));
|
||||
return Instant.now(clock);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user