Add logbook platforms (#37078)
* Add logbook platforms * Fix logbook describe test
This commit is contained in:
parent
508afd3b90
commit
5cbf77221a
19 changed files with 215 additions and 116 deletions
|
@ -4,7 +4,6 @@ import logging
|
|||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_NAME
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import config_validation as cv, entityfilter
|
||||
|
||||
from . import flash_briefings, intent, smart_home_http
|
||||
|
@ -23,7 +22,6 @@ from .const import (
|
|||
CONF_TITLE,
|
||||
CONF_UID,
|
||||
DOMAIN,
|
||||
EVENT_ALEXA_SMART_HOME,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -82,28 +80,6 @@ CONFIG_SCHEMA = vol.Schema(
|
|||
|
||||
async def async_setup(hass, config):
|
||||
"""Activate the Alexa component."""
|
||||
|
||||
@callback
|
||||
def async_describe_logbook_event(event):
|
||||
"""Describe a logbook event."""
|
||||
data = event.data
|
||||
entity_id = data["request"].get("entity_id")
|
||||
|
||||
if entity_id:
|
||||
state = hass.states.get(entity_id)
|
||||
name = state.name if state else entity_id
|
||||
message = f"send command {data['request']['namespace']}/{data['request']['name']} for {name}"
|
||||
else:
|
||||
message = (
|
||||
f"send command {data['request']['namespace']}/{data['request']['name']}"
|
||||
)
|
||||
|
||||
return {"name": "Amazon Alexa", "message": message, "entity_id": entity_id}
|
||||
|
||||
hass.components.logbook.async_describe_event(
|
||||
DOMAIN, EVENT_ALEXA_SMART_HOME, async_describe_logbook_event
|
||||
)
|
||||
|
||||
if DOMAIN not in config:
|
||||
return True
|
||||
|
||||
|
|
28
homeassistant/components/alexa/logbook.py
Normal file
28
homeassistant/components/alexa/logbook.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
"""Describe logbook events."""
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .const import DOMAIN, EVENT_ALEXA_SMART_HOME
|
||||
|
||||
|
||||
@callback
|
||||
def async_describe_events(hass, async_describe_event):
|
||||
"""Describe logbook events."""
|
||||
|
||||
@callback
|
||||
def async_describe_logbook_event(event):
|
||||
"""Describe a logbook event."""
|
||||
data = event.data
|
||||
entity_id = data["request"].get("entity_id")
|
||||
|
||||
if entity_id:
|
||||
state = hass.states.get(entity_id)
|
||||
name = state.name if state else entity_id
|
||||
message = f"send command {data['request']['namespace']}/{data['request']['name']} for {name}"
|
||||
else:
|
||||
message = (
|
||||
f"send command {data['request']['namespace']}/{data['request']['name']}"
|
||||
)
|
||||
|
||||
return {"name": "Amazon Alexa", "message": message, "entity_id": entity_id}
|
||||
|
||||
async_describe_event(DOMAIN, EVENT_ALEXA_SMART_HOME, async_describe_logbook_event)
|
|
@ -2,7 +2,14 @@
|
|||
"domain": "alexa",
|
||||
"name": "Amazon Alexa",
|
||||
"documentation": "https://www.home-assistant.io/integrations/alexa",
|
||||
"dependencies": ["http"],
|
||||
"after_dependencies": ["logbook", "camera"],
|
||||
"codeowners": ["@home-assistant/cloud", "@ochlocracy"]
|
||||
"dependencies": [
|
||||
"http"
|
||||
],
|
||||
"after_dependencies": [
|
||||
"camera"
|
||||
],
|
||||
"codeowners": [
|
||||
"@home-assistant/cloud",
|
||||
"@ochlocracy"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -222,19 +222,6 @@ async def async_setup(hass, config):
|
|||
hass, DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=vol.Schema({})
|
||||
)
|
||||
|
||||
@callback
|
||||
def async_describe_logbook_event(event):
|
||||
"""Describe a logbook event."""
|
||||
return {
|
||||
"name": event.data.get(ATTR_NAME),
|
||||
"message": "has been triggered",
|
||||
"entity_id": event.data.get(ATTR_ENTITY_ID),
|
||||
}
|
||||
|
||||
hass.components.logbook.async_describe_event(
|
||||
DOMAIN, EVENT_AUTOMATION_TRIGGERED, async_describe_logbook_event
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
|
23
homeassistant/components/automation/logbook.py
Normal file
23
homeassistant/components/automation/logbook.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
"""Describe logbook events."""
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_NAME
|
||||
from homeassistant.core import callback
|
||||
|
||||
from . import DOMAIN, EVENT_AUTOMATION_TRIGGERED
|
||||
|
||||
|
||||
@callback
|
||||
def async_describe_events(hass, async_describe_event): # type: ignore
|
||||
"""Describe logbook events."""
|
||||
|
||||
@callback
|
||||
def async_describe_logbook_event(event): # type: ignore
|
||||
"""Describe a logbook event."""
|
||||
return {
|
||||
"name": event.data.get(ATTR_NAME),
|
||||
"message": "has been triggered",
|
||||
"entity_id": event.data.get(ATTR_ENTITY_ID),
|
||||
}
|
||||
|
||||
async_describe_event(
|
||||
DOMAIN, EVENT_AUTOMATION_TRIGGERED, async_describe_logbook_event
|
||||
)
|
|
@ -2,7 +2,12 @@
|
|||
"domain": "automation",
|
||||
"name": "Automation",
|
||||
"documentation": "https://www.home-assistant.io/integrations/automation",
|
||||
"after_dependencies": ["device_automation", "logbook", "webhook"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"after_dependencies": [
|
||||
"device_automation",
|
||||
"webhook"
|
||||
],
|
||||
"codeowners": [
|
||||
"@home-assistant/core"
|
||||
],
|
||||
"quality_scale": "internal"
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ from homeassistant.const import (
|
|||
ATTR_BATTERY_CHARGING,
|
||||
ATTR_BATTERY_LEVEL,
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_SERVICE,
|
||||
CONF_IP_ADDRESS,
|
||||
CONF_NAME,
|
||||
CONF_PORT,
|
||||
|
@ -41,12 +40,10 @@ from .accessories import get_accessory
|
|||
from .aidmanager import AccessoryAidStorage
|
||||
from .const import (
|
||||
AID_STORAGE,
|
||||
ATTR_DISPLAY_NAME,
|
||||
ATTR_INTERGRATION,
|
||||
ATTR_MANUFACTURER,
|
||||
ATTR_MODEL,
|
||||
ATTR_SOFTWARE_VERSION,
|
||||
ATTR_VALUE,
|
||||
BRIDGE_NAME,
|
||||
BRIDGE_SERIAL_NUMBER,
|
||||
CONF_ADVERTISE_IP,
|
||||
|
@ -64,7 +61,6 @@ from .const import (
|
|||
DEFAULT_PORT,
|
||||
DEFAULT_SAFE_MODE,
|
||||
DOMAIN,
|
||||
EVENT_HOMEKIT_CHANGED,
|
||||
HOMEKIT,
|
||||
HOMEKIT_PAIRING_QR,
|
||||
HOMEKIT_PAIRING_QR_SECRET,
|
||||
|
@ -325,26 +321,6 @@ def _async_register_events_and_services(hass: HomeAssistant):
|
|||
schema=RESET_ACCESSORY_SERVICE_SCHEMA,
|
||||
)
|
||||
|
||||
@callback
|
||||
def async_describe_logbook_event(event):
|
||||
"""Describe a logbook event."""
|
||||
data = event.data
|
||||
entity_id = data.get(ATTR_ENTITY_ID)
|
||||
value = data.get(ATTR_VALUE)
|
||||
|
||||
value_msg = f" to {value}" if value else ""
|
||||
message = f"send command {data[ATTR_SERVICE]}{value_msg} for {data[ATTR_DISPLAY_NAME]}"
|
||||
|
||||
return {
|
||||
"name": "HomeKit",
|
||||
"message": message,
|
||||
"entity_id": entity_id,
|
||||
}
|
||||
|
||||
hass.components.logbook.async_describe_event(
|
||||
DOMAIN, EVENT_HOMEKIT_CHANGED, async_describe_logbook_event
|
||||
)
|
||||
|
||||
async def async_handle_homekit_service_start(service):
|
||||
"""Handle start HomeKit service call."""
|
||||
for entry_id in hass.data[DOMAIN]:
|
||||
|
|
28
homeassistant/components/homekit/logbook.py
Normal file
28
homeassistant/components/homekit/logbook.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
"""Describe logbook events."""
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_SERVICE
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .const import ATTR_DISPLAY_NAME, ATTR_VALUE, DOMAIN, EVENT_HOMEKIT_CHANGED
|
||||
|
||||
|
||||
@callback
|
||||
def async_describe_events(hass, async_describe_event):
|
||||
"""Describe logbook events."""
|
||||
|
||||
@callback
|
||||
def async_describe_logbook_event(event):
|
||||
"""Describe a logbook event."""
|
||||
data = event.data
|
||||
entity_id = data.get(ATTR_ENTITY_ID)
|
||||
value = data.get(ATTR_VALUE)
|
||||
|
||||
value_msg = f" to {value}" if value else ""
|
||||
message = f"send command {data[ATTR_SERVICE]}{value_msg} for {data[ATTR_DISPLAY_NAME]}"
|
||||
|
||||
return {
|
||||
"name": "HomeKit",
|
||||
"message": message,
|
||||
"entity_id": entity_id,
|
||||
}
|
||||
|
||||
async_describe_event(DOMAIN, EVENT_HOMEKIT_CHANGED, async_describe_logbook_event)
|
|
@ -2,9 +2,23 @@
|
|||
"domain": "homekit",
|
||||
"name": "HomeKit",
|
||||
"documentation": "https://www.home-assistant.io/integrations/homekit",
|
||||
"requirements": ["HAP-python==2.9.1","fnvhash==0.1.0","PyQRCode==1.2.1","base36==0.1.1","PyTurboJPEG==1.4.0"],
|
||||
"dependencies": ["http", "camera", "ffmpeg"],
|
||||
"after_dependencies": ["logbook", "zeroconf"],
|
||||
"codeowners": ["@bdraco"],
|
||||
"requirements": [
|
||||
"HAP-python==2.9.1",
|
||||
"fnvhash==0.1.0",
|
||||
"PyQRCode==1.2.1",
|
||||
"base36==0.1.1",
|
||||
"PyTurboJPEG==1.4.0"
|
||||
],
|
||||
"dependencies": [
|
||||
"http",
|
||||
"camera",
|
||||
"ffmpeg"
|
||||
],
|
||||
"after_dependencies": [
|
||||
"zeroconf"
|
||||
],
|
||||
"codeowners": [
|
||||
"@bdraco"
|
||||
],
|
||||
"config_flow": true
|
||||
}
|
||||
|
|
|
@ -47,6 +47,9 @@ from homeassistant.helpers.entityfilter import (
|
|||
convert_include_exclude_filter,
|
||||
generate_filter,
|
||||
)
|
||||
from homeassistant.helpers.integration_platform import (
|
||||
async_process_integration_platforms,
|
||||
)
|
||||
from homeassistant.loader import bind_hass
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
|
@ -102,15 +105,9 @@ def async_log_entry(hass, name, message, domain=None, entity_id=None):
|
|||
hass.bus.async_fire(EVENT_LOGBOOK_ENTRY, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def async_describe_event(hass, domain, event_name, describe_callback):
|
||||
"""Teach logbook how to describe a new event."""
|
||||
hass.data.setdefault(DOMAIN, {})[event_name] = (domain, describe_callback)
|
||||
|
||||
|
||||
async def async_setup(hass, config):
|
||||
"""Logbook setup."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
hass.data[DOMAIN] = {}
|
||||
|
||||
@callback
|
||||
def log_message(service):
|
||||
|
@ -131,9 +128,23 @@ async def async_setup(hass, config):
|
|||
)
|
||||
|
||||
hass.services.async_register(DOMAIN, "log", log_message, schema=LOG_MESSAGE_SCHEMA)
|
||||
|
||||
await async_process_integration_platforms(hass, DOMAIN, _process_logbook_platform)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def _process_logbook_platform(hass, domain, platform):
|
||||
"""Process a logbook platform."""
|
||||
|
||||
@callback
|
||||
def _async_describe_event(domain, event_name, describe_callback):
|
||||
"""Teach logbook how to describe a new event."""
|
||||
hass.data[DOMAIN][event_name] = (domain, describe_callback)
|
||||
|
||||
platform.async_describe_events(hass, _async_describe_event)
|
||||
|
||||
|
||||
class LogbookView(HomeAssistantView):
|
||||
"""Handle logbook view requests."""
|
||||
|
||||
|
|
|
@ -188,19 +188,6 @@ async def async_setup(hass, config):
|
|||
DOMAIN, SERVICE_TOGGLE, toggle_service, schema=SCRIPT_TURN_ONOFF_SCHEMA
|
||||
)
|
||||
|
||||
@callback
|
||||
def async_describe_logbook_event(event):
|
||||
"""Describe the logbook event."""
|
||||
return {
|
||||
"name": event.data.get(ATTR_NAME),
|
||||
"message": "started",
|
||||
"entity_id": event.data.get(ATTR_ENTITY_ID),
|
||||
}
|
||||
|
||||
hass.components.logbook.async_describe_event(
|
||||
DOMAIN, EVENT_SCRIPT_STARTED, async_describe_logbook_event
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
|
21
homeassistant/components/script/logbook.py
Normal file
21
homeassistant/components/script/logbook.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
"""Describe logbook events."""
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_NAME
|
||||
from homeassistant.core import callback
|
||||
|
||||
from . import DOMAIN, EVENT_SCRIPT_STARTED
|
||||
|
||||
|
||||
@callback
|
||||
def async_describe_events(hass, async_describe_event):
|
||||
"""Describe logbook events."""
|
||||
|
||||
@callback
|
||||
def async_describe_logbook_event(event):
|
||||
"""Describe the logbook event."""
|
||||
return {
|
||||
"name": event.data.get(ATTR_NAME),
|
||||
"message": "started",
|
||||
"entity_id": event.data.get(ATTR_ENTITY_ID),
|
||||
}
|
||||
|
||||
async_describe_event(DOMAIN, EVENT_SCRIPT_STARTED, async_describe_logbook_event)
|
|
@ -2,7 +2,8 @@
|
|||
"domain": "script",
|
||||
"name": "Scripts",
|
||||
"documentation": "https://www.home-assistant.io/integrations/script",
|
||||
"after_dependencies": ["logbook"],
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"codeowners": [
|
||||
"@home-assistant/core"
|
||||
],
|
||||
"quality_scale": "internal"
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import logging
|
|||
from typing import Any, Awaitable, Callable
|
||||
|
||||
from homeassistant.core import Event, HomeAssistant
|
||||
from homeassistant.loader import IntegrationNotFound, async_get_integration, bind_hass
|
||||
from homeassistant.loader import async_get_integration, bind_hass
|
||||
from homeassistant.setup import ATTR_COMPONENT, EVENT_COMPONENT_LOADED
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -21,10 +21,20 @@ async def async_process_integration_platforms(
|
|||
|
||||
async def _process(component_name: str) -> None:
|
||||
"""Process the intents of a component."""
|
||||
if "." in component_name:
|
||||
return
|
||||
|
||||
integration = await async_get_integration(hass, component_name)
|
||||
|
||||
try:
|
||||
integration = await async_get_integration(hass, component_name)
|
||||
platform = integration.get_platform(platform_name)
|
||||
except (IntegrationNotFound, ImportError):
|
||||
except ImportError as err:
|
||||
if f"{component_name}.{platform_name}" not in str(err):
|
||||
_LOGGER.exception(
|
||||
"Unexpected error importing %s/%s.py",
|
||||
component_name,
|
||||
platform_name,
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
|
|
|
@ -8,7 +8,9 @@ from tests.components.logbook.test_init import MockLazyEventPartialState
|
|||
|
||||
async def test_humanify_alexa_event(hass):
|
||||
"""Test humanifying Alexa event."""
|
||||
hass.config.components.add("recorder")
|
||||
await async_setup_component(hass, "alexa", {})
|
||||
await async_setup_component(hass, "logbook", {})
|
||||
hass.states.async_set("light.kitchen", "on", {"friendly_name": "Kitchen Light"})
|
||||
entity_attr_cache = logbook.EntityAttributeCache(hass)
|
||||
|
||||
|
|
|
@ -1039,7 +1039,9 @@ async def test_extraction_functions(hass):
|
|||
|
||||
async def test_logbook_humanify_automation_triggered_event(hass):
|
||||
"""Test humanifying Automation Trigger event."""
|
||||
hass.config.components.add("recorder")
|
||||
await async_setup_component(hass, automation.DOMAIN, {})
|
||||
await async_setup_component(hass, "logbook", {})
|
||||
entity_attr_cache = logbook.EntityAttributeCache(hass)
|
||||
|
||||
event1, event2 = list(
|
||||
|
|
|
@ -15,8 +15,10 @@ from tests.components.logbook.test_init import MockLazyEventPartialState
|
|||
|
||||
async def test_humanify_homekit_changed_event(hass, hk_driver):
|
||||
"""Test humanifying HomeKit changed event."""
|
||||
hass.config.components.add("recorder")
|
||||
with patch("homeassistant.components.homekit.HomeKit"):
|
||||
assert await async_setup_component(hass, "homekit", {"homekit": {}})
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
entity_attr_cache = logbook.EntityAttributeCache(hass)
|
||||
|
||||
event1, event2 = list(
|
||||
|
|
|
@ -36,8 +36,8 @@ from homeassistant.helpers.json import JSONEncoder
|
|||
from homeassistant.setup import async_setup_component, setup_component
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.async_mock import patch
|
||||
from tests.common import get_test_home_assistant, init_recorder_component
|
||||
from tests.async_mock import Mock, patch
|
||||
from tests.common import get_test_home_assistant, init_recorder_component, mock_platform
|
||||
from tests.components.recorder.common import trigger_db_commit
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -1563,6 +1563,22 @@ async def test_logbook_view_period_entity(hass, hass_client):
|
|||
async def test_logbook_describe_event(hass, hass_client):
|
||||
"""Test teaching logbook about a new event."""
|
||||
await hass.async_add_executor_job(init_recorder_component, hass)
|
||||
|
||||
def _describe(event):
|
||||
"""Describe an event."""
|
||||
return {"name": "Test Name", "message": "tested a message"}
|
||||
|
||||
hass.config.components.add("fake_integration")
|
||||
mock_platform(
|
||||
hass,
|
||||
"fake_integration.logbook",
|
||||
Mock(
|
||||
async_describe_events=lambda hass, async_describe_event: async_describe_event(
|
||||
"test_domain", "some_event", _describe
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
with patch(
|
||||
"homeassistant.util.dt.utcnow",
|
||||
|
@ -1574,12 +1590,6 @@ async def test_logbook_describe_event(hass, hass_client):
|
|||
hass.data[recorder.DATA_INSTANCE].block_till_done
|
||||
)
|
||||
|
||||
def _describe(event):
|
||||
"""Describe an event."""
|
||||
return {"name": "Test Name", "message": "tested a message"}
|
||||
|
||||
hass.components.logbook.async_describe_event("test_domain", "some_event", _describe)
|
||||
|
||||
client = await hass_client()
|
||||
response = await client.get("/api/logbook")
|
||||
results = await response.json()
|
||||
|
@ -1597,6 +1607,26 @@ async def test_exclude_described_event(hass, hass_client):
|
|||
entity_id2 = "automation.included_rule"
|
||||
entity_id3 = "sensor.excluded_domain"
|
||||
|
||||
def _describe(event):
|
||||
"""Describe an event."""
|
||||
return {
|
||||
"name": "Test Name",
|
||||
"message": "tested a message",
|
||||
"entity_id": event.data.get(ATTR_ENTITY_ID),
|
||||
}
|
||||
|
||||
def async_describe_events(hass, async_describe_event):
|
||||
"""Mock to describe events."""
|
||||
async_describe_event("automation", "some_automation_event", _describe)
|
||||
async_describe_event("sensor", "some_event", _describe)
|
||||
|
||||
hass.config.components.add("fake_integration")
|
||||
mock_platform(
|
||||
hass,
|
||||
"fake_integration.logbook",
|
||||
Mock(async_describe_events=async_describe_events),
|
||||
)
|
||||
|
||||
await hass.async_add_executor_job(init_recorder_component, hass)
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
|
@ -1631,19 +1661,6 @@ async def test_exclude_described_event(hass, hass_client):
|
|||
hass.data[recorder.DATA_INSTANCE].block_till_done
|
||||
)
|
||||
|
||||
def _describe(event):
|
||||
"""Describe an event."""
|
||||
return {
|
||||
"name": "Test Name",
|
||||
"message": "tested a message",
|
||||
"entity_id": event.data.get(ATTR_ENTITY_ID),
|
||||
}
|
||||
|
||||
hass.components.logbook.async_describe_event(
|
||||
"automation", "some_automation_event", _describe
|
||||
)
|
||||
hass.components.logbook.async_describe_event("sensor", "some_event", _describe)
|
||||
|
||||
client = await hass_client()
|
||||
response = await client.get("/api/logbook")
|
||||
results = await response.json()
|
||||
|
|
|
@ -472,7 +472,9 @@ async def test_config(hass):
|
|||
|
||||
async def test_logbook_humanify_script_started_event(hass):
|
||||
"""Test humanifying script started event."""
|
||||
hass.config.components.add("recorder")
|
||||
await async_setup_component(hass, DOMAIN, {})
|
||||
await async_setup_component(hass, "logbook", {})
|
||||
entity_attr_cache = logbook.EntityAttributeCache(hass)
|
||||
|
||||
event1, event2 = list(
|
||||
|
|
Loading…
Add table
Reference in a new issue