33
44from __future__ import annotations
55
6+ from collections .abc import Mapping
67from typing import Any
78
89import voluptuous as vol
1112from homeassistant .core import callback
1213
1314from .const import (
14- CONF_PUBLISH_INTERVAL_SECONDS ,
1515 CONF_SAMPLE_INTERVAL_SECONDS ,
1616 DEFAULT_NAME ,
1717 DEFAULT_PUBLISH_INTERVAL_SECONDS ,
2121 MAX_SAMPLE_INTERVAL ,
2222 MIN_PUBLISH_INTERVAL ,
2323 MIN_SAMPLE_INTERVAL ,
24+ PUBLISH_INTERVAL_CONF_BY_WINDOW ,
2425 UNIQUE_ID ,
26+ resolve_publish_interval ,
2527)
2628
2729
28- def _build_schema (sample_default : float , publish_default : float ) -> vol .Schema :
29- return vol .Schema (
30- {
31- vol .Required (
32- CONF_SAMPLE_INTERVAL_SECONDS ,
33- default = float (sample_default ),
34- ): vol .All (
35- vol .Coerce (float ),
36- vol .Range (min = MIN_SAMPLE_INTERVAL , max = MAX_SAMPLE_INTERVAL ),
37- ),
38- vol .Required (
39- CONF_PUBLISH_INTERVAL_SECONDS ,
40- default = float (publish_default ),
41- ): vol .All (
42- vol .Coerce (float ),
43- vol .Range (min = MIN_PUBLISH_INTERVAL , max = MAX_PUBLISH_INTERVAL ),
44- ),
45- }
46- )
30+ def _build_schema (
31+ sample_default : float , publish_defaults : Mapping [str , float ]
32+ ) -> vol .Schema :
33+ schema : dict [Any , Any ] = {
34+ vol .Required (
35+ CONF_SAMPLE_INTERVAL_SECONDS ,
36+ default = float (sample_default ),
37+ ): vol .All (
38+ vol .Coerce (float ),
39+ vol .Range (min = MIN_SAMPLE_INTERVAL , max = MAX_SAMPLE_INTERVAL ),
40+ ),
41+ }
42+ for window , conf in PUBLISH_INTERVAL_CONF_BY_WINDOW .items ():
43+ schema [vol .Required (conf , default = float (publish_defaults [window ]))] = vol .All (
44+ vol .Coerce (float ),
45+ vol .Range (min = MIN_PUBLISH_INTERVAL , max = MAX_PUBLISH_INTERVAL ),
46+ )
47+ return vol .Schema (schema )
48+
49+
50+ def _publish_error (user_input : dict [str , Any ]) -> str | None :
51+ """Each window must publish no faster than the sampler produces data."""
52+ sample_interval = float (user_input [CONF_SAMPLE_INTERVAL_SECONDS ])
53+ for conf in PUBLISH_INTERVAL_CONF_BY_WINDOW .values ():
54+ if float (user_input [conf ]) < sample_interval :
55+ return "publish_too_small"
56+ return None
4757
4858
4959@config_entries .HANDLERS .register (DOMAIN )
@@ -66,10 +76,9 @@ async def async_step_user(
6676 errors : dict [str , str ] = {}
6777
6878 if user_input is not None :
69- sample_interval = float (user_input [CONF_SAMPLE_INTERVAL_SECONDS ])
70- publish_interval = float (user_input [CONF_PUBLISH_INTERVAL_SECONDS ])
71- if publish_interval < sample_interval :
72- errors ["base" ] = "publish_too_small"
79+ error = _publish_error (user_input )
80+ if error :
81+ errors ["base" ] = error
7382 else :
7483 await self .async_set_unique_id (UNIQUE_ID )
7584 self ._abort_if_unique_id_configured ()
@@ -79,7 +88,10 @@ async def async_step_user(
7988 step_id = "user" ,
8089 data_schema = _build_schema (
8190 DEFAULT_SAMPLE_INTERVAL_SECONDS ,
82- DEFAULT_PUBLISH_INTERVAL_SECONDS ,
91+ {
92+ window : DEFAULT_PUBLISH_INTERVAL_SECONDS
93+ for window in PUBLISH_INTERVAL_CONF_BY_WINDOW
94+ },
8395 ),
8496 errors = errors ,
8597 )
@@ -95,34 +107,26 @@ async def async_step_init(
95107 errors : dict [str , str ] = {}
96108
97109 if user_input is not None :
98- sample_interval = float (user_input [CONF_SAMPLE_INTERVAL_SECONDS ])
99- publish_interval = float (user_input [CONF_PUBLISH_INTERVAL_SECONDS ])
100- if publish_interval < sample_interval :
101- errors ["base" ] = "publish_too_small"
110+ error = _publish_error (user_input )
111+ if error :
112+ errors ["base" ] = error
102113 else :
103114 return self .async_create_entry (title = "" , data = user_input )
104115
116+ source = {** self ._config_entry .data , ** self ._config_entry .options }
105117 sample_default = float (
106- self ._config_entry .options .get (
107- CONF_SAMPLE_INTERVAL_SECONDS ,
108- self ._config_entry .data .get (
109- CONF_SAMPLE_INTERVAL_SECONDS ,
110- DEFAULT_SAMPLE_INTERVAL_SECONDS ,
111- ),
112- )
113- )
114- publish_default = float (
115- self ._config_entry .options .get (
116- CONF_PUBLISH_INTERVAL_SECONDS ,
117- self ._config_entry .data .get (
118- CONF_PUBLISH_INTERVAL_SECONDS ,
119- DEFAULT_PUBLISH_INTERVAL_SECONDS ,
120- ),
121- )
118+ source .get (CONF_SAMPLE_INTERVAL_SECONDS , DEFAULT_SAMPLE_INTERVAL_SECONDS )
122119 )
120+ # Pre-existing entries only have the legacy single value;
121+ # resolve_publish_interval seeds every window from it so the form
122+ # opens reflecting the current behaviour.
123+ publish_defaults = {
124+ window : resolve_publish_interval (window , source )
125+ for window in PUBLISH_INTERVAL_CONF_BY_WINDOW
126+ }
123127
124128 return self .async_show_form (
125129 step_id = "init" ,
126- data_schema = _build_schema (sample_default , publish_default ),
130+ data_schema = _build_schema (sample_default , publish_defaults ),
127131 errors = errors ,
128132 )
0 commit comments