Configurable KNX Telegram history size (#93248)
* Configurable KNX Telegram history size * Add maximum value to description
This commit is contained in:
parent
3bf9eaffdf
commit
b10e73e2d4
6 changed files with 83 additions and 25 deletions
|
@ -60,6 +60,7 @@ from .const import (
|
||||||
CONF_KNX_SECURE_USER_ID,
|
CONF_KNX_SECURE_USER_ID,
|
||||||
CONF_KNX_SECURE_USER_PASSWORD,
|
CONF_KNX_SECURE_USER_PASSWORD,
|
||||||
CONF_KNX_STATE_UPDATER,
|
CONF_KNX_STATE_UPDATER,
|
||||||
|
CONF_KNX_TELEGRAM_LOG_SIZE,
|
||||||
CONF_KNX_TUNNELING,
|
CONF_KNX_TUNNELING,
|
||||||
CONF_KNX_TUNNELING_TCP,
|
CONF_KNX_TUNNELING_TCP,
|
||||||
CONF_KNX_TUNNELING_TCP_SECURE,
|
CONF_KNX_TUNNELING_TCP_SECURE,
|
||||||
|
@ -68,6 +69,7 @@ from .const import (
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
KNX_ADDRESS,
|
KNX_ADDRESS,
|
||||||
SUPPORTED_PLATFORMS,
|
SUPPORTED_PLATFORMS,
|
||||||
|
TELEGRAM_LOG_DEFAULT,
|
||||||
)
|
)
|
||||||
from .device import KNXInterfaceDevice
|
from .device import KNXInterfaceDevice
|
||||||
from .expose import KNXExposeSensor, KNXExposeTime, create_knx_exposure
|
from .expose import KNXExposeSensor, KNXExposeTime, create_knx_exposure
|
||||||
|
@ -384,7 +386,12 @@ class KNXModule:
|
||||||
self.xknx.connection_manager.register_connection_state_changed_cb(
|
self.xknx.connection_manager.register_connection_state_changed_cb(
|
||||||
self.connection_state_changed_cb
|
self.connection_state_changed_cb
|
||||||
)
|
)
|
||||||
self.telegrams = Telegrams(hass, self.xknx, self.project)
|
self.telegrams = Telegrams(
|
||||||
|
hass=hass,
|
||||||
|
xknx=self.xknx,
|
||||||
|
project=self.project,
|
||||||
|
log_size=entry.data.get(CONF_KNX_TELEGRAM_LOG_SIZE, TELEGRAM_LOG_DEFAULT),
|
||||||
|
)
|
||||||
self.interface_device = KNXInterfaceDevice(
|
self.interface_device = KNXInterfaceDevice(
|
||||||
hass=hass, entry=entry, xknx=self.xknx
|
hass=hass, entry=entry, xknx=self.xknx
|
||||||
)
|
)
|
||||||
|
|
|
@ -49,12 +49,15 @@ from .const import (
|
||||||
CONF_KNX_SECURE_USER_ID,
|
CONF_KNX_SECURE_USER_ID,
|
||||||
CONF_KNX_SECURE_USER_PASSWORD,
|
CONF_KNX_SECURE_USER_PASSWORD,
|
||||||
CONF_KNX_STATE_UPDATER,
|
CONF_KNX_STATE_UPDATER,
|
||||||
|
CONF_KNX_TELEGRAM_LOG_SIZE,
|
||||||
CONF_KNX_TUNNEL_ENDPOINT_IA,
|
CONF_KNX_TUNNEL_ENDPOINT_IA,
|
||||||
CONF_KNX_TUNNELING,
|
CONF_KNX_TUNNELING,
|
||||||
CONF_KNX_TUNNELING_TCP,
|
CONF_KNX_TUNNELING_TCP,
|
||||||
CONF_KNX_TUNNELING_TCP_SECURE,
|
CONF_KNX_TUNNELING_TCP_SECURE,
|
||||||
DEFAULT_ROUTING_IA,
|
DEFAULT_ROUTING_IA,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
TELEGRAM_LOG_DEFAULT,
|
||||||
|
TELEGRAM_LOG_MAX,
|
||||||
KNXConfigEntryData,
|
KNXConfigEntryData,
|
||||||
)
|
)
|
||||||
from .schema import ia_validator, ip_v4_validator
|
from .schema import ia_validator, ip_v4_validator
|
||||||
|
@ -70,6 +73,7 @@ DEFAULT_ENTRY_DATA = KNXConfigEntryData(
|
||||||
rate_limit=CONF_KNX_DEFAULT_RATE_LIMIT,
|
rate_limit=CONF_KNX_DEFAULT_RATE_LIMIT,
|
||||||
route_back=False,
|
route_back=False,
|
||||||
state_updater=CONF_KNX_DEFAULT_STATE_UPDATER,
|
state_updater=CONF_KNX_DEFAULT_STATE_UPDATER,
|
||||||
|
telegram_log_size=TELEGRAM_LOG_DEFAULT,
|
||||||
)
|
)
|
||||||
|
|
||||||
CONF_KEYRING_FILE: Final = "knxkeys_file"
|
CONF_KEYRING_FILE: Final = "knxkeys_file"
|
||||||
|
@ -203,7 +207,11 @@ class KNXCommonFlow(ABC, FlowHandler):
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_tunnel(self, user_input: dict | None = None) -> FlowResult:
|
async def async_step_tunnel(self, user_input: dict | None = None) -> FlowResult:
|
||||||
"""Select a tunnel from a list. Will be skipped if the gateway scan was unsuccessful or if only one gateway was found."""
|
"""Select a tunnel from a list.
|
||||||
|
|
||||||
|
Will be skipped if the gateway scan was unsuccessful
|
||||||
|
or if only one gateway was found.
|
||||||
|
"""
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
if user_input[CONF_KNX_GATEWAY] == OPTION_MANUAL_TUNNEL:
|
if user_input[CONF_KNX_GATEWAY] == OPTION_MANUAL_TUNNEL:
|
||||||
if self._found_tunnels:
|
if self._found_tunnels:
|
||||||
|
@ -804,6 +812,7 @@ class KNXOptionsFlow(KNXCommonFlow, OptionsFlow):
|
||||||
self.new_entry_data = KNXConfigEntryData(
|
self.new_entry_data = KNXConfigEntryData(
|
||||||
state_updater=user_input[CONF_KNX_STATE_UPDATER],
|
state_updater=user_input[CONF_KNX_STATE_UPDATER],
|
||||||
rate_limit=user_input[CONF_KNX_RATE_LIMIT],
|
rate_limit=user_input[CONF_KNX_RATE_LIMIT],
|
||||||
|
telegram_log_size=user_input[CONF_KNX_TELEGRAM_LOG_SIZE],
|
||||||
)
|
)
|
||||||
return self.finish_flow()
|
return self.finish_flow()
|
||||||
|
|
||||||
|
@ -811,15 +820,13 @@ class KNXOptionsFlow(KNXCommonFlow, OptionsFlow):
|
||||||
vol.Required(
|
vol.Required(
|
||||||
CONF_KNX_STATE_UPDATER,
|
CONF_KNX_STATE_UPDATER,
|
||||||
default=self.initial_data.get(
|
default=self.initial_data.get(
|
||||||
CONF_KNX_STATE_UPDATER,
|
CONF_KNX_STATE_UPDATER, CONF_KNX_DEFAULT_STATE_UPDATER
|
||||||
CONF_KNX_DEFAULT_STATE_UPDATER,
|
|
||||||
),
|
),
|
||||||
): selector.BooleanSelector(),
|
): selector.BooleanSelector(),
|
||||||
vol.Required(
|
vol.Required(
|
||||||
CONF_KNX_RATE_LIMIT,
|
CONF_KNX_RATE_LIMIT,
|
||||||
default=self.initial_data.get(
|
default=self.initial_data.get(
|
||||||
CONF_KNX_RATE_LIMIT,
|
CONF_KNX_RATE_LIMIT, CONF_KNX_DEFAULT_RATE_LIMIT
|
||||||
CONF_KNX_DEFAULT_RATE_LIMIT,
|
|
||||||
),
|
),
|
||||||
): vol.All(
|
): vol.All(
|
||||||
selector.NumberSelector(
|
selector.NumberSelector(
|
||||||
|
@ -831,9 +838,27 @@ class KNXOptionsFlow(KNXCommonFlow, OptionsFlow):
|
||||||
),
|
),
|
||||||
vol.Coerce(int),
|
vol.Coerce(int),
|
||||||
),
|
),
|
||||||
|
vol.Required(
|
||||||
|
CONF_KNX_TELEGRAM_LOG_SIZE,
|
||||||
|
default=self.initial_data.get(
|
||||||
|
CONF_KNX_TELEGRAM_LOG_SIZE, TELEGRAM_LOG_DEFAULT
|
||||||
|
),
|
||||||
|
): vol.All(
|
||||||
|
selector.NumberSelector(
|
||||||
|
selector.NumberSelectorConfig(
|
||||||
|
min=0,
|
||||||
|
max=TELEGRAM_LOG_MAX,
|
||||||
|
mode=selector.NumberSelectorMode.BOX,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
vol.Coerce(int),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="communication_settings",
|
step_id="communication_settings",
|
||||||
data_schema=vol.Schema(data_schema),
|
data_schema=vol.Schema(data_schema),
|
||||||
last_step=True,
|
last_step=True,
|
||||||
|
description_placeholders={
|
||||||
|
"telegram_log_size_max": f"{TELEGRAM_LOG_MAX}",
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -52,6 +52,10 @@ CONF_KNX_DEFAULT_RATE_LIMIT: Final = 0
|
||||||
|
|
||||||
DEFAULT_ROUTING_IA: Final = "0.0.240"
|
DEFAULT_ROUTING_IA: Final = "0.0.240"
|
||||||
|
|
||||||
|
CONF_KNX_TELEGRAM_LOG_SIZE: Final = "telegram_log_size"
|
||||||
|
TELEGRAM_LOG_DEFAULT: Final = 50
|
||||||
|
TELEGRAM_LOG_MAX: Final = 5000 # ~2 MB or ~5 hours of reasonable bus load
|
||||||
|
|
||||||
##
|
##
|
||||||
# Secure constants
|
# Secure constants
|
||||||
##
|
##
|
||||||
|
@ -88,23 +92,26 @@ class KNXConfigEntryData(TypedDict, total=False):
|
||||||
|
|
||||||
connection_type: str
|
connection_type: str
|
||||||
individual_address: str
|
individual_address: str
|
||||||
local_ip: str | None
|
local_ip: str | None # not required
|
||||||
multicast_group: str
|
multicast_group: str
|
||||||
multicast_port: int
|
multicast_port: int
|
||||||
route_back: bool
|
route_back: bool # not required
|
||||||
|
host: str # only required for tunnelling
|
||||||
|
port: int # only required for tunnelling
|
||||||
|
tunnel_endpoint_ia: str | None
|
||||||
|
# KNX secure
|
||||||
|
user_id: int | None # not required
|
||||||
|
user_password: str | None # not required
|
||||||
|
device_authentication: str | None # not required
|
||||||
|
knxkeys_filename: str # not required
|
||||||
|
knxkeys_password: str # not required
|
||||||
|
backbone_key: str | None # not required
|
||||||
|
sync_latency_tolerance: int | None # not required
|
||||||
|
# OptionsFlow only
|
||||||
state_updater: bool
|
state_updater: bool
|
||||||
rate_limit: int
|
rate_limit: int
|
||||||
host: str
|
# Integration only (not forwarded to xknx)
|
||||||
port: int
|
telegram_log_size: int # not required
|
||||||
tunnel_endpoint_ia: str | None
|
|
||||||
|
|
||||||
user_id: int | None
|
|
||||||
user_password: str | None
|
|
||||||
device_authentication: str | None
|
|
||||||
knxkeys_filename: str
|
|
||||||
knxkeys_password: str
|
|
||||||
backbone_key: str | None
|
|
||||||
sync_latency_tolerance: int | None
|
|
||||||
|
|
||||||
|
|
||||||
class KNXBusMonitorMessage(TypedDict):
|
class KNXBusMonitorMessage(TypedDict):
|
||||||
|
|
|
@ -133,11 +133,13 @@
|
||||||
"title": "Communication settings",
|
"title": "Communication settings",
|
||||||
"data": {
|
"data": {
|
||||||
"state_updater": "State updater",
|
"state_updater": "State updater",
|
||||||
"rate_limit": "Rate limit"
|
"rate_limit": "Rate limit",
|
||||||
|
"telegram_log_size": "Telegram history limit"
|
||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"state_updater": "Set default for reading states from the KNX Bus. When disabled, Home Assistant will not actively retrieve entity states from the KNX Bus. Can be overridden by `sync_state` entity options.",
|
"state_updater": "Set default for reading states from the KNX Bus. When disabled, Home Assistant will not actively retrieve entity states from the KNX Bus. Can be overridden by `sync_state` entity options.",
|
||||||
"rate_limit": "Maximum outgoing telegrams per second.\n`0` to disable limit. Recommended: 0 or 20 to 40"
|
"rate_limit": "Maximum outgoing telegrams per second.\n`0` to disable limit. Recommended: 0 or 20 to 40",
|
||||||
|
"telegram_log_size": "Telegrams to keep in memory for KNX panel group monitor. Maximum: {telegram_log_size_max}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"connection_type": {
|
"connection_type": {
|
||||||
|
|
|
@ -35,7 +35,13 @@ class TelegramDict(TypedDict):
|
||||||
class Telegrams:
|
class Telegrams:
|
||||||
"""Class to handle KNX telegrams."""
|
"""Class to handle KNX telegrams."""
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, xknx: XKNX, project: KNXProject) -> None:
|
def __init__(
|
||||||
|
self,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
xknx: XKNX,
|
||||||
|
project: KNXProject,
|
||||||
|
log_size: int,
|
||||||
|
) -> None:
|
||||||
"""Initialize Telegrams class."""
|
"""Initialize Telegrams class."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.project = project
|
self.project = project
|
||||||
|
@ -46,7 +52,7 @@ class Telegrams:
|
||||||
match_for_outgoing=True,
|
match_for_outgoing=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.recent_telegrams: deque[TelegramDict] = deque(maxlen=50)
|
self.recent_telegrams: deque[TelegramDict] = deque(maxlen=log_size)
|
||||||
|
|
||||||
async def _xknx_telegram_cb(self, telegram: Telegram) -> None:
|
async def _xknx_telegram_cb(self, telegram: Telegram) -> None:
|
||||||
"""Handle incoming and outgoing telegrams from xknx."""
|
"""Handle incoming and outgoing telegrams from xknx."""
|
||||||
|
|
|
@ -37,6 +37,7 @@ from homeassistant.components.knx.const import (
|
||||||
CONF_KNX_SECURE_USER_ID,
|
CONF_KNX_SECURE_USER_ID,
|
||||||
CONF_KNX_SECURE_USER_PASSWORD,
|
CONF_KNX_SECURE_USER_PASSWORD,
|
||||||
CONF_KNX_STATE_UPDATER,
|
CONF_KNX_STATE_UPDATER,
|
||||||
|
CONF_KNX_TELEGRAM_LOG_SIZE,
|
||||||
CONF_KNX_TUNNEL_ENDPOINT_IA,
|
CONF_KNX_TUNNEL_ENDPOINT_IA,
|
||||||
CONF_KNX_TUNNELING,
|
CONF_KNX_TUNNELING,
|
||||||
CONF_KNX_TUNNELING_TCP,
|
CONF_KNX_TUNNELING_TCP,
|
||||||
|
@ -820,7 +821,6 @@ async def test_tunneling_setup_for_multiple_found_gateways(
|
||||||
CONF_PORT: 3675,
|
CONF_PORT: 3675,
|
||||||
CONF_KNX_INDIVIDUAL_ADDRESS: "0.0.240",
|
CONF_KNX_INDIVIDUAL_ADDRESS: "0.0.240",
|
||||||
CONF_KNX_ROUTE_BACK: False,
|
CONF_KNX_ROUTE_BACK: False,
|
||||||
CONF_KNX_LOCAL_IP: None,
|
|
||||||
CONF_KNX_TUNNEL_ENDPOINT_IA: None,
|
CONF_KNX_TUNNEL_ENDPOINT_IA: None,
|
||||||
CONF_KNX_SECURE_DEVICE_AUTHENTICATION: None,
|
CONF_KNX_SECURE_DEVICE_AUTHENTICATION: None,
|
||||||
CONF_KNX_SECURE_USER_ID: None,
|
CONF_KNX_SECURE_USER_ID: None,
|
||||||
|
@ -900,9 +900,17 @@ async def test_form_with_automatic_connection_handling(
|
||||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||||
assert result2["title"] == CONF_KNX_AUTOMATIC.capitalize()
|
assert result2["title"] == CONF_KNX_AUTOMATIC.capitalize()
|
||||||
assert result2["data"] == {
|
assert result2["data"] == {
|
||||||
**DEFAULT_ENTRY_DATA,
|
# don't use **DEFAULT_ENTRY_DATA here to check for correct usage of defaults
|
||||||
CONF_KNX_CONNECTION_TYPE: CONF_KNX_AUTOMATIC,
|
CONF_KNX_CONNECTION_TYPE: CONF_KNX_AUTOMATIC,
|
||||||
|
CONF_KNX_INDIVIDUAL_ADDRESS: "0.0.240",
|
||||||
|
CONF_KNX_LOCAL_IP: None,
|
||||||
|
CONF_KNX_MCAST_PORT: DEFAULT_MCAST_PORT,
|
||||||
|
CONF_KNX_MCAST_GRP: DEFAULT_MCAST_GRP,
|
||||||
|
CONF_KNX_RATE_LIMIT: 0,
|
||||||
|
CONF_KNX_ROUTE_BACK: False,
|
||||||
CONF_KNX_TUNNEL_ENDPOINT_IA: None,
|
CONF_KNX_TUNNEL_ENDPOINT_IA: None,
|
||||||
|
CONF_KNX_STATE_UPDATER: True,
|
||||||
|
CONF_KNX_TELEGRAM_LOG_SIZE: 50,
|
||||||
}
|
}
|
||||||
knx_setup.assert_called_once()
|
knx_setup.assert_called_once()
|
||||||
|
|
||||||
|
@ -1202,6 +1210,7 @@ async def test_options_flow_connection_type(
|
||||||
CONF_KNX_SECURE_DEVICE_AUTHENTICATION: None,
|
CONF_KNX_SECURE_DEVICE_AUTHENTICATION: None,
|
||||||
CONF_KNX_SECURE_USER_ID: None,
|
CONF_KNX_SECURE_USER_ID: None,
|
||||||
CONF_KNX_SECURE_USER_PASSWORD: None,
|
CONF_KNX_SECURE_USER_PASSWORD: None,
|
||||||
|
CONF_KNX_TELEGRAM_LOG_SIZE: 50,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1331,6 +1340,7 @@ async def test_options_communication_settings(
|
||||||
user_input={
|
user_input={
|
||||||
CONF_KNX_STATE_UPDATER: False,
|
CONF_KNX_STATE_UPDATER: False,
|
||||||
CONF_KNX_RATE_LIMIT: 40,
|
CONF_KNX_RATE_LIMIT: 40,
|
||||||
|
CONF_KNX_TELEGRAM_LOG_SIZE: 3000,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -1341,6 +1351,7 @@ async def test_options_communication_settings(
|
||||||
CONF_KNX_CONNECTION_TYPE: CONF_KNX_AUTOMATIC,
|
CONF_KNX_CONNECTION_TYPE: CONF_KNX_AUTOMATIC,
|
||||||
CONF_KNX_STATE_UPDATER: False,
|
CONF_KNX_STATE_UPDATER: False,
|
||||||
CONF_KNX_RATE_LIMIT: 40,
|
CONF_KNX_RATE_LIMIT: 40,
|
||||||
|
CONF_KNX_TELEGRAM_LOG_SIZE: 3000,
|
||||||
}
|
}
|
||||||
knx_setup.assert_called_once()
|
knx_setup.assert_called_once()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue