]> git.basschouten.com Git - openhab-addons.git/commitdiff
[linky] Handle case when data from yesterday is still NaN (#9423)
authorlolodomo <lg.hc@free.fr>
Tue, 29 Dec 2020 18:43:31 +0000 (19:43 +0100)
committerGitHub <noreply@github.com>
Tue, 29 Dec 2020 18:43:31 +0000 (10:43 -0800)
* [linky] Handle case when data from yesterday is still NaN

Fix #9386
* Refresh every 2 hours until data from yesterday are available
* Log yesterday even for month and year requests

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/api/EnedisHttpApi.java
bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/console/LinkyCommandExtension.java
bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java

index 50581eabf2d5b9390ad96046fe11bda602c25f3c..2f9a706ce635825eebd36a7ed30ba900f112edf3 100644 (file)
@@ -256,6 +256,7 @@ public class EnedisHttpApi {
         if (data.isEmpty()) {
             throw new LinkyException(String.format("Requesting '%s' returned an empty response", url));
         }
+        logger.trace("getData returned {}", data);
         try {
             ConsumptionReport report = gson.fromJson(data, ConsumptionReport.class);
             return report.firstLevel.consumptions;
index 36a8ec9ab27e1dfcec067867d67d8ee0becd54e1..e0bd586d62c85ff59ed1cd481a8f42b86d4646b9 100644 (file)
@@ -80,9 +80,9 @@ public class LinkyCommandExtension extends AbstractConsoleCommandExtension {
                 console.println(String.format("'%s' is not a Linky thing id", args[0]));
                 printUsage(console);
             } else if (REPORT.equals(args[1])) {
-                LocalDate now = LocalDate.now();
-                LocalDate start = now.minusDays(7);
-                LocalDate end = now.minusDays(1);
+                LocalDate yesterday = LocalDate.now().minusDays(1);
+                LocalDate start = yesterday.minusDays(6);
+                LocalDate end = yesterday;
                 String separator = " ";
                 if (args.length >= 3) {
                     try {
@@ -104,13 +104,13 @@ public class LinkyCommandExtension extends AbstractConsoleCommandExtension {
                         return;
                     }
                 }
-                if (!start.isBefore(now) || start.isAfter(end)) {
+                if (start.isAfter(yesterday) || start.isAfter(end)) {
                     console.println("Start day must be in the past and before the end day");
                     printUsage(console);
                     return;
                 }
-                if (end.isAfter(now.minusDays(1))) {
-                    end = now.minusDays(1);
+                if (end.isAfter(yesterday)) {
+                    end = yesterday;
                 }
                 if (args.length >= 5) {
                     separator = args[4];
index 2da73b75370aaa87b31e278e9183f30539cc7cce..f2badd66e6f3f66aec529becf881df87de220712 100644 (file)
@@ -65,8 +65,8 @@ import com.google.gson.Gson;
 public class LinkyHandler extends BaseThingHandler {
     private final Logger logger = LoggerFactory.getLogger(LinkyHandler.class);
 
-    private static final int REFRESH_FIRST_HOUR_OF_DAY = 5;
-    private static final int REFRESH_INTERVAL_IN_MIN = 360;
+    private static final int REFRESH_FIRST_HOUR_OF_DAY = 1;
+    private static final int REFRESH_INTERVAL_IN_MIN = 120;
 
     private final HttpClient httpClient;
     private final Gson gson;
@@ -91,23 +91,48 @@ public class LinkyHandler extends BaseThingHandler {
 
         this.cachedDailyData = new ExpiringDayCache<>("daily cache", REFRESH_FIRST_HOUR_OF_DAY, () -> {
             LocalDate today = LocalDate.now();
-            return getConsumptionData(today.minusDays(15), today);
+            Consumption consumption = getConsumptionData(today.minusDays(15), today);
+            if (consumption != null) {
+                logData(consumption.aggregats.days, "Day", false, DateTimeFormatter.ISO_LOCAL_DATE, false);
+                logData(consumption.aggregats.weeks, "Week", true, DateTimeFormatter.ISO_LOCAL_DATE_TIME, false);
+                consumption = getConsumptionAfterChecks(consumption);
+            }
+            return consumption;
         });
 
         this.cachedPowerData = new ExpiringDayCache<>("power cache", REFRESH_FIRST_HOUR_OF_DAY, () -> {
             LocalDate to = LocalDate.now().plusDays(1);
             LocalDate from = to.minusDays(2);
-            return getPowerData(from, to);
+            Consumption consumption = getPowerData(from, to);
+            if (consumption != null) {
+                try {
+                    checkData(consumption);
+                } catch (LinkyException e) {
+                    logger.debug("Power data: {}", e.getMessage());
+                    return null;
+                }
+            }
+            return consumption;
         });
 
         this.cachedMonthlyData = new ExpiringDayCache<>("monthly cache", REFRESH_FIRST_HOUR_OF_DAY, () -> {
             LocalDate today = LocalDate.now();
-            return getConsumptionData(today.withDayOfMonth(1).minusMonths(1), today);
+            Consumption consumption = getConsumptionData(today.withDayOfMonth(1).minusMonths(1), today);
+            if (consumption != null) {
+                logData(consumption.aggregats.months, "Month", true, DateTimeFormatter.ISO_LOCAL_DATE_TIME, false);
+                consumption = getConsumptionAfterChecks(consumption);
+            }
+            return consumption;
         });
 
         this.cachedYearlyData = new ExpiringDayCache<>("yearly cache", REFRESH_FIRST_HOUR_OF_DAY, () -> {
             LocalDate today = LocalDate.now();
-            return getConsumptionData(LocalDate.of(today.getYear() - 1, 1, 1), today);
+            Consumption consumption = getConsumptionData(LocalDate.of(today.getYear() - 1, 1, 1), today);
+            if (consumption != null) {
+                logData(consumption.aggregats.years, "Year", true, DateTimeFormatter.ISO_LOCAL_DATE_TIME, false);
+                consumption = getConsumptionAfterChecks(consumption);
+            }
+            return consumption;
         });
     }
 
@@ -178,12 +203,8 @@ public class LinkyHandler extends BaseThingHandler {
         if (isLinked(PEAK_POWER) || isLinked(PEAK_TIMESTAMP)) {
             cachedPowerData.getValue().ifPresent(values -> {
                 Aggregate days = values.aggregats.days;
-                if (days.datas.size() == 0 || days.periodes.size() == 0) {
-                    logger.debug("Daily power data are without any period/data");
-                } else {
-                    updateVAChannel(PEAK_POWER, days.datas.get(0));
-                    updateState(PEAK_TIMESTAMP, new DateTimeType(days.periodes.get(0).dateDebut));
-                }
+                updateVAChannel(PEAK_POWER, days.datas.get(0));
+                updateState(PEAK_TIMESTAMP, new DateTimeType(days.periodes.get(0).dateDebut));
             });
         }
     }
@@ -192,30 +213,10 @@ public class LinkyHandler extends BaseThingHandler {
      * Request new dayly/weekly data and updates channels
      */
     private synchronized void updateDailyData() {
-        if (isLinked(YESTERDAY) || isLinked(THIS_WEEK)) {
+        if (isLinked(YESTERDAY)) {
             cachedDailyData.getValue().ifPresent(values -> {
                 Aggregate days = values.aggregats.days;
-                if (days.periodes.size() > days.datas.size()) {
-                    logger.debug("Daily data are invalid: not a data for each period");
-                    return;
-                }
-                int maxValue = days.periodes.size() - 1;
-                int thisWeekNumber = days.periodes.get(maxValue).dateDebut.get(weekFields.weekOfWeekBasedYear());
-                double yesterday = days.datas.get(maxValue);
-                double thisWeek = 0.00;
-
-                for (int i = maxValue; i >= 0; i--) {
-                    int weekNumber = days.periodes.get(i).dateDebut.get(weekFields.weekOfWeekBasedYear());
-                    if (weekNumber == thisWeekNumber) {
-                        Double value = days.datas.get(i);
-                        thisWeek += !value.isNaN() ? value : 0;
-                    } else {
-                        break;
-                    }
-                }
-
-                updateKwhChannel(YESTERDAY, yesterday);
-                updateKwhChannel(THIS_WEEK, thisWeek);
+                updateKwhChannel(YESTERDAY, days.datas.get(days.datas.size() - 1));
             });
         }
     }
@@ -224,14 +225,19 @@ public class LinkyHandler extends BaseThingHandler {
      * Request new weekly data and updates channels
      */
     private synchronized void updateWeeklyData() {
-        if (isLinked(LAST_WEEK)) {
+        if (isLinked(LAST_WEEK) || isLinked(THIS_WEEK)) {
             cachedDailyData.getValue().ifPresent(values -> {
+                Aggregate days = values.aggregats.days;
+                int idxLast = days.periodes.get(days.periodes.size() - 1).dateDebut.get(weekFields.dayOfWeek()) == 7 ? 2
+                        : 1;
                 Aggregate weeks = values.aggregats.weeks;
-                if (weeks.datas.size() > 1) {
-                    updateKwhChannel(LAST_WEEK, weeks.datas.get(1));
+                if (weeks.datas.size() > idxLast) {
+                    updateKwhChannel(LAST_WEEK, weeks.datas.get(idxLast));
+                }
+                if (weeks.datas.size() > (idxLast + 1)) {
+                    updateKwhChannel(THIS_WEEK, weeks.datas.get(idxLast + 1));
                 } else {
-                    logger.debug("Weekly data are without last week data");
-                    updateKwhChannel(LAST_WEEK, Double.NaN);
+                    updateKwhChannel(THIS_WEEK, 0.0);
                 }
             });
         }
@@ -244,18 +250,11 @@ public class LinkyHandler extends BaseThingHandler {
         if (isLinked(LAST_MONTH) || isLinked(THIS_MONTH)) {
             cachedMonthlyData.getValue().ifPresent(values -> {
                 Aggregate months = values.aggregats.months;
-                if (months.datas.size() == 0) {
-                    logger.debug("Monthly data are without any data");
-                    updateKwhChannel(LAST_MONTH, Double.NaN);
-                    updateKwhChannel(THIS_MONTH, Double.NaN);
+                updateKwhChannel(LAST_MONTH, months.datas.get(0));
+                if (months.datas.size() > 1) {
+                    updateKwhChannel(THIS_MONTH, months.datas.get(1));
                 } else {
-                    updateKwhChannel(LAST_MONTH, months.datas.get(0));
-                    if (months.datas.size() > 1) {
-                        updateKwhChannel(THIS_MONTH, months.datas.get(1));
-                    } else {
-                        logger.debug("Monthly data are without current month data");
-                        updateKwhChannel(THIS_MONTH, Double.NaN);
-                    }
+                    updateKwhChannel(THIS_MONTH, 0.0);
                 }
             });
         }
@@ -268,18 +267,11 @@ public class LinkyHandler extends BaseThingHandler {
         if (isLinked(LAST_YEAR) || isLinked(THIS_YEAR)) {
             cachedYearlyData.getValue().ifPresent(values -> {
                 Aggregate years = values.aggregats.years;
-                if (years.datas.size() == 0) {
-                    logger.debug("Yearly data are without any data");
-                    updateKwhChannel(LAST_YEAR, Double.NaN);
-                    updateKwhChannel(THIS_YEAR, Double.NaN);
+                updateKwhChannel(LAST_YEAR, years.datas.get(0));
+                if (years.datas.size() > 1) {
+                    updateKwhChannel(THIS_YEAR, years.datas.get(1));
                 } else {
-                    updateKwhChannel(LAST_YEAR, years.datas.get(0));
-                    if (years.datas.size() > 1) {
-                        updateKwhChannel(THIS_YEAR, years.datas.get(1));
-                    } else {
-                        logger.debug("Yearly data are without current year data");
-                        updateKwhChannel(THIS_YEAR, Double.NaN);
-                    }
+                    updateKwhChannel(THIS_YEAR, 0.0);
                 }
             });
         }
@@ -315,10 +307,12 @@ public class LinkyHandler extends BaseThingHandler {
         List<String> report = new ArrayList<>();
         if (startDay.getYear() == endDay.getYear() && startDay.getMonthValue() == endDay.getMonthValue()) {
             // All values in the same month
-            Consumption result = getConsumptionData(startDay, endDay);
+            Consumption result = getConsumptionData(startDay, endDay.plusDays(1));
             if (result != null) {
                 Aggregate days = result.aggregats.days;
-                for (int i = 0; i < days.datas.size(); i++) {
+                int size = (days.datas == null || days.periodes == null) ? 0
+                        : (days.datas.size() <= days.periodes.size() ? days.datas.size() : days.periodes.size());
+                for (int i = 0; i < size; i++) {
                     double consumption = days.datas.get(i);
                     String line = days.periodes.get(i).dateDebut.format(DateTimeFormatter.ISO_LOCAL_DATE) + separator;
                     if (consumption >= 0) {
@@ -354,7 +348,9 @@ public class LinkyHandler extends BaseThingHandler {
         EnedisHttpApi api = this.enedisApi;
         if (api != null) {
             try {
-                return api.getEnergyData(userId, prmId, from, to);
+                Consumption consumption = api.getEnergyData(userId, prmId, from, to);
+                updateStatus(ThingStatus.ONLINE);
+                return consumption;
             } catch (LinkyException e) {
                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage());
             }
@@ -368,7 +364,9 @@ public class LinkyHandler extends BaseThingHandler {
         EnedisHttpApi api = this.enedisApi;
         if (api != null) {
             try {
-                return api.getPowerData(userId, prmId, from, to);
+                Consumption consumption = api.getPowerData(userId, prmId, from, to);
+                updateStatus(ThingStatus.ONLINE);
+                return consumption;
             } catch (LinkyException e) {
                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage());
             }
@@ -410,10 +408,10 @@ public class LinkyHandler extends BaseThingHandler {
             boolean connectedBefore = isConnected();
             switch (channelUID.getId()) {
                 case YESTERDAY:
-                case THIS_WEEK:
                     updateDailyData();
                     break;
                 case LAST_WEEK:
+                case THIS_WEEK:
                     updateWeeklyData();
                     break;
                 case LAST_MONTH:
@@ -438,4 +436,80 @@ public class LinkyHandler extends BaseThingHandler {
             logger.debug("The Linky binding is read-only and can not handle command {}", command);
         }
     }
+
+    private @Nullable Consumption getConsumptionAfterChecks(Consumption consumption) {
+        try {
+            checkData(consumption);
+        } catch (LinkyException e) {
+            logger.debug("Consumption data: {}", e.getMessage());
+            return null;
+        }
+        if (!isDataLastDayAvailable(consumption)) {
+            logger.debug("Data including yesterday are not yet available");
+            return null;
+        }
+        return consumption;
+    }
+
+    public void checkData(Consumption consumption) throws LinkyException {
+        if (consumption.aggregats.days.periodes.size() == 0) {
+            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 one data for each day period");
+        }
+        if (consumption.aggregats.weeks.periodes.size() == 0) {
+            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 one data for each week period");
+        }
+        if (consumption.aggregats.months.periodes.size() == 0) {
+            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 one data for each month period");
+        }
+        if (consumption.aggregats.years.periodes.size() == 0) {
+            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 one data for each year period");
+        }
+    }
+
+    private boolean isDataLastDayAvailable(Consumption consumption) {
+        Aggregate days = consumption.aggregats.days;
+        logData(days, "Last day", false, DateTimeFormatter.ISO_LOCAL_DATE, true);
+        return days.datas != null && days.datas.size() > 0 && !days.datas.get(days.datas.size() - 1).isNaN();
+    }
+
+    private void logData(Aggregate aggregate, String title, boolean withDateFin, DateTimeFormatter dateTimeFormatter,
+            boolean onlyLast) {
+        if (logger.isDebugEnabled()) {
+            int size = (aggregate.datas == null || aggregate.periodes == null) ? 0
+                    : (aggregate.datas.size() <= aggregate.periodes.size() ? aggregate.datas.size()
+                            : aggregate.periodes.size());
+            if (onlyLast) {
+                if (size > 0) {
+                    logData(aggregate, size - 1, title, withDateFin, dateTimeFormatter);
+                }
+            } else {
+                for (int i = 0; i < size; i++) {
+                    logData(aggregate, i, title, withDateFin, dateTimeFormatter);
+                }
+            }
+        }
+    }
+
+    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));
+        } else {
+            logger.debug("{} {} value {}", title, aggregate.periodes.get(index).dateDebut.format(dateTimeFormatter),
+                    aggregate.datas.get(index));
+        }
+    }
 }