Do not allow modbus config without entities (#113516)

This commit is contained in:
jan iversen 2024-03-15 19:49:29 +01:00 committed by GitHub
parent 422d4ea5b3
commit 02d4bf007d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 135 additions and 4 deletions

View File

@ -131,6 +131,8 @@ async def async_modbus_setup(
if config[DOMAIN]: if config[DOMAIN]:
config[DOMAIN] = check_config(hass, config[DOMAIN]) config[DOMAIN] = check_config(hass, config[DOMAIN])
if not config[DOMAIN]:
return False
if DOMAIN in hass.data and config[DOMAIN] == []: if DOMAIN in hass.data and config[DOMAIN] == []:
hubs = hass.data[DOMAIN] hubs = hass.data[DOMAIN]
for name in hubs: for name in hubs:

View File

@ -93,6 +93,10 @@
"duplicate_entity_name": { "duplicate_entity_name": {
"title": "Modbus {sub_1} is duplicate, second entry not loaded.", "title": "Modbus {sub_1} is duplicate, second entry not loaded.",
"description": "A entity name must be unique, Please correct the entry in your configuration.yaml file and restart Home Assistant to fix this issue." "description": "A entity name must be unique, Please correct the entry in your configuration.yaml file and restart Home Assistant to fix this issue."
},
"no_entities": {
"title": "Modbus {sub_1} contain no entities, entry not loaded.",
"description": "Please add at least one entity to Modbus {sub_1} in your configuration.yaml file and restart Home Assistant to fix this issue."
} }
} }
} }

View File

@ -490,10 +490,18 @@ def check_config(hass: HomeAssistant, config: dict) -> dict:
else: else:
entity_inx += 1 entity_inx += 1
if no_entities: if no_entities:
err = f"Modbus {hub[CONF_NAME]} contain no entities, this will cause instability, please add at least one entity!" modbus_create_issue(
_LOGGER.warning(err) hass,
# Ensure timeout is not started/handled. "no_entities",
hub[CONF_TIMEOUT] = -1 [
hub[CONF_NAME],
"",
"",
],
f"Modbus {hub[CONF_NAME]} contain no entities, causing instability, entry not loaded",
)
del config[hub_inx]
continue
if hub[CONF_TIMEOUT] >= minimum_scan_interval: if hub[CONF_TIMEOUT] >= minimum_scan_interval:
hub[CONF_TIMEOUT] = minimum_scan_interval - 1 hub[CONF_TIMEOUT] = minimum_scan_interval - 1
_LOGGER.warning( _LOGGER.warning(

View File

@ -962,22 +962,46 @@ async def test_no_duplicate_names(hass: HomeAssistant, do_config) -> None:
CONF_TYPE: TCP, CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST, CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP, CONF_PORT: TEST_PORT_TCP,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: TCP, CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST, CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP, CONF_PORT: TEST_PORT_TCP,
CONF_RETRIES: 3, CONF_RETRIES: 3,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: TCP, CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST, CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP, CONF_PORT: TEST_PORT_TCP,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: TCP, CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST, CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP, CONF_PORT: TEST_PORT_TCP,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: TCP, CONF_TYPE: TCP,
@ -986,11 +1010,23 @@ async def test_no_duplicate_names(hass: HomeAssistant, do_config) -> None:
CONF_NAME: TEST_MODBUS_NAME, CONF_NAME: TEST_MODBUS_NAME,
CONF_TIMEOUT: 30, CONF_TIMEOUT: 30,
CONF_DELAY: 10, CONF_DELAY: 10,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: UDP, CONF_TYPE: UDP,
CONF_HOST: TEST_MODBUS_HOST, CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP, CONF_PORT: TEST_PORT_TCP,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: UDP, CONF_TYPE: UDP,
@ -999,11 +1035,23 @@ async def test_no_duplicate_names(hass: HomeAssistant, do_config) -> None:
CONF_NAME: TEST_MODBUS_NAME, CONF_NAME: TEST_MODBUS_NAME,
CONF_TIMEOUT: 30, CONF_TIMEOUT: 30,
CONF_DELAY: 10, CONF_DELAY: 10,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: RTUOVERTCP, CONF_TYPE: RTUOVERTCP,
CONF_HOST: TEST_MODBUS_HOST, CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP, CONF_PORT: TEST_PORT_TCP,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: RTUOVERTCP, CONF_TYPE: RTUOVERTCP,
@ -1012,6 +1060,12 @@ async def test_no_duplicate_names(hass: HomeAssistant, do_config) -> None:
CONF_NAME: TEST_MODBUS_NAME, CONF_NAME: TEST_MODBUS_NAME,
CONF_TIMEOUT: 30, CONF_TIMEOUT: 30,
CONF_DELAY: 10, CONF_DELAY: 10,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: SERIAL, CONF_TYPE: SERIAL,
@ -1022,6 +1076,12 @@ async def test_no_duplicate_names(hass: HomeAssistant, do_config) -> None:
CONF_PARITY: "E", CONF_PARITY: "E",
CONF_STOPBITS: 1, CONF_STOPBITS: 1,
CONF_MSG_WAIT: 100, CONF_MSG_WAIT: 100,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: SERIAL, CONF_TYPE: SERIAL,
@ -1034,12 +1094,24 @@ async def test_no_duplicate_names(hass: HomeAssistant, do_config) -> None:
CONF_NAME: TEST_MODBUS_NAME, CONF_NAME: TEST_MODBUS_NAME,
CONF_TIMEOUT: 30, CONF_TIMEOUT: 30,
CONF_DELAY: 10, CONF_DELAY: 10,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: TCP, CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST, CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP, CONF_PORT: TEST_PORT_TCP,
CONF_DELAY: 5, CONF_DELAY: 5,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
[ [
{ {
@ -1047,12 +1119,24 @@ async def test_no_duplicate_names(hass: HomeAssistant, do_config) -> None:
CONF_HOST: TEST_MODBUS_HOST, CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP, CONF_PORT: TEST_PORT_TCP,
CONF_NAME: TEST_MODBUS_NAME, CONF_NAME: TEST_MODBUS_NAME,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: TCP, CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST, CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP, CONF_PORT: TEST_PORT_TCP,
CONF_NAME: f"{TEST_MODBUS_NAME} 2", CONF_NAME: f"{TEST_MODBUS_NAME} 2",
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
{ {
CONF_TYPE: SERIAL, CONF_TYPE: SERIAL,
@ -1063,6 +1147,12 @@ async def test_no_duplicate_names(hass: HomeAssistant, do_config) -> None:
CONF_PARITY: "E", CONF_PARITY: "E",
CONF_STOPBITS: 1, CONF_STOPBITS: 1,
CONF_NAME: f"{TEST_MODBUS_NAME} 3", CONF_NAME: f"{TEST_MODBUS_NAME} 3",
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
}, },
], ],
{ {
@ -1351,6 +1441,12 @@ async def test_pymodbus_close_fail(
CONF_TYPE: TCP, CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST, CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP, CONF_PORT: TEST_PORT_TCP,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
} }
] ]
} }
@ -1373,6 +1469,12 @@ async def test_pymodbus_connect_fail(
CONF_TYPE: TCP, CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST, CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP, CONF_PORT: TEST_PORT_TCP,
CONF_SENSORS: [
{
CONF_NAME: "dummy",
CONF_ADDRESS: 9999,
}
],
} }
] ]
} }
@ -1603,3 +1705,18 @@ async def test_integration_setup_failed(
) )
await hass.services.async_call(DOMAIN, SERVICE_RELOAD, blocking=True) await hass.services.async_call(DOMAIN, SERVICE_RELOAD, blocking=True)
await hass.async_block_till_done() await hass.async_block_till_done()
async def test_no_entities(hass: HomeAssistant) -> None:
"""Run test for failing pymodbus constructor."""
config = {
DOMAIN: [
{
CONF_NAME: TEST_MODBUS_NAME,
CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP,
}
]
}
assert await async_setup_component(hass, DOMAIN, config) is False