hass-core/homeassistant/components/zwave_js/discovery.py

167 lines
5.7 KiB
Python
Raw Normal View History

Add zwave_js integration (#45020) * Run zwave_js scaffold (#44891) * Add zwave_js basic connection to zwave server (#44904) * add the basic connection to zwave server * fix name * Fix requirements * Fix things * Version bump dep to 0.1.2 * fix pylint Co-authored-by: Paulus Schoutsen <balloob@gmail.com> * Bump zwave-js-server-python to 0.2.0 * Use zwave js server version check instead of fetching full state (#44943) * Use version check instead of fetching full state * Fix tests * Use 0.3.0 * Also catch aiohttp client errors * Update docstring * Lint * Unignore zwave_js * Add zwave_js entity discovery basics and sensor platform (#44927) Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Paulus Schoutsen <balloob@gmail.com> * Complete zwave_js typing (#44960) * Type discovery * Type init * Type entity * Type config flow * Type sensor * Require typing of zwave_js * Complete zwave_js config flow test coverage (#44955) * Correct zwave_js sensor device class (#44968) * Fix zwave_js KeyError on entry setup timeout (#44966) * Bump zwave-js-server-python to 0.5.0 (#44975) * Remove stale callback signal from zwave_js (#44994) * Add light platform to zwave_js integration (#44974) * add light platform * styling fix * fix type hint * Fix typing * Update homeassistant/components/zwave_js/const.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/entity.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/entity.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/entity.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/entity.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/entity.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * color temp should be integer * guard Nonetype error * Update homeassistant/components/zwave_js/light.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/light.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * some fixes after merging * add additional guards for None values * adjustments for rgb lights * Fix typing * Fix black * Bump zwave-js-server-python to 0.6.0 * guard value updated log * remove value_id lookup as its no longer needed * fiz sending white value * Update homeassistant/components/zwave_js/light.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Add zwave_js test foundation (#44983) * Exclude text files from codespell * Add basic dump fixture * Add test foundation * Fix test after rebase * Exclude jsonl files from codespell * Rename fixture file type to jsonl * Update fixture path * Fix stale docstring * Add controller state json fixture * Add multisensor 6 state json fixture * Update fixtures * Remove basic dump fixture * Fix fixtures after library bump * Update codeowner * Minor cleanup Z-Wave JS (#45021) * Update zwave_js device_info (#45023) Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com> Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2021-01-10 18:08:25 -05:00
"""Map Z-Wave nodes and values to Home Assistant entities."""
from dataclasses import dataclass
from typing import Generator, Optional, Set, Union
from zwave_js_server.const import CommandClass
from zwave_js_server.model.node import Node as ZwaveNode
from zwave_js_server.model.value import Value as ZwaveValue
from homeassistant.core import callback
@dataclass
class ZwaveDiscoveryInfo:
"""Info discovered from (primary) ZWave Value to create entity."""
node: ZwaveNode # node to which the value(s) belongs
primary_value: ZwaveValue # the value object itself for primary value
platform: str # the home assistant platform for which an entity should be created
platform_hint: Optional[
str
] = "" # hint for the platform about this discovered entity
@property
def value_id(self) -> str:
"""Return the unique value_id belonging to primary value."""
return f"{self.node.node_id}.{self.primary_value.value_id}"
@dataclass
class ZWaveDiscoverySchema:
"""Z-Wave discovery schema.
The (primary) value for an entity must match these conditions.
Use the Z-Wave specifications to find out the values for these parameters:
https://github.com/zwave-js/node-zwave-js/tree/master/specs
"""
# specify the hass platform for which this scheme applies (e.g. light, sensor)
platform: str
# [optional] hint for platform
hint: Optional[str] = None
# [optional] the node's basic device class must match ANY of these values
device_class_basic: Optional[Set[str]] = None
# [optional] the node's generic device class must match ANY of these values
device_class_generic: Optional[Set[str]] = None
# [optional] the node's specific device class must match ANY of these values
device_class_specific: Optional[Set[str]] = None
# [optional] the value's command class must match ANY of these values
command_class: Optional[Set[int]] = None
# [optional] the value's endpoint must match ANY of these values
endpoint: Optional[Set[int]] = None
# [optional] the value's property must match ANY of these values
property: Optional[Set[Union[str, int]]] = None
# [optional] the value's metadata_type must match ANY of these values
type: Optional[Set[str]] = None
DISCOVERY_SCHEMAS = [
# light
# primary value is the currentValue (brightness)
ZWaveDiscoverySchema(
platform="light",
device_class_generic={"Multilevel Switch", "Remote Switch"},
device_class_specific={
"Multilevel Tunable Color Light",
"Binary Tunable Color Light",
"Multilevel Remote Switch",
"Multilevel Power Switch",
},
command_class={CommandClass.SWITCH_MULTILEVEL},
property={"currentValue"},
type={"number"},
),
# generic text sensors
ZWaveDiscoverySchema(
platform="sensor",
hint="string_sensor",
command_class={
CommandClass.ALARM,
CommandClass.SENSOR_ALARM,
CommandClass.INDICATOR,
CommandClass.NOTIFICATION,
},
type={"string"},
),
# generic numeric sensors
ZWaveDiscoverySchema(
platform="sensor",
hint="numeric_sensor",
command_class={
CommandClass.SENSOR_MULTILEVEL,
CommandClass.METER,
CommandClass.ALARM,
CommandClass.SENSOR_ALARM,
CommandClass.INDICATOR,
CommandClass.BATTERY,
CommandClass.NOTIFICATION,
CommandClass.BASIC,
},
type={"number"},
),
# binary switches
ZWaveDiscoverySchema(
platform="switch",
command_class={CommandClass.SWITCH_BINARY},
property={"currentValue"},
),
Add zwave_js integration (#45020) * Run zwave_js scaffold (#44891) * Add zwave_js basic connection to zwave server (#44904) * add the basic connection to zwave server * fix name * Fix requirements * Fix things * Version bump dep to 0.1.2 * fix pylint Co-authored-by: Paulus Schoutsen <balloob@gmail.com> * Bump zwave-js-server-python to 0.2.0 * Use zwave js server version check instead of fetching full state (#44943) * Use version check instead of fetching full state * Fix tests * Use 0.3.0 * Also catch aiohttp client errors * Update docstring * Lint * Unignore zwave_js * Add zwave_js entity discovery basics and sensor platform (#44927) Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Paulus Schoutsen <balloob@gmail.com> * Complete zwave_js typing (#44960) * Type discovery * Type init * Type entity * Type config flow * Type sensor * Require typing of zwave_js * Complete zwave_js config flow test coverage (#44955) * Correct zwave_js sensor device class (#44968) * Fix zwave_js KeyError on entry setup timeout (#44966) * Bump zwave-js-server-python to 0.5.0 (#44975) * Remove stale callback signal from zwave_js (#44994) * Add light platform to zwave_js integration (#44974) * add light platform * styling fix * fix type hint * Fix typing * Update homeassistant/components/zwave_js/const.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/entity.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/entity.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/entity.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/entity.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/entity.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * color temp should be integer * guard Nonetype error * Update homeassistant/components/zwave_js/light.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/zwave_js/light.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * some fixes after merging * add additional guards for None values * adjustments for rgb lights * Fix typing * Fix black * Bump zwave-js-server-python to 0.6.0 * guard value updated log * remove value_id lookup as its no longer needed * fiz sending white value * Update homeassistant/components/zwave_js/light.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Add zwave_js test foundation (#44983) * Exclude text files from codespell * Add basic dump fixture * Add test foundation * Fix test after rebase * Exclude jsonl files from codespell * Rename fixture file type to jsonl * Update fixture path * Fix stale docstring * Add controller state json fixture * Add multisensor 6 state json fixture * Update fixtures * Remove basic dump fixture * Fix fixtures after library bump * Update codeowner * Minor cleanup Z-Wave JS (#45021) * Update zwave_js device_info (#45023) Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com> Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2021-01-10 18:08:25 -05:00
]
@callback
def async_discover_values(node: ZwaveNode) -> Generator[ZwaveDiscoveryInfo, None, None]:
"""Run discovery on ZWave node and return matching (primary) values."""
for value in node.values.values():
disc_val = async_discover_value(value)
if disc_val:
yield disc_val
@callback
def async_discover_value(value: ZwaveValue) -> Optional[ZwaveDiscoveryInfo]:
"""Run discovery on Z-Wave value and return ZwaveDiscoveryInfo if match found."""
for schema in DISCOVERY_SCHEMAS:
# check device_class_basic
if (
schema.device_class_basic is not None
and value.node.device_class.basic not in schema.device_class_basic
):
continue
# check device_class_generic
if (
schema.device_class_generic is not None
and value.node.device_class.generic not in schema.device_class_generic
):
continue
# check device_class_specific
if (
schema.device_class_specific is not None
and value.node.device_class.specific not in schema.device_class_specific
):
continue
# check command_class
if (
schema.command_class is not None
and value.command_class not in schema.command_class
):
continue
# check endpoint
if schema.endpoint is not None and value.endpoint not in schema.endpoint:
continue
# check property
if schema.property is not None and value.property_ not in schema.property:
continue
# check metadata_type
if schema.type is not None and value.metadata.type not in schema.type:
continue
# all checks passed, this value belongs to an entity
return ZwaveDiscoveryInfo(
node=value.node,
primary_value=value,
platform=schema.platform,
platform_hint=schema.hint,
)
return None