Skip to content

Commit a2701a3

Browse files
committed
Add Teleinfo type input: base, hchp or tempo (automatic migration during upgrade)
1 parent e9c7be3 commit a2701a3

File tree

8 files changed

+284
-118
lines changed

8 files changed

+284
-118
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 5.0.0
4+
5+
- Add Tempo support
6+
- Add Teleinfo type input: `base`, `hchp` or `tempo` (automatic migration during upgrade)
7+
38
## 4.8.0
49

510
- Add divider factor for both meters to allow user to choose a compatible unit of measurement (example, m³ for gas instead of dm³ with a divider factor of 1000)

custom_components/ecodevices/__init__.py

+50-1
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,60 @@
2222
from homeassistant.helpers.aiohttp_client import async_get_clientsession
2323
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
2424

25-
from .const import CONTROLLER, COORDINATOR, DOMAIN, PLATFORMS, UNDO_UPDATE_LISTENER
25+
from .const import (
26+
CONF_T1_ENABLED,
27+
CONF_T1_TYPE,
28+
CONF_T2_ENABLED,
29+
CONF_T2_TYPE,
30+
CONF_TI_TYPE_BASE,
31+
CONF_TI_TYPE_HCHP,
32+
CONTROLLER,
33+
COORDINATOR,
34+
DOMAIN,
35+
PLATFORMS,
36+
UNDO_UPDATE_LISTENER,
37+
)
2638

2739
_LOGGER = logging.getLogger(__name__)
2840

2941

42+
async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
43+
"""Migrate old config entry."""
44+
45+
if entry.version == 1:
46+
_LOGGER.debug("Entry version %s needs migration", entry.version)
47+
new_options = entry.options.copy()
48+
49+
t1_enabled = new_options.get(
50+
CONF_T1_ENABLED, entry.data.get(CONF_T1_ENABLED, False)
51+
)
52+
t2_enabled = new_options.get(
53+
CONF_T2_ENABLED, entry.data.get(CONF_T2_ENABLED, False)
54+
)
55+
t1_hchp = new_options.get("t1_hchp", entry.data.get("t1_hchp", False))
56+
t2_hchp = new_options.get("t2_hchp", entry.data.get("t2_hchp", False))
57+
58+
if t1_enabled:
59+
new_options[CONF_T1_TYPE] = (
60+
CONF_TI_TYPE_HCHP if t1_hchp else CONF_TI_TYPE_BASE
61+
)
62+
_LOGGER.debug("Set T1 type to %s", new_options[CONF_T1_TYPE])
63+
if t2_enabled:
64+
new_options[CONF_T2_TYPE] = (
65+
CONF_TI_TYPE_HCHP if t2_hchp else CONF_TI_TYPE_BASE
66+
)
67+
_LOGGER.debug("Set T2 type to %s", new_options[CONF_T2_TYPE])
68+
69+
entry.version = 2
70+
71+
hass.config_entries.async_update_entry(
72+
entry, data=entry.data, options=new_options
73+
)
74+
_LOGGER.debug("Migration to version %s successful", entry.version)
75+
76+
return True
77+
78+
3079
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
3180
"""Set up Eco-Devices from a config entry."""
3281
hass.data.setdefault(DOMAIN, {})

custom_components/ecodevices/config_flow.py

+17-15
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@
3333
CONF_C2_TOTAL_UNIT_OF_MEASUREMENT,
3434
CONF_C2_UNIT_OF_MEASUREMENT,
3535
CONF_T1_ENABLED,
36-
CONF_T1_HCHP,
36+
CONF_T1_TYPE,
3737
CONF_T2_ENABLED,
38-
CONF_T2_HCHP,
38+
CONF_T2_TYPE,
39+
CONF_TI_TYPE_BASE,
40+
CONF_TI_TYPES,
3941
DEFAULT_SCAN_INTERVAL,
4042
DOMAIN,
4143
)
@@ -59,7 +61,7 @@
5961
class EcoDevicesConfigFlow(ConfigFlow, domain=DOMAIN):
6062
"""Handle a eco-devices config flow."""
6163

62-
VERSION = 1
64+
VERSION = 2
6365

6466
def __init__(self) -> None:
6567
"""Initialize class variables."""
@@ -171,13 +173,13 @@ async def async_step_params(self, user_input=None) -> FlowResult:
171173
options = self.config_entry.options
172174

173175
base_params = {
174-
CONF_T1_HCHP: options.get(
175-
CONF_T1_HCHP,
176-
config.get(CONF_T1_HCHP, False),
176+
CONF_T1_TYPE: options.get(
177+
CONF_T1_TYPE,
178+
config.get(CONF_T1_TYPE, False),
177179
),
178-
CONF_T2_HCHP: options.get(
179-
CONF_T2_HCHP,
180-
config.get(CONF_T2_HCHP, False),
180+
CONF_T2_TYPE: options.get(
181+
CONF_T2_TYPE,
182+
config.get(CONF_T2_TYPE, False),
181183
),
182184
CONF_C1_DEVICE_CLASS: options.get(
183185
CONF_C1_DEVICE_CLASS, config.get(CONF_C1_DEVICE_CLASS)
@@ -240,19 +242,19 @@ def _get_params(base_input, base_params):
240242
params_schema.update(
241243
{
242244
vol.Required(
243-
CONF_T1_HCHP,
244-
default=base_params.get(CONF_T1_HCHP, False),
245-
): bool,
245+
CONF_T1_TYPE,
246+
default=base_params.get(CONF_T1_TYPE, CONF_TI_TYPE_BASE),
247+
): vol.All(str, vol.Lower, vol.In(CONF_TI_TYPES)),
246248
}
247249
)
248250

249251
if base_input[CONF_T2_ENABLED]:
250252
params_schema.update(
251253
{
252254
vol.Required(
253-
CONF_T2_HCHP,
254-
default=base_params.get(CONF_T2_HCHP, False),
255-
): bool,
255+
CONF_T2_TYPE,
256+
default=base_params.get(CONF_T2_TYPE, CONF_TI_TYPE_BASE),
257+
): vol.All(str, vol.Lower, vol.In(CONF_TI_TYPES)),
256258
}
257259
)
258260

custom_components/ecodevices/const.py

+19-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
UNDO_UPDATE_LISTENER = "undo_update_listener"
88

99
CONF_T1_ENABLED = "t1_enabled"
10-
CONF_T1_HCHP = "t1_hchp"
10+
CONF_T1_TYPE = "t1_type"
1111
CONF_T2_ENABLED = "t2_enabled"
12-
CONF_T2_HCHP = "t2_hchp"
12+
CONF_T2_TYPE = "t2_type"
1313
CONF_C1_ENABLED = "c1_enabled"
1414
CONF_C1_UNIT_OF_MEASUREMENT = "c1_unit_of_measurement"
1515
CONF_C1_DIVIDER_FACTOR = "c1_divider_factor"
@@ -27,6 +27,15 @@
2727
DEFAULT_C2_NAME = "Meter 2"
2828
DEFAULT_SCAN_INTERVAL = 5
2929

30+
CONF_TI_TYPE_BASE = "base"
31+
CONF_TI_TYPE_HCHP = "hchp"
32+
CONF_TI_TYPE_TEMPO = "tempo"
33+
CONF_TI_TYPES = [
34+
CONF_TI_TYPE_BASE,
35+
CONF_TI_TYPE_HCHP,
36+
CONF_TI_TYPE_TEMPO,
37+
]
38+
3039
TELEINFO_EXTRA_ATTR = {
3140
"type_heures": "PTEC",
3241
"souscription": "ISOUSC",
@@ -62,3 +71,11 @@
6271
"index_heures_pleines_jour_rouge": "BBRHPJR",
6372
"type_heures_demain": "DEMAIN",
6473
}
74+
TELEINFO_TEMPO_ATTR = {
75+
"Jour Bleu HC": "BBRHCJB",
76+
"Jour Bleu HP": "BBRHPJB",
77+
"Jour Blanc HC": "BBRHCJW",
78+
"Jour Blanc HP": "BBRHPJW",
79+
"Jour Rouge HC": "BBRHCJR",
80+
"Jour Rouge HP": "BBRHPJR",
81+
}

custom_components/ecodevices/sensor.py

+103-10
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@
2929
CONF_C2_TOTAL_UNIT_OF_MEASUREMENT,
3030
CONF_C2_UNIT_OF_MEASUREMENT,
3131
CONF_T1_ENABLED,
32-
CONF_T1_HCHP,
32+
CONF_T1_TYPE,
3333
CONF_T2_ENABLED,
34-
CONF_T2_HCHP,
34+
CONF_T2_TYPE,
35+
CONF_TI_TYPE_BASE,
36+
CONF_TI_TYPE_HCHP,
37+
CONF_TI_TYPE_TEMPO,
3538
CONTROLLER,
3639
COORDINATOR,
3740
DEFAULT_C1_NAME,
@@ -40,6 +43,7 @@
4043
DEFAULT_T2_NAME,
4144
DOMAIN,
4245
TELEINFO_EXTRA_ATTR,
46+
TELEINFO_TEMPO_ATTR,
4347
)
4448

4549
_LOGGER = logging.getLogger(__name__)
@@ -56,9 +60,9 @@ async def async_setup_entry(
5660
options = entry.options
5761

5862
t1_enabled = options.get(CONF_T1_ENABLED, config.get(CONF_T1_ENABLED))
59-
t1_hchp = options.get(CONF_T1_HCHP, config.get(CONF_T1_HCHP))
63+
t1_type = options.get(CONF_T1_TYPE, config.get(CONF_T1_TYPE))
6064
t2_enabled = options.get(CONF_T2_ENABLED, config.get(CONF_T2_ENABLED))
61-
t2_hchp = options.get(CONF_T2_HCHP, config.get(CONF_T2_HCHP))
65+
t2_type = options.get(CONF_T2_TYPE, config.get(CONF_T2_TYPE))
6266
c1_enabled = options.get(CONF_C1_ENABLED, config.get(CONF_C1_ENABLED))
6367
c2_enabled = options.get(CONF_C2_ENABLED, config.get(CONF_C2_ENABLED))
6468

@@ -79,7 +83,21 @@ async def async_setup_entry(
7983
icon="mdi:flash",
8084
)
8185
)
82-
if t1_hchp:
86+
if t1_type == CONF_TI_TYPE_BASE:
87+
entities.append(
88+
TeleinfoInputTotalEdDevice(
89+
controller,
90+
coordinator,
91+
input_number=1,
92+
input_name="t1_total",
93+
name=DEFAULT_T1_NAME + " Total",
94+
unit=UnitOfEnergy.WATT_HOUR,
95+
device_class=SensorDeviceClass.ENERGY,
96+
state_class=SensorStateClass.TOTAL_INCREASING,
97+
icon="mdi:meter-electric",
98+
)
99+
)
100+
elif t1_type == CONF_TI_TYPE_HCHP:
83101
entities.append(
84102
TeleinfoInputTotalHchpEdDevice(
85103
controller,
@@ -119,9 +137,9 @@ async def async_setup_entry(
119137
icon="mdi:meter-electric",
120138
)
121139
)
122-
else:
140+
elif t1_type == CONF_TI_TYPE_TEMPO:
123141
entities.append(
124-
TeleinfoInputTotalEdDevice(
142+
TeleinfoInputTotalTempoEdDevice(
125143
controller,
126144
coordinator,
127145
input_number=1,
@@ -133,6 +151,20 @@ async def async_setup_entry(
133151
icon="mdi:meter-electric",
134152
)
135153
)
154+
for desc, key in TELEINFO_TEMPO_ATTR.items():
155+
entities.append(
156+
TeleinfoInputTempoEdDevice(
157+
controller,
158+
coordinator,
159+
input_number=1,
160+
input_name=f"t1_{key}",
161+
name=DEFAULT_T1_NAME + " " + desc + " Total",
162+
unit=UnitOfEnergy.WATT_HOUR,
163+
device_class=SensorDeviceClass.ENERGY,
164+
state_class=SensorStateClass.TOTAL_INCREASING,
165+
icon="mdi:meter-electric",
166+
)
167+
)
136168
if t2_enabled:
137169
_LOGGER.debug("Add the teleinfo 2 entities")
138170
entities.append(
@@ -148,7 +180,21 @@ async def async_setup_entry(
148180
icon="mdi:flash",
149181
)
150182
)
151-
if t2_hchp:
183+
if t2_type == CONF_TI_TYPE_BASE:
184+
entities.append(
185+
TeleinfoInputTotalEdDevice(
186+
controller,
187+
coordinator,
188+
input_number=2,
189+
input_name="t2_total",
190+
name=DEFAULT_T2_NAME + " Total",
191+
unit=UnitOfEnergy.WATT_HOUR,
192+
device_class=SensorDeviceClass.ENERGY,
193+
state_class=SensorStateClass.TOTAL_INCREASING,
194+
icon="mdi:meter-electric",
195+
)
196+
)
197+
elif t2_type == CONF_TI_TYPE_HCHP:
152198
entities.append(
153199
TeleinfoInputTotalHchpEdDevice(
154200
controller,
@@ -188,9 +234,9 @@ async def async_setup_entry(
188234
icon="mdi:meter-electric",
189235
)
190236
)
191-
else:
237+
elif t2_type == CONF_TI_TYPE_TEMPO:
192238
entities.append(
193-
TeleinfoInputTotalEdDevice(
239+
TeleinfoInputTotalTempoEdDevice(
194240
controller,
195241
coordinator,
196242
input_number=2,
@@ -202,6 +248,20 @@ async def async_setup_entry(
202248
icon="mdi:meter-electric",
203249
)
204250
)
251+
for desc, key in TELEINFO_TEMPO_ATTR.items():
252+
entities.append(
253+
TeleinfoInputTempoEdDevice(
254+
controller,
255+
coordinator,
256+
input_number=2,
257+
input_name=f"t2_{key}",
258+
name=DEFAULT_T2_NAME + " " + desc + " Total",
259+
unit=UnitOfEnergy.WATT_HOUR,
260+
device_class=SensorDeviceClass.ENERGY,
261+
state_class=SensorStateClass.TOTAL_INCREASING,
262+
icon="mdi:meter-electric",
263+
)
264+
)
205265
if c1_enabled:
206266
_LOGGER.debug("Add the Meter 1 - entities")
207267
entities.append(
@@ -484,6 +544,39 @@ def native_value(self) -> float | None:
484544
return None
485545

486546

547+
class TeleinfoInputTotalTempoEdDevice(EdDevice):
548+
"""Initialize the Teleinfo Input Tempo Total sensor."""
549+
550+
@property
551+
def native_value(self) -> float | None:
552+
"""Return the total value if it's greater than 0."""
553+
value = 0.0
554+
for key in TELEINFO_TEMPO_ATTR.values():
555+
value += float(self.coordinator.data[f"T{self._input_number}_{key}"])
556+
if value > 0:
557+
return value
558+
_LOGGER.warning(
559+
"Total value for Teleinfo Input %s not greater than 0, ignore",
560+
self._input_number,
561+
)
562+
return None
563+
564+
565+
class TeleinfoInputTempoEdDevice(EdDevice):
566+
"""Initialize the Teleinfo Input Tempo sensor."""
567+
568+
@property
569+
def native_value(self) -> float | None:
570+
"""Return the total value if it's greater than 0."""
571+
if (value := float(self.coordinator.data[self._input_name.upper()])) > 0:
572+
return value
573+
_LOGGER.warning(
574+
"Total value for Teleinfo Input %s not greater than 0, ignore",
575+
self._input_number,
576+
)
577+
return None
578+
579+
487580
class MeterInputEdDevice(EdDevice):
488581
"""Initialize the meter input sensor."""
489582

custom_components/ecodevices/strings.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
"params": {
2020
"title": "Parameters of Eco-Devices entities",
2121
"data": {
22-
"t1_hchp": "Teleinfo 1 - HC/HP enabled",
23-
"t2_hchp": "Teleinfo 2 - HC/HP enabled",
22+
"t1_type": "Teleinfo 1 - Rate type (Base, HC/HP or Tempo)",
23+
"t2_type": "Teleinfo 2 - Rate type (Base, HC/HP or Tempo)",
2424
"c1_device_class": "Meter 1 - Device Class (sensor)",
2525
"c1_unit_of_measurement": "Meter 1 - Unit of measurement for current and daily values",
2626
"c1_total_unit_of_measurement": "Meter 1 - Unit of measurement for total value",
@@ -59,8 +59,8 @@
5959
"params": {
6060
"title": "Parameters of Eco-Devices entities",
6161
"data": {
62-
"t1_hchp": "Teleinfo 1 - HC/HP enabled",
63-
"t2_hchp": "Teleinfo 2 - HC/HP enabled",
62+
"t1_type": "Teleinfo 1 - Rate type (Base, HC/HP or Tempo)",
63+
"t2_type": "Teleinfo 2 - Rate type (Base, HC/HP or Tempo)",
6464
"c1_device_class": "Meter 1 - Device Class (sensor)",
6565
"c1_unit_of_measurement": "Meter 1 - Unit of measurement for current and daily values",
6666
"c1_total_unit_of_measurement": "Meter 1 - Unit of measurement for total value",

0 commit comments

Comments
 (0)