Example #1
0
def websocket_node_status(hass, connection, msg):
    """Get the status for a Z-Wave node."""
    try:
        node = get_node_from_manager(hass.data[DOMAIN][MANAGER],
                                     msg[OZW_INSTANCE], msg[NODE_ID])
    except NotFoundError as err:
        connection.send_error(
            msg[ID],
            websocket_api.const.ERR_NOT_FOUND,
            err.args[0],
        )
        return

    connection.send_result(
        msg[ID],
        {
            ATTR_NODE_QUERY_STAGE: node.node_query_stage,
            NODE_ID: node.node_id,
            ATTR_IS_ZWAVE_PLUS: node.is_zwave_plus,
            ATTR_IS_AWAKE: node.is_awake,
            ATTR_IS_FAILED: node.is_failed,
            ATTR_NODE_BAUD_RATE: node.node_baud_rate,
            ATTR_IS_BEAMING: node.is_beaming,
            ATTR_IS_FLIRS: node.is_flirs,
            ATTR_IS_ROUTING: node.is_routing,
            ATTR_IS_SECURITYV1: node.is_securityv1,
            ATTR_NODE_BASIC_STRING: node.node_basic_string,
            ATTR_NODE_GENERIC_STRING: node.node_generic_string,
            ATTR_NODE_SPECIFIC_STRING: node.node_specific_string,
            ATTR_NODE_MANUFACTURER_NAME: node.node_manufacturer_name,
            ATTR_NODE_PRODUCT_NAME: node.node_product_name,
            ATTR_NEIGHBORS: node.neighbors,
            OZW_INSTANCE: msg[OZW_INSTANCE],
        },
    )
Example #2
0
    def async_set_config_parameter(self, service):
        """Set a config parameter to a node."""
        instance_id = service.data[const.ATTR_INSTANCE_ID]
        node_id = service.data[const.ATTR_NODE_ID]
        param = service.data[const.ATTR_CONFIG_PARAMETER]
        selection = service.data[const.ATTR_CONFIG_VALUE]

        # These function calls may raise an exception but that's ok because
        # the exception will show in the UI to the user
        node = get_node_from_manager(self._manager, instance_id, node_id)
        payload = set_config_parameter(node, param, selection)

        _LOGGER.info(
            "Setting configuration parameter %s on Node %s with value %s",
            param,
            node_id,
            payload,
        )
Example #3
0
def websocket_node_metadata(hass, connection, msg):
    """Get the metadata for a Z-Wave node."""
    try:
        node = get_node_from_manager(hass.data[DOMAIN][MANAGER],
                                     msg[OZW_INSTANCE], msg[NODE_ID])
    except NotFoundError as err:
        connection.send_error(
            msg[ID],
            websocket_api.const.ERR_NOT_FOUND,
            err.args[0],
        )
        return

    connection.send_result(
        msg[ID],
        {
            "metadata": node.meta_data,
            NODE_ID: node.node_id,
            OZW_INSTANCE: msg[OZW_INSTANCE],
        },
    )
Example #4
0
def _call_util_function(hass, connection, msg, send_result, function, *args):
    """Call an openzwavemqtt.util function."""
    try:
        node = get_node_from_manager(
            hass.data[DOMAIN][MANAGER], msg[OZW_INSTANCE], msg[NODE_ID]
        )
    except NotFoundError as err:
        connection.send_error(
            msg[ID],
            websocket_api.const.ERR_NOT_FOUND,
            err.args[0],
        )
        return

    try:
        payload = function(node, *args)
    except NotFoundError as err:
        connection.send_error(
            msg[ID],
            websocket_api.const.ERR_NOT_FOUND,
            err.args[0],
        )
        return
    except NotSupportedError as err:
        connection.send_error(
            msg[ID],
            websocket_api.const.ERR_NOT_SUPPORTED,
            err.args[0],
        )
        return

    if send_result:
        connection.send_result(
            msg[ID],
            payload,
        )
        return

    connection.send_result(msg[ID])
Example #5
0
    async def _async_update(self) -> Dict[Union[str, int], Any]:
        """Update usercodes."""
        # loop to get user code data from entity_id node
        instance_id = 1  # default
        data = {CONF_LOCK_ENTITY_ID: self._primary_lock.lock_entity_id}

        # # make button call
        # servicedata = {"entity_id": self._entity_id}
        # await self.hass.services.async_call(
        #    DOMAIN, SERVICE_REFRESH_CODES, servicedata
        # )

        if async_using_zwave_js(lock=self._primary_lock):
            node: ZwaveJSNode = self._primary_lock.zwave_js_lock_node
            if node is None:
                raise NativeNotFoundError
            code_slot = 1

            for slot in get_usercodes(node):
                code_slot = int(slot[ATTR_CODE_SLOT])
                usercode: Optional[str] = slot[ATTR_USERCODE]
                in_use: Optional[bool] = slot[ATTR_IN_USE]
                # Retrieve code slots that haven't been populated yet
                if in_use is None and code_slot in self.slots:
                    usercode_resp = await get_usercode_from_node(
                        node, code_slot)
                    usercode = slot[ATTR_USERCODE] = usercode_resp[
                        ATTR_USERCODE]
                    in_use = slot[ATTR_IN_USE] = usercode_resp[ATTR_IN_USE]
                if not in_use:
                    _LOGGER.debug("DEBUG: Code slot %s not enabled", code_slot)
                    data[code_slot] = ""
                elif usercode and "*" in str(usercode):
                    _LOGGER.debug(
                        "DEBUG: Ignoring code slot with * in value for code slot %s",
                        code_slot,
                    )
                    data[code_slot] = self._invalid_code(code_slot)
                else:
                    _LOGGER.debug("DEBUG: Code slot %s value: %s", code_slot,
                                  usercode)
                    data[code_slot] = usercode

        # pull the codes for ozw
        elif async_using_ozw(lock=self._primary_lock):
            node_id = get_node_id(self.hass, self._primary_lock.lock_entity_id)
            if node_id is None:
                return data
            data[ATTR_NODE_ID] = node_id

            if data[ATTR_NODE_ID] is None:
                raise NoNodeSpecifiedError
            # Raises exception when node not found
            try:
                node = get_node_from_manager(
                    self.hass.data[OZW_DOMAIN][MANAGER],
                    instance_id,
                    data[ATTR_NODE_ID],
                )
            except NotFoundError:
                raise NativeNotFoundError from None

            command_class = node.get_command_class(CommandClass.USER_CODE)

            if not command_class:
                raise NativeNotSupportedError("Node doesn't have code slots")

            for value in command_class.values():  # type: ignore
                code_slot = int(value.index)
                _LOGGER.debug("DEBUG: Code slot %s value: %s", code_slot,
                              str(value.value))
                if value.value and "*" in str(value.value):
                    _LOGGER.debug("DEBUG: Ignoring code slot with * in value.")
                    data[code_slot] = self._invalid_code(code_slot)
                else:
                    data[code_slot] = value.value

        # pull codes for zwave
        elif async_using_zwave(lock=self._primary_lock):
            node_id = get_node_id(self.hass, self._primary_lock.lock_entity_id)
            if node_id is None:
                return data
            data[ATTR_NODE_ID] = node_id

            if data[ATTR_NODE_ID] is None:
                raise NoNodeSpecifiedError

            network = self.hass.data[ZWAVE_NETWORK]
            node = network.nodes.get(data[ATTR_NODE_ID])
            if not node:
                raise NativeNotFoundError

            lock_values = node.get_values(
                class_id=CommandClass.USER_CODE).values()
            for value in lock_values:
                _LOGGER.debug(
                    "DEBUG: Code slot %s value: %s",
                    str(value.index),
                    str(value.data),
                )
                # do not update if the code contains *s
                code = str(value.data)

                # Remove \x00 if found
                code = code.replace("\x00", "")

                # Check for * in lock data and use workaround code if exist
                if "*" in code:
                    _LOGGER.debug("DEBUG: Ignoring code slot with * in value.")
                    code = self._invalid_code(value.index)

                # Build data from entities
                active_binary_sensor = (
                    f"binary_sensor.active_{self._primary_lock.lock_name}_{value.index}"
                )
                active = self.hass.states.get(active_binary_sensor)

                # Report blank slot if occupied by random code
                if active is not None:
                    if active.state == "off":
                        _LOGGER.debug(
                            "DEBUG: Utilizing Zwave clear_usercode work around code"
                        )
                        code = ""

                data[int(value.index)] = code

        else:
            raise ZWaveIntegrationNotConfiguredError

        return data
Example #6
0
    def update_usercodes(self) -> Dict[str, Any]:
        """Update usercodes."""
        # loop to get user code data from entity_id node
        instance_id = 1  # default
        data = {}
        data[CONF_LOCK_ENTITY_ID] = self._lock.lock_entity_id
        node_id = get_node_id(self.hass, self._lock.lock_entity_id)
        if node_id is None:
            return data
        data[ATTR_NODE_ID] = node_id

        if data[ATTR_NODE_ID] is None:
            raise NoNodeSpecifiedError

        # # make button call
        # servicedata = {"entity_id": self._entity_id}
        # await self.hass.services.async_call(DOMAIN, SERVICE_REFRESH_CODES, servicedata)

        # pull the codes for ozw
        if using_ozw(self.hass):
            # Raises exception when node not found
            try:
                node = get_node_from_manager(
                    self.hass.data[OZW_DOMAIN][MANAGER],
                    instance_id,
                    data[ATTR_NODE_ID],
                )
            except NotFoundError:
                return data

            command_class = node.get_command_class(CommandClass.USER_CODE)

            if not command_class:
                raise NotSupportedError("Node doesn't have code slots")

            for value in command_class.values():  # type: ignore
                code_slot = int(value.index)
                _LOGGER.debug("DEBUG: Code slot %s value: %s", code_slot,
                              str(value.value))
                if value.value and "*" in str(value.value):
                    _LOGGER.debug("DEBUG: Ignoring code slot with * in value.")
                    data[code_slot] = self._invalid_code(code_slot)
                else:
                    data[code_slot] = value.value

            return data

        # pull codes for zwave
        elif using_zwave(self.hass):
            network = self.hass.data[ZWAVE_NETWORK]
            node = network.nodes.get(data[ATTR_NODE_ID])
            if not node:
                raise NotFoundError

            lock_values = node.get_values(
                class_id=CommandClass.USER_CODE).values()
            for value in lock_values:
                _LOGGER.debug(
                    "DEBUG: Code slot %s value: %s",
                    str(value.index),
                    str(value.data),
                )
                # do not update if the code contains *s
                code = str(value.data)

                # Remove \x00 if found
                code = code.replace("\x00", "")

                # Check for * in lock data and use workaround code if exist
                if "*" in code:
                    _LOGGER.debug("DEBUG: Ignoring code slot with * in value.")
                    code = self._invalid_code(value.index)

                # Build data from entities
                enabled_bool = (
                    f"input_boolean.{self._lock.lock_name}_enabled_{value.index}"
                )
                enabled = self.hass.states.get(enabled_bool)

                # Report blank slot if occupied by random code
                if enabled is not None:
                    if enabled.state == "off":
                        _LOGGER.debug(
                            "DEBUG: Utilizing Zwave clear_usercode work around code."
                        )
                        code = ""

                data[int(value.index)] = code

            return data
        else:
            raise ZWaveIntegrationNotConfiguredError
Example #7
0
    async def _async_update(self) -> Dict[str, Any]:
        """Update usercodes."""
        # loop to get user code data from entity_id node
        instance_id = 1  # default
        data = {CONF_LOCK_ENTITY_ID: self._primary_lock.lock_entity_id}

        # # make button call
        # servicedata = {"entity_id": self._entity_id}
        # await self.hass.services.async_call(
        #    DOMAIN, SERVICE_REFRESH_CODES, servicedata
        # )

        if async_using_zwave_js(lock=self._primary_lock):
            node = self._primary_lock.zwave_js_lock_node
            if node is None:
                raise NativeNotFoundError
            code_slot = 1

            for slot in get_usercodes(node):
                code_slot = int(slot[ATTR_CODE_SLOT])
                usercode = slot[ATTR_USERCODE]
                if not slot[ATTR_IN_USE]:
                    _LOGGER.debug("DEBUG: Code slot %s not enabled", code_slot)
                    data[code_slot] = ""
                elif usercode and "*" in str(usercode):
                    _LOGGER.debug(
                        "DEBUG: Ignoring code slot with * in value for code slot %s",
                        code_slot,
                    )
                    data[code_slot] = self._invalid_code(code_slot)
                else:
                    _LOGGER.debug("DEBUG: Code slot %s value: %s", code_slot,
                                  usercode)
                    data[code_slot] = usercode
            return data

        # pull codes for zha
        elif async_using_zha(lock=self._primary_lock):
            _LOGGER.debug('asking for update for zha')
            zha_lock_entity = self._primary_lock.zha_lock_entity
            _LOGGER.debug(self.hass.data[DATA_ZHA])
            _LOGGER.debug(self.hass.data[ZHA_DOMAIN])
            locks = [
                object_type(*instance) for object_type, instance in
                self.hass.data[DATA_ZHA][LOCK_DOMAIN]
            ]
            _LOGGER.debug(locks)
            lock = next(
                (x for x in locks if x.unique_id == zha_lock_entity.unique_id),
                None)
            _LOGGER.debug(lock)
            if lock is None:
                raise NativeNotFoundError

            start_from = self.config_entry.data.get(CONF_START, 1)
            code_slots = self.config_entry.data.get(CONF_SLOTS, 1)

            # return for the number of slots we have configured
            # TODO: figure out how to actually get the max number of slots
            # TODO: figure out how to get codes at a time other than startup
            for code_slot in range(start_from, start_from + code_slots):
                index, userstatus, usertype, usercode = await lock._doorlock_channel.async_get_user_code(
                    code_slot)
                if userstatus != DoorLock.UserStatus.Enabled:
                    _LOGGER.debug("DEBUG: Code slot %s not enabled", code_slot)
                    data[code_slot] = ""
                else:
                    _LOGGER.debug("DEBUG: Code slot %s value: %s", code_slot,
                                  usercode)
                    data[code_slot] = usercode
            return data

        # pull the codes for ozw
        elif async_using_ozw(lock=self._primary_lock):
            node_id = get_node_id(self.hass, self._primary_lock.lock_entity_id)
            if node_id is None:
                return data
            data[ATTR_NODE_ID] = node_id

            if data[ATTR_NODE_ID] is None:
                raise NoNodeSpecifiedError
            # Raises exception when node not found
            try:
                node = get_node_from_manager(
                    self.hass.data[OZW_DOMAIN][MANAGER],
                    instance_id,
                    data[ATTR_NODE_ID],
                )
            except NotFoundError:
                raise NativeNotFoundError from None

            command_class = node.get_command_class(CommandClass.USER_CODE)

            if not command_class:
                raise NativeNotSupportedError("Node doesn't have code slots")

            for value in command_class.values():  # type: ignore
                code_slot = int(value.index)
                _LOGGER.debug("DEBUG: Code slot %s value: %s", code_slot,
                              str(value.value))
                if value.value and "*" in str(value.value):
                    _LOGGER.debug("DEBUG: Ignoring code slot with * in value.")
                    data[code_slot] = self._invalid_code(code_slot)
                else:
                    data[code_slot] = value.value

            return data

        # pull codes for zwave
        elif async_using_zwave(lock=self._primary_lock):
            node_id = get_node_id(self.hass, self._primary_lock.lock_entity_id)
            if node_id is None:
                return data
            data[ATTR_NODE_ID] = node_id

            if data[ATTR_NODE_ID] is None:
                raise NoNodeSpecifiedError

            network = self.hass.data[ZWAVE_NETWORK]
            node = network.nodes.get(data[ATTR_NODE_ID])
            if not node:
                raise NativeNotFoundError

            lock_values = node.get_values(
                class_id=CommandClass.USER_CODE).values()
            for value in lock_values:
                _LOGGER.debug(
                    "DEBUG: Code slot %s value: %s",
                    str(value.index),
                    str(value.data),
                )
                # do not update if the code contains *s
                code = str(value.data)

                # Remove \x00 if found
                code = code.replace("\x00", "")

                # Check for * in lock data and use workaround code if exist
                if "*" in code:
                    _LOGGER.debug("DEBUG: Ignoring code slot with * in value.")
                    code = self._invalid_code(value.index)

                # Build data from entities
                active_binary_sensor = (
                    f"binary_sensor.active_{self._primary_lock.lock_name}_{value.index}"
                )
                active = self.hass.states.get(active_binary_sensor)

                # Report blank slot if occupied by random code
                if active is not None:
                    if active.state == "off":
                        _LOGGER.debug(
                            "DEBUG: Utilizing Zwave clear_usercode work around code"
                        )
                        code = ""

                data[int(value.index)] = code

            return data
        else:
            raise ZWaveIntegrationNotConfiguredError