mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[French Govt Energy Data] New binding (#16713)
Signed-off-by: Gaël L'hopital <gael@lhopital.org> Signed-off-by: clinique <gael@lhopital.org> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
5085c8d711
commit
1d6670f1cd
@ -119,6 +119,7 @@
|
||||
/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
|
||||
|
@ -586,6 +586,11 @@
|
||||
<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>
|
||||
|
13
bundles/org.openhab.binding.frenchgovtenergydata/NOTICE
Normal file
13
bundles/org.openhab.binding.frenchgovtenergydata/NOTICE
Normal file
@ -0,0 +1,13 @@
|
||||
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
|
72
bundles/org.openhab.binding.frenchgovtenergydata/README.md
Normal file
72
bundles/org.openhab.binding.frenchgovtenergydata/README.md
Normal file
@ -0,0 +1,72 @@
|
||||
# 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"}
|
||||
```
|
||||
|
||||
|
17
bundles/org.openhab.binding.frenchgovtenergydata/pom.xml
Normal file
17
bundles/org.openhab.binding.frenchgovtenergydata/pom.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?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>
|
@ -0,0 +1,9 @@
|
||||
<?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>
|
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* 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");
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<?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>
|
@ -0,0 +1,48 @@
|
||||
# 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
|
@ -0,0 +1,117 @@
|
||||
<?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>
|
@ -151,6 +151,7 @@
|
||||
<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>
|
||||
|
Loading…
Reference in New Issue
Block a user