Skip to content

Commit

Permalink
[ecobee] Fix issue with UTC and local dates (openhab#14170)
Browse files Browse the repository at this point in the history
* Correctly handle UTC and local date/times
* Eliminate use of Date class

Signed-off-by: Mark Hilbush <[email protected]>
  • Loading branch information
mhilbush authored and renescherer committed Mar 23, 2023
1 parent 3a7b3cd commit cd932e7
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
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;
Expand All @@ -32,6 +33,8 @@
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;
Expand Down Expand Up @@ -66,7 +69,8 @@
@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();

Expand Down
Original file line number Diff line number Diff line change
@@ -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<Instant> {

@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;
}
}
}
Original file line number Diff line number Diff line change
@@ -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<LocalDateTime> {

@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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*/
package org.openhab.binding.ecobee.internal.dto.thermostat;

import java.util.Date;
import java.time.Instant;
import java.util.List;

/**
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*/
package org.openhab.binding.ecobee.internal.dto.thermostat;

import java.util.Date;
import java.time.Instant;
import java.util.List;

/**
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@ private void updateWeather(@Nullable WeatherDTO weather) {
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));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -87,9 +88,13 @@ public static State undefOrPoint(@Nullable String value) {
return value == null ? UnDefType.UNDEF : new PointType(value);
}

public static State undefOrDate(@Nullable Date date, TimeZoneProvider timeZoneProvider) {
return date == null ? UnDefType.UNDEF
: new DateTimeType(ZonedDateTime.ofInstant(date.toInstant(), timeZoneProvider.getTimeZone()));
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) {
Expand Down

0 comments on commit cd932e7

Please sign in to comment.