diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/EcobeeBindingConstants.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/EcobeeBindingConstants.java index c743b550454..4f3d0704df5 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/EcobeeBindingConstants.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/EcobeeBindingConstants.java @@ -409,4 +409,5 @@ public class EcobeeBindingConstants { public static final String ECOBEE_AUTHORIZE_URL = ECOBEE_BASE_URL + "authorize"; public static final String ECOBEE_TOKEN_URL = ECOBEE_BASE_URL + "token"; public static final String ECOBEE_SCOPE = "smartWrite"; + public static final String ECOBEE_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; } diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java index b88702d4468..b245a4c83f9 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.Instant; +import java.time.LocalDateTime; import java.util.List; import java.util.Properties; import java.util.Set; @@ -32,6 +33,8 @@ import org.eclipse.jetty.client.HttpClient; import org.openhab.binding.ecobee.internal.dto.AbstractResponseDTO; import org.openhab.binding.ecobee.internal.dto.SelectionDTO; import org.openhab.binding.ecobee.internal.dto.SelectionType; +import org.openhab.binding.ecobee.internal.dto.thermostat.InstantDeserializer; +import org.openhab.binding.ecobee.internal.dto.thermostat.LocalDateTimeDeserializer; import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatDTO; import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatRequestDTO; import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatResponseDTO; @@ -66,7 +69,8 @@ import com.google.gson.JsonSyntaxException; @NonNullByDefault public class EcobeeApi implements AccessTokenRefreshListener { - private static final Gson GSON = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss") + private static final Gson GSON = new GsonBuilder().registerTypeAdapter(Instant.class, new InstantDeserializer()) + .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeDeserializer()) .registerTypeAdapter(RevisionDTO.class, new RevisionDTODeserializer()) .registerTypeAdapter(RunningDTO.class, new RunningDTODeserializer()).create(); diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/InstantDeserializer.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/InstantDeserializer.java new file mode 100644 index 00000000000..e6f944d64ee --- /dev/null +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/InstantDeserializer.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.ecobee.internal.dto.thermostat; + +import static org.openhab.binding.ecobee.internal.EcobeeBindingConstants.ECOBEE_DATETIME_FORMAT; + +import java.lang.reflect.Type; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; + +/** + * The {@link InstantDeserializer} is responsible for handling the UTC dates returned from + * the Ecobee API service. + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public class InstantDeserializer implements JsonDeserializer { + + @Override + public @Nullable Instant deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2) + throws JsonParseException { + try { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ECOBEE_DATETIME_FORMAT); + LocalDateTime localDateTime = formatter.parse(element.getAsString(), LocalDateTime::from); + return localDateTime.toInstant(ZoneOffset.UTC); + } catch (DateTimeParseException e) { + return null; + } + } +} diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/LocalDateTimeDeserializer.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/LocalDateTimeDeserializer.java new file mode 100644 index 00000000000..1b7e9080cf3 --- /dev/null +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/LocalDateTimeDeserializer.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.ecobee.internal.dto.thermostat; + +import static org.openhab.binding.ecobee.internal.EcobeeBindingConstants.ECOBEE_DATETIME_FORMAT; + +import java.lang.reflect.Type; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; + +/** + * The {@link LocalDateTimeDeserializer} is responsible for handling the local dates returned from + * the Ecobee API service. + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public class LocalDateTimeDeserializer implements JsonDeserializer { + + @Override + public @Nullable LocalDateTime deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2) + throws JsonParseException { + try { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ECOBEE_DATETIME_FORMAT); + return formatter.parse(element.getAsString(), LocalDateTime::from); + } catch (DateTimeParseException e) { + return null; + } + } +} diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/RuntimeDTO.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/RuntimeDTO.java index a946d05bb6e..4151e3ea1ec 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/RuntimeDTO.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/RuntimeDTO.java @@ -12,7 +12,7 @@ */ package org.openhab.binding.ecobee.internal.dto.thermostat; -import java.util.Date; +import java.time.Instant; import java.util.List; /** @@ -48,29 +48,29 @@ public class RuntimeDTO { * The UTC date/time stamp of when the thermostat first connected * to the ecobee server. */ - public Date firstConnected; + public Instant firstConnected; /* * The last recorded connection date and time. */ - public Date connectDateTime; + public Instant connectDateTime; /* * The last recorded disconnection date and time. */ - public Date disconnectDateTime; + public Instant disconnectDateTime; /* * The UTC date/time stamp of when the thermostat was updated. * Format: YYYY-MM-DD HH:MM:SS */ - public Date lastModified; + public Instant lastModified; /* * The UTC date/time stamp of when the thermostat last posted its * runtime information. Format: YYYY-MM-DD HH:MM:SS */ - public Date lastStatusModified; + public Instant lastStatusModified; /* * The UTC date of the last runtime reading. Format: YYYY-MM-DD diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/ThermostatDTO.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/ThermostatDTO.java index 073a6e074e1..6aae7cd984b 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/ThermostatDTO.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/ThermostatDTO.java @@ -12,7 +12,8 @@ */ package org.openhab.binding.ecobee.internal.dto.thermostat; -import java.util.Date; +import java.time.Instant; +import java.time.LocalDateTime; import java.util.List; /** @@ -64,12 +65,12 @@ public class ThermostatDTO { /* * The last modified date time for the thermostat configuration. */ - public Date lastModified; + public Instant lastModified; /* * The current time in the thermostat's time zone. */ - public Date thermostatTime; + public LocalDateTime thermostatTime; /* * The current time in UTC. diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/WeatherDTO.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/WeatherDTO.java index ec55310210b..be757061d51 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/WeatherDTO.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/WeatherDTO.java @@ -12,7 +12,7 @@ */ package org.openhab.binding.ecobee.internal.dto.thermostat; -import java.util.Date; +import java.time.Instant; import java.util.List; /** @@ -25,7 +25,7 @@ public class WeatherDTO { /* * The time stamp in UTC of the weather forecast */ - public Date timestamp; + public Instant timestamp; /* * The weather station identifier diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/WeatherForecastDTO.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/WeatherForecastDTO.java index cbc008dc99e..e882ab5dc49 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/WeatherForecastDTO.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/WeatherForecastDTO.java @@ -12,7 +12,7 @@ */ package org.openhab.binding.ecobee.internal.dto.thermostat; -import java.util.Date; +import java.time.LocalDateTime; /** * The {@link WeatherForecastDTO} contains the weather forecast information for @@ -31,9 +31,9 @@ public class WeatherForecastDTO { public Integer weatherSymbol; /* - * The time stamp of the weather forecast. + * The time stamp of the weather forecast in the thermostat's time zone. */ - public Date dateTime; + public LocalDateTime dateTime; /* * A text value representing the current weather condition. diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeThermostatBridgeHandler.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeThermostatBridgeHandler.java index aa8f1e8088c..1f20011f3d5 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeThermostatBridgeHandler.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeThermostatBridgeHandler.java @@ -662,6 +662,7 @@ public class EcobeeThermostatBridgeHandler extends BaseBridgeHandler { return; } final String weatherGrp = CHGRP_WEATHER + "#"; + updateChannel(weatherGrp + CH_WEATHER_TIMESTAMP, EcobeeUtils.undefOrDate(weather.timestamp, timeZoneProvider)); updateChannel(weatherGrp + CH_WEATHER_WEATHER_STATION, EcobeeUtils.undefOrString(weather.weatherStation)); diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeUtils.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeUtils.java index 410aac04e11..fec258982cf 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeUtils.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeUtils.java @@ -12,8 +12,9 @@ */ package org.openhab.binding.ecobee.internal.handler; +import java.time.Instant; +import java.time.LocalDateTime; import java.time.ZonedDateTime; -import java.util.Date; import javax.measure.Unit; import javax.measure.quantity.Temperature; @@ -87,9 +88,13 @@ public final class EcobeeUtils { return value == null ? UnDefType.UNDEF : new PointType(value); } - public static State undefOrDate(@Nullable Date date, TimeZoneProvider timeZoneProvider) { - return date == null ? UnDefType.UNDEF - : new DateTimeType(ZonedDateTime.ofInstant(date.toInstant(), timeZoneProvider.getTimeZone())); + public static State undefOrDate(@Nullable Instant instant, TimeZoneProvider timeZoneProvider) { + return instant == null ? UnDefType.UNDEF + : new DateTimeType(ZonedDateTime.ofInstant(instant, timeZoneProvider.getTimeZone())); + } + + public static State undefOrDate(@Nullable LocalDateTime ldt, TimeZoneProvider timeZoneProvider) { + return ldt == null ? UnDefType.UNDEF : new DateTimeType(ldt.atZone(timeZoneProvider.getTimeZone())); } private static boolean isUnknown(Number value) {