Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[linky] Handle case when data from yesterday is still NaN #9423

Merged
merged 13 commits into from
Dec 29, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,15 @@ private Consumption getMeasures(String userId, String prmId, LocalDate from, Loc
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);
try {
report.checkData();
} catch (LinkyException e) {
throw new LinkyException(
String.format("Requesting '%s' returned an invalid response: %s", url, e.getMessage()));
}
return report.firstLevel.consumptions;
} catch (JsonSyntaxException e) {
logger.debug("invalid JSON response not matching ConsumptionReport.class: {}", data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ public void execute(String[] args, Console console) {
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 {
Expand All @@ -104,13 +104,13 @@ public void execute(String[] args, Console console) {
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];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import java.time.ZonedDateTime;
import java.util.List;

import org.openhab.binding.linky.internal.LinkyException;

import com.google.gson.annotations.SerializedName;

/**
Expand Down Expand Up @@ -61,4 +63,32 @@ public class FirstLevel {

@SerializedName("1")
public FirstLevel firstLevel;

public void checkData() throws LinkyException {
Consumption cons = firstLevel.consumptions;
if (cons.aggregats.days.periodes.size() == 0) {
throw new LinkyException("invalid consumptions data: no day period");
}
if (cons.aggregats.days.periodes.size() != cons.aggregats.days.datas.size()) {
throw new LinkyException("invalid consumptions data: not one data for each day period");
}
if (cons.aggregats.weeks.periodes.size() == 0) {
throw new LinkyException("invalid consumptions data: no week period");
}
if (cons.aggregats.weeks.periodes.size() != cons.aggregats.weeks.datas.size()) {
throw new LinkyException("invalid consumptions data: not one data for each week period");
}
if (cons.aggregats.months.periodes.size() == 0) {
throw new LinkyException("invalid consumptions data: no month period");
}
if (cons.aggregats.months.periodes.size() != cons.aggregats.months.datas.size()) {
throw new LinkyException("invalid consumptions data: not one data for each month period");
}
if (cons.aggregats.years.periodes.size() == 0) {
throw new LinkyException("invalid consumptions data: no year period");
}
if (cons.aggregats.years.periodes.size() != cons.aggregats.years.datas.size()) {
throw new LinkyException("invalid consumptions data: not one data for each year period");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@
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;
Expand All @@ -91,7 +91,29 @@ public LinkyHandler(Thing thing, LocaleProvider localeProvider, Gson gson, HttpC

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) {
Aggregate days = consumption.aggregats.days;
Aggregate weeks = consumption.aggregats.weeks;
if (logger.isDebugEnabled()) {
for (int i = 0; i < days.datas.size(); i++) {
logger.debug("Day {} value {}",
days.periodes.get(i).dateDebut.format(DateTimeFormatter.ISO_LOCAL_DATE),
days.datas.get(i));
}
for (int i = 0; i < weeks.datas.size(); i++) {
logger.debug("Weeek {} {} value {}",
weeks.periodes.get(i).dateDebut.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
weeks.periodes.get(i).dateFin.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
weeks.datas.get(i));
}
}
if (days.datas.get(days.datas.size() - 1).isNaN()) {
lolodomo marked this conversation as resolved.
Show resolved Hide resolved
logger.debug("Dayly data including yesterday are not yet available");
consumption = null;
}
}
return consumption;
});

this.cachedPowerData = new ExpiringDayCache<>("power cache", REFRESH_FIRST_HOUR_OF_DAY, () -> {
Expand All @@ -102,12 +124,50 @@ public LinkyHandler(Thing thing, LocaleProvider localeProvider, Gson gson, HttpC

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) {
Aggregate days = consumption.aggregats.days;
Aggregate months = consumption.aggregats.months;
if (logger.isDebugEnabled()) {
logger.debug("Day {} value {}", days.periodes.get(days.periodes.size() - 1).dateDebut
.format(DateTimeFormatter.ISO_LOCAL_DATE), days.datas.get(days.datas.size() - 1));
for (int i = 0; i < months.datas.size(); i++) {
logger.debug("Month {} {} value {}",
months.periodes.get(i).dateDebut.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
months.periodes.get(i).dateFin.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
months.datas.get(i));
}
}
if (days.datas.get(days.datas.size() - 1).isNaN()) {
logger.debug("Monthly data including yesterday are not yet available");
consumption = null;
}
lolodomo marked this conversation as resolved.
Show resolved Hide resolved
}
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) {
Aggregate days = consumption.aggregats.days;
Aggregate years = consumption.aggregats.years;
if (logger.isDebugEnabled()) {
logger.debug("Day {} value {}", days.periodes.get(days.periodes.size() - 1).dateDebut
.format(DateTimeFormatter.ISO_LOCAL_DATE), days.datas.get(days.datas.size() - 1));
for (int i = 0; i < years.datas.size(); i++) {
logger.debug("Year {} {} value {}",
years.periodes.get(i).dateDebut.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
years.periodes.get(i).dateFin.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
years.datas.get(i));
}
}
if (days.datas.get(days.datas.size() - 1).isNaN()) {
lolodomo marked this conversation as resolved.
Show resolved Hide resolved
logger.debug("Yearly data including yesterday are not yet available");
consumption = null;
}
}
return consumption;
});
}

Expand Down Expand Up @@ -178,12 +238,8 @@ private synchronized void updatePowerData() {
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));
});
}
}
Expand All @@ -192,30 +248,10 @@ private synchronized void updatePowerData() {
* 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));
});
}
}
Expand All @@ -224,14 +260,19 @@ private synchronized void updateDailyData() {
* 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);
}
});
}
Expand All @@ -244,18 +285,11 @@ private synchronized void updateMonthlyData() {
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);
}
});
}
Expand All @@ -268,18 +302,11 @@ private synchronized void updateYearlyData() {
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);
}
});
}
Expand Down Expand Up @@ -315,7 +342,7 @@ private List<String> buildReport(LocalDate startDay, LocalDate endDay, @Nullable
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++) {
Expand Down Expand Up @@ -410,10 +437,10 @@ public synchronized void handleCommand(ChannelUID channelUID, Command command) {
boolean connectedBefore = isConnected();
switch (channelUID.getId()) {
case YESTERDAY:
case THIS_WEEK:
updateDailyData();
break;
case LAST_WEEK:
case THIS_WEEK:
updateWeeklyData();
break;
case LAST_MONTH:
Expand Down