/bundles/org.openhab.binding.freebox/ @lolodomo
/bundles/org.openhab.binding.freeboxos/ @clinique
/bundles/org.openhab.binding.freecurrency/ @J-N-K
+/bundles/org.openhab.binding.frenchgovtenergydata/ @clinique
/bundles/org.openhab.binding.fronius/ @trokohl
/bundles/org.openhab.binding.fsinternetradio/ @paphko
/bundles/org.openhab.binding.ftpupload/ @paulianttila
<artifactId>org.openhab.binding.freecurrency</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.openhab.addons.bundles</groupId>
+ <artifactId>org.openhab.binding.frenchgovtenergydata</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.fronius</artifactId>
--- /dev/null
+This content is produced and maintained by the openHAB project.
+
+* Project home: https://www.openhab.org
+
+== Declared Project Licenses
+
+This program and the accompanying materials are made available under the terms
+of the Eclipse Public License 2.0 which is available at
+https://www.eclipse.org/legal/epl-2.0/.
+
+== Source Code
+
+https://github.com/openhab/openhab-addons
--- /dev/null
+# French Government Energy Data Binding
+
+This binding provides regulated electricity prices in France.
+
+This can be used to plan energy consumption, for example to calculate the cheapest period for running a dishwasher or charging an EV.
+
+## Supported Things
+
+The binding offers things for the two usual tariff classes (proposed by example by EDF).
+
+- `base`: This is the basic subscription with a fixed kWh price.
+- `hphc`: Alternative subscription offering variable price in a given hour set (low hours/high hours).
+
+
+## Thing Configuration
+
+Things (both `base` and `hphc`) only offers the configuration of the power output of the electrical delivery point (Linky terminal).
+
+| Name | Type | Description | Default | Required |
+|-----------------------|---------|---------------------------------------------|---------------|----------|
+| puissance | integer | PDL power output (in kVA) | 6 | no |
+
+
+## Channels
+
+### `base` Tariff Thing
+
+All channels are read-only.
+
+| Channel | Type | Description | Advanced |
+|--------------|--------------------|-----------------------------------------|----------|
+| fixed-ttc | Number:Currency | Yearly fixed price including taxes | No |
+| variable-ttc | Number:EnergyPrice | Energy price in €/kWh including taxes | No |
+| tariff-start | DateTime | Beginning date for this tariff | Yes |
+| fixed-ht | Number:Currency | Yearly fixed price excluding taxes | Yes |
+| variable-ht | Number:EnergyPrice | Energy price in €/kWh excluding taxes | Yes |
+
+
+### `hphc` Tariff Thing
+
+All channels are read-only.
+
+| Channel | Type | Description | Advanced |
+|--------------|--------------------|----------------------------------------------------|----------|
+| fixed-ttc | Number:Currency | Yearly fixed price including taxes | No |
+| hc-ttc | Number:EnergyPrice | Low hours energy price in €/kWh including taxes | No |
+| hp-ttc | Number:EnergyPrice | High hours energy price in €/kWh including taxes | No |
+| tariff-start | DateTime | Beginning date for this tariff | Yes |
+| fixed-ht | Number:Currency | Yearly fixed price excluding taxes | Yes |
+| hc-ht | Number:EnergyPrice | Low hours energy price in €/kWh excluding taxes | Yes |
+| hp-ht | Number:EnergyPrice | High hours energy price in €/kWh excluding taxes | Yes |
+
+
+## Full Example
+
+
+### Thing Configuration
+
+```java
+Thing frenchgovtenergydata:hphc:local "Tarification Actuelle HP/HC" [puissance=9]
+```
+
+### Item Configuration
+
+```java
+DateTime Tarif_Start { channel="frenchgovtenergydata:hphc:local:tariff-start" }
+Number:Currency Abonnement_Annuel {channel="frenchgovtenergydata:hphc:local:fixed-ttc"}
+Number:EnergyPrice Prix_Heure_Pleine {channel="frenchgovtenergydata:hphc:local:hp-ttc"}
+Number:EnergyPrice Prix_Heure_Creuse {channel="frenchgovtenergydata:hphc:local:hc-ttc"}
+```
+
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.openhab.addons.bundles</groupId>
+ <artifactId>org.openhab.addons.reactor.bundles</artifactId>
+ <version>4.2.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.openhab.binding.frenchgovtenergydata</artifactId>
+
+ <name>openHAB Add-ons :: Bundles :: French Government Energy Data Binding</name>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<features name="org.openhab.binding.frenchgovtenergydata-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
+ <repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
+
+ <feature name="openhab-binding-frenchgovtenergydata" description="French Government Energy Data Binding" version="${project.version}">
+ <feature>openhab-runtime-base</feature>
+ <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.frenchgovtenergydata/${project.version}</bundle>
+ </feature>
+</features>
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.frenchgovtenergydata.internal;
+
+import java.util.Currency;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.ThingTypeUID;
+
+/**
+ * The {@link FrenchGovtEnergyDataBindingConstants} class defines common constants, which are
+ * used across the whole binding.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class FrenchGovtEnergyDataBindingConstants {
+
+ private static final String BINDING_ID = "frenchgovtenergydata";
+
+ // List of all Thing Type UIDs
+ public static final ThingTypeUID THING_TYPE_BASE = new ThingTypeUID(BINDING_ID, "base");
+ public static final ThingTypeUID THING_TYPE_HPHC = new ThingTypeUID(BINDING_ID, "hphc");
+
+ // List of all Channel ids
+ public static final String CHANNEL_TARIFF_START = "tariff-start";
+ public static final String CHANNEL_FIXED_HT = "fixed-ht";
+ public static final String CHANNEL_FIXED_TTC = "fixed-ttc";
+ public static final String CHANNEL_VARIABLE_HT = "variable-ht";
+ public static final String CHANNEL_VARIABLE_TTC = "variable-ttc";
+ public static final String CHANNEL_HC_HT = "hc-ht";
+ public static final String CHANNEL_HC_TTC = "hc-ttc";
+ public static final String CHANNEL_HP_HT = "hp-ht";
+ public static final String CHANNEL_HP_TTC = "hp-ttc";
+
+ public static final Currency CURRENCY_EUR = Currency.getInstance("EUR");
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.frenchgovtenergydata.internal;
+
+import static org.openhab.binding.frenchgovtenergydata.internal.FrenchGovtEnergyDataBindingConstants.*;
+
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.frenchgovtenergydata.internal.handler.BaseTariffHandler;
+import org.openhab.binding.frenchgovtenergydata.internal.handler.HpHcTariffHandler;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingTypeUID;
+import org.openhab.core.thing.binding.BaseThingHandlerFactory;
+import org.openhab.core.thing.binding.ThingHandler;
+import org.openhab.core.thing.binding.ThingHandlerFactory;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * The {@link FrenchGovtEnergyDataHandlerFactory} is responsible for creating things and thing handlers.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+@Component(configurationPid = "binding.frenchgovtenergydata", service = ThingHandlerFactory.class)
+public class FrenchGovtEnergyDataHandlerFactory extends BaseThingHandlerFactory {
+
+ private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_BASE, THING_TYPE_HPHC);
+
+ @Override
+ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
+ return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
+ }
+
+ @Override
+ protected @Nullable ThingHandler createHandler(Thing thing) {
+ ThingTypeUID thingTypeUID = thing.getThingTypeUID();
+
+ return THING_TYPE_BASE.equals(thingTypeUID) ? new BaseTariffHandler(thing)
+ : THING_TYPE_HPHC.equals(thingTypeUID) ? new HpHcTariffHandler(thing) : null;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.frenchgovtenergydata.internal.dto;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link BaseTariff} holds base price informations
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class BaseTariff extends Tariff {
+ public final double variableHT;
+ public final double variableTTC;
+
+ public BaseTariff(String line) {
+ super(line, 7);
+ try {
+ this.variableHT = Double.parseDouble(values[5]);
+ this.variableTTC = Double.parseDouble(values[6]);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Incorrect data in '%s'".formatted(line), e);
+ }
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.frenchgovtenergydata.internal.dto;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link HpHcTariff} holds HP-HC price informations
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class HpHcTariff extends Tariff {
+ public final double hcHT;
+ public final double hcTTC;
+ public final double hpHT;
+ public final double hpTTC;
+
+ public HpHcTariff(String line) {
+ super(line, 9);
+ try {
+ this.hcHT = Double.parseDouble(values[5]);
+ this.hcTTC = Double.parseDouble(values[6]);
+ this.hpHT = Double.parseDouble(values[7]);
+ this.hpTTC = Double.parseDouble(values[8]);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Incorrect data in '%s'".formatted(line), e);
+ }
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.frenchgovtenergydata.internal.dto;
+
+import java.time.LocalDate;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * The {@link Tariff} is the base class holding common information for Tariffs
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class Tariff {
+ protected static final DateTimeFormatter TARIFF_DATE_FORMAT = DateTimeFormatter.ofPattern("dd/MM/yyyy");
+
+ protected final String[] values;
+ public final ZonedDateTime dateDebut;
+ public final @Nullable ZonedDateTime dateFin;
+ public final int puissance;
+ public final double fixeHT;
+ public final double fixeTTC;
+
+ public Tariff(String line, int lenControl) {
+ this.values = line.replace(',', '.').split(";");
+ if (values.length == lenControl) {
+ try {
+ this.dateDebut = LocalDate.parse(values[0], TARIFF_DATE_FORMAT).atStartOfDay(ZoneOffset.UTC);
+ this.dateFin = !values[1].isEmpty()
+ ? LocalDate.parse(values[1], TARIFF_DATE_FORMAT).atStartOfDay(ZoneOffset.UTC)
+ : null;
+ this.puissance = Integer.parseInt(values[2]);
+ this.fixeHT = Double.parseDouble(values[3]);
+ this.fixeTTC = Double.parseDouble(values[4]);
+ } catch (NumberFormatException | DateTimeParseException e) {
+ throw new IllegalArgumentException("Incorrect data in '%s'".formatted(line), e);
+ }
+ } else {
+ throw new IllegalArgumentException("Unexpected number of data, %d expected".formatted(lenControl));
+ }
+ }
+
+ public boolean isActive() {
+ return dateFin == null;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.frenchgovtenergydata.internal.handler;
+
+import static org.openhab.binding.frenchgovtenergydata.internal.FrenchGovtEnergyDataBindingConstants.*;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.frenchgovtenergydata.internal.dto.BaseTariff;
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.unit.CurrencyUnits;
+import org.openhab.core.thing.Thing;
+
+/**
+ * The {@link BaseTariffHandler} is responsible for handling commands, which are
+ * sent to one of the channels.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class BaseTariffHandler extends TariffHandler<BaseTariff> {
+ private static final String DATASET_ID = "c13d05e5-9e55-4d03-bf7e-042a2ade7e49";
+
+ public BaseTariffHandler(Thing thing) {
+ super(thing, DATASET_ID);
+ }
+
+ @Override
+ protected Stream<BaseTariff> interpretLines(List<String> lines) {
+ return lines.stream().map(BaseTariff::new);
+ }
+
+ @Override
+ protected void updateChannels(BaseTariff tariff) {
+ super.updateChannels(tariff);
+ updateState(CHANNEL_VARIABLE_HT, new QuantityType<>(tariff.variableHT, CurrencyUnits.BASE_ENERGY_PRICE));
+ updateState(CHANNEL_VARIABLE_TTC, new QuantityType<>(tariff.variableTTC, CurrencyUnits.BASE_ENERGY_PRICE));
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.frenchgovtenergydata.internal.handler;
+
+import static org.openhab.binding.frenchgovtenergydata.internal.FrenchGovtEnergyDataBindingConstants.*;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.frenchgovtenergydata.internal.dto.HpHcTariff;
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.unit.CurrencyUnits;
+import org.openhab.core.thing.Thing;
+
+/**
+ * The {@link HpHcTariffHandler} is responsible for handling commands, which are
+ * sent to one of the channels.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class HpHcTariffHandler extends TariffHandler<HpHcTariff> {
+ private static final String EMPTY_LINE = ";;;;;;;;";
+ private static final String DATASET_ID = "f7303b3a-93c7-4242-813d-84919034c416";
+
+ public HpHcTariffHandler(Thing thing) {
+ super(thing, DATASET_ID);
+ }
+
+ @Override
+ protected Stream<HpHcTariff> interpretLines(List<String> lines) {
+ return lines.stream().filter(line -> !line.equals(EMPTY_LINE)).map(HpHcTariff::new);
+ }
+
+ @Override
+ protected void updateChannels(HpHcTariff tariff) {
+ super.updateChannels(tariff);
+ updateState(CHANNEL_HP_HT, new QuantityType<>(tariff.hpHT, CurrencyUnits.BASE_ENERGY_PRICE));
+ updateState(CHANNEL_HP_TTC, new QuantityType<>(tariff.hpTTC, CurrencyUnits.BASE_ENERGY_PRICE));
+ updateState(CHANNEL_HC_HT, new QuantityType<>(tariff.hcHT, CurrencyUnits.BASE_ENERGY_PRICE));
+ updateState(CHANNEL_HC_TTC, new QuantityType<>(tariff.hcTTC, CurrencyUnits.BASE_ENERGY_PRICE));
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.frenchgovtenergydata.internal.handler;
+
+import static org.openhab.binding.frenchgovtenergydata.internal.FrenchGovtEnergyDataBindingConstants.*;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.ws.rs.HttpMethod;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.frenchgovtenergydata.internal.dto.Tariff;
+import org.openhab.core.io.net.http.HttpUtil;
+import org.openhab.core.library.types.DateTimeType;
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.unit.CurrencyUnits;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingStatus;
+import org.openhab.core.thing.ThingStatusDetail;
+import org.openhab.core.thing.ThingUID;
+import org.openhab.core.thing.binding.BaseThingHandler;
+import org.openhab.core.types.Command;
+import org.openhab.core.types.RefreshType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link TariffHandler} is the base class for Tariff Things. It takes care of
+ * update logic and update scheduling once a day.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public abstract class TariffHandler<T extends Tariff> extends BaseThingHandler {
+ private static final String URL = "https://www.data.gouv.fr/fr/datasets/r/%s";
+ private static final int REFRESH_FIRST_HOUR_OF_DAY = 0;
+ private static final int REFRESH_FIRST_MINUTE_OF_DAY = 1;
+
+ private final Logger logger = LoggerFactory.getLogger(TariffHandler.class);
+ private final List<T> tariffs = new ArrayList<>();
+ private final String url;
+
+ private Optional<ScheduledFuture<?>> refreshJob = Optional.empty();
+ private @Nullable String fileCache = null;
+ private int puissance = 6;
+
+ public TariffHandler(Thing thing, String dataset) {
+ super(thing);
+ this.url = URL.formatted(dataset);
+ }
+
+ @Override
+ public void initialize() {
+ updateStatus(ThingStatus.UNKNOWN);
+ Object confPower = getConfig().get("puissance");
+ puissance = confPower != null ? ((BigDecimal) confPower).intValue() : 6;
+ refreshJob = Optional.of(scheduler.schedule(this::updateData, 1, TimeUnit.SECONDS));
+ }
+
+ @Override
+ public void dispose() {
+ refreshJob.ifPresent(job -> job.cancel(true));
+ refreshJob = Optional.empty();
+ super.dispose();
+ }
+
+ private @Nullable String readFile() {
+ @Nullable
+ String result = null;
+ try {
+ result = HttpUtil.executeUrl(HttpMethod.GET, url, 10000);
+ fileCache = result;
+ } catch (IOException e) {
+ // Use the cache if we had an error accessing the cloud resource
+ result = fileCache;
+ }
+ return result;
+ }
+
+ private void updateData() {
+ ThingUID thingUID = getThing().getUID();
+ logger.debug("Updating {} channels", thingUID);
+
+ @Nullable
+ String result = readFile();
+ if (result != null) {
+ List<String> lines = new ArrayList<>(Arrays.asList(result.split("\r\n")));
+ lines.remove(0);
+
+ List<T> newTariffs = interpretLines(lines).collect(Collectors.toList());
+ if (!newTariffs.isEmpty()) {
+ tariffs.clear();
+ tariffs.addAll(newTariffs);
+ }
+
+ tariffs.stream().filter(t -> t.puissance == puissance).filter(Tariff::isActive).findFirst().ifPresentOrElse(
+ this::updateChannels,
+ () -> updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "No active tariff"));
+
+ ZonedDateTime now = ZonedDateTime.now();
+ ZonedDateTime nextUpdate = now.plusDays(1).withHour(REFRESH_FIRST_HOUR_OF_DAY)
+ .withMinute(REFRESH_FIRST_MINUTE_OF_DAY).truncatedTo(ChronoUnit.MINUTES);
+ long delay = ChronoUnit.MINUTES.between(now, nextUpdate);
+ logger.debug("Scheduling next {} update in {} minutes", thingUID, delay);
+ refreshJob = Optional.of(scheduler.schedule(this::updateData, delay, TimeUnit.MINUTES));
+ } else {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+ "Unable to access %s".formatted(url));
+ }
+ }
+
+ protected void updateChannels(T tariff) {
+ updateStatus(ThingStatus.ONLINE);
+ updateState(CHANNEL_TARIFF_START, new DateTimeType(tariff.dateDebut));
+ updateState(CHANNEL_FIXED_HT, new QuantityType<>(tariff.fixeHT, CurrencyUnits.BASE_CURRENCY));
+ updateState(CHANNEL_FIXED_TTC, new QuantityType<>(tariff.fixeTTC, CurrencyUnits.BASE_CURRENCY));
+ }
+
+ protected abstract Stream<T> interpretLines(List<String> lines);
+
+ @Override
+ public void handleCommand(ChannelUID channelUID, Command command) {
+ if (RefreshType.REFRESH.equals(command)) {
+ updateData();
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<addon:addon id="frenchgovtenergydata" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
+ xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
+
+ <type>binding</type>
+ <name>French Government Energy Data Binding</name>
+ <description>This binding provides French regulated electricity tariffs.</description>
+ <connection>cloud</connection>
+ <countries>fr</countries>
+
+</addon:addon>
--- /dev/null
+# add-on
+
+addon.frenchgovtenergydata.name = French Government Energy Data Binding
+addon.frenchgovtenergydata.description = This binding provides French regulated electricity tariffs.
+
+# thing types
+
+thing-type.frenchgovtenergydata.base.label = Base Tariff
+thing-type.frenchgovtenergydata.base.description = Default Tariff Subscription
+thing-type.frenchgovtenergydata.base.channel.fixed-ht.label = Fixed Price HT
+thing-type.frenchgovtenergydata.base.channel.fixed-ht.description = Yearly fixed price excluding taxes.
+thing-type.frenchgovtenergydata.base.channel.fixed-ttc.label = Fixed Price TTC
+thing-type.frenchgovtenergydata.base.channel.fixed-ttc.description = Yearly fixed price including taxes.
+thing-type.frenchgovtenergydata.base.channel.variable-ht.label = Variable Price HT
+thing-type.frenchgovtenergydata.base.channel.variable-ht.description = Energy price in €/kWh excluding taxes.
+thing-type.frenchgovtenergydata.base.channel.variable-ttc.label = Variable Price TTC
+thing-type.frenchgovtenergydata.base.channel.variable-ttc.description = Energy price in €/kWh including taxes.
+thing-type.frenchgovtenergydata.hphc.label = HP-HC Tariff
+thing-type.frenchgovtenergydata.hphc.description = High / Low usage Tariff Subscription
+thing-type.frenchgovtenergydata.hphc.channel.fixed-ht.label = Fixed Price HT
+thing-type.frenchgovtenergydata.hphc.channel.fixed-ht.description = Yearly fixed price excluding taxes.
+thing-type.frenchgovtenergydata.hphc.channel.fixed-ttc.label = Fixed Price TTC
+thing-type.frenchgovtenergydata.hphc.channel.fixed-ttc.description = Yearly fixed price including taxes.
+thing-type.frenchgovtenergydata.hphc.channel.hc-ht.label = Low Hours Price HT
+thing-type.frenchgovtenergydata.hphc.channel.hc-ht.description = Low hours energy price in €/kWh excluding taxes.
+thing-type.frenchgovtenergydata.hphc.channel.hc-ttc.label = Low Hours Price TTC
+thing-type.frenchgovtenergydata.hphc.channel.hc-ttc.description = Low hours energy price in €/kWh including taxes.
+thing-type.frenchgovtenergydata.hphc.channel.hp-ht.label = High Hours Price HT
+thing-type.frenchgovtenergydata.hphc.channel.hp-ht.description = High hours energy price in €/kWh excluding taxes.
+thing-type.frenchgovtenergydata.hphc.channel.hp-ttc.label = High Hours Price TTC
+thing-type.frenchgovtenergydata.hphc.channel.hp-ttc.description = High hours energy price in €/kWh including taxes.
+
+# thing types config
+
+thing-type.config.frenchgovtenergydata.base.puissance.label = Power output
+thing-type.config.frenchgovtenergydata.base.puissance.description = PDL power output (in kVA)
+thing-type.config.frenchgovtenergydata.hphc.puissance.label = Power Output
+thing-type.config.frenchgovtenergydata.hphc.puissance.description = PDL power output (in kVA)
+
+# channel types
+
+channel-type.frenchgovtenergydata.energy-price-ht.label = Variable Price HT
+channel-type.frenchgovtenergydata.energy-price-ttc.label = Variable Price TTC
+channel-type.frenchgovtenergydata.price-ht.label = Price HT
+channel-type.frenchgovtenergydata.price-ttc.label = Price TTC
+channel-type.frenchgovtenergydata.timestamp.label = Tariff Start
+channel-type.frenchgovtenergydata.timestamp.description = Beginning date for this tariff
+channel-type.frenchgovtenergydata.timestamp.state.pattern = %1$tY-%1$tm-%1$td
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="frenchgovtenergydata"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+ <thing-type id="base">
+ <label>Base Tariff</label>
+ <description>Default Tariff Subscription</description>
+
+ <channels>
+ <channel id="tariff-start" typeId="timestamp"/>
+ <channel id="fixed-ht" typeId="price-ht">
+ <label>Fixed Price HT</label>
+ <description>Yearly fixed price excluding taxes.</description>
+ </channel>
+ <channel id="fixed-ttc" typeId="price-ttc">
+ <label>Fixed Price TTC</label>
+ <description>Yearly fixed price including taxes.</description>
+ </channel>
+ <channel id="variable-ht" typeId="energy-price-ht">
+ <label>Variable Price HT</label>
+ <description>Energy price in €/kWh excluding taxes.</description>
+ </channel>
+ <channel id="variable-ttc" typeId="energy-price-ttc">
+ <label>Variable Price TTC</label>
+ <description>Energy price in €/kWh including taxes.</description>
+ </channel>
+ </channels>
+
+ <config-description>
+ <parameter name="puissance" type="integer" min="3" max="36">
+ <default>6</default>
+ <label>Power output</label>
+ <description>PDL power output (in kVA)</description>
+ </parameter>
+ </config-description>
+ </thing-type>
+
+ <thing-type id="hphc">
+ <label>HP-HC Tariff</label>
+ <description>High / Low usage Tariff Subscription</description>
+
+ <channels>
+ <channel id="tariff-start" typeId="timestamp"/>
+ <channel id="fixed-ht" typeId="price-ht">
+ <label>Fixed Price HT</label>
+ <description>Yearly fixed price excluding taxes.</description>
+ </channel>
+ <channel id="fixed-ttc" typeId="price-ttc">
+ <label>Fixed Price TTC</label>
+ <description>Yearly fixed price including taxes.</description>
+ </channel>
+ <channel id="hc-ht" typeId="energy-price-ht">
+ <label>Low Hours Price HT</label>
+ <description>Low hours energy price in €/kWh excluding taxes.</description>
+ </channel>
+ <channel id="hc-ttc" typeId="energy-price-ttc">
+ <label>Low Hours Price TTC</label>
+ <description>Low hours energy price in €/kWh including taxes.</description>
+ </channel>
+ <channel id="hp-ht" typeId="energy-price-ht">
+ <label>High Hours Price HT</label>
+ <description>High hours energy price in €/kWh excluding taxes.</description>
+ </channel>
+ <channel id="hp-ttc" typeId="energy-price-ttc">
+ <label>High Hours Price TTC</label>
+ <description>High hours energy price in €/kWh including taxes.</description>
+ </channel>
+ </channels>
+
+ <config-description>
+ <parameter name="puissance" type="integer" min="3" max="36">
+ <default>6</default>
+ <label>Power Output</label>
+ <description>PDL power output (in kVA)</description>
+ </parameter>
+ </config-description>
+ </thing-type>
+
+ <channel-type id="price-ht" advanced="true">
+ <item-type>Number:Currency</item-type>
+ <label>Price HT</label>
+ <category>Price</category>
+ <state readOnly="true" pattern="%.2f %unit%"></state>
+ </channel-type>
+
+ <channel-type id="price-ttc">
+ <item-type>Number:Currency</item-type>
+ <label>Price TTC</label>
+ <category>Price</category>
+ <state readOnly="true" pattern="%.2f %unit%"></state>
+ </channel-type>
+
+ <channel-type id="timestamp" advanced="true">
+ <item-type>DateTime</item-type>
+ <label>Tariff Start</label>
+ <description>Beginning date for this tariff</description>
+ <category>Time</category>
+ <state readOnly="true" pattern="%1$tY-%1$tm-%1$td"/>
+ </channel-type>
+
+ <channel-type id="energy-price-ht" advanced="true">
+ <item-type>Number:EnergyPrice</item-type>
+ <label>Variable Price HT</label>
+ <category>Price</category>
+ <state readOnly="true" pattern="%.4f %unit%"></state>
+ </channel-type>
+
+ <channel-type id="energy-price-ttc">
+ <item-type>Number:EnergyPrice</item-type>
+ <label>Variable Price TTC</label>
+ <category>Price</category>
+ <state readOnly="true" pattern="%.4f %unit%"></state>
+ </channel-type>
+
+</thing:thing-descriptions>
<module>org.openhab.binding.freebox</module>
<module>org.openhab.binding.freeboxos</module>
<module>org.openhab.binding.freecurrency</module>
+ <module>org.openhab.binding.frenchgovtenergydata</module>
<module>org.openhab.binding.fronius</module>
<module>org.openhab.binding.fsinternetradio</module>
<module>org.openhab.binding.ftpupload</module>