[Linky] Some enhancements and corrections on the linky binding (#8871)
* Some enhancements and corrections on the linky binding spotless apply Adressing code review comments * Adressing potential NPR. * Code review findings correction * Pleasing SAT checks Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
parent
adde339414
commit
5a1428dddc
@ -40,7 +40,8 @@ Instructions given for Firefox :
|
|||||||
4. Clic on "Suivant".
|
4. Clic on "Suivant".
|
||||||
5. In the login page, prefilled with your mail address, enter your Enedis account password and click on "Connexion à Espace Client Enedis".
|
5. In the login page, prefilled with your mail address, enter your Enedis account password and click on "Connexion à Espace Client Enedis".
|
||||||
6. You will be directed to your Enedis account environment. Get back to previous page in you browser.
|
6. You will be directed to your Enedis account environment. Get back to previous page in you browser.
|
||||||
7. Open the developper tool window (F12) and select "Stockage" tab. In the "Cookies" entry, select "https://mon-compte-enedis.fr". You should see an entry named "internalAuthId", copy this value in your Openhab configuration.
|
7. Disconnect from your Enedis account
|
||||||
|
8. Repeat steps 1, 2. You should arrive directly on step 5, then open the developer tool window (F12) and select "Stockage" tab. In the "Cookies" entry, select "https://mon-compte-enedis.fr". You'll find an entry named "internalAuthId", copy this value in your Openhab configuration.
|
||||||
|
|
||||||
## Channels
|
## Channels
|
||||||
|
|
||||||
|
|||||||
@ -28,9 +28,12 @@ import org.openhab.core.thing.ThingTypeUID;
|
|||||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||||
import org.openhab.core.thing.binding.ThingHandler;
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||||
|
import org.osgi.service.component.ComponentContext;
|
||||||
import org.osgi.service.component.annotations.Activate;
|
import org.osgi.service.component.annotations.Activate;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
@ -44,6 +47,8 @@ import com.google.gson.JsonDeserializer;
|
|||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.linky")
|
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.linky")
|
||||||
public class LinkyHandlerFactory extends BaseThingHandlerFactory {
|
public class LinkyHandlerFactory extends BaseThingHandlerFactory {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(LinkyHandlerFactory.class);
|
||||||
|
|
||||||
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX");
|
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX");
|
||||||
private final LocaleProvider localeProvider;
|
private final LocaleProvider localeProvider;
|
||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
@ -53,11 +58,33 @@ public class LinkyHandlerFactory extends BaseThingHandlerFactory {
|
|||||||
public LinkyHandlerFactory(final @Reference LocaleProvider localeProvider,
|
public LinkyHandlerFactory(final @Reference LocaleProvider localeProvider,
|
||||||
final @Reference HttpClientFactory httpClientFactory) {
|
final @Reference HttpClientFactory httpClientFactory) {
|
||||||
this.localeProvider = localeProvider;
|
this.localeProvider = localeProvider;
|
||||||
this.httpClient = httpClientFactory.createHttpClient(LinkyBindingConstants.BINDING_ID);
|
|
||||||
this.gson = new GsonBuilder().registerTypeAdapter(ZonedDateTime.class,
|
this.gson = new GsonBuilder().registerTypeAdapter(ZonedDateTime.class,
|
||||||
(JsonDeserializer<ZonedDateTime>) (json, type, jsonDeserializationContext) -> ZonedDateTime
|
(JsonDeserializer<ZonedDateTime>) (json, type, jsonDeserializationContext) -> ZonedDateTime
|
||||||
.parse(json.getAsJsonPrimitive().getAsString(), formatter))
|
.parse(json.getAsJsonPrimitive().getAsString(), formatter))
|
||||||
.create();
|
.create();
|
||||||
|
this.httpClient = httpClientFactory.createHttpClient(LinkyBindingConstants.BINDING_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void activate(ComponentContext componentContext) {
|
||||||
|
super.activate(componentContext);
|
||||||
|
httpClient.getSslContextFactory().setExcludeCipherSuites(new String[0]);
|
||||||
|
httpClient.setFollowRedirects(false);
|
||||||
|
try {
|
||||||
|
httpClient.start();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("Unable to start Jetty HttpClient {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void deactivate(ComponentContext componentContext) {
|
||||||
|
super.deactivate(componentContext);
|
||||||
|
try {
|
||||||
|
httpClient.stop();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("Unable to stop Jetty HttpClient {}", e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -69,10 +96,6 @@ public class LinkyHandlerFactory extends BaseThingHandlerFactory {
|
|||||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||||
|
|
||||||
if (supportsThingType(thingTypeUID)) {
|
return supportsThingType(thingTypeUID) ? new LinkyHandler(thing, localeProvider, gson, httpClient) : null;
|
||||||
return new LinkyHandler(thing, localeProvider, gson, httpClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,17 +73,6 @@ public class EnedisHttpApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() throws LinkyException {
|
public void initialize() throws LinkyException {
|
||||||
httpClient.getSslContextFactory().setExcludeCipherSuites(new String[0]);
|
|
||||||
httpClient.setFollowRedirects(false);
|
|
||||||
try {
|
|
||||||
httpClient.start();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new LinkyException("Unable to start Jetty HttpClient", e);
|
|
||||||
}
|
|
||||||
connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void connect() throws LinkyException {
|
|
||||||
addCookie(LinkyConfiguration.INTERNAL_AUTH_ID, config.internalAuthId);
|
addCookie(LinkyConfiguration.INTERNAL_AUTH_ID, config.internalAuthId);
|
||||||
|
|
||||||
logger.debug("Starting login process for user : {}", config.username);
|
logger.debug("Starting login process for user : {}", config.username);
|
||||||
@ -185,12 +174,7 @@ public class EnedisHttpApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() throws LinkyException {
|
public void dispose() throws LinkyException {
|
||||||
try {
|
disconnect();
|
||||||
disconnect();
|
|
||||||
httpClient.stop();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new LinkyException("Error stopping Jetty client", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCookie(String key, String value) {
|
private void addCookie(String key, String value) {
|
||||||
|
|||||||
@ -15,6 +15,7 @@ package org.openhab.binding.linky.internal.api;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
@ -64,7 +65,7 @@ public class ExpiringDayCache<V> {
|
|||||||
/**
|
/**
|
||||||
* Returns the value - possibly from the cache, if it is still valid.
|
* Returns the value - possibly from the cache, if it is still valid.
|
||||||
*/
|
*/
|
||||||
public synchronized @Nullable V getValue() {
|
public synchronized Optional<V> getValue() {
|
||||||
@Nullable
|
@Nullable
|
||||||
V cachedValue = value;
|
V cachedValue = value;
|
||||||
if (cachedValue == null || isExpired()) {
|
if (cachedValue == null || isExpired()) {
|
||||||
@ -73,7 +74,7 @@ public class ExpiringDayCache<V> {
|
|||||||
} else {
|
} else {
|
||||||
logger.debug("getValue from cache \"{}\" is returning a cached value", name);
|
logger.debug("getValue from cache \"{}\" is returning a cached value", name);
|
||||||
}
|
}
|
||||||
return cachedValue;
|
return Optional.ofNullable(cachedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -15,6 +15,7 @@ package org.openhab.binding.linky.internal.dto;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,12 +23,12 @@ import org.eclipse.jdt.annotation.Nullable;
|
|||||||
*
|
*
|
||||||
* @author Gaël L'hopital - Initial contribution
|
* @author Gaël L'hopital - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class AuthData {
|
public class AuthData {
|
||||||
public class AuthDataCallBack {
|
public class AuthDataCallBack {
|
||||||
public class NameValuePair {
|
public class NameValuePair {
|
||||||
public String name;
|
public @Nullable String name;
|
||||||
public Object value;
|
public @Nullable Object value;
|
||||||
|
|
||||||
public @Nullable String valueAsString() {
|
public @Nullable String valueAsString() {
|
||||||
if (value instanceof String) {
|
if (value instanceof String) {
|
||||||
@ -37,15 +38,15 @@ public class AuthData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String type;
|
public @Nullable String type;
|
||||||
|
|
||||||
public List<NameValuePair> output = new ArrayList<>();
|
public List<NameValuePair> output = new ArrayList<>();
|
||||||
public List<NameValuePair> input = new ArrayList<>();
|
public List<NameValuePair> input = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String authId;
|
public @Nullable String authId;
|
||||||
public String template;
|
public @Nullable String template;
|
||||||
public String stage;
|
public @Nullable String stage;
|
||||||
public String header;
|
public @Nullable String header;
|
||||||
public List<AuthDataCallBack> callbacks = new ArrayList<>();
|
public List<AuthDataCallBack> callbacks = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,12 +70,12 @@ public class LinkyHandler extends BaseThingHandler {
|
|||||||
|
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
|
private final WeekFields weekFields;
|
||||||
|
|
||||||
private @Nullable ScheduledFuture<?> refreshJob;
|
private @Nullable ScheduledFuture<?> refreshJob;
|
||||||
private @Nullable EnedisHttpApi enedisApi;
|
private @Nullable EnedisHttpApi enedisApi;
|
||||||
private final WeekFields weekFields;
|
|
||||||
|
|
||||||
private final ExpiringDayCache<Consumption> cachedDaylyData;
|
private final ExpiringDayCache<Consumption> cachedDailyData;
|
||||||
private final ExpiringDayCache<Consumption> cachedPowerData;
|
private final ExpiringDayCache<Consumption> cachedPowerData;
|
||||||
private final ExpiringDayCache<Consumption> cachedMonthlyData;
|
private final ExpiringDayCache<Consumption> cachedMonthlyData;
|
||||||
private final ExpiringDayCache<Consumption> cachedYearlyData;
|
private final ExpiringDayCache<Consumption> cachedYearlyData;
|
||||||
@ -87,12 +87,11 @@ public class LinkyHandler extends BaseThingHandler {
|
|||||||
super(thing);
|
super(thing);
|
||||||
this.gson = gson;
|
this.gson = gson;
|
||||||
this.httpClient = httpClient;
|
this.httpClient = httpClient;
|
||||||
|
|
||||||
this.weekFields = WeekFields.of(localeProvider.getLocale());
|
this.weekFields = WeekFields.of(localeProvider.getLocale());
|
||||||
|
|
||||||
this.cachedDaylyData = new ExpiringDayCache<>("daily cache", REFRESH_FIRST_HOUR_OF_DAY, () -> {
|
this.cachedDailyData = new ExpiringDayCache<>("daily cache", REFRESH_FIRST_HOUR_OF_DAY, () -> {
|
||||||
LocalDate today = LocalDate.now();
|
LocalDate today = LocalDate.now();
|
||||||
return getConsumptionData(today.minusDays(13), today);
|
return getConsumptionData(today.minusDays(15), today);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.cachedPowerData = new ExpiringDayCache<>("power cache", REFRESH_FIRST_HOUR_OF_DAY, () -> {
|
this.cachedPowerData = new ExpiringDayCache<>("power cache", REFRESH_FIRST_HOUR_OF_DAY, () -> {
|
||||||
@ -120,31 +119,37 @@ public class LinkyHandler extends BaseThingHandler {
|
|||||||
LinkyConfiguration config = getConfigAs(LinkyConfiguration.class);
|
LinkyConfiguration config = getConfigAs(LinkyConfiguration.class);
|
||||||
enedisApi = new EnedisHttpApi(config, gson, httpClient);
|
enedisApi = new EnedisHttpApi(config, gson, httpClient);
|
||||||
|
|
||||||
try {
|
scheduler.submit(() -> {
|
||||||
enedisApi.initialize();
|
try {
|
||||||
updateStatus(ThingStatus.ONLINE);
|
EnedisHttpApi api = this.enedisApi;
|
||||||
|
if (api != null) {
|
||||||
|
api.initialize();
|
||||||
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
|
||||||
if (thing.getProperties().isEmpty()) {
|
if (thing.getProperties().isEmpty()) {
|
||||||
Map<String, String> properties = discoverAttributes();
|
Map<String, String> properties = discoverAttributes();
|
||||||
updateProperties(properties);
|
updateProperties(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
prmId = thing.getProperties().get(PRM_ID);
|
||||||
|
userId = thing.getProperties().get(USER_ID);
|
||||||
|
|
||||||
|
final LocalDateTime now = LocalDateTime.now();
|
||||||
|
final LocalDateTime nextDayFirstTimeUpdate = now.plusDays(1).withHour(REFRESH_FIRST_HOUR_OF_DAY)
|
||||||
|
.truncatedTo(ChronoUnit.HOURS);
|
||||||
|
|
||||||
|
updateData();
|
||||||
|
|
||||||
|
refreshJob = scheduler.scheduleWithFixedDelay(this::updateData,
|
||||||
|
ChronoUnit.MINUTES.between(now, nextDayFirstTimeUpdate) % REFRESH_INTERVAL_IN_MIN + 1,
|
||||||
|
REFRESH_INTERVAL_IN_MIN, TimeUnit.MINUTES);
|
||||||
|
} else {
|
||||||
|
throw new LinkyException("Enedis Api is not initialized");
|
||||||
|
}
|
||||||
|
} catch (LinkyException e) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||||
}
|
}
|
||||||
|
});
|
||||||
prmId = thing.getProperties().get(PRM_ID);
|
|
||||||
userId = thing.getProperties().get(USER_ID);
|
|
||||||
|
|
||||||
final LocalDateTime now = LocalDateTime.now();
|
|
||||||
final LocalDateTime nextDayFirstTimeUpdate = now.plusDays(1).withHour(REFRESH_FIRST_HOUR_OF_DAY)
|
|
||||||
.truncatedTo(ChronoUnit.HOURS);
|
|
||||||
|
|
||||||
updateData();
|
|
||||||
|
|
||||||
refreshJob = scheduler.scheduleWithFixedDelay(this::updateData,
|
|
||||||
ChronoUnit.MINUTES.between(now, nextDayFirstTimeUpdate) % REFRESH_INTERVAL_IN_MIN + 1,
|
|
||||||
REFRESH_INTERVAL_IN_MIN, TimeUnit.MINUTES);
|
|
||||||
|
|
||||||
} catch (LinkyException e) {
|
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> discoverAttributes() throws LinkyException {
|
private Map<String, String> discoverAttributes() throws LinkyException {
|
||||||
@ -167,17 +172,17 @@ public class LinkyHandler extends BaseThingHandler {
|
|||||||
private void updateData() {
|
private void updateData() {
|
||||||
updatePowerData();
|
updatePowerData();
|
||||||
updateDailyData();
|
updateDailyData();
|
||||||
|
updateWeeklyData();
|
||||||
updateMonthlyData();
|
updateMonthlyData();
|
||||||
updateYearlyData();
|
updateYearlyData();
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void updatePowerData() {
|
private synchronized void updatePowerData() {
|
||||||
if (isLinked(PEAK_POWER) || isLinked(PEAK_TIMESTAMP)) {
|
if (isLinked(PEAK_POWER) || isLinked(PEAK_TIMESTAMP)) {
|
||||||
Consumption result = cachedPowerData.getValue();
|
cachedPowerData.getValue().ifPresent(values -> {
|
||||||
if (result != null) {
|
updateVAChannel(PEAK_POWER, values.aggregats.days.datas.get(0));
|
||||||
updateVAChannel(PEAK_POWER, result.aggregats.days.datas.get(0));
|
updateState(PEAK_TIMESTAMP, new DateTimeType(values.aggregats.days.periodes.get(0).dateDebut));
|
||||||
updateState(PEAK_TIMESTAMP, new DateTimeType(result.aggregats.days.periodes.get(0).dateDebut));
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,23 +190,19 @@ public class LinkyHandler extends BaseThingHandler {
|
|||||||
* Request new dayly/weekly data and updates channels
|
* Request new dayly/weekly data and updates channels
|
||||||
*/
|
*/
|
||||||
private synchronized void updateDailyData() {
|
private synchronized void updateDailyData() {
|
||||||
if (isLinked(YESTERDAY) || isLinked(LAST_WEEK) || isLinked(THIS_WEEK)) {
|
if (isLinked(YESTERDAY) || isLinked(THIS_WEEK)) {
|
||||||
Consumption result = cachedDaylyData.getValue();
|
cachedDailyData.getValue().ifPresent(values -> {
|
||||||
if (result != null) {
|
Aggregate days = values.aggregats.days;
|
||||||
Aggregate days = result.aggregats.days;
|
|
||||||
|
|
||||||
int maxValue = days.periodes.size() - 1;
|
int maxValue = days.periodes.size() - 1;
|
||||||
int thisWeekNumber = days.periodes.get(maxValue).dateDebut.get(weekFields.weekOfWeekBasedYear());
|
int thisWeekNumber = days.periodes.get(maxValue).dateDebut.get(weekFields.weekOfWeekBasedYear());
|
||||||
double yesterday = days.datas.get(maxValue);
|
double yesterday = days.datas.get(maxValue);
|
||||||
double lastWeek = 0.0;
|
double thisWeek = 0.00;
|
||||||
double thisWeek = 0.0;
|
|
||||||
|
|
||||||
for (int i = maxValue; i >= 0; i--) {
|
for (int i = maxValue; i >= 0; i--) {
|
||||||
int weekNumber = days.periodes.get(i).dateDebut.get(weekFields.weekOfWeekBasedYear());
|
int weekNumber = days.periodes.get(i).dateDebut.get(weekFields.weekOfWeekBasedYear());
|
||||||
if (weekNumber == thisWeekNumber) {
|
if (weekNumber == thisWeekNumber) {
|
||||||
thisWeek += days.datas.get(i);
|
Double value = days.datas.get(i);
|
||||||
} else if (weekNumber == thisWeekNumber - 1) {
|
thisWeek += !value.isNaN() ? value : 0;
|
||||||
lastWeek += days.datas.get(i);
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -209,8 +210,21 @@ public class LinkyHandler extends BaseThingHandler {
|
|||||||
|
|
||||||
updateKwhChannel(YESTERDAY, yesterday);
|
updateKwhChannel(YESTERDAY, yesterday);
|
||||||
updateKwhChannel(THIS_WEEK, thisWeek);
|
updateKwhChannel(THIS_WEEK, thisWeek);
|
||||||
updateKwhChannel(LAST_WEEK, lastWeek);
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request new weekly data and updates channels
|
||||||
|
*/
|
||||||
|
private synchronized void updateWeeklyData() {
|
||||||
|
if (isLinked(LAST_WEEK)) {
|
||||||
|
cachedDailyData.getValue().ifPresent(values -> {
|
||||||
|
Aggregate weeks = values.aggregats.weeks;
|
||||||
|
if (weeks.datas.size() > 1) {
|
||||||
|
updateKwhChannel(LAST_WEEK, weeks.datas.get(1));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,16 +233,15 @@ public class LinkyHandler extends BaseThingHandler {
|
|||||||
*/
|
*/
|
||||||
private synchronized void updateMonthlyData() {
|
private synchronized void updateMonthlyData() {
|
||||||
if (isLinked(LAST_MONTH) || isLinked(THIS_MONTH)) {
|
if (isLinked(LAST_MONTH) || isLinked(THIS_MONTH)) {
|
||||||
Consumption result = cachedMonthlyData.getValue();
|
cachedMonthlyData.getValue().ifPresent(values -> {
|
||||||
if (result != null) {
|
Aggregate months = values.aggregats.months;
|
||||||
Aggregate months = result.aggregats.months;
|
|
||||||
if (months.datas.size() < 2) {
|
|
||||||
logger.debug("Received data array too small (required size is 2): {}", months);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
updateKwhChannel(LAST_MONTH, months.datas.get(0));
|
updateKwhChannel(LAST_MONTH, months.datas.get(0));
|
||||||
updateKwhChannel(THIS_MONTH, months.datas.get(1));
|
if (months.datas.size() > 1) {
|
||||||
}
|
updateKwhChannel(THIS_MONTH, months.datas.get(1));
|
||||||
|
} else {
|
||||||
|
updateKwhChannel(THIS_MONTH, Double.NaN);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,26 +250,28 @@ public class LinkyHandler extends BaseThingHandler {
|
|||||||
*/
|
*/
|
||||||
private synchronized void updateYearlyData() {
|
private synchronized void updateYearlyData() {
|
||||||
if (isLinked(LAST_YEAR) || isLinked(THIS_YEAR)) {
|
if (isLinked(LAST_YEAR) || isLinked(THIS_YEAR)) {
|
||||||
Consumption result = cachedYearlyData.getValue();
|
cachedYearlyData.getValue().ifPresent(values -> {
|
||||||
if (result != null) {
|
Aggregate years = values.aggregats.years;
|
||||||
Aggregate years = result.aggregats.years;
|
|
||||||
updateKwhChannel(LAST_YEAR, years.datas.get(0));
|
updateKwhChannel(LAST_YEAR, years.datas.get(0));
|
||||||
updateKwhChannel(THIS_YEAR, years.datas.get(1));
|
if (years.datas.size() > 1) {
|
||||||
}
|
updateKwhChannel(THIS_YEAR, years.datas.get(1));
|
||||||
|
} else {
|
||||||
|
updateKwhChannel(THIS_YEAR, Double.NaN);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateKwhChannel(String channelId, double consumption) {
|
private void updateKwhChannel(String channelId, double consumption) {
|
||||||
logger.debug("Update channel {} with {}", channelId, consumption);
|
logger.debug("Update channel {} with {}", channelId, consumption);
|
||||||
updateState(channelId,
|
updateState(channelId, Double.isNaN(consumption) ? UnDefType.UNDEF
|
||||||
!Double.isNaN(consumption) ? new QuantityType<>(consumption, SmartHomeUnits.KILOWATT_HOUR)
|
: new QuantityType<>(consumption, SmartHomeUnits.KILOWATT_HOUR));
|
||||||
: UnDefType.UNDEF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateVAChannel(String channelId, double power) {
|
private void updateVAChannel(String channelId, double power) {
|
||||||
logger.debug("Update channel {} with {}", channelId, power);
|
logger.debug("Update channel {} with {}", channelId, power);
|
||||||
updateState(channelId,
|
updateState(channelId,
|
||||||
!Double.isNaN(power) ? new QuantityType<>(power, SmartHomeUnits.VOLT_AMPERE) : UnDefType.UNDEF);
|
Double.isNaN(power) ? UnDefType.UNDEF : new QuantityType<>(power, SmartHomeUnits.VOLT_AMPERE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -43,8 +43,13 @@
|
|||||||
<channel id="yesterday" typeId="consumption">
|
<channel id="yesterday" typeId="consumption">
|
||||||
<label>Yesterday Consumption</label>
|
<label>Yesterday Consumption</label>
|
||||||
</channel>
|
</channel>
|
||||||
<channel id="power" typeId="power"/>
|
<channel id="power" typeId="power">
|
||||||
<channel id="timestamp" typeId="timestamp"/>
|
<label>Maximum power usage yesterday</label>
|
||||||
|
</channel>
|
||||||
|
<channel id="timestamp" typeId="timestamp">
|
||||||
|
<label>Peak Timestamp</label>
|
||||||
|
<description>Maximum power usage timestamp</description>
|
||||||
|
</channel>
|
||||||
</channels>
|
</channels>
|
||||||
</channel-group-type>
|
</channel-group-type>
|
||||||
|
|
||||||
@ -55,7 +60,7 @@
|
|||||||
<label>This Week Consumption</label>
|
<label>This Week Consumption</label>
|
||||||
</channel>
|
</channel>
|
||||||
<channel id="lastWeek" typeId="consumption">
|
<channel id="lastWeek" typeId="consumption">
|
||||||
<label>Maximum power usage yesterday</label>
|
<label>Last Week Consumption</label>
|
||||||
</channel>
|
</channel>
|
||||||
</channels>
|
</channels>
|
||||||
</channel-group-type>
|
</channel-group-type>
|
||||||
@ -88,21 +93,21 @@
|
|||||||
<item-type>Number:Energy</item-type>
|
<item-type>Number:Energy</item-type>
|
||||||
<label>Total Consumption</label>
|
<label>Total Consumption</label>
|
||||||
<description>Consumption at given time interval</description>
|
<description>Consumption at given time interval</description>
|
||||||
<state readOnly="true" pattern="%.3f %unit%"></state>
|
<category>energy</category>
|
||||||
|
<state readOnly="true" pattern="%.3f %unit%"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="power">
|
<channel-type id="power">
|
||||||
<item-type>Number:Power</item-type>
|
<item-type>Number:Power</item-type>
|
||||||
<label>Peak Power</label>
|
<label>Peak Power</label>
|
||||||
<description>Maximum power usage yesterday</description>
|
<description>Maximum power usage yesterday</description>
|
||||||
<state readOnly="true" pattern="%.3f %unit%"></state>
|
<state readOnly="true" pattern="%.3f %unit%"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="timestamp">
|
<channel-type id="timestamp">
|
||||||
<item-type>DateTime</item-type>
|
<item-type>DateTime</item-type>
|
||||||
<label>Peak Timestamp</label>
|
<label>Timestamp</label>
|
||||||
<description>Maximum power usage timestamp</description>
|
<category>time</category>
|
||||||
<state readOnly="true">
|
<state readOnly="true"/>
|
||||||
</state>
|
|
||||||
</channel-type>
|
</channel-type>
|
||||||
</thing:thing-descriptions>
|
</thing:thing-descriptions>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user