Skip to content

Commit 6049be8

Browse files
authored
Merge pull request #23 from azebro/main
Add configurable reporting interval and live reporting features
2 parents c216689 + 9963d1e commit 6049be8

16 files changed

Lines changed: 1091 additions & 38 deletions

‎CHANGELOG.md‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Changelog
2+
3+
## [1.2.0] - 2026-03-07
4+
5+
### Changed
6+
7+
- Refactor code structure for improved readability and maintainability
8+
9+
## [1.1.1] - 2026-03-05
10+
11+
### Added
12+
13+
- Proactive midnight reset for daily energy accumulators
14+
15+
### Changed
16+
17+
- Reorder datetime imports for improved clarity
18+
- Refactor code structure for improved readability and maintainability
19+
20+
### Documentation
21+
22+
- Document `sensor.tigo_max_power` and Page 3 (Panel Power) in pv_production dashboard
23+
24+
## [1.1.0] - Previous release
25+
26+
See [v1.1.0 tag](https://github.com/azebro/pytap/releases/tag/v1.1.0).
27+
28+
## [1.0.0] - Initial release
29+
30+
See [v1.0.0 tag](https://github.com/azebro/pytap/releases/tag/v1.0.0).

‎custom_components/pytap/__init__.py‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
from homeassistant.helpers import entity_registry as er
1616

1717
from .const import (
18+
CONF_LIVE_REPORTING,
1819
CONF_MODULE_BARCODE,
1920
CONF_MODULE_PEAK_POWER,
2021
CONF_MODULE_STRING,
2122
CONF_MODULES,
23+
DEFAULT_LIVE_REPORTING,
2224
DEFAULT_PEAK_POWER,
2325
DEFAULT_STRING_NAME,
2426
DOMAIN,
@@ -32,7 +34,8 @@
3234
# Bumped from 1 → 2 when voltage/current were split into in/out variants.
3335
# Bumped from 2 → 3 when module string labels became mandatory.
3436
# Bumped from 3 → 4 when module peak_power became mandatory in config.
35-
CONFIG_ENTRY_VERSION = 4
37+
# Bumped from 4 → 5 when live_reporting toggle was added.
38+
CONFIG_ENTRY_VERSION = 5
3639

3740
# Old unique IDs that were replaced by the _in/_out split.
3841
_LEGACY_UNIQUE_ID_RENAMES: dict[str, str] = {
@@ -103,6 +106,7 @@ async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
103106
v1 → v2: voltage/current sensors split into _in/_out variants.
104107
v2 → v3: module string labels are mandatory.
105108
v3 → v4: module peak power is added with default value.
109+
v4 → v5: live_reporting toggle added (default True).
106110
"""
107111
if entry.version == 1:
108112
_LOGGER.info(
@@ -150,6 +154,16 @@ async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
150154
new_data = {**entry.data, CONF_MODULES: updated_modules}
151155
hass.config_entries.async_update_entry(entry, data=new_data, version=4)
152156

157+
if entry.version == 4:
158+
_LOGGER.info(
159+
"Migrating PyTap config entry %s from version 4 to 5",
160+
entry.entry_id,
161+
)
162+
new_data = {**entry.data}
163+
if CONF_LIVE_REPORTING not in new_data:
164+
new_data[CONF_LIVE_REPORTING] = DEFAULT_LIVE_REPORTING
165+
hass.config_entries.async_update_entry(entry, data=new_data, version=5)
166+
153167
return True
154168

155169

‎custom_components/pytap/config_flow.py‎

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
rather than a comma-separated text blob.
66
77
Flow: user (host/port) → modules_menu → add_module (repeat) → finish
8-
Options: init (menu) → add_module / remove_module → done
8+
Options: init (menu) → add_module / remove_module / change_connection /
9+
change_reporting → done
910
"""
1011

1112
from __future__ import annotations
@@ -27,13 +28,17 @@
2728
import voluptuous as vol
2829

2930
from .const import (
31+
CONF_LIVE_REPORTING,
3032
CONF_MODULE_BARCODE,
3133
CONF_MODULE_NAME,
3234
CONF_MODULE_PEAK_POWER,
3335
CONF_MODULE_STRING,
3436
CONF_MODULES,
37+
CONF_WRITE_INTERVAL,
38+
DEFAULT_LIVE_REPORTING,
3539
DEFAULT_PEAK_POWER,
3640
DEFAULT_PORT,
41+
DEFAULT_WRITE_INTERVAL,
3742
DOMAIN,
3843
)
3944

@@ -109,7 +114,7 @@ def _modules_description(modules: list[dict[str, Any]]) -> str:
109114
class PyTapConfigFlow(ConfigFlow, domain=DOMAIN):
110115
"""Handle a config flow for PyTap."""
111116

112-
VERSION = 4
117+
VERSION = 5
113118

114119
def __init__(self) -> None:
115120
"""Initialize the config flow."""
@@ -242,7 +247,13 @@ async def async_step_init(
242247
"""Show the options menu: change connection / add / remove / done."""
243248
return self.async_show_menu(
244249
step_id="init",
245-
menu_options=["change_connection", "add_module", "remove_module", "done"],
250+
menu_options=[
251+
"change_connection",
252+
"change_reporting",
253+
"add_module",
254+
"remove_module",
255+
"done",
256+
],
246257
description_placeholders={
247258
"modules_list": _modules_description(self._modules),
248259
},
@@ -308,6 +319,54 @@ async def async_step_change_connection(
308319
errors=errors,
309320
)
310321

322+
async def async_step_change_reporting(
323+
self, user_input: dict[str, Any] | None = None
324+
) -> ConfigFlowResult:
325+
"""Allow the user to change reporting settings.
326+
327+
Presents a 'Live reporting' checkbox (default ON) that delivers
328+
readings as they arrive. When unchecked, a write_interval field
329+
appears and readings are cached, then pushed as a time-weighted
330+
average every ``write_interval`` seconds.
331+
"""
332+
if user_input is not None:
333+
new_data = {**self._config_entry.data}
334+
live = user_input.get(CONF_LIVE_REPORTING, DEFAULT_LIVE_REPORTING)
335+
new_data[CONF_LIVE_REPORTING] = live
336+
if live:
337+
# Live mode — clear any stored interval
338+
new_data.pop(CONF_WRITE_INTERVAL, None)
339+
else:
340+
new_data[CONF_WRITE_INTERVAL] = user_input.get(
341+
CONF_WRITE_INTERVAL, DEFAULT_WRITE_INTERVAL
342+
)
343+
self.hass.config_entries.async_update_entry(
344+
self._config_entry, data=new_data
345+
)
346+
return await self.async_step_init()
347+
348+
current_live = self._config_entry.data.get(
349+
CONF_LIVE_REPORTING, DEFAULT_LIVE_REPORTING
350+
)
351+
current_write_interval = self._config_entry.data.get(
352+
CONF_WRITE_INTERVAL, DEFAULT_WRITE_INTERVAL
353+
)
354+
schema = vol.Schema(
355+
{
356+
vol.Optional(
357+
CONF_LIVE_REPORTING, default=current_live
358+
): bool,
359+
vol.Optional(
360+
CONF_WRITE_INTERVAL, default=current_write_interval
361+
): vol.All(vol.Coerce(int), vol.Range(min=5, max=300)),
362+
}
363+
)
364+
365+
return self.async_show_form(
366+
step_id="change_reporting",
367+
data_schema=schema,
368+
)
369+
311370
async def async_step_add_module(
312371
self, user_input: dict[str, Any] | None = None
313372
) -> ConfigFlowResult:

‎custom_components/pytap/const.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
CONF_HOST = "host"
88
CONF_PORT = "port"
99
CONF_MODULES = "modules"
10+
CONF_LIVE_REPORTING = "live_reporting"
11+
CONF_WRITE_INTERVAL = "write_interval"
1012

1113
# Module dict keys
1214
CONF_MODULE_STRING = "string"
@@ -19,6 +21,8 @@
1921
DEFAULT_STRING_NAME = "Default"
2022
DEFAULT_PEAK_POWER = 455
2123
DEFAULT_SCAN_INTERVAL = 30
24+
DEFAULT_LIVE_REPORTING = True
25+
DEFAULT_WRITE_INTERVAL = 30
2226
RECONNECT_TIMEOUT = 60
2327
RECONNECT_DELAY = 5
2428
RECONNECT_RETRIES = 0

0 commit comments

Comments
 (0)