mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Expose supported brands via API (#75074)
This commit is contained in:
parent
b54fe14a10
commit
41ec8cd354
@ -21,7 +21,7 @@ repos:
|
|||||||
- --skip="./.*,*.csv,*.json"
|
- --skip="./.*,*.csv,*.json"
|
||||||
- --quiet-level=2
|
- --quiet-level=2
|
||||||
exclude_types: [csv, json]
|
exclude_types: [csv, json]
|
||||||
exclude: ^tests/fixtures/
|
exclude: ^tests/fixtures/|homeassistant/generated/
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 4.0.1
|
rev: 4.0.1
|
||||||
hooks:
|
hooks:
|
||||||
|
@ -22,6 +22,7 @@ from homeassistant.exceptions import (
|
|||||||
TemplateError,
|
TemplateError,
|
||||||
Unauthorized,
|
Unauthorized,
|
||||||
)
|
)
|
||||||
|
from homeassistant.generated import supported_brands
|
||||||
from homeassistant.helpers import config_validation as cv, entity, template
|
from homeassistant.helpers import config_validation as cv, entity, template
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.event import (
|
from homeassistant.helpers.event import (
|
||||||
@ -68,6 +69,7 @@ def async_register_commands(
|
|||||||
async_reg(hass, handle_unsubscribe_events)
|
async_reg(hass, handle_unsubscribe_events)
|
||||||
async_reg(hass, handle_validate_config)
|
async_reg(hass, handle_validate_config)
|
||||||
async_reg(hass, handle_subscribe_entities)
|
async_reg(hass, handle_subscribe_entities)
|
||||||
|
async_reg(hass, handle_supported_brands)
|
||||||
|
|
||||||
|
|
||||||
def pong_message(iden: int) -> dict[str, Any]:
|
def pong_message(iden: int) -> dict[str, Any]:
|
||||||
@ -691,3 +693,25 @@ async def handle_validate_config(
|
|||||||
result[key] = {"valid": True, "error": None}
|
result[key] = {"valid": True, "error": None}
|
||||||
|
|
||||||
connection.send_result(msg["id"], result)
|
connection.send_result(msg["id"], result)
|
||||||
|
|
||||||
|
|
||||||
|
@decorators.websocket_command(
|
||||||
|
{
|
||||||
|
vol.Required("type"): "supported_brands",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@decorators.async_response
|
||||||
|
async def handle_supported_brands(
|
||||||
|
hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any]
|
||||||
|
) -> None:
|
||||||
|
"""Handle supported brands command."""
|
||||||
|
data = {}
|
||||||
|
for integration in await asyncio.gather(
|
||||||
|
*[
|
||||||
|
async_get_integration(hass, integration)
|
||||||
|
for integration in supported_brands.HAS_SUPPORTED_BRANDS
|
||||||
|
]
|
||||||
|
):
|
||||||
|
data[integration.domain] = integration.manifest["supported_brands"]
|
||||||
|
|
||||||
|
connection.send_result(msg["id"], data)
|
||||||
|
15
homeassistant/generated/supported_brands.py
Normal file
15
homeassistant/generated/supported_brands.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
"""Automatically generated by hassfest.
|
||||||
|
|
||||||
|
To update, run python3 -m script.hassfest
|
||||||
|
"""
|
||||||
|
|
||||||
|
# fmt: off
|
||||||
|
|
||||||
|
HAS_SUPPORTED_BRANDS = (
|
||||||
|
"denonavr",
|
||||||
|
"hunterdouglas_powerview",
|
||||||
|
"motion_blinds",
|
||||||
|
"overkiz",
|
||||||
|
"renault",
|
||||||
|
"wemo"
|
||||||
|
)
|
@ -20,6 +20,7 @@ from . import (
|
|||||||
requirements,
|
requirements,
|
||||||
services,
|
services,
|
||||||
ssdp,
|
ssdp,
|
||||||
|
supported_brands,
|
||||||
translations,
|
translations,
|
||||||
usb,
|
usb,
|
||||||
zeroconf,
|
zeroconf,
|
||||||
@ -39,6 +40,7 @@ INTEGRATION_PLUGINS = [
|
|||||||
requirements,
|
requirements,
|
||||||
services,
|
services,
|
||||||
ssdp,
|
ssdp,
|
||||||
|
supported_brands,
|
||||||
translations,
|
translations,
|
||||||
usb,
|
usb,
|
||||||
zeroconf,
|
zeroconf,
|
||||||
|
@ -112,6 +112,11 @@ class Integration:
|
|||||||
"""List of dependencies."""
|
"""List of dependencies."""
|
||||||
return self.manifest.get("dependencies", [])
|
return self.manifest.get("dependencies", [])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supported_brands(self) -> dict[str]:
|
||||||
|
"""Return dict of supported brands."""
|
||||||
|
return self.manifest.get("supported_brands", {})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def integration_type(self) -> str:
|
def integration_type(self) -> str:
|
||||||
"""Get integration_type."""
|
"""Get integration_type."""
|
||||||
|
55
script/hassfest/supported_brands.py
Normal file
55
script/hassfest/supported_brands.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
"""Generate supported_brands data."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
from .model import Config, Integration
|
||||||
|
|
||||||
|
BASE = """
|
||||||
|
\"\"\"Automatically generated by hassfest.
|
||||||
|
|
||||||
|
To update, run python3 -m script.hassfest
|
||||||
|
\"\"\"
|
||||||
|
|
||||||
|
# fmt: off
|
||||||
|
|
||||||
|
HAS_SUPPORTED_BRANDS = ({})
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
|
||||||
|
def generate_and_validate(integrations: dict[str, Integration], config: Config) -> str:
|
||||||
|
"""Validate and generate supported_brands data."""
|
||||||
|
|
||||||
|
brands = [
|
||||||
|
domain
|
||||||
|
for domain, integration in sorted(integrations.items())
|
||||||
|
if integration.supported_brands
|
||||||
|
]
|
||||||
|
|
||||||
|
return BASE.format(json.dumps(brands, indent=4)[1:-1])
|
||||||
|
|
||||||
|
|
||||||
|
def validate(integrations: dict[str, Integration], config: Config) -> None:
|
||||||
|
"""Validate supported_brands data."""
|
||||||
|
supported_brands_path = config.root / "homeassistant/generated/supported_brands.py"
|
||||||
|
config.cache["supported_brands"] = content = generate_and_validate(
|
||||||
|
integrations, config
|
||||||
|
)
|
||||||
|
|
||||||
|
if config.specific_integrations:
|
||||||
|
return
|
||||||
|
|
||||||
|
if supported_brands_path.read_text(encoding="utf-8").strip() != content:
|
||||||
|
config.add_error(
|
||||||
|
"supported_brands",
|
||||||
|
"File supported_brands.py is not up to date. Run python3 -m script.hassfest",
|
||||||
|
fixable=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def generate(integrations: dict[str, Integration], config: Config):
|
||||||
|
"""Generate supported_brands data."""
|
||||||
|
supported_brands_path = config.root / "homeassistant/generated/supported_brands.py"
|
||||||
|
supported_brands_path.write_text(
|
||||||
|
f"{config.cache['supported_brands']}\n", encoding="utf-8"
|
||||||
|
)
|
@ -22,7 +22,13 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send
|
|||||||
from homeassistant.loader import async_get_integration
|
from homeassistant.loader import async_get_integration
|
||||||
from homeassistant.setup import DATA_SETUP_TIME, async_setup_component
|
from homeassistant.setup import DATA_SETUP_TIME, async_setup_component
|
||||||
|
|
||||||
from tests.common import MockEntity, MockEntityPlatform, async_mock_service
|
from tests.common import (
|
||||||
|
MockEntity,
|
||||||
|
MockEntityPlatform,
|
||||||
|
MockModule,
|
||||||
|
async_mock_service,
|
||||||
|
mock_integration,
|
||||||
|
)
|
||||||
|
|
||||||
STATE_KEY_SHORT_NAMES = {
|
STATE_KEY_SHORT_NAMES = {
|
||||||
"entity_id": "e",
|
"entity_id": "e",
|
||||||
@ -1749,3 +1755,36 @@ async def test_validate_config_invalid(websocket_client, key, config, error):
|
|||||||
assert msg["type"] == const.TYPE_RESULT
|
assert msg["type"] == const.TYPE_RESULT
|
||||||
assert msg["success"]
|
assert msg["success"]
|
||||||
assert msg["result"] == {key: {"valid": False, "error": error}}
|
assert msg["result"] == {key: {"valid": False, "error": error}}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_supported_brands(hass, websocket_client):
|
||||||
|
"""Test supported brands."""
|
||||||
|
mock_integration(
|
||||||
|
hass,
|
||||||
|
MockModule("test", partial_manifest={"supported_brands": {"hello": "World"}}),
|
||||||
|
)
|
||||||
|
mock_integration(
|
||||||
|
hass,
|
||||||
|
MockModule(
|
||||||
|
"abcd", partial_manifest={"supported_brands": {"something": "Something"}}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.generated.supported_brands.HAS_SUPPORTED_BRANDS",
|
||||||
|
("abcd", "test"),
|
||||||
|
):
|
||||||
|
await websocket_client.send_json({"id": 7, "type": "supported_brands"})
|
||||||
|
msg = await websocket_client.receive_json()
|
||||||
|
|
||||||
|
assert msg["id"] == 7
|
||||||
|
assert msg["type"] == const.TYPE_RESULT
|
||||||
|
assert msg["success"]
|
||||||
|
assert msg["result"] == {
|
||||||
|
"abcd": {
|
||||||
|
"something": "Something",
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"hello": "World",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user