Add Z-Wave installer_mode yaml option (#129888)

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Petar Petrov 2024-11-20 13:04:29 +02:00 committed by GitHub
parent 621c66a214
commit 061c19fbf8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 72 additions and 3 deletions

View File

@ -9,6 +9,7 @@ import logging
from typing import Any from typing import Any
from awesomeversion import AwesomeVersion from awesomeversion import AwesomeVersion
import voluptuous as vol
from zwave_js_server.client import Client as ZwaveClient from zwave_js_server.client import Client as ZwaveClient
from zwave_js_server.const import CommandClass, RemoveNodeReason from zwave_js_server.const import CommandClass, RemoveNodeReason
from zwave_js_server.exceptions import BaseZwaveJSServerError, InvalidServerVersion from zwave_js_server.exceptions import BaseZwaveJSServerError, InvalidServerVersion
@ -87,6 +88,7 @@ from .const import (
CONF_ADDON_S2_AUTHENTICATED_KEY, CONF_ADDON_S2_AUTHENTICATED_KEY,
CONF_ADDON_S2_UNAUTHENTICATED_KEY, CONF_ADDON_S2_UNAUTHENTICATED_KEY,
CONF_DATA_COLLECTION_OPTED_IN, CONF_DATA_COLLECTION_OPTED_IN,
CONF_INSTALLER_MODE,
CONF_INTEGRATION_CREATED_ADDON, CONF_INTEGRATION_CREATED_ADDON,
CONF_LR_S2_ACCESS_CONTROL_KEY, CONF_LR_S2_ACCESS_CONTROL_KEY,
CONF_LR_S2_AUTHENTICATED_KEY, CONF_LR_S2_AUTHENTICATED_KEY,
@ -132,12 +134,21 @@ DATA_CLIENT_LISTEN_TASK = "client_listen_task"
DATA_DRIVER_EVENTS = "driver_events" DATA_DRIVER_EVENTS = "driver_events"
DATA_START_CLIENT_TASK = "start_client_task" DATA_START_CLIENT_TASK = "start_client_task"
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Optional(CONF_INSTALLER_MODE, default=False): cv.boolean,
}
)
},
extra=vol.ALLOW_EXTRA,
)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Z-Wave JS component.""" """Set up the Z-Wave JS component."""
hass.data[DOMAIN] = {} hass.data[DOMAIN] = config.get(DOMAIN, {})
for entry in hass.config_entries.async_entries(DOMAIN): for entry in hass.config_entries.async_entries(DOMAIN):
if not isinstance(entry.unique_id, str): if not isinstance(entry.unique_id, str):
hass.config_entries.async_update_entry( hass.config_entries.async_update_entry(

View File

@ -83,7 +83,9 @@ from .const import (
ATTR_PARAMETERS, ATTR_PARAMETERS,
ATTR_WAIT_FOR_RESULT, ATTR_WAIT_FOR_RESULT,
CONF_DATA_COLLECTION_OPTED_IN, CONF_DATA_COLLECTION_OPTED_IN,
CONF_INSTALLER_MODE,
DATA_CLIENT, DATA_CLIENT,
DOMAIN,
EVENT_DEVICE_ADDED_TO_REGISTRY, EVENT_DEVICE_ADDED_TO_REGISTRY,
USER_AGENT, USER_AGENT,
) )
@ -450,6 +452,7 @@ def async_register_api(hass: HomeAssistant) -> None:
websocket_api.async_register_command(hass, websocket_hard_reset_controller) websocket_api.async_register_command(hass, websocket_hard_reset_controller)
websocket_api.async_register_command(hass, websocket_node_capabilities) websocket_api.async_register_command(hass, websocket_node_capabilities)
websocket_api.async_register_command(hass, websocket_invoke_cc_api) websocket_api.async_register_command(hass, websocket_invoke_cc_api)
websocket_api.async_register_command(hass, websocket_get_integration_settings)
hass.http.register_view(FirmwareUploadView(dr.async_get(hass))) hass.http.register_view(FirmwareUploadView(dr.async_get(hass)))
@ -2682,3 +2685,25 @@ async def websocket_invoke_cc_api(
msg[ID], msg[ID],
result, result,
) )
@callback
@websocket_api.require_admin
@websocket_api.websocket_command(
{
vol.Required(TYPE): "zwave_js/get_integration_settings",
}
)
def websocket_get_integration_settings(
hass: HomeAssistant,
connection: ActiveConnection,
msg: dict[str, Any],
) -> None:
"""Get Z-Wave JS integration wide configuration."""
connection.send_result(
msg[ID],
{
# list explicitly to avoid leaking other keys and to set default
CONF_INSTALLER_MODE: hass.data[DOMAIN].get(CONF_INSTALLER_MODE, False),
},
)

View File

@ -25,6 +25,7 @@ CONF_ADDON_S2_AUTHENTICATED_KEY = "s2_authenticated_key"
CONF_ADDON_S2_UNAUTHENTICATED_KEY = "s2_unauthenticated_key" CONF_ADDON_S2_UNAUTHENTICATED_KEY = "s2_unauthenticated_key"
CONF_ADDON_LR_S2_ACCESS_CONTROL_KEY = "lr_s2_access_control_key" CONF_ADDON_LR_S2_ACCESS_CONTROL_KEY = "lr_s2_access_control_key"
CONF_ADDON_LR_S2_AUTHENTICATED_KEY = "lr_s2_authenticated_key" CONF_ADDON_LR_S2_AUTHENTICATED_KEY = "lr_s2_authenticated_key"
CONF_INSTALLER_MODE = "installer_mode"
CONF_INTEGRATION_CREATED_ADDON = "integration_created_addon" CONF_INTEGRATION_CREATED_ADDON = "integration_created_addon"
CONF_NETWORK_KEY = "network_key" CONF_NETWORK_KEY = "network_key"
CONF_S0_LEGACY_KEY = "s0_legacy_key" CONF_S0_LEGACY_KEY = "s0_legacy_key"

View File

@ -5,7 +5,7 @@ from http import HTTPStatus
from io import BytesIO from io import BytesIO
import json import json
from typing import Any from typing import Any
from unittest.mock import PropertyMock, patch from unittest.mock import MagicMock, PropertyMock, patch
import pytest import pytest
from zwave_js_server.const import ( from zwave_js_server.const import (
@ -89,11 +89,13 @@ from homeassistant.components.zwave_js.const import (
ATTR_PARAMETERS, ATTR_PARAMETERS,
ATTR_WAIT_FOR_RESULT, ATTR_WAIT_FOR_RESULT,
CONF_DATA_COLLECTION_OPTED_IN, CONF_DATA_COLLECTION_OPTED_IN,
CONF_INSTALLER_MODE,
DOMAIN, DOMAIN,
) )
from homeassistant.components.zwave_js.helpers import get_device_id from homeassistant.components.zwave_js.helpers import get_device_id
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr from homeassistant.helpers import device_registry as dr
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry, MockUser from tests.common import MockConfigEntry, MockUser
from tests.typing import ClientSessionGenerator, WebSocketGenerator from tests.typing import ClientSessionGenerator, WebSocketGenerator
@ -5163,3 +5165,33 @@ async def test_invoke_cc_api(
msg = await ws_client.receive_json() msg = await ws_client.receive_json()
assert not msg["success"] assert not msg["success"]
assert msg["error"] == {"code": "NotFoundError", "message": ""} assert msg["error"] == {"code": "NotFoundError", "message": ""}
@pytest.mark.parametrize(
("config", "installer_mode"), [({}, False), ({CONF_INSTALLER_MODE: True}, True)]
)
async def test_get_integration_settings(
config: dict[str, Any],
installer_mode: bool,
hass: HomeAssistant,
client: MagicMock,
hass_ws_client: WebSocketGenerator,
) -> None:
"""Test that the get_integration_settings WS API call works."""
ws_client = await hass_ws_client(hass)
entry = MockConfigEntry(domain="zwave_js", data={"url": "ws://test.org"})
entry.add_to_hass(hass)
assert await async_setup_component(hass, DOMAIN, {DOMAIN: config})
await hass.async_block_till_done()
await ws_client.send_json_auto_id(
{
TYPE: "zwave_js/get_integration_settings",
}
)
msg = await ws_client.receive_json()
assert msg["success"]
assert msg["result"] == {
CONF_INSTALLER_MODE: installer_mode,
}