diff --git a/.coveragerc b/.coveragerc index ed5aff10dd6..47400426202 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1464,7 +1464,6 @@ omit = homeassistant/components/ziggo_mediabox_xl/media_player.py homeassistant/components/zoneminder/* homeassistant/components/supla/* - homeassistant/components/zwave/util.py homeassistant/components/zwave_js/discovery.py homeassistant/components/zwave_js/sensor.py homeassistant/components/zwave_me/__init__.py diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 9a561d11997..0b95a1cc96f 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -148,7 +148,6 @@ jobs: sed -i "s|# pySwitchmate|pySwitchmate|g" ${requirement_file} sed -i "s|# face_recognition|face_recognition|g" ${requirement_file} sed -i "s|# python-gammu|python-gammu|g" ${requirement_file} - sed -i "s|# homeassistant-pyozw|homeassistant-pyozw|g" ${requirement_file} done - name: Build wheels diff --git a/CODEOWNERS b/CODEOWNERS index eee2d323086..12a7b42f0d2 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1179,8 +1179,6 @@ tests/components/zodiac/* @JulienTant homeassistant/components/zone/* @home-assistant/core tests/components/zone/* @home-assistant/core homeassistant/components/zoneminder/* @rohankapoorcom -homeassistant/components/zwave/* @home-assistant/z-wave -tests/components/zwave/* @home-assistant/z-wave homeassistant/components/zwave_js/* @home-assistant/z-wave tests/components/zwave_js/* @home-assistant/z-wave homeassistant/components/zwave_me/* @lawfulchaos @Z-Wave-Me diff --git a/Dockerfile b/Dockerfile index 7193d706b89..1d6ce675e74 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,8 +15,7 @@ RUN \ -r homeassistant/requirements.txt --use-deprecated=legacy-resolver COPY requirements_all.txt homeassistant/ RUN \ - sed -i "s|# homeassistant-pyozw|homeassistant-pyozw|g" homeassistant/requirements_all.txt \ - && pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \ + pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \ -r homeassistant/requirements_all.txt --use-deprecated=legacy-resolver ## Setup Home Assistant Core diff --git a/homeassistant/components/config/__init__.py b/homeassistant/components/config/__init__.py index 772f7376acc..329134e5486 100644 --- a/homeassistant/components/config/__init__.py +++ b/homeassistant/components/config/__init__.py @@ -9,7 +9,7 @@ import voluptuous as vol from homeassistant.components import frontend from homeassistant.components.http import HomeAssistantView from homeassistant.const import CONF_ID, EVENT_COMPONENT_LOADED -from homeassistant.core import HomeAssistant, callback +from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.typing import ConfigType from homeassistant.setup import ATTR_COMPONENT @@ -29,7 +29,6 @@ SECTIONS = ( "script", "scene", ) -ON_DEMAND = ("zwave",) ACTION_CREATE_UPDATE = "create_update" ACTION_DELETE = "delete" @@ -53,21 +52,8 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: key = f"{DOMAIN}.{panel_name}" hass.bus.async_fire(EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: key}) - @callback - def component_loaded(event): - """Respond to components being loaded.""" - panel_name = event.data.get(ATTR_COMPONENT) - if panel_name in ON_DEMAND: - hass.async_create_task(setup_panel(panel_name)) - - hass.bus.async_listen(EVENT_COMPONENT_LOADED, component_loaded) - tasks = [asyncio.create_task(setup_panel(panel_name)) for panel_name in SECTIONS] - for panel_name in ON_DEMAND: - if panel_name in hass.config.components: - tasks.append(asyncio.create_task(setup_panel(panel_name))) - if tasks: await asyncio.wait(tasks) diff --git a/homeassistant/components/config/zwave.py b/homeassistant/components/config/zwave.py deleted file mode 100644 index 63b7bdf9868..00000000000 --- a/homeassistant/components/config/zwave.py +++ /dev/null @@ -1,259 +0,0 @@ -"""Provide configuration end points for Z-Wave.""" -from collections import deque -from http import HTTPStatus -import logging - -from aiohttp.web import Response - -from homeassistant.components.http import HomeAssistantView -from homeassistant.components.zwave import DEVICE_CONFIG_SCHEMA_ENTRY, const -import homeassistant.core as ha -import homeassistant.helpers.config_validation as cv - -from . import EditKeyBasedConfigView - -_LOGGER = logging.getLogger(__name__) -CONFIG_PATH = "zwave_device_config.yaml" -OZW_LOG_FILENAME = "OZW_Log.txt" - - -async def async_setup(hass): - """Set up the Z-Wave config API.""" - hass.http.register_view( - EditKeyBasedConfigView( - "zwave", - "device_config", - CONFIG_PATH, - cv.entity_id, - DEVICE_CONFIG_SCHEMA_ENTRY, - ) - ) - hass.http.register_view(ZWaveNodeValueView) - hass.http.register_view(ZWaveNodeGroupView) - hass.http.register_view(ZWaveNodeConfigView) - hass.http.register_view(ZWaveUserCodeView) - hass.http.register_view(ZWaveLogView) - hass.http.register_view(ZWaveConfigWriteView) - hass.http.register_view(ZWaveProtectionView) - - return True - - -class ZWaveLogView(HomeAssistantView): - """View to read the ZWave log file.""" - - url = "/api/zwave/ozwlog" - name = "api:zwave:ozwlog" - - # pylint: disable=no-self-use - async def get(self, request): - """Retrieve the lines from ZWave log.""" - try: - lines = int(request.query.get("lines", 0)) - except ValueError: - return Response(text="Invalid datetime", status=HTTPStatus.BAD_REQUEST) - - hass = request.app["hass"] - response = await hass.async_add_executor_job(self._get_log, hass, lines) - - return Response(text="\n".join(response)) - - def _get_log(self, hass, lines): - """Retrieve the logfile content.""" - logfilepath = hass.config.path(OZW_LOG_FILENAME) - with open(logfilepath, encoding="utf8") as logfile: - data = (line.rstrip() for line in logfile) - if lines == 0: - loglines = list(data) - else: - loglines = deque(data, lines) - return loglines - - -class ZWaveConfigWriteView(HomeAssistantView): - """View to save the ZWave configuration to zwcfg_xxxxx.xml.""" - - url = "/api/zwave/saveconfig" - name = "api:zwave:saveconfig" - - @ha.callback - def post(self, request): - """Save cache configuration to zwcfg_xxxxx.xml.""" - hass = request.app["hass"] - if (network := hass.data.get(const.DATA_NETWORK)) is None: - return self.json_message( - "No Z-Wave network data found", HTTPStatus.NOT_FOUND - ) - _LOGGER.info("Z-Wave configuration written to file") - network.write_config() - return self.json_message("Z-Wave configuration saved to file") - - -class ZWaveNodeValueView(HomeAssistantView): - """View to return the node values.""" - - url = r"/api/zwave/values/{node_id:\d+}" - name = "api:zwave:values" - - @ha.callback - def get(self, request, node_id): - """Retrieve groups of node.""" - nodeid = int(node_id) - hass = request.app["hass"] - values_list = hass.data[const.DATA_ENTITY_VALUES] - - values_data = {} - # Return a list of values for this node that are used as a - # primary value for an entity - for entity_values in values_list: - if entity_values.primary.node.node_id != nodeid: - continue - - values_data[entity_values.primary.value_id] = { - "label": entity_values.primary.label, - "index": entity_values.primary.index, - "instance": entity_values.primary.instance, - "poll_intensity": entity_values.primary.poll_intensity, - } - return self.json(values_data) - - -class ZWaveNodeGroupView(HomeAssistantView): - """View to return the nodes group configuration.""" - - url = r"/api/zwave/groups/{node_id:\d+}" - name = "api:zwave:groups" - - @ha.callback - def get(self, request, node_id): - """Retrieve groups of node.""" - nodeid = int(node_id) - hass = request.app["hass"] - network = hass.data.get(const.DATA_NETWORK) - if (node := network.nodes.get(nodeid)) is None: - return self.json_message("Node not found", HTTPStatus.NOT_FOUND) - groupdata = node.groups - groups = {} - for key, value in groupdata.items(): - groups[key] = { - "associations": value.associations, - "association_instances": value.associations_instances, - "label": value.label, - "max_associations": value.max_associations, - } - return self.json(groups) - - -class ZWaveNodeConfigView(HomeAssistantView): - """View to return the nodes configuration options.""" - - url = r"/api/zwave/config/{node_id:\d+}" - name = "api:zwave:config" - - @ha.callback - def get(self, request, node_id): - """Retrieve configurations of node.""" - nodeid = int(node_id) - hass = request.app["hass"] - network = hass.data.get(const.DATA_NETWORK) - if (node := network.nodes.get(nodeid)) is None: - return self.json_message("Node not found", HTTPStatus.NOT_FOUND) - config = {} - for value in node.get_values( - class_id=const.COMMAND_CLASS_CONFIGURATION - ).values(): - config[value.index] = { - "label": value.label, - "type": value.type, - "help": value.help, - "data_items": value.data_items, - "data": value.data, - "max": value.max, - "min": value.min, - } - return self.json(config) - - -class ZWaveUserCodeView(HomeAssistantView): - """View to return the nodes usercode configuration.""" - - url = r"/api/zwave/usercodes/{node_id:\d+}" - name = "api:zwave:usercodes" - - @ha.callback - def get(self, request, node_id): - """Retrieve usercodes of node.""" - nodeid = int(node_id) - hass = request.app["hass"] - network = hass.data.get(const.DATA_NETWORK) - if (node := network.nodes.get(nodeid)) is None: - return self.json_message("Node not found", HTTPStatus.NOT_FOUND) - usercodes = {} - if not node.has_command_class(const.COMMAND_CLASS_USER_CODE): - return self.json(usercodes) - for value in node.get_values(class_id=const.COMMAND_CLASS_USER_CODE).values(): - if value.genre != const.GENRE_USER: - continue - usercodes[value.index] = { - "code": value.data, - "label": value.label, - "length": len(value.data), - } - return self.json(usercodes) - - -class ZWaveProtectionView(HomeAssistantView): - """View for the protection commandclass of a node.""" - - url = r"/api/zwave/protection/{node_id:\d+}" - name = "api:zwave:protection" - - async def get(self, request, node_id): - """Retrieve the protection commandclass options of node.""" - nodeid = int(node_id) - hass = request.app["hass"] - network = hass.data.get(const.DATA_NETWORK) - - def _fetch_protection(): - """Get protection data.""" - if (node := network.nodes.get(nodeid)) is None: - return self.json_message("Node not found", HTTPStatus.NOT_FOUND) - protection_options = {} - if not node.has_command_class(const.COMMAND_CLASS_PROTECTION): - return self.json(protection_options) - protections = node.get_protections() - protection_options = { - "value_id": f"{list(protections)[0]:d}", - "selected": node.get_protection_item(list(protections)[0]), - "options": node.get_protection_items(list(protections)[0]), - } - return self.json(protection_options) - - return await hass.async_add_executor_job(_fetch_protection) - - async def post(self, request, node_id): - """Change the selected option in protection commandclass.""" - nodeid = int(node_id) - hass = request.app["hass"] - network = hass.data.get(const.DATA_NETWORK) - protection_data = await request.json() - - def _set_protection(): - """Set protection data.""" - node = network.nodes.get(nodeid) - selection = protection_data["selection"] - value_id = int(protection_data[const.ATTR_VALUE_ID]) - if node is None: - return self.json_message("Node not found", HTTPStatus.NOT_FOUND) - if not node.has_command_class(const.COMMAND_CLASS_PROTECTION): - return self.json_message( - "No protection commandclass on this node", HTTPStatus.NOT_FOUND - ) - state = node.set_protection(value_id, selection) - if not state: - return self.json_message( - "Protection setting did not complete", HTTPStatus.ACCEPTED - ) - return self.json_message("Protection setting successfully set") - - return await hass.async_add_executor_job(_set_protection) diff --git a/homeassistant/components/zwave/__init__.py b/homeassistant/components/zwave/__init__.py deleted file mode 100644 index 3424aa11a87..00000000000 --- a/homeassistant/components/zwave/__init__.py +++ /dev/null @@ -1,1355 +0,0 @@ -"""Support for Z-Wave.""" -# pylint: disable=import-error -# pylint: disable=import-outside-toplevel -from __future__ import annotations - -import asyncio -import copy -from importlib import import_module -import logging -from pprint import pprint - -import voluptuous as vol - -from homeassistant import config_entries -from homeassistant.const import ( - ATTR_ENTITY_ID, - ATTR_NAME, - ATTR_VIA_DEVICE, - EVENT_HOMEASSISTANT_START, - EVENT_HOMEASSISTANT_STOP, - Platform, -) -from homeassistant.core import CoreState, Event, HomeAssistant, ServiceCall, callback -from homeassistant.helpers import discovery -import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.device_registry import ( - async_get_registry as async_get_device_registry, -) -from homeassistant.helpers.dispatcher import ( - async_dispatcher_connect, - async_dispatcher_send, -) -from homeassistant.helpers.entity import DeviceInfo, generate_entity_id -from homeassistant.helpers.entity_component import DEFAULT_SCAN_INTERVAL -from homeassistant.helpers.entity_platform import EntityPlatform -from homeassistant.helpers.entity_registry import ( - async_get_registry as async_get_entity_registry, -) -from homeassistant.helpers.entity_values import EntityValues -from homeassistant.helpers.event import async_track_time_change -from homeassistant.helpers.typing import ConfigType -from homeassistant.util import convert -import homeassistant.util.dt as dt_util - -from . import const, websocket_api as wsapi, workaround -from .const import ( - CONF_AUTOHEAL, - CONF_CONFIG_PATH, - CONF_DEBUG, - CONF_NETWORK_KEY, - CONF_POLLING_INTERVAL, - CONF_USB_STICK_PATH, - DATA_DEVICES, - DATA_ENTITY_VALUES, - DATA_NETWORK, - DATA_ZWAVE_CONFIG, - DEFAULT_CONF_AUTOHEAL, - DEFAULT_CONF_USB_STICK_PATH, - DEFAULT_DEBUG, - DEFAULT_POLLING_INTERVAL, - DOMAIN, -) -from .discovery_schemas import DISCOVERY_SCHEMAS -from .migration import ( # noqa: F401 - async_add_migration_entity_value, - async_get_migration_data, - async_is_ozw_migrated, - async_is_zwave_js_migrated, -) -from .node_entity import ZWaveBaseEntity, ZWaveNodeEntity -from .util import ( - check_has_unique_id, - check_node_schema, - check_value_schema, - compute_value_unique_id, - is_node_parsed, - node_device_id_and_name, - node_name, -) - -_LOGGER = logging.getLogger(__name__) - -CLASS_ID = "class_id" - -ATTR_POWER = "power_consumption" - -CONF_POLLING_INTENSITY = "polling_intensity" -CONF_IGNORED = "ignored" -CONF_INVERT_OPENCLOSE_BUTTONS = "invert_openclose_buttons" -CONF_INVERT_PERCENT = "invert_percent" -CONF_REFRESH_VALUE = "refresh_value" -CONF_REFRESH_DELAY = "delay" -CONF_DEVICE_CONFIG = "device_config" -CONF_DEVICE_CONFIG_GLOB = "device_config_glob" -CONF_DEVICE_CONFIG_DOMAIN = "device_config_domain" - -DATA_ZWAVE_CONFIG_YAML_PRESENT = "zwave_config_yaml_present" - -DEFAULT_CONF_IGNORED = False -DEFAULT_CONF_INVERT_OPENCLOSE_BUTTONS = False -DEFAULT_CONF_INVERT_PERCENT = False -DEFAULT_CONF_REFRESH_VALUE = False -DEFAULT_CONF_REFRESH_DELAY = 5 - -PLATFORMS = [ - Platform.BINARY_SENSOR, - Platform.CLIMATE, - Platform.COVER, - Platform.FAN, - Platform.LIGHT, - Platform.LOCK, - Platform.SENSOR, - Platform.SWITCH, -] - -RENAME_NODE_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(ATTR_NAME): cv.string, - vol.Optional(const.ATTR_UPDATE_IDS, default=False): cv.boolean, - } -) - -RENAME_VALUE_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(const.ATTR_VALUE_ID): vol.Coerce(int), - vol.Required(ATTR_NAME): cv.string, - vol.Optional(const.ATTR_UPDATE_IDS, default=False): cv.boolean, - } -) - -SET_CONFIG_PARAMETER_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(const.ATTR_CONFIG_PARAMETER): vol.Coerce(int), - vol.Required(const.ATTR_CONFIG_VALUE): vol.Any(vol.Coerce(int), cv.string), - vol.Optional(const.ATTR_CONFIG_SIZE, default=2): vol.Coerce(int), - } -) - -SET_NODE_VALUE_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(const.ATTR_VALUE_ID): vol.Any(vol.Coerce(int), cv.string), - vol.Required(const.ATTR_CONFIG_VALUE): vol.Any(vol.Coerce(int), cv.string), - } -) - -REFRESH_NODE_VALUE_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(const.ATTR_VALUE_ID): vol.Coerce(int), - } -) - -SET_POLL_INTENSITY_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(const.ATTR_VALUE_ID): vol.Coerce(int), - vol.Required(const.ATTR_POLL_INTENSITY): vol.Coerce(int), - } -) - -PRINT_CONFIG_PARAMETER_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(const.ATTR_CONFIG_PARAMETER): vol.Coerce(int), - } -) - -NODE_SERVICE_SCHEMA = vol.Schema({vol.Required(const.ATTR_NODE_ID): vol.Coerce(int)}) - -REFRESH_ENTITY_SCHEMA = vol.Schema({vol.Required(ATTR_ENTITY_ID): cv.entity_id}) - -RESET_NODE_METERS_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Optional(const.ATTR_INSTANCE, default=1): vol.Coerce(int), - } -) - -CHANGE_ASSOCIATION_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_ASSOCIATION): cv.string, - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(const.ATTR_TARGET_NODE_ID): vol.Coerce(int), - vol.Required(const.ATTR_GROUP): vol.Coerce(int), - vol.Optional(const.ATTR_INSTANCE, default=0x00): vol.Coerce(int), - } -) - -SET_WAKEUP_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(const.ATTR_CONFIG_VALUE): vol.All( - vol.Coerce(int), cv.positive_int - ), - } -) - -HEAL_NODE_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Optional(const.ATTR_RETURN_ROUTES, default=False): cv.boolean, - } -) - -TEST_NODE_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Optional(const.ATTR_MESSAGES, default=1): cv.positive_int, - } -) - - -DEVICE_CONFIG_SCHEMA_ENTRY = vol.Schema( - { - vol.Optional(CONF_POLLING_INTENSITY): cv.positive_int, - vol.Optional(CONF_IGNORED, default=DEFAULT_CONF_IGNORED): cv.boolean, - vol.Optional( - CONF_INVERT_OPENCLOSE_BUTTONS, default=DEFAULT_CONF_INVERT_OPENCLOSE_BUTTONS - ): cv.boolean, - vol.Optional( - CONF_INVERT_PERCENT, default=DEFAULT_CONF_INVERT_PERCENT - ): cv.boolean, - vol.Optional( - CONF_REFRESH_VALUE, default=DEFAULT_CONF_REFRESH_VALUE - ): cv.boolean, - vol.Optional( - CONF_REFRESH_DELAY, default=DEFAULT_CONF_REFRESH_DELAY - ): cv.positive_int, - } -) - -SIGNAL_REFRESH_ENTITY_FORMAT = "zwave_refresh_entity_{}" - -CONFIG_SCHEMA = vol.Schema( - { - DOMAIN: vol.Schema( - { - vol.Optional(CONF_AUTOHEAL, default=DEFAULT_CONF_AUTOHEAL): cv.boolean, - vol.Optional(CONF_CONFIG_PATH): cv.string, - vol.Optional(CONF_NETWORK_KEY): vol.All( - cv.string, vol.Match(r"(0x\w\w,\s?){15}0x\w\w") - ), - vol.Optional(CONF_DEVICE_CONFIG, default={}): vol.Schema( - {cv.entity_id: DEVICE_CONFIG_SCHEMA_ENTRY} - ), - vol.Optional(CONF_DEVICE_CONFIG_GLOB, default={}): vol.Schema( - {cv.string: DEVICE_CONFIG_SCHEMA_ENTRY} - ), - vol.Optional(CONF_DEVICE_CONFIG_DOMAIN, default={}): vol.Schema( - {cv.string: DEVICE_CONFIG_SCHEMA_ENTRY} - ), - vol.Optional(CONF_DEBUG, default=DEFAULT_DEBUG): cv.boolean, - vol.Optional( - CONF_POLLING_INTERVAL, default=DEFAULT_POLLING_INTERVAL - ): cv.positive_int, - vol.Optional(CONF_USB_STICK_PATH): cv.string, - } - ) - }, - extra=vol.ALLOW_EXTRA, -) - - -def _obj_to_dict(obj): - """Convert an object into a hash for debug.""" - return { - key: getattr(obj, key) - for key in dir(obj) - if key[0] != "_" and not callable(getattr(obj, key)) - } - - -def _value_name(value): - """Return the name of the value.""" - return f"{node_name(value.node)} {value.label}".strip() - - -def nice_print_node(node): - """Print a nice formatted node to the output (debug method).""" - node_dict = _obj_to_dict(node) - node_dict["values"] = { - value_id: _obj_to_dict(value) for value_id, value in node.values.items() - } - - _LOGGER.info("FOUND NODE %s \n%s", node.product_name, node_dict) - - -def get_config_value(node, value_index, tries=5): - """Return the current configuration value for a specific index.""" - try: - for value in node.values.values(): - if ( - value.command_class == const.COMMAND_CLASS_CONFIGURATION - and value.index == value_index - ): - return value.data - except RuntimeError: - # If we get a runtime error the dict has changed while - # we was looking for a value, just do it again - return ( - None if tries <= 0 else get_config_value(node, value_index, tries=tries - 1) - ) - return None - - -async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): - """Set up the Z-Wave platform (generic part).""" - if discovery_info is None or DATA_NETWORK not in hass.data: - return False - - device = hass.data[DATA_DEVICES].get(discovery_info[const.DISCOVERY_DEVICE]) - if device is None: - return False - - async_add_entities([device]) - return True - - -async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: - """Set up Z-Wave components.""" - if DOMAIN not in config: - return True - - conf = config[DOMAIN] - hass.data[DATA_ZWAVE_CONFIG] = conf - hass.data[DATA_ZWAVE_CONFIG_YAML_PRESENT] = True - - if not hass.config_entries.async_entries(DOMAIN): - hass.async_create_task( - hass.config_entries.flow.async_init( - DOMAIN, - context={"source": config_entries.SOURCE_IMPORT}, - data={ - CONF_USB_STICK_PATH: conf.get( - CONF_USB_STICK_PATH, DEFAULT_CONF_USB_STICK_PATH - ), - CONF_NETWORK_KEY: conf.get(CONF_NETWORK_KEY), - }, - ) - ) - - return True - - -async def async_setup_entry( # noqa: C901 - hass: HomeAssistant, config_entry: config_entries.ConfigEntry -) -> bool: - """Set up Z-Wave from a config entry. - - Will automatically load components to support devices found on the network. - """ - from openzwave.group import ZWaveGroup - from openzwave.network import ZWaveNetwork - from openzwave.option import ZWaveOption - from pydispatch import dispatcher - - if async_is_ozw_migrated(hass) or async_is_zwave_js_migrated(hass): - - if hass.data.get(DATA_ZWAVE_CONFIG_YAML_PRESENT): - config_yaml_message = ( - ", and remove %s from configuration.yaml " - "to avoid setting up this integration on restart ", - DOMAIN, - ) - else: - config_yaml_message = "" - - _LOGGER.error( - "Migration away from legacy Z-Wave has been done. " - "Please remove the %s integration%s", - DOMAIN, - config_yaml_message, - ) - return False - - # Merge config entry and yaml config - config = config_entry.data - if DATA_ZWAVE_CONFIG in hass.data: - config = {**config, **hass.data[DATA_ZWAVE_CONFIG]} - - # Update hass.data with merged config so we can access it elsewhere - hass.data[DATA_ZWAVE_CONFIG] = config - - # Load configuration - use_debug = config.get(CONF_DEBUG, DEFAULT_DEBUG) - autoheal = config.get(CONF_AUTOHEAL, DEFAULT_CONF_AUTOHEAL) - device_config = EntityValues( - config.get(CONF_DEVICE_CONFIG), - config.get(CONF_DEVICE_CONFIG_DOMAIN), - config.get(CONF_DEVICE_CONFIG_GLOB), - ) - - usb_path = config[CONF_USB_STICK_PATH] - - _LOGGER.info("Z-Wave USB path is %s", usb_path) - - # Setup options - options = ZWaveOption( - usb_path, - user_path=hass.config.config_dir, - config_path=config.get(CONF_CONFIG_PATH), - ) - - options.set_console_output(use_debug) - - if config.get(CONF_NETWORK_KEY): - options.addOption("NetworkKey", config[CONF_NETWORK_KEY]) - - await hass.async_add_executor_job(options.lock) - network = hass.data[DATA_NETWORK] = ZWaveNetwork(options, autostart=False) - hass.data[DATA_DEVICES] = {} - hass.data[DATA_ENTITY_VALUES] = [] - - registry = await async_get_entity_registry(hass) - - wsapi.async_load_websocket_api(hass) - - if use_debug: # pragma: no cover - - def log_all(signal, value=None): - """Log all the signals.""" - print("") - print("SIGNAL *****", signal) - if value and signal in ( - ZWaveNetwork.SIGNAL_VALUE_CHANGED, - ZWaveNetwork.SIGNAL_VALUE_ADDED, - ZWaveNetwork.SIGNAL_SCENE_EVENT, - ZWaveNetwork.SIGNAL_NODE_EVENT, - ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, - ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED, - ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED_SOME_DEAD, - ): - pprint(_obj_to_dict(value)) - - print("") - - dispatcher.connect(log_all, weak=False) - - def value_added(node, value): - """Handle new added value to a node on the network.""" - # Check if this value should be tracked by an existing entity - for values in hass.data[DATA_ENTITY_VALUES]: - values.check_value(value) - - for schema in DISCOVERY_SCHEMAS: - if not check_node_schema(node, schema): - continue - if not check_value_schema( - value, schema[const.DISC_VALUES][const.DISC_PRIMARY] - ): - continue - - values = ZWaveDeviceEntityValues( - hass, schema, value, config, device_config, registry - ) - - # We create a new list and update the reference here so that - # the list can be safely iterated over in the main thread - new_values = hass.data[DATA_ENTITY_VALUES] + [values] - hass.data[DATA_ENTITY_VALUES] = new_values - - platform = EntityPlatform( - hass=hass, - logger=_LOGGER, - domain=DOMAIN, - platform_name=DOMAIN, - platform=None, - scan_interval=DEFAULT_SCAN_INTERVAL, - entity_namespace=None, - ) - platform.config_entry = config_entry - - def node_added(node): - """Handle a new node on the network.""" - entity = ZWaveNodeEntity(node, network) - - async def _add_node_to_component(): - if hass.data[DATA_DEVICES].get(entity.unique_id): - return - - name = node_name(node) - generated_id = generate_entity_id(DOMAIN + ".{}", name, []) - node_config = device_config.get(generated_id) - if node_config.get(CONF_IGNORED): - _LOGGER.info( - "Ignoring node entity %s due to device settings", generated_id - ) - return - - hass.data[DATA_DEVICES][entity.unique_id] = entity - await platform.async_add_entities([entity]) - - if entity.unique_id: - hass.create_task(_add_node_to_component()) - return - - @callback - def _on_ready(sec): - _LOGGER.info("Z-Wave node %d ready after %d seconds", entity.node_id, sec) - hass.async_add_job(_add_node_to_component) - - @callback - def _on_timeout(sec): - _LOGGER.warning( - "Z-Wave node %d not ready after %d seconds, continuing anyway", - entity.node_id, - sec, - ) - hass.async_add_job(_add_node_to_component) - - hass.add_job(check_has_unique_id, entity, _on_ready, _on_timeout) - - def node_removed(node): - node_id = node.node_id - node_key = f"node-{node_id}" - for key in list(hass.data[DATA_DEVICES]): - if key is None: - continue - if not key.startswith(f"{node_id}-"): - continue - - entity = hass.data[DATA_DEVICES][key] - _LOGGER.debug( - "Removing Entity - value: %s - entity_id: %s", key, entity.entity_id - ) - hass.add_job(entity.node_removed()) - del hass.data[DATA_DEVICES][key] - - entity = hass.data[DATA_DEVICES][node_key] - hass.add_job(entity.node_removed()) - del hass.data[DATA_DEVICES][node_key] - - hass.add_job(_remove_device(node)) - - async def _remove_device(node): - dev_reg = await async_get_device_registry(hass) - identifier, name = node_device_id_and_name(node) - device = dev_reg.async_get_device(identifiers={identifier}) - if device is not None: - _LOGGER.debug("Removing Device - %s - %s", device.id, name) - dev_reg.async_remove_device(device.id) - - def network_ready(): - """Handle the query of all awake nodes.""" - _LOGGER.info( - "Z-Wave network is ready for use. All awake nodes " - "have been queried. Sleeping nodes will be " - "queried when they awake" - ) - hass.bus.fire(const.EVENT_NETWORK_READY) - - def network_complete(): - """Handle the querying of all nodes on network.""" - _LOGGER.info( - "Z-Wave network is complete. All nodes on the network have been queried" - ) - hass.bus.fire(const.EVENT_NETWORK_COMPLETE) - - def network_complete_some_dead(): - """Handle the querying of all nodes on network.""" - _LOGGER.info( - "Z-Wave network is complete. All nodes on the network " - "have been queried, but some nodes are marked dead" - ) - hass.bus.fire(const.EVENT_NETWORK_COMPLETE_SOME_DEAD) - - dispatcher.connect(value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED, weak=False) - dispatcher.connect(node_added, ZWaveNetwork.SIGNAL_NODE_ADDED, weak=False) - dispatcher.connect(node_removed, ZWaveNetwork.SIGNAL_NODE_REMOVED, weak=False) - dispatcher.connect( - network_ready, ZWaveNetwork.SIGNAL_AWAKE_NODES_QUERIED, weak=False - ) - dispatcher.connect( - network_complete, ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED, weak=False - ) - dispatcher.connect( - network_complete_some_dead, - ZWaveNetwork.SIGNAL_ALL_NODES_QUERIED_SOME_DEAD, - weak=False, - ) - - def add_node(service: ServiceCall) -> None: - """Switch into inclusion mode.""" - _LOGGER.info("Z-Wave add_node have been initialized") - network.controller.add_node() - - def add_node_secure(service: ServiceCall) -> None: - """Switch into secure inclusion mode.""" - _LOGGER.info("Z-Wave add_node_secure have been initialized") - network.controller.add_node(True) - - def remove_node(service: ServiceCall) -> None: - """Switch into exclusion mode.""" - _LOGGER.info("Z-Wave remove_node have been initialized") - network.controller.remove_node() - - def cancel_command(service: ServiceCall) -> None: - """Cancel a running controller command.""" - _LOGGER.info("Cancel running Z-Wave command") - network.controller.cancel_command() - - def heal_network(service: ServiceCall) -> None: - """Heal the network.""" - _LOGGER.info("Z-Wave heal running") - network.heal() - - def soft_reset(service: ServiceCall) -> None: - """Soft reset the controller.""" - _LOGGER.info("Z-Wave soft_reset have been initialized") - network.controller.soft_reset() - - def test_network(service: ServiceCall) -> None: - """Test the network by sending commands to all the nodes.""" - _LOGGER.info("Z-Wave test_network have been initialized") - network.test() - - def stop_network(_service_or_event: Event | ServiceCall) -> None: - """Stop Z-Wave network.""" - _LOGGER.info("Stopping Z-Wave network") - network.stop() - if hass.state == CoreState.running: - hass.bus.fire(const.EVENT_NETWORK_STOP) - - async def rename_node(service: ServiceCall) -> None: - """Rename a node.""" - node_id = service.data.get(const.ATTR_NODE_ID) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - name = service.data.get(ATTR_NAME) - node.name = name - _LOGGER.info("Renamed Z-Wave node %d to %s", node_id, name) - update_ids = service.data.get(const.ATTR_UPDATE_IDS) - # We want to rename the device, the node entity, - # and all the contained entities - node_key = f"node-{node_id}" - entity = hass.data[DATA_DEVICES][node_key] - await entity.node_renamed(update_ids) - for key in list(hass.data[DATA_DEVICES]): - if not key.startswith(f"{node_id}-"): - continue - entity = hass.data[DATA_DEVICES][key] - await entity.value_renamed(update_ids) - - async def rename_value(service: ServiceCall) -> None: - """Rename a node value.""" - node_id = service.data.get(const.ATTR_NODE_ID) - value_id = service.data.get(const.ATTR_VALUE_ID) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - value = node.values[value_id] - name = service.data.get(ATTR_NAME) - value.label = name - _LOGGER.info( - "Renamed Z-Wave value (Node %d Value %d) to %s", node_id, value_id, name - ) - update_ids = service.data.get(const.ATTR_UPDATE_IDS) - value_key = f"{node_id}-{value_id}" - entity = hass.data[DATA_DEVICES][value_key] - await entity.value_renamed(update_ids) - - def set_poll_intensity(service: ServiceCall) -> None: - """Set the polling intensity of a node value.""" - node_id = service.data.get(const.ATTR_NODE_ID) - value_id = service.data.get(const.ATTR_VALUE_ID) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - value = node.values[value_id] - intensity = service.data.get(const.ATTR_POLL_INTENSITY) - if intensity == 0: - if value.disable_poll(): - _LOGGER.info("Polling disabled (Node %d Value %d)", node_id, value_id) - return - _LOGGER.info( - "Polling disabled failed (Node %d Value %d)", node_id, value_id - ) - else: - if value.enable_poll(intensity): - _LOGGER.info( - "Set polling intensity (Node %d Value %d) to %s", - node_id, - value_id, - intensity, - ) - return - _LOGGER.info( - "Set polling intensity failed (Node %d Value %d)", node_id, value_id - ) - - def remove_failed_node(service: ServiceCall) -> None: - """Remove failed node.""" - node_id = service.data.get(const.ATTR_NODE_ID) - _LOGGER.info("Trying to remove zwave node %d", node_id) - network.controller.remove_failed_node(node_id) - - def replace_failed_node(service: ServiceCall) -> None: - """Replace failed node.""" - node_id = service.data.get(const.ATTR_NODE_ID) - _LOGGER.info("Trying to replace zwave node %d", node_id) - network.controller.replace_failed_node(node_id) - - def set_config_parameter(service: ServiceCall) -> None: - """Set a config parameter to a node.""" - node_id = service.data.get(const.ATTR_NODE_ID) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - param = service.data.get(const.ATTR_CONFIG_PARAMETER) - selection = service.data.get(const.ATTR_CONFIG_VALUE) - size = service.data.get(const.ATTR_CONFIG_SIZE) - for value in node.get_values( - class_id=const.COMMAND_CLASS_CONFIGURATION - ).values(): - if value.index != param: - continue - if value.type == const.TYPE_BOOL: - value.data = int(selection == "True") - _LOGGER.info( - "Setting configuration parameter %s on Node %s with bool selection %s", - param, - node_id, - str(selection), - ) - return - if value.type == const.TYPE_LIST: - value.data = str(selection) - _LOGGER.info( - "Setting configuration parameter %s on Node %s with list selection %s", - param, - node_id, - str(selection), - ) - return - if value.type == const.TYPE_BUTTON: - network.manager.pressButton(value.value_id) - network.manager.releaseButton(value.value_id) - _LOGGER.info( - "Setting configuration parameter %s on Node %s " - "with button selection %s", - param, - node_id, - selection, - ) - return - value.data = int(selection) - _LOGGER.info( - "Setting configuration parameter %s on Node %s with selection %s", - param, - node_id, - selection, - ) - return - node.set_config_param(param, selection, size) - _LOGGER.info( - "Setting unknown configuration parameter %s on Node %s with selection %s", - param, - node_id, - selection, - ) - - def refresh_node_value(service: ServiceCall) -> None: - """Refresh the specified value from a node.""" - node_id = service.data.get(const.ATTR_NODE_ID) - value_id = service.data.get(const.ATTR_VALUE_ID) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - node.values[value_id].refresh() - _LOGGER.info("Node %s value %s refreshed", node_id, value_id) - - def set_node_value(service: ServiceCall) -> None: - """Set the specified value on a node.""" - node_id = service.data.get(const.ATTR_NODE_ID) - value_id = service.data.get(const.ATTR_VALUE_ID) - value = service.data.get(const.ATTR_CONFIG_VALUE) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - node.values[value_id].data = value - _LOGGER.info("Node %s value %s set to %s", node_id, value_id, value) - - def print_config_parameter(service: ServiceCall) -> None: - """Print a config parameter from a node.""" - node_id = service.data.get(const.ATTR_NODE_ID) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - param = service.data.get(const.ATTR_CONFIG_PARAMETER) - _LOGGER.info( - "Config parameter %s on Node %s: %s", - param, - node_id, - get_config_value(node, param), - ) - - def print_node(service: ServiceCall) -> None: - """Print all information about z-wave node.""" - node_id = service.data.get(const.ATTR_NODE_ID) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - nice_print_node(node) - - def set_wakeup(service: ServiceCall) -> None: - """Set wake-up interval of a node.""" - node_id = service.data.get(const.ATTR_NODE_ID) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - value = service.data.get(const.ATTR_CONFIG_VALUE) - if node.can_wake_up(): - for value_id in node.get_values(class_id=const.COMMAND_CLASS_WAKE_UP): - node.values[value_id].data = value - _LOGGER.info("Node %s wake-up set to %d", node_id, value) - else: - _LOGGER.info("Node %s is not wakeable", node_id) - - def change_association(service: ServiceCall) -> None: - """Change an association in the zwave network.""" - association_type = service.data.get(const.ATTR_ASSOCIATION) - node_id = service.data.get(const.ATTR_NODE_ID) - target_node_id = service.data.get(const.ATTR_TARGET_NODE_ID) - group = service.data.get(const.ATTR_GROUP) - instance = service.data.get(const.ATTR_INSTANCE) - - node = ZWaveGroup(group, network, node_id) - if association_type == "add": - node.add_association(target_node_id, instance) - _LOGGER.info( - "Adding association for node:%s in group:%s " - "target node:%s, instance=%s", - node_id, - group, - target_node_id, - instance, - ) - if association_type == "remove": - node.remove_association(target_node_id, instance) - _LOGGER.info( - "Removing association for node:%s in group:%s " - "target node:%s, instance=%s", - node_id, - group, - target_node_id, - instance, - ) - - async def async_refresh_entity(service: ServiceCall) -> None: - """Refresh values that specific entity depends on.""" - entity_id = service.data.get(ATTR_ENTITY_ID) - async_dispatcher_send(hass, SIGNAL_REFRESH_ENTITY_FORMAT.format(entity_id)) - - def refresh_node(service: ServiceCall) -> None: - """Refresh all node info.""" - node_id = service.data.get(const.ATTR_NODE_ID) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - node.refresh_info() - - def reset_node_meters(service: ServiceCall) -> None: - """Reset meter counters of a node.""" - node_id = service.data.get(const.ATTR_NODE_ID) - instance = service.data.get(const.ATTR_INSTANCE) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - for value in node.get_values(class_id=const.COMMAND_CLASS_METER).values(): - if value.index != const.INDEX_METER_RESET: - continue - if value.instance != instance: - continue - network.manager.pressButton(value.value_id) - network.manager.releaseButton(value.value_id) - _LOGGER.info("Resetting meters on node %s instance %s", node_id, instance) - return - _LOGGER.info( - "Node %s on instance %s does not have resettable meters", node_id, instance - ) - - def heal_node(service: ServiceCall) -> None: - """Heal a node on the network.""" - node_id = service.data.get(const.ATTR_NODE_ID) - update_return_routes = service.data.get(const.ATTR_RETURN_ROUTES) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - _LOGGER.info("Z-Wave node heal running for node %s", node_id) - node.heal(update_return_routes) - - def test_node(service: ServiceCall) -> None: - """Send test messages to a node on the network.""" - node_id = service.data.get(const.ATTR_NODE_ID) - messages = service.data.get(const.ATTR_MESSAGES) - node = network.nodes[node_id] # pylint: disable=unsubscriptable-object - _LOGGER.info("Sending %s test-messages to node %s", messages, node_id) - node.test(messages) - - def start_zwave(_service_or_event: ServiceCall | Event) -> None: - """Startup Z-Wave network.""" - _LOGGER.info("Starting Z-Wave network") - network.start() - hass.bus.fire(const.EVENT_NETWORK_START) - - async def _check_awaked(): - """Wait for Z-wave awaked state (or timeout) and finalize start.""" - _LOGGER.debug("network state: %d %s", network.state, network.state_str) - - start_time = dt_util.utcnow() - while True: - waited = int((dt_util.utcnow() - start_time).total_seconds()) - - if network.state >= network.STATE_AWAKED: - # Need to be in STATE_AWAKED before talking to nodes. - _LOGGER.info("Z-Wave ready after %d seconds", waited) - break - - if waited >= const.NETWORK_READY_WAIT_SECS: - # Wait up to NETWORK_READY_WAIT_SECS seconds for the Z-Wave - # network to be ready. - _LOGGER.warning( - "Z-Wave not ready after %d seconds, continuing anyway", waited - ) - _LOGGER.info( - "Final network state: %d %s", network.state, network.state_str - ) - break - - await asyncio.sleep(1) - - hass.async_add_job(_finalize_start) - - hass.add_job(_check_awaked) - - def _finalize_start(): - """Perform final initializations after Z-Wave network is awaked.""" - polling_interval = convert(config.get(CONF_POLLING_INTERVAL), int) - if polling_interval is not None: - network.set_poll_interval(polling_interval, False) - - poll_interval = network.get_poll_interval() - _LOGGER.info("Z-Wave polling interval set to %d ms", poll_interval) - - hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_network) - - # Register node services for Z-Wave network - hass.services.register(DOMAIN, const.SERVICE_ADD_NODE, add_node) - hass.services.register(DOMAIN, const.SERVICE_ADD_NODE_SECURE, add_node_secure) - hass.services.register(DOMAIN, const.SERVICE_REMOVE_NODE, remove_node) - hass.services.register(DOMAIN, const.SERVICE_CANCEL_COMMAND, cancel_command) - hass.services.register(DOMAIN, const.SERVICE_HEAL_NETWORK, heal_network) - hass.services.register(DOMAIN, const.SERVICE_SOFT_RESET, soft_reset) - hass.services.register(DOMAIN, const.SERVICE_TEST_NETWORK, test_network) - hass.services.register(DOMAIN, const.SERVICE_STOP_NETWORK, stop_network) - hass.services.register( - DOMAIN, const.SERVICE_RENAME_NODE, rename_node, schema=RENAME_NODE_SCHEMA - ) - hass.services.register( - DOMAIN, const.SERVICE_RENAME_VALUE, rename_value, schema=RENAME_VALUE_SCHEMA - ) - hass.services.register( - DOMAIN, - const.SERVICE_SET_CONFIG_PARAMETER, - set_config_parameter, - schema=SET_CONFIG_PARAMETER_SCHEMA, - ) - hass.services.register( - DOMAIN, - const.SERVICE_SET_NODE_VALUE, - set_node_value, - schema=SET_NODE_VALUE_SCHEMA, - ) - hass.services.register( - DOMAIN, - const.SERVICE_REFRESH_NODE_VALUE, - refresh_node_value, - schema=REFRESH_NODE_VALUE_SCHEMA, - ) - hass.services.register( - DOMAIN, - const.SERVICE_PRINT_CONFIG_PARAMETER, - print_config_parameter, - schema=PRINT_CONFIG_PARAMETER_SCHEMA, - ) - hass.services.register( - DOMAIN, - const.SERVICE_REMOVE_FAILED_NODE, - remove_failed_node, - schema=NODE_SERVICE_SCHEMA, - ) - hass.services.register( - DOMAIN, - const.SERVICE_REPLACE_FAILED_NODE, - replace_failed_node, - schema=NODE_SERVICE_SCHEMA, - ) - - hass.services.register( - DOMAIN, - const.SERVICE_CHANGE_ASSOCIATION, - change_association, - schema=CHANGE_ASSOCIATION_SCHEMA, - ) - hass.services.register( - DOMAIN, const.SERVICE_SET_WAKEUP, set_wakeup, schema=SET_WAKEUP_SCHEMA - ) - hass.services.register( - DOMAIN, const.SERVICE_PRINT_NODE, print_node, schema=NODE_SERVICE_SCHEMA - ) - hass.services.register( - DOMAIN, - const.SERVICE_REFRESH_ENTITY, - async_refresh_entity, - schema=REFRESH_ENTITY_SCHEMA, - ) - hass.services.register( - DOMAIN, const.SERVICE_REFRESH_NODE, refresh_node, schema=NODE_SERVICE_SCHEMA - ) - hass.services.register( - DOMAIN, - const.SERVICE_RESET_NODE_METERS, - reset_node_meters, - schema=RESET_NODE_METERS_SCHEMA, - ) - hass.services.register( - DOMAIN, - const.SERVICE_SET_POLL_INTENSITY, - set_poll_intensity, - schema=SET_POLL_INTENSITY_SCHEMA, - ) - hass.services.register( - DOMAIN, const.SERVICE_HEAL_NODE, heal_node, schema=HEAL_NODE_SCHEMA - ) - hass.services.register( - DOMAIN, const.SERVICE_TEST_NODE, test_node, schema=TEST_NODE_SCHEMA - ) - - # Setup autoheal - if autoheal: - _LOGGER.info("Z-Wave network autoheal is enabled") - async_track_time_change(hass, heal_network, hour=0, minute=0, second=0) - - hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, start_zwave) - - hass.services.async_register(DOMAIN, const.SERVICE_START_NETWORK, start_zwave) - - hass.config_entries.async_setup_platforms(config_entry, PLATFORMS) - - return True - - -class ZWaveDeviceEntityValues: - """Manages entity access to the underlying zwave value objects.""" - - def __init__( - self, hass, schema, primary_value, zwave_config, device_config, registry - ): - """Initialize the values object with the passed entity schema.""" - self._hass = hass - self._zwave_config = zwave_config - self._device_config = device_config - self._schema = copy.deepcopy(schema) - self._values = {} - self._entity = None - self._workaround_ignore = False - self._registry = registry - - for name in self._schema[const.DISC_VALUES].keys(): - self._values[name] = None - self._schema[const.DISC_VALUES][name][const.DISC_INSTANCE] = [ - primary_value.instance - ] - - self._values[const.DISC_PRIMARY] = primary_value - self._node = primary_value.node - self._schema[const.DISC_NODE_ID] = [self._node.node_id] - - # Check values that have already been discovered for node - for value in self._node.values.values(): - self.check_value(value) - - self._check_entity_ready() - - def __getattr__(self, name): - """Get the specified value for this entity.""" - return self._values[name] - - def __iter__(self): - """Allow iteration over all values.""" - return iter(self._values.values()) - - def check_value(self, value): - """Check if the new value matches a missing value for this entity. - - If a match is found, it is added to the values mapping. - """ - if not check_node_schema(value.node, self._schema): - return - for name, name_value in self._values.items(): - if name_value is not None: - continue - if not check_value_schema(value, self._schema[const.DISC_VALUES][name]): - continue - self._values[name] = value - if self._entity: - self._entity.value_added() - self._entity.value_changed() - - self._check_entity_ready() - - def _check_entity_ready(self): - """Check if all required values are discovered and create entity.""" - if self._workaround_ignore: - return - if self._entity is not None: - return - - for name in self._schema[const.DISC_VALUES]: - if self._values[name] is None and not self._schema[const.DISC_VALUES][ - name - ].get(const.DISC_OPTIONAL): - return - - component = self._schema[const.DISC_COMPONENT] - - workaround_component = workaround.get_device_component_mapping(self.primary) - if workaround_component and workaround_component != component: - if workaround_component == workaround.WORKAROUND_IGNORE: - _LOGGER.info( - "Ignoring Node %d Value %d due to workaround", - self.primary.node.node_id, - self.primary.value_id, - ) - # No entity will be created for this value - self._workaround_ignore = True - return - _LOGGER.debug("Using %s instead of %s", workaround_component, component) - component = workaround_component - - entity_id = self._registry.async_get_entity_id( - component, DOMAIN, compute_value_unique_id(self._node, self.primary) - ) - if entity_id is None: - value_name = _value_name(self.primary) - entity_id = generate_entity_id(component + ".{}", value_name, []) - node_config = self._device_config.get(entity_id) - - # Configure node - _LOGGER.debug( - "Adding Node_id=%s Generic_command_class=%s, " - "Specific_command_class=%s, " - "Command_class=%s, Value type=%s, " - "Genre=%s as %s", - self._node.node_id, - self._node.generic, - self._node.specific, - self.primary.command_class, - self.primary.type, - self.primary.genre, - component, - ) - - if node_config.get(CONF_IGNORED): - _LOGGER.info("Ignoring entity %s due to device settings", entity_id) - # No entity will be created for this value - self._workaround_ignore = True - return - - polling_intensity = convert(node_config.get(CONF_POLLING_INTENSITY), int) - if polling_intensity: - self.primary.enable_poll(polling_intensity) - - platform = import_module(f".{component}", __name__) - - device = platform.get_device( - node=self._node, values=self, node_config=node_config, hass=self._hass - ) - if device is None: - # No entity will be created for this value - self._workaround_ignore = True - return - - self._entity = device - - @callback - def _on_ready(sec): - _LOGGER.info( - "Z-Wave entity %s (node_id: %d) ready after %d seconds", - device.name, - self._node.node_id, - sec, - ) - self._hass.async_add_job(discover_device, component, device) - - @callback - def _on_timeout(sec): - _LOGGER.warning( - "Z-Wave entity %s (node_id: %d) not ready after %d seconds, " - "continuing anyway", - device.name, - self._node.node_id, - sec, - ) - self._hass.async_add_job(discover_device, component, device) - - async def discover_device(component, device): - """Put device in a dictionary and call discovery on it.""" - if self._hass.data[DATA_DEVICES].get(device.unique_id): - return - - self._hass.data[DATA_DEVICES][device.unique_id] = device - if component in PLATFORMS: - async_dispatcher_send(self._hass, f"zwave_new_{component}", device) - else: - await discovery.async_load_platform( - self._hass, - component, - DOMAIN, - {const.DISCOVERY_DEVICE: device.unique_id}, - self._zwave_config, - ) - - if device.unique_id: - self._hass.add_job(discover_device, component, device) - else: - self._hass.add_job(check_has_unique_id, device, _on_ready, _on_timeout) - - -class ZWaveDeviceEntity(ZWaveBaseEntity): - """Representation of a Z-Wave node entity.""" - - def __init__(self, values, domain): - """Initialize the z-Wave device.""" - super().__init__() - from openzwave.network import ZWaveNetwork - from pydispatch import dispatcher - - self.values = values - self.node = values.primary.node - self.values.primary.set_change_verified(False) - - self._name = _value_name(self.values.primary) - self._unique_id = self._compute_unique_id() - self._update_attributes() - - dispatcher.connect( - self.network_value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED - ) - - def network_value_changed(self, value): - """Handle a value change on the network.""" - if value.value_id in [v.value_id for v in self.values if v]: - return self.value_changed() - - def value_added(self): - """Handle a new value of this entity.""" - - def value_changed(self): - """Handle a changed value for this entity's node.""" - self._update_attributes() - self.update_properties() - self.maybe_schedule_update() - - async def value_renamed(self, update_ids=False): - """Rename the node and update any IDs.""" - self._name = _value_name(self.values.primary) - if update_ids: - # Update entity ID. - ent_reg = await async_get_entity_registry(self.hass) - new_entity_id = ent_reg.async_generate_entity_id( - self.platform.domain, - self._name, - self.platform.entities.keys() - {self.entity_id}, - ) - if new_entity_id != self.entity_id: - # Don't change the name attribute, it will be None unless - # customised and if it's been customised, keep the - # customisation. - ent_reg.async_update_entity(self.entity_id, new_entity_id=new_entity_id) - return - # else for the above two ifs, update if not using update_entity - self.async_write_ha_state() - - async def async_added_to_hass(self): - """Add device to dict.""" - async_dispatcher_connect( - self.hass, - SIGNAL_REFRESH_ENTITY_FORMAT.format(self.entity_id), - self.refresh_from_network, - ) - - # Add legacy Z-Wave migration data. - await async_add_migration_entity_value(self.hass, self.entity_id, self.values) - - def _update_attributes(self): - """Update the node attributes. May only be used inside callback.""" - self.node_id = self.node.node_id - self._name = _value_name(self.values.primary) - if not self._unique_id: - self._unique_id = self._compute_unique_id() - if self._unique_id: - self.try_remove_and_add() - - if self.values.power: - self.power_consumption = round( - self.values.power.data, self.values.power.precision - ) - else: - self.power_consumption = None - - def update_properties(self): - """Update on data changes for node values.""" - - @property - def should_poll(self): - """No polling needed.""" - return False - - @property - def unique_id(self): - """Return a unique ID.""" - return self._unique_id - - @property - def device_info(self) -> DeviceInfo: - """Return device information.""" - identifier, name = node_device_id_and_name( - self.node, self.values.primary.instance - ) - info = DeviceInfo( - name=name, - identifiers={identifier}, - manufacturer=self.node.manufacturer_name, - model=self.node.product_name, - ) - if self.values.primary.instance > 1: - info[ATTR_VIA_DEVICE] = (DOMAIN, self.node_id) - elif self.node_id > 1: - info[ATTR_VIA_DEVICE] = (DOMAIN, 1) - return info - - @property - def name(self): - """Return the name of the device.""" - return self._name - - @property - def extra_state_attributes(self): - """Return the device specific state attributes.""" - attrs = { - const.ATTR_NODE_ID: self.node_id, - const.ATTR_VALUE_INDEX: self.values.primary.index, - const.ATTR_VALUE_INSTANCE: self.values.primary.instance, - const.ATTR_VALUE_ID: str(self.values.primary.value_id), - } - - if self.power_consumption is not None: - attrs[ATTR_POWER] = self.power_consumption - - return attrs - - def refresh_from_network(self): - """Refresh all dependent values from zwave network.""" - for value in self.values: - if value is not None: - self.node.refresh_value(value.value_id) - - def _compute_unique_id(self): - if ( - is_node_parsed(self.node) and self.values.primary.label != "Unknown" - ) or self.node.is_ready: - return compute_value_unique_id(self.node, self.values.primary) - return None diff --git a/homeassistant/components/zwave/binary_sensor.py b/homeassistant/components/zwave/binary_sensor.py deleted file mode 100644 index 26944b6661d..00000000000 --- a/homeassistant/components/zwave/binary_sensor.py +++ /dev/null @@ -1,106 +0,0 @@ -"""Support for Z-Wave binary sensors.""" -import datetime -import logging - -from homeassistant.components.binary_sensor import DOMAIN, BinarySensorEntity -from homeassistant.config_entries import ConfigEntry -from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers.dispatcher import async_dispatcher_connect -from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.event import track_point_in_time -import homeassistant.util.dt as dt_util - -from . import ZWaveDeviceEntity, workaround -from .const import COMMAND_CLASS_SENSOR_BINARY - -_LOGGER = logging.getLogger(__name__) - - -async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, -) -> None: - """Set up Z-Wave binary sensors from Config Entry.""" - - @callback - def async_add_binary_sensor(binary_sensor): - """Add Z-Wave binary sensor.""" - async_add_entities([binary_sensor]) - - async_dispatcher_connect(hass, "zwave_new_binary_sensor", async_add_binary_sensor) - - -def get_device(values, **kwargs): - """Create Z-Wave entity device.""" - device_mapping = workaround.get_device_mapping(values.primary) - if device_mapping == workaround.WORKAROUND_NO_OFF_EVENT: - return ZWaveTriggerSensor(values, "motion") - - if workaround.get_device_component_mapping(values.primary) == DOMAIN: - return ZWaveBinarySensor(values, None) - - if values.primary.command_class == COMMAND_CLASS_SENSOR_BINARY: - return ZWaveBinarySensor(values, None) - return None - - -class ZWaveBinarySensor(BinarySensorEntity, ZWaveDeviceEntity): - """Representation of a binary sensor within Z-Wave.""" - - def __init__(self, values, device_class): - """Initialize the sensor.""" - ZWaveDeviceEntity.__init__(self, values, DOMAIN) - self._sensor_type = device_class - self._state = self.values.primary.data - - def update_properties(self): - """Handle data changes for node values.""" - self._state = self.values.primary.data - - @property - def is_on(self): - """Return true if the binary sensor is on.""" - return self._state - - @property - def device_class(self): - """Return the class of this sensor, from BinarySensorDeviceClass.""" - return self._sensor_type - - -class ZWaveTriggerSensor(ZWaveBinarySensor): - """Representation of a stateless sensor within Z-Wave.""" - - def __init__(self, values, device_class): - """Initialize the sensor.""" - super().__init__(values, device_class) - # Set default off delay to 60 sec - self.re_arm_sec = 60 - self.invalidate_after = None - - def update_properties(self): - """Handle value changes for this entity's node.""" - self._state = self.values.primary.data - _LOGGER.debug("off_delay=%s", self.values.off_delay) - # Set re_arm_sec if off_delay is provided from the sensor - if self.values.off_delay: - _LOGGER.debug("off_delay.data=%s", self.values.off_delay.data) - self.re_arm_sec = self.values.off_delay.data * 8 - # only allow this value to be true for re_arm secs - if not self.hass: - return - - self.invalidate_after = dt_util.utcnow() + datetime.timedelta( - seconds=self.re_arm_sec - ) - track_point_in_time( - self.hass, self.async_update_ha_state, self.invalidate_after - ) - - @property - def is_on(self): - """Return true if movement has happened within the rearm time.""" - return self._state and ( - self.invalidate_after is None or self.invalidate_after > dt_util.utcnow() - ) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py deleted file mode 100644 index d56910e1b74..00000000000 --- a/homeassistant/components/zwave/climate.py +++ /dev/null @@ -1,619 +0,0 @@ -"""Support for Z-Wave climate devices.""" -# Because we do not compile openzwave on CI -from __future__ import annotations - -import logging - -from homeassistant.components.climate import ClimateEntity -from homeassistant.components.climate.const import ( - ATTR_TARGET_TEMP_HIGH, - ATTR_TARGET_TEMP_LOW, - CURRENT_HVAC_COOL, - CURRENT_HVAC_FAN, - CURRENT_HVAC_HEAT, - CURRENT_HVAC_IDLE, - CURRENT_HVAC_OFF, - DOMAIN, - HVAC_MODE_AUTO, - HVAC_MODE_COOL, - HVAC_MODE_DRY, - HVAC_MODE_FAN_ONLY, - HVAC_MODE_HEAT, - HVAC_MODE_HEAT_COOL, - HVAC_MODE_OFF, - PRESET_AWAY, - PRESET_BOOST, - PRESET_NONE, - SUPPORT_AUX_HEAT, - SUPPORT_FAN_MODE, - SUPPORT_PRESET_MODE, - SUPPORT_SWING_MODE, - SUPPORT_TARGET_TEMPERATURE, - SUPPORT_TARGET_TEMPERATURE_RANGE, -) -from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT -from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers.dispatcher import async_dispatcher_connect -from homeassistant.helpers.entity_platform import AddEntitiesCallback - -from . import ZWaveDeviceEntity, const - -_LOGGER = logging.getLogger(__name__) - -CONF_NAME = "name" -DEFAULT_NAME = "Z-Wave Climate" - -REMOTEC = 0x5254 -REMOTEC_ZXT_120 = 0x8377 -REMOTEC_ZXT_120_THERMOSTAT = (REMOTEC, REMOTEC_ZXT_120) -ATTR_OPERATING_STATE = "operating_state" -ATTR_FAN_STATE = "fan_state" -ATTR_FAN_ACTION = "fan_action" -AUX_HEAT_ZWAVE_MODE = "Aux Heat" - -# Device is in manufacturer specific mode (e.g. setting the valve manually) -PRESET_MANUFACTURER_SPECIFIC = "Manufacturer Specific" - -WORKAROUND_ZXT_120 = "zxt_120" - -DEVICE_MAPPINGS = {REMOTEC_ZXT_120_THERMOSTAT: WORKAROUND_ZXT_120} - -HVAC_STATE_MAPPINGS = { - "off": HVAC_MODE_OFF, - "heat": HVAC_MODE_HEAT, - "heat mode": HVAC_MODE_HEAT, - "heat (default)": HVAC_MODE_HEAT, - "furnace": HVAC_MODE_HEAT, - "fan only": HVAC_MODE_FAN_ONLY, - "dry air": HVAC_MODE_DRY, - "moist air": HVAC_MODE_DRY, - "cool": HVAC_MODE_COOL, - "heat_cool": HVAC_MODE_HEAT_COOL, - "auto": HVAC_MODE_HEAT_COOL, - "auto changeover": HVAC_MODE_HEAT_COOL, -} - -MODE_SETPOINT_MAPPINGS = { - "off": (), - "heat": ("setpoint_heating",), - "cool": ("setpoint_cooling",), - "auto": ("setpoint_heating", "setpoint_cooling"), - "aux heat": ("setpoint_heating",), - "furnace": ("setpoint_furnace",), - "dry air": ("setpoint_dry_air",), - "moist air": ("setpoint_moist_air",), - "auto changeover": ("setpoint_auto_changeover",), - "heat econ": ("setpoint_eco_heating",), - "cool econ": ("setpoint_eco_cooling",), - "away": ("setpoint_away_heating", "setpoint_away_cooling"), - "full power": ("setpoint_full_power",), - # aliases found in xml configs - "comfort": ("setpoint_heating",), - "heat mode": ("setpoint_heating",), - "heat (default)": ("setpoint_heating",), - "dry floor": ("setpoint_dry_air",), - "heat eco": ("setpoint_eco_heating",), - "energy saving": ("setpoint_eco_heating",), - "energy heat": ("setpoint_eco_heating",), - "vacation": ("setpoint_away_heating", "setpoint_away_cooling"), - # for tests - "heat_cool": ("setpoint_heating", "setpoint_cooling"), -} - -HVAC_CURRENT_MAPPINGS = { - "idle": CURRENT_HVAC_IDLE, - "heat": CURRENT_HVAC_HEAT, - "pending heat": CURRENT_HVAC_IDLE, - "heating": CURRENT_HVAC_HEAT, - "cool": CURRENT_HVAC_COOL, - "pending cool": CURRENT_HVAC_IDLE, - "cooling": CURRENT_HVAC_COOL, - "fan only": CURRENT_HVAC_FAN, - "vent / economiser": CURRENT_HVAC_FAN, - "off": CURRENT_HVAC_OFF, -} - -PRESET_MAPPINGS = { - "away": PRESET_AWAY, - "full power": PRESET_BOOST, - "manufacturer specific": PRESET_MANUFACTURER_SPECIFIC, -} - -DEFAULT_HVAC_MODES = [ - HVAC_MODE_HEAT_COOL, - HVAC_MODE_HEAT, - HVAC_MODE_COOL, - HVAC_MODE_FAN_ONLY, - HVAC_MODE_DRY, - HVAC_MODE_OFF, - HVAC_MODE_AUTO, -] - - -async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, -) -> None: - """Set up Z-Wave Climate device from Config Entry.""" - - @callback - def async_add_climate(climate): - """Add Z-Wave Climate Device.""" - async_add_entities([climate]) - - async_dispatcher_connect(hass, "zwave_new_climate", async_add_climate) - - -def get_device(hass, values, **kwargs): - """Create Z-Wave entity device.""" - temp_unit = hass.config.units.temperature_unit - if values.primary.command_class == const.COMMAND_CLASS_THERMOSTAT_SETPOINT: - return ZWaveClimateSingleSetpoint(values, temp_unit) - if values.primary.command_class == const.COMMAND_CLASS_THERMOSTAT_MODE: - return ZWaveClimateMultipleSetpoint(values, temp_unit) - return None - - -class ZWaveClimateBase(ZWaveDeviceEntity, ClimateEntity): - """Representation of a Z-Wave Climate device.""" - - def __init__(self, values, temp_unit): - """Initialize the Z-Wave climate device.""" - ZWaveDeviceEntity.__init__(self, values, DOMAIN) - self._target_temperature = None - self._target_temperature_range = (None, None) - self._current_temperature = None - self._hvac_action = None - self._hvac_list = None # [zwave_mode] - self._hvac_mapping = None # {ha_mode:zwave_mode} - self._hvac_mode = None # ha_mode - self._aux_heat = None - self._default_hvac_mode = None # ha_mode - self._preset_mapping = None # {ha_mode:zwave_mode} - self._preset_list = None # [zwave_mode] - self._preset_mode = None # ha_mode if exists, else zwave_mode - self._current_fan_mode = None - self._fan_modes = None - self._fan_action = None - self._current_swing_mode = None - self._swing_modes = None - self._unit = temp_unit - _LOGGER.debug("temp_unit is %s", self._unit) - self._zxt_120 = None - # Make sure that we have values for the key before converting to int - if self.node.manufacturer_id.strip() and self.node.product_id.strip(): - specific_sensor_key = ( - int(self.node.manufacturer_id, 16), - int(self.node.product_id, 16), - ) - if ( - specific_sensor_key in DEVICE_MAPPINGS - and DEVICE_MAPPINGS[specific_sensor_key] == WORKAROUND_ZXT_120 - ): - _LOGGER.debug("Remotec ZXT-120 Zwave Thermostat workaround") - self._zxt_120 = 1 - self.update_properties() - - def _mode(self) -> None: - """Return thermostat mode Z-Wave value.""" - raise NotImplementedError() - - def _current_mode_setpoints(self) -> tuple: - """Return a tuple of current setpoint Z-Wave value(s).""" - raise NotImplementedError() - - @property - def supported_features(self): - """Return the list of supported features.""" - support = SUPPORT_TARGET_TEMPERATURE - if self._hvac_list and HVAC_MODE_HEAT_COOL in self._hvac_list: - support |= SUPPORT_TARGET_TEMPERATURE_RANGE - if self._preset_list and PRESET_AWAY in self._preset_list: - support |= SUPPORT_TARGET_TEMPERATURE_RANGE - - if self.values.fan_mode: - support |= SUPPORT_FAN_MODE - if self._zxt_120 == 1 and self.values.zxt_120_swing_mode: - support |= SUPPORT_SWING_MODE - if self._aux_heat: - support |= SUPPORT_AUX_HEAT - if self._preset_list: - support |= SUPPORT_PRESET_MODE - return support - - def update_properties(self): - """Handle the data changes for node values.""" - # Operation Mode - self._update_operation_mode() - - # Current Temp - self._update_current_temp() - - # Fan Mode - self._update_fan_mode() - - # Swing mode - self._update_swing_mode() - - # Set point - self._update_target_temp() - - # Operating state - self._update_operating_state() - - # Fan operating state - self._update_fan_state() - - def _update_operation_mode(self): - """Update hvac and preset modes.""" - if self._mode(): - self._hvac_list = [] - self._hvac_mapping = {} - self._preset_list = [] - self._preset_mapping = {} - - if mode_list := self._mode().data_items: - for mode in mode_list: - ha_mode = HVAC_STATE_MAPPINGS.get(str(mode).lower()) - ha_preset = PRESET_MAPPINGS.get(str(mode).lower()) - if mode == AUX_HEAT_ZWAVE_MODE: - # Aux Heat should not be included in any mapping - self._aux_heat = True - elif ha_mode and ha_mode not in self._hvac_mapping: - self._hvac_mapping[ha_mode] = mode - self._hvac_list.append(ha_mode) - elif ha_preset and ha_preset not in self._preset_mapping: - self._preset_mapping[ha_preset] = mode - self._preset_list.append(ha_preset) - else: - # If nothing matches - self._preset_list.append(mode) - - # Default operation mode - for mode in DEFAULT_HVAC_MODES: - if mode in self._hvac_mapping: - self._default_hvac_mode = mode - break - - if self._preset_list: - # Presets are supported - self._preset_list.append(PRESET_NONE) - - current_mode = self._mode().data - _LOGGER.debug("current_mode=%s", current_mode) - _hvac_temp = next( - ( - key - for key, value in self._hvac_mapping.items() - if value == current_mode - ), - None, - ) - - if _hvac_temp is None: - # The current mode is not a hvac mode - if ( - "heat" in current_mode.lower() - and HVAC_MODE_HEAT in self._hvac_mapping - ): - # The current preset modes maps to HVAC_MODE_HEAT - _LOGGER.debug("Mapped to HEAT") - self._hvac_mode = HVAC_MODE_HEAT - elif ( - "cool" in current_mode.lower() - and HVAC_MODE_COOL in self._hvac_mapping - ): - # The current preset modes maps to HVAC_MODE_COOL - _LOGGER.debug("Mapped to COOL") - self._hvac_mode = HVAC_MODE_COOL - else: - # The current preset modes maps to self._default_hvac_mode - _LOGGER.debug("Mapped to DEFAULT") - self._hvac_mode = self._default_hvac_mode - self._preset_mode = next( - ( - key - for key, value in self._preset_mapping.items() - if value == current_mode - ), - current_mode, - ) - else: - # The current mode is a hvac mode - self._hvac_mode = _hvac_temp - self._preset_mode = PRESET_NONE - - _LOGGER.debug("self._hvac_mapping=%s", self._hvac_mapping) - _LOGGER.debug("self._hvac_list=%s", self._hvac_list) - _LOGGER.debug("self._hvac_mode=%s", self._hvac_mode) - _LOGGER.debug("self._default_hvac_mode=%s", self._default_hvac_mode) - _LOGGER.debug("self._hvac_action=%s", self._hvac_action) - _LOGGER.debug("self._aux_heat=%s", self._aux_heat) - _LOGGER.debug("self._preset_mapping=%s", self._preset_mapping) - _LOGGER.debug("self._preset_list=%s", self._preset_list) - _LOGGER.debug("self._preset_mode=%s", self._preset_mode) - - def _update_current_temp(self): - """Update current temperature.""" - if self.values.temperature: - self._current_temperature = self.values.temperature.data - device_unit = self.values.temperature.units - if device_unit is not None: - self._unit = device_unit - - def _update_fan_mode(self): - """Update fan mode.""" - if self.values.fan_mode: - self._current_fan_mode = self.values.fan_mode.data - if fan_modes := self.values.fan_mode.data_items: - self._fan_modes = list(fan_modes) - - _LOGGER.debug("self._fan_modes=%s", self._fan_modes) - _LOGGER.debug("self._current_fan_mode=%s", self._current_fan_mode) - - def _update_swing_mode(self): - """Update swing mode.""" - if self._zxt_120 == 1: - if self.values.zxt_120_swing_mode: - self._current_swing_mode = self.values.zxt_120_swing_mode.data - swing_modes = self.values.zxt_120_swing_mode.data_items - if swing_modes: - self._swing_modes = list(swing_modes) - _LOGGER.debug("self._swing_modes=%s", self._swing_modes) - _LOGGER.debug("self._current_swing_mode=%s", self._current_swing_mode) - - def _update_target_temp(self): - """Update target temperature.""" - current_setpoints = self._current_mode_setpoints() - self._target_temperature = None - self._target_temperature_range = (None, None) - if len(current_setpoints) == 1: - (setpoint,) = current_setpoints - if setpoint is not None: - self._target_temperature = round((float(setpoint.data)), 1) - elif len(current_setpoints) == 2: - (setpoint_low, setpoint_high) = current_setpoints - target_low, target_high = None, None - if setpoint_low is not None: - target_low = round((float(setpoint_low.data)), 1) - if setpoint_high is not None: - target_high = round((float(setpoint_high.data)), 1) - self._target_temperature_range = (target_low, target_high) - - def _update_operating_state(self): - """Update operating state.""" - if self.values.operating_state: - mode = self.values.operating_state.data - self._hvac_action = HVAC_CURRENT_MAPPINGS.get(str(mode).lower(), mode) - - def _update_fan_state(self): - """Update fan state.""" - if self.values.fan_action: - self._fan_action = self.values.fan_action.data - - @property - def fan_mode(self): - """Return the fan speed set.""" - return self._current_fan_mode - - @property - def fan_modes(self): - """Return a list of available fan modes.""" - return self._fan_modes - - @property - def swing_mode(self): - """Return the swing mode set.""" - return self._current_swing_mode - - @property - def swing_modes(self): - """Return a list of available swing modes.""" - return self._swing_modes - - @property - def temperature_unit(self): - """Return the unit of measurement.""" - if self._unit == "C": - return TEMP_CELSIUS - if self._unit == "F": - return TEMP_FAHRENHEIT - return self._unit - - @property - def current_temperature(self): - """Return the current temperature.""" - return self._current_temperature - - @property - def hvac_mode(self): - """Return hvac operation ie. heat, cool mode. - - Need to be one of HVAC_MODE_*. - """ - if self._mode(): - return self._hvac_mode - return self._default_hvac_mode - - @property - def hvac_modes(self): - """Return the list of available hvac operation modes. - - Need to be a subset of HVAC_MODES. - """ - if self._mode(): - return self._hvac_list - return [] - - @property - def hvac_action(self): - """Return the current running hvac operation if supported. - - Need to be one of CURRENT_HVAC_*. - """ - return self._hvac_action - - @property - def is_aux_heat(self): - """Return true if aux heater.""" - if not self._aux_heat: - return None - if self._mode().data == AUX_HEAT_ZWAVE_MODE: - return True - return False - - @property - def preset_mode(self): - """Return preset operation ie. eco, away. - - Need to be one of PRESET_*. - """ - if self._mode(): - return self._preset_mode - return PRESET_NONE - - @property - def preset_modes(self): - """Return the list of available preset operation modes. - - Need to be a subset of PRESET_MODES. - """ - if self._mode(): - return self._preset_list - return [] - - @property - def target_temperature(self): - """Return the temperature we try to reach.""" - return self._target_temperature - - @property - def target_temperature_low(self) -> float | None: - """Return the lowbound target temperature we try to reach.""" - return self._target_temperature_range[0] - - @property - def target_temperature_high(self) -> float | None: - """Return the highbound target temperature we try to reach.""" - return self._target_temperature_range[1] - - def set_temperature(self, **kwargs): - """Set new target temperature.""" - current_setpoints = self._current_mode_setpoints() - if len(current_setpoints) == 1: - (setpoint,) = current_setpoints - target_temp = kwargs.get(ATTR_TEMPERATURE) - if setpoint is not None and target_temp is not None: - _LOGGER.debug("Set temperature to %s", target_temp) - setpoint.data = target_temp - elif len(current_setpoints) == 2: - (setpoint_low, setpoint_high) = current_setpoints - target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW) - target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH) - if setpoint_low is not None and target_temp_low is not None: - _LOGGER.debug("Set low temperature to %s", target_temp_low) - setpoint_low.data = target_temp_low - if setpoint_high is not None and target_temp_high is not None: - _LOGGER.debug("Set high temperature to %s", target_temp_high) - setpoint_high.data = target_temp_high - - def set_fan_mode(self, fan_mode): - """Set new target fan mode.""" - _LOGGER.debug("Set fan mode to %s", fan_mode) - if not self.values.fan_mode: - return - self.values.fan_mode.data = fan_mode - - def set_hvac_mode(self, hvac_mode): - """Set new target hvac mode.""" - _LOGGER.debug("Set hvac_mode to %s", hvac_mode) - if not self._mode(): - return - operation_mode = self._hvac_mapping.get(hvac_mode) - _LOGGER.debug("Set operation_mode to %s", operation_mode) - self._mode().data = operation_mode - - def turn_aux_heat_on(self): - """Turn auxiliary heater on.""" - if not self._aux_heat: - return - operation_mode = AUX_HEAT_ZWAVE_MODE - _LOGGER.debug("Aux heat on. Set operation mode to %s", operation_mode) - self._mode().data = operation_mode - - def turn_aux_heat_off(self): - """Turn auxiliary heater off.""" - if not self._aux_heat: - return - if HVAC_MODE_HEAT in self._hvac_mapping: - operation_mode = self._hvac_mapping.get(HVAC_MODE_HEAT) - else: - operation_mode = self._hvac_mapping.get(HVAC_MODE_OFF) - _LOGGER.debug("Aux heat off. Set operation mode to %s", operation_mode) - self._mode().data = operation_mode - - def set_preset_mode(self, preset_mode): - """Set new target preset mode.""" - _LOGGER.debug("Set preset_mode to %s", preset_mode) - if not self._mode(): - return - if preset_mode == PRESET_NONE: - # Activate the current hvac mode - self._update_operation_mode() - operation_mode = self._hvac_mapping.get(self.hvac_mode) - _LOGGER.debug("Set operation_mode to %s", operation_mode) - self._mode().data = operation_mode - else: - operation_mode = self._preset_mapping.get(preset_mode, preset_mode) - _LOGGER.debug("Set operation_mode to %s", operation_mode) - self._mode().data = operation_mode - - def set_swing_mode(self, swing_mode): - """Set new target swing mode.""" - _LOGGER.debug("Set swing_mode to %s", swing_mode) - if self._zxt_120 == 1 and self.values.zxt_120_swing_mode: - self.values.zxt_120_swing_mode.data = swing_mode - - @property - def extra_state_attributes(self): - """Return the optional state attributes.""" - data = super().extra_state_attributes - if self._fan_action: - data[ATTR_FAN_ACTION] = self._fan_action - return data - - -class ZWaveClimateSingleSetpoint(ZWaveClimateBase): - """Representation of a single setpoint Z-Wave thermostat device.""" - - def __init__(self, values, temp_unit): - """Initialize the Z-Wave climate device.""" - ZWaveClimateBase.__init__(self, values, temp_unit) - - def _mode(self) -> None: - """Return thermostat mode Z-Wave value.""" - return self.values.mode - - def _current_mode_setpoints(self) -> tuple: - """Return a tuple of current setpoint Z-Wave value(s).""" - return (self.values.primary,) - - -class ZWaveClimateMultipleSetpoint(ZWaveClimateBase): - """Representation of a multiple setpoint Z-Wave thermostat device.""" - - def __init__(self, values, temp_unit): - """Initialize the Z-Wave climate device.""" - ZWaveClimateBase.__init__(self, values, temp_unit) - - def _mode(self) -> None: - """Return thermostat mode Z-Wave value.""" - return self.values.primary - - def _current_mode_setpoints(self) -> tuple: - """Return a tuple of current setpoint Z-Wave value(s).""" - current_mode = str(self.values.primary.data).lower() - setpoints_names = MODE_SETPOINT_MAPPINGS.get(current_mode, ()) - return tuple(getattr(self.values, name, None) for name in setpoints_names) diff --git a/homeassistant/components/zwave/config_flow.py b/homeassistant/components/zwave/config_flow.py deleted file mode 100644 index f29f2e6f6d0..00000000000 --- a/homeassistant/components/zwave/config_flow.py +++ /dev/null @@ -1,95 +0,0 @@ -"""Config flow to configure Z-Wave.""" -# pylint: disable=import-error -# pylint: disable=import-outside-toplevel -from collections import OrderedDict - -import voluptuous as vol - -from homeassistant import config_entries - -from .const import ( - CONF_NETWORK_KEY, - CONF_USB_STICK_PATH, - DEFAULT_CONF_USB_STICK_PATH, - DOMAIN, -) - - -class ZwaveFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): - """Handle a Z-Wave config flow.""" - - VERSION = 1 - - def __init__(self): - """Initialize the Z-Wave config flow.""" - self.usb_path = CONF_USB_STICK_PATH - - async def async_step_user(self, user_input=None): - """Handle a flow start.""" - if self._async_current_entries(): - return self.async_abort(reason="single_instance_allowed") - - errors = {} - - fields = OrderedDict() - fields[ - vol.Required(CONF_USB_STICK_PATH, default=DEFAULT_CONF_USB_STICK_PATH) - ] = str - fields[vol.Optional(CONF_NETWORK_KEY)] = str - - if user_input is not None: - # Check if USB path is valid - from openzwave.object import ZWaveException - from openzwave.option import ZWaveOption - - try: - from functools import partial - - option = await self.hass.async_add_executor_job( # noqa: F841 pylint: disable=unused-variable - partial( - ZWaveOption, - user_input[CONF_USB_STICK_PATH], - user_path=self.hass.config.config_dir, - ) - ) - except ZWaveException: - errors["base"] = "option_error" - return self.async_show_form( - step_id="user", data_schema=vol.Schema(fields), errors=errors - ) - - if user_input.get(CONF_NETWORK_KEY) is None: - # Generate a random key - from random import choice - - key = "" - for i in range(16): - key += "0x" - key += choice("1234567890ABCDEF") - key += choice("1234567890ABCDEF") - if i < 15: - key += ", " - user_input[CONF_NETWORK_KEY] = key - - return self.async_create_entry( - title="Z-Wave", - data={ - CONF_USB_STICK_PATH: user_input[CONF_USB_STICK_PATH], - CONF_NETWORK_KEY: user_input[CONF_NETWORK_KEY], - }, - ) - - return self.async_show_form(step_id="user", data_schema=vol.Schema(fields)) - - async def async_step_import(self, info): - """Import existing configuration from Z-Wave.""" - if self._async_current_entries(): - return self.async_abort(reason="already_setup") - - return self.async_create_entry( - title="Z-Wave (import from configuration.yaml)", - data={ - CONF_USB_STICK_PATH: info.get(CONF_USB_STICK_PATH), - CONF_NETWORK_KEY: info.get(CONF_NETWORK_KEY), - }, - ) diff --git a/homeassistant/components/zwave/const.py b/homeassistant/components/zwave/const.py deleted file mode 100644 index d11d308c490..00000000000 --- a/homeassistant/components/zwave/const.py +++ /dev/null @@ -1,395 +0,0 @@ -"""Z-Wave Constants.""" -DOMAIN = "zwave" - -ATTR_NODE_ID = "node_id" -ATTR_TARGET_NODE_ID = "target_node_id" -ATTR_ASSOCIATION = "association" -ATTR_INSTANCE = "instance" -ATTR_GROUP = "group" -ATTR_VALUE_ID = "value_id" -ATTR_MESSAGES = "messages" -ATTR_RETURN_ROUTES = "return_routes" -ATTR_SCENE_ID = "scene_id" -ATTR_SCENE_DATA = "scene_data" -ATTR_BASIC_LEVEL = "basic_level" -ATTR_CONFIG_PARAMETER = "parameter" -ATTR_CONFIG_SIZE = "size" -ATTR_CONFIG_VALUE = "value" -ATTR_POLL_INTENSITY = "poll_intensity" -ATTR_VALUE_INDEX = "value_index" -ATTR_VALUE_INSTANCE = "value_instance" -ATTR_UPDATE_IDS = "update_ids" -NETWORK_READY_WAIT_SECS = 300 -NODE_READY_WAIT_SECS = 30 - -CONF_AUTOHEAL = "autoheal" -CONF_DEBUG = "debug" -CONF_POLLING_INTERVAL = "polling_interval" -CONF_USB_STICK_PATH = "usb_path" -CONF_CONFIG_PATH = "config_path" -CONF_NETWORK_KEY = "network_key" - -DEFAULT_CONF_AUTOHEAL = False -DEFAULT_CONF_USB_STICK_PATH = "/zwaveusbstick" -DEFAULT_POLLING_INTERVAL = 60000 -DEFAULT_DEBUG = False - -DISCOVERY_DEVICE = "device" - -DATA_DEVICES = "zwave_devices" -DATA_NETWORK = "zwave_network" -DATA_ENTITY_VALUES = "zwave_entity_values" -DATA_ZWAVE_CONFIG = "zwave_config" - -SERVICE_CHANGE_ASSOCIATION = "change_association" -SERVICE_ADD_NODE = "add_node" -SERVICE_ADD_NODE_SECURE = "add_node_secure" -SERVICE_REMOVE_NODE = "remove_node" -SERVICE_CANCEL_COMMAND = "cancel_command" -SERVICE_HEAL_NETWORK = "heal_network" -SERVICE_HEAL_NODE = "heal_node" -SERVICE_SOFT_RESET = "soft_reset" -SERVICE_TEST_NODE = "test_node" -SERVICE_TEST_NETWORK = "test_network" -SERVICE_SET_CONFIG_PARAMETER = "set_config_parameter" -SERVICE_SET_NODE_VALUE = "set_node_value" -SERVICE_REFRESH_NODE_VALUE = "refresh_node_value" -SERVICE_PRINT_CONFIG_PARAMETER = "print_config_parameter" -SERVICE_PRINT_NODE = "print_node" -SERVICE_REMOVE_FAILED_NODE = "remove_failed_node" -SERVICE_REPLACE_FAILED_NODE = "replace_failed_node" -SERVICE_SET_POLL_INTENSITY = "set_poll_intensity" -SERVICE_SET_WAKEUP = "set_wakeup" -SERVICE_STOP_NETWORK = "stop_network" -SERVICE_START_NETWORK = "start_network" -SERVICE_RENAME_NODE = "rename_node" -SERVICE_RENAME_VALUE = "rename_value" -SERVICE_REFRESH_ENTITY = "refresh_entity" -SERVICE_REFRESH_NODE = "refresh_node" -SERVICE_RESET_NODE_METERS = "reset_node_meters" - -EVENT_SCENE_ACTIVATED = "zwave.scene_activated" -EVENT_NODE_EVENT = "zwave.node_event" -EVENT_NETWORK_READY = "zwave.network_ready" -EVENT_NETWORK_COMPLETE = "zwave.network_complete" -EVENT_NETWORK_COMPLETE_SOME_DEAD = "zwave.network_complete_some_dead" -EVENT_NETWORK_START = "zwave.network_start" -EVENT_NETWORK_STOP = "zwave.network_stop" - -COMMAND_CLASS_ALARM = 113 -COMMAND_CLASS_ANTITHEFT = 93 -COMMAND_CLASS_APPLICATION_CAPABILITY = 87 -COMMAND_CLASS_APPLICATION_STATUS = 34 -COMMAND_CLASS_ASSOCIATION = 133 -COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION = 155 -COMMAND_CLASS_ASSOCIATION_GRP_INFO = 89 -COMMAND_CLASS_BARRIER_OPERATOR = 102 -COMMAND_CLASS_BASIC = 32 -COMMAND_CLASS_BASIC_TARIFF_INFO = 54 -COMMAND_CLASS_BASIC_WINDOW_COVERING = 80 -COMMAND_CLASS_BATTERY = 128 -COMMAND_CLASS_CENTRAL_SCENE = 91 -COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE = 70 -COMMAND_CLASS_CLOCK = 129 -COMMAND_CLASS_CONFIGURATION = 112 -COMMAND_CLASS_CONTROLLER_REPLICATION = 33 -COMMAND_CLASS_CRC_16_ENCAP = 86 -COMMAND_CLASS_DCP_CONFIG = 58 -COMMAND_CLASS_DCP_MONITOR = 59 -COMMAND_CLASS_DEVICE_RESET_LOCALLY = 90 -COMMAND_CLASS_DOOR_LOCK = 98 -COMMAND_CLASS_DOOR_LOCK_LOGGING = 76 -COMMAND_CLASS_ENERGY_PRODUCTION = 144 -COMMAND_CLASS_ENTRY_CONTROL = 111 -COMMAND_CLASS_FIRMWARE_UPDATE_MD = 122 -COMMAND_CLASS_GEOGRAPHIC_LOCATION = 140 -COMMAND_CLASS_GROUPING_NAME = 123 -COMMAND_CLASS_HAIL = 130 -COMMAND_CLASS_HRV_CONTROL = 57 -COMMAND_CLASS_HRV_STATUS = 55 -COMMAND_CLASS_HUMIDITY_CONTROL_MODE = 109 -COMMAND_CLASS_HUMIDITY_CONTROL_OPERATING_STATE = 110 -COMMAND_CLASS_HUMIDITY_CONTROL_SETPOINT = 100 -COMMAND_CLASS_INDICATOR = 135 -COMMAND_CLASS_IP_ASSOCIATION = 92 -COMMAND_CLASS_IP_CONFIGURATION = 14 -COMMAND_CLASS_IRRIGATION = 107 -COMMAND_CLASS_LANGUAGE = 137 -COMMAND_CLASS_LOCK = 118 -COMMAND_CLASS_MAILBOX = 105 -COMMAND_CLASS_MANUFACTURER_PROPRIETARY = 145 -COMMAND_CLASS_MANUFACTURER_SPECIFIC = 114 -COMMAND_CLASS_MARK = 239 -COMMAND_CLASS_METER = 50 -COMMAND_CLASS_METER_PULSE = 53 -COMMAND_CLASS_METER_TBL_CONFIG = 60 -COMMAND_CLASS_METER_TBL_MONITOR = 61 -COMMAND_CLASS_METER_TBL_PUSH = 62 -COMMAND_CLASS_MTP_WINDOW_COVERING = 81 -COMMAND_CLASS_MULTI_CHANNEL = 96 -COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION = 142 -COMMAND_CLASS_MULTI_COMMAND = 143 -COMMAND_CLASS_NETWORK_MANAGEMENT_BASIC = 77 -COMMAND_CLASS_NETWORK_MANAGEMENT_INCLUSION = 52 -COMMAND_CLASS_NETWORK_MANAGEMENT_PRIMARY = 84 -COMMAND_CLASS_NETWORK_MANAGEMENT_PROXY = 82 -COMMAND_CLASS_NO_OPERATION = 0 -COMMAND_CLASS_NODE_NAMING = 119 -COMMAND_CLASS_NON_INTEROPERABLE = 240 -COMMAND_CLASS_NOTIFICATION = 113 -COMMAND_CLASS_POWERLEVEL = 115 -COMMAND_CLASS_PREPAYMENT = 63 -COMMAND_CLASS_PREPAYMENT_ENCAPSULATION = 65 -COMMAND_CLASS_PROPRIETARY = 136 -COMMAND_CLASS_PROTECTION = 117 -COMMAND_CLASS_RATE_TBL_CONFIG = 72 -COMMAND_CLASS_RATE_TBL_MONITOR = 73 -COMMAND_CLASS_REMOTE_ASSOCIATION_ACTIVATE = 124 -COMMAND_CLASS_REMOTE_ASSOCIATION = 125 -COMMAND_CLASS_SCENE_ACTIVATION = 43 -COMMAND_CLASS_SCENE_ACTUATOR_CONF = 44 -COMMAND_CLASS_SCENE_CONTROLLER_CONF = 45 -COMMAND_CLASS_SCHEDULE = 83 -COMMAND_CLASS_SCHEDULE_ENTRY_LOCK = 78 -COMMAND_CLASS_SCREEN_ATTRIBUTES = 147 -COMMAND_CLASS_SCREEN_MD = 146 -COMMAND_CLASS_SECURITY = 152 -COMMAND_CLASS_SECURITY_SCHEME0_MARK = 61696 -COMMAND_CLASS_SENSOR_ALARM = 156 -COMMAND_CLASS_SENSOR_BINARY = 48 -COMMAND_CLASS_SENSOR_CONFIGURATION = 158 -COMMAND_CLASS_SENSOR_MULTILEVEL = 49 -COMMAND_CLASS_SILENCE_ALARM = 157 -COMMAND_CLASS_SIMPLE_AV_CONTROL = 148 -COMMAND_CLASS_SUPERVISION = 108 -COMMAND_CLASS_SWITCH_ALL = 39 -COMMAND_CLASS_SWITCH_BINARY = 37 -COMMAND_CLASS_SWITCH_COLOR = 51 -COMMAND_CLASS_SWITCH_MULTILEVEL = 38 -COMMAND_CLASS_SWITCH_TOGGLE_BINARY = 40 -COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL = 41 -COMMAND_CLASS_TARIFF_TBL_CONFIG = 74 -COMMAND_CLASS_TARIFF_TBL_MONITOR = 75 -COMMAND_CLASS_THERMOSTAT_FAN_MODE = 68 -COMMAND_CLASS_THERMOSTAT_FAN_ACTION = 69 -COMMAND_CLASS_THERMOSTAT_MODE = 64 -COMMAND_CLASS_THERMOSTAT_OPERATING_STATE = 66 -COMMAND_CLASS_THERMOSTAT_SETBACK = 71 -COMMAND_CLASS_THERMOSTAT_SETPOINT = 67 -COMMAND_CLASS_TIME = 138 -COMMAND_CLASS_TIME_PARAMETERS = 139 -COMMAND_CLASS_TRANSPORT_SERVICE = 85 -COMMAND_CLASS_USER_CODE = 99 -COMMAND_CLASS_VERSION = 134 -COMMAND_CLASS_WAKE_UP = 132 -COMMAND_CLASS_ZIP = 35 -COMMAND_CLASS_ZIP_NAMING = 104 -COMMAND_CLASS_ZIP_ND = 88 -COMMAND_CLASS_ZIP_6LOWPAN = 79 -COMMAND_CLASS_ZIP_GATEWAY = 95 -COMMAND_CLASS_ZIP_PORTAL = 97 -COMMAND_CLASS_ZWAVEPLUS_INFO = 94 -COMMAND_CLASS_WHATEVER = None # Match ALL -COMMAND_CLASS_WINDOW_COVERING = 106 - -GENERIC_TYPE_WHATEVER = None # Match ALL -SPECIFIC_TYPE_WHATEVER = None # Match ALL -SPECIFIC_TYPE_NOT_USED = 0 # Available in all Generic types - -GENERIC_TYPE_AV_CONTROL_POINT = 3 -SPECIFIC_TYPE_DOORBELL = 18 -SPECIFIC_TYPE_SATELLITE_RECEIVER = 4 -SPECIFIC_TYPE_SATELLITE_RECEIVER_V2 = 17 - -GENERIC_TYPE_DISPLAY = 4 -SPECIFIC_TYPE_SIMPLE_DISPLAY = 1 - -GENERIC_TYPE_ENTRY_CONTROL = 64 -SPECIFIC_TYPE_DOOR_LOCK = 1 -SPECIFIC_TYPE_ADVANCED_DOOR_LOCK = 2 -SPECIFIC_TYPE_SECURE_KEYPAD_DOOR_LOCK = 3 -SPECIFIC_TYPE_SECURE_KEYPAD_DOOR_LOCK_DEADBOLT = 4 -SPECIFIC_TYPE_SECURE_DOOR = 5 -SPECIFIC_TYPE_SECURE_GATE = 6 -SPECIFIC_TYPE_SECURE_BARRIER_ADDON = 7 -SPECIFIC_TYPE_SECURE_BARRIER_OPEN_ONLY = 8 -SPECIFIC_TYPE_SECURE_BARRIER_CLOSE_ONLY = 9 -SPECIFIC_TYPE_SECURE_LOCKBOX = 10 -SPECIFIC_TYPE_SECURE_KEYPAD = 11 - -GENERIC_TYPE_GENERIC_CONTROLLER = 1 -SPECIFIC_TYPE_PORTABLE_CONTROLLER = 1 -SPECIFIC_TYPE_PORTABLE_SCENE_CONTROLLER = 2 -SPECIFIC_TYPE_PORTABLE_INSTALLER_TOOL = 3 -SPECIFIC_TYPE_REMOTE_CONTROL_AV = 4 -SPECIFIC_TYPE_REMOTE_CONTROL_SIMPLE = 6 - -GENERIC_TYPE_METER = 49 -SPECIFIC_TYPE_SIMPLE_METER = 1 -SPECIFIC_TYPE_ADV_ENERGY_CONTROL = 2 -SPECIFIC_TYPE_WHOLE_HOME_METER_SIMPLE = 3 - -GENERIC_TYPE_METER_PULSE = 48 - -GENERIC_TYPE_NON_INTEROPERABLE = 255 - -GENERIC_TYPE_REPEATER_SLAVE = 15 -SPECIFIC_TYPE_REPEATER_SLAVE = 1 -SPECIFIC_TYPE_VIRTUAL_NODE = 2 - -GENERIC_TYPE_SECURITY_PANEL = 23 -SPECIFIC_TYPE_ZONED_SECURITY_PANEL = 1 - -GENERIC_TYPE_SEMI_INTEROPERABLE = 80 -SPECIFIC_TYPE_ENERGY_PRODUCTION = 1 - -GENERIC_TYPE_SENSOR_ALARM = 161 -SPECIFIC_TYPE_ADV_ZENSOR_NET_ALARM_SENSOR = 5 -SPECIFIC_TYPE_ADV_ZENSOR_NET_SMOKE_SENSOR = 10 -SPECIFIC_TYPE_BASIC_ROUTING_ALARM_SENSOR = 1 -SPECIFIC_TYPE_BASIC_ROUTING_SMOKE_SENSOR = 6 -SPECIFIC_TYPE_BASIC_ZENSOR_NET_ALARM_SENSOR = 3 -SPECIFIC_TYPE_BASIC_ZENSOR_NET_SMOKE_SENSOR = 8 -SPECIFIC_TYPE_ROUTING_ALARM_SENSOR = 2 -SPECIFIC_TYPE_ROUTING_SMOKE_SENSOR = 7 -SPECIFIC_TYPE_ZENSOR_NET_ALARM_SENSOR = 4 -SPECIFIC_TYPE_ZENSOR_NET_SMOKE_SENSOR = 9 -SPECIFIC_TYPE_ALARM_SENSOR = 11 - -GENERIC_TYPE_SENSOR_BINARY = 32 -SPECIFIC_TYPE_ROUTING_SENSOR_BINARY = 1 - -GENERIC_TYPE_SENSOR_MULTILEVEL = 33 -SPECIFIC_TYPE_ROUTING_SENSOR_MULTILEVEL = 1 -SPECIFIC_TYPE_CHIMNEY_FAN = 2 - -GENERIC_TYPE_STATIC_CONTROLLER = 2 -SPECIFIC_TYPE_PC_CONTROLLER = 1 -SPECIFIC_TYPE_SCENE_CONTROLLER = 2 -SPECIFIC_TYPE_STATIC_INSTALLER_TOOL = 3 -SPECIFIC_TYPE_SET_TOP_BOX = 4 -SPECIFIC_TYPE_SUB_SYSTEM_CONTROLLER = 5 -SPECIFIC_TYPE_TV = 6 -SPECIFIC_TYPE_GATEWAY = 7 - -GENERIC_TYPE_SWITCH_BINARY = 16 -SPECIFIC_TYPE_POWER_SWITCH_BINARY = 1 -SPECIFIC_TYPE_SCENE_SWITCH_BINARY = 3 -SPECIFIC_TYPE_POWER_STRIP = 4 -SPECIFIC_TYPE_SIREN = 5 -SPECIFIC_TYPE_VALVE_OPEN_CLOSE = 6 -SPECIFIC_TYPE_COLOR_TUNABLE_BINARY = 2 -SPECIFIC_TYPE_IRRIGATION_CONTROLLER = 7 - -GENERIC_TYPE_SWITCH_MULTILEVEL = 17 -SPECIFIC_TYPE_CLASS_A_MOTOR_CONTROL = 5 -SPECIFIC_TYPE_CLASS_B_MOTOR_CONTROL = 6 -SPECIFIC_TYPE_CLASS_C_MOTOR_CONTROL = 7 -SPECIFIC_TYPE_MOTOR_MULTIPOSITION = 3 -SPECIFIC_TYPE_POWER_SWITCH_MULTILEVEL = 1 -SPECIFIC_TYPE_SCENE_SWITCH_MULTILEVEL = 4 -SPECIFIC_TYPE_FAN_SWITCH = 8 -SPECIFIC_TYPE_COLOR_TUNABLE_MULTILEVEL = 2 - -GENERIC_TYPE_SWITCH_REMOTE = 18 -SPECIFIC_TYPE_REMOTE_BINARY = 1 -SPECIFIC_TYPE_REMOTE_MULTILEVEL = 2 -SPECIFIC_TYPE_REMOTE_TOGGLE_BINARY = 3 -SPECIFIC_TYPE_REMOTE_TOGGLE_MULTILEVEL = 4 - -GENERIC_TYPE_SWITCH_TOGGLE = 19 -SPECIFIC_TYPE_SWITCH_TOGGLE_BINARY = 1 -SPECIFIC_TYPE_SWITCH_TOGGLE_MULTILEVEL = 2 - -GENERIC_TYPE_THERMOSTAT = 8 -SPECIFIC_TYPE_SETBACK_SCHEDULE_THERMOSTAT = 3 -SPECIFIC_TYPE_SETBACK_THERMOSTAT = 5 -SPECIFIC_TYPE_SETPOINT_THERMOSTAT = 4 -SPECIFIC_TYPE_THERMOSTAT_GENERAL = 2 -SPECIFIC_TYPE_THERMOSTAT_GENERAL_V2 = 6 -SPECIFIC_TYPE_THERMOSTAT_HEATING = 1 - -GENERIC_TYPE_VENTILATION = 22 -SPECIFIC_TYPE_RESIDENTIAL_HRV = 1 - -GENERIC_TYPE_WINDOWS_COVERING = 9 -SPECIFIC_TYPE_SIMPLE_WINDOW_COVERING = 1 - -GENERIC_TYPE_ZIP_NODE = 21 -SPECIFIC_TYPE_ZIP_ADV_NODE = 2 -SPECIFIC_TYPE_ZIP_TUN_NODE = 1 - -GENERIC_TYPE_WALL_CONTROLLER = 24 -SPECIFIC_TYPE_BASIC_WALL_CONTROLLER = 1 - -GENERIC_TYPE_NETWORK_EXTENDER = 5 -SPECIFIC_TYPE_SECURE_EXTENDER = 1 - -GENERIC_TYPE_APPLIANCE = 6 -SPECIFIC_TYPE_GENERAL_APPLIANCE = 1 -SPECIFIC_TYPE_KITCHEN_APPLIANCE = 2 -SPECIFIC_TYPE_LAUNDRY_APPLIANCE = 3 - -GENERIC_TYPE_SENSOR_NOTIFICATION = 7 -SPECIFIC_TYPE_NOTIFICATION_SENSOR = 1 - -GENRE_WHATEVER = None -GENRE_USER = "User" -GENRE_SYSTEM = "System" - -TYPE_WHATEVER = None -TYPE_BYTE = "Byte" -TYPE_BOOL = "Bool" -TYPE_DECIMAL = "Decimal" -TYPE_INT = "Int" -TYPE_LIST = "List" -TYPE_STRING = "String" -TYPE_BUTTON = "Button" - -DISC_COMMAND_CLASS = "command_class" -DISC_COMPONENT = "component" -DISC_GENERIC_DEVICE_CLASS = "generic_device_class" -DISC_GENRE = "genre" -DISC_INDEX = "index" -DISC_INSTANCE = "instance" -DISC_NODE_ID = "node_id" -DISC_OPTIONAL = "optional" -DISC_PRIMARY = "primary" -DISC_SCHEMAS = "schemas" -DISC_SPECIFIC_DEVICE_CLASS = "specific_device_class" -DISC_TYPE = "type" -DISC_VALUES = "values" - -# https://github.com/OpenZWave/open-zwave/blob/67f180eb565f0054f517ff395c71ecd706f6a837/cpp/src/command_classes/Alarm.cpp#L49 -# See also: -# https://github.com/OpenZWave/open-zwave/blob/67f180eb565f0054f517ff395c71ecd706f6a837/cpp/src/command_classes/Alarm.cpp#L275 -# https://github.com/OpenZWave/open-zwave/blob/67f180eb565f0054f517ff395c71ecd706f6a837/cpp/src/command_classes/Alarm.cpp#L278 -INDEX_ALARM_TYPE = 0 -INDEX_ALARM_LEVEL = 1 -INDEX_ALARM_ACCESS_CONTROL = 9 - -# https://github.com/OpenZWave/open-zwave/blob/de1c0e60edf1d1bee81f1ae54b1f58e66c6fd8ed/cpp/src/command_classes/BarrierOperator.cpp#L69 -INDEX_BARRIER_OPERATOR_LABEL = 1 - -# https://github.com/OpenZWave/open-zwave/blob/67f180eb565f0054f517ff395c71ecd706f6a837/cpp/src/command_classes/DoorLock.cpp#L77 -INDEX_DOOR_LOCK_LOCK = 0 - -# https://github.com/OpenZWave/open-zwave/blob/67f180eb565f0054f517ff395c71ecd706f6a837/cpp/src/command_classes/Meter.cpp#L114 -# See also: -# https://github.com/OpenZWave/open-zwave/blob/67f180eb565f0054f517ff395c71ecd706f6a837/cpp/src/command_classes/Meter.cpp#L279 -INDEX_METER_POWER = 8 -INDEX_METER_RESET = 33 - -# https://github.com/OpenZWave/open-zwave/blob/67f180eb565f0054f517ff395c71ecd706f6a837/cpp/src/command_classes/SensorMultilevel.cpp#L50 -INDEX_SENSOR_MULTILEVEL_TEMPERATURE = 1 -INDEX_SENSOR_MULTILEVEL_POWER = 4 - -# https://github.com/OpenZWave/open-zwave/blob/67f180eb565f0054f517ff395c71ecd706f6a837/cpp/src/command_classes/Color.cpp#L109 -INDEX_SWITCH_COLOR_COLOR = 0 -INDEX_SWITCH_COLOR_CHANNELS = 2 - -# https://github.com/OpenZWave/open-zwave/blob/67f180eb565f0054f517ff395c71ecd706f6a837/cpp/src/command_classes/SwitchMultilevel.cpp#L54 -INDEX_SWITCH_MULTILEVEL_LEVEL = 0 -INDEX_SWITCH_MULTILEVEL_BRIGHT = 1 -INDEX_SWITCH_MULTILEVEL_DIM = 2 -INDEX_SWITCH_MULTILEVEL_DURATION = 5 diff --git a/homeassistant/components/zwave/cover.py b/homeassistant/components/zwave/cover.py deleted file mode 100644 index 2a49a34554b..00000000000 --- a/homeassistant/components/zwave/cover.py +++ /dev/null @@ -1,216 +0,0 @@ -"""Support for Z-Wave covers.""" -import logging - -from homeassistant.components.cover import ( - ATTR_POSITION, - DOMAIN, - SUPPORT_CLOSE, - SUPPORT_OPEN, - CoverDeviceClass, - CoverEntity, -) -from homeassistant.config_entries import ConfigEntry -from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers.dispatcher import async_dispatcher_connect -from homeassistant.helpers.entity_platform import AddEntitiesCallback - -from . import ( - CONF_INVERT_OPENCLOSE_BUTTONS, - CONF_INVERT_PERCENT, - ZWaveDeviceEntity, - workaround, -) -from .const import ( - COMMAND_CLASS_BARRIER_OPERATOR, - COMMAND_CLASS_SWITCH_BINARY, - COMMAND_CLASS_SWITCH_MULTILEVEL, - DATA_NETWORK, -) - -_LOGGER = logging.getLogger(__name__) - -SUPPORT_GARAGE = SUPPORT_OPEN | SUPPORT_CLOSE - - -async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, -) -> None: - """Set up Z-Wave Cover from Config Entry.""" - - @callback - def async_add_cover(cover): - """Add Z-Wave Cover.""" - async_add_entities([cover]) - - async_dispatcher_connect(hass, "zwave_new_cover", async_add_cover) - - -def get_device(hass, values, node_config, **kwargs): - """Create Z-Wave entity device.""" - invert_buttons = node_config.get(CONF_INVERT_OPENCLOSE_BUTTONS) - invert_percent = node_config.get(CONF_INVERT_PERCENT) - if ( - values.primary.command_class == COMMAND_CLASS_SWITCH_MULTILEVEL - and values.primary.index == 0 - ): - return ZwaveRollershutter(hass, values, invert_buttons, invert_percent) - if values.primary.command_class == COMMAND_CLASS_SWITCH_BINARY: - return ZwaveGarageDoorSwitch(values) - if values.primary.command_class == COMMAND_CLASS_BARRIER_OPERATOR: - return ZwaveGarageDoorBarrier(values) - return None - - -class ZwaveRollershutter(ZWaveDeviceEntity, CoverEntity): - """Representation of an Z-Wave cover.""" - - def __init__(self, hass, values, invert_buttons, invert_percent): - """Initialize the Z-Wave rollershutter.""" - ZWaveDeviceEntity.__init__(self, values, DOMAIN) - self._network = hass.data[DATA_NETWORK] - self._open_id = None - self._close_id = None - self._current_position = None - self._invert_buttons = invert_buttons - self._invert_percent = invert_percent - - self._workaround = workaround.get_device_mapping(values.primary) - if self._workaround: - _LOGGER.debug("Using workaround %s", self._workaround) - self.update_properties() - - def update_properties(self): - """Handle data changes for node values.""" - # Position value - self._current_position = self.values.primary.data - - if ( - self.values.open - and self.values.close - and self._open_id is None - and self._close_id is None - ): - if self._invert_buttons: - self._open_id = self.values.close.value_id - self._close_id = self.values.open.value_id - else: - self._open_id = self.values.open.value_id - self._close_id = self.values.close.value_id - - @property - def is_closed(self): - """Return if the cover is closed.""" - if self.current_cover_position is None: - return None - if self.current_cover_position > 0: - return False - return True - - @property - def current_cover_position(self): - """Return the current position of Zwave roller shutter.""" - if self._workaround == workaround.WORKAROUND_NO_POSITION: - return None - - if self._current_position is not None: - if self._current_position <= 5: - return 100 if self._invert_percent else 0 - if self._current_position >= 95: - return 0 if self._invert_percent else 100 - return ( - 100 - self._current_position - if self._invert_percent - else self._current_position - ) - - def open_cover(self, **kwargs): - """Move the roller shutter up.""" - self._network.manager.pressButton(self._open_id) - - def close_cover(self, **kwargs): - """Move the roller shutter down.""" - self._network.manager.pressButton(self._close_id) - - def set_cover_position(self, **kwargs): - """Move the roller shutter to a specific position.""" - self.node.set_dimmer( - self.values.primary.value_id, - (100 - kwargs.get(ATTR_POSITION)) - if self._invert_percent - else kwargs.get(ATTR_POSITION), - ) - - def stop_cover(self, **kwargs): - """Stop the roller shutter.""" - self._network.manager.releaseButton(self._open_id) - - -class ZwaveGarageDoorBase(ZWaveDeviceEntity, CoverEntity): - """Base class for a Zwave garage door device.""" - - def __init__(self, values): - """Initialize the zwave garage door.""" - ZWaveDeviceEntity.__init__(self, values, DOMAIN) - self._state = None - self.update_properties() - - def update_properties(self): - """Handle data changes for node values.""" - self._state = self.values.primary.data - _LOGGER.debug("self._state=%s", self._state) - - @property - def device_class(self): - """Return the class of this device, from CoverDeviceClass.""" - return CoverDeviceClass.GARAGE - - @property - def supported_features(self): - """Flag supported features.""" - return SUPPORT_GARAGE - - -class ZwaveGarageDoorSwitch(ZwaveGarageDoorBase): - """Representation of a switch based Zwave garage door device.""" - - @property - def is_closed(self): - """Return the current position of Zwave garage door.""" - return not self._state - - def close_cover(self, **kwargs): - """Close the garage door.""" - self.values.primary.data = False - - def open_cover(self, **kwargs): - """Open the garage door.""" - self.values.primary.data = True - - -class ZwaveGarageDoorBarrier(ZwaveGarageDoorBase): - """Representation of a barrier operator Zwave garage door device.""" - - @property - def is_opening(self): - """Return true if cover is in an opening state.""" - return self._state == "Opening" - - @property - def is_closing(self): - """Return true if cover is in a closing state.""" - return self._state == "Closing" - - @property - def is_closed(self): - """Return the current position of Zwave garage door.""" - return self._state == "Closed" - - def close_cover(self, **kwargs): - """Close the garage door.""" - self.values.primary.data = "Closed" - - def open_cover(self, **kwargs): - """Open the garage door.""" - self.values.primary.data = "Opened" diff --git a/homeassistant/components/zwave/discovery_schemas.py b/homeassistant/components/zwave/discovery_schemas.py deleted file mode 100644 index f8674a48a32..00000000000 --- a/homeassistant/components/zwave/discovery_schemas.py +++ /dev/null @@ -1,416 +0,0 @@ -"""Z-Wave discovery schemas.""" -from . import const - -DEFAULT_VALUES_SCHEMA = { - "power": { - const.DISC_SCHEMAS: [ - { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SENSOR_MULTILEVEL], - const.DISC_INDEX: [const.INDEX_SENSOR_MULTILEVEL_POWER], - }, - { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_METER], - const.DISC_INDEX: [const.INDEX_METER_POWER], - }, - ], - const.DISC_OPTIONAL: True, - } -} - -DISCOVERY_SCHEMAS = [ - { - const.DISC_COMPONENT: "binary_sensor", - const.DISC_GENERIC_DEVICE_CLASS: [ - const.GENERIC_TYPE_ENTRY_CONTROL, - const.GENERIC_TYPE_SENSOR_ALARM, - const.GENERIC_TYPE_SENSOR_BINARY, - const.GENERIC_TYPE_SWITCH_BINARY, - const.GENERIC_TYPE_METER, - const.GENERIC_TYPE_SENSOR_MULTILEVEL, - const.GENERIC_TYPE_SWITCH_MULTILEVEL, - const.GENERIC_TYPE_SENSOR_NOTIFICATION, - const.GENERIC_TYPE_THERMOSTAT, - ], - const.DISC_VALUES: dict( - DEFAULT_VALUES_SCHEMA, - **{ - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SENSOR_BINARY], - const.DISC_TYPE: const.TYPE_BOOL, - const.DISC_GENRE: const.GENRE_USER, - }, - "off_delay": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_CONFIGURATION], - const.DISC_INDEX: [9], - const.DISC_OPTIONAL: True, - }, - }, - ), - }, - { - const.DISC_COMPONENT: "climate", # thermostat without COMMAND_CLASS_THERMOSTAT_MODE - const.DISC_GENERIC_DEVICE_CLASS: [ - const.GENERIC_TYPE_THERMOSTAT, - const.GENERIC_TYPE_SENSOR_MULTILEVEL, - ], - const.DISC_SPECIFIC_DEVICE_CLASS: [ - const.SPECIFIC_TYPE_THERMOSTAT_HEATING, - const.SPECIFIC_TYPE_SETPOINT_THERMOSTAT, - const.SPECIFIC_TYPE_NOT_USED, - ], - const.DISC_VALUES: dict( - DEFAULT_VALUES_SCHEMA, - **{ - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT] - }, - "temperature": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SENSOR_MULTILEVEL], - const.DISC_INDEX: [const.INDEX_SENSOR_MULTILEVEL_TEMPERATURE], - const.DISC_OPTIONAL: True, - }, - "fan_mode": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_FAN_MODE], - const.DISC_OPTIONAL: True, - }, - "operating_state": { - const.DISC_COMMAND_CLASS: [ - const.COMMAND_CLASS_THERMOSTAT_OPERATING_STATE - ], - const.DISC_OPTIONAL: True, - }, - "fan_action": { - const.DISC_COMMAND_CLASS: [ - const.COMMAND_CLASS_THERMOSTAT_FAN_ACTION - ], - const.DISC_OPTIONAL: True, - }, - "mode": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_MODE], - const.DISC_OPTIONAL: True, - }, - }, - ), - }, - { - const.DISC_COMPONENT: "climate", # thermostat with COMMAND_CLASS_THERMOSTAT_MODE - const.DISC_GENERIC_DEVICE_CLASS: [ - const.GENERIC_TYPE_THERMOSTAT, - const.GENERIC_TYPE_SENSOR_MULTILEVEL, - ], - const.DISC_SPECIFIC_DEVICE_CLASS: [ - const.SPECIFIC_TYPE_THERMOSTAT_GENERAL, - const.SPECIFIC_TYPE_THERMOSTAT_GENERAL_V2, - const.SPECIFIC_TYPE_SETBACK_THERMOSTAT, - ], - const.DISC_VALUES: dict( - DEFAULT_VALUES_SCHEMA, - **{ - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_MODE] - }, - "setpoint_heating": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT], - const.DISC_INDEX: [1], - const.DISC_OPTIONAL: True, - }, - "setpoint_cooling": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT], - const.DISC_INDEX: [2], - const.DISC_OPTIONAL: True, - }, - "setpoint_furnace": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT], - const.DISC_INDEX: [7], - const.DISC_OPTIONAL: True, - }, - "setpoint_dry_air": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT], - const.DISC_INDEX: [8], - const.DISC_OPTIONAL: True, - }, - "setpoint_moist_air": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT], - const.DISC_INDEX: [9], - const.DISC_OPTIONAL: True, - }, - "setpoint_auto_changeover": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT], - const.DISC_INDEX: [10], - const.DISC_OPTIONAL: True, - }, - "setpoint_eco_heating": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT], - const.DISC_INDEX: [11], - const.DISC_OPTIONAL: True, - }, - "setpoint_eco_cooling": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT], - const.DISC_INDEX: [12], - const.DISC_OPTIONAL: True, - }, - "setpoint_away_heating": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT], - const.DISC_INDEX: [13], - const.DISC_OPTIONAL: True, - }, - "setpoint_away_cooling": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT], - const.DISC_INDEX: [14], - const.DISC_OPTIONAL: True, - }, - "setpoint_full_power": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT], - const.DISC_INDEX: [15], - const.DISC_OPTIONAL: True, - }, - "temperature": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SENSOR_MULTILEVEL], - const.DISC_INDEX: [const.INDEX_SENSOR_MULTILEVEL_TEMPERATURE], - const.DISC_OPTIONAL: True, - }, - "fan_mode": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_FAN_MODE], - const.DISC_OPTIONAL: True, - }, - "operating_state": { - const.DISC_COMMAND_CLASS: [ - const.COMMAND_CLASS_THERMOSTAT_OPERATING_STATE - ], - const.DISC_OPTIONAL: True, - }, - "fan_action": { - const.DISC_COMMAND_CLASS: [ - const.COMMAND_CLASS_THERMOSTAT_FAN_ACTION - ], - const.DISC_OPTIONAL: True, - }, - "zxt_120_swing_mode": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_CONFIGURATION], - const.DISC_INDEX: [33], - const.DISC_OPTIONAL: True, - }, - }, - ), - }, - { - const.DISC_COMPONENT: "cover", # Rollershutter - const.DISC_GENERIC_DEVICE_CLASS: [ - const.GENERIC_TYPE_SWITCH_MULTILEVEL, - const.GENERIC_TYPE_ENTRY_CONTROL, - ], - const.DISC_SPECIFIC_DEVICE_CLASS: [ - const.SPECIFIC_TYPE_CLASS_A_MOTOR_CONTROL, - const.SPECIFIC_TYPE_CLASS_B_MOTOR_CONTROL, - const.SPECIFIC_TYPE_CLASS_C_MOTOR_CONTROL, - const.SPECIFIC_TYPE_MOTOR_MULTIPOSITION, - const.SPECIFIC_TYPE_SECURE_BARRIER_ADDON, - const.SPECIFIC_TYPE_SECURE_DOOR, - ], - const.DISC_VALUES: dict( - DEFAULT_VALUES_SCHEMA, - **{ - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_MULTILEVEL], - const.DISC_GENRE: const.GENRE_USER, - }, - "open": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_MULTILEVEL], - const.DISC_INDEX: [const.INDEX_SWITCH_MULTILEVEL_BRIGHT], - const.DISC_OPTIONAL: True, - }, - "close": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_MULTILEVEL], - const.DISC_INDEX: [const.INDEX_SWITCH_MULTILEVEL_DIM], - const.DISC_OPTIONAL: True, - }, - }, - ), - }, - { - const.DISC_COMPONENT: "cover", # Garage Door Switch - const.DISC_GENERIC_DEVICE_CLASS: [ - const.GENERIC_TYPE_SWITCH_MULTILEVEL, - const.GENERIC_TYPE_ENTRY_CONTROL, - ], - const.DISC_SPECIFIC_DEVICE_CLASS: [ - const.SPECIFIC_TYPE_CLASS_A_MOTOR_CONTROL, - const.SPECIFIC_TYPE_CLASS_B_MOTOR_CONTROL, - const.SPECIFIC_TYPE_CLASS_C_MOTOR_CONTROL, - const.SPECIFIC_TYPE_MOTOR_MULTIPOSITION, - const.SPECIFIC_TYPE_SECURE_BARRIER_ADDON, - const.SPECIFIC_TYPE_SECURE_DOOR, - ], - const.DISC_VALUES: dict( - DEFAULT_VALUES_SCHEMA, - **{ - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_BINARY], - const.DISC_GENRE: const.GENRE_USER, - } - }, - ), - }, - { - const.DISC_COMPONENT: "cover", # Garage Door Barrier - const.DISC_GENERIC_DEVICE_CLASS: [ - const.GENERIC_TYPE_SWITCH_MULTILEVEL, - const.GENERIC_TYPE_ENTRY_CONTROL, - ], - const.DISC_SPECIFIC_DEVICE_CLASS: [ - const.SPECIFIC_TYPE_CLASS_A_MOTOR_CONTROL, - const.SPECIFIC_TYPE_CLASS_B_MOTOR_CONTROL, - const.SPECIFIC_TYPE_CLASS_C_MOTOR_CONTROL, - const.SPECIFIC_TYPE_MOTOR_MULTIPOSITION, - const.SPECIFIC_TYPE_SECURE_BARRIER_ADDON, - const.SPECIFIC_TYPE_SECURE_DOOR, - ], - const.DISC_VALUES: dict( - DEFAULT_VALUES_SCHEMA, - **{ - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_BARRIER_OPERATOR], - const.DISC_INDEX: [const.INDEX_BARRIER_OPERATOR_LABEL], - } - }, - ), - }, - { - const.DISC_COMPONENT: "fan", - const.DISC_GENERIC_DEVICE_CLASS: [const.GENERIC_TYPE_SWITCH_MULTILEVEL], - const.DISC_SPECIFIC_DEVICE_CLASS: [const.SPECIFIC_TYPE_FAN_SWITCH], - const.DISC_VALUES: dict( - DEFAULT_VALUES_SCHEMA, - **{ - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_MULTILEVEL], - const.DISC_INDEX: [const.INDEX_SWITCH_MULTILEVEL_LEVEL], - const.DISC_TYPE: const.TYPE_BYTE, - } - }, - ), - }, - { - const.DISC_COMPONENT: "light", - const.DISC_GENERIC_DEVICE_CLASS: [ - const.GENERIC_TYPE_SWITCH_MULTILEVEL, - const.GENERIC_TYPE_SWITCH_REMOTE, - ], - const.DISC_SPECIFIC_DEVICE_CLASS: [ - const.SPECIFIC_TYPE_POWER_SWITCH_MULTILEVEL, - const.SPECIFIC_TYPE_SCENE_SWITCH_MULTILEVEL, - const.SPECIFIC_TYPE_NOT_USED, - ], - const.DISC_VALUES: dict( - DEFAULT_VALUES_SCHEMA, - **{ - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_MULTILEVEL], - const.DISC_INDEX: [const.INDEX_SWITCH_MULTILEVEL_LEVEL], - const.DISC_TYPE: const.TYPE_BYTE, - }, - "dimming_duration": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_MULTILEVEL], - const.DISC_INDEX: [const.INDEX_SWITCH_MULTILEVEL_DURATION], - const.DISC_OPTIONAL: True, - }, - "color": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_COLOR], - const.DISC_INDEX: [const.INDEX_SWITCH_COLOR_COLOR], - const.DISC_OPTIONAL: True, - }, - "color_channels": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_COLOR], - const.DISC_INDEX: [const.INDEX_SWITCH_COLOR_CHANNELS], - const.DISC_OPTIONAL: True, - }, - }, - ), - }, - { - const.DISC_COMPONENT: "lock", - const.DISC_GENERIC_DEVICE_CLASS: [const.GENERIC_TYPE_ENTRY_CONTROL], - const.DISC_SPECIFIC_DEVICE_CLASS: [ - const.SPECIFIC_TYPE_DOOR_LOCK, - const.SPECIFIC_TYPE_ADVANCED_DOOR_LOCK, - const.SPECIFIC_TYPE_SECURE_KEYPAD_DOOR_LOCK, - const.SPECIFIC_TYPE_SECURE_LOCKBOX, - ], - const.DISC_VALUES: dict( - DEFAULT_VALUES_SCHEMA, - **{ - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_DOOR_LOCK], - const.DISC_INDEX: [const.INDEX_DOOR_LOCK_LOCK], - }, - "access_control": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_ALARM], - const.DISC_INDEX: [const.INDEX_ALARM_ACCESS_CONTROL], - const.DISC_OPTIONAL: True, - }, - "alarm_type": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_ALARM], - const.DISC_INDEX: [const.INDEX_ALARM_TYPE], - const.DISC_OPTIONAL: True, - }, - "alarm_level": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_ALARM], - const.DISC_INDEX: [const.INDEX_ALARM_LEVEL], - const.DISC_OPTIONAL: True, - }, - "v2btze_advanced": { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_CONFIGURATION], - const.DISC_INDEX: [12], - const.DISC_OPTIONAL: True, - }, - }, - ), - }, - { - const.DISC_COMPONENT: "sensor", - const.DISC_VALUES: dict( - DEFAULT_VALUES_SCHEMA, - **{ - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [ - const.COMMAND_CLASS_SENSOR_MULTILEVEL, - const.COMMAND_CLASS_METER, - const.COMMAND_CLASS_ALARM, - const.COMMAND_CLASS_SENSOR_ALARM, - const.COMMAND_CLASS_INDICATOR, - const.COMMAND_CLASS_BATTERY, - ], - const.DISC_GENRE: const.GENRE_USER, - } - }, - ), - }, - { - const.DISC_COMPONENT: "switch", - const.DISC_GENERIC_DEVICE_CLASS: [ - const.GENERIC_TYPE_METER, - const.GENERIC_TYPE_SENSOR_ALARM, - const.GENERIC_TYPE_SENSOR_BINARY, - const.GENERIC_TYPE_SWITCH_BINARY, - const.GENERIC_TYPE_ENTRY_CONTROL, - const.GENERIC_TYPE_SENSOR_MULTILEVEL, - const.GENERIC_TYPE_SWITCH_MULTILEVEL, - const.GENERIC_TYPE_SENSOR_NOTIFICATION, - const.GENERIC_TYPE_GENERIC_CONTROLLER, - const.GENERIC_TYPE_SWITCH_REMOTE, - const.GENERIC_TYPE_REPEATER_SLAVE, - const.GENERIC_TYPE_THERMOSTAT, - const.GENERIC_TYPE_WALL_CONTROLLER, - ], - const.DISC_VALUES: dict( - DEFAULT_VALUES_SCHEMA, - **{ - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_BINARY], - const.DISC_TYPE: const.TYPE_BOOL, - const.DISC_GENRE: const.GENRE_USER, - } - }, - ), - }, -] diff --git a/homeassistant/components/zwave/fan.py b/homeassistant/components/zwave/fan.py deleted file mode 100644 index ba758844c69..00000000000 --- a/homeassistant/components/zwave/fan.py +++ /dev/null @@ -1,86 +0,0 @@ -"""Support for Z-Wave fans.""" -import math - -from homeassistant.components.fan import DOMAIN, SUPPORT_SET_SPEED, FanEntity -from homeassistant.config_entries import ConfigEntry -from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers.dispatcher import async_dispatcher_connect -from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.util.percentage import ( - int_states_in_range, - percentage_to_ranged_value, - ranged_value_to_percentage, -) - -from . import ZWaveDeviceEntity - -SUPPORTED_FEATURES = SUPPORT_SET_SPEED - -SPEED_RANGE = (1, 99) # off is not included - - -async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, -) -> None: - """Set up Z-Wave Fan from Config Entry.""" - - @callback - def async_add_fan(fan): - """Add Z-Wave Fan.""" - async_add_entities([fan]) - - async_dispatcher_connect(hass, "zwave_new_fan", async_add_fan) - - -def get_device(values, **kwargs): - """Create Z-Wave entity device.""" - return ZwaveFan(values) - - -class ZwaveFan(ZWaveDeviceEntity, FanEntity): - """Representation of a Z-Wave fan.""" - - def __init__(self, values): - """Initialize the Z-Wave fan device.""" - ZWaveDeviceEntity.__init__(self, values, DOMAIN) - self.update_properties() - - def update_properties(self): - """Handle data changes for node values.""" - self._state = self.values.primary.data - - def set_percentage(self, percentage): - """Set the speed percentage of the fan.""" - if percentage is None: - # Value 255 tells device to return to previous value - zwave_speed = 255 - elif percentage == 0: - zwave_speed = 0 - else: - zwave_speed = math.ceil(percentage_to_ranged_value(SPEED_RANGE, percentage)) - self.node.set_dimmer(self.values.primary.value_id, zwave_speed) - - def turn_on(self, percentage=None, preset_mode=None, **kwargs): - """Turn the device on.""" - self.set_percentage(percentage) - - def turn_off(self, **kwargs): - """Turn the device off.""" - self.node.set_dimmer(self.values.primary.value_id, 0) - - @property - def percentage(self): - """Return the current speed percentage.""" - return ranged_value_to_percentage(SPEED_RANGE, self._state) - - @property - def speed_count(self) -> int: - """Return the number of speeds the fan supports.""" - return int_states_in_range(SPEED_RANGE) - - @property - def supported_features(self): - """Flag supported features.""" - return SUPPORTED_FEATURES diff --git a/homeassistant/components/zwave/light.py b/homeassistant/components/zwave/light.py deleted file mode 100644 index ea2b34a874f..00000000000 --- a/homeassistant/components/zwave/light.py +++ /dev/null @@ -1,407 +0,0 @@ -"""Support for Z-Wave lights.""" -import logging -from threading import Timer - -from homeassistant.components.light import ( - ATTR_BRIGHTNESS, - ATTR_COLOR_TEMP, - ATTR_RGB_COLOR, - ATTR_RGBW_COLOR, - ATTR_TRANSITION, - COLOR_MODE_BRIGHTNESS, - COLOR_MODE_COLOR_TEMP, - COLOR_MODE_RGB, - COLOR_MODE_RGBW, - DOMAIN, - SUPPORT_TRANSITION, - LightEntity, -) -from homeassistant.config_entries import ConfigEntry -from homeassistant.const import STATE_OFF, STATE_ON -from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers.dispatcher import async_dispatcher_connect -from homeassistant.helpers.entity_platform import AddEntitiesCallback - -from . import CONF_REFRESH_DELAY, CONF_REFRESH_VALUE, ZWaveDeviceEntity, const - -_LOGGER = logging.getLogger(__name__) - -COLOR_CHANNEL_WARM_WHITE = 0x01 -COLOR_CHANNEL_COLD_WHITE = 0x02 -COLOR_CHANNEL_RED = 0x04 -COLOR_CHANNEL_GREEN = 0x08 -COLOR_CHANNEL_BLUE = 0x10 - -# Some bulbs have an independent warm and cool white light LEDs. These need -# to be treated differently, aka the zw098 workaround. Ensure these are added -# to DEVICE_MAPPINGS below. -# (Manufacturer ID, Product ID) from -# https://github.com/OpenZWave/open-zwave/blob/master/config/manufacturer_specific.xml -AEOTEC_ZW098_LED_BULB_LIGHT = (0x86, 0x62) -AEOTEC_ZWA001_LED_BULB_LIGHT = (0x371, 0x1) -AEOTEC_ZWA002_LED_BULB_LIGHT = (0x371, 0x2) -HANK_HKZW_RGB01_LED_BULB_LIGHT = (0x208, 0x4) -ZIPATO_RGB_BULB_2_LED_BULB_LIGHT = (0x131, 0x3) - -WORKAROUND_ZW098 = "zw098" - -DEVICE_MAPPINGS = { - AEOTEC_ZW098_LED_BULB_LIGHT: WORKAROUND_ZW098, - AEOTEC_ZWA001_LED_BULB_LIGHT: WORKAROUND_ZW098, - AEOTEC_ZWA002_LED_BULB_LIGHT: WORKAROUND_ZW098, - HANK_HKZW_RGB01_LED_BULB_LIGHT: WORKAROUND_ZW098, - ZIPATO_RGB_BULB_2_LED_BULB_LIGHT: WORKAROUND_ZW098, -} - -# Generate midpoint color temperatures for bulbs that have limited -# support for white light colors -TEMP_COLOR_MAX = 500 # mireds (inverted) -TEMP_COLOR_MIN = 154 -TEMP_MID_HASS = (TEMP_COLOR_MAX - TEMP_COLOR_MIN) / 2 + TEMP_COLOR_MIN -TEMP_WARM_HASS = (TEMP_COLOR_MAX - TEMP_COLOR_MIN) / 3 * 2 + TEMP_COLOR_MIN -TEMP_COLD_HASS = (TEMP_COLOR_MAX - TEMP_COLOR_MIN) / 3 + TEMP_COLOR_MIN - - -async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, -) -> None: - """Set up Z-Wave Light from Config Entry.""" - - @callback - def async_add_light(light): - """Add Z-Wave Light.""" - async_add_entities([light]) - - async_dispatcher_connect(hass, "zwave_new_light", async_add_light) - - -def get_device(node, values, node_config, **kwargs): - """Create Z-Wave entity device.""" - refresh = node_config.get(CONF_REFRESH_VALUE) - delay = node_config.get(CONF_REFRESH_DELAY) - _LOGGER.debug( - "node=%d value=%d node_config=%s CONF_REFRESH_VALUE=%s" - " CONF_REFRESH_DELAY=%s", - node.node_id, - values.primary.value_id, - node_config, - refresh, - delay, - ) - - if node.has_command_class(const.COMMAND_CLASS_SWITCH_COLOR): - return ZwaveColorLight(values, refresh, delay) - return ZwaveDimmer(values, refresh, delay) - - -def brightness_state(value): - """Return the brightness and state.""" - if value.data > 0: - return round((value.data / 99) * 255), STATE_ON - return 0, STATE_OFF - - -def byte_to_zwave_brightness(value): - """Convert brightness in 0-255 scale to 0-99 scale. - - `value` -- (int) Brightness byte value from 0-255. - """ - if value > 0: - return max(1, round((value / 255) * 99)) - return 0 - - -class ZwaveDimmer(ZWaveDeviceEntity, LightEntity): - """Representation of a Z-Wave dimmer.""" - - def __init__(self, values, refresh, delay): - """Initialize the light.""" - ZWaveDeviceEntity.__init__(self, values, DOMAIN) - self._brightness = None - self._state = None - self._color_mode = None - self._supported_color_modes = set() - self._supported_features = 0 - self._delay = delay - self._refresh_value = refresh - self._zw098 = None - - # Enable appropriate workaround flags for our device - # Make sure that we have values for the key before converting to int - if self.node.manufacturer_id.strip() and self.node.product_id.strip(): - specific_sensor_key = ( - int(self.node.manufacturer_id, 16), - int(self.node.product_id, 16), - ) - if ( - specific_sensor_key in DEVICE_MAPPINGS - and DEVICE_MAPPINGS[specific_sensor_key] == WORKAROUND_ZW098 - ): - _LOGGER.debug("AEOTEC ZW098 workaround enabled") - self._zw098 = 1 - - # Used for value change event handling - self._refreshing = False - self._timer = None - _LOGGER.debug( - "self._refreshing=%s self.delay=%s", self._refresh_value, self._delay - ) - self.value_added() - self.update_properties() - - def update_properties(self): - """Update internal properties based on zwave values.""" - # Brightness - self._brightness, self._state = brightness_state(self.values.primary) - - def value_added(self): - """Call when a new value is added to this entity.""" - self._supported_color_modes = {COLOR_MODE_BRIGHTNESS} - self._color_mode = COLOR_MODE_BRIGHTNESS - if self.values.dimming_duration is not None: - self._supported_features = SUPPORT_TRANSITION - - def value_changed(self): - """Call when a value for this entity's node has changed.""" - if self._refresh_value: - if self._refreshing: - self._refreshing = False - else: - - def _refresh_value(): - """Use timer callback for delayed value refresh.""" - self._refreshing = True - self.values.primary.refresh() - - if self._timer is not None and self._timer.is_alive(): - self._timer.cancel() - - self._timer = Timer(self._delay, _refresh_value) - self._timer.start() - return - super().value_changed() - - @property - def brightness(self): - """Return the brightness of this light between 0..255.""" - return self._brightness - - @property - def is_on(self): - """Return true if device is on.""" - return self._state == STATE_ON - - @property - def color_mode(self): - """Return the current color mode.""" - return self._color_mode - - @property - def supported_color_modes(self): - """Flag supported color modes.""" - return self._supported_color_modes - - @property - def supported_features(self): - """Flag supported features.""" - return self._supported_features - - def _set_duration(self, **kwargs): - """Set the transition time for the brightness value. - - Zwave Dimming Duration values: - 0x00 = instant - 0x01-0x7F = 1 second to 127 seconds - 0x80-0xFE = 1 minute to 127 minutes - 0xFF = factory default - """ - if self.values.dimming_duration is None: - if ATTR_TRANSITION in kwargs: - _LOGGER.debug("Dimming not supported by %s", self.entity_id) - return - - if ATTR_TRANSITION not in kwargs: - self.values.dimming_duration.data = 0xFF - return - - transition = kwargs[ATTR_TRANSITION] - if transition <= 127: - self.values.dimming_duration.data = int(transition) - elif transition > 7620: - self.values.dimming_duration.data = 0xFE - _LOGGER.warning("Transition clipped to 127 minutes for %s", self.entity_id) - else: - minutes = int(transition / 60) - _LOGGER.debug( - "Transition rounded to %d minutes for %s", minutes, self.entity_id - ) - self.values.dimming_duration.data = minutes + 0x7F - - def turn_on(self, **kwargs): - """Turn the device on.""" - self._set_duration(**kwargs) - - # Zwave multilevel switches use a range of [0, 99] to control - # brightness. Level 255 means to set it to previous value. - if ATTR_BRIGHTNESS in kwargs: - self._brightness = kwargs[ATTR_BRIGHTNESS] - brightness = byte_to_zwave_brightness(self._brightness) - else: - brightness = 255 - - if self.node.set_dimmer(self.values.primary.value_id, brightness): - self._state = STATE_ON - - def turn_off(self, **kwargs): - """Turn the device off.""" - self._set_duration(**kwargs) - - if self.node.set_dimmer(self.values.primary.value_id, 0): - self._state = STATE_OFF - - -class ZwaveColorLight(ZwaveDimmer): - """Representation of a Z-Wave color changing light.""" - - def __init__(self, values, refresh, delay): - """Initialize the light.""" - self._color_channels = None - self._rgb = None - self._ct = None - self._white = None - - super().__init__(values, refresh, delay) - - def value_added(self): - """Call when a new value is added to this entity.""" - if self.values.dimming_duration is not None: - self._supported_features = SUPPORT_TRANSITION - - self._supported_color_modes = {COLOR_MODE_RGB} - self._color_mode = COLOR_MODE_RGB - if self._zw098: - self._supported_color_modes.add(COLOR_MODE_COLOR_TEMP) - elif self._color_channels is not None and self._color_channels & ( - COLOR_CHANNEL_WARM_WHITE | COLOR_CHANNEL_COLD_WHITE - ): - self._supported_color_modes = {COLOR_MODE_RGBW} - self._color_mode = COLOR_MODE_RGBW - - def update_properties(self): - """Update internal properties based on zwave values.""" - super().update_properties() - - if self.values.color is None: - return - if self.values.color_channels is None: - return - - # Color Channels - self._color_channels = self.values.color_channels.data - - # Color Data String - data = self.values.color.data - - # RGB is always present in the openzwave color data string. - self._rgb = (int(data[1:3], 16), int(data[3:5], 16), int(data[5:7], 16)) - - # Parse remaining color channels. Openzwave appends white channels - # that are present. - index = 7 - - # Warm white - if self._color_channels & COLOR_CHANNEL_WARM_WHITE: - warm_white = int(data[index : index + 2], 16) - index += 2 - else: - warm_white = 0 - - # Cold white - if self._color_channels & COLOR_CHANNEL_COLD_WHITE: - cold_white = int(data[index : index + 2], 16) - index += 2 - else: - cold_white = 0 - - # Color temperature. With the AEOTEC ZW098 bulb, only two color - # temperatures are supported. The warm and cold channel values - # indicate brightness for warm/cold color temperature. - if self._zw098: - if warm_white > 0: - self._ct = TEMP_WARM_HASS - self._color_mode = COLOR_MODE_COLOR_TEMP - elif cold_white > 0: - self._ct = TEMP_COLD_HASS - self._color_mode = COLOR_MODE_COLOR_TEMP - else: - self._color_mode = COLOR_MODE_RGB - - elif self._color_channels & COLOR_CHANNEL_WARM_WHITE: - self._white = warm_white - - elif self._color_channels & COLOR_CHANNEL_COLD_WHITE: - self._white = cold_white - - # If no rgb channels supported, report None. - if not ( - self._color_channels & COLOR_CHANNEL_RED - or self._color_channels & COLOR_CHANNEL_GREEN - or self._color_channels & COLOR_CHANNEL_BLUE - ): - self._rgb = None - - @property - def rgb_color(self): - """Return the rgb color.""" - return self._rgb - - @property - def rgbw_color(self): - """Return the rgbw color.""" - if self._rgb is None: - return None - return (*self._rgb, self._white) - - @property - def color_temp(self): - """Return the color temperature.""" - return self._ct - - def turn_on(self, **kwargs): - """Turn the device on.""" - rgbw = None - - if ATTR_COLOR_TEMP in kwargs: - # Color temperature. With the AEOTEC ZW098 bulb, only two color - # temperatures are supported. The warm and cold channel values - # indicate brightness for warm/cold color temperature. - if self._zw098: - self._color_mode = COLOR_MODE_COLOR_TEMP - if kwargs[ATTR_COLOR_TEMP] > TEMP_MID_HASS: - self._ct = TEMP_WARM_HASS - rgbw = "#000000ff00" - else: - self._ct = TEMP_COLD_HASS - rgbw = "#00000000ff" - elif ATTR_RGB_COLOR in kwargs: - self._rgb = kwargs[ATTR_RGB_COLOR] - self._white = 0 - elif ATTR_RGBW_COLOR in kwargs: - self._rgb = kwargs[ATTR_RGBW_COLOR][0:3] - self._white = kwargs[ATTR_RGBW_COLOR][3] - - if ATTR_RGB_COLOR in kwargs or ATTR_RGBW_COLOR in kwargs: - rgbw = "#" - for colorval in self._rgb: - rgbw += format(colorval, "02x") - if self._white is not None: - rgbw += format(self._white, "02x") + "00" - else: - rgbw += "0000" - - if rgbw and self.values.color: - self.values.color.data = rgbw - - super().turn_on(**kwargs) diff --git a/homeassistant/components/zwave/lock.py b/homeassistant/components/zwave/lock.py deleted file mode 100644 index 06ce59a1f9e..00000000000 --- a/homeassistant/components/zwave/lock.py +++ /dev/null @@ -1,390 +0,0 @@ -"""Support for Z-Wave door locks.""" -import logging - -import voluptuous as vol - -from homeassistant.components.lock import DOMAIN, LockEntity -from homeassistant.config_entries import ConfigEntry -from homeassistant.core import HomeAssistant, ServiceCall, callback -import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.dispatcher import async_dispatcher_connect -from homeassistant.helpers.entity_platform import AddEntitiesCallback - -from . import ZWaveDeviceEntity, const - -_LOGGER = logging.getLogger(__name__) - -ATTR_NOTIFICATION = "notification" -ATTR_LOCK_STATUS = "lock_status" -ATTR_CODE_SLOT = "code_slot" -ATTR_USERCODE = "usercode" -CONFIG_ADVANCED = "Advanced" - -SERVICE_SET_USERCODE = "set_usercode" -SERVICE_GET_USERCODE = "get_usercode" -SERVICE_CLEAR_USERCODE = "clear_usercode" - -POLYCONTROL = 0x10E -DANALOCK_V2_BTZE = 0x2 -POLYCONTROL_DANALOCK_V2_BTZE_LOCK = (POLYCONTROL, DANALOCK_V2_BTZE) -WORKAROUND_V2BTZE = 1 -WORKAROUND_DEVICE_STATE = 2 -WORKAROUND_TRACK_MESSAGE = 4 -WORKAROUND_ALARM_TYPE = 8 - -DEVICE_MAPPINGS = { - POLYCONTROL_DANALOCK_V2_BTZE_LOCK: WORKAROUND_V2BTZE, - # Kwikset 914TRL ZW500 99100-078 - (0x0090, 0x440): WORKAROUND_DEVICE_STATE, - (0x0090, 0x446): WORKAROUND_DEVICE_STATE, - (0x0090, 0x238): WORKAROUND_DEVICE_STATE, - # Kwikset 888ZW500-15S Smartcode 888 - (0x0090, 0x541): WORKAROUND_DEVICE_STATE, - # Kwikset 916 - (0x0090, 0x0001): WORKAROUND_DEVICE_STATE, - # Kwikset Obsidian - (0x0090, 0x0742): WORKAROUND_DEVICE_STATE, - # Yale Locks - # Yale YRD210, YRD220, YRL220 - (0x0129, 0x0000): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - # Yale YRD210, YRD220 - (0x0129, 0x0209): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - # Yale YRL210, YRL220 - (0x0129, 0x0409): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - # Yale YRD256 - (0x0129, 0x0600): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - # Yale YRD110, YRD120 - (0x0129, 0x0800): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - # Yale YRD446 - (0x0129, 0x1000): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - # Yale YRL220 - (0x0129, 0x2132): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - (0x0129, 0x3CAC): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - # Yale YRD210, YRD220 - (0x0129, 0xAA00): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - # Yale YRD220 - (0x0129, 0xFFFF): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - # Yale YRL256 - (0x0129, 0x0F00): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - # Yale YRD220 (Older Yale products with incorrect vendor ID) - (0x0109, 0x0000): WORKAROUND_DEVICE_STATE | WORKAROUND_ALARM_TYPE, - # Schlage BE469 - (0x003B, 0x5044): WORKAROUND_DEVICE_STATE | WORKAROUND_TRACK_MESSAGE, - # Schlage FE599NX - (0x003B, 0x504C): WORKAROUND_DEVICE_STATE, -} - -LOCK_NOTIFICATION = { - "1": "Manual Lock", - "2": "Manual Unlock", - "5": "Keypad Lock", - "6": "Keypad Unlock", - "11": "Lock Jammed", - "254": "Unknown Event", -} -NOTIFICATION_RF_LOCK = "3" -NOTIFICATION_RF_UNLOCK = "4" -LOCK_NOTIFICATION[NOTIFICATION_RF_LOCK] = "RF Lock" -LOCK_NOTIFICATION[NOTIFICATION_RF_UNLOCK] = "RF Unlock" - -LOCK_ALARM_TYPE = { - "9": "Deadbolt Jammed", - "16": "Unlocked by Bluetooth ", - "18": "Locked with Keypad by user ", - "19": "Unlocked with Keypad by user ", - "21": "Manually Locked ", - "22": "Manually Unlocked ", - "27": "Auto re-lock", - "33": "User deleted: ", - "112": "Master code changed or User added: ", - "113": "Duplicate PIN code: ", - "130": "RF module, power restored", - "144": "Unlocked by NFC Tag or Card by user ", - "161": "Tamper Alarm: ", - "167": "Low Battery", - "168": "Critical Battery Level", - "169": "Battery too low to operate", -} -ALARM_RF_LOCK = "24" -ALARM_RF_UNLOCK = "25" -LOCK_ALARM_TYPE[ALARM_RF_LOCK] = "Locked by RF" -LOCK_ALARM_TYPE[ALARM_RF_UNLOCK] = "Unlocked by RF" - -MANUAL_LOCK_ALARM_LEVEL = { - "1": "by Key Cylinder or Inside thumb turn", - "2": "by Touch function (lock and leave)", -} - -TAMPER_ALARM_LEVEL = {"1": "Too many keypresses", "2": "Cover removed"} - -LOCK_STATUS = { - "1": True, - "2": False, - "3": True, - "4": False, - "5": True, - "6": False, - "9": False, - "18": True, - "19": False, - "21": True, - "22": False, - "24": True, - "25": False, - "27": True, -} - -ALARM_TYPE_STD = ["18", "19", "33", "112", "113", "144"] - -SET_USERCODE_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(ATTR_CODE_SLOT): vol.Coerce(int), - vol.Required(ATTR_USERCODE): cv.string, - } -) - -GET_USERCODE_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(ATTR_CODE_SLOT): vol.Coerce(int), - } -) - -CLEAR_USERCODE_SCHEMA = vol.Schema( - { - vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), - vol.Required(ATTR_CODE_SLOT): vol.Coerce(int), - } -) - - -async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, -) -> None: - """Set up Z-Wave Lock from Config Entry.""" - - @callback - def async_add_lock(lock): - """Add Z-Wave Lock.""" - async_add_entities([lock]) - - async_dispatcher_connect(hass, "zwave_new_lock", async_add_lock) - - network = hass.data[const.DATA_NETWORK] - - def set_usercode(service: ServiceCall) -> None: - """Set the usercode to index X on the lock.""" - node_id = service.data.get(const.ATTR_NODE_ID) - lock_node = network.nodes[node_id] - code_slot = service.data.get(ATTR_CODE_SLOT) - usercode = service.data.get(ATTR_USERCODE) - - for value in lock_node.get_values( - class_id=const.COMMAND_CLASS_USER_CODE - ).values(): - if value.index != code_slot: - continue - if len(str(usercode)) < 4: - _LOGGER.error( - "Invalid code provided: (%s) " - "usercode must be at least 4 and at most" - " %s digits", - usercode, - len(value.data), - ) - break - value.data = str(usercode) - break - - def get_usercode(service: ServiceCall) -> None: - """Get a usercode at index X on the lock.""" - node_id = service.data.get(const.ATTR_NODE_ID) - lock_node = network.nodes[node_id] - code_slot = service.data.get(ATTR_CODE_SLOT) - - for value in lock_node.get_values( - class_id=const.COMMAND_CLASS_USER_CODE - ).values(): - if value.index != code_slot: - continue - _LOGGER.info("Usercode at slot %s is: %s", value.index, value.data) - break - - def clear_usercode(service: ServiceCall) -> None: - """Set usercode to slot X on the lock.""" - node_id = service.data.get(const.ATTR_NODE_ID) - lock_node = network.nodes[node_id] - code_slot = service.data.get(ATTR_CODE_SLOT) - data = "" - - for value in lock_node.get_values( - class_id=const.COMMAND_CLASS_USER_CODE - ).values(): - if value.index != code_slot: - continue - for i in range(len(value.data)): - data += "\0" - i += 1 - _LOGGER.debug("Data to clear lock: %s", data) - value.data = data - _LOGGER.info("Usercode at slot %s is cleared", value.index) - break - - hass.services.async_register( - DOMAIN, SERVICE_SET_USERCODE, set_usercode, schema=SET_USERCODE_SCHEMA - ) - hass.services.async_register( - DOMAIN, SERVICE_GET_USERCODE, get_usercode, schema=GET_USERCODE_SCHEMA - ) - hass.services.async_register( - DOMAIN, SERVICE_CLEAR_USERCODE, clear_usercode, schema=CLEAR_USERCODE_SCHEMA - ) - - -def get_device(node, values, **kwargs): - """Create Z-Wave entity device.""" - return ZwaveLock(values) - - -class ZwaveLock(ZWaveDeviceEntity, LockEntity): - """Representation of a Z-Wave Lock.""" - - def __init__(self, values): - """Initialize the Z-Wave lock device.""" - ZWaveDeviceEntity.__init__(self, values, DOMAIN) - self._state = None - self._notification = None - self._lock_status = None - self._v2btze = None - self._state_workaround = False - self._track_message_workaround = False - self._previous_message = None - self._alarm_type_workaround = False - - # Enable appropriate workaround flags for our device - # Make sure that we have values for the key before converting to int - if self.node.manufacturer_id.strip() and self.node.product_id.strip(): - specific_sensor_key = ( - int(self.node.manufacturer_id, 16), - int(self.node.product_id, 16), - ) - if specific_sensor_key in DEVICE_MAPPINGS: - workaround = DEVICE_MAPPINGS[specific_sensor_key] - if workaround & WORKAROUND_V2BTZE: - self._v2btze = 1 - _LOGGER.debug("Polycontrol Danalock v2 BTZE workaround enabled") - if workaround & WORKAROUND_DEVICE_STATE: - self._state_workaround = True - _LOGGER.debug("Notification device state workaround enabled") - if workaround & WORKAROUND_TRACK_MESSAGE: - self._track_message_workaround = True - _LOGGER.debug("Message tracking workaround enabled") - if workaround & WORKAROUND_ALARM_TYPE: - self._alarm_type_workaround = True - _LOGGER.debug("Alarm Type device state workaround enabled") - self.update_properties() - - def update_properties(self): - """Handle data changes for node values.""" - self._state = self.values.primary.data - _LOGGER.debug("lock state set to %s", self._state) - if self.values.access_control: - notification_data = self.values.access_control.data - self._notification = LOCK_NOTIFICATION.get(str(notification_data)) - if self._state_workaround: - self._state = LOCK_STATUS.get(str(notification_data)) - _LOGGER.debug("workaround: lock state set to %s", self._state) - if ( - self._v2btze - and self.values.v2btze_advanced - and self.values.v2btze_advanced.data == CONFIG_ADVANCED - ): - self._state = LOCK_STATUS.get(str(notification_data)) - _LOGGER.debug( - "Lock state set from Access Control value and is %s, get=%s", - str(notification_data), - self.state, - ) - - if self._track_message_workaround: - this_message = self.node.stats["lastReceivedMessage"][5] - - if this_message == const.COMMAND_CLASS_DOOR_LOCK: - self._state = self.values.primary.data - _LOGGER.debug("set state to %s based on message tracking", self._state) - if self._previous_message == const.COMMAND_CLASS_DOOR_LOCK: - if self._state: - self._notification = LOCK_NOTIFICATION[NOTIFICATION_RF_LOCK] - self._lock_status = LOCK_ALARM_TYPE[ALARM_RF_LOCK] - else: - self._notification = LOCK_NOTIFICATION[NOTIFICATION_RF_UNLOCK] - self._lock_status = LOCK_ALARM_TYPE[ALARM_RF_UNLOCK] - return - - self._previous_message = this_message - - if not self.values.alarm_type: - return - - alarm_type = self.values.alarm_type.data - if self.values.alarm_level: - alarm_level = self.values.alarm_level.data - else: - alarm_level = None - - if not alarm_type: - return - - if self._alarm_type_workaround: - self._state = LOCK_STATUS.get(str(alarm_type)) - _LOGGER.debug( - "workaround: lock state set to %s -- alarm type: %s", - self._state, - str(alarm_type), - ) - - if alarm_type == 21: - self._lock_status = ( - f"{LOCK_ALARM_TYPE.get(str(alarm_type))}" - f"{MANUAL_LOCK_ALARM_LEVEL.get(str(alarm_level))}" - ) - return - if str(alarm_type) in ALARM_TYPE_STD: - self._lock_status = f"{LOCK_ALARM_TYPE.get(str(alarm_type))}{alarm_level}" - return - if alarm_type == 161: - self._lock_status = ( - f"{LOCK_ALARM_TYPE.get(str(alarm_type))}" - f"{TAMPER_ALARM_LEVEL.get(str(alarm_level))}" - ) - - return - if alarm_type != 0: - self._lock_status = LOCK_ALARM_TYPE.get(str(alarm_type)) - return - - @property - def is_locked(self): - """Return true if device is locked.""" - return self._state - - def lock(self, **kwargs): - """Lock the device.""" - self.values.primary.data = True - - def unlock(self, **kwargs): - """Unlock the device.""" - self.values.primary.data = False - - @property - def extra_state_attributes(self): - """Return the device specific state attributes.""" - data = super().extra_state_attributes - if self._notification: - data[ATTR_NOTIFICATION] = self._notification - if self._lock_status: - data[ATTR_LOCK_STATUS] = self._lock_status - return data diff --git a/homeassistant/components/zwave/manifest.json b/homeassistant/components/zwave/manifest.json deleted file mode 100644 index bf3a9abe77e..00000000000 --- a/homeassistant/components/zwave/manifest.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "domain": "zwave", - "name": "Z-Wave (deprecated)", - "config_flow": true, - "documentation": "https://www.home-assistant.io/integrations/zwave", - "requirements": ["homeassistant-pyozw==0.1.10", "pydispatcher==2.0.5"], - "codeowners": ["@home-assistant/z-wave"], - "iot_class": "local_push" -} diff --git a/homeassistant/components/zwave/migration.py b/homeassistant/components/zwave/migration.py deleted file mode 100644 index 0b151d18e4b..00000000000 --- a/homeassistant/components/zwave/migration.py +++ /dev/null @@ -1,167 +0,0 @@ -"""Handle migration from legacy Z-Wave to OpenZWave and Z-Wave JS.""" -from __future__ import annotations - -from typing import TYPE_CHECKING, TypedDict, cast - -from homeassistant.config_entries import ConfigEntry -from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers.device_registry import async_get as async_get_device_registry -from homeassistant.helpers.entity_registry import async_get as async_get_entity_registry -from homeassistant.helpers.singleton import singleton -from homeassistant.helpers.storage import Store - -from .const import DOMAIN -from .util import node_device_id_and_name - -if TYPE_CHECKING: - from . import ZWaveDeviceEntityValues - -LEGACY_ZWAVE_MIGRATION = f"{DOMAIN}_legacy_zwave_migration" -STORAGE_WRITE_DELAY = 30 -STORAGE_KEY = f"{DOMAIN}.legacy_zwave_migration" -STORAGE_VERSION = 1 - - -class ZWaveMigrationData(TypedDict): - """Represent the Z-Wave migration data dict.""" - - node_id: int - node_instance: int - command_class: int - command_class_label: str - value_index: int - device_id: str - domain: str - entity_id: str - unique_id: str - unit_of_measurement: str | None - - -@callback -def async_is_ozw_migrated(hass): - """Return True if migration to ozw is done.""" - ozw_config_entries = hass.config_entries.async_entries("ozw") - if not ozw_config_entries: - return False - - ozw_config_entry = ozw_config_entries[0] # only one ozw entry is allowed - migrated = bool(ozw_config_entry.data.get("migrated")) - return migrated - - -@callback -def async_is_zwave_js_migrated(hass): - """Return True if migration to Z-Wave JS is done.""" - zwave_js_config_entries = hass.config_entries.async_entries("zwave_js") - if not zwave_js_config_entries: - return False - - migrated = any( - config_entry.data.get("migrated") for config_entry in zwave_js_config_entries - ) - return migrated - - -async def async_add_migration_entity_value( - hass: HomeAssistant, - entity_id: str, - entity_values: ZWaveDeviceEntityValues, -) -> None: - """Add Z-Wave entity value for legacy Z-Wave migration.""" - migration_handler: LegacyZWaveMigration = await get_legacy_zwave_migration(hass) - migration_handler.add_entity_value(entity_id, entity_values) - - -async def async_get_migration_data( - hass: HomeAssistant, config_entry: ConfigEntry -) -> dict[str, ZWaveMigrationData]: - """Return Z-Wave migration data.""" - migration_handler: LegacyZWaveMigration = await get_legacy_zwave_migration(hass) - return await migration_handler.get_data(config_entry) - - -@singleton(LEGACY_ZWAVE_MIGRATION) -async def get_legacy_zwave_migration(hass: HomeAssistant) -> LegacyZWaveMigration: - """Return legacy Z-Wave migration handler.""" - migration_handler = LegacyZWaveMigration(hass) - await migration_handler.load_data() - return migration_handler - - -class LegacyZWaveMigration: - """Handle the migration from zwave to ozw and zwave_js.""" - - def __init__(self, hass: HomeAssistant) -> None: - """Set up migration instance.""" - self._hass = hass - self._store = Store(hass, STORAGE_VERSION, STORAGE_KEY) - self._data: dict[str, dict[str, ZWaveMigrationData]] = {} - - async def load_data(self) -> None: - """Load Z-Wave migration data.""" - stored = cast(dict, await self._store.async_load()) - if stored: - self._data = stored - - @callback - def save_data( - self, config_entry_id: str, entity_id: str, data: ZWaveMigrationData - ) -> None: - """Save Z-Wave migration data.""" - if config_entry_id not in self._data: - self._data[config_entry_id] = {} - self._data[config_entry_id][entity_id] = data - self._store.async_delay_save(self._data_to_save, STORAGE_WRITE_DELAY) - - @callback - def _data_to_save(self) -> dict[str, dict[str, ZWaveMigrationData]]: - """Return data to save.""" - return self._data - - @callback - def add_entity_value( - self, - entity_id: str, - entity_values: ZWaveDeviceEntityValues, - ) -> None: - """Add info for one entity and Z-Wave value.""" - ent_reg = async_get_entity_registry(self._hass) - dev_reg = async_get_device_registry(self._hass) - - node = entity_values.primary.node - entity_entry = ent_reg.async_get(entity_id) - assert entity_entry - device_identifier, _ = node_device_id_and_name( - node, entity_values.primary.instance - ) - device_entry = dev_reg.async_get_device({device_identifier}, set()) - assert device_entry - - # Normalize unit of measurement. - if unit := entity_entry.unit_of_measurement: - unit = unit.lower() - if unit == "": - unit = None - - data: ZWaveMigrationData = { - "node_id": node.node_id, - "node_instance": entity_values.primary.instance, - "command_class": entity_values.primary.command_class, - "command_class_label": entity_values.primary.label, - "value_index": entity_values.primary.index, - "device_id": device_entry.id, - "domain": entity_entry.domain, - "entity_id": entity_id, - "unique_id": entity_entry.unique_id, - "unit_of_measurement": unit, - } - - self.save_data(entity_entry.config_entry_id, entity_id, data) - - async def get_data( - self, config_entry: ConfigEntry - ) -> dict[str, ZWaveMigrationData]: - """Return Z-Wave migration data.""" - await self.load_data() - data = self._data.get(config_entry.entry_id) - return data or {} diff --git a/homeassistant/components/zwave/node_entity.py b/homeassistant/components/zwave/node_entity.py deleted file mode 100644 index ade68284313..00000000000 --- a/homeassistant/components/zwave/node_entity.py +++ /dev/null @@ -1,381 +0,0 @@ -"""Entity class that represents Z-Wave node.""" -# pylint: disable=import-error -# pylint: disable=import-outside-toplevel -from itertools import count - -from homeassistant.const import ( - ATTR_BATTERY_LEVEL, - ATTR_ENTITY_ID, - ATTR_VIA_DEVICE, - ATTR_WAKEUP, -) -from homeassistant.core import callback -from homeassistant.helpers.device_registry import async_get_registry as get_dev_reg -from homeassistant.helpers.entity import DeviceInfo, Entity -from homeassistant.helpers.entity_registry import async_get_registry - -from .const import ( - ATTR_BASIC_LEVEL, - ATTR_NODE_ID, - ATTR_SCENE_DATA, - ATTR_SCENE_ID, - COMMAND_CLASS_CENTRAL_SCENE, - COMMAND_CLASS_VERSION, - COMMAND_CLASS_WAKE_UP, - DOMAIN, - EVENT_NODE_EVENT, - EVENT_SCENE_ACTIVATED, -) -from .util import is_node_parsed, node_device_id_and_name, node_name - -ATTR_QUERY_STAGE = "query_stage" -ATTR_AWAKE = "is_awake" -ATTR_READY = "is_ready" -ATTR_FAILED = "is_failed" -ATTR_PRODUCT_NAME = "product_name" -ATTR_MANUFACTURER_NAME = "manufacturer_name" -ATTR_NODE_NAME = "node_name" -ATTR_APPLICATION_VERSION = "application_version" - -STAGE_COMPLETE = "Complete" - -_REQUIRED_ATTRIBUTES = [ - ATTR_QUERY_STAGE, - ATTR_AWAKE, - ATTR_READY, - ATTR_FAILED, - "is_info_received", - "max_baud_rate", - "is_zwave_plus", -] -_OPTIONAL_ATTRIBUTES = ["capabilities", "neighbors", "location"] -_COMM_ATTRIBUTES = [ - "sentCnt", - "sentFailed", - "retries", - "receivedCnt", - "receivedDups", - "receivedUnsolicited", - "sentTS", - "receivedTS", - "lastRequestRTT", - "averageRequestRTT", - "lastResponseRTT", - "averageResponseRTT", -] -ATTRIBUTES = _REQUIRED_ATTRIBUTES + _OPTIONAL_ATTRIBUTES - - -class ZWaveBaseEntity(Entity): - """Base class for Z-Wave Node and Value entities.""" - - def __init__(self): - """Initialize the base Z-Wave class.""" - self._update_scheduled = False - - def maybe_schedule_update(self): - """Maybe schedule state update. - - If value changed after device was created but before setup_platform - was called - skip updating state. - """ - if self.hass and not self._update_scheduled: - self.hass.add_job(self._schedule_update) - - @callback - def _schedule_update(self): - """Schedule delayed update.""" - if self._update_scheduled: - return - - @callback - def do_update(): - """Really update.""" - self.async_write_ha_state() - self._update_scheduled = False - - self._update_scheduled = True - self.hass.loop.call_later(0.1, do_update) - - def try_remove_and_add(self): - """Remove this entity and add it back.""" - - async def _async_remove_and_add(): - await self.async_remove(force_remove=True) - self.entity_id = None - await self.platform.async_add_entities([self]) - - if self.hass and self.platform: - self.hass.add_job(_async_remove_and_add) - - async def node_removed(self): - """Call when a node is removed from the Z-Wave network.""" - await self.async_remove(force_remove=True) - - registry = await async_get_registry(self.hass) - if self.entity_id not in registry.entities: - return - - registry.async_remove(self.entity_id) - - -class ZWaveNodeEntity(ZWaveBaseEntity): - """Representation of a Z-Wave node.""" - - def __init__(self, node, network): - """Initialize node.""" - super().__init__() - from openzwave.network import ZWaveNetwork - from pydispatch import dispatcher - - self._network = network - self.node = node - self.node_id = self.node.node_id - self._name = node_name(self.node) - self._product_name = node.product_name - self._manufacturer_name = node.manufacturer_name - self._unique_id = self._compute_unique_id() - self._application_version = None - self._attributes = {} - self.wakeup_interval = None - self.location = None - self.battery_level = None - dispatcher.connect( - self.network_node_value_added, ZWaveNetwork.SIGNAL_VALUE_ADDED - ) - dispatcher.connect(self.network_node_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED) - dispatcher.connect(self.network_node_changed, ZWaveNetwork.SIGNAL_NODE) - dispatcher.connect(self.network_node_changed, ZWaveNetwork.SIGNAL_NOTIFICATION) - dispatcher.connect(self.network_node_event, ZWaveNetwork.SIGNAL_NODE_EVENT) - dispatcher.connect( - self.network_scene_activated, ZWaveNetwork.SIGNAL_SCENE_EVENT - ) - - @property - def unique_id(self): - """Return unique ID of Z-wave node.""" - return self._unique_id - - @property - def device_info(self) -> DeviceInfo: - """Return device information.""" - identifier, name = node_device_id_and_name(self.node) - info = DeviceInfo( - identifiers={identifier}, - manufacturer=self.node.manufacturer_name, - model=self.node.product_name, - name=name, - ) - if self.node_id > 1: - info[ATTR_VIA_DEVICE] = (DOMAIN, 1) - return info - - def maybe_update_application_version(self, value): - """Update application version if value is a Command Class Version, Application Value.""" - if ( - value - and value.command_class == COMMAND_CLASS_VERSION - and value.label == "Application Version" - ): - self._application_version = value.data - - def network_node_value_added(self, node=None, value=None, args=None): - """Handle a added value to a none on the network.""" - if node and node.node_id != self.node_id: - return - if args is not None and "nodeId" in args and args["nodeId"] != self.node_id: - return - - self.maybe_update_application_version(value) - - def network_node_changed(self, node=None, value=None, args=None): - """Handle a changed node on the network.""" - if node and node.node_id != self.node_id: - return - if args is not None and "nodeId" in args and args["nodeId"] != self.node_id: - return - - # Process central scene activation - if value is not None and value.command_class == COMMAND_CLASS_CENTRAL_SCENE: - self.central_scene_activated(value.index, value.data) - - self.maybe_update_application_version(value) - - self.node_changed() - - def get_node_statistics(self): - """Retrieve statistics from the node.""" - return self._network.manager.getNodeStatistics( - self._network.home_id, self.node_id - ) - - def node_changed(self): - """Update node properties.""" - attributes = {} - stats = self.get_node_statistics() - for attr in ATTRIBUTES: - value = getattr(self.node, attr) - if attr in _REQUIRED_ATTRIBUTES or value: - attributes[attr] = value - - for attr in _COMM_ATTRIBUTES: - attributes[attr] = stats[attr] - - if self.node.can_wake_up(): - for value in self.node.get_values(COMMAND_CLASS_WAKE_UP).values(): - if value.index != 0: - continue - - self.wakeup_interval = value.data - break - else: - self.wakeup_interval = None - - self.battery_level = self.node.get_battery_level() - self._product_name = self.node.product_name - self._manufacturer_name = self.node.manufacturer_name - self._name = node_name(self.node) - self._attributes = attributes - - if not self._unique_id: - self._unique_id = self._compute_unique_id() - if self._unique_id: - # Node info parsed. Remove and re-add - self.try_remove_and_add() - - self.maybe_schedule_update() - - async def node_renamed(self, update_ids=False): - """Rename the node and update any IDs.""" - identifier, self._name = node_device_id_and_name(self.node) - # Set the name in the devices. If they're customised - # the customisation will not be stored as name and will stick. - dev_reg = await get_dev_reg(self.hass) - device = dev_reg.async_get_device(identifiers={identifier}) - dev_reg.async_update_device(device.id, name=self._name) - # update sub-devices too - for i in count(2): - identifier, new_name = node_device_id_and_name(self.node, i) - device = dev_reg.async_get_device(identifiers={identifier}) - if not device: - break - dev_reg.async_update_device(device.id, name=new_name) - - # Update entity ID. - if update_ids: - ent_reg = await async_get_registry(self.hass) - new_entity_id = ent_reg.async_generate_entity_id( - DOMAIN, self._name, self.platform.entities.keys() - {self.entity_id} - ) - if new_entity_id != self.entity_id: - # Don't change the name attribute, it will be None unless - # customised and if it's been customised, keep the - # customisation. - ent_reg.async_update_entity(self.entity_id, new_entity_id=new_entity_id) - return - # else for the above two ifs, update if not using update_entity - self.async_write_ha_state() - - def network_node_event(self, node, value): - """Handle a node activated event on the network.""" - if node.node_id == self.node.node_id: - self.node_event(value) - - def node_event(self, value): - """Handle a node activated event for this node.""" - if self.hass is None: - return - - self.hass.bus.fire( - EVENT_NODE_EVENT, - { - ATTR_ENTITY_ID: self.entity_id, - ATTR_NODE_ID: self.node.node_id, - ATTR_BASIC_LEVEL: value, - }, - ) - - def network_scene_activated(self, node, scene_id): - """Handle a scene activated event on the network.""" - if node.node_id == self.node.node_id: - self.scene_activated(scene_id) - - def scene_activated(self, scene_id): - """Handle an activated scene for this node.""" - if self.hass is None: - return - - self.hass.bus.fire( - EVENT_SCENE_ACTIVATED, - { - ATTR_ENTITY_ID: self.entity_id, - ATTR_NODE_ID: self.node.node_id, - ATTR_SCENE_ID: scene_id, - }, - ) - - def central_scene_activated(self, scene_id, scene_data): - """Handle an activated central scene for this node.""" - if self.hass is None: - return - - self.hass.bus.fire( - EVENT_SCENE_ACTIVATED, - { - ATTR_ENTITY_ID: self.entity_id, - ATTR_NODE_ID: self.node_id, - ATTR_SCENE_ID: scene_id, - ATTR_SCENE_DATA: scene_data, - }, - ) - - @property - def state(self): - """Return the state.""" - if ATTR_READY not in self._attributes: - return None - - if self._attributes[ATTR_FAILED]: - return "dead" - if self._attributes[ATTR_QUERY_STAGE] != "Complete": - return "initializing" - if not self._attributes[ATTR_AWAKE]: - return "sleeping" - if self._attributes[ATTR_READY]: - return "ready" - - return None - - @property - def should_poll(self): - """No polling needed.""" - return False - - @property - def name(self): - """Return the name of the device.""" - return self._name - - @property - def extra_state_attributes(self): - """Return the device specific state attributes.""" - attrs = { - ATTR_NODE_ID: self.node_id, - ATTR_NODE_NAME: self._name, - ATTR_MANUFACTURER_NAME: self._manufacturer_name, - ATTR_PRODUCT_NAME: self._product_name, - } - attrs.update(self._attributes) - if self.battery_level is not None: - attrs[ATTR_BATTERY_LEVEL] = self.battery_level - if self.wakeup_interval is not None: - attrs[ATTR_WAKEUP] = self.wakeup_interval - if self._application_version is not None: - attrs[ATTR_APPLICATION_VERSION] = self._application_version - - return attrs - - def _compute_unique_id(self): - if is_node_parsed(self.node) or self.node.is_ready: - return f"node-{self.node_id}" - return None diff --git a/homeassistant/components/zwave/sensor.py b/homeassistant/components/zwave/sensor.py deleted file mode 100644 index 1f32f8bb681..00000000000 --- a/homeassistant/components/zwave/sensor.py +++ /dev/null @@ -1,124 +0,0 @@ -"""Support for Z-Wave sensors.""" -from homeassistant.components.sensor import DOMAIN, SensorDeviceClass, SensorEntity -from homeassistant.config_entries import ConfigEntry -from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT -from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers.dispatcher import async_dispatcher_connect -from homeassistant.helpers.entity_platform import AddEntitiesCallback - -from . import ZWaveDeviceEntity, const - - -async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, -) -> None: - """Set up Z-Wave Sensor from Config Entry.""" - - @callback - def async_add_sensor(sensor): - """Add Z-Wave Sensor.""" - async_add_entities([sensor]) - - async_dispatcher_connect(hass, "zwave_new_sensor", async_add_sensor) - - -def get_device(node, values, **kwargs): - """Create Z-Wave entity device.""" - # Generic Device mappings - if values.primary.command_class == const.COMMAND_CLASS_BATTERY: - return ZWaveBatterySensor(values) - if node.has_command_class(const.COMMAND_CLASS_SENSOR_MULTILEVEL): - return ZWaveMultilevelSensor(values) - if ( - node.has_command_class(const.COMMAND_CLASS_METER) - and values.primary.type == const.TYPE_DECIMAL - ): - return ZWaveMultilevelSensor(values) - if node.has_command_class(const.COMMAND_CLASS_ALARM) or node.has_command_class( - const.COMMAND_CLASS_SENSOR_ALARM - ): - return ZWaveAlarmSensor(values) - return None - - -class ZWaveSensor(ZWaveDeviceEntity, SensorEntity): - """Representation of a Z-Wave sensor.""" - - def __init__(self, values): - """Initialize the sensor.""" - ZWaveDeviceEntity.__init__(self, values, DOMAIN) - self.update_properties() - - def update_properties(self): - """Handle the data changes for node values.""" - self._state = self.values.primary.data - self._units = self.values.primary.units - - @property - def force_update(self): - """Return force_update.""" - return True - - @property - def native_value(self): - """Return the state of the sensor.""" - return self._state - - @property - def native_unit_of_measurement(self): - """Return the unit of measurement the value is expressed in.""" - return self._units - - -class ZWaveMultilevelSensor(ZWaveSensor): - """Representation of a multi level sensor Z-Wave sensor.""" - - @property - def native_value(self): - """Return the state of the sensor.""" - if self._units in ("C", "F"): - return round(self._state, 1) - if isinstance(self._state, float): - return round(self._state, 2) - - return self._state - - @property - def device_class(self): - """Return the class of this device.""" - if self._units in ["C", "F"]: - return SensorDeviceClass.TEMPERATURE - return None - - @property - def native_unit_of_measurement(self): - """Return the unit the value is expressed in.""" - if self._units == "C": - return TEMP_CELSIUS - if self._units == "F": - return TEMP_FAHRENHEIT - return self._units - - -class ZWaveAlarmSensor(ZWaveSensor): - """Representation of a Z-Wave sensor that sends Alarm alerts. - - Examples include certain Multisensors that have motion and vibration - capabilities. Z-Wave defines various alarm types such as Smoke, Flood, - Burglar, CarbonMonoxide, etc. - - This wraps these alarms and allows you to use them to trigger things, etc. - - COMMAND_CLASS_ALARM is what we get here. - """ - - -class ZWaveBatterySensor(ZWaveSensor): - """Representation of Z-Wave device battery level.""" - - @property - def device_class(self): - """Return the class of this device.""" - return SensorDeviceClass.BATTERY diff --git a/homeassistant/components/zwave/services.yaml b/homeassistant/components/zwave/services.yaml deleted file mode 100644 index d3063ef5d43..00000000000 --- a/homeassistant/components/zwave/services.yaml +++ /dev/null @@ -1,411 +0,0 @@ -# Describes the format for available Z-Wave services - -change_association: - name: Change association - description: Change an association in the Z-Wave network. - fields: - association: - name: Association - description: Specify add or remove association - required: true - example: add - selector: - text: - node_id: - name: Node ID - description: Node id of the node to set association for. - required: true - selector: - number: - min: 1 - max: 255 - target_node_id: - name: Target node ID - description: Node id of the node to associate to. - required: true - selector: - number: - min: 1 - max: 255 - group: - name: Group - description: Group number to set association for. - required: true - selector: - number: - min: 1 - max: 5 - instance: - name: Instance - description: Instance of multichannel association. - default: 0 - selector: - number: - min: 0 - max: 255 - -add_node: - name: Add node - description: Add a new (unsecure) node to the Z-Wave network. Refer to OZW_Log.txt for progress. - -add_node_secure: - name: Add node secure - description: Add a new node to the Z-Wave network with secure communications. Secure network key must be set, this process will fallback to add_node (unsecure) for unsupported devices. Note that unsecure devices can't directly talk to secure devices. Refer to OZW_Log.txt for progress. - -cancel_command: - name: Cancel command - description: Cancel a running Z-Wave controller command. Use this to exit add_node, if you weren't going to use it but activated it. - -heal_network: - name: Heal network - description: Start a Z-Wave network heal. This might take a while and will slow down the Z-Wave network greatly while it is being processed. Refer to OZW_Log.txt for progress. - fields: - return_routes: - name: Return routes - description: Whether or not to update the return routes from the nodes to the controller. - default: false - selector: - boolean: - -heal_node: - name: Heal node - description: Start a Z-Wave node heal. Refer to OZW_Log.txt for progress. - fields: - return_routes: - name: Return routes - description: Whether or not to update the return routes from the node to the controller. - default: false - selector: - boolean: - -remove_node: - name: Remove node - description: Remove a node from the Z-Wave network. Refer to OZW_Log.txt for progress. - -remove_failed_node: - name: Remove failed node - description: This command will remove a failed node from the network. The node should be on the controller's failed nodes list, otherwise this command will fail. Refer to OZW_Log.txt for progress. - fields: - node_id: - name: Node ID - description: Node id of the device to remove. - required: true - selector: - number: - min: 1 - max: 255 - -replace_failed_node: - name: Replace failed node - description: Replace a failed node with another. If the node is not in the controller's failed nodes list, or the node responds, this command will fail. Refer to OZW_Log.txt for progress. - fields: - node_id: - name: Node ID - description: Node id of the device to replace. - required: true - selector: - number: - min: 1 - max: 255 - -set_config_parameter: - name: Set config parameter - description: Set a config parameter to a node on the Z-Wave network. - fields: - node_id: - name: Node ID - description: Node id of the device to set config parameter to. - required: true - selector: - number: - min: 1 - max: 255 - parameter: - name: Parameter - description: Parameter number to set. - required: true - selector: - number: - min: 1 - max: 255 - value: - name: Value - description: Value to set for parameter. (String value for list and bool parameters, integer for others). - required: true - selector: - text: - size: - name: Size - description: Set the size of the parameter value. Only needed if no parameters are available. - default: 2 - selector: - number: - min: 1 - max: 255 - -set_node_value: - name: Set node value - description: Set the value for a given value_id on a Z-Wave device. - fields: - node_id: - name: Node ID - description: Node id of the device to set the value on. - required: true - selector: - number: - min: 1 - max: 255 - value_id: - name: Value ID - description: Value id of the value to set (integer or string). - required: true - selector: - text: - value: - name: Value - description: Value to set (integer or string). - required: true - selector: - text: - -refresh_node_value: - name: Refresh node value - description: Refresh the value for a given value_id on a Z-Wave device. - fields: - node_id: - name: Node ID - description: Node id of the device to refresh value from. - required: true - selector: - number: - min: 1 - max: 255 - value_id: - name: Value ID - description: Value id of the value to refresh. - required: true - selector: - text: - -set_poll_intensity: - name: Set poll intensity - description: Set the polling interval to a nodes value - fields: - node_id: - name: Node ID - description: ID of the node to set polling to. - required: true - selector: - number: - min: 1 - max: 255 - value_id: - name: Value ID - description: ID of the value to set polling to. - example: 72037594255792737 - required: true - selector: - text: - poll_intensity: - name: Poll intensity - description: The intensity to poll, 0 = disabled, 1 = Every time through list, 2 = Every second time through list... - required: true - selector: - number: - min: 0 - max: 100 - -print_config_parameter: - name: Print configuration parameter - description: Prints a Z-Wave node config parameter value to log. - fields: - node_id: - name: Node ID - description: Node id of the device to print the parameter from. - required: true - selector: - number: - min: 1 - max: 255 - parameter: - name: Parameter - description: Parameter number to print. - required: true - selector: - number: - min: 1 - max: 255 - -print_node: - name: Print node - description: Print all information about z-wave node. - fields: - node_id: - name: Node ID - description: Node id of the device to print. - required: true - selector: - number: - min: 1 - max: 255 - -refresh_entity: - name: Refresh entity - description: Refresh zwave entity. - fields: - entity_id: - name: Entity - description: Name of the entity to refresh. - required: true - selector: - entity: - integration: zwave - -refresh_node: - name: Refresh node - description: Refresh zwave node. - fields: - node_id: - name: Node ID - description: ID of the node to refresh. - required: true - selector: - number: - min: 1 - max: 255 - -set_wakeup: - name: Set wakeup - description: Sets wake-up interval of a node. - fields: - node_id: - name: Node ID - description: Node id of the device to set the wake-up interval for. - required: true - selector: - number: - min: 1 - max: 255 - value: - name: Value - description: Value of the interval to set. - required: true - selector: - text: - -start_network: - name: Start network - description: Start the Z-Wave network. This might take a while, depending on how big your Z-Wave network is. - -stop_network: - name: Stop network - description: Stop the Z-Wave network, all updates into Home Assistant will stop. - -soft_reset: - name: Soft reset - description: This will reset the controller without removing its data. Use carefully because not all controllers support this. Refer to your controller's manual. - -test_network: - name: Test network - description: This will send test to nodes in the Z-Wave network. This will greatly slow down the Z-Wave network while it is being processed. Refer to OZW_Log.txt for progress. - -test_node: - name: Test node - description: This will send test messages to a node in the Z-Wave network. This could bring back dead nodes. - fields: - node_id: - name: Node ID - description: ID of the node to send test messages to. - required: true - selector: - number: - min: 1 - max: 255 - messages: - name: Messages - description: Amount of test messages to send. - default: 1 - selector: - number: - min: 1 - max: 100 - -rename_node: - name: Rename node - description: Set the name of a node. This will also affect the IDs of all entities in the node. - fields: - node_id: - name: Node ID - description: ID of the node to rename. - required: true - selector: - number: - min: 1 - max: 255 - update_ids: - name: Update IDs - description: Rename the entity IDs for entities of this node. - default: false - selector: - boolean: - name: - name: Name - description: New Name - required: true - example: "kitchen" - selector: - text: - -rename_value: - name: Rename value - description: Set the name of a node value. This will affect the ID of the value entity. Value IDs can be queried from /api/zwave/values/{node_id} - fields: - node_id: - name: Node ID - description: ID of the node to rename. - required: true - selector: - number: - min: 1 - max: 255 - value_id: - name: Value ID - description: ID of the value to rename. - example: 72037594255792737 - required: true - selector: - text: - update_ids: - name: Update IDs - description: Update the entity ID for this value's entity. - default: false - selector: - boolean: - name: - name: Name - description: New Name - example: "Luminosity" - required: true - selector: - text: - -reset_node_meters: - name: Reset node meters - description: Resets the meter counters of a node. - fields: - node_id: - name: Node ID - description: Node id of the device to reset meters for. - required: true - selector: - number: - min: 1 - max: 255 - instance: - name: Instance - description: Instance of association. - default: 1 - selector: - number: - min: 1 - max: 100 diff --git a/homeassistant/components/zwave/strings.json b/homeassistant/components/zwave/strings.json deleted file mode 100644 index 69401b171e2..00000000000 --- a/homeassistant/components/zwave/strings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "step": { - "user": { - "description": "This integration is no longer maintained. For new installations, use Z-Wave JS instead.\n\nSee https://www.home-assistant.io/docs/z-wave/installation/ for information on the configuration variables", - "data": { - "usb_path": "[%key:common::config_flow::data::usb_path%]", - "network_key": "Network Key (leave blank to auto-generate)" - } - } - }, - "error": { - "option_error": "Z-Wave validation failed. Is the path to the USB stick correct?" - }, - "abort": { - "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", - "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]" - } - }, - "state": { - "query_stage": { - "initializing": "[%key:component::zwave::state::_::initializing%]", - "dead": "[%key:component::zwave::state::_::dead%]" - }, - "_": { - "initializing": "Initializing", - "dead": "Dead", - "sleeping": "Sleeping", - "ready": "Ready" - } - } -} diff --git a/homeassistant/components/zwave/switch.py b/homeassistant/components/zwave/switch.py deleted file mode 100644 index f7d3471e2ab..00000000000 --- a/homeassistant/components/zwave/switch.py +++ /dev/null @@ -1,64 +0,0 @@ -"""Support for Z-Wave switches.""" -import time - -from homeassistant.components.switch import DOMAIN, SwitchEntity -from homeassistant.config_entries import ConfigEntry -from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers.dispatcher import async_dispatcher_connect -from homeassistant.helpers.entity_platform import AddEntitiesCallback - -from . import ZWaveDeviceEntity, workaround - - -async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, -) -> None: - """Set up Z-Wave Switch from Config Entry.""" - - @callback - def async_add_switch(switch): - """Add Z-Wave Switch.""" - async_add_entities([switch]) - - async_dispatcher_connect(hass, "zwave_new_switch", async_add_switch) - - -def get_device(values, **kwargs): - """Create zwave entity device.""" - return ZwaveSwitch(values) - - -class ZwaveSwitch(ZWaveDeviceEntity, SwitchEntity): - """Representation of a Z-Wave switch.""" - - def __init__(self, values): - """Initialize the Z-Wave switch device.""" - ZWaveDeviceEntity.__init__(self, values, DOMAIN) - self.refresh_on_update = ( - workaround.get_device_mapping(values.primary) - == workaround.WORKAROUND_REFRESH_NODE_ON_UPDATE - ) - self.last_update = time.perf_counter() - self._state = self.values.primary.data - - def update_properties(self): - """Handle data changes for node values.""" - self._state = self.values.primary.data - if self.refresh_on_update and time.perf_counter() - self.last_update > 30: - self.last_update = time.perf_counter() - self.node.request_state() - - @property - def is_on(self): - """Return true if device is on.""" - return self._state - - def turn_on(self, **kwargs): - """Turn the device on.""" - self.node.set_switch(self.values.primary.value_id, True) - - def turn_off(self, **kwargs): - """Turn the device off.""" - self.node.set_switch(self.values.primary.value_id, False) diff --git a/homeassistant/components/zwave/translations/af.json b/homeassistant/components/zwave/translations/af.json deleted file mode 100644 index 155960b3884..00000000000 --- a/homeassistant/components/zwave/translations/af.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "Dood", - "initializing": "Inisialiseer", - "ready": "Gereed", - "sleeping": "Aan die slaap" - }, - "query_stage": { - "dead": "Dood ({query_stage})", - "initializing": "Inisialiseer ({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/ar.json b/homeassistant/components/zwave/translations/ar.json deleted file mode 100644 index 5dc1469d468..00000000000 --- a/homeassistant/components/zwave/translations/ar.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "\u0645\u0641\u0635\u0648\u0644", - "initializing": "\u0642\u064a\u062f \u0627\u0644\u0625\u0646\u0634\u0627\u0621", - "ready": "\u062c\u0627\u0647\u0632", - "sleeping": "\u0646\u0627\u0626\u0645" - }, - "query_stage": { - "dead": "\u0645\u0641\u0635\u0648\u0644 ({query_stage})", - "initializing": "\u0642\u064a\u062f \u0627\u0644\u0625\u0646\u0634\u0627\u0621 ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/bg.json b/homeassistant/components/zwave/translations/bg.json deleted file mode 100644 index ae82e98d705..00000000000 --- a/homeassistant/components/zwave/translations/bg.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Z-Wave \u0432\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d" - }, - "error": { - "option_error": "\u0412\u0430\u043b\u0438\u0434\u0438\u0440\u0430\u043d\u0435\u0442\u043e \u043d\u0430 Z-Wave \u043d\u0435 \u0431\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e. \u041f\u0440\u0430\u0432\u0438\u043b\u0435\u043d \u043b\u0438 \u0435 \u043f\u044a\u0442\u044f\u0442 \u043a\u044a\u043c USB \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e?" - }, - "step": { - "user": { - "data": { - "network_key": "\u041c\u0440\u0435\u0436\u043e\u0432 \u043a\u043b\u044e\u0447 (\u043e\u0441\u0442\u0430\u0432\u0435\u0442\u0435 \u043f\u0440\u0430\u0437\u043d\u043e \u0437\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0430\u043d\u0435)", - "usb_path": "USB \u043f\u044a\u0442" - }, - "description": "\u0412\u0438\u0436\u0442\u0435 https://www.home-assistant.io/docs/z-wave/installation/ \u0437\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0442\u043d\u043e\u0441\u043d\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0438\u0442\u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u043b\u0438\u0432\u0438" - } - } - }, - "state": { - "_": { - "dead": "\u041c\u044a\u0440\u0442\u044a\u0432", - "initializing": "\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f", - "ready": "\u0413\u043e\u0442\u043e\u0432", - "sleeping": "\u0421\u043f\u044f\u0449" - }, - "query_stage": { - "dead": "\u041c\u044a\u0440\u0442\u044a\u0432 ({query_stage})", - "initializing": "\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/bs.json b/homeassistant/components/zwave/translations/bs.json deleted file mode 100644 index 8d58bad5606..00000000000 --- a/homeassistant/components/zwave/translations/bs.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "Mrtav", - "initializing": "Inicijalizacija", - "ready": "Spreman", - "sleeping": "Spava" - }, - "query_stage": { - "dead": "Mrtav ({query_stage})", - "initializing": "Inicijalizacija ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/ca.json b/homeassistant/components/zwave/translations/ca.json deleted file mode 100644 index 4b9e8953b8a..00000000000 --- a/homeassistant/components/zwave/translations/ca.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "El dispositiu ja est\u00e0 configurat", - "single_instance_allowed": "Ja configurat. Nom\u00e9s \u00e9s possible una sola configuraci\u00f3." - }, - "error": { - "option_error": "Ha fallat la validaci\u00f3 de Z-Wave. \u00c9s correcta la ruta al port USB on hi ha connectat el dispositiu?" - }, - "step": { - "user": { - "data": { - "network_key": "Clau de xarxa (deixa-ho en blanc per generar-la autom\u00e0ticament)", - "usb_path": "Ruta del dispositiu USB" - }, - "description": "Aquesta integraci\u00f3 ja no s'actualitzar\u00e0. Utilitza Z-Wave JS per a instal\u00b7lacions noves.\n\nConsulta https://www.home-assistant.io/docs/z-wave/installation/ per a m\u00e9s informaci\u00f3 sobre les variables de configuraci\u00f3" - } - } - }, - "state": { - "_": { - "dead": "No disponible", - "initializing": "Inicialitzant", - "ready": "A punt", - "sleeping": "Dormint" - }, - "query_stage": { - "dead": "No disponible", - "initializing": "Inicialitzant" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/cs.json b/homeassistant/components/zwave/translations/cs.json deleted file mode 100644 index 320feafe08a..00000000000 --- a/homeassistant/components/zwave/translations/cs.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Za\u0159\u00edzen\u00ed je ji\u017e nastaveno", - "single_instance_allowed": "Ji\u017e nastaveno. Je mo\u017en\u00e1 pouze jedin\u00e1 konfigurace." - }, - "error": { - "option_error": "Z-Wave ov\u011b\u0159en\u00ed se nezda\u0159ilo. Je cesta k USB za\u0159\u00edzen\u00ed spr\u00e1vn\u011b?" - }, - "step": { - "user": { - "data": { - "network_key": "S\u00ed\u0165ov\u00fd kl\u00ed\u010d (ponechte pr\u00e1zdn\u00e9 pro automatick\u00e9 generov\u00e1n\u00ed)", - "usb_path": "Cesta k USB za\u0159\u00edzen\u00ed" - }, - "description": "Viz https://www.home-assistant.io/docs/z-wave/installation/ pro informace o konfigura\u010dn\u00edch prom\u011bnn\u00fdch" - } - } - }, - "state": { - "_": { - "dead": "Nereaguje", - "initializing": "Inicializace", - "ready": "P\u0159ipraveno", - "sleeping": "\u00dasporn\u00fd re\u017eim" - }, - "query_stage": { - "dead": "Nereaguje", - "initializing": "Inicializace" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/cy.json b/homeassistant/components/zwave/translations/cy.json deleted file mode 100644 index 43860e1c1fd..00000000000 --- a/homeassistant/components/zwave/translations/cy.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "Marw", - "initializing": "Ymgychwyn", - "ready": "Barod", - "sleeping": "Cysgu" - }, - "query_stage": { - "dead": "Marw ({query_stage})", - "initializing": "Ymgychwyn ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/da.json b/homeassistant/components/zwave/translations/da.json deleted file mode 100644 index 7bad51c4f8e..00000000000 --- a/homeassistant/components/zwave/translations/da.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Z-Wave er allerede konfigureret" - }, - "error": { - "option_error": "Z-Wave-validering mislykkedes. Er stien til USB-enhed korrekt?" - }, - "step": { - "user": { - "data": { - "network_key": "Netv\u00e6rksn\u00f8gle (efterlad blank for autogenerering)", - "usb_path": "Sti til USB-enhed" - }, - "description": "Se https://www.home-assistant.io/docs/z-wave/installation/ for oplysninger om konfigurationsvariabler" - } - } - }, - "state": { - "_": { - "dead": "D\u00f8d", - "initializing": "Initialiserer", - "ready": "Klar", - "sleeping": "Sover" - }, - "query_stage": { - "dead": "D\u00f8d ({query_stage})", - "initializing": "Initialiserer ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/de.json b/homeassistant/components/zwave/translations/de.json deleted file mode 100644 index 9d432edd1e5..00000000000 --- a/homeassistant/components/zwave/translations/de.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Ger\u00e4t ist bereits konfiguriert", - "single_instance_allowed": "Bereits konfiguriert. Nur eine einzige Konfiguration m\u00f6glich." - }, - "error": { - "option_error": "Z-Wave-Validierung fehlgeschlagen. Ist der Pfad zum USB-Stick korrekt?" - }, - "step": { - "user": { - "data": { - "network_key": "Netzwerkschl\u00fcssel (leer lassen, um automatisch zu generieren)", - "usb_path": "USB-Ger\u00e4te-Pfad" - }, - "description": "Diese Integration wird nicht mehr gepflegt. Verwende bei Neuinstallationen stattdessen Z-Wave JS.\n\nSiehe https://www.home-assistant.io/docs/z-wave/installation/ f\u00fcr Informationen zu den Konfigurationsvariablen" - } - } - }, - "state": { - "_": { - "dead": "Nicht erreichbar", - "initializing": "Initialisierend", - "ready": "Bereit", - "sleeping": "Schlafend" - }, - "query_stage": { - "dead": "Nicht erreichbar ({query_stage})", - "initializing": "Initialisierend" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/el.json b/homeassistant/components/zwave/translations/el.json deleted file mode 100644 index 48b5eba30f6..00000000000 --- a/homeassistant/components/zwave/translations/el.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "\u0397 \u03c3\u03c5\u03c3\u03ba\u03b5\u03c5\u03ae \u03ad\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03b4\u03b9\u03b1\u03bc\u03bf\u03c1\u03c6\u03c9\u03b8\u03b5\u03af", - "single_instance_allowed": "\u0388\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03c1\u03c5\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af. \u039c\u03cc\u03bd\u03bf \u03bc\u03af\u03b1 \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae." - }, - "error": { - "option_error": "\u0397 \u03b5\u03c0\u03b9\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7 Z-Wave \u03b1\u03c0\u03ad\u03c4\u03c5\u03c7\u03b5. \u0395\u03af\u03bd\u03b1\u03b9 \u03c3\u03c9\u03c3\u03c4\u03ae \u03b7 \u03b4\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae \u03c0\u03c1\u03bf\u03c2 \u03c4\u03bf \u03c3\u03c4\u03b9\u03ba\u03ac\u03ba\u03b9 USB;" - }, - "step": { - "user": { - "data": { - "network_key": "\u039a\u03bb\u03b5\u03b9\u03b4\u03af \u03b4\u03b9\u03ba\u03c4\u03cd\u03bf\u03c5 (\u03b1\u03c6\u03ae\u03c3\u03c4\u03b5 \u03c4\u03bf \u03ba\u03b5\u03bd\u03cc \u03b3\u03b9\u03b1 \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b7 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1)", - "usb_path": "\u0394\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae \u03c3\u03c5\u03c3\u03ba\u03b5\u03c5\u03ae\u03c2 USB" - }, - "description": "\u0391\u03c5\u03c4\u03ae \u03b7 \u03b5\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03b4\u03b5\u03bd \u03b4\u03b9\u03b1\u03c4\u03b7\u03c1\u03b5\u03af\u03c4\u03b1\u03b9 \u03c0\u03bb\u03ad\u03bf\u03bd. \u0393\u03b9\u03b1 \u03bd\u03ad\u03b5\u03c2 \u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03ac\u03c3\u03b5\u03b9\u03c2, \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03c4\u03b5 \u03c4\u03bf Z-Wave JS. \n\n \u0394\u03b5\u03af\u03c4\u03b5 https://www.home-assistant.io/docs/z-wave/installation/ \u03b3\u03b9\u03b1 \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 \u03c3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ac \u03bc\u03b5 \u03c4\u03b9\u03c2 \u03bc\u03b5\u03c4\u03b1\u03b2\u03bb\u03b7\u03c4\u03ad\u03c2 \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7\u03c2" - } - } - }, - "state": { - "_": { - "dead": "\u039d\u03b5\u03ba\u03c1\u03cc", - "initializing": "\u0391\u03c1\u03c7\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7", - "ready": "\u0388\u03c4\u03bf\u03b9\u03bc\u03bf", - "sleeping": "\u039a\u03bf\u03b9\u03bc\u03ac\u03c4\u03b1\u03b9" - }, - "query_stage": { - "dead": "\u039d\u03b5\u03ba\u03c1\u03cc", - "initializing": "\u0391\u03c1\u03c7\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/en.json b/homeassistant/components/zwave/translations/en.json deleted file mode 100644 index 5c7442fea05..00000000000 --- a/homeassistant/components/zwave/translations/en.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Device is already configured", - "single_instance_allowed": "Already configured. Only a single configuration possible." - }, - "error": { - "option_error": "Z-Wave validation failed. Is the path to the USB stick correct?" - }, - "step": { - "user": { - "data": { - "network_key": "Network Key (leave blank to auto-generate)", - "usb_path": "USB Device Path" - }, - "description": "This integration is no longer maintained. For new installations, use Z-Wave JS instead.\n\nSee https://www.home-assistant.io/docs/z-wave/installation/ for information on the configuration variables" - } - } - }, - "state": { - "_": { - "dead": "Dead", - "initializing": "Initializing", - "ready": "Ready", - "sleeping": "Sleeping" - }, - "query_stage": { - "dead": "Dead", - "initializing": "Initializing" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/es-419.json b/homeassistant/components/zwave/translations/es-419.json deleted file mode 100644 index abcf85fffa1..00000000000 --- a/homeassistant/components/zwave/translations/es-419.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Z-Wave ya est\u00e1 configurado" - }, - "error": { - "option_error": "La validaci\u00f3n de Z-Wave fall\u00f3. \u00bfEs correcta la ruta a la memoria USB?" - }, - "step": { - "user": { - "data": { - "network_key": "Clave de red (dejar en blanco para auto-generar)", - "usb_path": "Ruta USB" - }, - "description": "Consulte https://www.home-assistant.io/docs/z-wave/installation/ para obtener informaci\u00f3n sobre las variables de configuraci\u00f3n" - } - } - }, - "state": { - "_": { - "dead": "Desconectado", - "initializing": "Iniciando", - "ready": "Listo", - "sleeping": "Hibernacion" - }, - "query_stage": { - "dead": "Desconectado ({query_stage})", - "initializing": "Iniciando ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/es.json b/homeassistant/components/zwave/translations/es.json deleted file mode 100644 index 0d8b9a3020c..00000000000 --- a/homeassistant/components/zwave/translations/es.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Z-Wave ya est\u00e1 configurado", - "single_instance_allowed": "Ya est\u00e1 configurado. Solo es posible una \u00fanica configuraci\u00f3n." - }, - "error": { - "option_error": "Z-Wave error de validaci\u00f3n. \u00bfLa ruta de acceso a la memoria USB escorrecta?" - }, - "step": { - "user": { - "data": { - "network_key": "Clave de red (d\u00e9jelo en blanco para generar autom\u00e1ticamente)", - "usb_path": "Ruta del dispositivo USB" - }, - "description": "Consulta https://www.home-assistant.io/docs/z-wave/installation/ para obtener informaci\u00f3n sobre las variables de configuraci\u00f3n" - } - } - }, - "state": { - "_": { - "dead": "No responde", - "initializing": "Inicializando", - "ready": "Listo", - "sleeping": "Ahorro de energ\u00eda" - }, - "query_stage": { - "dead": "No responde", - "initializing": "Inicializando" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/et.json b/homeassistant/components/zwave/translations/et.json deleted file mode 100644 index 922126e0d86..00000000000 --- a/homeassistant/components/zwave/translations/et.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Seade on juba h\u00e4\u00e4lestatud", - "single_instance_allowed": "Juba seadistatud. V\u00f5imalik on ainult \u00fcks seadistamine." - }, - "error": { - "option_error": "Z-Wave valideerimine nurjus. Kas USB-m\u00e4lupulga tee on \u00f5ige?" - }, - "step": { - "user": { - "data": { - "network_key": "V\u00f5rguv\u00f5ti (j\u00e4ta automaatse genereerimise jaoks t\u00fchjaks)", - "usb_path": "USB seadme rada" - }, - "description": "Seda sidumist enam ei hallata. Uueks sidumiseks kasuta Z-Wave JS.\n\nKonfiguratsioonimuutujate kohta leiad teavet https://www.home-assistant.io/docs/z-wave/installation/" - } - } - }, - "state": { - "_": { - "dead": "Surnud", - "initializing": "L\u00e4htestan", - "ready": "Valmis", - "sleeping": "Ootel" - }, - "query_stage": { - "dead": "Surnud", - "initializing": "L\u00e4htestan" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/eu.json b/homeassistant/components/zwave/translations/eu.json deleted file mode 100644 index ceab4ed0d98..00000000000 --- a/homeassistant/components/zwave/translations/eu.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "Hilda", - "initializing": "Hasieratzen", - "ready": "Prest", - "sleeping": "Lotan" - }, - "query_stage": { - "dead": "Ez du erantzuten ({query_stage})", - "initializing": "Hasieratzen ({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/fa.json b/homeassistant/components/zwave/translations/fa.json deleted file mode 100644 index 21d9a0c0fb7..00000000000 --- a/homeassistant/components/zwave/translations/fa.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "\u0645\u0631\u062f\u0647", - "initializing": "\u062f\u0631 \u062d\u0627\u0644 \u0622\u0645\u0627\u062f\u0647 \u0634\u062f\u0646", - "ready": "\u0622\u0645\u0627\u062f\u0647", - "sleeping": "\u062f\u0631 \u062d\u0627\u0644 \u062e\u0648\u0627\u0628" - }, - "query_stage": { - "dead": "\u0645\u0631\u062f\u0647 ({query_stage})", - "initializing": "\u062f\u0631 \u062d\u0627\u0644 \u0622\u0645\u0627\u062f\u0647 \u0634\u062f\u0646 ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/fi.json b/homeassistant/components/zwave/translations/fi.json deleted file mode 100644 index 90fb77b49e1..00000000000 --- a/homeassistant/components/zwave/translations/fi.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "config": { - "step": { - "user": { - "data": { - "usb_path": "USB-polku" - } - } - } - }, - "state": { - "_": { - "dead": "Kuollut", - "initializing": "Alustaa", - "ready": "Valmis", - "sleeping": "Lepotilassa" - }, - "query_stage": { - "dead": "Kuollut ({query_stage})", - "initializing": "Alustaa ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/fr.json b/homeassistant/components/zwave/translations/fr.json deleted file mode 100644 index 280d86e1537..00000000000 --- a/homeassistant/components/zwave/translations/fr.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "L'appareil est d\u00e9j\u00e0 configur\u00e9", - "single_instance_allowed": "D\u00e9j\u00e0 configur\u00e9. Une seule configuration possible." - }, - "error": { - "option_error": "La validation Z-Wave a \u00e9chou\u00e9. Le chemin d'acc\u00e8s \u00e0 la cl\u00e9 USB est-il correct?" - }, - "step": { - "user": { - "data": { - "network_key": "Cl\u00e9 r\u00e9seau (laisser vide pour g\u00e9n\u00e9rer automatiquement)", - "usb_path": "Chemin du p\u00e9riph\u00e9rique USB" - }, - "description": "Voir https://www.home-assistant.io/docs/z-wave/installation/ pour plus d'informations sur les variables de configuration." - } - } - }, - "state": { - "_": { - "dead": "Morte", - "initializing": "Initialisation", - "ready": "Pr\u00eat", - "sleeping": "En veille" - }, - "query_stage": { - "dead": "Morte", - "initializing": "Initialisation" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/gsw.json b/homeassistant/components/zwave/translations/gsw.json deleted file mode 100644 index fb704e97c7d..00000000000 --- a/homeassistant/components/zwave/translations/gsw.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "Tod", - "initializing": "Inizialisi\u00e4r\u00e4", - "ready": "Parat", - "sleeping": "Schlaf\u00e4" - }, - "query_stage": { - "dead": "Tod ({query_stage})", - "initializing": "Inizialisi\u00e4r\u00e4 ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/he.json b/homeassistant/components/zwave/translations/he.json deleted file mode 100644 index 9cbf39a6d16..00000000000 --- a/homeassistant/components/zwave/translations/he.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "\u05ea\u05e6\u05d5\u05e8\u05ea \u05d4\u05d4\u05ea\u05e7\u05df \u05db\u05d1\u05e8 \u05e0\u05e7\u05d1\u05e2\u05d4", - "single_instance_allowed": "\u05ea\u05e6\u05d5\u05e8\u05ea\u05d5 \u05db\u05d1\u05e8 \u05e0\u05e7\u05d1\u05e2\u05d4. \u05e8\u05e7 \u05ea\u05e6\u05d5\u05e8\u05d4 \u05d0\u05d7\u05ea \u05d0\u05e4\u05e9\u05e8\u05d9\u05ea." - }, - "step": { - "user": { - "data": { - "usb_path": "\u05e0\u05ea\u05d9\u05d1 \u05d4\u05ea\u05e7\u05df USB" - } - } - } - }, - "state": { - "_": { - "dead": "\u05de\u05ea", - "initializing": "\u05d0\u05ea\u05d7\u05d5\u05dc", - "ready": "\u05de\u05d5\u05db\u05df", - "sleeping": "\u05d9\u05e9\u05df" - }, - "query_stage": { - "dead": "\u05de\u05ea", - "initializing": "\u05d0\u05ea\u05d7\u05d5\u05dc" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/hi.json b/homeassistant/components/zwave/translations/hi.json deleted file mode 100644 index 99e98c4aa9f..00000000000 --- a/homeassistant/components/zwave/translations/hi.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "\u092e\u0943\u0924", - "initializing": "\u0906\u0930\u0902\u092d", - "ready": "\u0924\u0948\u092f\u093e\u0930", - "sleeping": "\u0938\u094b\u092f\u093e \u0939\u0941\u0906" - }, - "query_stage": { - "dead": " ( {query_stage} )", - "initializing": "\u0906\u0930\u0902\u092d ({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/hr.json b/homeassistant/components/zwave/translations/hr.json deleted file mode 100644 index dbff348b761..00000000000 --- a/homeassistant/components/zwave/translations/hr.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "Mrtav", - "initializing": "Inicijalizacija", - "ready": "Spreman", - "sleeping": "Spavanje" - }, - "query_stage": { - "dead": "Mrtav ({query_stage})", - "initializing": "Inicijalizacija ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/hu.json b/homeassistant/components/zwave/translations/hu.json deleted file mode 100644 index 4d0c6adff59..00000000000 --- a/homeassistant/components/zwave/translations/hu.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Az eszk\u00f6z m\u00e1r konfigur\u00e1lva van", - "single_instance_allowed": "M\u00e1r konfigur\u00e1lva van. Csak egy konfigur\u00e1ci\u00f3 lehets\u00e9ges." - }, - "error": { - "option_error": "A Z-Wave \u00e9rv\u00e9nyes\u00edt\u00e9s sikertelen. Az USB-meghajt\u00f3 el\u00e9r\u00e9si \u00fatj\u00e1t helyesen adtad meg?" - }, - "step": { - "user": { - "data": { - "network_key": "H\u00e1l\u00f3zati kulcs (hagyja \u00fcresen az automatikus gener\u00e1l\u00e1shoz)", - "usb_path": "USB eszk\u00f6z el\u00e9r\u00e9si \u00fat" - }, - "description": "Ezt az integr\u00e1ci\u00f3t m\u00e1r nem tartj\u00e1k fenn. \u00daj telep\u00edt\u00e9sek eset\u00e9n haszn\u00e1lja helyette a Z-Wave JS-t.\n\nA konfigur\u00e1ci\u00f3s v\u00e1ltoz\u00f3kkal kapcsolatos inform\u00e1ci\u00f3k\u00e9rt l\u00e1sd https://www.home-assistant.io/docs/z-wave/installation/." - } - } - }, - "state": { - "_": { - "dead": "Nem ad \u00e9letjelet", - "initializing": "Inicializ\u00e1l\u00e1s", - "ready": "K\u00e9sz", - "sleeping": "Alv\u00e1s" - }, - "query_stage": { - "dead": "Nem ad \u00e9letjelet", - "initializing": "Inicializ\u00e1l\u00e1s" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/hy.json b/homeassistant/components/zwave/translations/hy.json deleted file mode 100644 index c4fa19f700a..00000000000 --- a/homeassistant/components/zwave/translations/hy.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "\u0544\u0565\u057c\u0561\u056e", - "initializing": "\u0546\u0561\u056d\u0561\u0571\u0565\u057c\u0576\u0578\u0572", - "ready": "\u054a\u0561\u057f\u0580\u0561\u057d\u057f \u0567", - "sleeping": "\u0554\u0576\u0565\u056c" - }, - "query_stage": { - "dead": "\u0544\u0561\u0570\u0561\u0581\u0561\u056e{query_stage})", - "initializing": "\u0546\u0561\u056d\u0561\u0571\u0565\u057c\u0576\u0578\u0582\u0569\u0575\u0578\u0582\u0576({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/id.json b/homeassistant/components/zwave/translations/id.json deleted file mode 100644 index 91301f6e00e..00000000000 --- a/homeassistant/components/zwave/translations/id.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Perangkat sudah dikonfigurasi", - "single_instance_allowed": "Sudah dikonfigurasi. Hanya satu konfigurasi yang diizinkan." - }, - "error": { - "option_error": "Validasi Z-Wave gagal. Apakah jalur ke stik USB sudah benar?" - }, - "step": { - "user": { - "data": { - "network_key": "Kunci Jaringan (biarkan kosong untuk dibuat secara otomatis)", - "usb_path": "Jalur Perangkat USB" - }, - "description": "Integrasi ini tidak lagi dipertahankan. Untuk instalasi baru, gunakan Z-Wave JS sebagai gantinya.\n\nBaca https://www.home-assistant.io/docs/z-wave/installation/ untuk informasi tentang variabel konfigurasi" - } - } - }, - "state": { - "_": { - "dead": "Mati", - "initializing": "Inisialisasi", - "ready": "Siap", - "sleeping": "Tidur" - }, - "query_stage": { - "dead": "Mati", - "initializing": "Inisialisasi" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/is.json b/homeassistant/components/zwave/translations/is.json deleted file mode 100644 index bb54fd48425..00000000000 --- a/homeassistant/components/zwave/translations/is.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "Dau\u00f0ur", - "initializing": "Frumstilli", - "ready": "Tilb\u00fainn", - "sleeping": "\u00cd dvala" - }, - "query_stage": { - "dead": "Dau\u00f0ur ({query_stage})", - "initializing": "Frumstilli ({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/it.json b/homeassistant/components/zwave/translations/it.json deleted file mode 100644 index 17207c23b50..00000000000 --- a/homeassistant/components/zwave/translations/it.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Il dispositivo \u00e8 gi\u00e0 configurato", - "single_instance_allowed": "Gi\u00e0 configurato. \u00c8 possibile una sola configurazione." - }, - "error": { - "option_error": "Convalida Z-Wave non riuscita. Il percorso della chiavetta USB \u00e8 corretto?" - }, - "step": { - "user": { - "data": { - "network_key": "Chiave di rete (lascia vuoto per generare automaticamente)", - "usb_path": "Percorso del dispositivo USB" - }, - "description": "Questa integrazione non viene pi\u00f9 mantenuta. Per le nuove installazioni, usa invece Z-Wave JS. \n\nVedere https://www.home-assistant.io/docs/z-wave/installation/ per informazioni sulle variabili di configurazione" - } - } - }, - "state": { - "_": { - "dead": "Disattivo", - "initializing": "In avvio", - "ready": "Pronto", - "sleeping": "Dormiente" - }, - "query_stage": { - "dead": "Disattivo", - "initializing": "In avvio" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/ja.json b/homeassistant/components/zwave/translations/ja.json deleted file mode 100644 index ff0afe58c0e..00000000000 --- a/homeassistant/components/zwave/translations/ja.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "\u30c7\u30d0\u30a4\u30b9\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059", - "single_instance_allowed": "\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u5358\u4e00\u306e\u8a2d\u5b9a\u3057\u304b\u3067\u304d\u307e\u305b\u3093\u3002" - }, - "error": { - "option_error": "Z-Wave\u306e\u691c\u8a3c\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002USB\u30b9\u30c6\u30a3\u30c3\u30af\u3078\u306e\u30d1\u30b9\u306f\u6b63\u3057\u3044\u3067\u3059\u304b\uff1f" - }, - "step": { - "user": { - "data": { - "network_key": "\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u30ad\u30fc(\u7a7a\u767d\u306b\u3059\u308b\u3068\u81ea\u52d5\u751f\u6210\u3055\u308c\u307e\u3059)", - "usb_path": "USB\u30c7\u30d0\u30a4\u30b9\u306e\u30d1\u30b9" - }, - "description": "\u3053\u306e\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u306e\u30e1\u30f3\u30c6\u30ca\u30f3\u30b9\u306f\u7d42\u4e86\u3057\u307e\u3057\u305f\u3002\u65b0\u898f\u306b\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u5834\u5408\u306f\u3001\u4ee3\u308f\u308a\u306bZ-Wave JS\u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\n\u69cb\u6210\u5909\u6570\u306e\u8a73\u7d30\u306b\u3064\u3044\u3066\u306f\u3001https://www.home-assistant.io/docs/z-wave/installation/ \u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002" - } - } - }, - "state": { - "_": { - "dead": "\u30c7\u30c3\u30c9", - "initializing": "\u521d\u671f\u5316\u4e2d", - "ready": "\u6e96\u5099\u5b8c\u4e86", - "sleeping": "\u30b9\u30ea\u30fc\u30d7" - }, - "query_stage": { - "dead": "\u30c7\u30c3\u30c9", - "initializing": "\u521d\u671f\u5316\u4e2d" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/ko.json b/homeassistant/components/zwave/translations/ko.json deleted file mode 100644 index 613b4108d22..00000000000 --- a/homeassistant/components/zwave/translations/ko.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "\uae30\uae30\uac00 \uc774\ubbf8 \uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4", - "single_instance_allowed": "\uc774\ubbf8 \uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ud558\ub098\uc758 \uc778\uc2a4\ud134\uc2a4\ub9cc \uad6c\uc131\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4." - }, - "error": { - "option_error": "Z-Wave \uc720\ud6a8\uc131 \uac80\uc0ac\uc5d0 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. USB \uc2a4\ud2f1\uc758 \uacbd\ub85c\uac00 \uc815\ud655\ud569\ub2c8\uae4c?" - }, - "step": { - "user": { - "data": { - "network_key": "\ub124\ud2b8\uc6cc\ud06c \ud0a4 (\uacf5\ub780\uc73c\ub85c \ube44\uc6cc\ub450\uba74 \uc790\ub3d9 \uc0dd\uc131\ud569\ub2c8\ub2e4)", - "usb_path": "USB \uc7a5\uce58 \uacbd\ub85c" - }, - "description": "\uc774 \ud1b5\ud569 \uad6c\uc131\uc694\uc18c\ub294 \ub354 \uc774\uc0c1 \uc9c0\uc6d0\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc0c8\ub85c\uc6b4 \uc124\uce58\uc758 \uacbd\uc6b0 Z-Wave JS \ub97c \uc0ac\uc6a9\ud574\uc8fc\uc138\uc694.\n\n\uad6c\uc131 \ubcc0\uc218\uc5d0 \ub300\ud55c \uc815\ubcf4\ub294 https://www.home-assistant.io/docs/z-wave/installation/ \uc744 \ucc38\uc870\ud574\uc8fc\uc138\uc694" - } - } - }, - "state": { - "_": { - "dead": "\uc751\ub2f5\uc5c6\uc74c", - "initializing": "\ucd08\uae30\ud654\uc911", - "ready": "\uc900\ube44", - "sleeping": "\uc808\uc804\ubaa8\ub4dc" - }, - "query_stage": { - "dead": "\uc751\ub2f5\uc5c6\uc74c", - "initializing": "\ucd08\uae30\ud654\uc911" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/lb.json b/homeassistant/components/zwave/translations/lb.json deleted file mode 100644 index e41d37b2025..00000000000 --- a/homeassistant/components/zwave/translations/lb.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Apparat ass scho konfigur\u00e9iert", - "single_instance_allowed": "Scho konfigur\u00e9iert. N\u00ebmmen eng eenzeg Konfiguratioun m\u00e9iglech." - }, - "error": { - "option_error": "Z-Wave Validatioun net g\u00eblteg. Ass de Pad zum USB Stick richteg?" - }, - "step": { - "user": { - "data": { - "network_key": "Netzwierk Schl\u00ebssel (eidel loossen fir een automatesch z'erstellen)", - "usb_path": "Pad zum USB Apparat" - }, - "description": "Lies op https://www.home-assistant.io/docs/z-wave/installation/ fir weider Informatiounen iwwert d'Konfiguratioun vun den Variabelen" - } - } - }, - "state": { - "_": { - "dead": "Doud", - "initializing": "Initialis\u00e9iert", - "ready": "Bereet", - "sleeping": "Schl\u00e9ift" - }, - "query_stage": { - "dead": "Doud", - "initializing": "Initialis\u00e9iert" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/lt.json b/homeassistant/components/zwave/translations/lt.json deleted file mode 100644 index a390b260a03..00000000000 --- a/homeassistant/components/zwave/translations/lt.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "state": { - "query_stage": { - "dead": " ({query_stage})", - "initializing": " ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/lv.json b/homeassistant/components/zwave/translations/lv.json deleted file mode 100644 index d759c7a9213..00000000000 --- a/homeassistant/components/zwave/translations/lv.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "Beigta", - "initializing": "Inicializ\u0113", - "ready": "Gatavs", - "sleeping": "Gu\u013c" - }, - "query_stage": { - "dead": "Beigta ({query_stage})", - "initializing": "Inicializ\u0113 ({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/nb.json b/homeassistant/components/zwave/translations/nb.json deleted file mode 100644 index 9dcd1e82788..00000000000 --- a/homeassistant/components/zwave/translations/nb.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "D\u00f8d", - "initializing": "Initialiserer", - "ready": "Klar", - "sleeping": "Sover" - }, - "query_stage": { - "dead": "D\u00f8d ({query_stage})", - "initializing": "Initialiserer ({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/nl.json b/homeassistant/components/zwave/translations/nl.json deleted file mode 100644 index d8c58fe784c..00000000000 --- a/homeassistant/components/zwave/translations/nl.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Apparaat is al geconfigureerd", - "single_instance_allowed": "Al geconfigureerd. Slechts \u00e9\u00e9n configuratie mogelijk." - }, - "error": { - "option_error": "Z-Wave-validatie mislukt. Is het pad naar de USB-stick correct?" - }, - "step": { - "user": { - "data": { - "network_key": "Netwerksleutel (laat leeg om automatisch te genereren)", - "usb_path": "USB-apparaatpad" - }, - "description": "Deze integratie wordt niet langer onderhouden. Voor nieuwe installaties, gebruik Z-Wave JS in plaats daarvan.\n\nZie https://www.home-assistant.io/docs/z-wave/installation/ voor informatie over de configuratievariabelen" - } - } - }, - "state": { - "_": { - "dead": "Onbereikbaar", - "initializing": "Initialiseren", - "ready": "Gereed", - "sleeping": "Slaapt" - }, - "query_stage": { - "dead": "Onbereikbaar", - "initializing": "Initialiseren" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/nn.json b/homeassistant/components/zwave/translations/nn.json deleted file mode 100644 index 76ff6120d81..00000000000 --- a/homeassistant/components/zwave/translations/nn.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "config": { - "step": { - "user": { - "description": "Sj\u00e5 [www.home-assistant.io/docs/z-wave/installation/](https://www.home-assistant.io/docs/z-wave/installation/) for informasjon om konfigurasjonsvariablene." - } - } - }, - "state": { - "_": { - "dead": "D\u00f8d", - "initializing": "Initialiserer", - "ready": "Klar", - "sleeping": "S\u00f8v" - }, - "query_stage": { - "dead": "D\u00f8d ({query_stage})", - "initializing": "Initialiserer ({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/no.json b/homeassistant/components/zwave/translations/no.json deleted file mode 100644 index 8582f906b57..00000000000 --- a/homeassistant/components/zwave/translations/no.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Enheten er allerede konfigurert", - "single_instance_allowed": "Allerede konfigurert. Bare \u00e9n enkelt konfigurasjon er mulig." - }, - "error": { - "option_error": "Z-Wave-validering mislyktes. Er banen til USB dongel riktig?" - }, - "step": { - "user": { - "data": { - "network_key": "Nettverksn\u00f8kkel (la v\u00e6re tom for automatisk oppretting)", - "usb_path": "USB enhetsbane" - }, - "description": "Denne integrasjonen opprettholdes ikke lenger. For nye installasjoner, bruk Z-Wave JS i stedet. \n\n Se https://www.home-assistant.io/docs/z-wave/installation/ for informasjon om konfigurasjonsvariablene" - } - } - }, - "state": { - "_": { - "dead": "D\u00f8d", - "initializing": "Initialiserer", - "ready": "Klar", - "sleeping": "Sover" - }, - "query_stage": { - "dead": "D\u00f8d", - "initializing": "Initialiserer" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/pl.json b/homeassistant/components/zwave/translations/pl.json deleted file mode 100644 index 9706fb1721f..00000000000 --- a/homeassistant/components/zwave/translations/pl.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Urz\u0105dzenie jest ju\u017c skonfigurowane", - "single_instance_allowed": "Ju\u017c skonfigurowano. Mo\u017cliwa jest tylko jedna konfiguracja." - }, - "error": { - "option_error": "Walidacja Z-Wave si\u0119 nie powiod\u0142a. Czy \u015bcie\u017cka do kontrolera Z-Wave USB jest prawid\u0142owa?" - }, - "step": { - "user": { - "data": { - "network_key": "Klucz sieciowy (pozostaw pusty, by generowa\u0107 automatycznie)", - "usb_path": "\u015acie\u017cka urz\u0105dzenia USB" - }, - "description": "Ta integracja nie jest ju\u017c wspierana. Dla nowych instalacji, u\u017cyj Z-Wave JS.\n\nPrzejd\u017a na https://www.home-assistant.io/docs/z-wave/installation/, aby uzyska\u0107 informacje na temat zmiennych konfiguracyjnych" - } - } - }, - "state": { - "_": { - "dead": "martwy", - "initializing": "inicjalizacja", - "ready": "gotowy", - "sleeping": "u\u015bpiony" - }, - "query_stage": { - "dead": "martwy", - "initializing": "inicjalizacja" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/pt-BR.json b/homeassistant/components/zwave/translations/pt-BR.json deleted file mode 100644 index 079f1ab8593..00000000000 --- a/homeassistant/components/zwave/translations/pt-BR.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Dispositivo j\u00e1 est\u00e1 configurado", - "single_instance_allowed": "J\u00e1 configurado. Apenas uma configura\u00e7\u00e3o \u00e9 poss\u00edvel." - }, - "error": { - "option_error": "A valida\u00e7\u00e3o Z-Wave falhou. O caminho para o USB est\u00e1 correto?" - }, - "step": { - "user": { - "data": { - "network_key": "Chave de rede (deixe em branco para gerar automaticamente)", - "usb_path": "Caminho do Dispositivo USB" - }, - "description": "Consulte https://www.home-assistant.io/docs/z-wave/installation/ para obter informa\u00e7\u00f5es sobre as vari\u00e1veis de configura\u00e7\u00e3o" - } - } - }, - "state": { - "_": { - "dead": "Morto", - "initializing": "Iniciando", - "ready": "Pronto", - "sleeping": "Dormindo" - }, - "query_stage": { - "dead": "Morto", - "initializing": "Iniciando" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/pt.json b/homeassistant/components/zwave/translations/pt.json deleted file mode 100644 index 27fc303f08b..00000000000 --- a/homeassistant/components/zwave/translations/pt.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "O Z-Wave j\u00e1 est\u00e1 configurado", - "single_instance_allowed": "J\u00e1 configurado. Apenas uma \u00fanica configura\u00e7\u00e3o \u00e9 poss\u00edvel." - }, - "error": { - "option_error": "A valida\u00e7\u00e3o Z-Wave falhou. O caminho para o dispositivo USB est\u00e1 correto?" - }, - "step": { - "user": { - "data": { - "network_key": "Network Key (deixe em branco para auto-gera\u00e7\u00e3o)", - "usb_path": "Endere\u00e7o USB" - }, - "description": "Consulte https://www.home-assistant.io/docs/z-wave/installation/ para obter informa\u00e7\u00f5es sobre as vari\u00e1veis de configura\u00e7\u00e3o" - } - } - }, - "state": { - "_": { - "dead": "Morto", - "initializing": "A inicializar", - "ready": "Pronto", - "sleeping": "Adormecido" - }, - "query_stage": { - "dead": "Morto ({query_stage})", - "initializing": "A inicializar ({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/ro.json b/homeassistant/components/zwave/translations/ro.json deleted file mode 100644 index de199bea03b..00000000000 --- a/homeassistant/components/zwave/translations/ro.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Z-Wave este deja configurat" - }, - "error": { - "option_error": "Validarea Z-Wave a e\u0219uat. Este corect\u0103 calea c\u0103tre stick-ul USB?" - }, - "step": { - "user": { - "data": { - "network_key": "Cheie de re\u021bea (l\u0103sa\u021bi necompletat pentru a genera automat)", - "usb_path": "Cale USB" - }, - "description": "Vede\u021bi https://www.home-assistant.io/docs/z-wave/installation/ pentru informa\u021bii despre variabilele de configurare" - } - } - }, - "state": { - "_": { - "dead": "Inactiv", - "initializing": "Se ini\u021bializeaz\u0103", - "ready": "Disponibil", - "sleeping": "Adormit" - }, - "query_stage": { - "dead": "Inactiv ({query_stage})", - "initializing": "Se ini\u021bializeaz\u0103 ({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/ru.json b/homeassistant/components/zwave/translations/ru.json deleted file mode 100644 index 7b7f0c6733d..00000000000 --- a/homeassistant/components/zwave/translations/ru.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "\u042d\u0442\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0443\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0432 Home Assistant.", - "single_instance_allowed": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e." - }, - "error": { - "option_error": "\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 Z-Wave. \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u043f\u0443\u0442\u044c \u043a USB-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0443." - }, - "step": { - "user": { - "data": { - "network_key": "\u041a\u043b\u044e\u0447 \u0441\u0435\u0442\u0438 (\u043e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u0443\u0441\u0442\u044b\u043c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438)", - "usb_path": "\u041f\u0443\u0442\u044c \u043a USB-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0443" - }, - "description": "\u042d\u0442\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u043e \u043d\u0435\u0451 Z-Wave JS.\n\n\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 [\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438](https://www.home-assistant.io/docs/z-wave/installation/) \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430." - } - } - }, - "state": { - "_": { - "dead": "\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u043e", - "initializing": "\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f", - "ready": "\u0413\u043e\u0442\u043e\u0432", - "sleeping": "\u0420\u0435\u0436\u0438\u043c \u0441\u043d\u0430" - }, - "query_stage": { - "dead": "\u041d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u043e", - "initializing": "\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/sk.json b/homeassistant/components/zwave/translations/sk.json deleted file mode 100644 index 9819295ee1f..00000000000 --- a/homeassistant/components/zwave/translations/sk.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Zariadenie u\u017e je nakonfigurovan\u00e9" - } - }, - "state": { - "_": { - "dead": "Nereaguje", - "initializing": "Inicializ\u00e1cia", - "ready": "Pripraven\u00e9", - "sleeping": "\u00dasporn\u00fd re\u017eim" - }, - "query_stage": { - "dead": "Nereaguje ({query_stage})", - "initializing": "Inicializ\u00e1cia ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/sl.json b/homeassistant/components/zwave/translations/sl.json deleted file mode 100644 index 38e70c59652..00000000000 --- a/homeassistant/components/zwave/translations/sl.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Z-Wave je \u017ee konfiguriran" - }, - "error": { - "option_error": "Potrjevanje Z-Wave ni uspelo. Ali je pot do USB klju\u010da pravilna?" - }, - "step": { - "user": { - "data": { - "network_key": "Omre\u017eni klju\u010d (pustite prazno za samodejno generiranje)", - "usb_path": "USB Pot" - }, - "description": "Za informacije o konfiguracijskih spremenljivka si oglejte https://www.home-assistant.io/docs/z-wave/installation/" - } - } - }, - "state": { - "_": { - "dead": "Mrtva", - "initializing": "Inicializacija", - "ready": "Pripravljen", - "sleeping": "Spi" - }, - "query_stage": { - "dead": "Mrtva", - "initializing": "Inicializacija" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/sr-Latn.json b/homeassistant/components/zwave/translations/sr-Latn.json deleted file mode 100644 index a390b260a03..00000000000 --- a/homeassistant/components/zwave/translations/sr-Latn.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "state": { - "query_stage": { - "dead": " ({query_stage})", - "initializing": " ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/sr.json b/homeassistant/components/zwave/translations/sr.json deleted file mode 100644 index 00727fbb694..00000000000 --- a/homeassistant/components/zwave/translations/sr.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "state": { - "_": { - "ready": "Spreman" - }, - "query_stage": { - "dead": " ({query_stage})", - "initializing": " ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/sv.json b/homeassistant/components/zwave/translations/sv.json deleted file mode 100644 index 6d3af30a057..00000000000 --- a/homeassistant/components/zwave/translations/sv.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Z-Wave \u00e4r redan konfigurerat" - }, - "error": { - "option_error": "Z-Wave-valideringen misslyckades. \u00c4r s\u00f6kv\u00e4gen till USB-minnet korrekt?" - }, - "step": { - "user": { - "data": { - "network_key": "N\u00e4tverksnyckel (l\u00e4mna blank f\u00f6r automatisk generering)", - "usb_path": "USB-s\u00f6kv\u00e4g" - }, - "description": "Se https://www.home-assistant.io/docs/z-wave/installation/ f\u00f6r information om konfigurationsvariabler" - } - } - }, - "state": { - "_": { - "dead": "D\u00f6d", - "initializing": "Initierar", - "ready": "Redo", - "sleeping": "Sovande" - }, - "query_stage": { - "dead": "D\u00f6d ({query_stage})", - "initializing": "Initierar ({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/ta.json b/homeassistant/components/zwave/translations/ta.json deleted file mode 100644 index 9b4fa65530c..00000000000 --- a/homeassistant/components/zwave/translations/ta.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "\u0b87\u0bb1\u0ba8\u0bcd\u0ba4\u0bc1\u0bb5\u0bbf\u0b9f\u0bcd\u0b9f\u0ba4\u0bc1", - "initializing": "\u0ba4\u0bc1\u0bb5\u0b95\u0bcd\u0b95\u0bc1\u0b95\u0bbf\u0bb1\u0ba4\u0bc1", - "ready": "\u0ba4\u0baf\u0bbe\u0bb0\u0bcd", - "sleeping": "\u0ba4\u0bc2\u0b99\u0bcd\u0b95\u0bc1\u0b95\u0bbf\u0ba9\u0bcd\u0bb1\u0ba4\u0bc1" - }, - "query_stage": { - "dead": "\u0b87\u0bb1\u0ba8\u0bcd\u0ba4\u0bc1\u0bb5\u0bbf\u0b9f\u0bcd\u0b9f\u0ba4\u0bc1 ({query_stage})", - "initializing": "\u0ba4\u0bc1\u0bb5\u0b95\u0bcd\u0b95\u0bc1\u0b95\u0bbf\u0bb1\u0ba4\u0bc1 ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/te.json b/homeassistant/components/zwave/translations/te.json deleted file mode 100644 index 88e4eac6961..00000000000 --- a/homeassistant/components/zwave/translations/te.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "\u0c2e\u0c43\u0c24 \u0c2a\u0c30\u0c3f\u0c15\u0c30\u0c02", - "initializing": "\u0c38\u0c3f\u0c26\u0c4d\u0c27\u0c02 \u0c05\u0c35\u0c41\u0c24\u0c4b\u0c02\u0c26\u0c3f", - "ready": "\u0c30\u0c46\u0c21\u0c40", - "sleeping": "\u0c28\u0c3f\u0c26\u0c4d\u0c30\u0c3f\u0c38\u0c4d\u0c24\u0c4b\u0c02\u0c26\u0c3f" - }, - "query_stage": { - "dead": "\u0c2e\u0c43\u0c24 \u0c2a\u0c30\u0c3f\u0c15\u0c30\u0c02 ({query_stage})", - "initializing": "\u0c38\u0c3f\u0c26\u0c4d\u0c27\u0c02 \u0c05\u0c35\u0c41\u0c24\u0c4b\u0c02\u0c26\u0c3f ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/th.json b/homeassistant/components/zwave/translations/th.json deleted file mode 100644 index 51db4f5b2e1..00000000000 --- a/homeassistant/components/zwave/translations/th.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "\u0e44\u0e21\u0e48\u0e1e\u0e23\u0e49\u0e2d\u0e21\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19", - "initializing": "\u0e01\u0e33\u0e25\u0e31\u0e07\u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e49\u0e19", - "ready": "\u0e1e\u0e23\u0e49\u0e2d\u0e21\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19", - "sleeping": "\u0e01\u0e33\u0e25\u0e31\u0e07\u0e2b\u0e25\u0e31\u0e1a" - }, - "query_stage": { - "dead": "\u0e44\u0e21\u0e48\u0e1e\u0e23\u0e49\u0e2d\u0e21\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19 ({query_stage})", - "initializing": "\u0e01\u0e33\u0e25\u0e31\u0e07\u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e49\u0e19 ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/tr.json b/homeassistant/components/zwave/translations/tr.json deleted file mode 100644 index b6afa368b6d..00000000000 --- a/homeassistant/components/zwave/translations/tr.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Cihaz zaten yap\u0131land\u0131r\u0131lm\u0131\u015f", - "single_instance_allowed": "Zaten yap\u0131land\u0131r\u0131lm\u0131\u015f. Yaln\u0131zca tek bir konfig\u00fcrasyon m\u00fcmk\u00fcnd\u00fcr." - }, - "error": { - "option_error": "Z-Wave do\u011frulamas\u0131 ba\u015far\u0131s\u0131z oldu. USB stickin yolu do\u011fru mu?" - }, - "step": { - "user": { - "data": { - "network_key": "A\u011f Anajtar\u0131 (otomatik \u00fcretilmesi i\u00e7in bo\u015f b\u0131rak\u0131n\u0131z)", - "usb_path": "USB Cihaz Yolu" - }, - "description": "Bu entegrasyon art\u0131k korunmuyor. Yeni kurulumlar i\u00e7in bunun yerine Z-Wave JS kullan\u0131n. \n\n Yap\u0131land\u0131rma de\u011fi\u015fkenleri hakk\u0131nda bilgi i\u00e7in https://www.home-assistant.io/docs/z-wave/installation/ adresine bak\u0131n." - } - } - }, - "state": { - "_": { - "dead": "\u00d6l\u00fc", - "initializing": "Ba\u015flat\u0131l\u0131yor", - "ready": "Haz\u0131r", - "sleeping": "Uyuyor" - }, - "query_stage": { - "dead": "\u00d6l\u00fc", - "initializing": "Ba\u015flat\u0131l\u0131yor" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/uk.json b/homeassistant/components/zwave/translations/uk.json deleted file mode 100644 index 3c5b49681c8..00000000000 --- a/homeassistant/components/zwave/translations/uk.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "\u0426\u0435\u0439 \u043f\u0440\u0438\u0441\u0442\u0440\u0456\u0439 \u0432\u0436\u0435 \u0434\u043e\u0434\u0430\u043d\u043e \u0432 Home Assistant.", - "single_instance_allowed": "\u0412\u0436\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u043e. \u041c\u043e\u0436\u043b\u0438\u0432\u0430 \u043b\u0438\u0448\u0435 \u043e\u0434\u043d\u0430 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044f." - }, - "error": { - "option_error": "\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 Z-Wave. \u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0448\u043b\u044f\u0445 \u0434\u043e USB-\u043f\u0440\u0438\u0441\u0442\u0440\u043e\u044e." - }, - "step": { - "user": { - "data": { - "network_key": "\u041a\u043b\u044e\u0447 \u043c\u0435\u0440\u0435\u0436\u0456 (\u0437\u0430\u043b\u0438\u0448\u0442\u0435 \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u043c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438)", - "usb_path": "\u0428\u043b\u044f\u0445 \u0434\u043e USB-\u043f\u0440\u0438\u0441\u0442\u0440\u043e\u044e" - }, - "description": "\u041e\u0437\u043d\u0430\u0439\u043e\u043c\u0442\u0435\u0441\u044f \u0437 [\u0456\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0456\u044f\u043c\u0438](https://www.home-assistant.io/docs/z-wave/installation/) \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u0431\u0456\u043b\u044c\u0448 \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u043f\u0440\u043e \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430." - } - } - }, - "state": { - "_": { - "dead": "\u041d\u0435\u0441\u043f\u0440\u0430\u0432\u043d\u0438\u0439", - "initializing": "\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f", - "ready": "\u0413\u043e\u0442\u043e\u0432\u0438\u0439", - "sleeping": "\u0420\u0435\u0436\u0438\u043c \u0441\u043d\u0443" - }, - "query_stage": { - "dead": "\u041d\u0435\u0441\u043f\u0440\u0430\u0432\u043d\u0438\u0439", - "initializing": "\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/vi.json b/homeassistant/components/zwave/translations/vi.json deleted file mode 100644 index 4055e09a8df..00000000000 --- a/homeassistant/components/zwave/translations/vi.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "state": { - "_": { - "dead": "\u0110\u00e3 t\u1eaft", - "initializing": "Kh\u1edfi t\u1ea1o", - "ready": "S\u1eb5n s\u00e0ng", - "sleeping": "Ng\u1ee7" - }, - "query_stage": { - "dead": "\u0110\u00e3 t\u1eaft ({query_stage})", - "initializing": "Kh\u1edfi t\u1ea1o ( {query_stage} )" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/zh-Hans.json b/homeassistant/components/zwave/translations/zh-Hans.json deleted file mode 100644 index 64af99e21ff..00000000000 --- a/homeassistant/components/zwave/translations/zh-Hans.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Z-Wave \u5df2\u914d\u7f6e\u5b8c\u6210" - }, - "error": { - "option_error": "Z-Wave \u9a8c\u8bc1\u5931\u8d25\u3002 USB \u68d2\u7684\u8def\u5f84\u662f\u5426\u6b63\u786e\uff1f" - }, - "step": { - "user": { - "data": { - "network_key": "\u7f51\u7edc\u5bc6\u94a5\uff08\u7559\u7a7a\u5c06\u81ea\u52a8\u751f\u6210\uff09", - "usb_path": "USB \u8def\u5f84" - }, - "description": "\u6709\u5173\u914d\u7f6e\u7684\u4fe1\u606f\uff0c\u8bf7\u53c2\u9605 https://www.home-assistant.io/docs/z-wave/installation/" - } - } - }, - "state": { - "_": { - "dead": "\u65ad\u5f00", - "initializing": "\u521d\u59cb\u5316", - "ready": "\u5c31\u7eea", - "sleeping": "\u4f11\u7720" - }, - "query_stage": { - "dead": "\u65ad\u5f00 ({query_stage})", - "initializing": "\u521d\u59cb\u5316 ({query_stage})" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/translations/zh-Hant.json b/homeassistant/components/zwave/translations/zh-Hant.json deleted file mode 100644 index 9dc8810f499..00000000000 --- a/homeassistant/components/zwave/translations/zh-Hant.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "\u88dd\u7f6e\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210", - "single_instance_allowed": "\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210\u3001\u50c5\u80fd\u8a2d\u5b9a\u4e00\u7d44\u88dd\u7f6e\u3002" - }, - "error": { - "option_error": "Z-Wave \u9a57\u8b49\u5931\u6557\uff0c\u8acb\u78ba\u5b9a USB \u96a8\u8eab\u789f\u8def\u5f91\u6b63\u78ba\uff1f" - }, - "step": { - "user": { - "data": { - "network_key": "\u7db2\u8def\u91d1\u9470\uff08\u4fdd\u7559\u7a7a\u767d\u5c07\u6703\u81ea\u52d5\u7522\u751f\uff09", - "usb_path": "USB \u88dd\u7f6e\u8def\u5f91" - }, - "description": "\u6b64\u6574\u5408\u5df2\u7d93\u4e0d\u518d\u9032\u884c\u7dad\u8b77\uff0c\u8acb\u4f7f\u7528 Z-Wave JS \u53d6\u4ee3\u70ba\u65b0\u5b89\u88dd\u65b9\u5f0f\u3002\n\n\u8acb\u53c3\u95b1 https://www.home-assistant.io/docs/z-wave/installation/ \u4ee5\n\u7372\u5f97\u8a2d\u5b9a\u8b8a\u6578\u8cc7\u8a0a" - } - } - }, - "state": { - "_": { - "dead": "\u5931\u53bb\u9023\u7dda", - "initializing": "\u6b63\u5728\u521d\u59cb\u5316", - "ready": "\u6e96\u5099\u5c31\u7dd2", - "sleeping": "\u4f11\u7720\u4e2d" - }, - "query_stage": { - "dead": "\u5931\u53bb\u9023\u7dda", - "initializing": "\u6b63\u5728\u521d\u59cb\u5316" - } - } -} \ No newline at end of file diff --git a/homeassistant/components/zwave/util.py b/homeassistant/components/zwave/util.py deleted file mode 100644 index 19be3f7a659..00000000000 --- a/homeassistant/components/zwave/util.py +++ /dev/null @@ -1,129 +0,0 @@ -"""Zwave util methods.""" -import asyncio -import logging - -import homeassistant.util.dt as dt_util - -from . import const - -_LOGGER = logging.getLogger(__name__) - - -def check_node_schema(node, schema): - """Check if node matches the passed node schema.""" - if const.DISC_NODE_ID in schema and node.node_id not in schema[const.DISC_NODE_ID]: - _LOGGER.debug( - "node.node_id %s not in node_id %s", - node.node_id, - schema[const.DISC_NODE_ID], - ) - return False - if ( - const.DISC_GENERIC_DEVICE_CLASS in schema - and node.generic not in schema[const.DISC_GENERIC_DEVICE_CLASS] - ): - _LOGGER.debug( - "node.generic %s not in generic_device_class %s", - node.generic, - schema[const.DISC_GENERIC_DEVICE_CLASS], - ) - return False - if ( - const.DISC_SPECIFIC_DEVICE_CLASS in schema - and node.specific not in schema[const.DISC_SPECIFIC_DEVICE_CLASS] - ): - _LOGGER.debug( - "node.specific %s not in specific_device_class %s", - node.specific, - schema[const.DISC_SPECIFIC_DEVICE_CLASS], - ) - return False - return True - - -def check_value_schema(value, schema): - """Check if the value matches the passed value schema.""" - if ( - const.DISC_COMMAND_CLASS in schema - and value.command_class not in schema[const.DISC_COMMAND_CLASS] - ): - _LOGGER.debug( - "value.command_class %s not in command_class %s", - value.command_class, - schema[const.DISC_COMMAND_CLASS], - ) - return False - if const.DISC_TYPE in schema and value.type not in schema[const.DISC_TYPE]: - _LOGGER.debug( - "value.type %s not in type %s", value.type, schema[const.DISC_TYPE] - ) - return False - if const.DISC_GENRE in schema and value.genre not in schema[const.DISC_GENRE]: - _LOGGER.debug( - "value.genre %s not in genre %s", value.genre, schema[const.DISC_GENRE] - ) - return False - if const.DISC_INDEX in schema and value.index not in schema[const.DISC_INDEX]: - _LOGGER.debug( - "value.index %s not in index %s", value.index, schema[const.DISC_INDEX] - ) - return False - if ( - const.DISC_INSTANCE in schema - and value.instance not in schema[const.DISC_INSTANCE] - ): - _LOGGER.debug( - "value.instance %s not in instance %s", - value.instance, - schema[const.DISC_INSTANCE], - ) - return False - if const.DISC_SCHEMAS in schema: - found = False - for schema_item in schema[const.DISC_SCHEMAS]: - found = found or check_value_schema(value, schema_item) - if not found: - return False - - return True - - -def compute_value_unique_id(node, value): - """Compute unique_id a value would get if it were to get one.""" - return f"{node.node_id}-{value.object_id}" - - -def node_name(node): - """Return the name of the node.""" - if is_node_parsed(node): - return node.name or f"{node.manufacturer_name} {node.product_name}" - return f"Unknown Node {node.node_id}" - - -def node_device_id_and_name(node, instance=1): - """Return the name and device ID for the value with the given index.""" - name = node_name(node) - if instance == 1: - return ((const.DOMAIN, node.node_id), name) - name = f"{name} ({instance})" - return ((const.DOMAIN, node.node_id, instance), name) - - -async def check_has_unique_id(entity, ready_callback, timeout_callback): - """Wait for entity to have unique_id.""" - start_time = dt_util.utcnow() - while True: - waited = int((dt_util.utcnow() - start_time).total_seconds()) - if entity.unique_id: - ready_callback(waited) - return - if waited >= const.NODE_READY_WAIT_SECS: - # Wait up to NODE_READY_WAIT_SECS seconds for unique_id to appear. - timeout_callback(waited) - return - await asyncio.sleep(1) - - -def is_node_parsed(node): - """Check whether the node has been parsed or still waiting to be parsed.""" - return bool((node.manufacturer_name and node.product_name) or node.name) diff --git a/homeassistant/components/zwave/websocket_api.py b/homeassistant/components/zwave/websocket_api.py deleted file mode 100644 index b86e46bee98..00000000000 --- a/homeassistant/components/zwave/websocket_api.py +++ /dev/null @@ -1,90 +0,0 @@ -"""Web socket API for Z-Wave.""" -import voluptuous as vol - -from homeassistant.components import websocket_api -from homeassistant.config_entries import SOURCE_IMPORT -from homeassistant.core import callback - -from .const import ( - CONF_AUTOHEAL, - CONF_DEBUG, - CONF_NETWORK_KEY, - CONF_POLLING_INTERVAL, - CONF_USB_STICK_PATH, - DATA_NETWORK, - DATA_ZWAVE_CONFIG, -) - -TYPE = "type" -ID = "id" - - -@websocket_api.require_admin -@websocket_api.websocket_command({vol.Required(TYPE): "zwave/network_status"}) -def websocket_network_status(hass, connection, msg): - """Get Z-Wave network status.""" - network = hass.data[DATA_NETWORK] - connection.send_result(msg[ID], {"state": network.state}) - - -@websocket_api.require_admin -@websocket_api.websocket_command({vol.Required(TYPE): "zwave/get_config"}) -def websocket_get_config(hass, connection, msg): - """Get Z-Wave configuration.""" - config = hass.data[DATA_ZWAVE_CONFIG] - connection.send_result( - msg[ID], - { - CONF_AUTOHEAL: config[CONF_AUTOHEAL], - CONF_DEBUG: config[CONF_DEBUG], - CONF_POLLING_INTERVAL: config[CONF_POLLING_INTERVAL], - CONF_USB_STICK_PATH: config[CONF_USB_STICK_PATH], - }, - ) - - -@websocket_api.require_admin -@websocket_api.websocket_command({vol.Required(TYPE): "zwave/get_migration_config"}) -def websocket_get_migration_config(hass, connection, msg): - """Get Z-Wave configuration for migration.""" - config = hass.data[DATA_ZWAVE_CONFIG] - connection.send_result( - msg[ID], - { - CONF_USB_STICK_PATH: config[CONF_USB_STICK_PATH], - CONF_NETWORK_KEY: config[CONF_NETWORK_KEY], - }, - ) - - -@websocket_api.require_admin -@websocket_api.websocket_command( - {vol.Required(TYPE): "zwave/start_zwave_js_config_flow"} -) -@websocket_api.async_response -async def websocket_start_zwave_js_config_flow(hass, connection, msg): - """Start the Z-Wave JS integration config flow (for migration wizard). - - Return data with the flow id of the started Z-Wave JS config flow. - """ - config = hass.data[DATA_ZWAVE_CONFIG] - data = { - "usb_path": config[CONF_USB_STICK_PATH], - "network_key": config[CONF_NETWORK_KEY], - } - result = await hass.config_entries.flow.async_init( - "zwave_js", context={"source": SOURCE_IMPORT}, data=data - ) - connection.send_result( - msg[ID], - {"flow_id": result["flow_id"]}, - ) - - -@callback -def async_load_websocket_api(hass): - """Set up the web socket API.""" - websocket_api.async_register_command(hass, websocket_network_status) - websocket_api.async_register_command(hass, websocket_get_config) - websocket_api.async_register_command(hass, websocket_get_migration_config) - websocket_api.async_register_command(hass, websocket_start_zwave_js_config_flow) diff --git a/homeassistant/components/zwave/workaround.py b/homeassistant/components/zwave/workaround.py deleted file mode 100644 index 9ef7cde446d..00000000000 --- a/homeassistant/components/zwave/workaround.py +++ /dev/null @@ -1,170 +0,0 @@ -"""Z-Wave workarounds.""" -from . import const - -# Manufacturers -FIBARO = 0x010F -GE = 0x0063 -PHILIO = 0x013C -SOMFY = 0x0047 -WENZHOU = 0x0118 -LEVITON = 0x001D - -# Product IDs -GE_FAN_CONTROLLER_12730 = 0x3034 -GE_FAN_CONTROLLER_14287 = 0x3131 -JASCO_FAN_CONTROLLER_14314 = 0x3138 -PHILIO_SLIM_SENSOR = 0x0002 -PHILIO_3_IN_1_SENSOR_GEN_4 = 0x000D -PHILIO_PAN07 = 0x0005 -VIZIA_FAN_CONTROLLER_VRF01 = 0x0334 -LEVITON_DECORA_FAN_CONTROLLER_ZW4SF = 0x0002 - -# Product Types -FGFS101_FLOOD_SENSOR_TYPE = 0x0B00 -FGRM222_SHUTTER2 = 0x0301 -FGR222_SHUTTER2 = 0x0302 -GE_DIMMER = 0x4944 -PHILIO_SWITCH = 0x0001 -PHILIO_SENSOR = 0x0002 -SOMFY_ZRTSI = 0x5A52 -VIZIA_DIMMER = 0x1001 -LEVITON_DECORA_FAN_CONTROLLER = 0x0038 - -# Mapping devices -PHILIO_SLIM_SENSOR_MOTION_MTII = (PHILIO, PHILIO_SENSOR, PHILIO_SLIM_SENSOR, 0) -PHILIO_3_IN_1_SENSOR_GEN_4_MOTION_MTII = ( - PHILIO, - PHILIO_SENSOR, - PHILIO_3_IN_1_SENSOR_GEN_4, - 0, -) -PHILIO_PAN07_MTI_INSTANCE = (PHILIO, PHILIO_SWITCH, PHILIO_PAN07, 1) -WENZHOU_SLIM_SENSOR_MOTION_MTII = (WENZHOU, PHILIO_SENSOR, PHILIO_SLIM_SENSOR, 0) - -# Workarounds -WORKAROUND_NO_OFF_EVENT = "trigger_no_off_event" -WORKAROUND_NO_POSITION = "workaround_no_position" -WORKAROUND_REFRESH_NODE_ON_UPDATE = "refresh_node_on_update" -WORKAROUND_IGNORE = "workaround_ignore" - -# List of workarounds by (manufacturer_id, product_type, product_id, index) -DEVICE_MAPPINGS_MTII = { - PHILIO_SLIM_SENSOR_MOTION_MTII: WORKAROUND_NO_OFF_EVENT, - PHILIO_3_IN_1_SENSOR_GEN_4_MOTION_MTII: WORKAROUND_NO_OFF_EVENT, - WENZHOU_SLIM_SENSOR_MOTION_MTII: WORKAROUND_NO_OFF_EVENT, -} - -# List of workarounds by (manufacturer_id, product_type, product_id, instance) -DEVICE_MAPPINGS_MTI_INSTANCE = { - PHILIO_PAN07_MTI_INSTANCE: WORKAROUND_REFRESH_NODE_ON_UPDATE -} - -SOMFY_ZRTSI_CONTROLLER_MT = (SOMFY, SOMFY_ZRTSI) - -# List of workarounds by (manufacturer_id, product_type) -DEVICE_MAPPINGS_MT = {SOMFY_ZRTSI_CONTROLLER_MT: WORKAROUND_NO_POSITION} - -# Component mapping devices -FIBARO_FGFS101_SENSOR_ALARM = ( - FIBARO, - FGFS101_FLOOD_SENSOR_TYPE, - const.COMMAND_CLASS_SENSOR_ALARM, -) -FIBARO_FGRM222_BINARY = (FIBARO, FGRM222_SHUTTER2, const.COMMAND_CLASS_SWITCH_BINARY) -FIBARO_FGR222_BINARY = (FIBARO, FGR222_SHUTTER2, const.COMMAND_CLASS_SWITCH_BINARY) -GE_FAN_CONTROLLER_12730_MULTILEVEL = ( - GE, - GE_DIMMER, - GE_FAN_CONTROLLER_12730, - const.COMMAND_CLASS_SWITCH_MULTILEVEL, -) -GE_FAN_CONTROLLER_14287_MULTILEVEL = ( - GE, - GE_DIMMER, - GE_FAN_CONTROLLER_14287, - const.COMMAND_CLASS_SWITCH_MULTILEVEL, -) -JASCO_FAN_CONTROLLER_14314_MULTILEVEL = ( - GE, - GE_DIMMER, - JASCO_FAN_CONTROLLER_14314, - const.COMMAND_CLASS_SWITCH_MULTILEVEL, -) -VIZIA_FAN_CONTROLLER_VRF01_MULTILEVEL = ( - LEVITON, - VIZIA_DIMMER, - VIZIA_FAN_CONTROLLER_VRF01, - const.COMMAND_CLASS_SWITCH_MULTILEVEL, -) -LEVITON_FAN_CONTROLLER_ZW4SF_MULTILEVEL = ( - LEVITON, - LEVITON_DECORA_FAN_CONTROLLER, - LEVITON_DECORA_FAN_CONTROLLER_ZW4SF, - const.COMMAND_CLASS_SWITCH_MULTILEVEL, -) - -# List of component workarounds by -# (manufacturer_id, product_type, command_class) -DEVICE_COMPONENT_MAPPING = { - FIBARO_FGFS101_SENSOR_ALARM: "binary_sensor", - FIBARO_FGRM222_BINARY: WORKAROUND_IGNORE, - FIBARO_FGR222_BINARY: WORKAROUND_IGNORE, -} - -# List of component workarounds by -# (manufacturer_id, product_type, product_id, command_class) -DEVICE_COMPONENT_MAPPING_MTI = { - GE_FAN_CONTROLLER_12730_MULTILEVEL: "fan", - GE_FAN_CONTROLLER_14287_MULTILEVEL: "fan", - JASCO_FAN_CONTROLLER_14314_MULTILEVEL: "fan", - VIZIA_FAN_CONTROLLER_VRF01_MULTILEVEL: "fan", - LEVITON_FAN_CONTROLLER_ZW4SF_MULTILEVEL: "fan", -} - - -def get_device_component_mapping(value): - """Get mapping of value to another component.""" - if value.node.manufacturer_id.strip() and value.node.product_type.strip(): - manufacturer_id = int(value.node.manufacturer_id, 16) - product_type = int(value.node.product_type, 16) - product_id = int(value.node.product_id, 16) - result = DEVICE_COMPONENT_MAPPING.get( - (manufacturer_id, product_type, value.command_class) - ) - if result: - return result - - result = DEVICE_COMPONENT_MAPPING_MTI.get( - (manufacturer_id, product_type, product_id, value.command_class) - ) - if result: - return result - - return None - - -def get_device_mapping(value): - """Get mapping of value to a workaround.""" - if ( - value.node.manufacturer_id.strip() - and value.node.product_id.strip() - and value.node.product_type.strip() - ): - manufacturer_id = int(value.node.manufacturer_id, 16) - product_type = int(value.node.product_type, 16) - product_id = int(value.node.product_id, 16) - result = DEVICE_MAPPINGS_MTII.get( - (manufacturer_id, product_type, product_id, value.index) - ) - if result: - return result - - result = DEVICE_MAPPINGS_MTI_INSTANCE.get( - (manufacturer_id, product_type, product_id, value.instance) - ) - if result: - return result - - return DEVICE_MAPPINGS_MT.get((manufacturer_id, product_type)) - - return None diff --git a/homeassistant/generated/config_flows.py b/homeassistant/generated/config_flows.py index 89cd4495326..a96acda5824 100644 --- a/homeassistant/generated/config_flows.py +++ b/homeassistant/generated/config_flows.py @@ -394,7 +394,6 @@ FLOWS = [ "youless", "zerproc", "zha", - "zwave", "zwave_js", "zwave_me" ] diff --git a/mypy.ini b/mypy.ini index 16bf8394eee..0cde5eda9a3 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2917,12 +2917,3 @@ ignore_errors = true [mypy-homeassistant.components.zha.switch] ignore_errors = true - -[mypy-homeassistant.components.zwave] -ignore_errors = true - -[mypy-homeassistant.components.zwave.migration] -ignore_errors = true - -[mypy-homeassistant.components.zwave.node_entity] -ignore_errors = true diff --git a/requirements_all.txt b/requirements_all.txt index ba4ec4536e5..52ad3feb66a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -811,9 +811,6 @@ holidays==0.13 # homeassistant.components.frontend home-assistant-frontend==20220317.0 -# homeassistant.components.zwave -# homeassistant-pyozw==0.1.10 - # homeassistant.components.home_connect homeconnect==0.7.0 @@ -1424,9 +1421,6 @@ pydelijn==1.0.0 # homeassistant.components.dexcom pydexcom==0.2.3 -# homeassistant.components.zwave -pydispatcher==2.0.5 - # homeassistant.components.doods pydoods==1.0.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index da1d72eb5e2..2c68b9fcbc4 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -561,9 +561,6 @@ holidays==0.13 # homeassistant.components.frontend home-assistant-frontend==20220317.0 -# homeassistant.components.zwave -# homeassistant-pyozw==0.1.10 - # homeassistant.components.home_connect homeconnect==0.7.0 @@ -931,9 +928,6 @@ pydeconz==87 # homeassistant.components.dexcom pydexcom==0.2.3 -# homeassistant.components.zwave -pydispatcher==2.0.5 - # homeassistant.components.econet pyeconet==0.1.15 diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index 9d5127a626b..896c87a2d80 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -23,7 +23,6 @@ COMMENT_REQUIREMENTS = ( "decora_wifi", "evdev", "face_recognition", - "homeassistant-pyozw", "opencv-python-headless", "pybluez", "pycups", diff --git a/script/hassfest/mypy_config.py b/script/hassfest/mypy_config.py index fcc03a35524..279e78fb44f 100644 --- a/script/hassfest/mypy_config.py +++ b/script/hassfest/mypy_config.py @@ -214,9 +214,6 @@ IGNORED_MODULES: Final[list[str]] = [ "homeassistant.components.zha.sensor", "homeassistant.components.zha.siren", "homeassistant.components.zha.switch", - "homeassistant.components.zwave", - "homeassistant.components.zwave.migration", - "homeassistant.components.zwave.node_entity", ] # Component modules which should set no_implicit_reexport = true. diff --git a/script/translations/migrate.py b/script/translations/migrate.py index c4c47600698..d3efdc28d13 100644 --- a/script/translations/migrate.py +++ b/script/translations/migrate.py @@ -237,7 +237,7 @@ STATE_REWRITE = { "[%key:state::lock::unlocked%]": "[%key:common::state::unlocked%]", } SKIP_DOMAIN = {"default", "scene"} -STATES_WITH_DEV_CLASS = {"binary_sensor", "zwave"} +STATES_WITH_DEV_CLASS = {"binary_sensor"} GROUP_DELETE = {"opening", "closing", "stopped"} # They don't exist diff --git a/tests/components/config/test_init.py b/tests/components/config/test_init.py index dd3e294bac3..2d5610cadfb 100644 --- a/tests/components/config/test_init.py +++ b/tests/components/config/test_init.py @@ -1,49 +1,8 @@ """Test config init.""" - -from unittest.mock import patch - -from homeassistant.components import config -from homeassistant.const import EVENT_COMPONENT_LOADED -from homeassistant.setup import ATTR_COMPONENT, async_setup_component - -from tests.common import mock_component +from homeassistant.setup import async_setup_component async def test_config_setup(hass, loop): """Test it sets up hassbian.""" await async_setup_component(hass, "config", {}) assert "config" in hass.config.components - - -async def test_load_on_demand_already_loaded(hass, aiohttp_client): - """Test getting suites.""" - mock_component(hass, "zwave") - - with patch.object(config, "SECTIONS", []), patch.object( - config, "ON_DEMAND", ["zwave"] - ), patch( - "homeassistant.components.config.zwave.async_setup", return_value=True - ) as stp: - - await async_setup_component(hass, "config", {}) - - await hass.async_block_till_done() - assert stp.called - - -async def test_load_on_demand_on_load(hass, aiohttp_client): - """Test getting suites.""" - with patch.object(config, "SECTIONS", []), patch.object( - config, "ON_DEMAND", ["zwave"] - ): - await async_setup_component(hass, "config", {}) - - assert "config.zwave" not in hass.config.components - - with patch( - "homeassistant.components.config.zwave.async_setup", return_value=True - ) as stp: - hass.bus.async_fire(EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: "zwave"}) - await hass.async_block_till_done() - - assert stp.called diff --git a/tests/components/config/test_zwave.py b/tests/components/config/test_zwave.py deleted file mode 100644 index bc7f22c104f..00000000000 --- a/tests/components/config/test_zwave.py +++ /dev/null @@ -1,542 +0,0 @@ -"""Test Z-Wave config panel.""" -from http import HTTPStatus -import json -from unittest.mock import MagicMock, patch - -import pytest - -from homeassistant.bootstrap import async_setup_component -from homeassistant.components import config -from homeassistant.components.zwave import DATA_NETWORK, const - -from tests.mock.zwave import MockEntityValues, MockNode, MockValue - -VIEW_NAME = "api:config:zwave:device_config" - - -@pytest.fixture -def client(loop, hass, hass_client): - """Client to communicate with Z-Wave config views.""" - with patch.object(config, "SECTIONS", ["zwave"]): - loop.run_until_complete(async_setup_component(hass, "config", {})) - - return loop.run_until_complete(hass_client()) - - -async def test_get_device_config(client): - """Test getting device config.""" - - def mock_read(path): - """Mock reading data.""" - return {"hello.beer": {"free": "beer"}, "other.entity": {"do": "something"}} - - with patch("homeassistant.components.config._read", mock_read): - resp = await client.get("/api/config/zwave/device_config/hello.beer") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - - assert result == {"free": "beer"} - - -async def test_update_device_config(client): - """Test updating device config.""" - orig_data = { - "hello.beer": {"ignored": True}, - "other.entity": {"polling_intensity": 2}, - } - - def mock_read(path): - """Mock reading data.""" - return orig_data - - written = [] - - def mock_write(path, data): - """Mock writing data.""" - written.append(data) - - with patch("homeassistant.components.config._read", mock_read), patch( - "homeassistant.components.config._write", mock_write - ): - resp = await client.post( - "/api/config/zwave/device_config/hello.beer", - data=json.dumps({"polling_intensity": 2}), - ) - - assert resp.status == HTTPStatus.OK - result = await resp.json() - assert result == {"result": "ok"} - - orig_data["hello.beer"]["polling_intensity"] = 2 - - assert written[0] == orig_data - - -async def test_update_device_config_invalid_key(client): - """Test updating device config.""" - resp = await client.post( - "/api/config/zwave/device_config/invalid_entity", - data=json.dumps({"polling_intensity": 2}), - ) - - assert resp.status == HTTPStatus.BAD_REQUEST - - -async def test_update_device_config_invalid_data(client): - """Test updating device config.""" - resp = await client.post( - "/api/config/zwave/device_config/hello.beer", - data=json.dumps({"invalid_option": 2}), - ) - - assert resp.status == HTTPStatus.BAD_REQUEST - - -async def test_update_device_config_invalid_json(client): - """Test updating device config.""" - resp = await client.post( - "/api/config/zwave/device_config/hello.beer", data="not json" - ) - - assert resp.status == HTTPStatus.BAD_REQUEST - - -async def test_get_values(hass, client): - """Test getting values on node.""" - node = MockNode(node_id=1) - value = MockValue( - value_id=123456, - node=node, - label="Test Label", - instance=1, - index=2, - poll_intensity=4, - ) - values = MockEntityValues(primary=value) - node2 = MockNode(node_id=2) - value2 = MockValue(value_id=234567, node=node2, label="Test Label 2") - values2 = MockEntityValues(primary=value2) - hass.data[const.DATA_ENTITY_VALUES] = [values, values2] - - resp = await client.get("/api/zwave/values/1") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - - assert result == { - "123456": { - "label": "Test Label", - "instance": 1, - "index": 2, - "poll_intensity": 4, - } - } - - -async def test_get_groups(hass, client): - """Test getting groupdata on node.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=2) - node.groups.associations = "assoc" - node.groups.associations_instances = "inst" - node.groups.label = "the label" - node.groups.max_associations = "max" - node.groups = {1: node.groups} - network.nodes = {2: node} - - resp = await client.get("/api/zwave/groups/2") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - - assert result == { - "1": { - "association_instances": "inst", - "associations": "assoc", - "label": "the label", - "max_associations": "max", - } - } - - -async def test_get_groups_nogroups(hass, client): - """Test getting groupdata on node with no groups.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=2) - - network.nodes = {2: node} - - resp = await client.get("/api/zwave/groups/2") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - - assert result == {} - - -async def test_get_groups_nonode(hass, client): - """Test getting groupdata on nonexisting node.""" - network = hass.data[DATA_NETWORK] = MagicMock() - network.nodes = {1: 1, 5: 5} - - resp = await client.get("/api/zwave/groups/2") - - assert resp.status == HTTPStatus.NOT_FOUND - result = await resp.json() - - assert result == {"message": "Node not found"} - - -async def test_get_config(hass, client): - """Test getting config on node.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=2) - value = MockValue(index=12, command_class=const.COMMAND_CLASS_CONFIGURATION) - value.label = "label" - value.help = "help" - value.type = "type" - value.data = "data" - value.data_items = ["item1", "item2"] - value.max = "max" - value.min = "min" - node.values = {12: value} - network.nodes = {2: node} - node.get_values.return_value = node.values - - resp = await client.get("/api/zwave/config/2") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - - assert result == { - "12": { - "data": "data", - "data_items": ["item1", "item2"], - "help": "help", - "label": "label", - "max": "max", - "min": "min", - "type": "type", - } - } - - -async def test_get_config_noconfig_node(hass, client): - """Test getting config on node without config.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=2) - - network.nodes = {2: node} - node.get_values.return_value = node.values - - resp = await client.get("/api/zwave/config/2") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - - assert result == {} - - -async def test_get_config_nonode(hass, client): - """Test getting config on nonexisting node.""" - network = hass.data[DATA_NETWORK] = MagicMock() - network.nodes = {1: 1, 5: 5} - - resp = await client.get("/api/zwave/config/2") - - assert resp.status == HTTPStatus.NOT_FOUND - result = await resp.json() - - assert result == {"message": "Node not found"} - - -async def test_get_usercodes_nonode(hass, client): - """Test getting usercodes on nonexisting node.""" - network = hass.data[DATA_NETWORK] = MagicMock() - network.nodes = {1: 1, 5: 5} - - resp = await client.get("/api/zwave/usercodes/2") - - assert resp.status == HTTPStatus.NOT_FOUND - result = await resp.json() - - assert result == {"message": "Node not found"} - - -async def test_get_usercodes(hass, client): - """Test getting usercodes on node.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_USER_CODE]) - value = MockValue(index=0, command_class=const.COMMAND_CLASS_USER_CODE) - value.genre = const.GENRE_USER - value.label = "label" - value.data = "1234" - node.values = {0: value} - network.nodes = {18: node} - node.get_values.return_value = node.values - - resp = await client.get("/api/zwave/usercodes/18") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - - assert result == {"0": {"code": "1234", "label": "label", "length": 4}} - - -async def test_get_usercode_nousercode_node(hass, client): - """Test getting usercodes on node without usercodes.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=18) - - network.nodes = {18: node} - node.get_values.return_value = node.values - - resp = await client.get("/api/zwave/usercodes/18") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - - assert result == {} - - -async def test_get_usercodes_no_genreuser(hass, client): - """Test getting usercodes on node missing genre user.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_USER_CODE]) - value = MockValue(index=0, command_class=const.COMMAND_CLASS_USER_CODE) - value.genre = const.GENRE_SYSTEM - value.label = "label" - value.data = "1234" - node.values = {0: value} - network.nodes = {18: node} - node.get_values.return_value = node.values - - resp = await client.get("/api/zwave/usercodes/18") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - - assert result == {} - - -async def test_save_config_no_network(hass, client): - """Test saving configuration without network data.""" - resp = await client.post("/api/zwave/saveconfig") - - assert resp.status == HTTPStatus.NOT_FOUND - result = await resp.json() - assert result == {"message": "No Z-Wave network data found"} - - -async def test_save_config(hass, client): - """Test saving configuration.""" - network = hass.data[DATA_NETWORK] = MagicMock() - - resp = await client.post("/api/zwave/saveconfig") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - assert network.write_config.called - assert result == {"message": "Z-Wave configuration saved to file"} - - -async def test_get_protection_values(hass, client): - """Test getting protection values on node.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_PROTECTION]) - value = MockValue( - value_id=123456, - index=0, - instance=1, - command_class=const.COMMAND_CLASS_PROTECTION, - ) - value.label = "Protection Test" - value.data_items = [ - "Unprotected", - "Protection by Sequence", - "No Operation Possible", - ] - value.data = "Unprotected" - network.nodes = {18: node} - node.value = value - - node.get_protection_item.return_value = "Unprotected" - node.get_protection_items.return_value = value.data_items - node.get_protections.return_value = {value.value_id: "Object"} - - resp = await client.get("/api/zwave/protection/18") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - assert node.get_protections.called - assert node.get_protection_item.called - assert node.get_protection_items.called - assert result == { - "value_id": "123456", - "selected": "Unprotected", - "options": ["Unprotected", "Protection by Sequence", "No Operation Possible"], - } - - -async def test_get_protection_values_nonexisting_node(hass, client): - """Test getting protection values on node with wrong nodeid.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_PROTECTION]) - value = MockValue( - value_id=123456, - index=0, - instance=1, - command_class=const.COMMAND_CLASS_PROTECTION, - ) - value.label = "Protection Test" - value.data_items = [ - "Unprotected", - "Protection by Sequence", - "No Operation Possible", - ] - value.data = "Unprotected" - network.nodes = {17: node} - node.value = value - - resp = await client.get("/api/zwave/protection/18") - - assert resp.status == HTTPStatus.NOT_FOUND - result = await resp.json() - assert not node.get_protections.called - assert not node.get_protection_item.called - assert not node.get_protection_items.called - assert result == {"message": "Node not found"} - - -async def test_get_protection_values_without_protectionclass(hass, client): - """Test getting protection values on node without protectionclass.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=18) - value = MockValue(value_id=123456, index=0, instance=1) - network.nodes = {18: node} - node.value = value - - resp = await client.get("/api/zwave/protection/18") - - assert resp.status == HTTPStatus.OK - result = await resp.json() - assert not node.get_protections.called - assert not node.get_protection_item.called - assert not node.get_protection_items.called - assert result == {} - - -async def test_set_protection_value(hass, client): - """Test setting protection value on node.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_PROTECTION]) - value = MockValue( - value_id=123456, - index=0, - instance=1, - command_class=const.COMMAND_CLASS_PROTECTION, - ) - value.label = "Protection Test" - value.data_items = [ - "Unprotected", - "Protection by Sequence", - "No Operation Possible", - ] - value.data = "Unprotected" - network.nodes = {18: node} - node.value = value - - resp = await client.post( - "/api/zwave/protection/18", - data=json.dumps({"value_id": "123456", "selection": "Protection by Sequence"}), - ) - - assert resp.status == HTTPStatus.OK - result = await resp.json() - assert node.set_protection.called - assert result == {"message": "Protection setting successfully set"} - - -async def test_set_protection_value_failed(hass, client): - """Test setting protection value failed on node.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_PROTECTION]) - value = MockValue( - value_id=123456, - index=0, - instance=1, - command_class=const.COMMAND_CLASS_PROTECTION, - ) - value.label = "Protection Test" - value.data_items = [ - "Unprotected", - "Protection by Sequence", - "No Operation Possible", - ] - value.data = "Unprotected" - network.nodes = {18: node} - node.value = value - node.set_protection.return_value = False - - resp = await client.post( - "/api/zwave/protection/18", - data=json.dumps({"value_id": "123456", "selection": "Protecton by Sequence"}), - ) - - assert resp.status == HTTPStatus.ACCEPTED - result = await resp.json() - assert node.set_protection.called - assert result == {"message": "Protection setting did not complete"} - - -async def test_set_protection_value_nonexisting_node(hass, client): - """Test setting protection value on nonexisting node.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=17, command_classes=[const.COMMAND_CLASS_PROTECTION]) - value = MockValue( - value_id=123456, - index=0, - instance=1, - command_class=const.COMMAND_CLASS_PROTECTION, - ) - value.label = "Protection Test" - value.data_items = [ - "Unprotected", - "Protection by Sequence", - "No Operation Possible", - ] - value.data = "Unprotected" - network.nodes = {17: node} - node.value = value - node.set_protection.return_value = False - - resp = await client.post( - "/api/zwave/protection/18", - data=json.dumps({"value_id": "123456", "selection": "Protecton by Sequence"}), - ) - - assert resp.status == HTTPStatus.NOT_FOUND - result = await resp.json() - assert not node.set_protection.called - assert result == {"message": "Node not found"} - - -async def test_set_protection_value_missing_class(hass, client): - """Test setting protection value on node without protectionclass.""" - network = hass.data[DATA_NETWORK] = MagicMock() - node = MockNode(node_id=17) - value = MockValue(value_id=123456, index=0, instance=1) - network.nodes = {17: node} - node.value = value - node.set_protection.return_value = False - - resp = await client.post( - "/api/zwave/protection/17", - data=json.dumps({"value_id": "123456", "selection": "Protecton by Sequence"}), - ) - - assert resp.status == HTTPStatus.NOT_FOUND - result = await resp.json() - assert not node.set_protection.called - assert result == {"message": "No protection commandclass on this node"} diff --git a/tests/components/zwave/__init__.py b/tests/components/zwave/__init__.py deleted file mode 100644 index 996bbf22b69..00000000000 --- a/tests/components/zwave/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Tests for the Z-Wave component.""" diff --git a/tests/components/zwave/conftest.py b/tests/components/zwave/conftest.py deleted file mode 100644 index 027d3a82ea2..00000000000 --- a/tests/components/zwave/conftest.py +++ /dev/null @@ -1,80 +0,0 @@ -"""Fixtures for Z-Wave tests.""" -from unittest.mock import AsyncMock, MagicMock, patch - -import pytest - -from homeassistant.components.zwave import const - -from tests.components.light.conftest import mock_light_profiles # noqa: F401 -from tests.mock.zwave import MockNetwork, MockNode, MockOption, MockValue - - -@pytest.fixture -def mock_openzwave(): - """Mock out Open Z-Wave.""" - base_mock = MagicMock() - libopenzwave = base_mock.libopenzwave - libopenzwave.__file__ = "test" - base_mock.network.ZWaveNetwork = MockNetwork - base_mock.option.ZWaveOption = MockOption - - with patch.dict( - "sys.modules", - { - "libopenzwave": libopenzwave, - "openzwave.option": base_mock.option, - "openzwave.network": base_mock.network, - "openzwave.group": base_mock.group, - }, - ): - yield base_mock - - -@pytest.fixture -def mock_discovery(): - """Mock discovery.""" - discovery = MagicMock() - discovery.async_load_platform = AsyncMock(return_value=None) - yield discovery - - -@pytest.fixture -def mock_import_module(): - """Mock import module.""" - platform = MagicMock() - mock_device = MagicMock() - mock_device.name = "test_device" - platform.get_device.return_value = mock_device - - import_module = MagicMock() - import_module.return_value = platform - yield import_module - - -@pytest.fixture -def mock_values(): - """Mock values.""" - node = MockNode() - mock_schema = { - const.DISC_COMPONENT: "mock_component", - const.DISC_VALUES: { - const.DISC_PRIMARY: {const.DISC_COMMAND_CLASS: ["mock_primary_class"]}, - "secondary": {const.DISC_COMMAND_CLASS: ["mock_secondary_class"]}, - "optional": { - const.DISC_COMMAND_CLASS: ["mock_optional_class"], - const.DISC_OPTIONAL: True, - }, - }, - } - value_class = MagicMock() - value_class.primary = MockValue( - command_class="mock_primary_class", node=node, value_id=1000 - ) - value_class.secondary = MockValue(command_class="mock_secondary_class", node=node) - value_class.duplicate_secondary = MockValue( - command_class="mock_secondary_class", node=node - ) - value_class.optional = MockValue(command_class="mock_optional_class", node=node) - value_class.no_match_value = MockValue(command_class="mock_bad_class", node=node) - - yield (node, value_class, mock_schema) diff --git a/tests/components/zwave/test_binary_sensor.py b/tests/components/zwave/test_binary_sensor.py deleted file mode 100644 index 265ec6f2d1e..00000000000 --- a/tests/components/zwave/test_binary_sensor.py +++ /dev/null @@ -1,103 +0,0 @@ -"""Test Z-Wave binary sensors.""" -import datetime -from unittest.mock import patch - -import pytest - -from homeassistant.components.zwave import binary_sensor, const - -from tests.mock.zwave import MockEntityValues, MockNode, MockValue, value_changed - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -def test_get_device_detects_none(mock_openzwave): - """Test device is not returned.""" - node = MockNode() - value = MockValue(data=False, node=node) - values = MockEntityValues(primary=value) - - device = binary_sensor.get_device(node=node, values=values, node_config={}) - assert device is None - - -def test_get_device_detects_trigger_sensor(mock_openzwave): - """Test device is a trigger sensor.""" - node = MockNode(manufacturer_id="013c", product_type="0002", product_id="0002") - value = MockValue(data=False, node=node) - values = MockEntityValues(primary=value) - - device = binary_sensor.get_device(node=node, values=values, node_config={}) - assert isinstance(device, binary_sensor.ZWaveTriggerSensor) - assert device.device_class == "motion" - - -def test_get_device_detects_workaround_sensor(mock_openzwave): - """Test that workaround returns a binary sensor.""" - node = MockNode(manufacturer_id="010f", product_type="0b00") - value = MockValue( - data=False, node=node, command_class=const.COMMAND_CLASS_SENSOR_ALARM - ) - values = MockEntityValues(primary=value) - - device = binary_sensor.get_device(node=node, values=values, node_config={}) - assert isinstance(device, binary_sensor.ZWaveBinarySensor) - - -def test_get_device_detects_sensor(mock_openzwave): - """Test that device returns a binary sensor.""" - node = MockNode() - value = MockValue( - data=False, node=node, command_class=const.COMMAND_CLASS_SENSOR_BINARY - ) - values = MockEntityValues(primary=value) - - device = binary_sensor.get_device(node=node, values=values, node_config={}) - assert isinstance(device, binary_sensor.ZWaveBinarySensor) - - -def test_binary_sensor_value_changed(mock_openzwave): - """Test value changed for binary sensor.""" - node = MockNode() - value = MockValue( - data=False, node=node, command_class=const.COMMAND_CLASS_SENSOR_BINARY - ) - values = MockEntityValues(primary=value) - device = binary_sensor.get_device(node=node, values=values, node_config={}) - - assert not device.is_on - - value.data = True - value_changed(value) - - assert device.is_on - - -async def test_trigger_sensor_value_changed(hass, mock_openzwave): - """Test value changed for trigger sensor.""" - node = MockNode(manufacturer_id="013c", product_type="0002", product_id="0002") - value = MockValue(data=False, node=node) - value_off_delay = MockValue(data=15, node=node) - values = MockEntityValues(primary=value, off_delay=value_off_delay) - device = binary_sensor.get_device(node=node, values=values, node_config={}) - - assert not device.is_on - - value.data = True - await hass.async_add_executor_job(value_changed, value) - assert device.invalidate_after is None - - device.hass = hass - - value.data = True - await hass.async_add_executor_job(value_changed, value) - assert device.is_on - - test_time = device.invalidate_after - datetime.timedelta(seconds=1) - with patch("homeassistant.util.dt.utcnow", return_value=test_time): - assert device.is_on - - test_time = device.invalidate_after - with patch("homeassistant.util.dt.utcnow", return_value=test_time): - assert not device.is_on diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py deleted file mode 100644 index a9ad182c4b1..00000000000 --- a/tests/components/zwave/test_climate.py +++ /dev/null @@ -1,893 +0,0 @@ -"""Test Z-Wave climate devices.""" -import pytest - -from homeassistant.components.climate.const import ( - ATTR_TARGET_TEMP_HIGH, - ATTR_TARGET_TEMP_LOW, - CURRENT_HVAC_COOL, - CURRENT_HVAC_HEAT, - HVAC_MODE_COOL, - HVAC_MODE_HEAT, - HVAC_MODE_HEAT_COOL, - HVAC_MODE_OFF, - HVAC_MODES, - PRESET_AWAY, - PRESET_BOOST, - PRESET_ECO, - PRESET_NONE, - SUPPORT_AUX_HEAT, - SUPPORT_FAN_MODE, - SUPPORT_PRESET_MODE, - SUPPORT_SWING_MODE, - SUPPORT_TARGET_TEMPERATURE, - SUPPORT_TARGET_TEMPERATURE_RANGE, -) -from homeassistant.components.zwave import climate, const -from homeassistant.components.zwave.climate import ( - AUX_HEAT_ZWAVE_MODE, - DEFAULT_HVAC_MODES, -) -from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT - -from tests.mock.zwave import MockEntityValues, MockNode, MockValue, value_changed - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -@pytest.fixture -def device(hass, mock_openzwave): - """Fixture to provide a precreated climate device.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_MODE, - data=HVAC_MODE_HEAT, - data_items=[ - HVAC_MODE_OFF, - HVAC_MODE_HEAT, - HVAC_MODE_COOL, - HVAC_MODE_HEAT_COOL, - ], - node=node, - ), - setpoint_heating=MockValue(data=1, node=node), - setpoint_cooling=MockValue(data=10, node=node), - temperature=MockValue(data=5, node=node, units=None), - fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), - operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), - fan_action=MockValue(data=7, node=node), - ) - device = climate.get_device(hass, node=node, values=values, node_config={}) - - yield device - - -@pytest.fixture -def device_zxt_120(hass, mock_openzwave): - """Fixture to provide a precreated climate device.""" - node = MockNode(manufacturer_id="5254", product_id="8377") - - values = MockEntityValues( - primary=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_MODE, - data=HVAC_MODE_HEAT, - data_items=[ - HVAC_MODE_OFF, - HVAC_MODE_HEAT, - HVAC_MODE_COOL, - HVAC_MODE_HEAT_COOL, - ], - node=node, - ), - setpoint_heating=MockValue(data=1, node=node), - setpoint_cooling=MockValue(data=10, node=node), - temperature=MockValue(data=5, node=node, units=None), - fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), - operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), - fan_action=MockValue(data=7, node=node), - zxt_120_swing_mode=MockValue(data="test3", data_items=[6, 7, 8], node=node), - ) - device = climate.get_device(hass, node=node, values=values, node_config={}) - - yield device - - -@pytest.fixture -def device_mapping(hass, mock_openzwave): - """Fixture to provide a precreated climate device. Test state mapping.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_MODE, - data="Heat", - data_items=["Off", "Cool", "Heat", "Full Power", "Auto"], - node=node, - ), - setpoint_heating=MockValue(data=1, node=node), - setpoint_cooling=MockValue(data=10, node=node), - temperature=MockValue(data=5, node=node, units=None), - fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), - operating_state=MockValue(data="heating", node=node), - fan_action=MockValue(data=7, node=node), - ) - device = climate.get_device(hass, node=node, values=values, node_config={}) - - yield device - - -@pytest.fixture -def device_unknown(hass, mock_openzwave): - """Fixture to provide a precreated climate device. Test state unknown.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_MODE, - data="Heat", - data_items=["Off", "Cool", "Heat", "heat_cool", "Abcdefg"], - node=node, - ), - setpoint_heating=MockValue(data=1, node=node), - setpoint_cooling=MockValue(data=10, node=node), - temperature=MockValue(data=5, node=node, units=None), - fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), - operating_state=MockValue(data="test4", node=node), - fan_action=MockValue(data=7, node=node), - ) - device = climate.get_device(hass, node=node, values=values, node_config={}) - - yield device - - -@pytest.fixture -def device_heat_cool(hass, mock_openzwave): - """Fixture to provide a precreated climate device. Test state heat only.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_MODE, - data=HVAC_MODE_HEAT, - data_items=[ - HVAC_MODE_OFF, - HVAC_MODE_HEAT, - HVAC_MODE_COOL, - "Heat Eco", - "Cool Eco", - ], - node=node, - ), - setpoint_heating=MockValue(data=1, node=node), - setpoint_cooling=MockValue(data=10, node=node), - temperature=MockValue(data=5, node=node, units=None), - fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), - operating_state=MockValue(data="test4", node=node), - fan_action=MockValue(data=7, node=node), - ) - device = climate.get_device(hass, node=node, values=values, node_config={}) - - yield device - - -@pytest.fixture -def device_heat_cool_range(hass, mock_openzwave): - """Fixture to provide a precreated climate device. Target range mode.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_MODE, - data=HVAC_MODE_HEAT_COOL, - data_items=[ - HVAC_MODE_OFF, - HVAC_MODE_HEAT, - HVAC_MODE_COOL, - HVAC_MODE_HEAT_COOL, - ], - node=node, - ), - setpoint_heating=MockValue(data=1, node=node), - setpoint_cooling=MockValue(data=10, node=node), - temperature=MockValue(data=5, node=node, units=None), - fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), - operating_state=MockValue(data="test4", node=node), - fan_action=MockValue(data=7, node=node), - ) - device = climate.get_device(hass, node=node, values=values, node_config={}) - - yield device - - -@pytest.fixture -def device_heat_cool_away(hass, mock_openzwave): - """Fixture to provide a precreated climate device. Target range mode.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_MODE, - data=HVAC_MODE_HEAT_COOL, - data_items=[ - HVAC_MODE_OFF, - HVAC_MODE_HEAT, - HVAC_MODE_COOL, - HVAC_MODE_HEAT_COOL, - PRESET_AWAY, - ], - node=node, - ), - setpoint_heating=MockValue(data=2, node=node), - setpoint_cooling=MockValue(data=9, node=node), - setpoint_away_heating=MockValue(data=1, node=node), - setpoint_away_cooling=MockValue(data=10, node=node), - temperature=MockValue(data=5, node=node, units=None), - fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), - operating_state=MockValue(data="test4", node=node), - fan_action=MockValue(data=7, node=node), - ) - device = climate.get_device(hass, node=node, values=values, node_config={}) - - yield device - - -@pytest.fixture -def device_heat_eco(hass, mock_openzwave): - """Fixture to provide a precreated climate device. heat/heat eco.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_MODE, - data=HVAC_MODE_HEAT, - data_items=[HVAC_MODE_OFF, HVAC_MODE_HEAT, "heat econ"], - node=node, - ), - setpoint_heating=MockValue(data=2, node=node), - setpoint_eco_heating=MockValue(data=1, node=node), - temperature=MockValue(data=5, node=node, units=None), - fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), - operating_state=MockValue(data="test4", node=node), - fan_action=MockValue(data=7, node=node), - ) - device = climate.get_device(hass, node=node, values=values, node_config={}) - - yield device - - -@pytest.fixture -def device_aux_heat(hass, mock_openzwave): - """Fixture to provide a precreated climate device. aux heat.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_MODE, - data=HVAC_MODE_HEAT, - data_items=[HVAC_MODE_OFF, HVAC_MODE_HEAT, "Aux Heat"], - node=node, - ), - setpoint_heating=MockValue(data=2, node=node), - setpoint_eco_heating=MockValue(data=1, node=node), - temperature=MockValue(data=5, node=node, units=None), - fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), - operating_state=MockValue(data="test4", node=node), - fan_action=MockValue(data=7, node=node), - ) - device = climate.get_device(hass, node=node, values=values, node_config={}) - - yield device - - -@pytest.fixture -def device_single_setpoint(hass, mock_openzwave): - """Fixture to provide a precreated climate device. - - SETPOINT_THERMOSTAT device class. - """ - - node = MockNode() - values = MockEntityValues( - primary=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_SETPOINT, data=1, node=node - ), - mode=None, - temperature=MockValue(data=5, node=node, units=None), - fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), - operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), - fan_action=MockValue(data=7, node=node), - ) - device = climate.get_device(hass, node=node, values=values, node_config={}) - - yield device - - -@pytest.fixture -def device_single_setpoint_with_mode(hass, mock_openzwave): - """Fixture to provide a precreated climate device. - - SETPOINT_THERMOSTAT device class with COMMAND_CLASS_THERMOSTAT_MODE command class - """ - - node = MockNode() - values = MockEntityValues( - primary=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_SETPOINT, data=1, node=node - ), - mode=MockValue( - command_class=const.COMMAND_CLASS_THERMOSTAT_MODE, - data=HVAC_MODE_HEAT, - data_items=[HVAC_MODE_OFF, HVAC_MODE_HEAT], - node=node, - ), - temperature=MockValue(data=5, node=node, units=None), - fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), - operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), - fan_action=MockValue(data=7, node=node), - ) - device = climate.get_device(hass, node=node, values=values, node_config={}) - - yield device - - -def test_get_device_detects_none(hass, mock_openzwave): - """Test get_device returns None.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockEntityValues(primary=value) - - device = climate.get_device(hass, node=node, values=values, node_config={}) - assert device is None - - -def test_get_device_detects_multiple_setpoint_device(device): - """Test get_device returns a Z-Wave multiple setpoint device.""" - assert isinstance(device, climate.ZWaveClimateMultipleSetpoint) - - -def test_get_device_detects_single_setpoint_device(device_single_setpoint): - """Test get_device returns a Z-Wave single setpoint device.""" - assert isinstance(device_single_setpoint, climate.ZWaveClimateSingleSetpoint) - - -def test_default_hvac_modes(): - """Test whether all hvac modes are included in default_hvac_modes.""" - for hvac_mode in HVAC_MODES: - assert hvac_mode in DEFAULT_HVAC_MODES - - -def test_supported_features(device): - """Test supported features flags.""" - assert ( - device.supported_features - == SUPPORT_FAN_MODE - + SUPPORT_TARGET_TEMPERATURE - + SUPPORT_TARGET_TEMPERATURE_RANGE - ) - - -def test_supported_features_temp_range(device_heat_cool_range): - """Test supported features flags with target temp range.""" - device = device_heat_cool_range - assert ( - device.supported_features - == SUPPORT_FAN_MODE - + SUPPORT_TARGET_TEMPERATURE - + SUPPORT_TARGET_TEMPERATURE_RANGE - ) - - -def test_supported_features_preset_mode(device_mapping): - """Test supported features flags with swing mode.""" - device = device_mapping - assert ( - device.supported_features - == SUPPORT_FAN_MODE - + SUPPORT_TARGET_TEMPERATURE - + SUPPORT_TARGET_TEMPERATURE_RANGE - + SUPPORT_PRESET_MODE - ) - - -def test_supported_features_preset_mode_away(device_heat_cool_away): - """Test supported features flags with swing mode.""" - device = device_heat_cool_away - assert ( - device.supported_features - == SUPPORT_FAN_MODE - + SUPPORT_TARGET_TEMPERATURE - + SUPPORT_TARGET_TEMPERATURE_RANGE - + SUPPORT_PRESET_MODE - ) - - -def test_supported_features_swing_mode(device_zxt_120): - """Test supported features flags with swing mode.""" - device = device_zxt_120 - assert ( - device.supported_features - == SUPPORT_FAN_MODE - + SUPPORT_TARGET_TEMPERATURE - + SUPPORT_TARGET_TEMPERATURE_RANGE - + SUPPORT_SWING_MODE - ) - - -def test_supported_features_aux_heat(device_aux_heat): - """Test supported features flags with aux heat.""" - device = device_aux_heat - assert ( - device.supported_features - == SUPPORT_FAN_MODE + SUPPORT_TARGET_TEMPERATURE + SUPPORT_AUX_HEAT - ) - - -def test_supported_features_single_setpoint(device_single_setpoint): - """Test supported features flags for SETPOINT_THERMOSTAT.""" - device = device_single_setpoint - assert device.supported_features == SUPPORT_FAN_MODE + SUPPORT_TARGET_TEMPERATURE - - -def test_supported_features_single_setpoint_with_mode(device_single_setpoint_with_mode): - """Test supported features flags for SETPOINT_THERMOSTAT.""" - device = device_single_setpoint_with_mode - assert device.supported_features == SUPPORT_FAN_MODE + SUPPORT_TARGET_TEMPERATURE - - -def test_zxt_120_swing_mode(device_zxt_120): - """Test operation of the zxt 120 swing mode.""" - device = device_zxt_120 - - assert device.swing_modes == [6, 7, 8] - assert device._zxt_120 == 1 - - # Test set mode - assert device.values.zxt_120_swing_mode.data == "test3" - device.set_swing_mode("test_swing_set") - assert device.values.zxt_120_swing_mode.data == "test_swing_set" - - # Test mode changed - value_changed(device.values.zxt_120_swing_mode) - assert device.swing_mode == "test_swing_set" - device.values.zxt_120_swing_mode.data = "test_swing_updated" - value_changed(device.values.zxt_120_swing_mode) - assert device.swing_mode == "test_swing_updated" - - -def test_temperature_unit(device): - """Test temperature unit.""" - assert device.temperature_unit == TEMP_CELSIUS - device.values.temperature.units = "F" - value_changed(device.values.temperature) - assert device.temperature_unit == TEMP_FAHRENHEIT - device.values.temperature.units = "C" - value_changed(device.values.temperature) - assert device.temperature_unit == TEMP_CELSIUS - - -def test_data_lists(device): - """Test data lists from zwave value items.""" - assert device.fan_modes == [3, 4, 5] - assert device.hvac_modes == [ - HVAC_MODE_OFF, - HVAC_MODE_HEAT, - HVAC_MODE_COOL, - HVAC_MODE_HEAT_COOL, - ] - assert device.preset_modes == [] - device.values.primary = None - assert device.preset_modes == [] - - -def test_data_lists_single_setpoint(device_single_setpoint): - """Test data lists from zwave value items.""" - device = device_single_setpoint - assert device.fan_modes == [3, 4, 5] - assert device.hvac_modes == [] - assert device.preset_modes == [] - - -def test_data_lists_single_setpoint_with_mode(device_single_setpoint_with_mode): - """Test data lists from zwave value items.""" - device = device_single_setpoint_with_mode - assert device.fan_modes == [3, 4, 5] - assert device.hvac_modes == [HVAC_MODE_OFF, HVAC_MODE_HEAT] - assert device.preset_modes == [] - - -def test_data_lists_mapping(device_mapping): - """Test data lists from zwave value items.""" - device = device_mapping - assert device.hvac_modes == ["off", "cool", "heat", "heat_cool"] - assert device.preset_modes == ["boost", "none"] - device.values.primary = None - assert device.preset_modes == [] - - -def test_target_value_set(device): - """Test values changed for climate device.""" - assert device.values.setpoint_heating.data == 1 - assert device.values.setpoint_cooling.data == 10 - device.set_temperature() - assert device.values.setpoint_heating.data == 1 - assert device.values.setpoint_cooling.data == 10 - device.set_temperature(**{ATTR_TEMPERATURE: 2}) - assert device.values.setpoint_heating.data == 2 - assert device.values.setpoint_cooling.data == 10 - device.set_hvac_mode(HVAC_MODE_COOL) - value_changed(device.values.primary) - assert device.values.setpoint_heating.data == 2 - assert device.values.setpoint_cooling.data == 10 - device.set_temperature(**{ATTR_TEMPERATURE: 9}) - assert device.values.setpoint_heating.data == 2 - assert device.values.setpoint_cooling.data == 9 - - -def test_target_value_set_range(device_heat_cool_range): - """Test values changed for climate device.""" - device = device_heat_cool_range - assert device.values.setpoint_heating.data == 1 - assert device.values.setpoint_cooling.data == 10 - device.set_temperature() - assert device.values.setpoint_heating.data == 1 - assert device.values.setpoint_cooling.data == 10 - device.set_temperature(**{ATTR_TARGET_TEMP_LOW: 2}) - assert device.values.setpoint_heating.data == 2 - assert device.values.setpoint_cooling.data == 10 - device.set_temperature(**{ATTR_TARGET_TEMP_HIGH: 9}) - assert device.values.setpoint_heating.data == 2 - assert device.values.setpoint_cooling.data == 9 - device.set_temperature(**{ATTR_TARGET_TEMP_LOW: 3, ATTR_TARGET_TEMP_HIGH: 8}) - assert device.values.setpoint_heating.data == 3 - assert device.values.setpoint_cooling.data == 8 - - -def test_target_value_set_range_away(device_heat_cool_away): - """Test values changed for climate device.""" - device = device_heat_cool_away - assert device.values.setpoint_heating.data == 2 - assert device.values.setpoint_cooling.data == 9 - assert device.values.setpoint_away_heating.data == 1 - assert device.values.setpoint_away_cooling.data == 10 - device.set_preset_mode(PRESET_AWAY) - device.set_temperature(**{ATTR_TARGET_TEMP_LOW: 0, ATTR_TARGET_TEMP_HIGH: 11}) - assert device.values.setpoint_heating.data == 2 - assert device.values.setpoint_cooling.data == 9 - assert device.values.setpoint_away_heating.data == 0 - assert device.values.setpoint_away_cooling.data == 11 - - -def test_target_value_set_eco(device_heat_eco): - """Test values changed for climate device.""" - device = device_heat_eco - assert device.values.setpoint_heating.data == 2 - assert device.values.setpoint_eco_heating.data == 1 - device.set_preset_mode("heat econ") - device.set_temperature(**{ATTR_TEMPERATURE: 0}) - assert device.values.setpoint_heating.data == 2 - assert device.values.setpoint_eco_heating.data == 0 - - -def test_target_value_set_single_setpoint(device_single_setpoint): - """Test values changed for climate device.""" - device = device_single_setpoint - assert device.values.primary.data == 1 - device.set_temperature(**{ATTR_TEMPERATURE: 2}) - assert device.values.primary.data == 2 - - -def test_operation_value_set(device): - """Test values changed for climate device.""" - assert device.values.primary.data == HVAC_MODE_HEAT - device.set_hvac_mode(HVAC_MODE_COOL) - assert device.values.primary.data == HVAC_MODE_COOL - device.set_preset_mode(PRESET_ECO) - assert device.values.primary.data == PRESET_ECO - device.set_preset_mode(PRESET_NONE) - assert device.values.primary.data == HVAC_MODE_HEAT_COOL - device.values.primary = None - device.set_hvac_mode("test_set_failes") - assert device.values.primary is None - device.set_preset_mode("test_set_failes") - assert device.values.primary is None - - -def test_operation_value_set_mapping(device_mapping): - """Test values changed for climate device. Mapping.""" - device = device_mapping - assert device.values.primary.data == "Heat" - device.set_hvac_mode(HVAC_MODE_COOL) - assert device.values.primary.data == "Cool" - device.set_hvac_mode(HVAC_MODE_OFF) - assert device.values.primary.data == "Off" - device.set_preset_mode(PRESET_BOOST) - assert device.values.primary.data == "Full Power" - device.set_preset_mode(PRESET_ECO) - assert device.values.primary.data == "eco" - - -def test_operation_value_set_unknown(device_unknown): - """Test values changed for climate device. Unknown.""" - device = device_unknown - assert device.values.primary.data == "Heat" - device.set_preset_mode("Abcdefg") - assert device.values.primary.data == "Abcdefg" - device.set_preset_mode(PRESET_NONE) - assert device.values.primary.data == HVAC_MODE_HEAT_COOL - - -def test_operation_value_set_heat_cool(device_heat_cool): - """Test values changed for climate device. Heat/Cool only.""" - device = device_heat_cool - assert device.values.primary.data == HVAC_MODE_HEAT - device.set_preset_mode("Heat Eco") - assert device.values.primary.data == "Heat Eco" - device.set_preset_mode(PRESET_NONE) - assert device.values.primary.data == HVAC_MODE_HEAT - device.set_preset_mode("Cool Eco") - assert device.values.primary.data == "Cool Eco" - device.set_preset_mode(PRESET_NONE) - assert device.values.primary.data == HVAC_MODE_COOL - - -def test_fan_mode_value_set(device): - """Test values changed for climate device.""" - assert device.values.fan_mode.data == "test2" - device.set_fan_mode("test_fan_set") - assert device.values.fan_mode.data == "test_fan_set" - device.values.fan_mode = None - device.set_fan_mode("test_fan_set_failes") - assert device.values.fan_mode is None - - -def test_target_value_changed(device): - """Test values changed for climate device.""" - assert device.target_temperature == 1 - device.values.setpoint_heating.data = 2 - value_changed(device.values.setpoint_heating) - assert device.target_temperature == 2 - device.values.primary.data = HVAC_MODE_COOL - value_changed(device.values.primary) - assert device.target_temperature == 10 - device.values.setpoint_cooling.data = 9 - value_changed(device.values.setpoint_cooling) - assert device.target_temperature == 9 - - -def test_target_range_changed(device_heat_cool_range): - """Test values changed for climate device.""" - device = device_heat_cool_range - assert device.target_temperature_low == 1 - assert device.target_temperature_high == 10 - device.values.setpoint_heating.data = 2 - value_changed(device.values.setpoint_heating) - assert device.target_temperature_low == 2 - assert device.target_temperature_high == 10 - device.values.setpoint_cooling.data = 9 - value_changed(device.values.setpoint_cooling) - assert device.target_temperature_low == 2 - assert device.target_temperature_high == 9 - - -def test_target_changed_preset_range(device_heat_cool_away): - """Test values changed for climate device.""" - device = device_heat_cool_away - assert device.target_temperature_low == 2 - assert device.target_temperature_high == 9 - device.values.primary.data = PRESET_AWAY - value_changed(device.values.primary) - assert device.target_temperature_low == 1 - assert device.target_temperature_high == 10 - device.values.setpoint_away_heating.data = 0 - value_changed(device.values.setpoint_away_heating) - device.values.setpoint_away_cooling.data = 11 - value_changed(device.values.setpoint_away_cooling) - assert device.target_temperature_low == 0 - assert device.target_temperature_high == 11 - device.values.primary.data = HVAC_MODE_HEAT_COOL - value_changed(device.values.primary) - assert device.target_temperature_low == 2 - assert device.target_temperature_high == 9 - - -def test_target_changed_eco(device_heat_eco): - """Test values changed for climate device.""" - device = device_heat_eco - assert device.target_temperature == 2 - device.values.primary.data = "heat econ" - value_changed(device.values.primary) - assert device.target_temperature == 1 - device.values.setpoint_eco_heating.data = 0 - value_changed(device.values.setpoint_eco_heating) - assert device.target_temperature == 0 - device.values.primary.data = HVAC_MODE_HEAT - value_changed(device.values.primary) - assert device.target_temperature == 2 - - -def test_target_changed_with_mode(device): - """Test values changed for climate device.""" - assert device.hvac_mode == HVAC_MODE_HEAT - assert device.target_temperature == 1 - device.values.primary.data = HVAC_MODE_COOL - value_changed(device.values.primary) - assert device.target_temperature == 10 - device.values.primary.data = HVAC_MODE_HEAT_COOL - value_changed(device.values.primary) - assert device.target_temperature_low == 1 - assert device.target_temperature_high == 10 - - -def test_target_value_changed_single_setpoint(device_single_setpoint): - """Test values changed for climate device.""" - device = device_single_setpoint - assert device.target_temperature == 1 - device.values.primary.data = 2 - value_changed(device.values.primary) - assert device.target_temperature == 2 - - -def test_temperature_value_changed(device): - """Test values changed for climate device.""" - assert device.current_temperature == 5 - device.values.temperature.data = 3 - value_changed(device.values.temperature) - assert device.current_temperature == 3 - - -def test_operation_value_changed(device): - """Test values changed for climate device.""" - assert device.hvac_mode == HVAC_MODE_HEAT - assert device.preset_mode == PRESET_NONE - device.values.primary.data = HVAC_MODE_COOL - value_changed(device.values.primary) - assert device.hvac_mode == HVAC_MODE_COOL - assert device.preset_mode == PRESET_NONE - device.values.primary.data = HVAC_MODE_OFF - value_changed(device.values.primary) - assert device.hvac_mode == HVAC_MODE_OFF - assert device.preset_mode == PRESET_NONE - device.values.primary = None - assert device.hvac_mode == HVAC_MODE_HEAT_COOL - assert device.preset_mode == PRESET_NONE - - -def test_operation_value_changed_preset(device_mapping): - """Test preset changed for climate device.""" - device = device_mapping - assert device.hvac_mode == HVAC_MODE_HEAT - assert device.preset_mode == PRESET_NONE - device.values.primary.data = PRESET_ECO - value_changed(device.values.primary) - assert device.hvac_mode == HVAC_MODE_HEAT_COOL - assert device.preset_mode == PRESET_ECO - - -def test_operation_value_changed_mapping(device_mapping): - """Test values changed for climate device. Mapping.""" - device = device_mapping - assert device.hvac_mode == HVAC_MODE_HEAT - assert device.preset_mode == PRESET_NONE - device.values.primary.data = "Off" - value_changed(device.values.primary) - assert device.hvac_mode == HVAC_MODE_OFF - assert device.preset_mode == PRESET_NONE - device.values.primary.data = "Cool" - value_changed(device.values.primary) - assert device.hvac_mode == HVAC_MODE_COOL - assert device.preset_mode == PRESET_NONE - - -def test_operation_value_changed_mapping_preset(device_mapping): - """Test values changed for climate device. Mapping with presets.""" - device = device_mapping - assert device.hvac_mode == HVAC_MODE_HEAT - assert device.preset_mode == PRESET_NONE - device.values.primary.data = "Full Power" - value_changed(device.values.primary) - assert device.hvac_mode == HVAC_MODE_HEAT_COOL - assert device.preset_mode == PRESET_BOOST - device.values.primary = None - assert device.hvac_mode == HVAC_MODE_HEAT_COOL - assert device.preset_mode == PRESET_NONE - - -def test_operation_value_changed_unknown(device_unknown): - """Test preset changed for climate device. Unknown.""" - device = device_unknown - assert device.hvac_mode == HVAC_MODE_HEAT - assert device.preset_mode == PRESET_NONE - device.values.primary.data = "Abcdefg" - value_changed(device.values.primary) - assert device.hvac_mode == HVAC_MODE_HEAT_COOL - assert device.preset_mode == "Abcdefg" - - -def test_operation_value_changed_heat_cool(device_heat_cool): - """Test preset changed for climate device. Heat/Cool only.""" - device = device_heat_cool - assert device.hvac_mode == HVAC_MODE_HEAT - assert device.preset_mode == PRESET_NONE - device.values.primary.data = "Cool Eco" - value_changed(device.values.primary) - assert device.hvac_mode == HVAC_MODE_COOL - assert device.preset_mode == "Cool Eco" - device.values.primary.data = "Heat Eco" - value_changed(device.values.primary) - assert device.hvac_mode == HVAC_MODE_HEAT - assert device.preset_mode == "Heat Eco" - - -def test_fan_mode_value_changed(device): - """Test values changed for climate device.""" - assert device.fan_mode == "test2" - device.values.fan_mode.data = "test_updated_fan" - value_changed(device.values.fan_mode) - assert device.fan_mode == "test_updated_fan" - - -def test_hvac_action_value_changed(device): - """Test values changed for climate device.""" - assert device.hvac_action == CURRENT_HVAC_HEAT - device.values.operating_state.data = CURRENT_HVAC_COOL - value_changed(device.values.operating_state) - assert device.hvac_action == CURRENT_HVAC_COOL - - -def test_hvac_action_value_changed_mapping(device_mapping): - """Test values changed for climate device.""" - device = device_mapping - assert device.hvac_action == CURRENT_HVAC_HEAT - device.values.operating_state.data = "cooling" - value_changed(device.values.operating_state) - assert device.hvac_action == CURRENT_HVAC_COOL - - -def test_hvac_action_value_changed_unknown(device_unknown): - """Test values changed for climate device.""" - device = device_unknown - assert device.hvac_action == "test4" - device.values.operating_state.data = "another_hvac_action" - value_changed(device.values.operating_state) - assert device.hvac_action == "another_hvac_action" - - -def test_fan_action_value_changed(device): - """Test values changed for climate device.""" - assert device.extra_state_attributes[climate.ATTR_FAN_ACTION] == 7 - device.values.fan_action.data = 9 - value_changed(device.values.fan_action) - assert device.extra_state_attributes[climate.ATTR_FAN_ACTION] == 9 - - -def test_aux_heat_unsupported_set(device): - """Test aux heat for climate device.""" - assert device.values.primary.data == HVAC_MODE_HEAT - device.turn_aux_heat_on() - assert device.values.primary.data == HVAC_MODE_HEAT - device.turn_aux_heat_off() - assert device.values.primary.data == HVAC_MODE_HEAT - - -def test_aux_heat_unsupported_value_changed(device): - """Test aux heat for climate device.""" - assert device.is_aux_heat is None - device.values.primary.data = HVAC_MODE_HEAT - value_changed(device.values.primary) - assert device.is_aux_heat is None - - -def test_aux_heat_set(device_aux_heat): - """Test aux heat for climate device.""" - device = device_aux_heat - assert device.values.primary.data == HVAC_MODE_HEAT - device.turn_aux_heat_on() - assert device.values.primary.data == AUX_HEAT_ZWAVE_MODE - device.turn_aux_heat_off() - assert device.values.primary.data == HVAC_MODE_HEAT - - -def test_aux_heat_value_changed(device_aux_heat): - """Test aux heat for climate device.""" - device = device_aux_heat - assert device.is_aux_heat is False - device.values.primary.data = AUX_HEAT_ZWAVE_MODE - value_changed(device.values.primary) - assert device.is_aux_heat is True - device.values.primary.data = HVAC_MODE_HEAT - value_changed(device.values.primary) - assert device.is_aux_heat is False diff --git a/tests/components/zwave/test_cover.py b/tests/components/zwave/test_cover.py deleted file mode 100644 index e7283de25b4..00000000000 --- a/tests/components/zwave/test_cover.py +++ /dev/null @@ -1,292 +0,0 @@ -"""Test Z-Wave cover devices.""" -from unittest.mock import MagicMock - -import pytest - -from homeassistant.components.cover import SUPPORT_CLOSE, SUPPORT_OPEN -from homeassistant.components.zwave import ( - CONF_INVERT_OPENCLOSE_BUTTONS, - CONF_INVERT_PERCENT, - const, - cover, -) - -from tests.mock.zwave import MockEntityValues, MockNode, MockValue, value_changed - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -def test_get_device_detects_none(hass, mock_openzwave): - """Test device returns none.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockEntityValues(primary=value, node=node) - - device = cover.get_device(hass=hass, node=node, values=values, node_config={}) - assert device is None - - -def test_get_device_detects_rollershutter(hass, mock_openzwave): - """Test device returns rollershutter.""" - hass.data[const.DATA_NETWORK] = MagicMock() - node = MockNode() - value = MockValue( - data=0, node=node, command_class=const.COMMAND_CLASS_SWITCH_MULTILEVEL - ) - values = MockEntityValues(primary=value, open=None, close=None, node=node) - - device = cover.get_device(hass=hass, node=node, values=values, node_config={}) - assert isinstance(device, cover.ZwaveRollershutter) - - -def test_get_device_detects_garagedoor_switch(hass, mock_openzwave): - """Test device returns garage door.""" - node = MockNode() - value = MockValue( - data=False, node=node, command_class=const.COMMAND_CLASS_SWITCH_BINARY - ) - values = MockEntityValues(primary=value, node=node) - - device = cover.get_device(hass=hass, node=node, values=values, node_config={}) - assert isinstance(device, cover.ZwaveGarageDoorSwitch) - assert device.device_class == "garage" - assert device.supported_features == SUPPORT_OPEN | SUPPORT_CLOSE - - -def test_get_device_detects_garagedoor_barrier(hass, mock_openzwave): - """Test device returns garage door.""" - node = MockNode() - value = MockValue( - data="Closed", node=node, command_class=const.COMMAND_CLASS_BARRIER_OPERATOR - ) - values = MockEntityValues(primary=value, node=node) - - device = cover.get_device(hass=hass, node=node, values=values, node_config={}) - assert isinstance(device, cover.ZwaveGarageDoorBarrier) - assert device.device_class == "garage" - assert device.supported_features == SUPPORT_OPEN | SUPPORT_CLOSE - - -def test_roller_no_position_workaround(hass, mock_openzwave): - """Test position changed.""" - hass.data[const.DATA_NETWORK] = MagicMock() - node = MockNode(manufacturer_id="0047", product_type="5a52") - value = MockValue( - data=45, node=node, command_class=const.COMMAND_CLASS_SWITCH_MULTILEVEL - ) - values = MockEntityValues(primary=value, open=None, close=None, node=node) - device = cover.get_device(hass=hass, node=node, values=values, node_config={}) - - assert device.current_cover_position is None - - -def test_roller_value_changed(hass, mock_openzwave): - """Test position changed.""" - hass.data[const.DATA_NETWORK] = MagicMock() - node = MockNode() - value = MockValue( - data=None, node=node, command_class=const.COMMAND_CLASS_SWITCH_MULTILEVEL - ) - values = MockEntityValues(primary=value, open=None, close=None, node=node) - device = cover.get_device(hass=hass, node=node, values=values, node_config={}) - - assert device.current_cover_position is None - assert device.is_closed is None - - value.data = 2 - value_changed(value) - - assert device.current_cover_position == 0 - assert device.is_closed - - value.data = 35 - value_changed(value) - - assert device.current_cover_position == 35 - assert not device.is_closed - - value.data = 97 - value_changed(value) - - assert device.current_cover_position == 100 - assert not device.is_closed - - -def test_roller_commands(hass, mock_openzwave): - """Test position changed.""" - mock_network = hass.data[const.DATA_NETWORK] = MagicMock() - node = MockNode() - value = MockValue( - data=50, node=node, command_class=const.COMMAND_CLASS_SWITCH_MULTILEVEL - ) - open_value = MockValue(data=False, node=node) - close_value = MockValue(data=False, node=node) - values = MockEntityValues( - primary=value, open=open_value, close=close_value, node=node - ) - device = cover.get_device(hass=hass, node=node, values=values, node_config={}) - - device.set_cover_position(position=25) - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - assert value_id == value.value_id - assert brightness == 25 - - device.open_cover() - assert mock_network.manager.pressButton.called - (value_id,) = mock_network.manager.pressButton.mock_calls.pop(0)[1] - assert value_id == open_value.value_id - - device.close_cover() - assert mock_network.manager.pressButton.called - (value_id,) = mock_network.manager.pressButton.mock_calls.pop(0)[1] - assert value_id == close_value.value_id - - device.stop_cover() - assert mock_network.manager.releaseButton.called - (value_id,) = mock_network.manager.releaseButton.mock_calls.pop(0)[1] - assert value_id == open_value.value_id - - -def test_roller_invert_percent(hass, mock_openzwave): - """Test position changed.""" - mock_network = hass.data[const.DATA_NETWORK] = MagicMock() - node = MockNode() - value = MockValue( - data=50, node=node, command_class=const.COMMAND_CLASS_SWITCH_MULTILEVEL - ) - open_value = MockValue(data=False, node=node) - close_value = MockValue(data=False, node=node) - values = MockEntityValues( - primary=value, open=open_value, close=close_value, node=node - ) - device = cover.get_device( - hass=hass, node=node, values=values, node_config={CONF_INVERT_PERCENT: True} - ) - - device.set_cover_position(position=25) - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - assert value_id == value.value_id - assert brightness == 75 - - device.open_cover() - assert mock_network.manager.pressButton.called - (value_id,) = mock_network.manager.pressButton.mock_calls.pop(0)[1] - assert value_id == open_value.value_id - - -def test_roller_reverse_open_close(hass, mock_openzwave): - """Test position changed.""" - mock_network = hass.data[const.DATA_NETWORK] = MagicMock() - node = MockNode() - value = MockValue( - data=50, node=node, command_class=const.COMMAND_CLASS_SWITCH_MULTILEVEL - ) - open_value = MockValue(data=False, node=node) - close_value = MockValue(data=False, node=node) - values = MockEntityValues( - primary=value, open=open_value, close=close_value, node=node - ) - device = cover.get_device( - hass=hass, - node=node, - values=values, - node_config={CONF_INVERT_OPENCLOSE_BUTTONS: True}, - ) - - device.open_cover() - assert mock_network.manager.pressButton.called - (value_id,) = mock_network.manager.pressButton.mock_calls.pop(0)[1] - assert value_id == close_value.value_id - - device.close_cover() - assert mock_network.manager.pressButton.called - (value_id,) = mock_network.manager.pressButton.mock_calls.pop(0)[1] - assert value_id == open_value.value_id - - device.stop_cover() - assert mock_network.manager.releaseButton.called - (value_id,) = mock_network.manager.releaseButton.mock_calls.pop(0)[1] - assert value_id == close_value.value_id - - -def test_switch_garage_value_changed(hass, mock_openzwave): - """Test position changed.""" - node = MockNode() - value = MockValue( - data=False, node=node, command_class=const.COMMAND_CLASS_SWITCH_BINARY - ) - values = MockEntityValues(primary=value, node=node) - device = cover.get_device(hass=hass, node=node, values=values, node_config={}) - - assert device.is_closed - - value.data = True - value_changed(value) - assert not device.is_closed - - -def test_switch_garage_commands(hass, mock_openzwave): - """Test position changed.""" - node = MockNode() - value = MockValue( - data=False, node=node, command_class=const.COMMAND_CLASS_SWITCH_BINARY - ) - values = MockEntityValues(primary=value, node=node) - device = cover.get_device(hass=hass, node=node, values=values, node_config={}) - - assert value.data is False - device.open_cover() - assert value.data is True - device.close_cover() - assert value.data is False - - -def test_barrier_garage_value_changed(hass, mock_openzwave): - """Test position changed.""" - node = MockNode() - value = MockValue( - data="Closed", node=node, command_class=const.COMMAND_CLASS_BARRIER_OPERATOR - ) - values = MockEntityValues(primary=value, node=node) - device = cover.get_device(hass=hass, node=node, values=values, node_config={}) - - assert device.is_closed - assert not device.is_opening - assert not device.is_closing - - value.data = "Opening" - value_changed(value) - assert not device.is_closed - assert device.is_opening - assert not device.is_closing - - value.data = "Opened" - value_changed(value) - assert not device.is_closed - assert not device.is_opening - assert not device.is_closing - - value.data = "Closing" - value_changed(value) - assert not device.is_closed - assert not device.is_opening - assert device.is_closing - - -def test_barrier_garage_commands(hass, mock_openzwave): - """Test position changed.""" - node = MockNode() - value = MockValue( - data="Closed", node=node, command_class=const.COMMAND_CLASS_BARRIER_OPERATOR - ) - values = MockEntityValues(primary=value, node=node) - device = cover.get_device(hass=hass, node=node, values=values, node_config={}) - - assert value.data == "Closed" - device.open_cover() - assert value.data == "Opened" - device.close_cover() - assert value.data == "Closed" diff --git a/tests/components/zwave/test_fan.py b/tests/components/zwave/test_fan.py deleted file mode 100644 index 0104353f851..00000000000 --- a/tests/components/zwave/test_fan.py +++ /dev/null @@ -1,91 +0,0 @@ -"""Test Z-Wave fans.""" -import pytest - -from homeassistant.components.fan import SUPPORT_SET_SPEED -from homeassistant.components.zwave import fan - -from tests.mock.zwave import MockEntityValues, MockNode, MockValue - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -def test_get_device_detects_fan(mock_openzwave): - """Test get_device returns a zwave fan.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockEntityValues(primary=value) - - device = fan.get_device(node=node, values=values, node_config={}) - assert isinstance(device, fan.ZwaveFan) - assert device.supported_features == SUPPORT_SET_SPEED - - -def test_fan_turn_on(mock_openzwave): - """Test turning on a zwave fan.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockEntityValues(primary=value) - device = fan.get_device(node=node, values=values, node_config={}) - - device.turn_on() - - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - assert value_id == value.value_id - assert brightness == 255 - - node.reset_mock() - - device.turn_on(percentage=0) - - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - - assert value_id == value.value_id - assert brightness == 0 - - node.reset_mock() - - device.turn_on(percentage=1) - - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - - assert value_id == value.value_id - assert brightness == 1 - - node.reset_mock() - - device.turn_on(percentage=50) - - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - - assert value_id == value.value_id - assert brightness == 50 - - node.reset_mock() - - device.turn_on(percentage=100) - - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - - assert value_id == value.value_id - assert brightness == 99 - - -def test_fan_turn_off(mock_openzwave): - """Test turning off a dimmable zwave fan.""" - node = MockNode() - value = MockValue(data=46, node=node) - values = MockEntityValues(primary=value) - device = fan.get_device(node=node, values=values, node_config={}) - - device.turn_off() - - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - assert value_id == value.value_id - assert brightness == 0 diff --git a/tests/components/zwave/test_init.py b/tests/components/zwave/test_init.py deleted file mode 100644 index 745d6d8ce57..00000000000 --- a/tests/components/zwave/test_init.py +++ /dev/null @@ -1,1977 +0,0 @@ -"""Tests for the Z-Wave init.""" -import asyncio -from collections import OrderedDict -from datetime import datetime -from unittest.mock import MagicMock, patch - -import pytest -import voluptuous as vol - -from homeassistant.bootstrap import async_setup_component -from homeassistant.components import zwave -from homeassistant.components.zwave import ( - CONF_DEVICE_CONFIG_GLOB, - CONFIG_SCHEMA, - DATA_NETWORK, - const, -) -from homeassistant.const import ATTR_NAME -from homeassistant.helpers import device_registry as dr, entity_registry as er -from homeassistant.util import dt as dt_util - -from tests.common import async_fire_time_changed, mock_registry -from tests.mock.zwave import MockEntityValues, MockNetwork, MockNode, MockValue - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -@pytest.fixture(autouse=True) -def mock_storage(hass_storage): - """Autouse hass_storage for the TestCase tests.""" - - -@pytest.fixture -async def zwave_setup(hass): - """Zwave setup.""" - await async_setup_component(hass, "zwave", {"zwave": {}}) - await hass.async_block_till_done() - - -@pytest.fixture -async def zwave_setup_ready(hass, zwave_setup): - """Zwave setup and set network to ready.""" - zwave_network = hass.data[DATA_NETWORK] - zwave_network.state = MockNetwork.STATE_READY - - await hass.async_start() - - -async def test_valid_device_config(hass, mock_openzwave): - """Test valid device config.""" - device_config = {"light.kitchen": {"ignored": "true"}} - result = await async_setup_component( - hass, "zwave", {"zwave": {"device_config": device_config}} - ) - await hass.async_block_till_done() - - assert result - - -async def test_invalid_device_config(hass, mock_openzwave): - """Test invalid device config.""" - device_config = {"light.kitchen": {"some_ignored": "true"}} - result = await async_setup_component( - hass, "zwave", {"zwave": {"device_config": device_config}} - ) - await hass.async_block_till_done() - - assert not result - - -def test_config_access_error(): - """Test threading error accessing config values.""" - node = MagicMock() - - def side_effect(): - raise RuntimeError - - node.values.values.side_effect = side_effect - result = zwave.get_config_value(node, 1) - assert result is None - - -async def test_network_options(hass, mock_openzwave): - """Test network options.""" - result = await async_setup_component( - hass, - "zwave", - {"zwave": {"usb_path": "mock_usb_path", "config_path": "mock_config_path"}}, - ) - await hass.async_block_till_done() - - assert result - - network = hass.data[zwave.DATA_NETWORK] - assert network.options.device == "mock_usb_path" - assert network.options.config_path == "mock_config_path" - - -async def test_network_key_validation(hass, mock_openzwave): - """Test network key validation.""" - test_values = [ - ( - "0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, " - "0x0C, 0x0D, 0x0E, 0x0F, 0x10" - ), - ( - "0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D," - "0x0E,0x0F,0x10" - ), - ] - for value in test_values: - result = zwave.CONFIG_SCHEMA({"zwave": {"network_key": value}}) - assert result["zwave"]["network_key"] == value - - -async def test_erronous_network_key_fails_validation(hass, mock_openzwave): - """Test failing erroneous network key validation.""" - test_values = [ - ( - "0x 01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, " - "0x0C, 0x0D, 0x0E, 0x0F, 0x10" - ), - ( - "0X01,0X02,0X03,0X04,0X05,0X06,0X07,0X08,0X09,0X0A,0X0B,0X0C,0X0D," - "0X0E,0X0F,0X10" - ), - "invalid", - "1234567", - 1234567, - ] - for value in test_values: - with pytest.raises(vol.Invalid): - zwave.CONFIG_SCHEMA({"zwave": {"network_key": value}}) - - -async def test_auto_heal_midnight(hass, mock_openzwave, legacy_patchable_time): - """Test network auto-heal at midnight.""" - await async_setup_component(hass, "zwave", {"zwave": {"autoheal": True}}) - await hass.async_block_till_done() - - network = hass.data[zwave.DATA_NETWORK] - assert not network.heal.called - - time = datetime(2017, 5, 6, 0, 0, 0, tzinfo=dt_util.UTC) - async_fire_time_changed(hass, time) - await hass.async_block_till_done() - await hass.async_block_till_done() - assert network.heal.called - assert len(network.heal.mock_calls) == 1 - - -async def test_auto_heal_disabled(hass, mock_openzwave): - """Test network auto-heal disabled.""" - await async_setup_component(hass, "zwave", {"zwave": {"autoheal": False}}) - await hass.async_block_till_done() - - network = hass.data[zwave.DATA_NETWORK] - assert not network.heal.called - - time = datetime(2017, 5, 6, 0, 0, 0, tzinfo=dt_util.UTC) - async_fire_time_changed(hass, time) - await hass.async_block_till_done() - assert not network.heal.called - - -async def test_setup_platform(hass, mock_openzwave): - """Test invalid device config.""" - mock_device = MagicMock() - hass.data[DATA_NETWORK] = MagicMock() - hass.data[zwave.DATA_DEVICES] = {456: mock_device} - async_add_entities = MagicMock() - - result = await zwave.async_setup_platform(hass, None, async_add_entities, None) - assert not result - assert not async_add_entities.called - - result = await zwave.async_setup_platform( - hass, None, async_add_entities, {const.DISCOVERY_DEVICE: 123} - ) - assert not result - assert not async_add_entities.called - - result = await zwave.async_setup_platform( - hass, None, async_add_entities, {const.DISCOVERY_DEVICE: 456} - ) - assert result - assert async_add_entities.called - assert len(async_add_entities.mock_calls) == 1 - assert async_add_entities.mock_calls[0][1][0] == [mock_device] - - -async def test_zwave_ready_wait(hass, mock_openzwave, zwave_setup): - """Test that zwave continues after waiting for network ready.""" - sleeps = [] - - def utcnow(): - return datetime.fromtimestamp(len(sleeps)) - - asyncio_sleep = asyncio.sleep - - async def sleep(duration, loop=None): - if duration > 0: - sleeps.append(duration) - await asyncio_sleep(0) - - with patch("homeassistant.components.zwave.dt_util.utcnow", new=utcnow), patch( - "asyncio.sleep", new=sleep - ), patch.object(zwave, "_LOGGER") as mock_logger: - hass.data[DATA_NETWORK].state = MockNetwork.STATE_STARTED - - await hass.async_start() - - assert len(sleeps) == const.NETWORK_READY_WAIT_SECS - assert mock_logger.warning.called - assert len(mock_logger.warning.mock_calls) == 1 - assert mock_logger.warning.mock_calls[0][1][1] == const.NETWORK_READY_WAIT_SECS - - -async def test_device_entity(hass, mock_openzwave): - """Test device entity base class.""" - node = MockNode(node_id="10", name="Mock Node") - value = MockValue( - data=False, - node=node, - instance=2, - object_id="11", - label="Sensor", - command_class=const.COMMAND_CLASS_SENSOR_BINARY, - ) - power_value = MockValue( - data=50.123456, node=node, precision=3, command_class=const.COMMAND_CLASS_METER - ) - values = MockEntityValues(primary=value, power=power_value) - device = zwave.ZWaveDeviceEntity(values, "zwave") - device.hass = hass - device.value_added() - device.update_properties() - await hass.async_block_till_done() - - assert not device.should_poll - assert device.unique_id == "10-11" - assert device.name == "Mock Node Sensor" - assert device.extra_state_attributes[zwave.ATTR_POWER] == 50.123 - - -async def test_node_removed(hass, mock_openzwave): - """Test node removed in base class.""" - # Create a mock node & node entity - node = MockNode(node_id="10", name="Mock Node") - value = MockValue( - data=False, - node=node, - instance=2, - object_id="11", - label="Sensor", - command_class=const.COMMAND_CLASS_SENSOR_BINARY, - ) - power_value = MockValue( - data=50.123456, node=node, precision=3, command_class=const.COMMAND_CLASS_METER - ) - values = MockEntityValues(primary=value, power=power_value) - device = zwave.ZWaveDeviceEntity(values, "zwave") - device.hass = hass - device.entity_id = "zwave.mock_node" - device.value_added() - device.update_properties() - await hass.async_block_till_done() - - # Save it to the entity registry - registry = mock_registry(hass) - registry.async_get_or_create("zwave", "zwave", device.unique_id) - device.entity_id = registry.async_get_entity_id("zwave", "zwave", device.unique_id) - - # Create dummy entity registry entries for other integrations - hue_entity = registry.async_get_or_create("light", "hue", 1234) - zha_entity = registry.async_get_or_create("sensor", "zha", 5678) - - # Verify our Z-Wave entity is registered - assert registry.async_is_registered(device.entity_id) - - # Remove it - entity_id = device.entity_id - await device.node_removed() - - # Verify registry entry for our Z-Wave node is gone - assert not registry.async_is_registered(entity_id) - - # Verify registry entries for our other entities remain - assert registry.async_is_registered(hue_entity.entity_id) - assert registry.async_is_registered(zha_entity.entity_id) - - -async def test_node_discovery(hass, mock_openzwave): - """Test discovery of a node.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == MockNetwork.SIGNAL_NODE_ADDED: - mock_receivers.append(receiver) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - await async_setup_component(hass, "zwave", {"zwave": {}}) - await hass.async_block_till_done() - - assert len(mock_receivers) == 1 - - node = MockNode(node_id=14) - await hass.async_add_executor_job(mock_receivers[0], node) - await hass.async_block_till_done() - - assert hass.states.get("zwave.mock_node").state == "unknown" - - -async def test_unparsed_node_discovery(hass, mock_openzwave): - """Test discovery of a node.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == MockNetwork.SIGNAL_NODE_ADDED: - mock_receivers.append(receiver) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - await async_setup_component(hass, "zwave", {"zwave": {}}) - await hass.async_block_till_done() - - assert len(mock_receivers) == 1 - - node = MockNode(node_id=14, manufacturer_name=None, name=None, is_ready=False) - - sleeps = [] - - def utcnow(): - return datetime.fromtimestamp(len(sleeps)) - - asyncio_sleep = asyncio.sleep - - async def sleep(duration, loop=None): - if duration > 0: - sleeps.append(duration) - await asyncio_sleep(0) - - with patch("homeassistant.components.zwave.dt_util.utcnow", new=utcnow), patch( - "asyncio.sleep", new=sleep - ), patch.object(zwave, "_LOGGER") as mock_logger: - await hass.async_add_executor_job(mock_receivers[0], node) - await hass.async_block_till_done() - - assert len(sleeps) == const.NODE_READY_WAIT_SECS - assert mock_logger.warning.called - assert len(mock_logger.warning.mock_calls) == 1 - assert mock_logger.warning.mock_calls[0][1][1:] == ( - 14, - const.NODE_READY_WAIT_SECS, - ) - assert hass.states.get("zwave.unknown_node_14").state == "unknown" - - -async def test_node_ignored(hass, mock_openzwave): - """Test discovery of a node.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == MockNetwork.SIGNAL_NODE_ADDED: - mock_receivers.append(receiver) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - await async_setup_component( - hass, - "zwave", - {"zwave": {"device_config": {"zwave.mock_node": {"ignored": True}}}}, - ) - await hass.async_block_till_done() - - assert len(mock_receivers) == 1 - - node = MockNode(node_id=14) - await hass.async_add_executor_job(mock_receivers[0], node) - await hass.async_block_till_done() - - assert hass.states.get("zwave.mock_node") is None - - -async def test_value_discovery(hass, mock_openzwave): - """Test discovery of a node.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == MockNetwork.SIGNAL_VALUE_ADDED: - mock_receivers.append(receiver) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - await async_setup_component(hass, "zwave", {"zwave": {}}) - await hass.async_block_till_done() - - assert len(mock_receivers) == 1 - - node = MockNode(node_id=11, generic=const.GENERIC_TYPE_SENSOR_BINARY) - value = MockValue( - data=False, - node=node, - index=12, - instance=13, - command_class=const.COMMAND_CLASS_SENSOR_BINARY, - type=const.TYPE_BOOL, - genre=const.GENRE_USER, - ) - await hass.async_add_executor_job(mock_receivers[0], node, value) - await hass.async_block_till_done() - - assert hass.states.get("binary_sensor.mock_node_mock_value").state == "off" - - -async def test_value_entities(hass, mock_openzwave): - """Test discovery of a node.""" - mock_receivers = {} - - def mock_connect(receiver, signal, *args, **kwargs): - mock_receivers[signal] = receiver - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - await async_setup_component(hass, "zwave", {"zwave": {}}) - await hass.async_block_till_done() - - zwave_network = hass.data[DATA_NETWORK] - zwave_network.state = MockNetwork.STATE_READY - - await hass.async_start() - - assert mock_receivers - - await hass.async_add_executor_job( - mock_receivers[MockNetwork.SIGNAL_ALL_NODES_QUERIED] - ) - node = MockNode(node_id=11, generic=const.GENERIC_TYPE_SENSOR_BINARY) - zwave_network.nodes = {node.node_id: node} - value = MockValue( - data=False, - node=node, - index=12, - instance=1, - command_class=const.COMMAND_CLASS_SENSOR_BINARY, - type=const.TYPE_BOOL, - genre=const.GENRE_USER, - ) - node.values = {"primary": value, value.value_id: value} - value2 = MockValue( - data=False, - node=node, - index=12, - instance=2, - label="Mock Value B", - command_class=const.COMMAND_CLASS_SENSOR_BINARY, - type=const.TYPE_BOOL, - genre=const.GENRE_USER, - ) - node.values[value2.value_id] = value2 - - await hass.async_add_executor_job( - mock_receivers[MockNetwork.SIGNAL_NODE_ADDED], node - ) - await hass.async_add_executor_job( - mock_receivers[MockNetwork.SIGNAL_VALUE_ADDED], node, value - ) - await hass.async_add_executor_job( - mock_receivers[MockNetwork.SIGNAL_VALUE_ADDED], node, value2 - ) - await hass.async_block_till_done() - - assert hass.states.get("binary_sensor.mock_node_mock_value").state == "off" - assert hass.states.get("binary_sensor.mock_node_mock_value_b").state == "off" - - ent_reg = er.async_get(hass) - dev_reg = dr.async_get(hass) - - entry = ent_reg.async_get("zwave.mock_node") - assert entry is not None - assert entry.unique_id == f"node-{node.node_id}" - node_dev_id = entry.device_id - - entry = ent_reg.async_get("binary_sensor.mock_node_mock_value") - assert entry is not None - assert entry.unique_id == f"{node.node_id}-{value.object_id}" - assert entry.name is None - assert entry.device_id == node_dev_id - - entry = ent_reg.async_get("binary_sensor.mock_node_mock_value_b") - assert entry is not None - assert entry.unique_id == f"{node.node_id}-{value2.object_id}" - assert entry.name is None - assert entry.device_id != node_dev_id - device_id_b = entry.device_id - - device = dev_reg.async_get(node_dev_id) - assert device is not None - assert device.name == node.name - old_device = device - - device = dev_reg.async_get(device_id_b) - assert device is not None - assert device.name == f"{node.name} ({value2.instance})" - - # test renaming without updating - await hass.services.async_call( - "zwave", - "rename_node", - {const.ATTR_NODE_ID: node.node_id, ATTR_NAME: "Demo Node"}, - ) - await hass.async_block_till_done() - - assert node.name == "Demo Node" - - entry = ent_reg.async_get("zwave.mock_node") - assert entry is not None - - entry = ent_reg.async_get("binary_sensor.mock_node_mock_value") - assert entry is not None - - entry = ent_reg.async_get("binary_sensor.mock_node_mock_value_b") - assert entry is not None - - device = dev_reg.async_get(node_dev_id) - assert device is not None - assert device.id == old_device.id - assert device.name == node.name - - device = dev_reg.async_get(device_id_b) - assert device is not None - assert device.name == f"{node.name} ({value2.instance})" - - # test renaming - await hass.services.async_call( - "zwave", - "rename_node", - { - const.ATTR_NODE_ID: node.node_id, - const.ATTR_UPDATE_IDS: True, - ATTR_NAME: "New Node", - }, - ) - await hass.async_block_till_done() - - assert node.name == "New Node" - - entry = ent_reg.async_get("zwave.new_node") - assert entry is not None - assert entry.unique_id == f"node-{node.node_id}" - - entry = ent_reg.async_get("binary_sensor.new_node_mock_value") - assert entry is not None - assert entry.unique_id == f"{node.node_id}-{value.object_id}" - - device = dev_reg.async_get(node_dev_id) - assert device is not None - assert device.id == old_device.id - assert device.name == node.name - - device = dev_reg.async_get(device_id_b) - assert device is not None - assert device.name == f"{node.name} ({value2.instance})" - - await hass.services.async_call( - "zwave", - "rename_value", - { - const.ATTR_NODE_ID: node.node_id, - const.ATTR_VALUE_ID: value.object_id, - const.ATTR_UPDATE_IDS: True, - ATTR_NAME: "New Label", - }, - ) - await hass.async_block_till_done() - - entry = ent_reg.async_get("binary_sensor.new_node_new_label") - assert entry is not None - assert entry.unique_id == f"{node.node_id}-{value.object_id}" - - -async def test_value_discovery_existing_entity(hass, mock_openzwave): - """Test discovery of a node.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == MockNetwork.SIGNAL_VALUE_ADDED: - mock_receivers.append(receiver) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - await async_setup_component(hass, "zwave", {"zwave": {}}) - await hass.async_block_till_done() - - assert len(mock_receivers) == 1 - - node = MockNode( - node_id=11, - generic=const.GENERIC_TYPE_THERMOSTAT, - specific=const.SPECIFIC_TYPE_THERMOSTAT_GENERAL_V2, - ) - thermostat_mode = MockValue( - data="Heat", - data_items=["Off", "Heat"], - node=node, - command_class=const.COMMAND_CLASS_THERMOSTAT_MODE, - genre=const.GENRE_USER, - ) - setpoint_heating = MockValue( - data=22.0, - node=node, - command_class=const.COMMAND_CLASS_THERMOSTAT_SETPOINT, - index=1, - genre=const.GENRE_USER, - ) - - await hass.async_add_executor_job(mock_receivers[0], node, thermostat_mode) - await hass.async_block_till_done() - - def mock_update(self): - self.hass.add_job(self.async_update_ha_state) - - with patch.object( - zwave.node_entity.ZWaveBaseEntity, "maybe_schedule_update", new=mock_update - ): - await hass.async_add_executor_job(mock_receivers[0], node, setpoint_heating) - await hass.async_block_till_done() - - assert ( - hass.states.get("climate.mock_node_mock_value").attributes["temperature"] - == 22.0 - ) - assert ( - hass.states.get("climate.mock_node_mock_value").attributes[ - "current_temperature" - ] - is None - ) - - with patch.object( - zwave.node_entity.ZWaveBaseEntity, "maybe_schedule_update", new=mock_update - ): - temperature = MockValue( - data=23.5, - node=node, - index=1, - command_class=const.COMMAND_CLASS_SENSOR_MULTILEVEL, - genre=const.GENRE_USER, - units="C", - ) - await hass.async_add_executor_job(mock_receivers[0], node, temperature) - await hass.async_block_till_done() - - assert ( - hass.states.get("climate.mock_node_mock_value").attributes["temperature"] - == 22.0 - ) - assert ( - hass.states.get("climate.mock_node_mock_value").attributes[ - "current_temperature" - ] - == 23.5 - ) - - -async def test_value_discovery_legacy_thermostat(hass, mock_openzwave): - """Test discovery of a node. Special case for legacy thermostats.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == MockNetwork.SIGNAL_VALUE_ADDED: - mock_receivers.append(receiver) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - await async_setup_component(hass, "zwave", {"zwave": {}}) - await hass.async_block_till_done() - - assert len(mock_receivers) == 1 - - node = MockNode( - node_id=11, - generic=const.GENERIC_TYPE_THERMOSTAT, - specific=const.SPECIFIC_TYPE_SETPOINT_THERMOSTAT, - ) - setpoint_heating = MockValue( - data=22.0, - node=node, - command_class=const.COMMAND_CLASS_THERMOSTAT_SETPOINT, - index=1, - genre=const.GENRE_USER, - ) - - await hass.async_add_executor_job(mock_receivers[0], node, setpoint_heating) - await hass.async_block_till_done() - - assert ( - hass.states.get("climate.mock_node_mock_value").attributes["temperature"] - == 22.0 - ) - - -async def test_power_schemes(hass, mock_openzwave): - """Test power attribute.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == MockNetwork.SIGNAL_VALUE_ADDED: - mock_receivers.append(receiver) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - await async_setup_component(hass, "zwave", {"zwave": {}}) - await hass.async_block_till_done() - - assert len(mock_receivers) == 1 - - node = MockNode(node_id=11, generic=const.GENERIC_TYPE_SWITCH_BINARY) - switch = MockValue( - data=True, - node=node, - index=12, - instance=13, - command_class=const.COMMAND_CLASS_SWITCH_BINARY, - genre=const.GENRE_USER, - type=const.TYPE_BOOL, - ) - await hass.async_add_executor_job(mock_receivers[0], node, switch) - - await hass.async_block_till_done() - - assert hass.states.get("switch.mock_node_mock_value").state == "on" - assert ( - "power_consumption" - not in hass.states.get("switch.mock_node_mock_value").attributes - ) - - def mock_update(self): - self.hass.add_job(self.async_update_ha_state) - - with patch.object( - zwave.node_entity.ZWaveBaseEntity, "maybe_schedule_update", new=mock_update - ): - power = MockValue( - data=23.5, - node=node, - index=const.INDEX_SENSOR_MULTILEVEL_POWER, - instance=13, - command_class=const.COMMAND_CLASS_SENSOR_MULTILEVEL, - genre=const.GENRE_USER, # to avoid exception - ) - await hass.async_add_executor_job(mock_receivers[0], node, power) - await hass.async_block_till_done() - - assert ( - hass.states.get("switch.mock_node_mock_value").attributes["power_consumption"] - == 23.5 - ) - - -async def test_network_ready(hass, mock_openzwave): - """Test Node network ready event.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == MockNetwork.SIGNAL_ALL_NODES_QUERIED: - mock_receivers.append(receiver) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - await async_setup_component(hass, "zwave", {"zwave": {}}) - await hass.async_block_till_done() - - assert len(mock_receivers) == 1 - - events = [] - - def listener(event): - events.append(event) - - hass.bus.async_listen(const.EVENT_NETWORK_COMPLETE, listener) - - await hass.async_add_executor_job(mock_receivers[0]) - await hass.async_block_till_done() - - assert len(events) == 1 - - -async def test_network_complete(hass, mock_openzwave): - """Test Node network complete event.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == MockNetwork.SIGNAL_AWAKE_NODES_QUERIED: - mock_receivers.append(receiver) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - await async_setup_component(hass, "zwave", {"zwave": {}}) - await hass.async_block_till_done() - - assert len(mock_receivers) == 1 - - events = [] - - def listener(event): - events.append(event) - - hass.bus.async_listen(const.EVENT_NETWORK_READY, listener) - - await hass.async_add_executor_job(mock_receivers[0]) - await hass.async_block_till_done() - - assert len(events) == 1 - - -async def test_network_complete_some_dead(hass, mock_openzwave): - """Test Node network complete some dead event.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == MockNetwork.SIGNAL_ALL_NODES_QUERIED_SOME_DEAD: - mock_receivers.append(receiver) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - await async_setup_component(hass, "zwave", {"zwave": {}}) - await hass.async_block_till_done() - - assert len(mock_receivers) == 1 - - events = [] - - def listener(event): - events.append(event) - - hass.bus.async_listen(const.EVENT_NETWORK_COMPLETE_SOME_DEAD, listener) - - await hass.async_add_executor_job(mock_receivers[0]) - await hass.async_block_till_done() - - assert len(events) == 1 - - -async def test_entity_discovery( - hass, mock_discovery, mock_import_module, mock_values, mock_openzwave, zwave_setup -): - """Test the creation of a new entity.""" - (node, value_class, mock_schema) = mock_values - - registry = mock_registry(hass) - - entity_id = "mock_component.mock_node_mock_value" - zwave_config = {"zwave": {}} - device_config = {entity_id: {}} - - with patch.object(zwave, "discovery", mock_discovery), patch.object( - zwave, "import_module", mock_import_module - ): - values = zwave.ZWaveDeviceEntityValues( - hass=hass, - schema=mock_schema, - primary_value=value_class.primary, - zwave_config=zwave_config, - device_config=device_config, - registry=registry, - ) - assert not mock_discovery.async_load_platform.called - - assert values.primary is value_class.primary - assert len(list(values)) == 3 - assert sorted(values, key=lambda a: id(a)) == sorted( - [value_class.primary, None, None], key=lambda a: id(a) - ) - - with patch.object(zwave, "discovery", mock_discovery), patch.object( - zwave, "import_module", mock_import_module - ): - values.check_value(value_class.secondary) - await hass.async_block_till_done() - - assert mock_discovery.async_load_platform.called - assert len(mock_discovery.async_load_platform.mock_calls) == 1 - - args = mock_discovery.async_load_platform.mock_calls[0][1] - assert args[0] == hass - assert args[1] == "mock_component" - assert args[2] == "zwave" - assert args[3] == { - const.DISCOVERY_DEVICE: mock_import_module().get_device().unique_id - } - assert args[4] == zwave_config - - assert values.secondary is value_class.secondary - assert len(list(values)) == 3 - assert sorted(values, key=lambda a: id(a)) == sorted( - [value_class.primary, value_class.secondary, None], key=lambda a: id(a) - ) - - mock_discovery.async_load_platform.reset_mock() - with patch.object(zwave, "discovery", mock_discovery), patch.object( - zwave, "import_module", mock_import_module - ): - values.check_value(value_class.optional) - values.check_value(value_class.duplicate_secondary) - values.check_value(value_class.no_match_value) - await hass.async_block_till_done() - - assert not mock_discovery.async_load_platform.called - - assert values.optional is value_class.optional - assert len(list(values)) == 3 - assert sorted(values, key=lambda a: id(a)) == sorted( - [value_class.primary, value_class.secondary, value_class.optional], - key=lambda a: id(a), - ) - - assert values._entity.value_added.called - assert len(values._entity.value_added.mock_calls) == 1 - assert values._entity.value_changed.called - assert len(values._entity.value_changed.mock_calls) == 1 - - -async def test_entity_existing_values( - hass, mock_discovery, mock_import_module, mock_values, mock_openzwave, zwave_setup -): - """Test the loading of already discovered values.""" - (node, value_class, mock_schema) = mock_values - - registry = mock_registry(hass) - - entity_id = "mock_component.mock_node_mock_value" - zwave_config = {"zwave": {}} - device_config = {entity_id: {}} - - node.values = { - value_class.primary.value_id: value_class.primary, - value_class.secondary.value_id: value_class.secondary, - value_class.optional.value_id: value_class.optional, - value_class.no_match_value.value_id: value_class.no_match_value, - } - - with patch.object(zwave, "discovery", mock_discovery), patch.object( - zwave, "import_module", mock_import_module - ): - values = zwave.ZWaveDeviceEntityValues( - hass=hass, - schema=mock_schema, - primary_value=value_class.primary, - zwave_config=zwave_config, - device_config=device_config, - registry=registry, - ) - await hass.async_block_till_done() - - assert mock_discovery.async_load_platform.called - assert len(mock_discovery.async_load_platform.mock_calls) == 1 - args = mock_discovery.async_load_platform.mock_calls[0][1] - assert args[0] == hass - assert args[1] == "mock_component" - assert args[2] == "zwave" - assert args[3] == { - const.DISCOVERY_DEVICE: mock_import_module().get_device().unique_id - } - assert args[4] == zwave_config - assert not value_class.primary.enable_poll.called - - assert values.primary is value_class.primary - assert values.secondary is value_class.secondary - assert values.optional is value_class.optional - assert len(list(values)) == 3 - assert sorted(values, key=lambda a: id(a)) == sorted( - [value_class.primary, value_class.secondary, value_class.optional], - key=lambda a: id(a), - ) - - -async def test_node_schema_mismatch( - hass, mock_discovery, mock_import_module, mock_values, mock_openzwave, zwave_setup -): - """Test node schema mismatch.""" - (node, value_class, mock_schema) = mock_values - - registry = mock_registry(hass) - - entity_id = "mock_component.mock_node_mock_value" - zwave_config = {"zwave": {}} - device_config = {entity_id: {}} - - node.generic = "no_match" - node.values = { - value_class.primary.value_id: value_class.primary, - value_class.secondary.value_id: value_class.secondary, - } - mock_schema[const.DISC_GENERIC_DEVICE_CLASS] = ["generic_match"] - - with patch.object(zwave, "discovery", mock_discovery), patch.object( - zwave, "import_module", mock_import_module - ): - values = zwave.ZWaveDeviceEntityValues( - hass=hass, - schema=mock_schema, - primary_value=value_class.primary, - zwave_config=zwave_config, - device_config=device_config, - registry=registry, - ) - values._check_entity_ready() - await hass.async_block_till_done() - - assert not mock_discovery.async_load_platform.called - - -async def test_entity_workaround_component( - hass, mock_discovery, mock_import_module, mock_values, mock_openzwave, zwave_setup -): - """Test component workaround.""" - (node, value_class, mock_schema) = mock_values - - registry = mock_registry(hass) - - node.manufacturer_id = "010f" - node.product_type = "0b00" - value_class.primary.command_class = const.COMMAND_CLASS_SENSOR_ALARM - - entity_id = "binary_sensor.mock_node_mock_value" - zwave_config = {"zwave": {}} - device_config = {entity_id: {}} - - mock_schema = { - const.DISC_COMPONENT: "mock_component", - const.DISC_VALUES: { - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_BINARY] - } - }, - } - - with patch.object( - zwave, "async_dispatcher_send" - ) as mock_dispatch_send, patch.object( - zwave, "discovery", mock_discovery - ), patch.object( - zwave, "import_module", mock_import_module - ): - - values = zwave.ZWaveDeviceEntityValues( - hass=hass, - schema=mock_schema, - primary_value=value_class.primary, - zwave_config=zwave_config, - device_config=device_config, - registry=registry, - ) - values._check_entity_ready() - await hass.async_block_till_done() - - assert mock_dispatch_send.called - assert len(mock_dispatch_send.mock_calls) == 1 - args = mock_dispatch_send.mock_calls[0][1] - assert args[1] == "zwave_new_binary_sensor" - - -async def test_entity_workaround_ignore( - hass, mock_discovery, mock_import_module, mock_values, mock_openzwave, zwave_setup -): - """Test ignore workaround.""" - (node, value_class, mock_schema) = mock_values - - registry = mock_registry(hass) - - entity_id = "mock_component.mock_node_mock_value" - zwave_config = {"zwave": {}} - device_config = {entity_id: {}} - - node.manufacturer_id = "010f" - node.product_type = "0301" - value_class.primary.command_class = const.COMMAND_CLASS_SWITCH_BINARY - - mock_schema = { - const.DISC_COMPONENT: "mock_component", - const.DISC_VALUES: { - const.DISC_PRIMARY: { - const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SWITCH_BINARY] - } - }, - } - - with patch.object(zwave, "discovery", mock_discovery), patch.object( - zwave, "import_module", mock_import_module - ): - values = zwave.ZWaveDeviceEntityValues( - hass=hass, - schema=mock_schema, - primary_value=value_class.primary, - zwave_config=zwave_config, - device_config=device_config, - registry=registry, - ) - values._check_entity_ready() - await hass.async_block_till_done() - - assert not mock_discovery.async_load_platform.called - - -async def test_entity_config_ignore( - hass, mock_discovery, mock_import_module, mock_values, mock_openzwave, zwave_setup -): - """Test ignore config.""" - (node, value_class, mock_schema) = mock_values - - registry = mock_registry(hass) - - entity_id = "mock_component.mock_node_mock_value" - zwave_config = {"zwave": {}} - device_config = {entity_id: {}} - - node.values = { - value_class.primary.value_id: value_class.primary, - value_class.secondary.value_id: value_class.secondary, - } - device_config = {entity_id: {zwave.CONF_IGNORED: True}} - - with patch.object(zwave, "discovery", mock_discovery), patch.object( - zwave, "import_module", mock_import_module - ): - values = zwave.ZWaveDeviceEntityValues( - hass=hass, - schema=mock_schema, - primary_value=value_class.primary, - zwave_config=zwave_config, - device_config=device_config, - registry=registry, - ) - values._check_entity_ready() - await hass.async_block_till_done() - - assert not mock_discovery.async_load_platform.called - - -async def test_entity_config_ignore_with_registry( - hass, mock_discovery, mock_import_module, mock_values, mock_openzwave, zwave_setup -): - """Test ignore config. - - The case when the device is in entity registry. - """ - (node, value_class, mock_schema) = mock_values - - registry = mock_registry(hass) - - entity_id = "mock_component.mock_node_mock_value" - zwave_config = {"zwave": {}} - device_config = {entity_id: {}} - - node.values = { - value_class.primary.value_id: value_class.primary, - value_class.secondary.value_id: value_class.secondary, - } - device_config = {"mock_component.registry_id": {zwave.CONF_IGNORED: True}} - with patch.object(registry, "async_schedule_save"): - registry.async_get_or_create( - "mock_component", - zwave.DOMAIN, - "567-1000", - suggested_object_id="registry_id", - ) - - with patch.object(zwave, "discovery", mock_discovery), patch.object( - zwave, "import_module", mock_import_module - ): - zwave.ZWaveDeviceEntityValues( - hass=hass, - schema=mock_schema, - primary_value=value_class.primary, - zwave_config=zwave_config, - device_config=device_config, - registry=registry, - ) - await hass.async_block_till_done() - - assert not mock_discovery.async_load_platform.called - - -async def test_entity_platform_ignore( - hass, mock_discovery, mock_import_module, mock_values, mock_openzwave, zwave_setup -): - """Test platform ignore device.""" - (node, value_class, mock_schema) = mock_values - - registry = mock_registry(hass) - - entity_id = "mock_component.mock_node_mock_value" - zwave_config = {"zwave": {}} - device_config = {entity_id: {}} - - node.values = { - value_class.primary.value_id: value_class.primary, - value_class.secondary.value_id: value_class.secondary, - } - - import_module = MagicMock() - platform = MagicMock() - import_module.return_value = platform - platform.get_device.return_value = None - - with patch.object(zwave, "discovery", mock_discovery), patch.object( - zwave, "import_module", import_module - ): - zwave.ZWaveDeviceEntityValues( - hass=hass, - schema=mock_schema, - primary_value=value_class.primary, - zwave_config=zwave_config, - device_config=device_config, - registry=registry, - ) - await hass.async_block_till_done() - - assert not mock_discovery.async_load_platform.called - - -async def test_config_polling_intensity( - hass, mock_discovery, mock_import_module, mock_values, mock_openzwave, zwave_setup -): - """Test polling intensity.""" - (node, value_class, mock_schema) = mock_values - - registry = mock_registry(hass) - - entity_id = "mock_component.mock_node_mock_value" - zwave_config = {"zwave": {}} - device_config = {entity_id: {}} - - node.values = { - value_class.primary.value_id: value_class.primary, - value_class.secondary.value_id: value_class.secondary, - } - device_config = {entity_id: {zwave.CONF_POLLING_INTENSITY: 123}} - - with patch.object(zwave, "discovery", mock_discovery), patch.object( - zwave, "import_module", mock_import_module - ): - values = zwave.ZWaveDeviceEntityValues( - hass=hass, - schema=mock_schema, - primary_value=value_class.primary, - zwave_config=zwave_config, - device_config=device_config, - registry=registry, - ) - values._check_entity_ready() - await hass.async_block_till_done() - - assert mock_discovery.async_load_platform.called - - assert value_class.primary.enable_poll.called - assert len(value_class.primary.enable_poll.mock_calls) == 1 - assert value_class.primary.enable_poll.mock_calls[0][1][0] == 123 - - -async def test_device_config_glob_is_ordered(): - """Test that device_config_glob preserves order.""" - conf = CONFIG_SCHEMA({"zwave": {CONF_DEVICE_CONFIG_GLOB: OrderedDict()}}) - assert isinstance(conf["zwave"][CONF_DEVICE_CONFIG_GLOB], OrderedDict) - - -async def test_add_node(hass, mock_openzwave, zwave_setup_ready): - """Test zwave add_node service.""" - zwave_network = hass.data[DATA_NETWORK] - - await hass.services.async_call("zwave", "add_node", {}) - await hass.async_block_till_done() - - assert zwave_network.controller.add_node.called - assert len(zwave_network.controller.add_node.mock_calls) == 1 - assert len(zwave_network.controller.add_node.mock_calls[0][1]) == 0 - - -async def test_add_node_secure(hass, mock_openzwave, zwave_setup_ready): - """Test zwave add_node_secure service.""" - zwave_network = hass.data[DATA_NETWORK] - - await hass.services.async_call("zwave", "add_node_secure", {}) - await hass.async_block_till_done() - - assert zwave_network.controller.add_node.called - assert len(zwave_network.controller.add_node.mock_calls) == 1 - assert zwave_network.controller.add_node.mock_calls[0][1][0] is True - - -async def test_remove_node(hass, mock_openzwave, zwave_setup_ready): - """Test zwave remove_node service.""" - zwave_network = hass.data[DATA_NETWORK] - - await hass.services.async_call("zwave", "remove_node", {}) - await hass.async_block_till_done() - - assert zwave_network.controller.remove_node.called - assert len(zwave_network.controller.remove_node.mock_calls) == 1 - - -async def test_cancel_command(hass, mock_openzwave, zwave_setup_ready): - """Test zwave cancel_command service.""" - zwave_network = hass.data[DATA_NETWORK] - - await hass.services.async_call("zwave", "cancel_command", {}) - await hass.async_block_till_done() - - assert zwave_network.controller.cancel_command.called - assert len(zwave_network.controller.cancel_command.mock_calls) == 1 - - -async def test_heal_network(hass, mock_openzwave, zwave_setup_ready): - """Test zwave heal_network service.""" - zwave_network = hass.data[DATA_NETWORK] - - await hass.services.async_call("zwave", "heal_network", {}) - await hass.async_block_till_done() - - assert zwave_network.heal.called - assert len(zwave_network.heal.mock_calls) == 1 - - -async def test_soft_reset(hass, mock_openzwave, zwave_setup_ready): - """Test zwave soft_reset service.""" - zwave_network = hass.data[DATA_NETWORK] - - await hass.services.async_call("zwave", "soft_reset", {}) - await hass.async_block_till_done() - - assert zwave_network.controller.soft_reset.called - assert len(zwave_network.controller.soft_reset.mock_calls) == 1 - - -async def test_test_network(hass, mock_openzwave, zwave_setup_ready): - """Test zwave test_network service.""" - zwave_network = hass.data[DATA_NETWORK] - - await hass.services.async_call("zwave", "test_network", {}) - await hass.async_block_till_done() - - assert zwave_network.test.called - assert len(zwave_network.test.mock_calls) == 1 - - -async def test_stop_network(hass, mock_openzwave, zwave_setup_ready): - """Test zwave stop_network service.""" - zwave_network = hass.data[DATA_NETWORK] - - with patch.object(hass.bus, "fire") as mock_fire: - await hass.services.async_call("zwave", "stop_network", {}) - await hass.async_block_till_done() - - assert zwave_network.stop.called - assert len(zwave_network.stop.mock_calls) == 1 - assert mock_fire.called - assert len(mock_fire.mock_calls) == 1 - assert mock_fire.mock_calls[0][1][0] == const.EVENT_NETWORK_STOP - - -async def test_rename_node(hass, mock_openzwave, zwave_setup_ready): - """Test zwave rename_node service.""" - zwave_network = hass.data[DATA_NETWORK] - - zwave_network.nodes = {11: MagicMock()} - await hass.services.async_call( - "zwave", - "rename_node", - {const.ATTR_NODE_ID: 11, ATTR_NAME: "test_name"}, - ) - await hass.async_block_till_done() - - assert zwave_network.nodes[11].name == "test_name" - - -async def test_rename_value(hass, mock_openzwave, zwave_setup_ready): - """Test zwave rename_value service.""" - zwave_network = hass.data[DATA_NETWORK] - - node = MockNode(node_id=14) - value = MockValue(index=12, value_id=123456, label="Old Label") - node.values = {123456: value} - zwave_network.nodes = {11: node} - - assert value.label == "Old Label" - await hass.services.async_call( - "zwave", - "rename_value", - { - const.ATTR_NODE_ID: 11, - const.ATTR_VALUE_ID: 123456, - ATTR_NAME: "New Label", - }, - ) - await hass.async_block_till_done() - - assert value.label == "New Label" - - -async def test_set_poll_intensity_enable(hass, mock_openzwave, zwave_setup_ready): - """Test zwave set_poll_intensity service, successful set.""" - zwave_network = hass.data[DATA_NETWORK] - - node = MockNode(node_id=14) - value = MockValue(index=12, value_id=123456, poll_intensity=0) - node.values = {123456: value} - zwave_network.nodes = {11: node} - - assert value.poll_intensity == 0 - await hass.services.async_call( - "zwave", - "set_poll_intensity", - { - const.ATTR_NODE_ID: 11, - const.ATTR_VALUE_ID: 123456, - const.ATTR_POLL_INTENSITY: 4, - }, - ) - await hass.async_block_till_done() - - enable_poll = value.enable_poll - assert value.enable_poll.called - assert len(enable_poll.mock_calls) == 2 - assert enable_poll.mock_calls[0][1][0] == 4 - - -async def test_set_poll_intensity_enable_failed( - hass, mock_openzwave, zwave_setup_ready -): - """Test zwave set_poll_intensity service, failed set.""" - zwave_network = hass.data[DATA_NETWORK] - - node = MockNode(node_id=14) - value = MockValue(index=12, value_id=123456, poll_intensity=0) - value.enable_poll.return_value = False - node.values = {123456: value} - zwave_network.nodes = {11: node} - - assert value.poll_intensity == 0 - await hass.services.async_call( - "zwave", - "set_poll_intensity", - { - const.ATTR_NODE_ID: 11, - const.ATTR_VALUE_ID: 123456, - const.ATTR_POLL_INTENSITY: 4, - }, - ) - await hass.async_block_till_done() - - enable_poll = value.enable_poll - assert value.enable_poll.called - assert len(enable_poll.mock_calls) == 1 - - -async def test_set_poll_intensity_disable(hass, mock_openzwave, zwave_setup_ready): - """Test zwave set_poll_intensity service, successful disable.""" - zwave_network = hass.data[DATA_NETWORK] - - node = MockNode(node_id=14) - value = MockValue(index=12, value_id=123456, poll_intensity=4) - node.values = {123456: value} - zwave_network.nodes = {11: node} - - assert value.poll_intensity == 4 - await hass.services.async_call( - "zwave", - "set_poll_intensity", - { - const.ATTR_NODE_ID: 11, - const.ATTR_VALUE_ID: 123456, - const.ATTR_POLL_INTENSITY: 0, - }, - ) - await hass.async_block_till_done() - - disable_poll = value.disable_poll - assert value.disable_poll.called - assert len(disable_poll.mock_calls) == 2 - - -async def test_set_poll_intensity_disable_failed( - hass, mock_openzwave, zwave_setup_ready -): - """Test zwave set_poll_intensity service, failed disable.""" - zwave_network = hass.data[DATA_NETWORK] - - node = MockNode(node_id=14) - value = MockValue(index=12, value_id=123456, poll_intensity=4) - value.disable_poll.return_value = False - node.values = {123456: value} - zwave_network.nodes = {11: node} - - assert value.poll_intensity == 4 - await hass.services.async_call( - "zwave", - "set_poll_intensity", - { - const.ATTR_NODE_ID: 11, - const.ATTR_VALUE_ID: 123456, - const.ATTR_POLL_INTENSITY: 0, - }, - ) - await hass.async_block_till_done() - - disable_poll = value.disable_poll - assert value.disable_poll.called - assert len(disable_poll.mock_calls) == 1 - - -async def test_remove_failed_node(hass, mock_openzwave, zwave_setup_ready): - """Test zwave remove_failed_node service.""" - zwave_network = hass.data[DATA_NETWORK] - - await hass.services.async_call( - "zwave", "remove_failed_node", {const.ATTR_NODE_ID: 12} - ) - await hass.async_block_till_done() - - remove_failed_node = zwave_network.controller.remove_failed_node - assert remove_failed_node.called - assert len(remove_failed_node.mock_calls) == 1 - assert remove_failed_node.mock_calls[0][1][0] == 12 - - -async def test_replace_failed_node(hass, mock_openzwave, zwave_setup_ready): - """Test zwave replace_failed_node service.""" - zwave_network = hass.data[DATA_NETWORK] - - await hass.services.async_call( - "zwave", "replace_failed_node", {const.ATTR_NODE_ID: 13} - ) - await hass.async_block_till_done() - - replace_failed_node = zwave_network.controller.replace_failed_node - assert replace_failed_node.called - assert len(replace_failed_node.mock_calls) == 1 - assert replace_failed_node.mock_calls[0][1][0] == 13 - - -async def test_set_config_parameter(hass, mock_openzwave, zwave_setup_ready): - """Test zwave set_config_parameter service.""" - zwave_network = hass.data[DATA_NETWORK] - - value_byte = MockValue( - index=12, - command_class=const.COMMAND_CLASS_CONFIGURATION, - type=const.TYPE_BYTE, - ) - value_list = MockValue( - index=13, - command_class=const.COMMAND_CLASS_CONFIGURATION, - type=const.TYPE_LIST, - data_items=["item1", "item2", "item3"], - ) - value_button = MockValue( - index=14, - command_class=const.COMMAND_CLASS_CONFIGURATION, - type=const.TYPE_BUTTON, - ) - value_list_int = MockValue( - index=15, - command_class=const.COMMAND_CLASS_CONFIGURATION, - type=const.TYPE_LIST, - data_items=["1", "2", "3"], - ) - value_bool = MockValue( - index=16, - command_class=const.COMMAND_CLASS_CONFIGURATION, - type=const.TYPE_BOOL, - ) - node = MockNode(node_id=14) - node.get_values.return_value = { - 12: value_byte, - 13: value_list, - 14: value_button, - 15: value_list_int, - 16: value_bool, - } - zwave_network.nodes = {14: node} - - # Byte - await hass.services.async_call( - "zwave", - "set_config_parameter", - { - const.ATTR_NODE_ID: 14, - const.ATTR_CONFIG_PARAMETER: 12, - const.ATTR_CONFIG_VALUE: 7, - }, - ) - await hass.async_block_till_done() - - assert value_byte.data == 7 - - # List - await hass.services.async_call( - "zwave", - "set_config_parameter", - { - const.ATTR_NODE_ID: 14, - const.ATTR_CONFIG_PARAMETER: 13, - const.ATTR_CONFIG_VALUE: "item3", - }, - ) - await hass.async_block_till_done() - - assert value_list.data == "item3" - - # Button - await hass.services.async_call( - "zwave", - "set_config_parameter", - { - const.ATTR_NODE_ID: 14, - const.ATTR_CONFIG_PARAMETER: 14, - const.ATTR_CONFIG_VALUE: True, - }, - ) - await hass.async_block_till_done() - - assert zwave_network.manager.pressButton.called - assert zwave_network.manager.releaseButton.called - - # List of Ints - await hass.services.async_call( - "zwave", - "set_config_parameter", - { - const.ATTR_NODE_ID: 14, - const.ATTR_CONFIG_PARAMETER: 15, - const.ATTR_CONFIG_VALUE: 3, - }, - ) - await hass.async_block_till_done() - - assert value_list_int.data == "3" - - # Boolean Truthy - await hass.services.async_call( - "zwave", - "set_config_parameter", - { - const.ATTR_NODE_ID: 14, - const.ATTR_CONFIG_PARAMETER: 16, - const.ATTR_CONFIG_VALUE: "True", - }, - ) - await hass.async_block_till_done() - - assert value_bool.data == 1 - - # Boolean Falsy - await hass.services.async_call( - "zwave", - "set_config_parameter", - { - const.ATTR_NODE_ID: 14, - const.ATTR_CONFIG_PARAMETER: 16, - const.ATTR_CONFIG_VALUE: "False", - }, - ) - await hass.async_block_till_done() - - assert value_bool.data == 0 - - # Different Parameter Size - await hass.services.async_call( - "zwave", - "set_config_parameter", - { - const.ATTR_NODE_ID: 14, - const.ATTR_CONFIG_PARAMETER: 19, - const.ATTR_CONFIG_VALUE: 0x01020304, - const.ATTR_CONFIG_SIZE: 4, - }, - ) - await hass.async_block_till_done() - - assert node.set_config_param.called - assert len(node.set_config_param.mock_calls) == 1 - assert node.set_config_param.mock_calls[0][1][0] == 19 - assert node.set_config_param.mock_calls[0][1][1] == 0x01020304 - assert node.set_config_param.mock_calls[0][1][2] == 4 - node.set_config_param.reset_mock() - - -async def test_print_config_parameter(hass, mock_openzwave, zwave_setup_ready, caplog): - """Test zwave print_config_parameter service.""" - zwave_network = hass.data[DATA_NETWORK] - - value1 = MockValue( - index=12, command_class=const.COMMAND_CLASS_CONFIGURATION, data=1234 - ) - value2 = MockValue( - index=13, command_class=const.COMMAND_CLASS_CONFIGURATION, data=2345 - ) - node = MockNode(node_id=14) - node.values = {12: value1, 13: value2} - zwave_network.nodes = {14: node} - - caplog.clear() - - await hass.services.async_call( - "zwave", - "print_config_parameter", - {const.ATTR_NODE_ID: 14, const.ATTR_CONFIG_PARAMETER: 13}, - ) - await hass.async_block_till_done() - - assert "Config parameter 13 on Node 14: 2345" in caplog.text - - -async def test_print_node(hass, mock_openzwave, zwave_setup_ready): - """Test zwave print_node_parameter service.""" - zwave_network = hass.data[DATA_NETWORK] - - node = MockNode(node_id=14) - - zwave_network.nodes = {14: node} - - with patch.object(zwave, "_LOGGER") as mock_logger: - await hass.services.async_call("zwave", "print_node", {const.ATTR_NODE_ID: 14}) - await hass.async_block_till_done() - - assert "FOUND NODE " in mock_logger.info.mock_calls[0][1][0] - - -async def test_set_wakeup(hass, mock_openzwave, zwave_setup_ready): - """Test zwave set_wakeup service.""" - zwave_network = hass.data[DATA_NETWORK] - - value = MockValue(index=12, command_class=const.COMMAND_CLASS_WAKE_UP) - node = MockNode(node_id=14) - node.values = {12: value} - node.get_values.return_value = node.values - zwave_network.nodes = {14: node} - - await hass.services.async_call( - "zwave", "set_wakeup", {const.ATTR_NODE_ID: 14, const.ATTR_CONFIG_VALUE: 15} - ) - await hass.async_block_till_done() - - assert value.data == 15 - - node.can_wake_up_value = False - await hass.services.async_call( - "zwave", "set_wakeup", {const.ATTR_NODE_ID: 14, const.ATTR_CONFIG_VALUE: 20} - ) - await hass.async_block_till_done() - - assert value.data == 15 - - -async def test_reset_node_meters(hass, mock_openzwave, zwave_setup_ready): - """Test zwave reset_node_meters service.""" - zwave_network = hass.data[DATA_NETWORK] - - value = MockValue( - instance=1, index=8, data=99.5, command_class=const.COMMAND_CLASS_METER - ) - reset_value = MockValue( - instance=1, index=33, command_class=const.COMMAND_CLASS_METER - ) - node = MockNode(node_id=14) - node.values = {8: value, 33: reset_value} - node.get_values.return_value = node.values - zwave_network.nodes = {14: node} - - await hass.services.async_call( - "zwave", - "reset_node_meters", - {const.ATTR_NODE_ID: 14, const.ATTR_INSTANCE: 2}, - ) - await hass.async_block_till_done() - - assert not zwave_network.manager.pressButton.called - assert not zwave_network.manager.releaseButton.called - - await hass.services.async_call( - "zwave", "reset_node_meters", {const.ATTR_NODE_ID: 14} - ) - await hass.async_block_till_done() - - assert zwave_network.manager.pressButton.called - (value_id,) = zwave_network.manager.pressButton.mock_calls.pop(0)[1] - assert value_id == reset_value.value_id - assert zwave_network.manager.releaseButton.called - (value_id,) = zwave_network.manager.releaseButton.mock_calls.pop(0)[1] - assert value_id == reset_value.value_id - - -async def test_add_association(hass, mock_openzwave, zwave_setup_ready): - """Test zwave change_association service.""" - zwave_network = hass.data[DATA_NETWORK] - - ZWaveGroup = mock_openzwave.group.ZWaveGroup - group = MagicMock() - ZWaveGroup.return_value = group - - value = MockValue(index=12, command_class=const.COMMAND_CLASS_WAKE_UP) - node = MockNode(node_id=14) - node.values = {12: value} - node.get_values.return_value = node.values - zwave_network.nodes = {14: node} - - await hass.services.async_call( - "zwave", - "change_association", - { - const.ATTR_ASSOCIATION: "add", - const.ATTR_NODE_ID: 14, - const.ATTR_TARGET_NODE_ID: 24, - const.ATTR_GROUP: 3, - const.ATTR_INSTANCE: 5, - }, - ) - await hass.async_block_till_done() - - assert ZWaveGroup.called - assert len(ZWaveGroup.mock_calls) == 2 - assert ZWaveGroup.mock_calls[0][1][0] == 3 - assert ZWaveGroup.mock_calls[0][1][2] == 14 - assert group.add_association.called - assert len(group.add_association.mock_calls) == 1 - assert group.add_association.mock_calls[0][1][0] == 24 - assert group.add_association.mock_calls[0][1][1] == 5 - - -async def test_remove_association(hass, mock_openzwave, zwave_setup_ready): - """Test zwave change_association service.""" - zwave_network = hass.data[DATA_NETWORK] - - ZWaveGroup = mock_openzwave.group.ZWaveGroup - group = MagicMock() - ZWaveGroup.return_value = group - - value = MockValue(index=12, command_class=const.COMMAND_CLASS_WAKE_UP) - node = MockNode(node_id=14) - node.values = {12: value} - node.get_values.return_value = node.values - zwave_network.nodes = {14: node} - - await hass.services.async_call( - "zwave", - "change_association", - { - const.ATTR_ASSOCIATION: "remove", - const.ATTR_NODE_ID: 14, - const.ATTR_TARGET_NODE_ID: 24, - const.ATTR_GROUP: 3, - const.ATTR_INSTANCE: 5, - }, - ) - await hass.async_block_till_done() - - assert ZWaveGroup.called - assert len(ZWaveGroup.mock_calls) == 2 - assert ZWaveGroup.mock_calls[0][1][0] == 3 - assert ZWaveGroup.mock_calls[0][1][2] == 14 - assert group.remove_association.called - assert len(group.remove_association.mock_calls) == 1 - assert group.remove_association.mock_calls[0][1][0] == 24 - assert group.remove_association.mock_calls[0][1][1] == 5 - - -async def test_refresh_node(hass, mock_openzwave, zwave_setup_ready): - """Test zwave refresh_node service.""" - zwave_network = hass.data[DATA_NETWORK] - - node = MockNode(node_id=14) - zwave_network.nodes = {14: node} - await hass.services.async_call("zwave", "refresh_node", {const.ATTR_NODE_ID: 14}) - await hass.async_block_till_done() - - assert node.refresh_info.called - assert len(node.refresh_info.mock_calls) == 1 - - -async def test_set_node_value(hass, mock_openzwave, zwave_setup_ready): - """Test zwave set_node_value service.""" - zwave_network = hass.data[DATA_NETWORK] - - value = MockValue(index=12, command_class=const.COMMAND_CLASS_INDICATOR, data=4) - node = MockNode(node_id=14, command_classes=[const.COMMAND_CLASS_INDICATOR]) - node.values = {12: value} - node.get_values.return_value = node.values - zwave_network.nodes = {14: node} - - await hass.services.async_call( - "zwave", - "set_node_value", - { - const.ATTR_NODE_ID: 14, - const.ATTR_VALUE_ID: 12, - const.ATTR_CONFIG_VALUE: 2, - }, - ) - await hass.async_block_till_done() - - assert zwave_network.nodes[14].values[12].data == 2 - - -async def test_set_node_value_with_long_id_and_text_value( - hass, mock_openzwave, zwave_setup_ready -): - """Test zwave set_node_value service.""" - zwave_network = hass.data[DATA_NETWORK] - - value = MockValue( - index=87512398541236578, - command_class=const.COMMAND_CLASS_SWITCH_COLOR, - data="#ff0000", - ) - node = MockNode(node_id=14, command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - node.values = {87512398541236578: value} - node.get_values.return_value = node.values - zwave_network.nodes = {14: node} - - await hass.services.async_call( - "zwave", - "set_node_value", - { - const.ATTR_NODE_ID: 14, - const.ATTR_VALUE_ID: "87512398541236578", - const.ATTR_CONFIG_VALUE: "#00ff00", - }, - ) - await hass.async_block_till_done() - - assert zwave_network.nodes[14].values[87512398541236578].data == "#00ff00" - - -async def test_refresh_node_value(hass, mock_openzwave, zwave_setup_ready): - """Test zwave refresh_node_value service.""" - zwave_network = hass.data[DATA_NETWORK] - - node = MockNode( - node_id=14, - command_classes=[const.COMMAND_CLASS_INDICATOR], - network=zwave_network, - ) - value = MockValue( - node=node, index=12, command_class=const.COMMAND_CLASS_INDICATOR, data=2 - ) - value.refresh = MagicMock() - - node.values = {12: value} - node.get_values.return_value = node.values - zwave_network.nodes = {14: node} - - await hass.services.async_call( - "zwave", - "refresh_node_value", - {const.ATTR_NODE_ID: 14, const.ATTR_VALUE_ID: 12}, - ) - await hass.async_block_till_done() - - assert value.refresh.called - - -async def test_heal_node(hass, mock_openzwave, zwave_setup_ready): - """Test zwave heal_node service.""" - zwave_network = hass.data[DATA_NETWORK] - - node = MockNode(node_id=19) - zwave_network.nodes = {19: node} - await hass.services.async_call("zwave", "heal_node", {const.ATTR_NODE_ID: 19}) - await hass.async_block_till_done() - - assert node.heal.called - assert len(node.heal.mock_calls) == 1 - - -async def test_test_node(hass, mock_openzwave, zwave_setup_ready): - """Test the zwave test_node service.""" - zwave_network = hass.data[DATA_NETWORK] - - node = MockNode(node_id=19) - zwave_network.nodes = {19: node} - await hass.services.async_call("zwave", "test_node", {const.ATTR_NODE_ID: 19}) - await hass.async_block_till_done() - - assert node.test.called - assert len(node.test.mock_calls) == 1 diff --git a/tests/components/zwave/test_light.py b/tests/components/zwave/test_light.py deleted file mode 100644 index 87bfb1ec726..00000000000 --- a/tests/components/zwave/test_light.py +++ /dev/null @@ -1,481 +0,0 @@ -"""Test Z-Wave lights.""" -from unittest.mock import MagicMock, patch - -import pytest - -from homeassistant.components import zwave -from homeassistant.components.light import ( - ATTR_BRIGHTNESS, - ATTR_COLOR_TEMP, - ATTR_RGB_COLOR, - ATTR_RGBW_COLOR, - ATTR_TRANSITION, - COLOR_MODE_BRIGHTNESS, - COLOR_MODE_COLOR_TEMP, - COLOR_MODE_RGB, - COLOR_MODE_RGBW, - SUPPORT_TRANSITION, -) -from homeassistant.components.zwave import const, light - -from tests.mock.zwave import MockEntityValues, MockNode, MockValue, value_changed - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -class MockLightValues(MockEntityValues): - """Mock Z-Wave light values.""" - - def __init__(self, **kwargs): - """Initialize the mock zwave values.""" - self.dimming_duration = None - self.color = None - self.color_channels = None - super().__init__(**kwargs) - - -def test_get_device_detects_dimmer(mock_openzwave): - """Test get_device returns a normal dimmer.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockLightValues(primary=value) - - device = light.get_device(node=node, values=values, node_config={}) - assert isinstance(device, light.ZwaveDimmer) - assert device.color_mode == COLOR_MODE_BRIGHTNESS - assert device.supported_features == 0 - assert device.supported_color_modes == {COLOR_MODE_BRIGHTNESS} - - -def test_get_device_detects_colorlight(mock_openzwave): - """Test get_device returns a color light.""" - node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - value = MockValue(data=0, node=node) - values = MockLightValues(primary=value) - - device = light.get_device(node=node, values=values, node_config={}) - assert isinstance(device, light.ZwaveColorLight) - assert device.color_mode == COLOR_MODE_RGB - assert device.supported_features == 0 - assert device.supported_color_modes == {COLOR_MODE_RGB} - - -def test_get_device_detects_zw098(mock_openzwave): - """Test get_device returns a zw098 color light.""" - node = MockNode( - manufacturer_id="0086", - product_id="0062", - command_classes=[const.COMMAND_CLASS_SWITCH_COLOR], - ) - value = MockValue(data=0, node=node) - values = MockLightValues(primary=value) - device = light.get_device(node=node, values=values, node_config={}) - assert isinstance(device, light.ZwaveColorLight) - assert device.color_mode == COLOR_MODE_RGB - assert device.supported_features == 0 - assert device.supported_color_modes == {COLOR_MODE_COLOR_TEMP, COLOR_MODE_RGB} - - -def test_get_device_detects_rgbw_light(mock_openzwave): - """Test get_device returns a color light.""" - node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - value = MockValue(data=0, node=node) - color = MockValue(data="#0000000000", node=node) - color_channels = MockValue(data=0x1D, node=node) - values = MockLightValues(primary=value, color=color, color_channels=color_channels) - - device = light.get_device(node=node, values=values, node_config={}) - device.value_added() - assert isinstance(device, light.ZwaveColorLight) - assert device.color_mode == COLOR_MODE_RGBW - assert device.supported_features == 0 - assert device.supported_color_modes == {COLOR_MODE_RGBW} - - -def test_dimmer_turn_on(mock_openzwave): - """Test turning on a dimmable Z-Wave light.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockLightValues(primary=value) - device = light.get_device(node=node, values=values, node_config={}) - - device.turn_on() - - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - assert value_id == value.value_id - assert brightness == 255 - - node.reset_mock() - - device.turn_on(**{ATTR_BRIGHTNESS: 224}) - - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - - assert value_id == value.value_id - assert brightness == 87 # round(224 / 255 * 99) - - node.reset_mock() - - device.turn_on(**{ATTR_BRIGHTNESS: 120}) - - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - - assert value_id == value.value_id - assert brightness == 47 # round(120 / 255 * 99) - - with patch.object(light, "_LOGGER", MagicMock()) as mock_logger: - device.turn_on(**{ATTR_TRANSITION: 35}) - assert mock_logger.debug.called - assert node.set_dimmer.called - msg, entity_id = mock_logger.debug.mock_calls[0][1] - assert entity_id == device.entity_id - - -def test_dimmer_min_brightness(mock_openzwave): - """Test turning on a dimmable Z-Wave light to its minimum brightness.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockLightValues(primary=value) - device = light.get_device(node=node, values=values, node_config={}) - - assert not device.is_on - - device.turn_on(**{ATTR_BRIGHTNESS: 1}) - - assert device.is_on - assert device.brightness == 1 - - device.turn_on(**{ATTR_BRIGHTNESS: 0}) - - assert device.is_on - assert device.brightness == 0 - - -def test_dimmer_transitions(mock_openzwave): - """Test dimming transition on a dimmable Z-Wave light.""" - node = MockNode() - value = MockValue(data=0, node=node) - duration = MockValue(data=0, node=node) - values = MockLightValues(primary=value, dimming_duration=duration) - device = light.get_device(node=node, values=values, node_config={}) - assert device.color_mode == COLOR_MODE_BRIGHTNESS - assert device.supported_features == SUPPORT_TRANSITION - assert device.supported_color_modes == {COLOR_MODE_BRIGHTNESS} - - # Test turn_on - # Factory Default - device.turn_on() - assert duration.data == 0xFF - - # Seconds transition - device.turn_on(**{ATTR_TRANSITION: 45}) - assert duration.data == 45 - - # Minutes transition - device.turn_on(**{ATTR_TRANSITION: 245}) - assert duration.data == 0x83 - - # Clipped transition - device.turn_on(**{ATTR_TRANSITION: 10000}) - assert duration.data == 0xFE - - # Test turn_off - # Factory Default - device.turn_off() - assert duration.data == 0xFF - - # Seconds transition - device.turn_off(**{ATTR_TRANSITION: 45}) - assert duration.data == 45 - - # Minutes transition - device.turn_off(**{ATTR_TRANSITION: 245}) - assert duration.data == 0x83 - - # Clipped transition - device.turn_off(**{ATTR_TRANSITION: 10000}) - assert duration.data == 0xFE - - -def test_dimmer_turn_off(mock_openzwave): - """Test turning off a dimmable Z-Wave light.""" - node = MockNode() - value = MockValue(data=46, node=node) - values = MockLightValues(primary=value) - device = light.get_device(node=node, values=values, node_config={}) - - device.turn_off() - - assert node.set_dimmer.called - value_id, brightness = node.set_dimmer.mock_calls[0][1] - assert value_id == value.value_id - assert brightness == 0 - - -def test_dimmer_value_changed(mock_openzwave): - """Test value changed for dimmer lights.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockLightValues(primary=value) - device = light.get_device(node=node, values=values, node_config={}) - - assert not device.is_on - - value.data = 46 - value_changed(value) - - assert device.is_on - assert device.brightness == 118 - - -def test_dimmer_refresh_value(mock_openzwave): - """Test value changed for dimmer lights.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockLightValues(primary=value) - device = light.get_device( - node=node, - values=values, - node_config={zwave.CONF_REFRESH_VALUE: True, zwave.CONF_REFRESH_DELAY: 5}, - ) - - assert not device.is_on - - with patch.object(light, "Timer") as mock_timer: - value.data = 46 - value_changed(value) - - assert not device.is_on - assert mock_timer.called - assert len(mock_timer.mock_calls) == 2 - timeout, callback = mock_timer.mock_calls[0][1][:2] - assert timeout == 5 - assert mock_timer().start.called - assert len(mock_timer().start.mock_calls) == 1 - - with patch.object(light, "Timer") as mock_timer_2: - value_changed(value) - assert not device.is_on - assert mock_timer().cancel.called - assert len(mock_timer_2.mock_calls) == 2 - timeout, callback = mock_timer_2.mock_calls[0][1][:2] - assert timeout == 5 - assert mock_timer_2().start.called - assert len(mock_timer_2().start.mock_calls) == 1 - - callback() - assert device.is_on - assert device.brightness == 118 - - -def test_set_rgb_color(mock_openzwave): - """Test setting zwave light color.""" - node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - value = MockValue(data=0, node=node) - color = MockValue(data="#0000000000", node=node) - # Supports RGB only - color_channels = MockValue(data=0x1C, node=node) - values = MockLightValues(primary=value, color=color, color_channels=color_channels) - device = light.get_device(node=node, values=values, node_config={}) - - assert color.data == "#0000000000" - - device.turn_on(**{ATTR_RGB_COLOR: (0xFF, 0xBF, 0x7F)}) - - assert color.data == "#ffbf7f0000" - - -def test_set_white_value(mock_openzwave): - """Test setting zwave light color.""" - node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - value = MockValue(data=0, node=node) - color = MockValue(data="#0000000000", node=node) - # Supports RGBW - color_channels = MockValue(data=0x1D, node=node) - values = MockLightValues(primary=value, color=color, color_channels=color_channels) - device = light.get_device(node=node, values=values, node_config={}) - - assert color.data == "#0000000000" - - device.turn_on(**{ATTR_RGBW_COLOR: (0xFF, 0xFF, 0xFF, 0xC8)}) - - assert color.data == "#ffffffc800" - - -def test_disable_white_if_set_color(mock_openzwave): - """ - Test that _white is set to 0 if turn_on with ATTR_RGB_COLOR. - - See Issue #13930 - many RGBW ZWave bulbs will only activate the RGB LED to - produce color if _white is set to zero. - """ - node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - value = MockValue(data=0, node=node) - color = MockValue(data="#0000000000", node=node) - # Supports RGB only - color_channels = MockValue(data=0x1C, node=node) - values = MockLightValues(primary=value, color=color, color_channels=color_channels) - device = light.get_device(node=node, values=values, node_config={}) - device._white = 234 - - assert color.data == "#0000000000" - assert device.rgbw_color == (0, 0, 0, 234) - - device.turn_on(**{ATTR_RGB_COLOR: (0xFF, 0xBF, 0x7F)}) - - assert color.data == "#ffbf7f0000" - assert device.rgbw_color == (0xFF, 0xBF, 0x7F, 0x00) - - -def test_zw098_set_color_temp(mock_openzwave): - """Test setting zwave light color.""" - node = MockNode( - manufacturer_id="0086", - product_id="0062", - command_classes=[const.COMMAND_CLASS_SWITCH_COLOR], - ) - value = MockValue(data=0, node=node) - color = MockValue(data="#0000000000", node=node) - # Supports RGB, warm white, cold white - color_channels = MockValue(data=0x1F, node=node) - values = MockLightValues(primary=value, color=color, color_channels=color_channels) - device = light.get_device(node=node, values=values, node_config={}) - - assert color.data == "#0000000000" - - device.turn_on(**{ATTR_COLOR_TEMP: 200}) - - assert color.data == "#00000000ff" - - device.turn_on(**{ATTR_COLOR_TEMP: 400}) - - assert color.data == "#000000ff00" - - -def test_rgb_not_supported(mock_openzwave): - """Test value changed for rgb lights.""" - node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - value = MockValue(data=0, node=node) - color = MockValue(data="#0000000000", node=node) - # Supports color temperature only - color_channels = MockValue(data=0x01, node=node) - values = MockLightValues(primary=value, color=color, color_channels=color_channels) - device = light.get_device(node=node, values=values, node_config={}) - - assert device.rgb_color is None - assert device.rgbw_color is None - - -def test_no_color_value(mock_openzwave): - """Test value changed for rgb lights.""" - node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - value = MockValue(data=0, node=node) - values = MockLightValues(primary=value) - device = light.get_device(node=node, values=values, node_config={}) - - assert device.rgb_color is None - assert device.rgbw_color is None - - -def test_no_color_channels_value(mock_openzwave): - """Test value changed for rgb lights.""" - node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - value = MockValue(data=0, node=node) - color = MockValue(data="#0000000000", node=node) - values = MockLightValues(primary=value, color=color) - device = light.get_device(node=node, values=values, node_config={}) - - assert device.rgb_color is None - assert device.rgbw_color is None - - -def test_rgb_value_changed(mock_openzwave): - """Test value changed for rgb lights.""" - node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - value = MockValue(data=0, node=node) - color = MockValue(data="#0000000000", node=node) - # Supports RGB only - color_channels = MockValue(data=0x1C, node=node) - values = MockLightValues(primary=value, color=color, color_channels=color_channels) - device = light.get_device(node=node, values=values, node_config={}) - - assert device.rgb_color == (0, 0, 0) - - color.data = "#ffbf800000" - value_changed(color) - - assert device.rgb_color == (0xFF, 0xBF, 0x80) - - -def test_rgbww_value_changed(mock_openzwave): - """Test value changed for rgb lights.""" - node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - value = MockValue(data=0, node=node) - color = MockValue(data="#0000000000", node=node) - # Supports RGB, Warm White - color_channels = MockValue(data=0x1D, node=node) - values = MockLightValues(primary=value, color=color, color_channels=color_channels) - device = light.get_device(node=node, values=values, node_config={}) - - assert device.rgbw_color == (0, 0, 0, 0) - - color.data = "#c86400c800" - value_changed(color) - - assert device.rgbw_color == (0xC8, 0x64, 0x00, 0xC8) - - -def test_rgbcw_value_changed(mock_openzwave): - """Test value changed for rgb lights.""" - node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) - value = MockValue(data=0, node=node) - color = MockValue(data="#0000000000", node=node) - # Supports RGB, Cold White - color_channels = MockValue(data=0x1E, node=node) - values = MockLightValues(primary=value, color=color, color_channels=color_channels) - device = light.get_device(node=node, values=values, node_config={}) - - assert device.rgbw_color == (0, 0, 0, 0) - - color.data = "#c86400c800" - value_changed(color) - - assert device.rgbw_color == (0xC8, 0x64, 0x00, 0xC8) - - -def test_ct_value_changed(mock_openzwave): - """Test value changed for zw098 lights.""" - node = MockNode( - manufacturer_id="0086", - product_id="0062", - command_classes=[const.COMMAND_CLASS_SWITCH_COLOR], - ) - value = MockValue(data=0, node=node) - color = MockValue(data="#0000000000", node=node) - # Supports RGB, Cold White - color_channels = MockValue(data=0x1F, node=node) - values = MockLightValues(primary=value, color=color, color_channels=color_channels) - device = light.get_device(node=node, values=values, node_config={}) - - assert device.color_mode == COLOR_MODE_RGB - assert device.color_temp is None - - color.data = "#000000ff00" - value_changed(color) - - assert device.color_mode == COLOR_MODE_COLOR_TEMP - assert device.color_temp == light.TEMP_WARM_HASS - - color.data = "#00000000ff" - value_changed(color) - - assert device.color_mode == COLOR_MODE_COLOR_TEMP - assert device.color_temp == light.TEMP_COLD_HASS - - color.data = "#ff00000000" - value_changed(color) - assert device.color_mode == COLOR_MODE_RGB diff --git a/tests/components/zwave/test_lock.py b/tests/components/zwave/test_lock.py deleted file mode 100644 index 575df9491ad..00000000000 --- a/tests/components/zwave/test_lock.py +++ /dev/null @@ -1,389 +0,0 @@ -"""Test Z-Wave locks.""" -from unittest.mock import MagicMock, patch - -import pytest - -from homeassistant import config_entries -from homeassistant.components.zwave import const, lock - -from tests.mock.zwave import MockEntityValues, MockNode, MockValue, value_changed - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -def test_get_device_detects_lock(mock_openzwave): - """Test get_device returns a Z-Wave lock.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue(data=None, node=node), - access_control=None, - alarm_type=None, - alarm_level=None, - ) - - device = lock.get_device(node=node, values=values, node_config={}) - assert isinstance(device, lock.ZwaveLock) - - -def test_lock_turn_on_and_off(mock_openzwave): - """Test turning on a Z-Wave lock.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue(data=None, node=node), - access_control=None, - alarm_type=None, - alarm_level=None, - ) - device = lock.get_device(node=node, values=values, node_config={}) - - assert not values.primary.data - - device.lock() - assert values.primary.data - - device.unlock() - assert not values.primary.data - - -def test_lock_value_changed(mock_openzwave): - """Test value changed for Z-Wave lock.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue(data=None, node=node), - access_control=None, - alarm_type=None, - alarm_level=None, - ) - device = lock.get_device(node=node, values=values, node_config={}) - - assert not device.is_locked - - values.primary.data = True - value_changed(values.primary) - - assert device.is_locked - - -def test_lock_state_workaround(mock_openzwave): - """Test value changed for Z-Wave lock using notification state.""" - node = MockNode(manufacturer_id="0090", product_id="0440") - values = MockEntityValues( - primary=MockValue(data=True, node=node), - access_control=MockValue(data=1, node=node), - alarm_type=None, - alarm_level=None, - ) - device = lock.get_device(node=node, values=values) - assert device.is_locked - values.access_control.data = 2 - value_changed(values.access_control) - assert not device.is_locked - - -def test_track_message_workaround(mock_openzwave): - """Test value changed for Z-Wave lock by alarm-clearing workaround.""" - node = MockNode( - manufacturer_id="003B", - product_id="5044", - stats={"lastReceivedMessage": [0] * 6}, - ) - values = MockEntityValues( - primary=MockValue(data=True, node=node), - access_control=None, - alarm_type=None, - alarm_level=None, - ) - - # Here we simulate an RF lock. The first lock.get_device will call - # update properties, simulating the first DoorLock report. We then trigger - # a change, simulating the openzwave automatic refreshing behavior (which - # is enabled for at least the lock that needs this workaround) - node.stats["lastReceivedMessage"][5] = const.COMMAND_CLASS_DOOR_LOCK - device = lock.get_device(node=node, values=values) - value_changed(values.primary) - assert device.is_locked - assert device.extra_state_attributes[lock.ATTR_NOTIFICATION] == "RF Lock" - - # Simulate a keypad unlock. We trigger a value_changed() which simulates - # the Alarm notification received from the lock. Then, we trigger - # value_changed() to simulate the automatic refreshing behavior. - values.access_control = MockValue(data=6, node=node) - values.alarm_type = MockValue(data=19, node=node) - values.alarm_level = MockValue(data=3, node=node) - node.stats["lastReceivedMessage"][5] = const.COMMAND_CLASS_ALARM - value_changed(values.access_control) - node.stats["lastReceivedMessage"][5] = const.COMMAND_CLASS_DOOR_LOCK - values.primary.data = False - value_changed(values.primary) - assert not device.is_locked - assert ( - device.extra_state_attributes[lock.ATTR_LOCK_STATUS] - == "Unlocked with Keypad by user 3" - ) - - # Again, simulate an RF lock. - device.lock() - node.stats["lastReceivedMessage"][5] = const.COMMAND_CLASS_DOOR_LOCK - value_changed(values.primary) - assert device.is_locked - assert device.extra_state_attributes[lock.ATTR_NOTIFICATION] == "RF Lock" - - -def test_v2btze_value_changed(mock_openzwave): - """Test value changed for v2btze Z-Wave lock.""" - node = MockNode(manufacturer_id="010e", product_id="0002") - values = MockEntityValues( - primary=MockValue(data=None, node=node), - v2btze_advanced=MockValue(data="Advanced", node=node), - access_control=MockValue(data=19, node=node), - alarm_type=None, - alarm_level=None, - ) - device = lock.get_device(node=node, values=values, node_config={}) - assert device._v2btze - - assert not device.is_locked - - values.access_control.data = 24 - value_changed(values.primary) - - assert device.is_locked - - -def test_alarm_type_workaround(mock_openzwave): - """Test value changed for Z-Wave lock using alarm type.""" - node = MockNode(manufacturer_id="0109", product_id="0000") - values = MockEntityValues( - primary=MockValue(data=True, node=node), - access_control=None, - alarm_type=MockValue(data=16, node=node), - alarm_level=None, - ) - device = lock.get_device(node=node, values=values) - assert not device.is_locked - - values.alarm_type.data = 18 - value_changed(values.alarm_type) - assert device.is_locked - - values.alarm_type.data = 19 - value_changed(values.alarm_type) - assert not device.is_locked - - values.alarm_type.data = 21 - value_changed(values.alarm_type) - assert device.is_locked - - values.alarm_type.data = 22 - value_changed(values.alarm_type) - assert not device.is_locked - - values.alarm_type.data = 24 - value_changed(values.alarm_type) - assert device.is_locked - - values.alarm_type.data = 25 - value_changed(values.alarm_type) - assert not device.is_locked - - values.alarm_type.data = 27 - value_changed(values.alarm_type) - assert device.is_locked - - -def test_lock_access_control(mock_openzwave): - """Test access control for Z-Wave lock.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue(data=None, node=node), - access_control=MockValue(data=11, node=node), - alarm_type=None, - alarm_level=None, - ) - device = lock.get_device(node=node, values=values, node_config={}) - - assert device.extra_state_attributes[lock.ATTR_NOTIFICATION] == "Lock Jammed" - - -def test_lock_alarm_type(mock_openzwave): - """Test alarm type for Z-Wave lock.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue(data=None, node=node), - access_control=None, - alarm_type=MockValue(data=None, node=node), - alarm_level=None, - ) - device = lock.get_device(node=node, values=values, node_config={}) - - assert lock.ATTR_LOCK_STATUS not in device.extra_state_attributes - - values.alarm_type.data = 21 - value_changed(values.alarm_type) - assert ( - device.extra_state_attributes[lock.ATTR_LOCK_STATUS] == "Manually Locked None" - ) - - values.alarm_type.data = 18 - value_changed(values.alarm_type) - assert ( - device.extra_state_attributes[lock.ATTR_LOCK_STATUS] - == "Locked with Keypad by user None" - ) - - values.alarm_type.data = 161 - value_changed(values.alarm_type) - assert device.extra_state_attributes[lock.ATTR_LOCK_STATUS] == "Tamper Alarm: None" - - values.alarm_type.data = 9 - value_changed(values.alarm_type) - assert device.extra_state_attributes[lock.ATTR_LOCK_STATUS] == "Deadbolt Jammed" - - -def test_lock_alarm_level(mock_openzwave): - """Test alarm level for Z-Wave lock.""" - node = MockNode() - values = MockEntityValues( - primary=MockValue(data=None, node=node), - access_control=None, - alarm_type=MockValue(data=None, node=node), - alarm_level=MockValue(data=None, node=node), - ) - device = lock.get_device(node=node, values=values, node_config={}) - - assert lock.ATTR_LOCK_STATUS not in device.extra_state_attributes - - values.alarm_type.data = 21 - values.alarm_level.data = 1 - value_changed(values.alarm_type) - value_changed(values.alarm_level) - assert ( - device.extra_state_attributes[lock.ATTR_LOCK_STATUS] - == "Manually Locked by Key Cylinder or Inside thumb turn" - ) - - values.alarm_type.data = 18 - values.alarm_level.data = "alice" - value_changed(values.alarm_type) - value_changed(values.alarm_level) - assert ( - device.extra_state_attributes[lock.ATTR_LOCK_STATUS] - == "Locked with Keypad by user alice" - ) - - values.alarm_type.data = 161 - values.alarm_level.data = 1 - value_changed(values.alarm_type) - value_changed(values.alarm_level) - assert ( - device.extra_state_attributes[lock.ATTR_LOCK_STATUS] - == "Tamper Alarm: Too many keypresses" - ) - - -async def setup_ozw(hass, mock_openzwave): - """Set up the mock ZWave config entry.""" - hass.config.components.add("zwave") - config_entry = config_entries.ConfigEntry( - 1, - "zwave", - "Mock Title", - {"usb_path": "mock-path", "network_key": "mock-key"}, - "test", - ) - await hass.config_entries.async_forward_entry_setup(config_entry, "lock") - await hass.async_block_till_done() - - -async def test_lock_set_usercode_service(hass, mock_openzwave): - """Test the zwave lock set_usercode service.""" - mock_network = hass.data[const.DATA_NETWORK] = MagicMock() - - node = MockNode(node_id=12) - value0 = MockValue(data=" ", node=node, index=0) - value1 = MockValue(data=" ", node=node, index=1) - - node.get_values.return_value = {value0.value_id: value0, value1.value_id: value1} - - mock_network.nodes = {node.node_id: node} - - await setup_ozw(hass, mock_openzwave) - await hass.async_block_till_done() - - await hass.services.async_call( - lock.DOMAIN, - lock.SERVICE_SET_USERCODE, - { - const.ATTR_NODE_ID: node.node_id, - lock.ATTR_USERCODE: "1234", - lock.ATTR_CODE_SLOT: 1, - }, - ) - await hass.async_block_till_done() - - assert value1.data == "1234" - - mock_network.nodes = {node.node_id: node} - await hass.services.async_call( - lock.DOMAIN, - lock.SERVICE_SET_USERCODE, - { - const.ATTR_NODE_ID: node.node_id, - lock.ATTR_USERCODE: "123", - lock.ATTR_CODE_SLOT: 1, - }, - ) - await hass.async_block_till_done() - - assert value1.data == "1234" - - -async def test_lock_get_usercode_service(hass, mock_openzwave): - """Test the zwave lock get_usercode service.""" - mock_network = hass.data[const.DATA_NETWORK] = MagicMock() - node = MockNode(node_id=12) - value0 = MockValue(data=None, node=node, index=0) - value1 = MockValue(data="1234", node=node, index=1) - - node.get_values.return_value = {value0.value_id: value0, value1.value_id: value1} - - await setup_ozw(hass, mock_openzwave) - await hass.async_block_till_done() - - with patch.object(lock, "_LOGGER") as mock_logger: - mock_network.nodes = {node.node_id: node} - await hass.services.async_call( - lock.DOMAIN, - lock.SERVICE_GET_USERCODE, - {const.ATTR_NODE_ID: node.node_id, lock.ATTR_CODE_SLOT: 1}, - ) - await hass.async_block_till_done() - # This service only seems to write to the log - assert mock_logger.info.called - assert len(mock_logger.info.mock_calls) == 1 - assert mock_logger.info.mock_calls[0][1][2] == "1234" - - -async def test_lock_clear_usercode_service(hass, mock_openzwave): - """Test the zwave lock clear_usercode service.""" - mock_network = hass.data[const.DATA_NETWORK] = MagicMock() - node = MockNode(node_id=12) - value0 = MockValue(data=None, node=node, index=0) - value1 = MockValue(data="123", node=node, index=1) - - node.get_values.return_value = {value0.value_id: value0, value1.value_id: value1} - - mock_network.nodes = {node.node_id: node} - - await setup_ozw(hass, mock_openzwave) - await hass.async_block_till_done() - - await hass.services.async_call( - lock.DOMAIN, - lock.SERVICE_CLEAR_USERCODE, - {const.ATTR_NODE_ID: node.node_id, lock.ATTR_CODE_SLOT: 1}, - ) - await hass.async_block_till_done() - - assert value1.data == "\0\0\0" diff --git a/tests/components/zwave/test_node_entity.py b/tests/components/zwave/test_node_entity.py deleted file mode 100644 index 56ae0d61d41..00000000000 --- a/tests/components/zwave/test_node_entity.py +++ /dev/null @@ -1,723 +0,0 @@ -"""Test Z-Wave node entity.""" -from unittest.mock import MagicMock, patch - -import pytest - -from homeassistant.components.zwave import const, node_entity -from homeassistant.const import ATTR_ENTITY_ID - -import tests.mock.zwave as mock_zwave - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -async def test_maybe_schedule_update(hass, mock_openzwave): - """Test maybe schedule update.""" - base_entity = node_entity.ZWaveBaseEntity() - base_entity.entity_id = "zwave.bla" - base_entity.hass = hass - - with patch.object(hass.loop, "call_later") as mock_call_later: - base_entity._schedule_update() - assert mock_call_later.called - - base_entity._schedule_update() - assert len(mock_call_later.mock_calls) == 1 - assert base_entity._update_scheduled is True - - do_update = mock_call_later.mock_calls[0][1][1] - - do_update() - assert base_entity._update_scheduled is False - - base_entity._schedule_update() - assert len(mock_call_later.mock_calls) == 2 - - -async def test_node_event_activated(hass, mock_openzwave): - """Test Node event activated event.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == mock_zwave.MockNetwork.SIGNAL_NODE_EVENT: - mock_receivers.append(receiver) - - node = mock_zwave.MockNode(node_id=11) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - entity = node_entity.ZWaveNodeEntity(node, mock_openzwave) - - assert len(mock_receivers) == 1 - - events = [] - - def listener(event): - events.append(event) - - hass.bus.async_listen(const.EVENT_NODE_EVENT, listener) - - # Test event before entity added to hass - value = 234 - hass.async_add_job(mock_receivers[0], node, value) - await hass.async_block_till_done() - assert len(events) == 0 - - # Add entity to hass - entity.hass = hass - entity.entity_id = "zwave.mock_node" - - value = 234 - hass.async_add_job(mock_receivers[0], node, value) - await hass.async_block_till_done() - - assert len(events) == 1 - assert events[0].data[ATTR_ENTITY_ID] == "zwave.mock_node" - assert events[0].data[const.ATTR_NODE_ID] == 11 - assert events[0].data[const.ATTR_BASIC_LEVEL] == value - - -async def test_scene_activated(hass, mock_openzwave): - """Test scene activated event.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == mock_zwave.MockNetwork.SIGNAL_SCENE_EVENT: - mock_receivers.append(receiver) - - node = mock_zwave.MockNode(node_id=11) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - entity = node_entity.ZWaveNodeEntity(node, mock_openzwave) - - assert len(mock_receivers) == 1 - - events = [] - - def listener(event): - events.append(event) - - hass.bus.async_listen(const.EVENT_SCENE_ACTIVATED, listener) - - # Test event before entity added to hass - scene_id = 123 - hass.async_add_job(mock_receivers[0], node, scene_id) - await hass.async_block_till_done() - assert len(events) == 0 - - # Add entity to hass - entity.hass = hass - entity.entity_id = "zwave.mock_node" - - scene_id = 123 - hass.async_add_job(mock_receivers[0], node, scene_id) - await hass.async_block_till_done() - - assert len(events) == 1 - assert events[0].data[ATTR_ENTITY_ID] == "zwave.mock_node" - assert events[0].data[const.ATTR_NODE_ID] == 11 - assert events[0].data[const.ATTR_SCENE_ID] == scene_id - - -async def test_central_scene_activated(hass, mock_openzwave): - """Test central scene activated event.""" - mock_receivers = [] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal == mock_zwave.MockNetwork.SIGNAL_VALUE_CHANGED: - mock_receivers.append(receiver) - - node = mock_zwave.MockNode(node_id=11) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - entity = node_entity.ZWaveNodeEntity(node, mock_openzwave) - - assert len(mock_receivers) == 1 - - events = [] - - def listener(event): - events.append(event) - - hass.bus.async_listen(const.EVENT_SCENE_ACTIVATED, listener) - - # Test event before entity added to hass - scene_id = 1 - scene_data = 3 - value = mock_zwave.MockValue( - command_class=const.COMMAND_CLASS_CENTRAL_SCENE, index=scene_id, data=scene_data - ) - hass.async_add_job(mock_receivers[0], node, value) - await hass.async_block_till_done() - assert len(events) == 0 - - # Add entity to hass - entity.hass = hass - entity.entity_id = "zwave.mock_node" - - scene_id = 1 - scene_data = 3 - value = mock_zwave.MockValue( - command_class=const.COMMAND_CLASS_CENTRAL_SCENE, index=scene_id, data=scene_data - ) - hass.async_add_job(mock_receivers[0], node, value) - await hass.async_block_till_done() - - assert len(events) == 1 - assert events[0].data[ATTR_ENTITY_ID] == "zwave.mock_node" - assert events[0].data[const.ATTR_NODE_ID] == 11 - assert events[0].data[const.ATTR_SCENE_ID] == scene_id - assert events[0].data[const.ATTR_SCENE_DATA] == scene_data - - -async def test_application_version(hass, mock_openzwave): - """Test application version.""" - mock_receivers = {} - - signal_mocks = [ - mock_zwave.MockNetwork.SIGNAL_VALUE_CHANGED, - mock_zwave.MockNetwork.SIGNAL_VALUE_ADDED, - ] - - def mock_connect(receiver, signal, *args, **kwargs): - if signal in signal_mocks: - mock_receivers[signal] = receiver - - node = mock_zwave.MockNode(node_id=11) - - with patch("pydispatch.dispatcher.connect", new=mock_connect): - entity = node_entity.ZWaveNodeEntity(node, mock_openzwave) - - for signal_mock in signal_mocks: - assert signal_mock in mock_receivers.keys() - - events = [] - - def listener(event): - events.append(event) - - # Make sure application version isn't set before - assert ( - node_entity.ATTR_APPLICATION_VERSION not in entity.extra_state_attributes.keys() - ) - - # Add entity to hass - entity.hass = hass - entity.entity_id = "zwave.mock_node" - - # Fire off an added value - value = mock_zwave.MockValue( - command_class=const.COMMAND_CLASS_VERSION, - label="Application Version", - data="5.10", - ) - hass.async_add_job( - mock_receivers[mock_zwave.MockNetwork.SIGNAL_VALUE_ADDED], node, value - ) - await hass.async_block_till_done() - - assert entity.extra_state_attributes[node_entity.ATTR_APPLICATION_VERSION] == "5.10" - - # Fire off a changed - value = mock_zwave.MockValue( - command_class=const.COMMAND_CLASS_VERSION, - label="Application Version", - data="4.14", - ) - hass.async_add_job( - mock_receivers[mock_zwave.MockNetwork.SIGNAL_VALUE_CHANGED], node, value - ) - await hass.async_block_till_done() - - assert entity.extra_state_attributes[node_entity.ATTR_APPLICATION_VERSION] == "4.14" - - -async def test_network_node_changed_from_value(hass, mock_openzwave): - """Test for network_node_changed.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode() - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - value = mock_zwave.MockValue(node=node) - with patch.object(entity, "maybe_schedule_update") as mock: - mock_zwave.value_changed(value) - mock.assert_called_once_with() - - -async def test_network_node_changed_from_node(hass, mock_openzwave): - """Test for network_node_changed.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode() - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - with patch.object(entity, "maybe_schedule_update") as mock: - mock_zwave.node_changed(node) - mock.assert_called_once_with() - - -async def test_network_node_changed_from_another_node(hass, mock_openzwave): - """Test for network_node_changed.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode() - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - with patch.object(entity, "maybe_schedule_update") as mock: - another_node = mock_zwave.MockNode(node_id=1024) - mock_zwave.node_changed(another_node) - assert not mock.called - - -async def test_network_node_changed_from_notification(hass, mock_openzwave): - """Test for network_node_changed.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode() - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - with patch.object(entity, "maybe_schedule_update") as mock: - mock_zwave.notification(node_id=node.node_id) - mock.assert_called_once_with() - - -async def test_network_node_changed_from_another_notification(hass, mock_openzwave): - """Test for network_node_changed.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode() - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - with patch.object(entity, "maybe_schedule_update") as mock: - mock_zwave.notification(node_id=1024) - assert not mock.called - - -async def test_node_changed(hass, mock_openzwave): - """Test node_changed function.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode( - query_stage="Dynamic", - is_awake=True, - is_ready=False, - is_failed=False, - is_info_received=True, - max_baud_rate=40000, - is_zwave_plus=False, - capabilities=[], - neighbors=[], - location=None, - ) - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - - assert { - "node_id": node.node_id, - "node_name": "Mock Node", - "manufacturer_name": "Test Manufacturer", - "product_name": "Test Product", - } == entity.extra_state_attributes - - node.get_values.return_value = {1: mock_zwave.MockValue(data=1800)} - zwave_network.manager.getNodeStatistics.return_value = { - "receivedCnt": 4, - "ccData": [ - {"receivedCnt": 0, "commandClassId": 134, "sentCnt": 0}, - {"receivedCnt": 1, "commandClassId": 133, "sentCnt": 1}, - {"receivedCnt": 1, "commandClassId": 115, "sentCnt": 1}, - {"receivedCnt": 0, "commandClassId": 114, "sentCnt": 0}, - {"receivedCnt": 0, "commandClassId": 112, "sentCnt": 0}, - {"receivedCnt": 1, "commandClassId": 32, "sentCnt": 1}, - {"receivedCnt": 0, "commandClassId": 0, "sentCnt": 0}, - ], - "receivedUnsolicited": 0, - "sentTS": "2017-03-27 15:38:15:620 ", - "averageRequestRTT": 2462, - "lastResponseRTT": 3679, - "retries": 0, - "sentFailed": 1, - "sentCnt": 7, - "quality": 0, - "lastRequestRTT": 1591, - "lastReceivedMessage": [ - 0, - 4, - 0, - 15, - 3, - 32, - 3, - 0, - 221, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ], - "receivedDups": 1, - "averageResponseRTT": 2443, - "receivedTS": "2017-03-27 15:38:19:298 ", - } - entity.node_changed() - assert { - "node_id": node.node_id, - "node_name": "Mock Node", - "manufacturer_name": "Test Manufacturer", - "product_name": "Test Product", - "query_stage": "Dynamic", - "is_awake": True, - "is_ready": False, - "is_failed": False, - "is_info_received": True, - "max_baud_rate": 40000, - "is_zwave_plus": False, - "battery_level": 42, - "wake_up_interval": 1800, - "averageRequestRTT": 2462, - "averageResponseRTT": 2443, - "lastRequestRTT": 1591, - "lastResponseRTT": 3679, - "receivedCnt": 4, - "receivedDups": 1, - "receivedTS": "2017-03-27 15:38:19:298 ", - "receivedUnsolicited": 0, - "retries": 0, - "sentCnt": 7, - "sentFailed": 1, - "sentTS": "2017-03-27 15:38:15:620 ", - } == entity.extra_state_attributes - - node.can_wake_up_value = False - entity.node_changed() - - assert "wake_up_interval" not in entity.extra_state_attributes - - -async def test_name(hass, mock_openzwave): - """Test name property.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode() - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - assert entity.name == "Mock Node" - - -async def test_state_before_update(hass, mock_openzwave): - """Test state before update was called.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode() - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - assert entity.state is None - - -async def test_state_not_ready(hass, mock_openzwave): - """Test state property.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode( - query_stage="Dynamic", - is_awake=True, - is_ready=False, - is_failed=False, - is_info_received=True, - ) - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - - node.is_ready = False - entity.node_changed() - assert entity.state == "initializing" - - node.is_failed = True - node.query_stage = "Complete" - entity.node_changed() - assert entity.state == "dead" - - node.is_failed = False - node.is_awake = False - entity.node_changed() - assert entity.state == "sleeping" - - -async def test_state_ready(hass, mock_openzwave): - """Test state property.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode( - query_stage="Dynamic", - is_awake=True, - is_ready=False, - is_failed=False, - is_info_received=True, - ) - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - - node.query_stage = "Complete" - node.is_ready = True - entity.node_changed() - await hass.async_block_till_done() - assert entity.state == "ready" - - node.is_failed = True - entity.node_changed() - assert entity.state == "dead" - - node.is_failed = False - node.is_awake = False - entity.node_changed() - assert entity.state == "sleeping" - - -async def test_not_polled(hass, mock_openzwave): - """Test should_poll property.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode() - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - assert not entity.should_poll - - -async def test_unique_id(hass, mock_openzwave): - """Test unique_id.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode() - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - assert entity.unique_id == "node-567" - - -async def test_unique_id_missing_data(hass, mock_openzwave): - """Test unique_id.""" - zwave_network = MagicMock() - node = mock_zwave.MockNode() - node.manufacturer_name = None - node.name = None - node.is_ready = False - entity = node_entity.ZWaveNodeEntity(node, zwave_network) - - assert entity.unique_id is None diff --git a/tests/components/zwave/test_sensor.py b/tests/components/zwave/test_sensor.py deleted file mode 100644 index 21944fe8f7e..00000000000 --- a/tests/components/zwave/test_sensor.py +++ /dev/null @@ -1,183 +0,0 @@ -"""Test Z-Wave sensor.""" -import pytest - -from homeassistant.components.sensor import SensorDeviceClass -from homeassistant.components.zwave import const, sensor -import homeassistant.const - -from tests.mock.zwave import MockEntityValues, MockNode, MockValue, value_changed - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -def test_get_device_detects_none(mock_openzwave): - """Test get_device returns None.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockEntityValues(primary=value) - - device = sensor.get_device(node=node, values=values, node_config={}) - assert device is None - - -def test_get_device_detects_alarmsensor(mock_openzwave): - """Test get_device returns a Z-Wave alarmsensor.""" - node = MockNode( - command_classes=[const.COMMAND_CLASS_ALARM, const.COMMAND_CLASS_SENSOR_ALARM] - ) - value = MockValue(data=0, node=node) - values = MockEntityValues(primary=value) - - device = sensor.get_device(node=node, values=values, node_config={}) - assert isinstance(device, sensor.ZWaveAlarmSensor) - - -def test_get_device_detects_multilevelsensor(mock_openzwave): - """Test get_device returns a Z-Wave multilevel sensor.""" - node = MockNode( - command_classes=[ - const.COMMAND_CLASS_SENSOR_MULTILEVEL, - const.COMMAND_CLASS_METER, - ] - ) - value = MockValue(data=0, node=node) - values = MockEntityValues(primary=value) - - device = sensor.get_device(node=node, values=values, node_config={}) - assert isinstance(device, sensor.ZWaveMultilevelSensor) - assert device.force_update - - -def test_get_device_detects_multilevel_meter(mock_openzwave): - """Test get_device returns a Z-Wave multilevel sensor.""" - node = MockNode(command_classes=[const.COMMAND_CLASS_METER]) - value = MockValue(data=0, node=node, type=const.TYPE_DECIMAL) - values = MockEntityValues(primary=value) - - device = sensor.get_device(node=node, values=values, node_config={}) - assert isinstance(device, sensor.ZWaveMultilevelSensor) - - -def test_get_device_detects_battery_sensor(mock_openzwave): - """Test get_device returns a Z-Wave battery sensor.""" - - node = MockNode(command_classes=[const.COMMAND_CLASS_BATTERY]) - value = MockValue( - data=0, - node=node, - type=const.TYPE_DECIMAL, - command_class=const.COMMAND_CLASS_BATTERY, - ) - values = MockEntityValues(primary=value) - - device = sensor.get_device(node=node, values=values, node_config={}) - assert isinstance(device, sensor.ZWaveBatterySensor) - assert device.device_class is SensorDeviceClass.BATTERY - - -def test_multilevelsensor_value_changed_temp_fahrenheit(hass, mock_openzwave): - """Test value changed for Z-Wave multilevel sensor for temperature.""" - hass.config.units.temperature_unit = homeassistant.const.TEMP_FAHRENHEIT - - node = MockNode( - command_classes=[ - const.COMMAND_CLASS_SENSOR_MULTILEVEL, - const.COMMAND_CLASS_METER, - ] - ) - value = MockValue(data=190.95555, units="F", node=node) - values = MockEntityValues(primary=value) - - device = sensor.get_device(node=node, values=values, node_config={}) - device.hass = hass - assert device.state == 191.0 - assert device.unit_of_measurement == homeassistant.const.TEMP_FAHRENHEIT - assert device.device_class is SensorDeviceClass.TEMPERATURE - value.data = 197.95555 - value_changed(value) - assert device.state == 198.0 - - -def test_multilevelsensor_value_changed_temp_celsius(hass, mock_openzwave): - """Test value changed for Z-Wave multilevel sensor for temperature.""" - hass.config.units.temperature_unit = homeassistant.const.TEMP_CELSIUS - node = MockNode( - command_classes=[ - const.COMMAND_CLASS_SENSOR_MULTILEVEL, - const.COMMAND_CLASS_METER, - ] - ) - value = MockValue(data=38.85555, units="C", node=node) - values = MockEntityValues(primary=value) - - device = sensor.get_device(node=node, values=values, node_config={}) - device.hass = hass - assert device.state == 38.9 - assert device.unit_of_measurement == homeassistant.const.TEMP_CELSIUS - assert device.device_class is SensorDeviceClass.TEMPERATURE - value.data = 37.95555 - value_changed(value) - assert device.state == 38.0 - - -def test_multilevelsensor_value_changed_other_units(hass, mock_openzwave): - """Test value changed for Z-Wave multilevel sensor for other units.""" - node = MockNode( - command_classes=[ - const.COMMAND_CLASS_SENSOR_MULTILEVEL, - const.COMMAND_CLASS_METER, - ] - ) - value = MockValue( - data=190.95555, units=homeassistant.const.ENERGY_KILO_WATT_HOUR, node=node - ) - values = MockEntityValues(primary=value) - - device = sensor.get_device(node=node, values=values, node_config={}) - device.hass = hass - assert device.state == 190.96 - assert device.unit_of_measurement == homeassistant.const.ENERGY_KILO_WATT_HOUR - assert device.device_class is None - value.data = 197.95555 - value_changed(value) - assert device.state == 197.96 - - -def test_multilevelsensor_value_changed_integer(hass, mock_openzwave): - """Test value changed for Z-Wave multilevel sensor for other units.""" - node = MockNode( - command_classes=[ - const.COMMAND_CLASS_SENSOR_MULTILEVEL, - const.COMMAND_CLASS_METER, - ] - ) - value = MockValue(data=5, units="counts", node=node) - values = MockEntityValues(primary=value) - - device = sensor.get_device(node=node, values=values, node_config={}) - device.hass = hass - assert device.state == 5 - assert device.unit_of_measurement == "counts" - assert device.device_class is None - value.data = 6 - value_changed(value) - assert device.state == 6 - - -def test_alarm_sensor_value_changed(hass, mock_openzwave): - """Test value changed for Z-Wave sensor.""" - node = MockNode( - command_classes=[const.COMMAND_CLASS_ALARM, const.COMMAND_CLASS_SENSOR_ALARM] - ) - value = MockValue(data=12.34, node=node, units=homeassistant.const.PERCENTAGE) - values = MockEntityValues(primary=value) - - device = sensor.get_device(node=node, values=values, node_config={}) - device.hass = hass - assert device.state == 12.34 - assert device.unit_of_measurement == homeassistant.const.PERCENTAGE - assert device.device_class is None - value.data = 45.67 - value_changed(value) - assert device.state == 45.67 diff --git a/tests/components/zwave/test_switch.py b/tests/components/zwave/test_switch.py deleted file mode 100644 index 4c3efbe61fd..00000000000 --- a/tests/components/zwave/test_switch.py +++ /dev/null @@ -1,85 +0,0 @@ -"""Test Z-Wave switches.""" -from unittest.mock import patch - -import pytest - -from homeassistant.components.zwave import switch - -from tests.mock.zwave import MockEntityValues, MockNode, MockValue, value_changed - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -def test_get_device_detects_switch(mock_openzwave): - """Test get_device returns a Z-Wave switch.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockEntityValues(primary=value) - - device = switch.get_device(node=node, values=values, node_config={}) - assert isinstance(device, switch.ZwaveSwitch) - - -def test_switch_turn_on_and_off(mock_openzwave): - """Test turning on a Z-Wave switch.""" - node = MockNode() - value = MockValue(data=0, node=node) - values = MockEntityValues(primary=value) - device = switch.get_device(node=node, values=values, node_config={}) - - device.turn_on() - - assert node.set_switch.called - value_id, state = node.set_switch.mock_calls[0][1] - assert value_id == value.value_id - assert state is True - node.reset_mock() - - device.turn_off() - - assert node.set_switch.called - value_id, state = node.set_switch.mock_calls[0][1] - assert value_id == value.value_id - assert state is False - - -def test_switch_value_changed(mock_openzwave): - """Test value changed for Z-Wave switch.""" - node = MockNode() - value = MockValue(data=False, node=node) - values = MockEntityValues(primary=value) - device = switch.get_device(node=node, values=values, node_config={}) - - assert not device.is_on - - value.data = True - value_changed(value) - - assert device.is_on - - -@patch("time.perf_counter") -def test_switch_refresh_on_update(mock_counter, mock_openzwave): - """Test value changed for refresh on update Z-Wave switch.""" - mock_counter.return_value = 10 - node = MockNode(manufacturer_id="013c", product_type="0001", product_id="0005") - value = MockValue(data=False, node=node, instance=1) - values = MockEntityValues(primary=value) - device = switch.get_device(node=node, values=values, node_config={}) - - assert not device.is_on - - mock_counter.return_value = 15 - value.data = True - value_changed(value) - - assert device.is_on - assert not node.request_state.called - - mock_counter.return_value = 45 - value.data = False - value_changed(value) - - assert not device.is_on - assert node.request_state.called diff --git a/tests/components/zwave/test_websocket_api.py b/tests/components/zwave/test_websocket_api.py deleted file mode 100644 index 2ffe5d61715..00000000000 --- a/tests/components/zwave/test_websocket_api.py +++ /dev/null @@ -1,95 +0,0 @@ -"""Test Z-Wave Websocket API.""" -from unittest.mock import call, patch - -import pytest - -from homeassistant import config_entries -from homeassistant.bootstrap import async_setup_component -from homeassistant.components.zwave.const import ( - CONF_AUTOHEAL, - CONF_NETWORK_KEY, - CONF_POLLING_INTERVAL, - CONF_USB_STICK_PATH, -) -from homeassistant.components.zwave.websocket_api import ID, TYPE - -NETWORK_KEY = "0xTE, 0xST, 0xTE, 0xST, 0xTE, 0xST, 0xTE, 0xST, 0xTE, 0xST, 0xTE, 0xST, 0xTE, 0xST, 0xTE, 0xST" - - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -async def test_zwave_ws_api(hass, mock_openzwave, hass_ws_client): - """Test Z-Wave websocket API.""" - - await async_setup_component( - hass, - "zwave", - { - "zwave": { - CONF_AUTOHEAL: False, - CONF_USB_STICK_PATH: "/dev/zwave", - CONF_POLLING_INTERVAL: 6000, - CONF_NETWORK_KEY: NETWORK_KEY, - } - }, - ) - - await hass.async_block_till_done() - - client = await hass_ws_client(hass) - - await client.send_json({ID: 5, TYPE: "zwave/get_config"}) - - msg = await client.receive_json() - result = msg["result"] - - assert result[CONF_USB_STICK_PATH] == "/dev/zwave" - assert not result[CONF_AUTOHEAL] - assert result[CONF_POLLING_INTERVAL] == 6000 - - -async def test_zwave_zwave_js_migration_api(hass, mock_openzwave, hass_ws_client): - """Test Z-Wave to Z-Wave JS websocket migration API.""" - - await async_setup_component( - hass, - "zwave", - { - "zwave": { - CONF_AUTOHEAL: False, - CONF_USB_STICK_PATH: "/dev/zwave", - CONF_POLLING_INTERVAL: 6000, - CONF_NETWORK_KEY: NETWORK_KEY, - } - }, - ) - - await hass.async_block_till_done() - - client = await hass_ws_client(hass) - - await client.send_json({ID: 6, TYPE: "zwave/get_migration_config"}) - msg = await client.receive_json() - result = msg["result"] - - assert result[CONF_USB_STICK_PATH] == "/dev/zwave" - assert result[CONF_NETWORK_KEY] == NETWORK_KEY - - with patch( - "homeassistant.config_entries.ConfigEntriesFlowManager.async_init" - ) as async_init: - - async_init.return_value = {"flow_id": "mock_flow_id"} - await client.send_json({ID: 7, TYPE: "zwave/start_zwave_js_config_flow"}) - msg = await client.receive_json() - - result = msg["result"] - - assert result["flow_id"] == "mock_flow_id" - assert async_init.call_args == call( - "zwave_js", - context={"source": config_entries.SOURCE_IMPORT}, - data={"usb_path": "/dev/zwave", "network_key": NETWORK_KEY}, - ) diff --git a/tests/components/zwave/test_workaround.py b/tests/components/zwave/test_workaround.py deleted file mode 100644 index 8f84fd6b949..00000000000 --- a/tests/components/zwave/test_workaround.py +++ /dev/null @@ -1,71 +0,0 @@ -"""Test Z-Wave workarounds.""" -import pytest - -from homeassistant.components.zwave import const, workaround - -from tests.mock.zwave import MockNode, MockValue - -# Integration is disabled -pytest.skip("Integration has been disabled in the manifest", allow_module_level=True) - - -def test_get_device_no_component_mapping(): - """Test that None is returned.""" - node = MockNode(manufacturer_id=" ") - value = MockValue(data=0, node=node) - assert workaround.get_device_component_mapping(value) is None - - -def test_get_device_component_mapping(): - """Test that component is returned.""" - node = MockNode(manufacturer_id="010f", product_type="0b00") - value = MockValue(data=0, node=node, command_class=const.COMMAND_CLASS_SENSOR_ALARM) - assert workaround.get_device_component_mapping(value) == "binary_sensor" - - -def test_get_device_component_mapping_mti(): - """Test that component is returned.""" - # GE Fan controller - node = MockNode(manufacturer_id="0063", product_type="4944", product_id="3034") - value = MockValue( - data=0, node=node, command_class=const.COMMAND_CLASS_SWITCH_MULTILEVEL - ) - assert workaround.get_device_component_mapping(value) == "fan" - - # GE Dimmer - node = MockNode(manufacturer_id="0063", product_type="4944", product_id="3031") - value = MockValue( - data=0, node=node, command_class=const.COMMAND_CLASS_SWITCH_MULTILEVEL - ) - assert workaround.get_device_component_mapping(value) is None - - -def test_get_device_no_mapping(): - """Test that no device mapping is returned.""" - node = MockNode(manufacturer_id=" ") - value = MockValue(data=0, node=node) - assert workaround.get_device_mapping(value) is None - - -def test_get_device_mapping_mt(): - """Test that device mapping mt is returned.""" - node = MockNode(manufacturer_id="0047", product_type="5a52") - value = MockValue(data=0, node=node) - assert workaround.get_device_mapping(value) == "workaround_no_position" - - -def test_get_device_mapping_mtii(): - """Test that device mapping mtii is returned.""" - node = MockNode(manufacturer_id="013c", product_type="0002", product_id="0002") - value = MockValue(data=0, node=node, index=0) - assert workaround.get_device_mapping(value) == "trigger_no_off_event" - - -def test_get_device_mapping_mti_instance(): - """Test that device mapping mti_instance is returned.""" - node = MockNode(manufacturer_id="013c", product_type="0001", product_id="0005") - value = MockValue(data=0, node=node, instance=1) - assert workaround.get_device_mapping(value) == "refresh_node_on_update" - - value = MockValue(data=0, node=node, instance=2) - assert workaround.get_device_mapping(value) is None diff --git a/tests/components/zwave_js/test_migrate.py b/tests/components/zwave_js/test_migrate.py index 95f969a9586..79201ebbede 100644 --- a/tests/components/zwave_js/test_migrate.py +++ b/tests/components/zwave_js/test_migrate.py @@ -217,6 +217,7 @@ def zwave_integration_fixture(hass, zwave_migration_data): yield zwave_config_entry +@pytest.mark.skip(reason="The old zwave integration has been removed.") async def test_migrate_zwave( hass, zwave_integration, @@ -353,7 +354,7 @@ async def test_migrate_zwave( assert not await hass.config_entries.async_setup(zwave_config_entry.entry_id) -@pytest.mark.skip(reason="The old zwave integration has been disabled.") +@pytest.mark.skip(reason="The old zwave integration has been removed.") async def test_migrate_zwave_dry_run( hass, zwave_integration, diff --git a/tests/mock/__init__.py b/tests/mock/__init__.py deleted file mode 100644 index acf1fe50f54..00000000000 --- a/tests/mock/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Mock helpers.""" diff --git a/tests/mock/zwave.py b/tests/mock/zwave.py deleted file mode 100644 index 89c70eaf83c..00000000000 --- a/tests/mock/zwave.py +++ /dev/null @@ -1,208 +0,0 @@ -"""Mock helpers for Z-Wave component.""" -from unittest.mock import MagicMock - -# Integration & integration tests are disabled -# from pydispatch import dispatcher -dispatcher = MagicMock() - - -def value_changed(value): - """Fire a value changed.""" - dispatcher.send( - MockNetwork.SIGNAL_VALUE_CHANGED, - value=value, - node=value.node, - network=value.node._network, - ) - - -def node_changed(node): - """Fire a node changed.""" - dispatcher.send(MockNetwork.SIGNAL_NODE, node=node, network=node._network) - - -def notification(node_id, network=None): - """Fire a notification.""" - dispatcher.send( - MockNetwork.SIGNAL_NOTIFICATION, args={"nodeId": node_id}, network=network - ) - - -class MockOption(MagicMock): - """Mock Z-Wave options.""" - - def __init__(self, device=None, config_path=None, user_path=None, cmd_line=None): - """Initialize a Z-Wave mock options.""" - super().__init__() - self.device = device - self.config_path = config_path - self.user_path = user_path - self.cmd_line = cmd_line - - def _get_child_mock(self, **kw): - """Create child mocks with right MagicMock class.""" - return MagicMock(**kw) - - -class MockNetwork(MagicMock): - """Mock Z-Wave network.""" - - SIGNAL_NETWORK_FAILED = "mock_NetworkFailed" - SIGNAL_NETWORK_STARTED = "mock_NetworkStarted" - SIGNAL_NETWORK_READY = "mock_NetworkReady" - SIGNAL_NETWORK_STOPPED = "mock_NetworkStopped" - SIGNAL_NETWORK_RESETTED = "mock_DriverResetted" - SIGNAL_NETWORK_AWAKED = "mock_DriverAwaked" - SIGNAL_DRIVER_FAILED = "mock_DriverFailed" - SIGNAL_DRIVER_READY = "mock_DriverReady" - SIGNAL_DRIVER_RESET = "mock_DriverReset" - SIGNAL_DRIVER_REMOVED = "mock_DriverRemoved" - SIGNAL_GROUP = "mock_Group" - SIGNAL_NODE = "mock_Node" - SIGNAL_NODE_ADDED = "mock_NodeAdded" - SIGNAL_NODE_EVENT = "mock_NodeEvent" - SIGNAL_NODE_NAMING = "mock_NodeNaming" - SIGNAL_NODE_NEW = "mock_NodeNew" - SIGNAL_NODE_PROTOCOL_INFO = "mock_NodeProtocolInfo" - SIGNAL_NODE_READY = "mock_NodeReady" - SIGNAL_NODE_REMOVED = "mock_NodeRemoved" - SIGNAL_SCENE_EVENT = "mock_SceneEvent" - SIGNAL_VALUE = "mock_Value" - SIGNAL_VALUE_ADDED = "mock_ValueAdded" - SIGNAL_VALUE_CHANGED = "mock_ValueChanged" - SIGNAL_VALUE_REFRESHED = "mock_ValueRefreshed" - SIGNAL_VALUE_REMOVED = "mock_ValueRemoved" - SIGNAL_POLLING_ENABLED = "mock_PollingEnabled" - SIGNAL_POLLING_DISABLED = "mock_PollingDisabled" - SIGNAL_CREATE_BUTTON = "mock_CreateButton" - SIGNAL_DELETE_BUTTON = "mock_DeleteButton" - SIGNAL_BUTTON_ON = "mock_ButtonOn" - SIGNAL_BUTTON_OFF = "mock_ButtonOff" - SIGNAL_ESSENTIAL_NODE_QUERIES_COMPLETE = "mock_EssentialNodeQueriesComplete" - SIGNAL_NODE_QUERIES_COMPLETE = "mock_NodeQueriesComplete" - SIGNAL_AWAKE_NODES_QUERIED = "mock_AwakeNodesQueried" - SIGNAL_ALL_NODES_QUERIED = "mock_AllNodesQueried" - SIGNAL_ALL_NODES_QUERIED_SOME_DEAD = "mock_AllNodesQueriedSomeDead" - SIGNAL_MSG_COMPLETE = "mock_MsgComplete" - SIGNAL_NOTIFICATION = "mock_Notification" - SIGNAL_CONTROLLER_COMMAND = "mock_ControllerCommand" - SIGNAL_CONTROLLER_WAITING = "mock_ControllerWaiting" - - STATE_STOPPED = 0 - STATE_FAILED = 1 - STATE_RESETTED = 3 - STATE_STARTED = 5 - STATE_AWAKED = 7 - STATE_READY = 10 - - def __init__(self, options=None, *args, **kwargs): - """Initialize a Z-Wave mock network.""" - super().__init__() - self.options = options - self.state = MockNetwork.STATE_STOPPED - - -class MockNode(MagicMock): - """Mock Z-Wave node.""" - - def __init__( - self, - *, - node_id=567, - name="Mock Node", - manufacturer_id="ABCD", - product_id="123", - product_type="678", - command_classes=None, - can_wake_up_value=True, - manufacturer_name="Test Manufacturer", - product_name="Test Product", - network=None, - **kwargs, - ): - """Initialize a Z-Wave mock node.""" - super().__init__() - self.node_id = node_id - self.name = name - self.manufacturer_id = manufacturer_id - self.product_id = product_id - self.product_type = product_type - self.manufacturer_name = manufacturer_name - self.product_name = product_name - self.can_wake_up_value = can_wake_up_value - self._command_classes = command_classes or [] - if network is not None: - self._network = network - for attr_name in kwargs: - setattr(self, attr_name, kwargs[attr_name]) - - def has_command_class(self, command_class): - """Test if mock has a command class.""" - return command_class in self._command_classes - - def get_battery_level(self): - """Return mock battery level.""" - return 42 - - def can_wake_up(self): - """Return whether the node can wake up.""" - return self.can_wake_up_value - - def _get_child_mock(self, **kw): - """Create child mocks with right MagicMock class.""" - return MagicMock(**kw) - - -class MockValue(MagicMock): - """Mock Z-Wave value.""" - - _mock_value_id = 1234 - - def __init__( - self, - *, - label="Mock Value", - node=None, - instance=0, - index=0, - value_id=None, - **kwargs, - ): - """Initialize a Z-Wave mock value.""" - super().__init__() - self.label = label - self.node = node - self.instance = instance - self.index = index - if value_id is None: - MockValue._mock_value_id += 1 - value_id = MockValue._mock_value_id - self.value_id = value_id - self.object_id = value_id - for attr_name in kwargs: - setattr(self, attr_name, kwargs[attr_name]) - - def _get_child_mock(self, **kw): - """Create child mocks with right MagicMock class.""" - return MagicMock(**kw) - - def refresh(self): - """Mock refresh of node value.""" - value_changed(self) - - -class MockEntityValues: - """Mock Z-Wave entity values.""" - - def __init__(self, **kwargs): - """Initialize the mock zwave values.""" - self.primary = None - self.wakeup = None - self.battery = None - self.power = None - for name in kwargs: - setattr(self, name, kwargs[name]) - - def __iter__(self): - """Allow iteration over all values.""" - return iter(self.__dict__.values())