From 918d1fa651c8715648a245ea55abd7c67db5826b Mon Sep 17 00:00:00 2001 From: Laurent ARNAL Date: Sat, 21 Dec 2024 12:01:50 +0100 Subject: [PATCH 1/4] fixes for change in Enedis API on 2024 December 20 ! - URL for data is now mes-mesures-prm and not mes-mesures. - Dto format have changed : mainly merge data & date, field renaming, and moving. - Some changes on date format. Signed-off-by: Laurent ARNAL --- .../linky/internal/LinkyHandlerFactory.java | 38 +++++++++-- .../linky/internal/api/EnedisHttpApi.java | 15 +++-- .../linky/internal/dto/ConsumptionReport.java | 39 ++++++------ .../linky/internal/handler/LinkyHandler.java | 63 ++++++++----------- 4 files changed, 86 insertions(+), 69 deletions(-) diff --git a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyHandlerFactory.java b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyHandlerFactory.java index 315ed268c12..74f8bf0abe0 100644 --- a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyHandlerFactory.java +++ b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyHandlerFactory.java @@ -12,12 +12,16 @@ */ package org.openhab.binding.linky.internal; +import static java.time.temporal.ChronoField.*; import static org.openhab.binding.linky.internal.LinkyBindingConstants.THING_TYPE_LINKY; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; @@ -28,6 +32,7 @@ import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.openhab.binding.linky.internal.handler.LinkyHandler; import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.io.net.http.HttpClientFactory; import org.openhab.core.io.net.http.TrustAllTrustManager; import org.openhab.core.thing.Thing; @@ -55,21 +60,43 @@ import com.google.gson.JsonDeserializer; @Component(service = ThingHandlerFactory.class, configurationPid = "binding.linky") public class LinkyHandlerFactory extends BaseThingHandlerFactory { private static final DateTimeFormatter LINKY_FORMATTER = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX"); + private static final DateTimeFormatter LINKY_LOCALDATE_FORMATTER = DateTimeFormatter.ofPattern("uuuu-MM-dd"); + private static final DateTimeFormatter LINKY_LOCALDATETIME_FORMATTER = new DateTimeFormatterBuilder() + .appendPattern("uuuu-MM-dd'T'HH:mm").optionalStart().appendLiteral(':').appendValue(SECOND_OF_MINUTE, 2) + .optionalStart().appendFraction(NANO_OF_SECOND, 0, 9, true).toFormatter(); + private static final int REQUEST_BUFFER_SIZE = 8000; private static final int RESPONSE_BUFFER_SIZE = 200000; private final Logger logger = LoggerFactory.getLogger(LinkyHandlerFactory.class); - private final Gson gson = new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, - (JsonDeserializer) (json, type, jsonDeserializationContext) -> ZonedDateTime - .parse(json.getAsJsonPrimitive().getAsString(), LINKY_FORMATTER)) + private final Gson gson = new GsonBuilder() + .registerTypeAdapter(ZonedDateTime.class, + (JsonDeserializer) (json, type, jsonDeserializationContext) -> ZonedDateTime + .parse(json.getAsJsonPrimitive().getAsString(), LINKY_FORMATTER)) + .registerTypeAdapter(LocalDate.class, + (JsonDeserializer) (json, type, jsonDeserializationContext) -> LocalDate + .parse(json.getAsJsonPrimitive().getAsString(), LINKY_LOCALDATE_FORMATTER)) + .registerTypeAdapter(LocalDateTime.class, + (JsonDeserializer) (json, type, jsonDeserializationContext) -> { + try { + return LocalDateTime.parse(json.getAsJsonPrimitive().getAsString(), + LINKY_LOCALDATETIME_FORMATTER); + } catch (Exception ex) { + return LocalDate.parse(json.getAsJsonPrimitive().getAsString(), LINKY_LOCALDATE_FORMATTER) + .atStartOfDay(); + } + }) + .create(); private final LocaleProvider localeProvider; private final HttpClient httpClient; + private final TimeZoneProvider timeZoneProvider; @Activate public LinkyHandlerFactory(final @Reference LocaleProvider localeProvider, - final @Reference HttpClientFactory httpClientFactory) { + final @Reference HttpClientFactory httpClientFactory, final @Reference TimeZoneProvider timeZoneProvider) { this.localeProvider = localeProvider; + this.timeZoneProvider = timeZoneProvider; SslContextFactory sslContextFactory = new SslContextFactory.Client(); try { SSLContext sslContext = SSLContext.getInstance("SSL"); @@ -114,7 +141,8 @@ public class LinkyHandlerFactory extends BaseThingHandlerFactory { @Override protected @Nullable ThingHandler createHandler(Thing thing) { - return supportsThingType(thing.getThingTypeUID()) ? new LinkyHandler(thing, localeProvider, gson, httpClient) + return supportsThingType(thing.getThingTypeUID()) + ? new LinkyHandler(thing, localeProvider, gson, httpClient, timeZoneProvider) : null; } } diff --git a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/api/EnedisHttpApi.java b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/api/EnedisHttpApi.java index 2c2a755d3ba..fce46ced0a9 100644 --- a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/api/EnedisHttpApi.java +++ b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/api/EnedisHttpApi.java @@ -62,7 +62,7 @@ import com.google.gson.JsonSyntaxException; */ @NonNullByDefault public class EnedisHttpApi { - private static final DateTimeFormatter API_DATE_FORMAT = DateTimeFormatter.ofPattern("dd-MM-yyyy"); + private static final DateTimeFormatter API_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); private static final String ENEDIS_DOMAIN = ".enedis.fr"; private static final String URL_APPS_LINCS = "https://alex.microapplications" + ENEDIS_DOMAIN; private static final String URL_MON_COMPTE = "https://mon-compte" + ENEDIS_DOMAIN; @@ -70,10 +70,10 @@ public class EnedisHttpApi { private static final String URL_ENEDIS_AUTHENTICATE = URL_APPS_LINCS + "/authenticate?target=" + URL_COMPTE_PART; private static final String USER_INFO_CONTRACT_URL = URL_APPS_LINCS + "/mon-compte-client/api/private/v1/userinfos"; private static final String USER_INFO_URL = URL_APPS_LINCS + "/userinfos"; - private static final String PRM_INFO_BASE_URL = URL_APPS_LINCS + "/mes-mesures/api/private/v1/personnes/"; + private static final String PRM_INFO_BASE_URL = URL_APPS_LINCS + "/mes-mesures-prm/api/private/v1/personnes/"; private static final String PRM_INFO_URL = URL_APPS_LINCS + "/mes-prms-part/api/private/v2/personnes/%s/prms"; private static final String MEASURE_URL = PRM_INFO_BASE_URL - + "%s/prms/%s/donnees-%s?dateDebut=%s&dateFin=%s&mesuretypecode=CONS"; + + "%s/prms/%s/donnees-energetiques?mesuresTypeCode=%s&mesuresCorrigees=false&typeDonnees=CONS&dateDebut=%s"; private static final URI COOKIE_URI = URI.create(URL_COMPTE_PART); private static final Pattern REQ_PATTERN = Pattern.compile("ReqID%(.*?)%26"); @@ -289,17 +289,16 @@ public class EnedisHttpApi { private Consumption getMeasures(String userId, String prmId, LocalDate from, LocalDate to, String request) throws LinkyException { - String url = String.format(MEASURE_URL, userId, prmId, request, from.format(API_DATE_FORMAT), - to.format(API_DATE_FORMAT)); + String url = String.format(MEASURE_URL, userId, prmId, request, from.format(API_DATE_FORMAT)); ConsumptionReport report = getData(url, ConsumptionReport.class); - return report.firstLevel.consumptions; + return report.consumptions; } public Consumption getEnergyData(String userId, String prmId, LocalDate from, LocalDate to) throws LinkyException { - return getMeasures(userId, prmId, from, to, "energie"); + return getMeasures(userId, prmId, from, to, "ENERGIE"); } public Consumption getPowerData(String userId, String prmId, LocalDate from, LocalDate to) throws LinkyException { - return getMeasures(userId, prmId, from, to, "pmax"); + return getMeasures(userId, prmId, from, to, "PMAX"); } } diff --git a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/dto/ConsumptionReport.java b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/dto/ConsumptionReport.java index e2d57620d2b..42529bd98d3 100644 --- a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/dto/ConsumptionReport.java +++ b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/dto/ConsumptionReport.java @@ -12,7 +12,8 @@ */ package org.openhab.binding.linky.internal.dto; -import java.time.ZonedDateTime; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; import com.google.gson.annotations.SerializedName; @@ -22,28 +23,30 @@ import com.google.gson.annotations.SerializedName; * returned by API calls * * @author Gaƫl L'hopital - Initial contribution + * @author Laurent ARNAL - fix to handle new Dto format after enedis site modifications */ public class ConsumptionReport { - public class Period { - public String grandeurPhysiqueEnum; - public ZonedDateTime dateDebut; - public ZonedDateTime dateFin; + + public class Data { + public LocalDateTime dateDebut; + public LocalDateTime dateFin; + public Double valeur; } public class Aggregate { - public List labels; - public List periodes; - public List datas; + @SerializedName("donnees") + public List datas; + public String unite; } public class ChronoData { - @SerializedName("JOUR") + @SerializedName("jour") public Aggregate days; - @SerializedName("SEMAINE") + @SerializedName("semaine") public Aggregate weeks; - @SerializedName("MOIS") + @SerializedName("mois") public Aggregate months; - @SerializedName("ANNEE") + @SerializedName("annee") public Aggregate years; } @@ -51,14 +54,10 @@ public class ConsumptionReport { public ChronoData aggregats; public String grandeurMetier; public String grandeurPhysique; - public String unite; + public LocalDate dateDebut; + public LocalDate dateFin; } - public class FirstLevel { - @SerializedName("CONS") - public Consumption consumptions; - } - - @SerializedName("1") - public FirstLevel firstLevel; + @SerializedName("cons") + public Consumption consumptions; } diff --git a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java index d38809b29a9..33cfd2f3a31 100644 --- a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java +++ b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java @@ -39,6 +39,7 @@ import org.openhab.binding.linky.internal.dto.PrmDetail; import org.openhab.binding.linky.internal.dto.PrmInfo; import org.openhab.binding.linky.internal.dto.UserInfo; import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.unit.MetricPrefix; @@ -65,6 +66,8 @@ import com.google.gson.Gson; @NonNullByDefault public class LinkyHandler extends BaseThingHandler { + private final TimeZoneProvider timeZoneProvider; + private static final int REFRESH_FIRST_HOUR_OF_DAY = 1; private static final int REFRESH_INTERVAL_IN_MIN = 120; @@ -90,11 +93,13 @@ public class LinkyHandler extends BaseThingHandler { ALL } - public LinkyHandler(Thing thing, LocaleProvider localeProvider, Gson gson, HttpClient httpClient) { + public LinkyHandler(Thing thing, LocaleProvider localeProvider, Gson gson, HttpClient httpClient, + TimeZoneProvider timeZoneProvider) { super(thing); this.gson = gson; this.httpClient = httpClient; this.weekFields = WeekFields.of(localeProvider.getLocale()); + this.timeZoneProvider = timeZoneProvider; this.cachedDailyData = new ExpiringDayCache<>("daily cache", REFRESH_FIRST_HOUR_OF_DAY, () -> { LocalDate today = LocalDate.now(); @@ -211,8 +216,9 @@ public class LinkyHandler extends BaseThingHandler { if (isLinked(PEAK_POWER) || isLinked(PEAK_TIMESTAMP)) { cachedPowerData.getValue().ifPresentOrElse(values -> { Aggregate days = values.aggregats.days; - updatekVAChannel(PEAK_POWER, days.datas.get(days.datas.size() - 1)); - updateState(PEAK_TIMESTAMP, new DateTimeType(days.periodes.get(days.datas.size() - 1).dateDebut)); + updatekVAChannel(PEAK_POWER, days.datas.get(days.datas.size() - 1).valeur); + updateState(PEAK_TIMESTAMP, new DateTimeType( + days.datas.get(days.datas.size() - 1).dateDebut.atZone(this.timeZoneProvider.getTimeZone()))); }, () -> { updateKwhChannel(PEAK_POWER, Double.NaN); updateState(PEAK_TIMESTAMP, UnDefType.UNDEF); @@ -224,9 +230,9 @@ public class LinkyHandler extends BaseThingHandler { double currentValue = 0.0; double previousValue = 0.0; if (!periods.datas.isEmpty()) { - currentValue = periods.datas.get(periods.datas.size() - 1); + currentValue = periods.datas.get(periods.datas.size() - 1).valeur; if (periods.datas.size() > 1) { - previousValue = periods.datas.get(periods.datas.size() - 2); + previousValue = periods.datas.get(periods.datas.size() - 2).valeur; } } updateKwhChannel(currentChannel, currentValue); @@ -240,7 +246,7 @@ public class LinkyHandler extends BaseThingHandler { if (isLinked(YESTERDAY) || isLinked(LAST_WEEK) || isLinked(THIS_WEEK)) { cachedDailyData.getValue().ifPresentOrElse(values -> { Aggregate days = values.aggregats.days; - updateKwhChannel(YESTERDAY, days.datas.get(days.datas.size() - 1)); + updateKwhChannel(YESTERDAY, days.datas.get(days.datas.size() - 1).valeur); setCurrentAndPrevious(values.aggregats.weeks, THIS_WEEK, LAST_WEEK); }, () -> { updateKwhChannel(YESTERDAY, Double.NaN); @@ -322,16 +328,15 @@ public class LinkyHandler extends BaseThingHandler { Consumption result = getConsumptionData(startDay, endDay.plusDays(1)); if (result != null) { Aggregate days = result.aggregats.days; - int size = (days.datas == null || days.periodes == null) ? 0 - : (days.datas.size() <= days.periodes.size() ? days.datas.size() : days.periodes.size()); + int size = (days.datas == null) ? 0 : days.datas.size(); for (int i = 0; i < size; i++) { - double consumption = days.datas.get(i); - LocalDate day = days.periodes.get(i).dateDebut.toLocalDate(); + double consumption = days.datas.get(i).valeur; + LocalDate day = days.datas.get(i).dateDebut.toLocalDate(); // Filter data in case it contains data from dates outside the requested period if (day.isBefore(startDay) || day.isAfter(endDay)) { continue; } - String line = days.periodes.get(i).dateDebut.format(DateTimeFormatter.ISO_LOCAL_DATE) + separator; + String line = days.datas.get(i).dateDebut.format(DateTimeFormatter.ISO_LOCAL_DATE) + separator; if (consumption >= 0) { line += String.valueOf(consumption); } @@ -474,50 +479,36 @@ public class LinkyHandler extends BaseThingHandler { } private void checkData(Consumption consumption) throws LinkyException { - if (consumption.aggregats.days.periodes.isEmpty()) { + if (consumption.aggregats.days.datas.isEmpty()) { throw new LinkyException("Invalid consumptions data: no day period"); } - if (consumption.aggregats.days.periodes.size() != consumption.aggregats.days.datas.size()) { - throw new LinkyException("Invalid consumptions data: not any data for each day period"); - } - if (consumption.aggregats.weeks.periodes.isEmpty()) { + if (consumption.aggregats.weeks != null && consumption.aggregats.weeks.datas.isEmpty()) { throw new LinkyException("Invalid consumptions data: no week period"); } - if (consumption.aggregats.weeks.periodes.size() != consumption.aggregats.weeks.datas.size()) { - throw new LinkyException("Invalid consumptions data: not any data for each week period"); - } - if (consumption.aggregats.months.periodes.isEmpty()) { + if (consumption.aggregats.months != null && consumption.aggregats.months.datas.isEmpty()) { throw new LinkyException("Invalid consumptions data: no month period"); } - if (consumption.aggregats.months.periodes.size() != consumption.aggregats.months.datas.size()) { - throw new LinkyException("Invalid consumptions data: not any data for each month period"); - } - if (consumption.aggregats.years.periodes.isEmpty()) { + if (consumption.aggregats.years != null && consumption.aggregats.years.datas.isEmpty()) { throw new LinkyException("Invalid consumptions data: no year period"); } - if (consumption.aggregats.years.periodes.size() != consumption.aggregats.years.datas.size()) { - throw new LinkyException("Invalid consumptions data: not any data for each year period"); - } } private boolean isDataFirstDayAvailable(Consumption consumption) { Aggregate days = consumption.aggregats.days; logData(days, "First day", false, DateTimeFormatter.ISO_LOCAL_DATE, Target.FIRST); - return days.datas != null && !days.datas.isEmpty() && !days.datas.get(0).isNaN(); + return days.datas != null && !days.datas.isEmpty() && !days.datas.get(0).valeur.isNaN(); } private boolean isDataLastDayAvailable(Consumption consumption) { Aggregate days = consumption.aggregats.days; logData(days, "Last day", false, DateTimeFormatter.ISO_LOCAL_DATE, Target.LAST); - return days.datas != null && !days.datas.isEmpty() && !days.datas.get(days.datas.size() - 1).isNaN(); + return days.datas != null && !days.datas.isEmpty() && !days.datas.get(days.datas.size() - 1).valeur.isNaN(); } private void logData(Aggregate aggregate, String title, boolean withDateFin, DateTimeFormatter dateTimeFormatter, Target target) { if (logger.isDebugEnabled()) { - int size = (aggregate.datas == null || aggregate.periodes == null) ? 0 - : (aggregate.datas.size() <= aggregate.periodes.size() ? aggregate.datas.size() - : aggregate.periodes.size()); + int size = (aggregate.datas == null) ? 0 : aggregate.datas.size(); if (target == Target.FIRST) { if (size > 0) { logData(aggregate, 0, title, withDateFin, dateTimeFormatter); @@ -537,11 +528,11 @@ public class LinkyHandler extends BaseThingHandler { private void logData(Aggregate aggregate, int index, String title, boolean withDateFin, DateTimeFormatter dateTimeFormatter) { if (withDateFin) { - logger.debug("{} {} {} value {}", title, aggregate.periodes.get(index).dateDebut.format(dateTimeFormatter), - aggregate.periodes.get(index).dateFin.format(dateTimeFormatter), aggregate.datas.get(index)); + logger.debug("{} {} {} value {}", title, aggregate.datas.get(index).dateDebut.format(dateTimeFormatter), + aggregate.datas.get(index).dateFin.format(dateTimeFormatter), aggregate.datas.get(index).valeur); } else { - logger.debug("{} {} value {}", title, aggregate.periodes.get(index).dateDebut.format(dateTimeFormatter), - aggregate.datas.get(index)); + logger.debug("{} {} value {}", title, aggregate.datas.get(index).dateDebut.format(dateTimeFormatter), + aggregate.datas.get(index).valeur); } } } From 4281d5e6014f260454293da01649652d70d9b4b2 Mon Sep 17 00:00:00 2001 From: Laurent ARNAL Date: Wed, 8 Jan 2025 11:47:18 +0100 Subject: [PATCH 2/4] add timezone to thing config to allow overriding default timezone Signed-off-by: Laurent ARNAL --- .../linky/internal/LinkyConfiguration.java | 1 + .../linky/internal/handler/LinkyHandler.java | 20 +++++++++++++++++-- .../resources/OH-INF/thing/thing-types.xml | 8 ++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyConfiguration.java b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyConfiguration.java index 3c75363fd83..8c7cd800e49 100644 --- a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyConfiguration.java +++ b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyConfiguration.java @@ -26,6 +26,7 @@ public class LinkyConfiguration { public String username = ""; public String password = ""; public String internalAuthId = ""; + public String timezone = ""; public boolean seemsValid() { return !username.isBlank() && !password.isBlank() && !internalAuthId.isBlank(); diff --git a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java index 33cfd2f3a31..193c0ccc4a5 100644 --- a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java +++ b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java @@ -16,6 +16,7 @@ import static org.openhab.binding.linky.internal.LinkyBindingConstants.*; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; @@ -38,6 +39,7 @@ import org.openhab.binding.linky.internal.dto.ConsumptionReport.Consumption; import org.openhab.binding.linky.internal.dto.PrmDetail; import org.openhab.binding.linky.internal.dto.PrmInfo; import org.openhab.binding.linky.internal.dto.UserInfo; +import org.openhab.core.config.core.Configuration; import org.openhab.core.i18n.LocaleProvider; import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.library.types.DateTimeType; @@ -67,6 +69,7 @@ import com.google.gson.Gson; @NonNullByDefault public class LinkyHandler extends BaseThingHandler { private final TimeZoneProvider timeZoneProvider; + private ZoneId zoneId = ZoneId.systemDefault(); private static final int REFRESH_FIRST_HOUR_OF_DAY = 1; private static final int REFRESH_INTERVAL_IN_MIN = 120; @@ -155,6 +158,19 @@ public class LinkyHandler extends BaseThingHandler { logger.debug("Initializing Linky handler."); updateStatus(ThingStatus.UNKNOWN); + // update the timezone if not set to default to openhab default timezone + Configuration thingConfig = getConfig(); + + Object val = thingConfig.get("timezone"); + if (val == null || "".equals(val)) { + zoneId = this.timeZoneProvider.getTimeZone(); + thingConfig.put("timezone", zoneId.getId()); + } else { + zoneId = ZoneId.of((String) val); + } + + updateConfiguration(thingConfig); + LinkyConfiguration config = getConfigAs(LinkyConfiguration.class); if (config.seemsValid()) { enedisApi = new EnedisHttpApi(config, gson, httpClient); @@ -217,8 +233,8 @@ public class LinkyHandler extends BaseThingHandler { cachedPowerData.getValue().ifPresentOrElse(values -> { Aggregate days = values.aggregats.days; updatekVAChannel(PEAK_POWER, days.datas.get(days.datas.size() - 1).valeur); - updateState(PEAK_TIMESTAMP, new DateTimeType( - days.datas.get(days.datas.size() - 1).dateDebut.atZone(this.timeZoneProvider.getTimeZone()))); + updateState(PEAK_TIMESTAMP, + new DateTimeType(days.datas.get(days.datas.size() - 1).dateDebut.atZone(zoneId))); }, () -> { updateKwhChannel(PEAK_POWER, Double.NaN); updateState(PEAK_TIMESTAMP, UnDefType.UNDEF); diff --git a/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml index fbcdbb509e3..b094796bd97 100644 --- a/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml @@ -34,6 +34,14 @@ Authentication ID delivered after the captcha (see documentation). + + + The timezone associated with your Point of delivery. + Will default to openhab default timezone. + You will need to change this if your linky is located in a different timezone that your openhab location. + You can use an offset, or a label like Europe/Paris + + From 592907a4bf24844c182c38f4b28fc4644deab8e6 Mon Sep 17 00:00:00 2001 From: Laurent ARNAL Date: Wed, 8 Jan 2025 11:49:27 +0100 Subject: [PATCH 3/4] spotless:apply Signed-off-by: Laurent ARNAL --- .../main/resources/OH-INF/thing/thing-types.xml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml index b094796bd97..8a66799dbcc 100644 --- a/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml @@ -35,13 +35,15 @@ Authentication ID delivered after the captcha (see documentation). - - The timezone associated with your Point of delivery. - Will default to openhab default timezone. - You will need to change this if your linky is located in a different timezone that your openhab location. - You can use an offset, or a label like Europe/Paris - - + + The timezone associated with your Point of delivery. + Will default to openhab default timezone. + You will + need to change this if your linky is located in a different timezone that your openhab location. + You can use an + offset, or a label like Europe/Paris + + From 40202b1641085d6fe789f8dc3b293df6524d01d5 Mon Sep 17 00:00:00 2001 From: Laurent ARNAL Date: Wed, 8 Jan 2025 12:20:01 +0100 Subject: [PATCH 4/4] fixes for Jacob review Signed-off-by: Laurent ARNAL --- .../binding/linky/internal/handler/LinkyHandler.java | 6 +++--- .../src/main/resources/OH-INF/i18n/linky.properties | 4 +++- .../src/main/resources/OH-INF/thing/thing-types.xml | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java index 193c0ccc4a5..3775a6c5d8e 100644 --- a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java +++ b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java @@ -161,12 +161,12 @@ public class LinkyHandler extends BaseThingHandler { // update the timezone if not set to default to openhab default timezone Configuration thingConfig = getConfig(); - Object val = thingConfig.get("timezone"); - if (val == null || "".equals(val)) { + String val = (String) thingConfig.get("timezone"); + if (val == null || val.isBlank()) { zoneId = this.timeZoneProvider.getTimeZone(); thingConfig.put("timezone", zoneId.getId()); } else { - zoneId = ZoneId.of((String) val); + zoneId = ZoneId.of(val); } updateConfiguration(thingConfig); diff --git a/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/i18n/linky.properties b/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/i18n/linky.properties index 9eeaf4460fd..ecf55352b3a 100644 --- a/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/i18n/linky.properties +++ b/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/i18n/linky.properties @@ -14,6 +14,8 @@ thing-type.config.linky.linky.internalAuthId.label = Auth ID thing-type.config.linky.linky.internalAuthId.description = Authentication ID delivered after the captcha (see documentation). thing-type.config.linky.linky.password.label = Password thing-type.config.linky.linky.password.description = Your Enedis Password +thing-type.config.linky.linky.timezone.label = timezone +thing-type.config.linky.linky.timezone.description = The timezone associated with your Point of delivery. Will default to openHAB default timezone. You will need to change this if your Linky is located in a different timezone that your openHAB location. You can use an offset, or a label like Europe/Paris thing-type.config.linky.linky.username.label = Username thing-type.config.linky.linky.username.description = Your Enedis Username @@ -41,6 +43,6 @@ channel-type.linky.power.label = Yesterday Peak Power channel-type.linky.power.description = Maximum power usage yesterday channel-type.linky.timestamp.label = Timestamp -# Thing status descriptions +# thing status descriptions offline.config-error-mandatory-settings = Username, password and authId are mandatory. diff --git a/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml index 8a66799dbcc..51a489096c7 100644 --- a/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.linky/src/main/resources/OH-INF/thing/thing-types.xml @@ -37,9 +37,9 @@ The timezone associated with your Point of delivery. - Will default to openhab default timezone. + Will default to openHAB default timezone. You will - need to change this if your linky is located in a different timezone that your openhab location. + need to change this if your Linky is located in a different timezone that your openHAB location. You can use an offset, or a label like Europe/Paris