mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 17:57:55 +00:00
Remove deprecated OpenZWave integration (#68054)
This commit is contained in:
parent
344537d0a8
commit
57c33a5cf0
@ -872,9 +872,6 @@ omit =
|
||||
homeassistant/components/ovo_energy/__init__.py
|
||||
homeassistant/components/ovo_energy/const.py
|
||||
homeassistant/components/ovo_energy/sensor.py
|
||||
homeassistant/components/ozw/__init__.py
|
||||
homeassistant/components/ozw/entity.py
|
||||
homeassistant/components/ozw/services.py
|
||||
homeassistant/components/panasonic_bluray/media_player.py
|
||||
homeassistant/components/panasonic_viera/media_player.py
|
||||
homeassistant/components/pandora/media_player.py
|
||||
|
@ -735,8 +735,6 @@ homeassistant/components/overkiz/* @imicknl @vlebourl @tetienne
|
||||
tests/components/overkiz/* @imicknl @vlebourl @tetienne
|
||||
homeassistant/components/ovo_energy/* @timmo001
|
||||
tests/components/ovo_energy/* @timmo001
|
||||
homeassistant/components/ozw/* @cgarwood @marcelveldt @MartinHjelmare
|
||||
tests/components/ozw/* @cgarwood @marcelveldt @MartinHjelmare
|
||||
homeassistant/components/p1_monitor/* @klaasnicolaas
|
||||
tests/components/p1_monitor/* @klaasnicolaas
|
||||
homeassistant/components/panel_custom/* @home-assistant/frontend
|
||||
|
@ -1,418 +0,0 @@
|
||||
"""The ozw integration."""
|
||||
import asyncio
|
||||
from contextlib import suppress
|
||||
import json
|
||||
import logging
|
||||
|
||||
from openzwavemqtt import OZWManager, OZWOptions
|
||||
from openzwavemqtt.const import (
|
||||
EVENT_INSTANCE_EVENT,
|
||||
EVENT_NODE_ADDED,
|
||||
EVENT_NODE_CHANGED,
|
||||
EVENT_NODE_REMOVED,
|
||||
EVENT_VALUE_ADDED,
|
||||
EVENT_VALUE_CHANGED,
|
||||
EVENT_VALUE_REMOVED,
|
||||
CommandClass,
|
||||
ValueType,
|
||||
)
|
||||
from openzwavemqtt.models.node import OZWNode
|
||||
from openzwavemqtt.models.value import OZWValue
|
||||
from openzwavemqtt.util.mqtt_client import MQTTClient
|
||||
|
||||
from homeassistant.components import hassio, mqtt
|
||||
from homeassistant.components.hassio.handler import HassioAPIError
|
||||
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.device_registry import async_get_registry as get_dev_reg
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
|
||||
from . import const
|
||||
from .const import (
|
||||
CONF_INTEGRATION_CREATED_ADDON,
|
||||
CONF_USE_ADDON,
|
||||
DATA_UNSUBSCRIBE,
|
||||
DOMAIN,
|
||||
MANAGER,
|
||||
NODES_VALUES,
|
||||
PLATFORMS,
|
||||
TOPIC_OPENZWAVE,
|
||||
)
|
||||
from .discovery import DISCOVERY_SCHEMAS, check_node_schema, check_value_schema
|
||||
from .entity import (
|
||||
ZWaveDeviceEntityValues,
|
||||
create_device_id,
|
||||
create_device_name,
|
||||
create_value_id,
|
||||
)
|
||||
from .services import ZWaveServices
|
||||
from .websocket_api import async_register_api
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DATA_DEVICES = "zwave-mqtt-devices"
|
||||
DATA_STOP_MQTT_CLIENT = "ozw_stop_mqtt_client"
|
||||
|
||||
|
||||
async def async_setup_entry( # noqa: C901
|
||||
hass: HomeAssistant, entry: ConfigEntry
|
||||
) -> bool:
|
||||
"""Set up ozw from a config entry."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
ozw_data = hass.data[DOMAIN][entry.entry_id] = {}
|
||||
ozw_data[DATA_UNSUBSCRIBE] = []
|
||||
|
||||
data_nodes = {}
|
||||
hass.data[DOMAIN][NODES_VALUES] = data_values = {}
|
||||
removed_nodes = []
|
||||
manager_options = {"topic_prefix": f"{TOPIC_OPENZWAVE}/"}
|
||||
|
||||
if entry.unique_id is None:
|
||||
hass.config_entries.async_update_entry(entry, unique_id=DOMAIN)
|
||||
|
||||
if entry.data.get(CONF_USE_ADDON):
|
||||
# Do not use MQTT integration. Use own MQTT client.
|
||||
# Retrieve discovery info from the OpenZWave add-on.
|
||||
discovery_info = await hassio.async_get_addon_discovery_info(hass, "core_zwave")
|
||||
|
||||
if not discovery_info:
|
||||
_LOGGER.error("Failed to get add-on discovery info")
|
||||
raise ConfigEntryNotReady
|
||||
|
||||
discovery_info_config = discovery_info["config"]
|
||||
|
||||
host = discovery_info_config["host"]
|
||||
port = discovery_info_config["port"]
|
||||
username = discovery_info_config["username"]
|
||||
password = discovery_info_config["password"]
|
||||
mqtt_client = MQTTClient(host, port, username=username, password=password)
|
||||
manager_options["send_message"] = mqtt_client.send_message
|
||||
|
||||
else:
|
||||
mqtt_entries = hass.config_entries.async_entries("mqtt")
|
||||
if not mqtt_entries or mqtt_entries[0].state is not ConfigEntryState.LOADED:
|
||||
_LOGGER.error("MQTT integration is not set up")
|
||||
return False
|
||||
|
||||
mqtt_entry = mqtt_entries[0] # MQTT integration only has one entry.
|
||||
|
||||
@callback
|
||||
def send_message(topic, payload):
|
||||
if mqtt_entry.state is not ConfigEntryState.LOADED:
|
||||
_LOGGER.error("MQTT integration is not set up")
|
||||
return
|
||||
|
||||
hass.async_create_task(mqtt.async_publish(hass, topic, json.dumps(payload)))
|
||||
|
||||
manager_options["send_message"] = send_message
|
||||
|
||||
options = OZWOptions(**manager_options)
|
||||
manager = OZWManager(options)
|
||||
|
||||
hass.data[DOMAIN][MANAGER] = manager
|
||||
|
||||
@callback
|
||||
def async_node_added(node):
|
||||
# Caution: This is also called on (re)start.
|
||||
_LOGGER.debug("[NODE ADDED] node_id: %s", node.id)
|
||||
data_nodes[node.id] = node
|
||||
if node.id not in data_values:
|
||||
data_values[node.id] = []
|
||||
|
||||
@callback
|
||||
def async_node_changed(node):
|
||||
_LOGGER.debug("[NODE CHANGED] node_id: %s", node.id)
|
||||
data_nodes[node.id] = node
|
||||
# notify devices about the node change
|
||||
if node.id not in removed_nodes:
|
||||
hass.async_create_task(async_handle_node_update(hass, node))
|
||||
|
||||
@callback
|
||||
def async_node_removed(node):
|
||||
_LOGGER.debug("[NODE REMOVED] node_id: %s", node.id)
|
||||
data_nodes.pop(node.id)
|
||||
# node added/removed events also happen on (re)starts of hass/mqtt/ozw
|
||||
# cleanup device/entity registry if we know this node is permanently deleted
|
||||
# entities itself are removed by the values logic
|
||||
if node.id in removed_nodes:
|
||||
hass.async_create_task(async_handle_remove_node(hass, node))
|
||||
removed_nodes.remove(node.id)
|
||||
|
||||
@callback
|
||||
def async_instance_event(message):
|
||||
event = message["event"]
|
||||
event_data = message["data"]
|
||||
_LOGGER.debug("[INSTANCE EVENT]: %s - data: %s", event, event_data)
|
||||
# The actual removal action of a Z-Wave node is reported as instance event
|
||||
# Only when this event is detected we cleanup the device and entities from hass
|
||||
# Note: Find a more elegant way of doing this, e.g. a notification of this event from OZW
|
||||
if event in ("removenode", "removefailednode") and "Node" in event_data:
|
||||
removed_nodes.append(event_data["Node"])
|
||||
|
||||
@callback
|
||||
def async_value_added(value):
|
||||
node = value.node
|
||||
# Clean up node.node_id and node.id use. They are the same.
|
||||
node_id = value.node.node_id
|
||||
|
||||
# Filter out CommandClasses we're definitely not interested in.
|
||||
if value.command_class in (CommandClass.MANUFACTURER_SPECIFIC,):
|
||||
return
|
||||
|
||||
_LOGGER.debug(
|
||||
"[VALUE ADDED] node_id: %s - label: %s - value: %s - value_id: %s - CC: %s",
|
||||
value.node.id,
|
||||
value.label,
|
||||
value.value,
|
||||
value.value_id_key,
|
||||
value.command_class,
|
||||
)
|
||||
|
||||
node_data_values = data_values[node_id]
|
||||
|
||||
# Check if this value should be tracked by an existing entity
|
||||
value_unique_id = create_value_id(value)
|
||||
for values in node_data_values:
|
||||
values.async_check_value(value)
|
||||
if values.values_id == value_unique_id:
|
||||
return # this value already has an entity
|
||||
|
||||
# Run discovery on it and see if any entities need created
|
||||
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, options, schema, value)
|
||||
values.async_setup()
|
||||
|
||||
# This is legacy and can be cleaned up since we are in the main thread:
|
||||
# We create a new list and update the reference here so that
|
||||
# the list can be safely iterated over in the main thread
|
||||
data_values[node_id] = node_data_values + [values]
|
||||
|
||||
@callback
|
||||
def async_value_changed(value):
|
||||
# if an entity belonging to this value needs updating,
|
||||
# it's handled within the entity logic
|
||||
_LOGGER.debug(
|
||||
"[VALUE CHANGED] node_id: %s - label: %s - value: %s - value_id: %s - CC: %s",
|
||||
value.node.id,
|
||||
value.label,
|
||||
value.value,
|
||||
value.value_id_key,
|
||||
value.command_class,
|
||||
)
|
||||
# Handle a scene activation message
|
||||
if value.command_class in (
|
||||
CommandClass.SCENE_ACTIVATION,
|
||||
CommandClass.CENTRAL_SCENE,
|
||||
):
|
||||
async_handle_scene_activated(hass, value)
|
||||
return
|
||||
|
||||
@callback
|
||||
def async_value_removed(value):
|
||||
_LOGGER.debug(
|
||||
"[VALUE REMOVED] node_id: %s - label: %s - value: %s - value_id: %s - CC: %s",
|
||||
value.node.id,
|
||||
value.label,
|
||||
value.value,
|
||||
value.value_id_key,
|
||||
value.command_class,
|
||||
)
|
||||
# signal all entities using this value for removal
|
||||
value_unique_id = create_value_id(value)
|
||||
async_dispatcher_send(hass, const.SIGNAL_DELETE_ENTITY, value_unique_id)
|
||||
# remove value from our local list
|
||||
node_data_values = data_values[value.node.id]
|
||||
node_data_values[:] = [
|
||||
item for item in node_data_values if item.values_id != value_unique_id
|
||||
]
|
||||
|
||||
# Listen to events for node and value changes
|
||||
for event, event_callback in (
|
||||
(EVENT_NODE_ADDED, async_node_added),
|
||||
(EVENT_NODE_CHANGED, async_node_changed),
|
||||
(EVENT_NODE_REMOVED, async_node_removed),
|
||||
(EVENT_VALUE_ADDED, async_value_added),
|
||||
(EVENT_VALUE_CHANGED, async_value_changed),
|
||||
(EVENT_VALUE_REMOVED, async_value_removed),
|
||||
(EVENT_INSTANCE_EVENT, async_instance_event),
|
||||
):
|
||||
ozw_data[DATA_UNSUBSCRIBE].append(options.listen(event, event_callback))
|
||||
|
||||
# Register Services
|
||||
services = ZWaveServices(hass, manager)
|
||||
services.async_register()
|
||||
|
||||
# Register WebSocket API
|
||||
async_register_api(hass)
|
||||
|
||||
@callback
|
||||
def async_receive_message(msg):
|
||||
manager.receive_message(msg.topic, msg.payload)
|
||||
|
||||
async def start_platforms():
|
||||
await asyncio.gather(
|
||||
*(
|
||||
hass.config_entries.async_forward_entry_setup(entry, platform)
|
||||
for platform in PLATFORMS
|
||||
)
|
||||
)
|
||||
if entry.data.get(CONF_USE_ADDON):
|
||||
mqtt_client_task = asyncio.create_task(mqtt_client.start_client(manager))
|
||||
|
||||
async def async_stop_mqtt_client(event=None):
|
||||
"""Stop the mqtt client.
|
||||
|
||||
Do not unsubscribe the manager topic.
|
||||
"""
|
||||
mqtt_client_task.cancel()
|
||||
with suppress(asyncio.CancelledError):
|
||||
await mqtt_client_task
|
||||
|
||||
ozw_data[DATA_UNSUBSCRIBE].append(
|
||||
hass.bus.async_listen_once(
|
||||
EVENT_HOMEASSISTANT_STOP, async_stop_mqtt_client
|
||||
)
|
||||
)
|
||||
ozw_data[DATA_STOP_MQTT_CLIENT] = async_stop_mqtt_client
|
||||
|
||||
else:
|
||||
ozw_data[DATA_UNSUBSCRIBE].append(
|
||||
await mqtt.async_subscribe(
|
||||
hass, f"{manager.options.topic_prefix}#", async_receive_message
|
||||
)
|
||||
)
|
||||
|
||||
hass.async_create_task(start_platforms())
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
# cleanup platforms
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
if not unload_ok:
|
||||
return False
|
||||
|
||||
# unsubscribe all listeners
|
||||
for unsubscribe_listener in hass.data[DOMAIN][entry.entry_id][DATA_UNSUBSCRIBE]:
|
||||
unsubscribe_listener()
|
||||
|
||||
if entry.data.get(CONF_USE_ADDON):
|
||||
async_stop_mqtt_client = hass.data[DOMAIN][entry.entry_id][
|
||||
DATA_STOP_MQTT_CLIENT
|
||||
]
|
||||
await async_stop_mqtt_client()
|
||||
|
||||
hass.data[DOMAIN].pop(entry.entry_id)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
||||
"""Remove a config entry."""
|
||||
if not entry.data.get(CONF_INTEGRATION_CREATED_ADDON):
|
||||
return
|
||||
|
||||
try:
|
||||
await hassio.async_stop_addon(hass, "core_zwave")
|
||||
except HassioAPIError as err:
|
||||
_LOGGER.error("Failed to stop the OpenZWave add-on: %s", err)
|
||||
return
|
||||
try:
|
||||
await hassio.async_uninstall_addon(hass, "core_zwave")
|
||||
except HassioAPIError as err:
|
||||
_LOGGER.error("Failed to uninstall the OpenZWave add-on: %s", err)
|
||||
|
||||
|
||||
async def async_handle_remove_node(hass: HomeAssistant, node: OZWNode):
|
||||
"""Handle the removal of a Z-Wave node, removing all traces in device/entity registry."""
|
||||
dev_registry = await get_dev_reg(hass)
|
||||
# grab device in device registry attached to this node
|
||||
dev_id = create_device_id(node)
|
||||
device = dev_registry.async_get_device({(DOMAIN, dev_id)})
|
||||
if not device:
|
||||
return
|
||||
devices_to_remove = [device.id]
|
||||
# also grab slave devices (node instances)
|
||||
for item in dev_registry.devices.values():
|
||||
if item.via_device_id == device.id:
|
||||
devices_to_remove.append(item.id)
|
||||
# remove all devices in registry related to this node
|
||||
# note: removal of entity registry is handled by core
|
||||
for dev_id in devices_to_remove:
|
||||
dev_registry.async_remove_device(dev_id)
|
||||
|
||||
|
||||
async def async_handle_node_update(hass: HomeAssistant, node: OZWNode):
|
||||
"""
|
||||
Handle a node updated event from OZW.
|
||||
|
||||
Meaning some of the basic info like name/model is updated.
|
||||
We want these changes to be pushed to the device registry.
|
||||
"""
|
||||
dev_registry = await get_dev_reg(hass)
|
||||
# grab device in device registry attached to this node
|
||||
dev_id = create_device_id(node)
|
||||
device = dev_registry.async_get_device({(DOMAIN, dev_id)})
|
||||
if not device:
|
||||
return
|
||||
# update device in device registry with (updated) info
|
||||
for item in dev_registry.devices.values():
|
||||
if device.id not in (item.id, item.via_device_id):
|
||||
continue
|
||||
dev_name = create_device_name(node)
|
||||
dev_registry.async_update_device(
|
||||
item.id,
|
||||
manufacturer=node.node_manufacturer_name,
|
||||
model=node.node_product_name,
|
||||
name=dev_name,
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def async_handle_scene_activated(hass: HomeAssistant, scene_value: OZWValue):
|
||||
"""Handle a (central) scene activation message."""
|
||||
node_id = scene_value.node.id
|
||||
ozw_instance_id = scene_value.ozw_instance.id
|
||||
scene_id = scene_value.index
|
||||
scene_label = scene_value.label
|
||||
if scene_value.command_class == CommandClass.SCENE_ACTIVATION:
|
||||
# legacy/network scene
|
||||
scene_value_id = scene_value.value
|
||||
scene_value_label = scene_value.label
|
||||
else:
|
||||
# central scene command
|
||||
if scene_value.type != ValueType.LIST:
|
||||
return
|
||||
scene_value_label = scene_value.value["Selected"]
|
||||
scene_value_id = scene_value.value["Selected_id"]
|
||||
|
||||
_LOGGER.debug(
|
||||
"[SCENE_ACTIVATED] ozw_instance: %s - node_id: %s - scene_id: %s - scene_value_id: %s",
|
||||
ozw_instance_id,
|
||||
node_id,
|
||||
scene_id,
|
||||
scene_value_id,
|
||||
)
|
||||
# Simply forward it to the hass event bus
|
||||
hass.bus.async_fire(
|
||||
const.EVENT_SCENE_ACTIVATED,
|
||||
{
|
||||
const.ATTR_INSTANCE_ID: ozw_instance_id,
|
||||
const.ATTR_NODE_ID: node_id,
|
||||
const.ATTR_SCENE_ID: scene_id,
|
||||
const.ATTR_SCENE_LABEL: scene_label,
|
||||
const.ATTR_SCENE_VALUE_ID: scene_value_id,
|
||||
const.ATTR_SCENE_VALUE_LABEL: scene_value_label,
|
||||
},
|
||||
)
|
@ -1,396 +0,0 @@
|
||||
"""Representation of Z-Wave binary_sensors."""
|
||||
from openzwavemqtt.const import CommandClass, ValueIndex, ValueType
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
DOMAIN as BINARY_SENSOR_DOMAIN,
|
||||
BinarySensorDeviceClass,
|
||||
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 .const import DATA_UNSUBSCRIBE, DOMAIN
|
||||
from .entity import ZWaveDeviceEntity
|
||||
|
||||
NOTIFICATION_TYPE = "index"
|
||||
NOTIFICATION_VALUES = "values"
|
||||
NOTIFICATION_DEVICE_CLASS = "device_class"
|
||||
NOTIFICATION_SENSOR_ENABLED = "enabled"
|
||||
NOTIFICATION_OFF_VALUE = "off_value"
|
||||
|
||||
NOTIFICATION_VALUE_CLEAR = 0
|
||||
|
||||
# Translation from values in Notification CC to binary sensors
|
||||
# https://github.com/OpenZWave/open-zwave/blob/master/config/NotificationCCTypes.xml
|
||||
NOTIFICATION_SENSORS = [
|
||||
{
|
||||
# Index 1: Smoke Alarm - Value Id's 1 and 2
|
||||
# Assuming here that Value 1 and 2 are not present at the same time
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_SMOKE_ALARM,
|
||||
NOTIFICATION_VALUES: [1, 2],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.SMOKE,
|
||||
},
|
||||
{
|
||||
# Index 1: Smoke Alarm - All other Value Id's
|
||||
# Create as disabled sensors
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_SMOKE_ALARM,
|
||||
NOTIFICATION_VALUES: [3, 4, 5, 6, 7, 8],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.SMOKE,
|
||||
NOTIFICATION_SENSOR_ENABLED: False,
|
||||
},
|
||||
{
|
||||
# Index 2: Carbon Monoxide - Value Id's 1 and 2
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_CARBON_MONOOXIDE,
|
||||
NOTIFICATION_VALUES: [1, 2],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.GAS,
|
||||
},
|
||||
{
|
||||
# Index 2: Carbon Monoxide - All other Value Id's
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_CARBON_MONOOXIDE,
|
||||
NOTIFICATION_VALUES: [4, 5, 7],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.GAS,
|
||||
NOTIFICATION_SENSOR_ENABLED: False,
|
||||
},
|
||||
{
|
||||
# Index 3: Carbon Dioxide - Value Id's 1 and 2
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_CARBON_DIOXIDE,
|
||||
NOTIFICATION_VALUES: [1, 2],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.GAS,
|
||||
},
|
||||
{
|
||||
# Index 3: Carbon Dioxide - All other Value Id's
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_CARBON_DIOXIDE,
|
||||
NOTIFICATION_VALUES: [4, 5, 7],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.GAS,
|
||||
NOTIFICATION_SENSOR_ENABLED: False,
|
||||
},
|
||||
{
|
||||
# Index 4: Heat - Value Id's 1, 2, 5, 6 (heat/underheat)
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_HEAT,
|
||||
NOTIFICATION_VALUES: [1, 2, 5, 6],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.HEAT,
|
||||
},
|
||||
{
|
||||
# Index 4: Heat - All other Value Id's
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_HEAT,
|
||||
NOTIFICATION_VALUES: [3, 4, 8, 10, 11],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.HEAT,
|
||||
NOTIFICATION_SENSOR_ENABLED: False,
|
||||
},
|
||||
{
|
||||
# Index 5: Water - Value Id's 1, 2, 3, 4
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_WATER,
|
||||
NOTIFICATION_VALUES: [1, 2, 3, 4],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.MOISTURE,
|
||||
},
|
||||
{
|
||||
# Index 5: Water - All other Value Id's
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_WATER,
|
||||
NOTIFICATION_VALUES: [5],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.MOISTURE,
|
||||
NOTIFICATION_SENSOR_ENABLED: False,
|
||||
},
|
||||
{
|
||||
# Index 6: Access Control - Value Id's 1, 2, 3, 4 (Lock)
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_ACCESS_CONTROL,
|
||||
NOTIFICATION_VALUES: [1, 2, 3, 4],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.LOCK,
|
||||
},
|
||||
{
|
||||
# Index 6: Access Control - Value Id 22 (door/window open)
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_ACCESS_CONTROL,
|
||||
NOTIFICATION_VALUES: [22],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.DOOR,
|
||||
NOTIFICATION_OFF_VALUE: 23,
|
||||
},
|
||||
{
|
||||
# Index 7: Home Security - Value Id's 1, 2 (intrusion)
|
||||
# Assuming that value 1 and 2 are not present at the same time
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_HOME_SECURITY,
|
||||
NOTIFICATION_VALUES: [1, 2],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.SAFETY,
|
||||
},
|
||||
{
|
||||
# Index 7: Home Security - Value Id's 3, 4, 9 (tampering)
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_HOME_SECURITY,
|
||||
NOTIFICATION_VALUES: [3, 4, 9],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.SAFETY,
|
||||
},
|
||||
{
|
||||
# Index 7: Home Security - Value Id's 5, 6 (glass breakage)
|
||||
# Assuming that value 5 and 6 are not present at the same time
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_HOME_SECURITY,
|
||||
NOTIFICATION_VALUES: [5, 6],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.SAFETY,
|
||||
},
|
||||
{
|
||||
# Index 7: Home Security - Value Id's 7, 8 (motion)
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_HOME_SECURITY,
|
||||
NOTIFICATION_VALUES: [7, 8],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.MOTION,
|
||||
},
|
||||
{
|
||||
# Index 8: Power management - Values 1...9
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_POWER_MANAGEMENT,
|
||||
NOTIFICATION_VALUES: [1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.POWER,
|
||||
NOTIFICATION_SENSOR_ENABLED: False,
|
||||
},
|
||||
{
|
||||
# Index 8: Power management - Values 10...15
|
||||
# Battery values (mutually exclusive)
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_POWER_MANAGEMENT,
|
||||
NOTIFICATION_VALUES: [10, 11, 12, 13, 14, 15],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.POWER,
|
||||
NOTIFICATION_SENSOR_ENABLED: False,
|
||||
NOTIFICATION_OFF_VALUE: None,
|
||||
},
|
||||
{
|
||||
# Index 9: System - Value Id's 1, 2, 6, 7
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_SYSTEM,
|
||||
NOTIFICATION_VALUES: [1, 2, 6, 7],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.PROBLEM,
|
||||
NOTIFICATION_SENSOR_ENABLED: False,
|
||||
},
|
||||
{
|
||||
# Index 10: Emergency - Value Id's 1, 2, 3
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_EMERGENCY,
|
||||
NOTIFICATION_VALUES: [1, 2, 3],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.PROBLEM,
|
||||
},
|
||||
{
|
||||
# Index 11: Clock - Value Id's 1, 2
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_CLOCK,
|
||||
NOTIFICATION_VALUES: [1, 2],
|
||||
NOTIFICATION_DEVICE_CLASS: None,
|
||||
NOTIFICATION_SENSOR_ENABLED: False,
|
||||
},
|
||||
{
|
||||
# Index 12: Appliance - All Value Id's
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_APPLIANCE,
|
||||
NOTIFICATION_VALUES: [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
],
|
||||
NOTIFICATION_DEVICE_CLASS: None,
|
||||
},
|
||||
{
|
||||
# Index 13: Home Health - Value Id's 1,2,3,4,5
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_APPLIANCE,
|
||||
NOTIFICATION_VALUES: [1, 2, 3, 4, 5],
|
||||
NOTIFICATION_DEVICE_CLASS: None,
|
||||
},
|
||||
{
|
||||
# Index 14: Siren
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_SIREN,
|
||||
NOTIFICATION_VALUES: [1],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.SOUND,
|
||||
},
|
||||
{
|
||||
# Index 15: Water valve
|
||||
# ignore non-boolean values
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_WATER_VALVE,
|
||||
NOTIFICATION_VALUES: [3, 4],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.PROBLEM,
|
||||
},
|
||||
{
|
||||
# Index 16: Weather
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_WEATHER,
|
||||
NOTIFICATION_VALUES: [1, 2],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.PROBLEM,
|
||||
},
|
||||
{
|
||||
# Index 17: Irrigation
|
||||
# ignore non-boolean values
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_IRRIGATION,
|
||||
NOTIFICATION_VALUES: [1, 2, 3, 4, 5],
|
||||
NOTIFICATION_DEVICE_CLASS: None,
|
||||
},
|
||||
{
|
||||
# Index 18: Gas
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_GAS,
|
||||
NOTIFICATION_VALUES: [1, 2, 3, 4],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.GAS,
|
||||
},
|
||||
{
|
||||
# Index 18: Gas
|
||||
NOTIFICATION_TYPE: ValueIndex.NOTIFICATION_GAS,
|
||||
NOTIFICATION_VALUES: [6],
|
||||
NOTIFICATION_DEVICE_CLASS: BinarySensorDeviceClass.PROBLEM,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up Z-Wave binary_sensor from config entry."""
|
||||
|
||||
@callback
|
||||
def async_add_binary_sensor(values):
|
||||
"""Add Z-Wave Binary Sensor(s)."""
|
||||
async_add_entities(VALUE_TYPE_SENSORS[values.primary.type](values))
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id][DATA_UNSUBSCRIBE].append(
|
||||
async_dispatcher_connect(
|
||||
hass, f"{DOMAIN}_new_{BINARY_SENSOR_DOMAIN}", async_add_binary_sensor
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def async_get_legacy_binary_sensors(values):
|
||||
"""Add Legacy/classic Z-Wave Binary Sensor."""
|
||||
return [ZWaveBinarySensor(values)]
|
||||
|
||||
|
||||
@callback
|
||||
def async_get_notification_sensors(values):
|
||||
"""Convert Notification values into binary sensors."""
|
||||
sensors_to_add = []
|
||||
for list_value in values.primary.value["List"]:
|
||||
# check if we have a mapping for this value
|
||||
for item in NOTIFICATION_SENSORS:
|
||||
if item[NOTIFICATION_TYPE] != values.primary.index:
|
||||
continue
|
||||
if list_value["Value"] not in item[NOTIFICATION_VALUES]:
|
||||
continue
|
||||
sensors_to_add.append(
|
||||
ZWaveListValueSensor(
|
||||
# required values
|
||||
values,
|
||||
list_value["Value"],
|
||||
item[NOTIFICATION_DEVICE_CLASS],
|
||||
# optional values
|
||||
item.get(NOTIFICATION_SENSOR_ENABLED, True),
|
||||
item.get(NOTIFICATION_OFF_VALUE, NOTIFICATION_VALUE_CLEAR),
|
||||
)
|
||||
)
|
||||
return sensors_to_add
|
||||
|
||||
|
||||
VALUE_TYPE_SENSORS = {
|
||||
ValueType.BOOL: async_get_legacy_binary_sensors,
|
||||
ValueType.LIST: async_get_notification_sensors,
|
||||
}
|
||||
|
||||
|
||||
class ZWaveBinarySensor(ZWaveDeviceEntity, BinarySensorEntity):
|
||||
"""Representation of a Z-Wave binary_sensor."""
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return if the sensor is on or off."""
|
||||
return self.values.primary.value
|
||||
|
||||
@property
|
||||
def entity_registry_enabled_default(self) -> bool:
|
||||
"""Return if the entity should be enabled when first added to the entity registry."""
|
||||
# Legacy binary sensors are phased out (replaced by notification sensors)
|
||||
# Disable by default to not confuse users
|
||||
for item in self.values.primary.node.values():
|
||||
if item.command_class == CommandClass.NOTIFICATION:
|
||||
# This device properly implements the Notification CC, legacy sensor can be disabled
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class ZWaveListValueSensor(ZWaveDeviceEntity, BinarySensorEntity):
|
||||
"""Representation of a binary_sensor from values in the Z-Wave Notification CommandClass."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
values,
|
||||
on_value,
|
||||
device_class=None,
|
||||
default_enabled=True,
|
||||
off_value=NOTIFICATION_VALUE_CLEAR,
|
||||
):
|
||||
"""Initialize a ZWaveListValueSensor entity."""
|
||||
super().__init__(values)
|
||||
self._on_value = on_value
|
||||
self._device_class = device_class
|
||||
self._default_enabled = default_enabled
|
||||
self._off_value = off_value
|
||||
# make sure the correct value is selected at startup
|
||||
self._state = False
|
||||
self.on_value_update()
|
||||
|
||||
@callback
|
||||
def on_value_update(self):
|
||||
"""Call when a value is added/updated in the underlying EntityValues Collection."""
|
||||
if self.values.primary.value["Selected_id"] == self._on_value:
|
||||
# Only when the active ID exactly matches our watched ON value, set sensor state to ON
|
||||
self._state = True
|
||||
elif self.values.primary.value["Selected_id"] == self._off_value:
|
||||
# Only when the active ID exactly matches our watched OFF value, set sensor state to OFF
|
||||
self._state = False
|
||||
elif (
|
||||
self._off_value is None
|
||||
and self.values.primary.value["Selected_id"] != self._on_value
|
||||
):
|
||||
# Off value not explicitly specified
|
||||
# Some values are reset by the simple fact they're overruled by another value coming in
|
||||
# For example the battery charging values in Power Management Index
|
||||
self._state = False
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the entity."""
|
||||
# Append value label to base name
|
||||
base_name = super().name
|
||||
value_label = ""
|
||||
for item in self.values.primary.value["List"]:
|
||||
if item["Value"] == self._on_value:
|
||||
value_label = item["Label"]
|
||||
break
|
||||
# Strip "on location" / "at location" from name
|
||||
# Note: We're assuming that we don't retrieve 2 values with different location
|
||||
value_label = value_label.split(" on ")[0]
|
||||
value_label = value_label.split(" at ")[0]
|
||||
return f"{base_name}: {value_label}"
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the unique_id of the entity."""
|
||||
unique_id = super().unique_id
|
||||
return f"{unique_id}.{self._on_value}"
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return if the sensor is on or off."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the class of this device, from component DEVICE_CLASSES."""
|
||||
return self._device_class
|
||||
|
||||
@property
|
||||
def entity_registry_enabled_default(self) -> bool:
|
||||
"""Return if the entity should be enabled when first added to the entity registry."""
|
||||
# We hide the more advanced sensors by default to not overwhelm users
|
||||
return self._default_enabled
|
@ -1,379 +0,0 @@
|
||||
"""Support for Z-Wave climate devices."""
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import IntEnum
|
||||
import logging
|
||||
|
||||
from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN, ClimateEntity
|
||||
from homeassistant.components.climate.const import (
|
||||
ATTR_HVAC_MODE,
|
||||
ATTR_TARGET_TEMP_HIGH,
|
||||
ATTR_TARGET_TEMP_LOW,
|
||||
CURRENT_HVAC_COOL,
|
||||
CURRENT_HVAC_FAN,
|
||||
CURRENT_HVAC_HEAT,
|
||||
CURRENT_HVAC_IDLE,
|
||||
CURRENT_HVAC_OFF,
|
||||
HVAC_MODE_COOL,
|
||||
HVAC_MODE_DRY,
|
||||
HVAC_MODE_FAN_ONLY,
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_HEAT_COOL,
|
||||
HVAC_MODE_OFF,
|
||||
PRESET_NONE,
|
||||
SUPPORT_FAN_MODE,
|
||||
SUPPORT_PRESET_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 .const import DATA_UNSUBSCRIBE, DOMAIN
|
||||
from .entity import ZWaveDeviceEntity
|
||||
|
||||
VALUE_LIST = "List"
|
||||
VALUE_ID = "Value"
|
||||
VALUE_LABEL = "Label"
|
||||
VALUE_SELECTED_ID = "Selected_id"
|
||||
VALUE_SELECTED_LABEL = "Selected"
|
||||
|
||||
ATTR_FAN_ACTION = "fan_action"
|
||||
ATTR_VALVE_POSITION = "valve_position"
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ThermostatMode(IntEnum):
|
||||
"""Enum with all (known/used) Z-Wave ThermostatModes."""
|
||||
|
||||
# https://github.com/OpenZWave/open-zwave/blob/master/cpp/src/command_classes/ThermostatMode.cpp
|
||||
OFF = 0
|
||||
HEAT = 1
|
||||
COOL = 2
|
||||
AUTO = 3
|
||||
AUXILIARY = 4
|
||||
RESUME_ON = 5
|
||||
FAN = 6
|
||||
FURNANCE = 7
|
||||
DRY = 8
|
||||
MOIST = 9
|
||||
AUTO_CHANGE_OVER = 10
|
||||
HEATING_ECON = 11
|
||||
COOLING_ECON = 12
|
||||
AWAY = 13
|
||||
FULL_POWER = 15
|
||||
MANUFACTURER_SPECIFIC = 31
|
||||
|
||||
|
||||
# In Z-Wave the modes and presets are both in ThermostatMode.
|
||||
# This list contains thermostatmodes we should consider a mode only
|
||||
MODES_LIST = [
|
||||
ThermostatMode.OFF,
|
||||
ThermostatMode.HEAT,
|
||||
ThermostatMode.COOL,
|
||||
ThermostatMode.AUTO,
|
||||
ThermostatMode.AUTO_CHANGE_OVER,
|
||||
]
|
||||
|
||||
MODE_SETPOINT_MAPPINGS = {
|
||||
ThermostatMode.OFF: (),
|
||||
ThermostatMode.HEAT: ("setpoint_heating",),
|
||||
ThermostatMode.COOL: ("setpoint_cooling",),
|
||||
ThermostatMode.AUTO: ("setpoint_heating", "setpoint_cooling"),
|
||||
ThermostatMode.AUXILIARY: ("setpoint_heating",),
|
||||
ThermostatMode.FURNANCE: ("setpoint_furnace",),
|
||||
ThermostatMode.DRY: ("setpoint_dry_air",),
|
||||
ThermostatMode.MOIST: ("setpoint_moist_air",),
|
||||
ThermostatMode.AUTO_CHANGE_OVER: ("setpoint_auto_changeover",),
|
||||
ThermostatMode.HEATING_ECON: ("setpoint_eco_heating",),
|
||||
ThermostatMode.COOLING_ECON: ("setpoint_eco_cooling",),
|
||||
ThermostatMode.AWAY: ("setpoint_away_heating", "setpoint_away_cooling"),
|
||||
ThermostatMode.FULL_POWER: ("setpoint_full_power",),
|
||||
}
|
||||
|
||||
|
||||
# strings, OZW and/or qt-ozw does not send numeric values
|
||||
# https://github.com/OpenZWave/open-zwave/blob/master/cpp/src/command_classes/ThermostatOperatingState.cpp
|
||||
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,
|
||||
}
|
||||
|
||||
|
||||
# Map Z-Wave HVAC Mode to Home Assistant value
|
||||
# Note: We treat "auto" as "heat_cool" as most Z-Wave devices
|
||||
# report auto_changeover as auto without schedule support.
|
||||
ZW_HVAC_MODE_MAPPINGS = {
|
||||
ThermostatMode.OFF: HVAC_MODE_OFF,
|
||||
ThermostatMode.HEAT: HVAC_MODE_HEAT,
|
||||
ThermostatMode.COOL: HVAC_MODE_COOL,
|
||||
# Z-Wave auto mode is actually heat/cool in the hass world
|
||||
ThermostatMode.AUTO: HVAC_MODE_HEAT_COOL,
|
||||
ThermostatMode.AUXILIARY: HVAC_MODE_HEAT,
|
||||
ThermostatMode.FAN: HVAC_MODE_FAN_ONLY,
|
||||
ThermostatMode.FURNANCE: HVAC_MODE_HEAT,
|
||||
ThermostatMode.DRY: HVAC_MODE_DRY,
|
||||
ThermostatMode.AUTO_CHANGE_OVER: HVAC_MODE_HEAT_COOL,
|
||||
ThermostatMode.HEATING_ECON: HVAC_MODE_HEAT,
|
||||
ThermostatMode.COOLING_ECON: HVAC_MODE_COOL,
|
||||
ThermostatMode.AWAY: HVAC_MODE_HEAT_COOL,
|
||||
ThermostatMode.FULL_POWER: HVAC_MODE_HEAT,
|
||||
}
|
||||
|
||||
# Map Home Assistant HVAC Mode to Z-Wave value
|
||||
HVAC_MODE_ZW_MAPPINGS = {
|
||||
HVAC_MODE_OFF: ThermostatMode.OFF,
|
||||
HVAC_MODE_HEAT: ThermostatMode.HEAT,
|
||||
HVAC_MODE_COOL: ThermostatMode.COOL,
|
||||
HVAC_MODE_FAN_ONLY: ThermostatMode.FAN,
|
||||
HVAC_MODE_DRY: ThermostatMode.DRY,
|
||||
HVAC_MODE_HEAT_COOL: ThermostatMode.AUTO_CHANGE_OVER,
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up Z-Wave Climate from Config Entry."""
|
||||
|
||||
@callback
|
||||
def async_add_climate(values):
|
||||
"""Add Z-Wave Climate."""
|
||||
async_add_entities([ZWaveClimateEntity(values)])
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id][DATA_UNSUBSCRIBE].append(
|
||||
async_dispatcher_connect(
|
||||
hass, f"{DOMAIN}_new_{CLIMATE_DOMAIN}", async_add_climate
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class ZWaveClimateEntity(ZWaveDeviceEntity, ClimateEntity):
|
||||
"""Representation of a Z-Wave Climate device."""
|
||||
|
||||
def __init__(self, values):
|
||||
"""Initialize the entity."""
|
||||
super().__init__(values)
|
||||
self._hvac_modes = {}
|
||||
self._hvac_presets = {}
|
||||
self.on_value_update()
|
||||
|
||||
@callback
|
||||
def on_value_update(self):
|
||||
"""Call when the underlying values object changes."""
|
||||
self._current_mode_setpoint_values = self._get_current_mode_setpoint_values()
|
||||
if not self._hvac_modes:
|
||||
self._set_modes_and_presets()
|
||||
|
||||
@property
|
||||
def hvac_mode(self):
|
||||
"""Return hvac operation ie. heat, cool mode."""
|
||||
if not self.values.mode:
|
||||
# Thermostat(valve) with no support for setting a mode is considered heating-only
|
||||
return HVAC_MODE_HEAT
|
||||
return ZW_HVAC_MODE_MAPPINGS.get(
|
||||
self.values.mode.value[VALUE_SELECTED_ID], HVAC_MODE_HEAT_COOL
|
||||
)
|
||||
|
||||
@property
|
||||
def hvac_modes(self):
|
||||
"""Return the list of available hvac operation modes."""
|
||||
return list(self._hvac_modes)
|
||||
|
||||
@property
|
||||
def fan_mode(self):
|
||||
"""Return the fan speed set."""
|
||||
return self.values.fan_mode.value[VALUE_SELECTED_LABEL]
|
||||
|
||||
@property
|
||||
def fan_modes(self):
|
||||
"""Return a list of available fan modes."""
|
||||
return [entry[VALUE_LABEL] for entry in self.values.fan_mode.value[VALUE_LIST]]
|
||||
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
"""Return the unit of measurement."""
|
||||
if self.values.temperature is not None and self.values.temperature.units == "F":
|
||||
return TEMP_FAHRENHEIT
|
||||
return TEMP_CELSIUS
|
||||
|
||||
@property
|
||||
def current_temperature(self):
|
||||
"""Return the current temperature."""
|
||||
if not self.values.temperature:
|
||||
return None
|
||||
return self.values.temperature.value
|
||||
|
||||
@property
|
||||
def hvac_action(self):
|
||||
"""Return the current running hvac operation if supported."""
|
||||
if not self.values.operating_state:
|
||||
return None
|
||||
cur_state = self.values.operating_state.value.lower()
|
||||
return HVAC_CURRENT_MAPPINGS.get(cur_state)
|
||||
|
||||
@property
|
||||
def preset_mode(self):
|
||||
"""Return preset operation ie. eco, away."""
|
||||
# A Zwave mode that can not be translated to a hass mode is considered a preset
|
||||
if not self.values.mode:
|
||||
return None
|
||||
if self.values.mode.value[VALUE_SELECTED_ID] not in MODES_LIST:
|
||||
return self.values.mode.value[VALUE_SELECTED_LABEL]
|
||||
return PRESET_NONE
|
||||
|
||||
@property
|
||||
def preset_modes(self):
|
||||
"""Return the list of available preset operation modes."""
|
||||
return list(self._hvac_presets)
|
||||
|
||||
@property
|
||||
def target_temperature(self):
|
||||
"""Return the temperature we try to reach."""
|
||||
return self._current_mode_setpoint_values[0].value
|
||||
|
||||
@property
|
||||
def target_temperature_low(self) -> float | None:
|
||||
"""Return the lowbound target temperature we try to reach."""
|
||||
return self._current_mode_setpoint_values[0].value
|
||||
|
||||
@property
|
||||
def target_temperature_high(self) -> float | None:
|
||||
"""Return the highbound target temperature we try to reach."""
|
||||
return self._current_mode_setpoint_values[1].value
|
||||
|
||||
async def async_set_temperature(self, **kwargs):
|
||||
"""Set new target temperature.
|
||||
|
||||
Must know if single or double setpoint.
|
||||
"""
|
||||
if (hvac_mode := kwargs.get(ATTR_HVAC_MODE)) is not None:
|
||||
await self.async_set_hvac_mode(hvac_mode)
|
||||
|
||||
if len(self._current_mode_setpoint_values) == 1:
|
||||
setpoint = self._current_mode_setpoint_values[0]
|
||||
target_temp = kwargs.get(ATTR_TEMPERATURE)
|
||||
if setpoint is not None and target_temp is not None:
|
||||
setpoint.send_value(target_temp)
|
||||
elif len(self._current_mode_setpoint_values) == 2:
|
||||
(setpoint_low, setpoint_high) = self._current_mode_setpoint_values
|
||||
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:
|
||||
setpoint_low.send_value(target_temp_low)
|
||||
if setpoint_high is not None and target_temp_high is not None:
|
||||
setpoint_high.send_value(target_temp_high)
|
||||
|
||||
async def async_set_fan_mode(self, fan_mode):
|
||||
"""Set new target fan mode."""
|
||||
# get id for this fan_mode
|
||||
fan_mode_value = _get_list_id(self.values.fan_mode.value[VALUE_LIST], fan_mode)
|
||||
if fan_mode_value is None:
|
||||
_LOGGER.warning("Received an invalid fan mode: %s", fan_mode)
|
||||
return
|
||||
self.values.fan_mode.send_value(fan_mode_value)
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode):
|
||||
"""Set new target hvac mode."""
|
||||
if not self.values.mode:
|
||||
# Thermostat(valve) with no support for setting a mode
|
||||
_LOGGER.warning(
|
||||
"Thermostat %s does not support setting a mode", self.entity_id
|
||||
)
|
||||
return
|
||||
if (hvac_mode_value := self._hvac_modes.get(hvac_mode)) is None:
|
||||
_LOGGER.warning("Received an invalid hvac mode: %s", hvac_mode)
|
||||
return
|
||||
self.values.mode.send_value(hvac_mode_value)
|
||||
|
||||
async def async_set_preset_mode(self, preset_mode):
|
||||
"""Set new target preset mode."""
|
||||
if preset_mode == PRESET_NONE:
|
||||
# try to restore to the (translated) main hvac mode
|
||||
await self.async_set_hvac_mode(self.hvac_mode)
|
||||
return
|
||||
preset_mode_value = self._hvac_presets.get(preset_mode)
|
||||
if preset_mode_value is None:
|
||||
_LOGGER.warning("Received an invalid preset mode: %s", preset_mode)
|
||||
return
|
||||
self.values.mode.send_value(preset_mode_value)
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return the optional state attributes."""
|
||||
data = super().extra_state_attributes
|
||||
if self.values.fan_action:
|
||||
data[ATTR_FAN_ACTION] = self.values.fan_action.value
|
||||
if self.values.valve_position:
|
||||
data[
|
||||
ATTR_VALVE_POSITION
|
||||
] = f"{self.values.valve_position.value} {self.values.valve_position.units}"
|
||||
return data
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Return the list of supported features."""
|
||||
support = 0
|
||||
if len(self._current_mode_setpoint_values) == 1:
|
||||
support |= SUPPORT_TARGET_TEMPERATURE
|
||||
if len(self._current_mode_setpoint_values) > 1:
|
||||
support |= SUPPORT_TARGET_TEMPERATURE_RANGE
|
||||
if self.values.fan_mode:
|
||||
support |= SUPPORT_FAN_MODE
|
||||
if self.values.mode:
|
||||
support |= SUPPORT_PRESET_MODE
|
||||
return support
|
||||
|
||||
def _get_current_mode_setpoint_values(self) -> tuple:
|
||||
"""Return a tuple of current setpoint Z-Wave value(s)."""
|
||||
if not self.values.mode:
|
||||
setpoint_names = ("setpoint_heating",)
|
||||
else:
|
||||
current_mode = self.values.mode.value[VALUE_SELECTED_ID]
|
||||
setpoint_names = MODE_SETPOINT_MAPPINGS.get(current_mode, ())
|
||||
# we do not want None values in our tuple so check if the value exists
|
||||
return tuple(
|
||||
getattr(self.values, value_name)
|
||||
for value_name in setpoint_names
|
||||
if getattr(self.values, value_name, None)
|
||||
)
|
||||
|
||||
def _set_modes_and_presets(self):
|
||||
"""Convert Z-Wave Thermostat modes into Home Assistant modes and presets."""
|
||||
all_modes = {}
|
||||
all_presets = {PRESET_NONE: None}
|
||||
if self.values.mode:
|
||||
# Z-Wave uses one list for both modes and presets.
|
||||
# Iterate over all Z-Wave ThermostatModes and extract the hvac modes and presets.
|
||||
for val in self.values.mode.value[VALUE_LIST]:
|
||||
if val[VALUE_ID] in MODES_LIST:
|
||||
# treat value as hvac mode
|
||||
hass_mode = ZW_HVAC_MODE_MAPPINGS.get(val[VALUE_ID])
|
||||
all_modes[hass_mode] = val[VALUE_ID]
|
||||
else:
|
||||
# treat value as hvac preset
|
||||
all_presets[val[VALUE_LABEL]] = val[VALUE_ID]
|
||||
else:
|
||||
all_modes[HVAC_MODE_HEAT] = None
|
||||
self._hvac_modes = all_modes
|
||||
self._hvac_presets = all_presets
|
||||
|
||||
|
||||
def _get_list_id(value_lst, value_lbl):
|
||||
"""Return the id for the value in the list."""
|
||||
return next(
|
||||
(val[VALUE_ID] for val in value_lst if val[VALUE_LABEL] == value_lbl), None
|
||||
)
|
@ -1,228 +0,0 @@
|
||||
"""Config flow for ozw integration."""
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components import hassio
|
||||
from homeassistant.components.hassio import HassioServiceInfo
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.data_entry_flow import AbortFlow, FlowResult
|
||||
|
||||
from .const import CONF_INTEGRATION_CREATED_ADDON, CONF_USE_ADDON, DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_ADDON_DEVICE = "device"
|
||||
CONF_ADDON_NETWORK_KEY = "network_key"
|
||||
CONF_NETWORK_KEY = "network_key"
|
||||
CONF_USB_PATH = "usb_path"
|
||||
TITLE = "OpenZWave"
|
||||
|
||||
ON_SUPERVISOR_SCHEMA = vol.Schema({vol.Optional(CONF_USE_ADDON, default=False): bool})
|
||||
|
||||
|
||||
class DomainConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for ozw."""
|
||||
|
||||
VERSION = 1
|
||||
|
||||
def __init__(self):
|
||||
"""Set up flow instance."""
|
||||
self.addon_config = None
|
||||
self.network_key = None
|
||||
self.usb_path = None
|
||||
self.use_addon = False
|
||||
# If we install the add-on we should uninstall it on entry remove.
|
||||
self.integration_created_addon = False
|
||||
self.install_task = None
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle the initial step."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
|
||||
# Set a unique_id to make sure discovery flow is aborted on progress.
|
||||
await self.async_set_unique_id(DOMAIN, raise_on_progress=False)
|
||||
|
||||
if not hassio.is_hassio(self.hass):
|
||||
return self._async_use_mqtt_integration()
|
||||
|
||||
return await self.async_step_on_supervisor()
|
||||
|
||||
async def async_step_hassio(self, discovery_info: HassioServiceInfo) -> FlowResult:
|
||||
"""Receive configuration from add-on discovery info.
|
||||
|
||||
This flow is triggered by the OpenZWave add-on.
|
||||
"""
|
||||
await self.async_set_unique_id(DOMAIN)
|
||||
self._abort_if_unique_id_configured()
|
||||
|
||||
return await self.async_step_hassio_confirm()
|
||||
|
||||
async def async_step_hassio_confirm(self, user_input=None):
|
||||
"""Confirm the add-on discovery."""
|
||||
if user_input is not None:
|
||||
return await self.async_step_on_supervisor(
|
||||
user_input={CONF_USE_ADDON: True}
|
||||
)
|
||||
|
||||
return self.async_show_form(step_id="hassio_confirm")
|
||||
|
||||
def _async_create_entry_from_vars(self):
|
||||
"""Return a config entry for the flow."""
|
||||
return self.async_create_entry(
|
||||
title=TITLE,
|
||||
data={
|
||||
CONF_USB_PATH: self.usb_path,
|
||||
CONF_NETWORK_KEY: self.network_key,
|
||||
CONF_USE_ADDON: self.use_addon,
|
||||
CONF_INTEGRATION_CREATED_ADDON: self.integration_created_addon,
|
||||
},
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_use_mqtt_integration(self):
|
||||
"""Handle logic when using the MQTT integration.
|
||||
|
||||
This is the entry point for the logic that is needed
|
||||
when this integration will depend on the MQTT integration.
|
||||
"""
|
||||
mqtt_entries = self.hass.config_entries.async_entries("mqtt")
|
||||
if (
|
||||
not mqtt_entries
|
||||
or mqtt_entries[0].state is not config_entries.ConfigEntryState.LOADED
|
||||
):
|
||||
return self.async_abort(reason="mqtt_required")
|
||||
return self._async_create_entry_from_vars()
|
||||
|
||||
async def async_step_on_supervisor(self, user_input=None):
|
||||
"""Handle logic when on Supervisor host."""
|
||||
if user_input is None:
|
||||
return self.async_show_form(
|
||||
step_id="on_supervisor", data_schema=ON_SUPERVISOR_SCHEMA
|
||||
)
|
||||
if not user_input[CONF_USE_ADDON]:
|
||||
return self._async_create_entry_from_vars()
|
||||
|
||||
self.use_addon = True
|
||||
|
||||
if await self._async_is_addon_running():
|
||||
addon_config = await self._async_get_addon_config()
|
||||
self.usb_path = addon_config[CONF_ADDON_DEVICE]
|
||||
self.network_key = addon_config.get(CONF_ADDON_NETWORK_KEY, "")
|
||||
return self._async_create_entry_from_vars()
|
||||
|
||||
if await self._async_is_addon_installed():
|
||||
return await self.async_step_start_addon()
|
||||
|
||||
return await self.async_step_install_addon()
|
||||
|
||||
async def async_step_install_addon(self, user_input=None):
|
||||
"""Install OpenZWave add-on."""
|
||||
if not self.install_task:
|
||||
self.install_task = self.hass.async_create_task(self._async_install_addon())
|
||||
return self.async_show_progress(
|
||||
step_id="install_addon", progress_action="install_addon"
|
||||
)
|
||||
|
||||
try:
|
||||
await self.install_task
|
||||
except hassio.HassioAPIError as err:
|
||||
_LOGGER.error("Failed to install OpenZWave add-on: %s", err)
|
||||
return self.async_show_progress_done(next_step_id="install_failed")
|
||||
|
||||
self.integration_created_addon = True
|
||||
|
||||
return self.async_show_progress_done(next_step_id="start_addon")
|
||||
|
||||
async def async_step_install_failed(self, user_input=None):
|
||||
"""Add-on installation failed."""
|
||||
return self.async_abort(reason="addon_install_failed")
|
||||
|
||||
async def async_step_start_addon(self, user_input=None):
|
||||
"""Ask for config and start OpenZWave add-on."""
|
||||
if self.addon_config is None:
|
||||
self.addon_config = await self._async_get_addon_config()
|
||||
|
||||
errors = {}
|
||||
|
||||
if user_input is not None:
|
||||
self.network_key = user_input[CONF_NETWORK_KEY]
|
||||
self.usb_path = user_input[CONF_USB_PATH]
|
||||
|
||||
new_addon_config = {
|
||||
CONF_ADDON_DEVICE: self.usb_path,
|
||||
CONF_ADDON_NETWORK_KEY: self.network_key,
|
||||
}
|
||||
|
||||
if new_addon_config != self.addon_config:
|
||||
await self._async_set_addon_config(new_addon_config)
|
||||
|
||||
try:
|
||||
await hassio.async_start_addon(self.hass, "core_zwave")
|
||||
except hassio.HassioAPIError as err:
|
||||
_LOGGER.error("Failed to start OpenZWave add-on: %s", err)
|
||||
errors["base"] = "addon_start_failed"
|
||||
else:
|
||||
return self._async_create_entry_from_vars()
|
||||
|
||||
usb_path = self.addon_config.get(CONF_ADDON_DEVICE, self.usb_path or "")
|
||||
network_key = self.addon_config.get(
|
||||
CONF_ADDON_NETWORK_KEY, self.network_key or ""
|
||||
)
|
||||
|
||||
data_schema = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_USB_PATH, default=usb_path): str,
|
||||
vol.Optional(CONF_NETWORK_KEY, default=network_key): str,
|
||||
}
|
||||
)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="start_addon", data_schema=data_schema, errors=errors
|
||||
)
|
||||
|
||||
async def _async_get_addon_info(self):
|
||||
"""Return and cache OpenZWave add-on info."""
|
||||
try:
|
||||
addon_info = await hassio.async_get_addon_info(self.hass, "core_zwave")
|
||||
except hassio.HassioAPIError as err:
|
||||
_LOGGER.error("Failed to get OpenZWave add-on info: %s", err)
|
||||
raise AbortFlow("addon_info_failed") from err
|
||||
|
||||
return addon_info
|
||||
|
||||
async def _async_is_addon_running(self):
|
||||
"""Return True if OpenZWave add-on is running."""
|
||||
addon_info = await self._async_get_addon_info()
|
||||
return addon_info["state"] == "started"
|
||||
|
||||
async def _async_is_addon_installed(self):
|
||||
"""Return True if OpenZWave add-on is installed."""
|
||||
addon_info = await self._async_get_addon_info()
|
||||
return addon_info["version"] is not None
|
||||
|
||||
async def _async_get_addon_config(self):
|
||||
"""Get OpenZWave add-on config."""
|
||||
addon_info = await self._async_get_addon_info()
|
||||
return addon_info["options"]
|
||||
|
||||
async def _async_set_addon_config(self, config):
|
||||
"""Set OpenZWave add-on config."""
|
||||
options = {"options": config}
|
||||
try:
|
||||
await hassio.async_set_addon_options(self.hass, "core_zwave", options)
|
||||
except hassio.HassioAPIError as err:
|
||||
_LOGGER.error("Failed to set OpenZWave add-on config: %s", err)
|
||||
raise AbortFlow("addon_set_config_failed") from err
|
||||
|
||||
async def _async_install_addon(self):
|
||||
"""Install the OpenZWave add-on."""
|
||||
try:
|
||||
await hassio.async_install_addon(self.hass, "core_zwave")
|
||||
finally:
|
||||
# Continue the flow after show progress when the task is done.
|
||||
self.hass.async_create_task(
|
||||
self.hass.config_entries.flow.async_configure(flow_id=self.flow_id)
|
||||
)
|
@ -1,71 +0,0 @@
|
||||
"""Constants for the ozw integration."""
|
||||
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
|
||||
from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN
|
||||
from homeassistant.components.cover import DOMAIN as COVER_DOMAIN
|
||||
from homeassistant.components.fan import DOMAIN as FAN_DOMAIN
|
||||
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
|
||||
from homeassistant.components.lock import DOMAIN as LOCK_DOMAIN
|
||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||
|
||||
DOMAIN = "ozw"
|
||||
DATA_UNSUBSCRIBE = "unsubscribe"
|
||||
|
||||
CONF_INTEGRATION_CREATED_ADDON = "integration_created_addon"
|
||||
CONF_USE_ADDON = "use_addon"
|
||||
|
||||
PLATFORMS = [
|
||||
BINARY_SENSOR_DOMAIN,
|
||||
COVER_DOMAIN,
|
||||
CLIMATE_DOMAIN,
|
||||
FAN_DOMAIN,
|
||||
LIGHT_DOMAIN,
|
||||
LOCK_DOMAIN,
|
||||
SENSOR_DOMAIN,
|
||||
SWITCH_DOMAIN,
|
||||
]
|
||||
MANAGER = "manager"
|
||||
NODES_VALUES = "nodes_values"
|
||||
|
||||
# MQTT Topics
|
||||
TOPIC_OPENZWAVE = "OpenZWave"
|
||||
|
||||
# Common Attributes
|
||||
ATTR_CONFIG_PARAMETER = "parameter"
|
||||
ATTR_CONFIG_VALUE = "value"
|
||||
ATTR_INSTANCE_ID = "instance_id"
|
||||
ATTR_SECURE = "secure"
|
||||
ATTR_NODE_ID = "node_id"
|
||||
ATTR_SCENE_ID = "scene_id"
|
||||
ATTR_SCENE_LABEL = "scene_label"
|
||||
ATTR_SCENE_VALUE_ID = "scene_value_id"
|
||||
ATTR_SCENE_VALUE_LABEL = "scene_value_label"
|
||||
|
||||
# Config entry data and options
|
||||
MIGRATED = "migrated"
|
||||
|
||||
# Service specific
|
||||
SERVICE_ADD_NODE = "add_node"
|
||||
SERVICE_REMOVE_NODE = "remove_node"
|
||||
SERVICE_CANCEL_COMMAND = "cancel_command"
|
||||
SERVICE_SET_CONFIG_PARAMETER = "set_config_parameter"
|
||||
|
||||
# Home Assistant Events
|
||||
EVENT_SCENE_ACTIVATED = f"{DOMAIN}.scene_activated"
|
||||
|
||||
# Signals
|
||||
SIGNAL_DELETE_ENTITY = f"{DOMAIN}_delete_entity"
|
||||
|
||||
# Discovery Information
|
||||
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_SPECIFIC_DEVICE_CLASS = "specific_device_class"
|
||||
DISC_TYPE = "type"
|
||||
DISC_VALUES = "values"
|
@ -1,127 +0,0 @@
|
||||
"""Support for Z-Wave cover devices."""
|
||||
from openzwavemqtt.const import CommandClass
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
ATTR_POSITION,
|
||||
DOMAIN as COVER_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 .const import DATA_UNSUBSCRIBE, DOMAIN
|
||||
from .entity import ZWaveDeviceEntity
|
||||
|
||||
SUPPORT_GARAGE = SUPPORT_OPEN | SUPPORT_CLOSE
|
||||
VALUE_SELECTED_ID = "Selected_id"
|
||||
PRESS_BUTTON = True
|
||||
RELEASE_BUTTON = False
|
||||
|
||||
|
||||
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(values):
|
||||
"""Add Z-Wave Cover."""
|
||||
if values.primary.command_class == CommandClass.BARRIER_OPERATOR:
|
||||
cover = ZwaveGarageDoorBarrier(values)
|
||||
else:
|
||||
cover = ZWaveCoverEntity(values)
|
||||
|
||||
async_add_entities([cover])
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id][DATA_UNSUBSCRIBE].append(
|
||||
async_dispatcher_connect(hass, f"{DOMAIN}_new_{COVER_DOMAIN}", async_add_cover)
|
||||
)
|
||||
|
||||
|
||||
def percent_to_zwave_position(value):
|
||||
"""Convert position in 0-100 scale to 0-99 scale.
|
||||
|
||||
`value` -- (int) Position byte value from 0-100.
|
||||
"""
|
||||
if value > 0:
|
||||
return max(1, round((value / 100) * 99))
|
||||
return 0
|
||||
|
||||
|
||||
class ZWaveCoverEntity(ZWaveDeviceEntity, CoverEntity):
|
||||
"""Representation of a Z-Wave Cover device."""
|
||||
|
||||
@property
|
||||
def is_closed(self):
|
||||
"""Return true if cover is closed."""
|
||||
return self.values.primary.value == 0
|
||||
|
||||
@property
|
||||
def current_cover_position(self):
|
||||
"""Return the current position of cover where 0 means closed and 100 is fully open."""
|
||||
return round((self.values.primary.value / 99) * 100)
|
||||
|
||||
async def async_set_cover_position(self, **kwargs):
|
||||
"""Move the cover to a specific position."""
|
||||
self.values.primary.send_value(percent_to_zwave_position(kwargs[ATTR_POSITION]))
|
||||
|
||||
async def async_open_cover(self, **kwargs):
|
||||
"""Open the cover."""
|
||||
self.values.open.send_value(PRESS_BUTTON)
|
||||
|
||||
async def async_close_cover(self, **kwargs):
|
||||
"""Close cover."""
|
||||
self.values.close.send_value(PRESS_BUTTON)
|
||||
|
||||
async def async_stop_cover(self, **kwargs):
|
||||
"""Stop cover."""
|
||||
# Need to issue both buttons release since qt-openzwave implements idempotency
|
||||
# keeping internal state of model to trigger actual updates. We could also keep
|
||||
# another state in Home Assistant to know which button to release,
|
||||
# but this implementation is simpler.
|
||||
self.values.open.send_value(RELEASE_BUTTON)
|
||||
self.values.close.send_value(RELEASE_BUTTON)
|
||||
|
||||
|
||||
class ZwaveGarageDoorBarrier(ZWaveDeviceEntity, CoverEntity):
|
||||
"""Representation of a barrier operator Zwave garage door device."""
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Flag supported features."""
|
||||
return SUPPORT_GARAGE
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the class of this device, from CoverDeviceClass."""
|
||||
return CoverDeviceClass.GARAGE
|
||||
|
||||
@property
|
||||
def is_opening(self):
|
||||
"""Return true if cover is in an opening state."""
|
||||
return self.values.primary.value[VALUE_SELECTED_ID] == 3
|
||||
|
||||
@property
|
||||
def is_closing(self):
|
||||
"""Return true if cover is in a closing state."""
|
||||
return self.values.primary.value[VALUE_SELECTED_ID] == 1
|
||||
|
||||
@property
|
||||
def is_closed(self):
|
||||
"""Return the current position of Zwave garage door."""
|
||||
return self.values.primary.value[VALUE_SELECTED_ID] == 0
|
||||
|
||||
async def async_close_cover(self, **kwargs):
|
||||
"""Close the garage door."""
|
||||
self.values.primary.send_value(0)
|
||||
|
||||
async def async_open_cover(self, **kwargs):
|
||||
"""Open the garage door."""
|
||||
self.values.primary.send_value(4)
|
@ -1,356 +0,0 @@
|
||||
"""Map Z-Wave nodes and values to Home Assistant entities."""
|
||||
import openzwavemqtt.const as const_ozw
|
||||
from openzwavemqtt.const import CommandClass, ValueGenre, ValueIndex, ValueType
|
||||
|
||||
from . import const
|
||||
|
||||
DISCOVERY_SCHEMAS = (
|
||||
{ # Binary sensors
|
||||
const.DISC_COMPONENT: "binary_sensor",
|
||||
const.DISC_VALUES: {
|
||||
const.DISC_PRIMARY: {
|
||||
const.DISC_COMMAND_CLASS: CommandClass.SENSOR_BINARY,
|
||||
const.DISC_TYPE: ValueType.BOOL,
|
||||
const.DISC_GENRE: ValueGenre.USER,
|
||||
},
|
||||
"off_delay": {
|
||||
const.DISC_COMMAND_CLASS: CommandClass.CONFIGURATION,
|
||||
const.DISC_INDEX: 9,
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
},
|
||||
},
|
||||
{ # Notification CommandClass translates to binary_sensor
|
||||
const.DISC_COMPONENT: "binary_sensor",
|
||||
const.DISC_VALUES: {
|
||||
const.DISC_PRIMARY: {
|
||||
const.DISC_COMMAND_CLASS: CommandClass.NOTIFICATION,
|
||||
const.DISC_GENRE: ValueGenre.USER,
|
||||
const.DISC_TYPE: (ValueType.BOOL, ValueType.LIST),
|
||||
}
|
||||
},
|
||||
},
|
||||
{ # Z-Wave Thermostat device translates to Climate entity
|
||||
const.DISC_COMPONENT: "climate",
|
||||
const.DISC_GENERIC_DEVICE_CLASS: (
|
||||
const_ozw.GENERIC_TYPE_THERMOSTAT,
|
||||
const_ozw.GENERIC_TYPE_SENSOR_MULTILEVEL,
|
||||
),
|
||||
const.DISC_SPECIFIC_DEVICE_CLASS: (
|
||||
const_ozw.SPECIFIC_TYPE_THERMOSTAT_GENERAL,
|
||||
const_ozw.SPECIFIC_TYPE_THERMOSTAT_GENERAL_V2,
|
||||
const_ozw.SPECIFIC_TYPE_SETBACK_THERMOSTAT,
|
||||
const_ozw.SPECIFIC_TYPE_THERMOSTAT_HEATING,
|
||||
const_ozw.SPECIFIC_TYPE_SETPOINT_THERMOSTAT,
|
||||
const_ozw.SPECIFIC_TYPE_NOT_USED,
|
||||
),
|
||||
const.DISC_VALUES: {
|
||||
const.DISC_PRIMARY: {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_MODE,)
|
||||
},
|
||||
"mode": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_MODE,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"temperature": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.SENSOR_MULTILEVEL,),
|
||||
const.DISC_INDEX: (1,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"fan_mode": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_FAN_MODE,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"operating_state": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_OPERATING_STATE,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"fan_action": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_FAN_STATE,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"valve_position": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.SWITCH_MULTILEVEL,),
|
||||
const.DISC_INDEX: (0,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_heating": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (1,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_cooling": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (2,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_furnace": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (7,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_dry_air": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (8,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_moist_air": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (9,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_auto_changeover": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (10,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_eco_heating": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (11,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_eco_cooling": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (12,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_away_heating": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (13,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_away_cooling": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (14,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_full_power": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (15,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
},
|
||||
},
|
||||
{ # Z-Wave Thermostat device without mode support
|
||||
const.DISC_COMPONENT: "climate",
|
||||
const.DISC_GENERIC_DEVICE_CLASS: (const_ozw.GENERIC_TYPE_THERMOSTAT,),
|
||||
const.DISC_SPECIFIC_DEVICE_CLASS: (
|
||||
const_ozw.SPECIFIC_TYPE_SETPOINT_THERMOSTAT,
|
||||
const_ozw.SPECIFIC_TYPE_NOT_USED,
|
||||
),
|
||||
const.DISC_VALUES: {
|
||||
const.DISC_PRIMARY: {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,)
|
||||
},
|
||||
"temperature": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.SENSOR_MULTILEVEL,),
|
||||
const.DISC_INDEX: (1,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"operating_state": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_OPERATING_STATE,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"valve_position": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.SWITCH_MULTILEVEL,),
|
||||
const.DISC_INDEX: (0,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"setpoint_heating": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.THERMOSTAT_SETPOINT,),
|
||||
const.DISC_INDEX: (1,),
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
},
|
||||
},
|
||||
{ # Rollershutter
|
||||
const.DISC_COMPONENT: "cover",
|
||||
const.DISC_GENERIC_DEVICE_CLASS: (const_ozw.GENERIC_TYPE_SWITCH_MULTILEVEL,),
|
||||
const.DISC_SPECIFIC_DEVICE_CLASS: (
|
||||
const_ozw.SPECIFIC_TYPE_CLASS_A_MOTOR_CONTROL,
|
||||
const_ozw.SPECIFIC_TYPE_CLASS_B_MOTOR_CONTROL,
|
||||
const_ozw.SPECIFIC_TYPE_CLASS_C_MOTOR_CONTROL,
|
||||
const_ozw.SPECIFIC_TYPE_MOTOR_MULTIPOSITION,
|
||||
const_ozw.SPECIFIC_TYPE_SECURE_BARRIER_ADDON,
|
||||
const_ozw.SPECIFIC_TYPE_SECURE_DOOR,
|
||||
),
|
||||
const.DISC_VALUES: {
|
||||
const.DISC_PRIMARY: {
|
||||
const.DISC_COMMAND_CLASS: CommandClass.SWITCH_MULTILEVEL,
|
||||
const.DISC_INDEX: ValueIndex.SWITCH_MULTILEVEL_LEVEL,
|
||||
const.DISC_GENRE: ValueGenre.USER,
|
||||
},
|
||||
"open": {
|
||||
const.DISC_COMMAND_CLASS: CommandClass.SWITCH_MULTILEVEL,
|
||||
const.DISC_INDEX: ValueIndex.SWITCH_MULTILEVEL_BRIGHT,
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"close": {
|
||||
const.DISC_COMMAND_CLASS: CommandClass.SWITCH_MULTILEVEL,
|
||||
const.DISC_INDEX: ValueIndex.SWITCH_MULTILEVEL_DIM,
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
},
|
||||
},
|
||||
{ # Garage Door Barrier
|
||||
const.DISC_COMPONENT: "cover",
|
||||
const.DISC_GENERIC_DEVICE_CLASS: (const_ozw.GENERIC_TYPE_ENTRY_CONTROL,),
|
||||
const.DISC_SPECIFIC_DEVICE_CLASS: (
|
||||
const_ozw.SPECIFIC_TYPE_SECURE_BARRIER_ADDON,
|
||||
),
|
||||
const.DISC_VALUES: {
|
||||
const.DISC_PRIMARY: {
|
||||
const.DISC_COMMAND_CLASS: CommandClass.BARRIER_OPERATOR,
|
||||
const.DISC_INDEX: ValueIndex.BARRIER_OPERATOR_LABEL,
|
||||
},
|
||||
},
|
||||
},
|
||||
{ # Fan
|
||||
const.DISC_COMPONENT: "fan",
|
||||
const.DISC_GENERIC_DEVICE_CLASS: const_ozw.GENERIC_TYPE_SWITCH_MULTILEVEL,
|
||||
const.DISC_SPECIFIC_DEVICE_CLASS: const_ozw.SPECIFIC_TYPE_FAN_SWITCH,
|
||||
const.DISC_VALUES: {
|
||||
const.DISC_PRIMARY: {
|
||||
const.DISC_COMMAND_CLASS: CommandClass.SWITCH_MULTILEVEL,
|
||||
const.DISC_INDEX: ValueIndex.SWITCH_MULTILEVEL_LEVEL,
|
||||
const.DISC_TYPE: ValueType.BYTE,
|
||||
},
|
||||
},
|
||||
},
|
||||
{ # Light
|
||||
const.DISC_COMPONENT: "light",
|
||||
const.DISC_GENERIC_DEVICE_CLASS: (
|
||||
const_ozw.GENERIC_TYPE_SWITCH_MULTILEVEL,
|
||||
const_ozw.GENERIC_TYPE_SWITCH_REMOTE,
|
||||
),
|
||||
const.DISC_SPECIFIC_DEVICE_CLASS: (
|
||||
const_ozw.SPECIFIC_TYPE_POWER_SWITCH_MULTILEVEL,
|
||||
const_ozw.SPECIFIC_TYPE_SCENE_SWITCH_MULTILEVEL,
|
||||
const_ozw.SPECIFIC_TYPE_COLOR_TUNABLE_BINARY,
|
||||
const_ozw.SPECIFIC_TYPE_COLOR_TUNABLE_MULTILEVEL,
|
||||
const_ozw.SPECIFIC_TYPE_NOT_USED,
|
||||
),
|
||||
const.DISC_VALUES: {
|
||||
const.DISC_PRIMARY: {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.SWITCH_MULTILEVEL,),
|
||||
const.DISC_INDEX: ValueIndex.SWITCH_MULTILEVEL_LEVEL,
|
||||
const.DISC_TYPE: ValueType.BYTE,
|
||||
},
|
||||
"dimming_duration": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.SWITCH_MULTILEVEL,),
|
||||
const.DISC_INDEX: ValueIndex.SWITCH_MULTILEVEL_DURATION,
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"color": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.SWITCH_COLOR,),
|
||||
const.DISC_INDEX: ValueIndex.SWITCH_COLOR_COLOR,
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"color_channels": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.SWITCH_COLOR,),
|
||||
const.DISC_INDEX: ValueIndex.SWITCH_COLOR_CHANNELS,
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"min_kelvin": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.CONFIGURATION,),
|
||||
const.DISC_INDEX: 81, # PR for upstream to add SWITCH_COLOR_CT_WARM
|
||||
const.DISC_TYPE: ValueType.INT,
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
"max_kelvin": {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.CONFIGURATION,),
|
||||
const.DISC_INDEX: 82, # PR for upstream to add SWITCH_COLOR_CT_COLD
|
||||
const.DISC_TYPE: ValueType.INT,
|
||||
const.DISC_OPTIONAL: True,
|
||||
},
|
||||
},
|
||||
},
|
||||
{ # All other text/numeric sensors
|
||||
const.DISC_COMPONENT: "sensor",
|
||||
const.DISC_VALUES: {
|
||||
const.DISC_PRIMARY: {
|
||||
const.DISC_COMMAND_CLASS: (
|
||||
CommandClass.SENSOR_MULTILEVEL,
|
||||
CommandClass.METER,
|
||||
CommandClass.ALARM,
|
||||
CommandClass.SENSOR_ALARM,
|
||||
CommandClass.INDICATOR,
|
||||
CommandClass.BATTERY,
|
||||
CommandClass.NOTIFICATION,
|
||||
CommandClass.BASIC,
|
||||
),
|
||||
const.DISC_TYPE: (
|
||||
ValueType.DECIMAL,
|
||||
ValueType.INT,
|
||||
ValueType.STRING,
|
||||
ValueType.BYTE,
|
||||
ValueType.LIST,
|
||||
),
|
||||
}
|
||||
},
|
||||
},
|
||||
{ # Switch platform
|
||||
const.DISC_COMPONENT: "switch",
|
||||
const.DISC_VALUES: {
|
||||
const.DISC_PRIMARY: {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.SWITCH_BINARY,),
|
||||
const.DISC_TYPE: ValueType.BOOL,
|
||||
const.DISC_GENRE: ValueGenre.USER,
|
||||
}
|
||||
},
|
||||
},
|
||||
{ # Lock platform
|
||||
const.DISC_COMPONENT: "lock",
|
||||
const.DISC_VALUES: {
|
||||
const.DISC_PRIMARY: {
|
||||
const.DISC_COMMAND_CLASS: (CommandClass.DOOR_LOCK,),
|
||||
const.DISC_TYPE: ValueType.BOOL,
|
||||
const.DISC_GENRE: ValueGenre.USER,
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
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]:
|
||||
return False
|
||||
if const.DISC_GENERIC_DEVICE_CLASS in schema and not eq_or_in(
|
||||
node.node_generic, schema[const.DISC_GENERIC_DEVICE_CLASS]
|
||||
):
|
||||
return False
|
||||
if const.DISC_SPECIFIC_DEVICE_CLASS in schema and not eq_or_in(
|
||||
node.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 not eq_or_in(
|
||||
value.parent.command_class_id, schema[const.DISC_COMMAND_CLASS]
|
||||
):
|
||||
return False
|
||||
if const.DISC_TYPE in schema and not eq_or_in(value.type, schema[const.DISC_TYPE]):
|
||||
return False
|
||||
if const.DISC_GENRE in schema and not eq_or_in(
|
||||
value.genre, schema[const.DISC_GENRE]
|
||||
):
|
||||
return False
|
||||
if const.DISC_INDEX in schema and not eq_or_in(
|
||||
value.index, schema[const.DISC_INDEX]
|
||||
):
|
||||
return False
|
||||
if const.DISC_INSTANCE in schema and not eq_or_in(
|
||||
value.instance, schema[const.DISC_INSTANCE]
|
||||
):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def eq_or_in(val, options):
|
||||
"""Return True if options contains value or if value is equal to options."""
|
||||
return val in options if isinstance(options, tuple) else val == options
|
@ -1,304 +0,0 @@
|
||||
"""Generic Z-Wave Entity Classes."""
|
||||
|
||||
import copy
|
||||
import logging
|
||||
|
||||
from openzwavemqtt.const import (
|
||||
EVENT_INSTANCE_STATUS_CHANGED,
|
||||
EVENT_VALUE_CHANGED,
|
||||
OZW_READY_STATES,
|
||||
CommandClass,
|
||||
ValueIndex,
|
||||
)
|
||||
from openzwavemqtt.models.node import OZWNode
|
||||
from openzwavemqtt.models.value import OZWValue
|
||||
|
||||
from homeassistant.const import ATTR_NAME, ATTR_SW_VERSION, ATTR_VIA_DEVICE
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import (
|
||||
async_dispatcher_connect,
|
||||
async_dispatcher_send,
|
||||
)
|
||||
from homeassistant.helpers.entity import DeviceInfo, Entity
|
||||
|
||||
from . import const
|
||||
from .const import DOMAIN, PLATFORMS
|
||||
from .discovery import check_node_schema, check_value_schema
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
OZW_READY_STATES_VALUES = {st.value for st in OZW_READY_STATES}
|
||||
|
||||
|
||||
class ZWaveDeviceEntityValues:
|
||||
"""Manages entity access to the underlying Z-Wave value objects."""
|
||||
|
||||
def __init__(self, hass, options, schema, primary_value):
|
||||
"""Initialize the values object with the passed entity schema."""
|
||||
self._hass = hass
|
||||
self._entity_created = False
|
||||
self._schema = copy.deepcopy(schema)
|
||||
self._values = {}
|
||||
self.options = options
|
||||
|
||||
# Go through values listed in the discovery schema, initialize them,
|
||||
# and add a check to the schema to make sure the Instance matches.
|
||||
for name, disc_settings in self._schema[const.DISC_VALUES].items():
|
||||
self._values[name] = None
|
||||
disc_settings[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]
|
||||
|
||||
def async_setup(self):
|
||||
"""Set up values instance."""
|
||||
# Check values that have already been discovered for node
|
||||
# and see if they match the schema and need added to the entity.
|
||||
for value in self._node.values():
|
||||
self.async_check_value(value)
|
||||
|
||||
# Check if all the _required_ values in the schema are present and
|
||||
# create the entity.
|
||||
self._async_check_entity_ready()
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Get the specified value for this entity."""
|
||||
return self._values.get(name, None)
|
||||
|
||||
def __iter__(self):
|
||||
"""Allow iteration over all values."""
|
||||
return iter(self._values.values())
|
||||
|
||||
def __contains__(self, name):
|
||||
"""Check if the specified name/key exists in the values."""
|
||||
return name in self._values
|
||||
|
||||
@callback
|
||||
def async_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.
|
||||
"""
|
||||
# Make sure the node matches the schema for this entity.
|
||||
if not check_node_schema(value.node, self._schema):
|
||||
return
|
||||
|
||||
# Go through the possible values for this entity defined by the schema.
|
||||
for name, name_value in self._values.items():
|
||||
# Skip if it's already been added.
|
||||
if name_value is not None:
|
||||
continue
|
||||
# Skip if the value doesn't match the schema.
|
||||
if not check_value_schema(value, self._schema[const.DISC_VALUES][name]):
|
||||
continue
|
||||
|
||||
# Add value to mapping.
|
||||
self._values[name] = value
|
||||
|
||||
# If the entity has already been created, notify it of the new value.
|
||||
if self._entity_created:
|
||||
async_dispatcher_send(
|
||||
self._hass, f"{DOMAIN}_{self.values_id}_value_added"
|
||||
)
|
||||
|
||||
# Check if entity has all required values and create the entity if needed.
|
||||
self._async_check_entity_ready()
|
||||
|
||||
@callback
|
||||
def _async_check_entity_ready(self):
|
||||
"""Check if all required values are discovered and create entity."""
|
||||
# Abort if the entity has already been created
|
||||
if self._entity_created:
|
||||
return
|
||||
|
||||
# Go through values defined in the schema and abort if a required value is missing.
|
||||
for name, disc_settings in self._schema[const.DISC_VALUES].items():
|
||||
if self._values[name] is None and not disc_settings.get(
|
||||
const.DISC_OPTIONAL
|
||||
):
|
||||
return
|
||||
|
||||
# We have all the required values, so create the entity.
|
||||
component = self._schema[const.DISC_COMPONENT]
|
||||
|
||||
_LOGGER.debug(
|
||||
"Adding Node_id=%s Generic_command_class=%s, "
|
||||
"Specific_command_class=%s, "
|
||||
"Command_class=%s, Index=%s, Value type=%s, "
|
||||
"Genre=%s as %s",
|
||||
self._node.node_id,
|
||||
self._node.node_generic,
|
||||
self._node.node_specific,
|
||||
self.primary.command_class,
|
||||
self.primary.index,
|
||||
self.primary.type,
|
||||
self.primary.genre,
|
||||
component,
|
||||
)
|
||||
self._entity_created = True
|
||||
|
||||
if component in PLATFORMS:
|
||||
async_dispatcher_send(self._hass, f"{DOMAIN}_new_{component}", self)
|
||||
|
||||
@property
|
||||
def values_id(self):
|
||||
"""Identification for this values collection."""
|
||||
return create_value_id(self.primary)
|
||||
|
||||
|
||||
class ZWaveDeviceEntity(Entity):
|
||||
"""Generic Entity Class for a Z-Wave Device."""
|
||||
|
||||
def __init__(self, values):
|
||||
"""Initialize a generic Z-Wave device entity."""
|
||||
self.values = values
|
||||
self.options = values.options
|
||||
|
||||
@callback
|
||||
def on_value_update(self):
|
||||
"""Call when a value is added/updated in the entity EntityValues Collection.
|
||||
|
||||
To be overridden by platforms needing this event.
|
||||
"""
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Call when entity is added."""
|
||||
# Add dispatcher and OZW listeners callbacks.
|
||||
# Add to on_remove so they will be cleaned up on entity removal.
|
||||
self.async_on_remove(
|
||||
self.options.listen(EVENT_VALUE_CHANGED, self._value_changed)
|
||||
)
|
||||
self.async_on_remove(
|
||||
self.options.listen(EVENT_INSTANCE_STATUS_CHANGED, self._instance_updated)
|
||||
)
|
||||
self.async_on_remove(
|
||||
async_dispatcher_connect(
|
||||
self.hass, const.SIGNAL_DELETE_ENTITY, self._delete_callback
|
||||
)
|
||||
)
|
||||
self.async_on_remove(
|
||||
async_dispatcher_connect(
|
||||
self.hass,
|
||||
f"{DOMAIN}_{self.values.values_id}_value_added",
|
||||
self._value_added,
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
"""Return device information for the device registry."""
|
||||
node = self.values.primary.node
|
||||
node_instance = self.values.primary.instance
|
||||
dev_id = create_device_id(node, self.values.primary.instance)
|
||||
node_firmware = node.get_value(
|
||||
CommandClass.VERSION, ValueIndex.VERSION_APPLICATION
|
||||
)
|
||||
device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, dev_id)},
|
||||
name=create_device_name(node),
|
||||
manufacturer=node.node_manufacturer_name,
|
||||
model=node.node_product_name,
|
||||
)
|
||||
if node_firmware is not None:
|
||||
device_info[ATTR_SW_VERSION] = node_firmware.value
|
||||
|
||||
# device with multiple instances is split up into virtual devices for each instance
|
||||
if node_instance > 1:
|
||||
parent_dev_id = create_device_id(node)
|
||||
device_info[ATTR_NAME] += f" - Instance {node_instance}"
|
||||
device_info[ATTR_VIA_DEVICE] = (DOMAIN, parent_dev_id)
|
||||
return device_info
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return the device specific state attributes."""
|
||||
return {const.ATTR_NODE_ID: self.values.primary.node.node_id}
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the entity."""
|
||||
node = self.values.primary.node
|
||||
return f"{create_device_name(node)}: {self.values.primary.label}"
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the unique_id of the entity."""
|
||||
return self.values.values_id
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return entity availability."""
|
||||
# Use OZW Daemon status for availability.
|
||||
instance_status = self.values.primary.ozw_instance.get_status()
|
||||
return instance_status and instance_status.status in OZW_READY_STATES_VALUES
|
||||
|
||||
@callback
|
||||
def _value_changed(self, value):
|
||||
"""Call when a value from ZWaveDeviceEntityValues is changed.
|
||||
|
||||
Should not be overridden by subclasses.
|
||||
"""
|
||||
if value.value_id_key in (v.value_id_key for v in self.values if v):
|
||||
self.on_value_update()
|
||||
self.async_write_ha_state()
|
||||
|
||||
@callback
|
||||
def _value_added(self):
|
||||
"""Call when a value from ZWaveDeviceEntityValues is added.
|
||||
|
||||
Should not be overridden by subclasses.
|
||||
"""
|
||||
self.on_value_update()
|
||||
|
||||
@callback
|
||||
def _instance_updated(self, new_status):
|
||||
"""Call when the instance status changes.
|
||||
|
||||
Should not be overridden by subclasses.
|
||||
"""
|
||||
self.on_value_update()
|
||||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""No polling needed."""
|
||||
return False
|
||||
|
||||
async def _delete_callback(self, values_id):
|
||||
"""Remove this entity."""
|
||||
if not self.values:
|
||||
return # race condition: delete already requested
|
||||
if values_id == self.values.values_id:
|
||||
await self.async_remove(force_remove=True)
|
||||
|
||||
|
||||
def create_device_name(node: OZWNode):
|
||||
"""Generate sensible (short) default device name from a OZWNode."""
|
||||
# Prefer custom name set by OZWAdmin if present
|
||||
if node.node_name:
|
||||
return node.node_name
|
||||
# Prefer short devicename from metadata if present
|
||||
if node.meta_data and node.meta_data.get("Name"):
|
||||
return node.meta_data["Name"]
|
||||
# Fallback to productname or devicetype strings
|
||||
if node.node_product_name:
|
||||
return node.node_product_name
|
||||
if node.node_device_type_string:
|
||||
return node.node_device_type_string
|
||||
if node.node_specific_string:
|
||||
return node.node_specific_string
|
||||
# Last resort: use Node id (should never happen, but just in case)
|
||||
return f"Node {node.id}"
|
||||
|
||||
|
||||
def create_device_id(node: OZWNode, node_instance: int = 1):
|
||||
"""Generate unique device_id from a OZWNode."""
|
||||
ozw_instance = node.parent.id
|
||||
dev_id = f"{ozw_instance}.{node.node_id}.{node_instance}"
|
||||
return dev_id
|
||||
|
||||
|
||||
def create_value_id(value: OZWValue):
|
||||
"""Generate unique value_id from an OZWValue."""
|
||||
# [OZW_INSTANCE_ID]-[NODE_ID]-[VALUE_ID_KEY]
|
||||
return f"{value.node.parent.id}-{value.node.id}-{value.value_id_key}"
|
@ -1,88 +0,0 @@
|
||||
"""Support for Z-Wave fans."""
|
||||
import math
|
||||
|
||||
from homeassistant.components.fan import (
|
||||
DOMAIN as FAN_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 .const import DATA_UNSUBSCRIBE, DOMAIN
|
||||
from .entity 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(values):
|
||||
"""Add Z-Wave Fan."""
|
||||
fan = ZwaveFan(values)
|
||||
async_add_entities([fan])
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id][DATA_UNSUBSCRIBE].append(
|
||||
async_dispatcher_connect(hass, f"{DOMAIN}_new_{FAN_DOMAIN}", async_add_fan)
|
||||
)
|
||||
|
||||
|
||||
class ZwaveFan(ZWaveDeviceEntity, FanEntity):
|
||||
"""Representation of a Z-Wave fan."""
|
||||
|
||||
async def async_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.values.primary.send_value(zwave_speed)
|
||||
|
||||
async def async_turn_on(self, percentage=None, preset_mode=None, **kwargs):
|
||||
"""Turn the device on."""
|
||||
await self.async_set_percentage(percentage)
|
||||
|
||||
async def async_turn_off(self, **kwargs):
|
||||
"""Turn the device off."""
|
||||
self.values.primary.send_value(0)
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if device is on (speed above 0)."""
|
||||
return self.values.primary.value > 0
|
||||
|
||||
@property
|
||||
def percentage(self):
|
||||
"""Return the current speed.
|
||||
|
||||
The Z-Wave speed value is a byte 0-255. 255 means previous value.
|
||||
The normal range of the speed is 0-99. 0 means off.
|
||||
"""
|
||||
return ranged_value_to_percentage(SPEED_RANGE, self.values.primary.value)
|
||||
|
||||
@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
|
@ -1,343 +0,0 @@
|
||||
"""Support for Z-Wave lights."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_COLOR_TEMP,
|
||||
ATTR_HS_COLOR,
|
||||
ATTR_RGBW_COLOR,
|
||||
ATTR_TRANSITION,
|
||||
COLOR_MODE_BRIGHTNESS,
|
||||
COLOR_MODE_COLOR_TEMP,
|
||||
COLOR_MODE_HS,
|
||||
COLOR_MODE_RGBW,
|
||||
DOMAIN as LIGHT_DOMAIN,
|
||||
SUPPORT_TRANSITION,
|
||||
LightEntity,
|
||||
)
|
||||
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
|
||||
import homeassistant.util.color as color_util
|
||||
|
||||
from .const import DATA_UNSUBSCRIBE, DOMAIN
|
||||
from .entity import ZWaveDeviceEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTR_VALUE = "Value"
|
||||
COLOR_CHANNEL_WARM_WHITE = 0x01
|
||||
COLOR_CHANNEL_COLD_WHITE = 0x02
|
||||
COLOR_CHANNEL_RED = 0x04
|
||||
COLOR_CHANNEL_GREEN = 0x08
|
||||
COLOR_CHANNEL_BLUE = 0x10
|
||||
|
||||
|
||||
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(values):
|
||||
"""Add Z-Wave Light."""
|
||||
light = ZwaveLight(values)
|
||||
|
||||
async_add_entities([light])
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id][DATA_UNSUBSCRIBE].append(
|
||||
async_dispatcher_connect(hass, f"{DOMAIN}_new_{LIGHT_DOMAIN}", async_add_light)
|
||||
)
|
||||
|
||||
|
||||
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 ZwaveLight(ZWaveDeviceEntity, LightEntity):
|
||||
"""Representation of a Z-Wave light."""
|
||||
|
||||
def __init__(self, values):
|
||||
"""Initialize the light."""
|
||||
super().__init__(values)
|
||||
self._color_channels = None
|
||||
self._hs = None
|
||||
self._rgbw_color = None
|
||||
self._ct = None
|
||||
self._attr_color_mode = None
|
||||
self._attr_supported_features = 0
|
||||
self._attr_supported_color_modes = set()
|
||||
self._min_mireds = 153 # 6500K as a safe default
|
||||
self._max_mireds = 370 # 2700K as a safe default
|
||||
|
||||
# make sure that supported features is correctly set
|
||||
self.on_value_update()
|
||||
|
||||
@callback
|
||||
def on_value_update(self):
|
||||
"""Call when the underlying value(s) is added or updated."""
|
||||
if self.values.dimming_duration is not None:
|
||||
self._attr_supported_features |= SUPPORT_TRANSITION
|
||||
|
||||
if self.values.color_channels is not None:
|
||||
# Support Color Temp if both white channels
|
||||
if (self.values.color_channels.value & COLOR_CHANNEL_WARM_WHITE) and (
|
||||
self.values.color_channels.value & COLOR_CHANNEL_COLD_WHITE
|
||||
):
|
||||
self._attr_supported_color_modes.add(COLOR_MODE_COLOR_TEMP)
|
||||
self._attr_supported_color_modes.add(COLOR_MODE_HS)
|
||||
|
||||
# Support White value if only a single white channel
|
||||
if ((self.values.color_channels.value & COLOR_CHANNEL_WARM_WHITE) != 0) ^ (
|
||||
(self.values.color_channels.value & COLOR_CHANNEL_COLD_WHITE) != 0
|
||||
):
|
||||
self._attr_supported_color_modes.add(COLOR_MODE_RGBW)
|
||||
|
||||
if not self._attr_supported_color_modes and self.values.color is not None:
|
||||
self._attr_supported_color_modes.add(COLOR_MODE_HS)
|
||||
|
||||
if not self._attr_supported_color_modes:
|
||||
self._attr_supported_color_modes.add(COLOR_MODE_BRIGHTNESS)
|
||||
# Default: Brightness (no color)
|
||||
self._attr_color_mode = COLOR_MODE_BRIGHTNESS
|
||||
|
||||
if self.values.color is not None:
|
||||
self._calculate_color_values()
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
"""Return the brightness of this light between 0..255.
|
||||
|
||||
Zwave multilevel switches use a range of [0, 99] to control brightness.
|
||||
"""
|
||||
if "target" in self.values:
|
||||
return round((self.values.target.value / 99) * 255)
|
||||
return round((self.values.primary.value / 99) * 255)
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if device is on (brightness above 0)."""
|
||||
if "target" in self.values:
|
||||
return self.values.target.value > 0
|
||||
return self.values.primary.value > 0
|
||||
|
||||
@property
|
||||
def hs_color(self):
|
||||
"""Return the hs color."""
|
||||
return self._hs
|
||||
|
||||
@property
|
||||
def rgbw_color(self):
|
||||
"""Return the rgbw color."""
|
||||
return self._rgbw_color
|
||||
|
||||
@property
|
||||
def color_temp(self):
|
||||
"""Return the color temperature."""
|
||||
return self._ct
|
||||
|
||||
@property
|
||||
def min_mireds(self):
|
||||
"""Return the coldest color_temp that this light supports."""
|
||||
return self._min_mireds
|
||||
|
||||
@property
|
||||
def max_mireds(self):
|
||||
"""Return the warmest color_temp that this light supports."""
|
||||
return self._max_mireds
|
||||
|
||||
@callback
|
||||
def async_set_duration(self, **kwargs):
|
||||
"""Set the transition time for the brightness value.
|
||||
|
||||
Zwave Dimming Duration values now use seconds as an
|
||||
integer (max: 7620 seconds or 127 mins)
|
||||
Build 1205 https://github.com/OpenZWave/open-zwave/commit/f81bc04
|
||||
"""
|
||||
if self.values.dimming_duration is None:
|
||||
return
|
||||
|
||||
ozw_version = tuple(
|
||||
int(x)
|
||||
for x in self.values.primary.ozw_instance.get_status().openzwave_version.split(
|
||||
"."
|
||||
)
|
||||
)
|
||||
|
||||
if ATTR_TRANSITION not in kwargs:
|
||||
# no transition specified by user, use defaults
|
||||
new_value = 7621 # anything over 7620 uses the factory default
|
||||
if ozw_version < (1, 6, 1205):
|
||||
new_value = 255 # default for older version
|
||||
|
||||
else:
|
||||
# transition specified by user
|
||||
new_value = int(max(0, min(7620, kwargs[ATTR_TRANSITION])))
|
||||
if ozw_version < (1, 6, 1205):
|
||||
if (transition := kwargs[ATTR_TRANSITION]) <= 127:
|
||||
new_value = int(transition)
|
||||
else:
|
||||
minutes = int(transition / 60)
|
||||
_LOGGER.debug(
|
||||
"Transition rounded to %d minutes for %s",
|
||||
minutes,
|
||||
self.entity_id,
|
||||
)
|
||||
new_value = minutes + 128
|
||||
|
||||
# only send value if it differs from current
|
||||
# this prevents a command for nothing
|
||||
if self.values.dimming_duration.value != new_value:
|
||||
self.values.dimming_duration.send_value(new_value)
|
||||
|
||||
async def async_turn_on(self, **kwargs):
|
||||
"""Turn the device on."""
|
||||
self.async_set_duration(**kwargs)
|
||||
|
||||
rgbw = None
|
||||
hs_color = kwargs.get(ATTR_HS_COLOR)
|
||||
rgbw_color = kwargs.get(ATTR_RGBW_COLOR)
|
||||
color_temp = kwargs.get(ATTR_COLOR_TEMP)
|
||||
|
||||
if hs_color is not None:
|
||||
rgbw = "#"
|
||||
for colorval in color_util.color_hs_to_RGB(*hs_color):
|
||||
rgbw += f"{colorval:02x}"
|
||||
if self._color_channels and self._color_channels & COLOR_CHANNEL_COLD_WHITE:
|
||||
rgbw += "0000"
|
||||
else:
|
||||
# trim the CW value or it will not work correctly
|
||||
rgbw += "00"
|
||||
# white LED must be off in order for color to work
|
||||
|
||||
elif rgbw_color is not None:
|
||||
red = rgbw_color[0]
|
||||
green = rgbw_color[1]
|
||||
blue = rgbw_color[2]
|
||||
white = rgbw_color[3]
|
||||
if self._color_channels & COLOR_CHANNEL_WARM_WHITE:
|
||||
# trim the CW value or it will not work correctly
|
||||
rgbw = f"#{red:02x}{green:02x}{blue:02x}{white:02x}"
|
||||
else:
|
||||
rgbw = f"#{red:02x}{green:02x}{blue:02x}00{white:02x}"
|
||||
|
||||
elif color_temp is not None:
|
||||
# Limit color temp to min/max values
|
||||
cold = max(
|
||||
0,
|
||||
min(
|
||||
255,
|
||||
round(
|
||||
(self._max_mireds - color_temp)
|
||||
/ (self._max_mireds - self._min_mireds)
|
||||
* 255
|
||||
),
|
||||
),
|
||||
)
|
||||
warm = 255 - cold
|
||||
rgbw = f"#000000{warm:02x}{cold:02x}"
|
||||
|
||||
if rgbw and self.values.color:
|
||||
self.values.color.send_value(rgbw)
|
||||
|
||||
# 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:
|
||||
brightness = kwargs[ATTR_BRIGHTNESS]
|
||||
brightness = byte_to_zwave_brightness(brightness)
|
||||
else:
|
||||
brightness = 255
|
||||
|
||||
self.values.primary.send_value(brightness)
|
||||
|
||||
async def async_turn_off(self, **kwargs):
|
||||
"""Turn the device off."""
|
||||
self.async_set_duration(**kwargs)
|
||||
|
||||
self.values.primary.send_value(0)
|
||||
|
||||
def _calculate_color_values(self):
|
||||
"""Parse color rgb and color temperature data."""
|
||||
# Color Data String
|
||||
data = self.values.color.data[ATTR_VALUE]
|
||||
|
||||
# RGB is always present in the OpenZWave color data string.
|
||||
rgb = [int(data[1:3], 16), int(data[3:5], 16), int(data[5:7], 16)]
|
||||
self._hs = color_util.color_RGB_to_hs(*rgb)
|
||||
|
||||
# Light supports color, set color mode to hs
|
||||
self._attr_color_mode = COLOR_MODE_HS
|
||||
|
||||
if self.values.color_channels is None:
|
||||
return
|
||||
|
||||
# Color Channels
|
||||
self._color_channels = self.values.color_channels.data[ATTR_VALUE]
|
||||
|
||||
# Parse remaining color channels. OpenZWave appends white channels
|
||||
# that are present.
|
||||
index = 7
|
||||
temp_warm = 0
|
||||
temp_cold = 0
|
||||
|
||||
# Update color temp limits.
|
||||
if self.values.min_kelvin:
|
||||
self._max_mireds = color_util.color_temperature_kelvin_to_mired(
|
||||
self.values.min_kelvin.data[ATTR_VALUE]
|
||||
)
|
||||
if self.values.max_kelvin:
|
||||
self._min_mireds = color_util.color_temperature_kelvin_to_mired(
|
||||
self.values.max_kelvin.data[ATTR_VALUE]
|
||||
)
|
||||
|
||||
# Warm white
|
||||
if self._color_channels & COLOR_CHANNEL_WARM_WHITE:
|
||||
white = int(data[index : index + 2], 16)
|
||||
self._rgbw_color = [rgb[0], rgb[1], rgb[2], white]
|
||||
temp_warm = white
|
||||
# Light supports rgbw, set color mode to rgbw
|
||||
self._attr_color_mode = COLOR_MODE_RGBW
|
||||
|
||||
index += 2
|
||||
|
||||
# Cold white
|
||||
if self._color_channels & COLOR_CHANNEL_COLD_WHITE:
|
||||
white = int(data[index : index + 2], 16)
|
||||
self._rgbw_color = [rgb[0], rgb[1], rgb[2], white]
|
||||
temp_cold = white
|
||||
# Light supports rgbw, set color mode to rgbw
|
||||
self._attr_color_mode = COLOR_MODE_RGBW
|
||||
|
||||
# Calculate color temps based on white LED status
|
||||
if temp_cold or temp_warm:
|
||||
self._ct = round(
|
||||
self._max_mireds
|
||||
- ((temp_cold / 255) * (self._max_mireds - self._min_mireds))
|
||||
)
|
||||
|
||||
if (
|
||||
self._color_channels & COLOR_CHANNEL_WARM_WHITE
|
||||
and self._color_channels & COLOR_CHANNEL_COLD_WHITE
|
||||
):
|
||||
# Light supports 5 channels, set color_mode to color_temp or hs
|
||||
if rgb[0] == 0 and rgb[1] == 0 and rgb[2] == 0:
|
||||
# Color channels turned off, set color mode to color_temp
|
||||
self._attr_color_mode = COLOR_MODE_COLOR_TEMP
|
||||
else:
|
||||
self._attr_color_mode = COLOR_MODE_HS
|
||||
|
||||
if not (
|
||||
self._color_channels & COLOR_CHANNEL_RED
|
||||
or self._color_channels & COLOR_CHANNEL_GREEN
|
||||
or self._color_channels & COLOR_CHANNEL_BLUE
|
||||
):
|
||||
self._hs = None
|
@ -1,105 +0,0 @@
|
||||
"""Representation of Z-Wave locks."""
|
||||
import logging
|
||||
|
||||
from openzwavemqtt.const import ATTR_CODE_SLOT
|
||||
from openzwavemqtt.exceptions import BaseOZWError
|
||||
from openzwavemqtt.util.lock import clear_usercode, set_usercode
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.lock import DOMAIN as LOCK_DOMAIN, LockEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import config_validation as cv, entity_platform
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DATA_UNSUBSCRIBE, DOMAIN
|
||||
from .entity import ZWaveDeviceEntity
|
||||
|
||||
ATTR_USERCODE = "usercode"
|
||||
|
||||
SERVICE_SET_USERCODE = "set_usercode"
|
||||
SERVICE_GET_USERCODE = "get_usercode"
|
||||
SERVICE_CLEAR_USERCODE = "clear_usercode"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
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(value):
|
||||
"""Add Z-Wave Lock."""
|
||||
lock = ZWaveLock(value)
|
||||
|
||||
async_add_entities([lock])
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id][DATA_UNSUBSCRIBE].append(
|
||||
async_dispatcher_connect(hass, f"{DOMAIN}_new_{LOCK_DOMAIN}", async_add_lock)
|
||||
)
|
||||
|
||||
platform = entity_platform.async_get_current_platform()
|
||||
|
||||
platform.async_register_entity_service(
|
||||
SERVICE_SET_USERCODE,
|
||||
{
|
||||
vol.Required(ATTR_CODE_SLOT): vol.Coerce(int),
|
||||
vol.Required(ATTR_USERCODE): cv.string,
|
||||
},
|
||||
"async_set_usercode",
|
||||
)
|
||||
|
||||
platform.async_register_entity_service(
|
||||
SERVICE_CLEAR_USERCODE,
|
||||
{vol.Required(ATTR_CODE_SLOT): vol.Coerce(int)},
|
||||
"async_clear_usercode",
|
||||
)
|
||||
|
||||
|
||||
def _call_util_lock_function(function, *args):
|
||||
"""Call an openzwavemqtt.util.lock function and return success of call."""
|
||||
try:
|
||||
function(*args)
|
||||
except BaseOZWError as err:
|
||||
_LOGGER.error("%s: %s", type(err), err.args[0])
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class ZWaveLock(ZWaveDeviceEntity, LockEntity):
|
||||
"""Representation of a Z-Wave lock."""
|
||||
|
||||
@property
|
||||
def is_locked(self):
|
||||
"""Return a boolean for the state of the lock."""
|
||||
return bool(self.values.primary.value)
|
||||
|
||||
async def async_lock(self, **kwargs):
|
||||
"""Lock the lock."""
|
||||
self.values.primary.send_value(True)
|
||||
|
||||
async def async_unlock(self, **kwargs):
|
||||
"""Unlock the lock."""
|
||||
self.values.primary.send_value(False)
|
||||
|
||||
@callback
|
||||
def async_set_usercode(self, code_slot, usercode):
|
||||
"""Set the usercode to index X on the lock."""
|
||||
if _call_util_lock_function(
|
||||
set_usercode, self.values.primary.node, code_slot, usercode
|
||||
):
|
||||
_LOGGER.debug("User code at slot %s set", code_slot)
|
||||
|
||||
@callback
|
||||
def async_clear_usercode(self, code_slot):
|
||||
"""Clear usercode in slot X on the lock."""
|
||||
if _call_util_lock_function(
|
||||
clear_usercode, self.values.primary.node, code_slot
|
||||
):
|
||||
_LOGGER.info("Usercode at slot %s is cleared", code_slot)
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"domain": "ozw",
|
||||
"name": "OpenZWave (deprecated)",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/ozw",
|
||||
"requirements": ["python-openzwave-mqtt[mqtt-client]==1.4.0"],
|
||||
"after_dependencies": ["mqtt"],
|
||||
"codeowners": ["@cgarwood", "@marcelveldt", "@MartinHjelmare"],
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["openzwavemqtt"]
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
"""Representation of Z-Wave sensors."""
|
||||
import logging
|
||||
|
||||
from openzwavemqtt.const import CommandClass, ValueType
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
DOMAIN as SENSOR_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 .const import DATA_UNSUBSCRIBE, DOMAIN
|
||||
from .entity import ZWaveDeviceEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
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(value):
|
||||
"""Add Z-Wave Sensor."""
|
||||
# Basic Sensor types
|
||||
if value.primary.type in (
|
||||
ValueType.BYTE,
|
||||
ValueType.INT,
|
||||
ValueType.SHORT,
|
||||
ValueType.DECIMAL,
|
||||
):
|
||||
sensor = ZWaveNumericSensor(value)
|
||||
|
||||
elif value.primary.type == ValueType.LIST:
|
||||
sensor = ZWaveListSensor(value)
|
||||
|
||||
elif value.primary.type == ValueType.STRING:
|
||||
sensor = ZWaveStringSensor(value)
|
||||
|
||||
else:
|
||||
_LOGGER.warning("Sensor not implemented for value %s", value.primary.label)
|
||||
return
|
||||
|
||||
async_add_entities([sensor])
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id][DATA_UNSUBSCRIBE].append(
|
||||
async_dispatcher_connect(
|
||||
hass, f"{DOMAIN}_new_{SENSOR_DOMAIN}", async_add_sensor
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class ZwaveSensorBase(ZWaveDeviceEntity, SensorEntity):
|
||||
"""Basic Representation of a Z-Wave sensor."""
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the device class of the sensor."""
|
||||
if self.values.primary.command_class == CommandClass.BATTERY:
|
||||
return SensorDeviceClass.BATTERY
|
||||
if self.values.primary.command_class == CommandClass.METER:
|
||||
return SensorDeviceClass.POWER
|
||||
if "Temperature" in self.values.primary.label:
|
||||
return SensorDeviceClass.TEMPERATURE
|
||||
if "Illuminance" in self.values.primary.label:
|
||||
return SensorDeviceClass.ILLUMINANCE
|
||||
if "Humidity" in self.values.primary.label:
|
||||
return SensorDeviceClass.HUMIDITY
|
||||
if "Power" in self.values.primary.label:
|
||||
return SensorDeviceClass.POWER
|
||||
if "Energy" in self.values.primary.label:
|
||||
return SensorDeviceClass.POWER
|
||||
if "Electric" in self.values.primary.label:
|
||||
return SensorDeviceClass.POWER
|
||||
if "Pressure" in self.values.primary.label:
|
||||
return SensorDeviceClass.PRESSURE
|
||||
return None
|
||||
|
||||
@property
|
||||
def entity_registry_enabled_default(self) -> bool:
|
||||
"""Return if the entity should be enabled when first added to the entity registry."""
|
||||
# We hide some of the more advanced sensors by default to not overwhelm users
|
||||
if self.values.primary.command_class in (
|
||||
CommandClass.BASIC,
|
||||
CommandClass.INDICATOR,
|
||||
CommandClass.NOTIFICATION,
|
||||
):
|
||||
return False
|
||||
return True
|
||||
|
||||
@property
|
||||
def force_update(self) -> bool:
|
||||
"""Force updates."""
|
||||
return True
|
||||
|
||||
|
||||
class ZWaveStringSensor(ZwaveSensorBase):
|
||||
"""Representation of a Z-Wave sensor."""
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return state of the sensor."""
|
||||
return self.values.primary.value
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self):
|
||||
"""Return unit of measurement the value is expressed in."""
|
||||
return self.values.primary.units
|
||||
|
||||
@property
|
||||
def entity_registry_enabled_default(self):
|
||||
"""Return if the entity should be enabled when first added to the entity registry."""
|
||||
return False
|
||||
|
||||
|
||||
class ZWaveNumericSensor(ZwaveSensorBase):
|
||||
"""Representation of a Z-Wave sensor."""
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return state of the sensor."""
|
||||
return round(self.values.primary.value, 2)
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self):
|
||||
"""Return unit of measurement the value is expressed in."""
|
||||
if self.values.primary.units == "C":
|
||||
return TEMP_CELSIUS
|
||||
if self.values.primary.units == "F":
|
||||
return TEMP_FAHRENHEIT
|
||||
|
||||
return self.values.primary.units
|
||||
|
||||
|
||||
class ZWaveListSensor(ZwaveSensorBase):
|
||||
"""Representation of a Z-Wave list sensor."""
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return the state of the sensor."""
|
||||
# We use the id as value for backwards compatibility
|
||||
return self.values.primary.value["Selected_id"]
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return the device specific state attributes."""
|
||||
attributes = super().extra_state_attributes
|
||||
# add the value's label as property
|
||||
attributes["label"] = self.values.primary.value["Selected"]
|
||||
return attributes
|
||||
|
||||
@property
|
||||
def entity_registry_enabled_default(self) -> bool:
|
||||
"""Return if the entity should be enabled when first added to the entity registry."""
|
||||
# these sensors are only here for backwards compatibility, disable them by default
|
||||
return False
|
@ -1,134 +0,0 @@
|
||||
"""Methods and classes related to executing Z-Wave commands and publishing these to hass."""
|
||||
import logging
|
||||
|
||||
from openzwavemqtt.const import ATTR_LABEL, ATTR_POSITION, ATTR_VALUE
|
||||
from openzwavemqtt.util.node import get_node_from_manager, set_config_parameter
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.core import ServiceCall, callback
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
from . import const
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ZWaveServices:
|
||||
"""Class that holds our services ( Zwave Commands) that should be published to hass."""
|
||||
|
||||
def __init__(self, hass, manager):
|
||||
"""Initialize with both hass and ozwmanager objects."""
|
||||
self._hass = hass
|
||||
self._manager = manager
|
||||
|
||||
@callback
|
||||
def async_register(self):
|
||||
"""Register all our services."""
|
||||
self._hass.services.async_register(
|
||||
const.DOMAIN,
|
||||
const.SERVICE_ADD_NODE,
|
||||
self.async_add_node,
|
||||
schema=vol.Schema(
|
||||
{
|
||||
vol.Optional(const.ATTR_INSTANCE_ID, default=1): vol.Coerce(int),
|
||||
vol.Optional(const.ATTR_SECURE, default=False): vol.Coerce(bool),
|
||||
}
|
||||
),
|
||||
)
|
||||
self._hass.services.async_register(
|
||||
const.DOMAIN,
|
||||
const.SERVICE_REMOVE_NODE,
|
||||
self.async_remove_node,
|
||||
schema=vol.Schema(
|
||||
{vol.Optional(const.ATTR_INSTANCE_ID, default=1): vol.Coerce(int)}
|
||||
),
|
||||
)
|
||||
self._hass.services.async_register(
|
||||
const.DOMAIN,
|
||||
const.SERVICE_CANCEL_COMMAND,
|
||||
self.async_cancel_command,
|
||||
schema=vol.Schema(
|
||||
{vol.Optional(const.ATTR_INSTANCE_ID, default=1): vol.Coerce(int)}
|
||||
),
|
||||
)
|
||||
|
||||
self._hass.services.async_register(
|
||||
const.DOMAIN,
|
||||
const.SERVICE_SET_CONFIG_PARAMETER,
|
||||
self.async_set_config_parameter,
|
||||
schema=vol.Schema(
|
||||
{
|
||||
vol.Optional(const.ATTR_INSTANCE_ID, default=1): vol.Coerce(int),
|
||||
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.All(
|
||||
cv.ensure_list,
|
||||
[
|
||||
vol.All(
|
||||
{
|
||||
vol.Exclusive(ATTR_LABEL, "bit"): cv.string,
|
||||
vol.Exclusive(ATTR_POSITION, "bit"): vol.Coerce(
|
||||
int
|
||||
),
|
||||
vol.Required(ATTR_VALUE): bool,
|
||||
},
|
||||
cv.has_at_least_one_key(ATTR_LABEL, ATTR_POSITION),
|
||||
)
|
||||
],
|
||||
),
|
||||
vol.Coerce(int),
|
||||
bool,
|
||||
cv.string,
|
||||
),
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
@callback
|
||||
def async_set_config_parameter(self, service: ServiceCall) -> None:
|
||||
"""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,
|
||||
)
|
||||
|
||||
@callback
|
||||
def async_add_node(self, service: ServiceCall) -> None:
|
||||
"""Enter inclusion mode on the controller."""
|
||||
instance_id = service.data[const.ATTR_INSTANCE_ID]
|
||||
secure = service.data[const.ATTR_SECURE]
|
||||
instance = self._manager.get_instance(instance_id)
|
||||
if instance is None:
|
||||
raise ValueError(f"No OpenZWave Instance with ID {instance_id}")
|
||||
instance.add_node(secure)
|
||||
|
||||
@callback
|
||||
def async_remove_node(self, service: ServiceCall) -> None:
|
||||
"""Enter exclusion mode on the controller."""
|
||||
instance_id = service.data[const.ATTR_INSTANCE_ID]
|
||||
instance = self._manager.get_instance(instance_id)
|
||||
if instance is None:
|
||||
raise ValueError(f"No OpenZWave Instance with ID {instance_id}")
|
||||
instance.remove_node()
|
||||
|
||||
@callback
|
||||
def async_cancel_command(self, service: ServiceCall) -> None:
|
||||
"""Tell the controller to cancel an add or remove command."""
|
||||
instance_id = service.data[const.ATTR_INSTANCE_ID]
|
||||
instance = self._manager.get_instance(instance_id)
|
||||
if instance is None:
|
||||
raise ValueError(f"No OpenZWave Instance with ID {instance_id}")
|
||||
instance.cancel_controller_command()
|
@ -1,121 +0,0 @@
|
||||
# Describes the format for available Z-Wave services
|
||||
add_node:
|
||||
name: Add node
|
||||
description: Add a new node to the Z-Wave network.
|
||||
fields:
|
||||
secure:
|
||||
name: Secure
|
||||
description: Add the new node 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.
|
||||
default: false
|
||||
selector:
|
||||
boolean:
|
||||
instance_id:
|
||||
name: Instance ID
|
||||
description: The OZW Instance/Controller to use.
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 255
|
||||
|
||||
remove_node:
|
||||
name: Remove node
|
||||
description: Remove a node from the Z-Wave network. Will set the controller into exclusion mode.
|
||||
fields:
|
||||
instance_id:
|
||||
name: Instance ID
|
||||
description: The OZW Instance/Controller to use.
|
||||
default: 1
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 255
|
||||
|
||||
cancel_command:
|
||||
name: Cancel command
|
||||
description: Cancel a pending add or remove node command.
|
||||
fields:
|
||||
instance_id:
|
||||
name: Instance ID
|
||||
description: The OZW Instance/Controller to use.
|
||||
default: 1
|
||||
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
|
||||
example: 50268673
|
||||
selector:
|
||||
text:
|
||||
instance_id:
|
||||
name: Instance ID
|
||||
description: The OZW Instance/Controller to use.
|
||||
default: 1
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 255
|
||||
|
||||
clear_usercode:
|
||||
name: Clear usercode
|
||||
description: Clear a usercode from lock.
|
||||
target:
|
||||
entity:
|
||||
integration: ozw
|
||||
domain: lock
|
||||
fields:
|
||||
code_slot:
|
||||
name: Code slot
|
||||
description: Code slot to clear code from.
|
||||
required: true
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 255
|
||||
|
||||
set_usercode:
|
||||
name: Set usercode
|
||||
description: Set a usercode to lock.
|
||||
target:
|
||||
entity:
|
||||
integration: ozw
|
||||
domain: lock
|
||||
fields:
|
||||
code_slot:
|
||||
name: Code slot
|
||||
description: Code slot to set the code.
|
||||
required: true
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 255
|
||||
usercode:
|
||||
name: Usercode
|
||||
description: Code to set.
|
||||
required: true
|
||||
example: 1234
|
||||
selector:
|
||||
text:
|
@ -1,39 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"on_supervisor": {
|
||||
"title": "Select connection method",
|
||||
"description": "Do you want to use the OpenZWave Supervisor add-on?",
|
||||
"data": { "use_addon": "Use the OpenZWave Supervisor add-on" }
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "The OpenZWave add-on installation has started"
|
||||
},
|
||||
"start_addon": {
|
||||
"title": "Enter the OpenZWave add-on configuration",
|
||||
"data": {
|
||||
"usb_path": "[%key:common::config_flow::data::usb_path%]",
|
||||
"network_key": "Network Key"
|
||||
}
|
||||
},
|
||||
"hassio_confirm": {
|
||||
"title": "Set up OpenZWave integration with the OpenZWave add-on"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
|
||||
"addon_info_failed": "Failed to get OpenZWave add-on info.",
|
||||
"addon_install_failed": "Failed to install the OpenZWave add-on.",
|
||||
"addon_set_config_failed": "Failed to set OpenZWave configuration.",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"mqtt_required": "The MQTT integration is not set up"
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "Failed to start the OpenZWave add-on. Check the configuration."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Please wait while the OpenZWave add-on installation finishes. This can take several minutes."
|
||||
}
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
"""Representation of Z-Wave switches."""
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_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 .const import DATA_UNSUBSCRIBE, DOMAIN
|
||||
from .entity import ZWaveDeviceEntity
|
||||
|
||||
|
||||
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(value):
|
||||
"""Add Z-Wave Switch."""
|
||||
switch = ZWaveSwitch(value)
|
||||
|
||||
async_add_entities([switch])
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id][DATA_UNSUBSCRIBE].append(
|
||||
async_dispatcher_connect(
|
||||
hass, f"{DOMAIN}_new_{SWITCH_DOMAIN}", async_add_switch
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class ZWaveSwitch(ZWaveDeviceEntity, SwitchEntity):
|
||||
"""Representation of a Z-Wave switch."""
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return a boolean for the state of the switch."""
|
||||
return bool(self.values.primary.value)
|
||||
|
||||
async def async_turn_on(self, **kwargs):
|
||||
"""Turn the switch on."""
|
||||
self.values.primary.send_value(True)
|
||||
|
||||
async def async_turn_off(self, **kwargs):
|
||||
"""Turn the switch off."""
|
||||
self.values.primary.send_value(False)
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e \u0432\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e",
|
||||
"single_instance_allowed": "\u0412\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e. \u0412\u044a\u0437\u043c\u043e\u0436\u043d\u0430 \u0435 \u0441\u0430\u043c\u043e \u0435\u0434\u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f."
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "No s'ha pogut obtenir la informaci\u00f3 del complement OpenZWave.",
|
||||
"addon_install_failed": "No s'ha pogut instal\u00b7lar el complement OpenZWave.",
|
||||
"addon_set_config_failed": "No s'ha pogut establir la configuraci\u00f3 d'OpenZWave.",
|
||||
"already_configured": "El dispositiu ja est\u00e0 configurat",
|
||||
"already_in_progress": "El flux de configuraci\u00f3 ja est\u00e0 en curs",
|
||||
"mqtt_required": "La integraci\u00f3 MQTT no est\u00e0 configurada",
|
||||
"single_instance_allowed": "Ja configurat. Nom\u00e9s \u00e9s possible una sola configuraci\u00f3."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "No s'ha pogut iniciar el complement OpenZWave. Comprova la configuraci\u00f3."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Espera mentre finalitza la instal\u00b7laci\u00f3 del complement OpenZWave. Pot tardar uns quants minuts."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Configuraci\u00f3 de la integraci\u00f3 d'OpenZWave amb el complement OpenZWave"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "Ha comen\u00e7at la instal\u00b7laci\u00f3 del complement OpenZWave"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Utilitza el complement OpenZWave Supervisor"
|
||||
},
|
||||
"description": "Vols utilitzar el complement Supervisor d'OpenZWave?",
|
||||
"title": "Selecciona el m\u00e8tode de connexi\u00f3"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Clau de xarxa",
|
||||
"usb_path": "Ruta del dispositiu USB"
|
||||
},
|
||||
"title": "Introdueix la configuraci\u00f3 del complement OpenZWave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "Nepoda\u0159ilo se z\u00edskat informace o dopl\u0148ku OpenZWave.",
|
||||
"addon_install_failed": "Instalace dopl\u0148ku OpenZWave se nezda\u0159ila.",
|
||||
"addon_set_config_failed": "Nepoda\u0159ilo se nastavit OpenZWave.",
|
||||
"already_configured": "Za\u0159\u00edzen\u00ed je ji\u017e nastaveno",
|
||||
"already_in_progress": "Konfigurace ji\u017e prob\u00edh\u00e1",
|
||||
"mqtt_required": "Integrace MQTT nen\u00ed nastavena",
|
||||
"single_instance_allowed": "Ji\u017e nastaveno. Je mo\u017en\u00e1 pouze jedin\u00e1 konfigurace."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "Spu\u0161t\u011bn\u00ed dopl\u0148ku OpenZWave se nezda\u0159ilo. Zkontrolujte konfiguraci."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Nastaven\u00ed integrace OpenZWave s dopl\u0148kem OpenZWave"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "Instalace dopl\u0148ku OpenZWave byla zah\u00e1jena."
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Pou\u017e\u00edt dopln\u011bk OpenZWave pro Supervisor"
|
||||
},
|
||||
"description": "Chcete pou\u017e\u00edt dopln\u011bk OpenZWave pro Supervisor?",
|
||||
"title": "Vyberte metodu p\u0159ipojen\u00ed"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "S\u00ed\u0165ov\u00fd kl\u00ed\u010d",
|
||||
"usb_path": "Cesta k USB za\u0159\u00edzen\u00ed"
|
||||
},
|
||||
"title": "Zadejte konfiguraci dopl\u0148ku OpenZWave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "Fehler beim Abrufen von OpenZWave Add-on Informationen.",
|
||||
"addon_install_failed": "Installation des OpenZWave Add-ons fehlgeschlagen.",
|
||||
"addon_set_config_failed": "Setzen der OpenZWave Konfiguration fehlgeschlagen.",
|
||||
"already_configured": "Ger\u00e4t ist bereits konfiguriert",
|
||||
"already_in_progress": "Der Konfigurationsablauf wird bereits ausgef\u00fchrt",
|
||||
"mqtt_required": "Die MQTT-Integration ist nicht eingerichtet",
|
||||
"single_instance_allowed": "Bereits konfiguriert. Nur eine einzige Konfiguration m\u00f6glich."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "Fehler beim Starten des OpenZWave Add-ons. \u00dcberpr\u00fcfe die Konfiguration."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Bitte warten, bis die Installation des OpenZWave-Add-Ons abgeschlossen ist. Dies kann einige Minuten dauern."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Richte die OpenZWave Integration mit dem OpenZWave Add-On ein"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "Die Installation des OpenZWave-Add-On wurde gestartet"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Verwende das OpenZWave Supervisor Add-on"
|
||||
},
|
||||
"description": "M\u00f6chtest du das OpenZWave Supervisor Add-on verwenden?",
|
||||
"title": "Verbindungstyp ausw\u00e4hlen"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Netzwerk-Schl\u00fcssel",
|
||||
"usb_path": "USB-Ger\u00e4te-Pfad"
|
||||
},
|
||||
"title": "Gib die Konfiguration des OpenZWave Add-ons ein"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03bb\u03ae\u03c8\u03b7\u03c2 \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03b9\u03ce\u03bd \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf\u03c5 OpenZWave.",
|
||||
"addon_install_failed": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03b5\u03b3\u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7\u03c2 \u03c4\u03bf\u03c5 \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf\u03c5 OpenZWave.",
|
||||
"addon_set_config_failed": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c1\u03cd\u03b8\u03bc\u03b9\u03c3\u03b7\u03c2 \u03c0\u03b1\u03c1\u03b1\u03bc\u03ad\u03c4\u03c1\u03c9\u03bd OpenZWave.",
|
||||
"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",
|
||||
"already_in_progress": "\u0397 \u03c1\u03bf\u03ae \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7\u03c2 \u03b2\u03c1\u03af\u03c3\u03ba\u03b5\u03c4\u03b1\u03b9 \u03ae\u03b4\u03b7 \u03c3\u03b5 \u03b5\u03be\u03ad\u03bb\u03b9\u03be\u03b7",
|
||||
"mqtt_required": "\u0397 \u03b5\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7 MQTT \u03b4\u03b5\u03bd \u03ad\u03c7\u03b5\u03b9 \u03c1\u03c5\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af",
|
||||
"single_instance_allowed": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03c4\u03b7\u03ba\u03b5 \u03ae\u03b4\u03b7. \u039c\u03cc\u03bd\u03bf \u03bc\u03af\u03b1 \u03c0\u03b1\u03c1\u03b1\u03bc\u03b5\u03c4\u03c1\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7\u03c2 \u03c4\u03bf\u03c5 \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf\u03c5 OpenZWave. \u0395\u03bb\u03ad\u03b3\u03be\u03c4\u03b5 \u03c4\u03b7 \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "\u03a0\u03b5\u03c1\u03b9\u03bc\u03ad\u03bd\u03b5\u03c4\u03b5 \u03bc\u03ad\u03c7\u03c1\u03b9 \u03bd\u03b1 \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03c9\u03b8\u03b5\u03af \u03b7 \u03b5\u03b3\u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf\u03c5 OpenZWave. \u0391\u03c5\u03c4\u03cc \u03bc\u03c0\u03bf\u03c1\u03b5\u03af \u03bd\u03b1 \u03b4\u03b9\u03b1\u03c1\u03ba\u03ad\u03c3\u03b5\u03b9 \u03b1\u03c1\u03ba\u03b5\u03c4\u03ac \u03bb\u03b5\u03c0\u03c4\u03ac."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "\u03a1\u03cd\u03b8\u03bc\u03b9\u03c3\u03b7 \u03b5\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7\u03c2 OpenZWave \u03bc\u03b5 \u03c4\u03bf \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf OpenZWave"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "\u0397 \u03b5\u03b3\u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf\u03c5 OpenZWave \u03ad\u03c7\u03b5\u03b9 \u03be\u03b5\u03ba\u03b9\u03bd\u03ae\u03c3\u03b5\u03b9"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "\u03a7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03c4\u03b5 \u03c4\u03bf \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf OpenZWave Supervisor"
|
||||
},
|
||||
"description": "\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03c4\u03bf \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf OpenZWave Supervisor;",
|
||||
"title": "\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03bc\u03ad\u03b8\u03bf\u03b4\u03bf \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "\u039a\u03bb\u03b5\u03b9\u03b4\u03af \u03b4\u03b9\u03ba\u03c4\u03cd\u03bf\u03c5",
|
||||
"usb_path": "\u0394\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae \u03c3\u03c5\u03c3\u03ba\u03b5\u03c5\u03ae\u03c2 USB"
|
||||
},
|
||||
"title": "\u0395\u03b9\u03c3\u03ac\u03b3\u03b5\u03c4\u03b5 \u03c4\u03b7 \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf\u03c5 OpenZWave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "Failed to get OpenZWave add-on info.",
|
||||
"addon_install_failed": "Failed to install the OpenZWave add-on.",
|
||||
"addon_set_config_failed": "Failed to set OpenZWave configuration.",
|
||||
"already_configured": "Device is already configured",
|
||||
"already_in_progress": "Configuration flow is already in progress",
|
||||
"mqtt_required": "The MQTT integration is not set up",
|
||||
"single_instance_allowed": "Already configured. Only a single configuration possible."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "Failed to start the OpenZWave add-on. Check the configuration."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Please wait while the OpenZWave add-on installation finishes. This can take several minutes."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Set up OpenZWave integration with the OpenZWave add-on"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "The OpenZWave add-on installation has started"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Use the OpenZWave Supervisor add-on"
|
||||
},
|
||||
"description": "Do you want to use the OpenZWave Supervisor add-on?",
|
||||
"title": "Select connection method"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Network Key",
|
||||
"usb_path": "USB Device Path"
|
||||
},
|
||||
"title": "Enter the OpenZWave add-on configuration"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "No se pudo obtener la informaci\u00f3n del complemento de OpenZWave.",
|
||||
"addon_install_failed": "No se pudo instalar el complemento de OpenZWave.",
|
||||
"addon_set_config_failed": "No se pudo establecer la configuraci\u00f3n de OpenZWave.",
|
||||
"already_configured": "El dispositivo ya est\u00e1 configurado",
|
||||
"already_in_progress": "El flujo de configuraci\u00f3n ya est\u00e1 en proceso",
|
||||
"mqtt_required": "La integraci\u00f3n de MQTT no est\u00e1 configurada",
|
||||
"single_instance_allowed": "Ya est\u00e1 configurado. Solo es posible una \u00fanica configuraci\u00f3n."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "No se pudo iniciar el complemento OpenZWave. Verifica la configuraci\u00f3n."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Espera mientras finaliza la instalaci\u00f3n del complemento OpenZWave. Esto puede tardar varios minutos."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Configurar la integraci\u00f3n de OpenZWave con el complemento OpenZWave"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "La instalaci\u00f3n del complemento OpenZWave se ha iniciado"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Usar el complemento de supervisor de OpenZWave"
|
||||
},
|
||||
"description": "\u00bfQuiere utilizar el complemento de Supervisor de OpenZWave?",
|
||||
"title": "Selecciona el m\u00e9todo de conexi\u00f3n"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Clave de red",
|
||||
"usb_path": "Ruta del dispositivo USB"
|
||||
},
|
||||
"title": "Introduce la configuraci\u00f3n del complemento OpenZWave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "OpenZWave'i lisandmooduli teabe hankimine nurjus.",
|
||||
"addon_install_failed": "OpenZWave'i lisandmooduli paigaldamine nurjus.",
|
||||
"addon_set_config_failed": "OpenZWave'i konfiguratsiooni seadistamine eba\u00f5nnestus.",
|
||||
"already_configured": "Seade on juba h\u00e4\u00e4lestatud",
|
||||
"already_in_progress": "Seadistamine on juba k\u00e4imas",
|
||||
"mqtt_required": "MQTT sidumine pole seadistatud",
|
||||
"single_instance_allowed": "Juba seadistatud. V\u00f5imalik on ainult \u00fcks seadistamine."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "OpenZWave'i lisandmooduli k\u00e4ivitamine nurjus. Kontrolli s\u00e4tteid."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Palun oota kuni OpenZWave lisandmooduli paigaldus l\u00f5peb. See v\u00f5ib v\u00f5tta mitu minutit."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Seadista OpenZWave'i sidumine OpenZWave lisandmooduli abil"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "OpenZWave lisandmooduli paigaldamine on alanud"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Kasuta OpenZWave Supervisori lisandmoodulit"
|
||||
},
|
||||
"description": "Kas soovid kasutada OpenZWave'i halduri lisandmoodulit?",
|
||||
"title": "Vali \u00fchendusviis"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "V\u00f5rgu v\u00f5ti",
|
||||
"usb_path": "USB seadme rada"
|
||||
},
|
||||
"title": "Sisesta OpenZWave'i lisandmooduli seaded"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "Impossible d'obtenir les informations sur le module compl\u00e9mentaire OpenZWave.",
|
||||
"addon_install_failed": "\u00c9chec de l'installation du module compl\u00e9mentaire OpenZWave.",
|
||||
"addon_set_config_failed": "\u00c9chec de la configuration OpenZWave.",
|
||||
"already_configured": "L'appareil est d\u00e9j\u00e0 configur\u00e9",
|
||||
"already_in_progress": "La configuration est d\u00e9j\u00e0 en cours\u00e0",
|
||||
"mqtt_required": "L'int\u00e9gration MQTT n'est pas configur\u00e9e",
|
||||
"single_instance_allowed": "D\u00e9j\u00e0 configur\u00e9. Une seule configuration possible."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "\u00c9chec du d\u00e9marrage du module compl\u00e9mentaire OpenZWave. V\u00e9rifiez la configuration."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Veuillez patienter pendant que l'installation du module OpenZWave se termine. Cela peut prendre plusieurs minutes."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Configurer l'int\u00e9gration d'OpenZWave avec le module compl\u00e9mentaire OpenZWave"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "L'installation du module compl\u00e9mentaire OpenZWave a commenc\u00e9"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Utilisez le module compl\u00e9mentaire OpenZWave du Supervisor"
|
||||
},
|
||||
"description": "Voulez-vous utiliser le module compl\u00e9mentaire OpenZWave du Supervisor?",
|
||||
"title": "S\u00e9lectionner la m\u00e9thode de connexion"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Cl\u00e9 r\u00e9seau",
|
||||
"usb_path": "Chemin du p\u00e9riph\u00e9rique USB"
|
||||
},
|
||||
"title": "Entrez dans la configuration du module compl\u00e9mentaire OpenZWave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u05ea\u05e6\u05d5\u05e8\u05ea \u05d4\u05d4\u05ea\u05e7\u05df \u05db\u05d1\u05e8 \u05e0\u05e7\u05d1\u05e2\u05d4",
|
||||
"already_in_progress": "\u05d6\u05e8\u05d9\u05de\u05ea \u05d4\u05ea\u05e6\u05d5\u05e8\u05d4 \u05db\u05d1\u05e8 \u05de\u05ea\u05d1\u05e6\u05e2\u05ea",
|
||||
"mqtt_required": "\u05e9\u05d9\u05dc\u05d5\u05d1 MQTT \u05d0\u05d9\u05e0\u05d5 \u05de\u05d5\u05d2\u05d3\u05e8",
|
||||
"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": {
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "\u05e9\u05d9\u05de\u05d5\u05e9 \u05d1\u05d4\u05e8\u05d7\u05d1\u05d4 '\u05de\u05e4\u05e7\u05d7 OpenZWave'"
|
||||
},
|
||||
"description": "\u05d4\u05d0\u05dd \u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05d4\u05e8\u05d7\u05d1\u05d4 \u05e9\u05dc \u05de\u05e4\u05e7\u05d7 OpenZWave?",
|
||||
"title": "\u05d1\u05d7\u05e8 \u05e9\u05d9\u05d8\u05ea \u05d7\u05d9\u05d1\u05d5\u05e8"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"usb_path": "\u05e0\u05ea\u05d9\u05d1 \u05d4\u05ea\u05e7\u05df USB"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "Nem siker\u00fclt leh\u00edvni az OpenZWave b\u0151v\u00edtm\u00e9ny inform\u00e1ci\u00f3kat.",
|
||||
"addon_install_failed": "Nem siker\u00fclt telep\u00edteni az OpenZWave b\u0151v\u00edtm\u00e9nyt.",
|
||||
"addon_set_config_failed": "Nem siker\u00fclt be\u00e1ll\u00edtani az OpenZWave konfigur\u00e1ci\u00f3t.",
|
||||
"already_configured": "Az eszk\u00f6z m\u00e1r konfigur\u00e1lva van",
|
||||
"already_in_progress": "A konfigur\u00e1l\u00e1s m\u00e1r folyamatban van",
|
||||
"mqtt_required": "Az MQTT integr\u00e1ci\u00f3 nincs be\u00e1ll\u00edtva",
|
||||
"single_instance_allowed": "M\u00e1r konfigur\u00e1lva van. Csak egy konfigur\u00e1ci\u00f3 lehets\u00e9ges."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "Nem siker\u00fclt elind\u00edtani az OpenZWave b\u0151v\u00edtm\u00e9nyt. Ellen\u0151rizze a konfigur\u00e1ci\u00f3t."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "V\u00e1rjon, am\u00edg az OpenZWave b\u0151v\u00edtm\u00e9ny telep\u00edt\u00e9se befejez\u0151dik. Ez t\u00f6bb percig is eltarthat."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "\u00c1ll\u00edtsa be az OpenZWave integr\u00e1ci\u00f3t az OpenZWave b\u0151v\u00edtm\u00e9nnyel"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "Elindult az OpenZWave b\u0151v\u00edtm\u00e9ny telep\u00edt\u00e9se"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "OpenZWave Supervisor b\u0151v\u00edtm\u00e9ny haszn\u00e1lata"
|
||||
},
|
||||
"description": "Szeretn\u00e9 haszn\u00e1lni az OpenZWave Supervisor b\u0151v\u00edtm\u00e9nyt?",
|
||||
"title": "V\u00e1lassza ki a csatlakoz\u00e1si m\u00f3dot"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "H\u00e1l\u00f3zati kulcs",
|
||||
"usb_path": "USB eszk\u00f6z el\u00e9r\u00e9si \u00fat"
|
||||
},
|
||||
"title": "Adja meg az OpenZWave b\u0151v\u00edtm\u00e9ny konfigur\u00e1ci\u00f3j\u00e1t"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "Gagal mendapatkan info add-on OpenZWave.",
|
||||
"addon_install_failed": "Gagal menginstal add-on OpenZWave.",
|
||||
"addon_set_config_failed": "Gagal menyetel konfigurasi OpenZWave.",
|
||||
"already_configured": "Perangkat sudah dikonfigurasi",
|
||||
"already_in_progress": "Alur konfigurasi sedang berlangsung",
|
||||
"mqtt_required": "Integrasi MQTT belum disiapkan",
|
||||
"single_instance_allowed": "Sudah dikonfigurasi. Hanya satu konfigurasi yang diizinkan."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "Gagal memulai add-on OpenZWave. Periksa konfigurasi."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Harap tunggu hingga penginstalan add-on OpenZWave selesai. Ini bisa memakan waktu beberapa saat."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Siapkan integrasi OpenZWave dengan add-on OpenZWave"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "Instalasi add-on OpenZWave telah dimulai"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Gunakan add-on Supervisor OpenZWave"
|
||||
},
|
||||
"description": "Ingin menggunakan add-on Supervisor OpenZWave?",
|
||||
"title": "Pilih metode koneksi"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Kunci Jaringan",
|
||||
"usb_path": "Jalur Perangkat USB"
|
||||
},
|
||||
"title": "Masukkan konfigurasi add-on OpenZWave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "Impossibile ottenere le informazioni sul componente aggiuntivo OpenZWave.",
|
||||
"addon_install_failed": "Impossibile installare il componente aggiuntivo OpenZWave.",
|
||||
"addon_set_config_failed": "Impossibile impostare la configurazione di OpenZWave.",
|
||||
"already_configured": "Il dispositivo \u00e8 gi\u00e0 configurato",
|
||||
"already_in_progress": "Il flusso di configurazione \u00e8 gi\u00e0 in corso",
|
||||
"mqtt_required": "L'integrazione MQTT non \u00e8 impostata",
|
||||
"single_instance_allowed": "Gi\u00e0 configurato. \u00c8 possibile una sola configurazione."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "Impossibile avviare il componente aggiuntivo OpenZWave. Controlla la configurazione."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Attendi il termine dell'installazione del componente aggiuntivo OpenZWave. Questa operazione pu\u00f2 richiedere diversi minuti."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Configura l'integrazione di OpenZWave con il componente aggiuntivo OpenZWave"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "L'installazione del componente aggiuntivo OpenZWave \u00e8 iniziata"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Usa il componente aggiuntivo OpenZWave Supervisor"
|
||||
},
|
||||
"description": "Vuoi usare il componente aggiuntivo OpenZWave Supervisor?",
|
||||
"title": "Seleziona il metodo di connessione"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Chiave di rete",
|
||||
"usb_path": "Percorso del dispositivo USB"
|
||||
},
|
||||
"title": "Accedi alla configurazione dell'add-on OpenZWave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "OpenZWave\u306e\u30a2\u30c9\u30aa\u30f3\u60c5\u5831\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002",
|
||||
"addon_install_failed": "OpenZWave\u30a2\u30c9\u30aa\u30f3\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002",
|
||||
"addon_set_config_failed": "OpenZWave\u306e\u8a2d\u5b9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002",
|
||||
"already_configured": "\u30c7\u30d0\u30a4\u30b9\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059",
|
||||
"already_in_progress": "\u69cb\u6210\u30d5\u30ed\u30fc\u306f\u3059\u3067\u306b\u9032\u884c\u4e2d\u3067\u3059",
|
||||
"mqtt_required": "MQTT\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093",
|
||||
"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": {
|
||||
"addon_start_failed": "OpenZWave\u30a2\u30c9\u30aa\u30f3\u306e\u8d77\u52d5\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u8a2d\u5b9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002"
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "OpenZWave\u30a2\u30c9\u30aa\u30f3\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u304c\u5b8c\u4e86\u3059\u308b\u307e\u3067\u304a\u5f85\u3061\u304f\u3060\u3055\u3044\u3002\u3053\u308c\u306b\u306f\u6570\u5206\u304b\u304b\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002"
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "OpenZWave\u30a2\u30c9\u30aa\u30f3\u3068OpenZWave\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u3092\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "OpenZWave\u30a2\u30c9\u30aa\u30f3\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u304c\u958b\u59cb\u3055\u308c\u307e\u3057\u305f"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "OpenZWave Supervisor\u30a2\u30c9\u30aa\u30f3\u3092\u4f7f\u7528\u3059\u308b"
|
||||
},
|
||||
"description": "OpenZWave Supervisor\u30a2\u30c9\u30aa\u30f3\u3092\u4f7f\u7528\u3057\u307e\u3059\u304b\uff1f",
|
||||
"title": "\u63a5\u7d9a\u65b9\u6cd5\u306e\u9078\u629e"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u30ad\u30fc",
|
||||
"usb_path": "USB\u30c7\u30d0\u30a4\u30b9\u306e\u30d1\u30b9"
|
||||
},
|
||||
"title": "OpenZWave\u30a2\u30c9\u30aa\u30f3\u306e\u8a2d\u5b9a\u3092\u5165\u529b\u3059\u308b"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "\u10d5\u10d4\u10e0 \u10db\u10dd\u10ee\u10d4\u10e0\u10ee\u10d3\u10d0 OpenZWave \u10d3\u10d0\u10dc\u10d0\u10db\u10d0\u10e2\u10d8\u10e1 \u10d8\u10dc\u10e4\u10dd\u10e1 \u10db\u10d8\u10e6\u10d4\u10d1\u10d0.",
|
||||
"addon_install_failed": "\u10d5\u10d4\u10e0 \u10db\u10dd\u10ee\u10d4\u10e0\u10ee\u10d3\u10d0 OpenZWave \u10d3\u10d0\u10dc\u10d0\u10db\u10d0\u10e2\u10d8\u10e1 \u10d8\u10dc\u10e1\u10e2\u10d0\u10da\u10d8\u10e0\u10d4\u10d1\u10d0.",
|
||||
"addon_set_config_failed": "\u10d5\u10d4\u10e0 \u10db\u10dd\u10ee\u10d4\u10e0\u10ee\u10d3\u10d0 OpenZWave \u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d8\u10e1 \u10d3\u10d0\u10e7\u10d4\u10dc\u10d4\u10d1\u10d0.",
|
||||
"single_instance_allowed": "\u10e3\u10d9\u10d5\u10d4 \u10d3\u10d0\u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d8\u10e0\u10d4\u10d1\u10e3\u10da\u10d8\u10d0. \u10e8\u10d4\u10e1\u10d0\u10eb\u10da\u10d4\u10d1\u10d4\u10da\u10d8\u10d0 \u10db\u10ee\u10dd\u10da\u10dd\u10d3 \u10d4\u10e0\u10d7\u10d8 \u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d0."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "OpenZWave \u10d3\u10d0\u10dc\u10d0\u10db\u10d0\u10e2\u10d8 \u10d0\u10e0 \u10d3\u10d0\u10d8\u10e1\u10e2\u10d0\u10e0\u10e2\u10d0. \u10e8\u10d4\u10d0\u10db\u10dd\u10ec\u10db\u10d4\u10d7 \u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d0."
|
||||
},
|
||||
"step": {
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "\u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10d4\u10d7 OpenZWave Supervisor \u10d3\u10d0\u10dc\u10d0\u10db\u10d0\u10e2\u10d8"
|
||||
},
|
||||
"description": "\u10d2\u10e1\u10e3\u10e0\u10d7 \u10d2\u10d0\u10db\u10dd\u10d8\u10e7\u10d4\u10dc\u10dd\u10d7 OpenZWave Supervisor-\u10d8\u10e1 \u10d3\u10d0\u10dc\u10d0\u10db\u10d0\u10e2\u10d8?",
|
||||
"title": "\u10d0\u10d8\u10e0\u10e9\u10d8\u10d4\u10d7 \u10d9\u10d0\u10d5\u10e8\u10d8\u10e0\u10d8\u10e1 \u10db\u10d4\u10d7\u10dd\u10d3\u10d8"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "\u10e5\u10e1\u10d4\u10da\u10d8\u10e1 \u10d2\u10d0\u10e1\u10d0\u10e6\u10d4\u10d1\u10d8",
|
||||
"usb_path": "USB \u10db\u10dd\u10ec\u10e7\u10dd\u10d1\u10da\u10dd\u10d1\u10d8\u10e1 \u10d2\u10d6\u10d0"
|
||||
},
|
||||
"title": "\u10e8\u10d4\u10d8\u10e7\u10d5\u10d0\u10dc\u10d4\u10d7 OpenZWave \u10d3\u10d0\u10dc\u10d0\u10db\u10d0\u10e2\u10d8\u10e1 \u10d9\u10dd\u10dc\u10e4\u10d8\u10d2\u10e3\u10e0\u10d0\u10ea\u10d8\u10d0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "OpenZWave \uc560\ub4dc\uc628\uc758 \uc815\ubcf4\ub97c \uac00\uc838\uc624\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.",
|
||||
"addon_install_failed": "OpenZWave \uc560\ub4dc\uc628\uc744 \uc124\uce58\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.",
|
||||
"addon_set_config_failed": "OpenZWave \uad6c\uc131\uc744 \uc124\uc815\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.",
|
||||
"already_configured": "\uae30\uae30\uac00 \uc774\ubbf8 \uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4",
|
||||
"already_in_progress": "\uae30\uae30 \uad6c\uc131\uc774 \uc774\ubbf8 \uc9c4\ud589 \uc911\uc785\ub2c8\ub2e4",
|
||||
"mqtt_required": "MQTT \ud1b5\ud569 \uad6c\uc131\uc694\uc18c\uac00 \uc124\uc815\ub418\uc9c0 \uc54a\uc558\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": {
|
||||
"addon_start_failed": "OpenZWave \uc560\ub4dc\uc628\uc744 \uc2dc\uc791\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4. \uad6c\uc131 \ub0b4\uc6a9\uc744 \ud655\uc778\ud574\uc8fc\uc138\uc694."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Openzwave \uc560\ub4dc\uc628\uc758 \uc124\uce58\uac00 \uc644\ub8cc\ub418\ub294 \ub3d9\uc548 \uc7a0\uc2dc \uae30\ub2e4\ub824\uc8fc\uc138\uc694. \uba87 \ubd84 \uc815\ub3c4 \uac78\ub9b4 \uc218 \uc788\uc2b5\ub2c8\ub2e4."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "OpenZWave \uc560\ub4dc\uc628\uc73c\ub85c OpenZWave \ud1b5\ud569 \uad6c\uc131\uc694\uc18c \uc124\uc815\ud558\uae30"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "Openzwave \uc560\ub4dc\uc628 \uc124\uce58\uac00 \uc2dc\uc791\ub418\uc5c8\uc2b5\ub2c8\ub2e4"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "OpenZWave Supervisor \uc560\ub4dc\uc628\uc744 \uc0ac\uc6a9\ud558\uae30"
|
||||
},
|
||||
"description": "OpenZWave Supervisor \uc560\ub4dc\uc628\uc744 \uc0ac\uc6a9\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?",
|
||||
"title": "\uc5f0\uacb0 \ubc29\ubc95 \uc120\ud0dd\ud558\uae30"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "\ub124\ud2b8\uc6cc\ud06c \ud0a4",
|
||||
"usb_path": "USB \uc7a5\uce58 \uacbd\ub85c"
|
||||
},
|
||||
"title": "OpenZWave \uc560\ub4dc\uc628\uc758 \uad6c\uc131\uc744 \uc785\ub825\ud574\uc8fc\uc138\uc694"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Apparat ass scho konfigur\u00e9iert",
|
||||
"already_in_progress": "Konfiguratioun's Oflaf ass schon am gaang",
|
||||
"mqtt_required": "MQTT Integratioun ass net ageriicht",
|
||||
"single_instance_allowed": "Scho konfigur\u00e9iert. N\u00ebmmen eng eenzeg Konfiguratioun ass m\u00e9iglech."
|
||||
},
|
||||
"step": {
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Netzwierk Schl\u00ebssel"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "Mislukt om OpenZWave add-on info te krijgen.",
|
||||
"addon_install_failed": "De installatie van de OpenZWave add-on is mislukt.",
|
||||
"addon_set_config_failed": "Mislukt om OpenZWave configuratie in te stellen.",
|
||||
"already_configured": "Apparaat is al geconfigureerd",
|
||||
"already_in_progress": "De configuratiestroom is al aan de gang",
|
||||
"mqtt_required": "De MQTT-integratie is niet ingesteld",
|
||||
"single_instance_allowed": "Al geconfigureerd. Slechts \u00e9\u00e9n configuratie mogelijk."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "Het starten van de OpenZWave-add-on is mislukt. Controleer de configuratie."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Wacht even terwijl de installatie van de OpenZWave add-on wordt voltooid. Dit kan enkele minuten duren."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "OpenZWave integratie instellen met de OpenZWave add-on"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "De OpenZWave add-on installatie is gestart"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Gebruik de OpenZWave Supervisor add-on"
|
||||
},
|
||||
"description": "Wilt u de OpenZWave Supervisor add-on gebruiken?",
|
||||
"title": "Selecteer een verbindingsmethode"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Netwerksleutel",
|
||||
"usb_path": "USB-apparaatpad"
|
||||
},
|
||||
"title": "Voer de OpenZWave add-on configuratie in"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "Kunne ikke hente informasjon om OpenZWave-tillegg",
|
||||
"addon_install_failed": "Kunne ikke installere OpenZWave-tillegg",
|
||||
"addon_set_config_failed": "Kunne ikke angi OpenZWave-konfigurasjon",
|
||||
"already_configured": "Enheten er allerede konfigurert",
|
||||
"already_in_progress": "Konfigurasjonsflyten p\u00e5g\u00e5r allerede",
|
||||
"mqtt_required": "MQTT-integrasjonen er ikke satt opp",
|
||||
"single_instance_allowed": "Allerede konfigurert. Bare \u00e9n enkelt konfigurasjon er mulig."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "Kunne ikke starte OpenZWave-tillegg. Sjekk konfigurasjonen."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Vent mens installasjonen av OpenZWave-tillegg er ferdig. Dette kan ta flere minutter."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Sett opp OpenZWave-integrasjon med OpenZWave-tillegg"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "Installasjonen av OpenZWave-tillegg har startet"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Bruk OpenZWave Supervisor-tillegg"
|
||||
},
|
||||
"description": "\u00d8nsker du \u00e5 bruke OpenZWave Supervisor-tillegg?",
|
||||
"title": "Velg tilkoblingsmetode"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Nettverksn\u00f8kkel",
|
||||
"usb_path": "USB enhetsbane"
|
||||
},
|
||||
"title": "Angi konfigurasjon for OpenZWave-tillegg"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "Nie uda\u0142o si\u0119 pobra\u0107 informacji o dodatku OpenZWave",
|
||||
"addon_install_failed": "Nie uda\u0142o si\u0119 zainstalowa\u0107 dodatku OpenZWave",
|
||||
"addon_set_config_failed": "Nie uda\u0142o si\u0119 ustawi\u0107 konfiguracji OpenZWave",
|
||||
"already_configured": "Urz\u0105dzenie jest ju\u017c skonfigurowane",
|
||||
"already_in_progress": "Konfiguracja jest ju\u017c w toku",
|
||||
"mqtt_required": "Integracja MQTT nie jest skonfigurowana",
|
||||
"single_instance_allowed": "Ju\u017c skonfigurowano. Mo\u017cliwa jest tylko jedna konfiguracja."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "Nie uda\u0142o si\u0119 uruchomi\u0107 dodatku OpenZWave. Sprawd\u017a konfiguracj\u0119."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Poczekaj, a\u017c zako\u0144czy si\u0119 instalacja dodatku OpenZWave. Mo\u017ce to potrwa\u0107 kilka minut."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Konfiguracja integracji OpenZWave z dodatkiem OpenZWave"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "Rozpocz\u0119\u0142a si\u0119 instalacja dodatku OpenZWave"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "U\u017cyj dodatku OpenZWave Supervisor"
|
||||
},
|
||||
"description": "Czy chcesz u\u017cy\u0107 dodatku OpenZWave Supervisor?",
|
||||
"title": "Wybierz metod\u0119 po\u0142\u0105czenia"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Klucz sieci",
|
||||
"usb_path": "\u015acie\u017cka urz\u0105dzenia USB"
|
||||
},
|
||||
"title": "Wprowad\u017a konfiguracj\u0119 dodatku OpenZWave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "Falha ao obter informa\u00e7\u00f5es do add-on OpenZWave.",
|
||||
"addon_install_failed": "Falha ao instalar o add-on OpenZWave.",
|
||||
"addon_set_config_failed": "Falha ao definir a configura\u00e7\u00e3o do OpenZWave.",
|
||||
"already_configured": "Dispositivo j\u00e1 est\u00e1 configurado",
|
||||
"already_in_progress": "O fluxo de configura\u00e7\u00e3o j\u00e1 est\u00e1 em andamento",
|
||||
"mqtt_required": "A integra\u00e7\u00e3o do MQTT n\u00e3o est\u00e1 configurada",
|
||||
"single_instance_allowed": "J\u00e1 configurado. Apenas uma configura\u00e7\u00e3o \u00e9 poss\u00edvel."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "Falha ao iniciar o add-on OpenZWave. Verifique a configura\u00e7\u00e3o."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Aguarde enquanto a instala\u00e7\u00e3o do add-on OpenZWave termina. Isso pode levar v\u00e1rios minutos."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Configure a integra\u00e7\u00e3o do OpenZWave com o add-on OpenZWave"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "A instala\u00e7\u00e3o do add-on OpenZWave foi iniciada"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Use o add-on OpenZWave Supervisor"
|
||||
},
|
||||
"description": "Deseja usar o add-on OpenZWave Supervisor?",
|
||||
"title": "Selecione o m\u00e9todo de conex\u00e3o"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "Chave de rede",
|
||||
"usb_path": "Caminho do Dispositivo USB"
|
||||
},
|
||||
"title": "Digite a configura\u00e7\u00e3o do add-on OpenZWave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "O dispositivo j\u00e1 est\u00e1 configurado",
|
||||
"already_in_progress": "O processo de configura\u00e7\u00e3o j\u00e1 est\u00e1 a decorrer",
|
||||
"single_instance_allowed": "J\u00e1 configurado. Apenas uma \u00fanica configura\u00e7\u00e3o \u00e9 poss\u00edvel."
|
||||
},
|
||||
"step": {
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"usb_path": "Caminho do Dispositivo USB"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 OpenZWave.",
|
||||
"addon_install_failed": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c OpenZWave.",
|
||||
"addon_set_config_failed": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e OpenZWave.",
|
||||
"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.",
|
||||
"already_in_progress": "\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f.",
|
||||
"mqtt_required": "\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f MQTT \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430.",
|
||||
"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": {
|
||||
"addon_start_failed": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c OpenZWave. \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "\u041f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435, \u043f\u043e\u043a\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f OpenZWave. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043d\u044f\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0438\u043d\u0443\u0442."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f OpenZWave"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "\u041d\u0430\u0447\u0430\u043b\u0430\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f OpenZWave"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 Supervisor OpenZWave"
|
||||
},
|
||||
"description": "\u0412\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 Supervisor OpenZWave?",
|
||||
"title": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "\u041a\u043b\u044e\u0447 \u0441\u0435\u0442\u0438",
|
||||
"usb_path": "\u041f\u0443\u0442\u044c \u043a USB-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0443"
|
||||
},
|
||||
"title": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f OpenZWave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_in_progress": "Konfigur\u00e1cia u\u017e prebieha"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Naprava je \u017ee name\u0161\u010dena",
|
||||
"already_in_progress": "Name\u0161\u010danje se \u017ee izvaja",
|
||||
"mqtt_required": "Integracija MQTT ni nastavljena"
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Po\u010dakajte, da se namestitev dodatka OpenZWave zaklju\u010di. To lahko traja ve\u010d minut."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Namestite OpenZWave integracijo z OpenZWave dodatkom."
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "Namestitev dodatka OpenZWave se je za\u010dela"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"title": "Izberite na\u010din povezave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "OpenZWave eklenti bilgileri al\u0131namad\u0131.",
|
||||
"addon_install_failed": "OpenZWave eklentisi y\u00fcklenemedi.",
|
||||
"addon_set_config_failed": "OpenZWave yap\u0131land\u0131rmas\u0131 ayarlanamad\u0131.",
|
||||
"already_configured": "Cihaz zaten yap\u0131land\u0131r\u0131lm\u0131\u015f",
|
||||
"already_in_progress": "Yap\u0131land\u0131rma ak\u0131\u015f\u0131 zaten devam ediyor",
|
||||
"mqtt_required": "MQTT entegrasyonu kurulmam\u0131\u015f",
|
||||
"single_instance_allowed": "Zaten yap\u0131land\u0131r\u0131lm\u0131\u015f. Yaln\u0131zca tek bir konfig\u00fcrasyon m\u00fcmk\u00fcnd\u00fcr."
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "OpenZWave eklentisi ba\u015flat\u0131lamad\u0131. Yap\u0131land\u0131rmay\u0131 kontrol edin."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "OpenZWave eklenti kurulumu bitene kadar l\u00fctfen bekleyin. Bu birka\u00e7 dakika s\u00fcrebilir."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "OpenZWave eklentisi ile OpenZWave entegrasyonunu kurun"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "OpenZWave eklenti kurulumu ba\u015flad\u0131"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "OpenZWave Supervisor eklentisini kullan\u0131n"
|
||||
},
|
||||
"description": "OpenZWave Supervisor eklentisini kullanmak istiyor musunuz?",
|
||||
"title": "Ba\u011flant\u0131 y\u00f6ntemini se\u00e7in"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "A\u011f Anahtar\u0131",
|
||||
"usb_path": "USB Cihaz Yolu"
|
||||
},
|
||||
"title": "OpenZWave eklenti yap\u0131land\u0131rmas\u0131n\u0131 girin"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f OpenZWave.",
|
||||
"addon_install_failed": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 OpenZWave.",
|
||||
"addon_set_config_failed": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044e OpenZWave.",
|
||||
"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.",
|
||||
"already_in_progress": "\u041f\u0440\u043e\u0446\u0435\u0441 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0436\u0435 \u0442\u0440\u0438\u0432\u0430\u0454.",
|
||||
"mqtt_required": "\u0406\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0456\u044f MQTT \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0430.",
|
||||
"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": {
|
||||
"addon_start_failed": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 OpenZWave. \u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044e."
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "\u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u043f\u043e\u043a\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c\u0441\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f OpenZWave. \u0426\u0435 \u043c\u043e\u0436\u0435 \u0437\u0430\u0439\u043d\u044f\u0442\u0438 \u043a\u0456\u043b\u044c\u043a\u0430 \u0445\u0432\u0438\u043b\u0438\u043d."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0439\u0442\u0435 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f OpenZWave"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "\u0420\u043e\u0437\u043f\u043e\u0447\u0430\u0442\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f Open'Wave"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u0434\u043e\u0434\u0430\u0442\u043e\u043a Supervisor OpenZWave"
|
||||
},
|
||||
"description": "\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0434\u043e\u0434\u0430\u0442\u043e\u043a Supervisor OpenZWave?",
|
||||
"title": "\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0441\u043f\u043e\u0441\u0456\u0431 \u043f\u0456\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044f"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "\u041a\u043b\u044e\u0447 \u043c\u0435\u0440\u0435\u0436\u0456",
|
||||
"usb_path": "\u0428\u043b\u044f\u0445 \u0434\u043e USB-\u043f\u0440\u0438\u0441\u0442\u0440\u043e\u044e"
|
||||
},
|
||||
"title": "\u0412\u0432\u0435\u0434\u0456\u0442\u044c \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 Open'Wave"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"mqtt_required": "\u672a\u8bbe\u7f6e MQTT \u96c6\u6210"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_info_failed": "\u53d6\u5f97 OpenZWave \u9644\u52a0\u5143\u4ef6\u8cc7\u8a0a\u5931\u6557\u3002",
|
||||
"addon_install_failed": "OpenZWave \u9644\u52a0\u5143\u4ef6\u5b89\u88dd\u5931\u6557\u3002",
|
||||
"addon_set_config_failed": "OpenZWave a\u9644\u52a0\u5143\u4ef6\u8a2d\u5b9a\u5931\u6557\u3002",
|
||||
"already_configured": "\u88dd\u7f6e\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210",
|
||||
"already_in_progress": "\u8a2d\u5b9a\u5df2\u7d93\u9032\u884c\u4e2d",
|
||||
"mqtt_required": "MQTT \u6574\u5408\u5c1a\u672a\u8a2d\u5b9a",
|
||||
"single_instance_allowed": "\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210\u3001\u50c5\u80fd\u8a2d\u5b9a\u4e00\u7d44\u88dd\u7f6e\u3002"
|
||||
},
|
||||
"error": {
|
||||
"addon_start_failed": "OpenZWave \u9644\u52a0\u5143\u4ef6\u555f\u52d5\u5931\u6557\uff0c\u8acb\u6aa2\u67e5\u8a2d\u5b9a\u3002"
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "\u8acb\u7a0d\u7b49 OpenZWave \u9644\u52a0\u5143\u4ef6\u5b89\u88dd\u5b8c\u6210\uff0c\u53ef\u80fd\u6703\u9700\u8981\u5e7e\u5206\u9418\u3002"
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "\u4ee5 OpenZWave \u9644\u52a0\u5143\u4ef6\u8a2d\u5b9a OpenZwave \u6574\u5408"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "OpenZWave \u9644\u52a0\u5143\u4ef6\u5b89\u88dd\u5df2\u555f\u52d5"
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "\u4f7f\u7528 OpenZWave Supervisor \u9644\u52a0\u5143\u4ef6"
|
||||
},
|
||||
"description": "\u662f\u5426\u8981\u4f7f\u7528 OpenZWave Supervisor \u9644\u52a0\u5143\u4ef6\uff1f",
|
||||
"title": "\u9078\u64c7\u9023\u7dda\u985e\u5225"
|
||||
},
|
||||
"start_addon": {
|
||||
"data": {
|
||||
"network_key": "\u7db2\u8def\u91d1\u9470",
|
||||
"usb_path": "USB \u88dd\u7f6e\u8def\u5f91"
|
||||
},
|
||||
"title": "\u8acb\u8f38\u5165 OpenZWave \u9644\u52a0\u5143\u4ef6\u8a2d\u5b9a\u3002"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,493 +0,0 @@
|
||||
"""Web socket API for OpenZWave."""
|
||||
from openzwavemqtt.const import (
|
||||
ATTR_CODE_SLOT,
|
||||
ATTR_LABEL,
|
||||
ATTR_POSITION,
|
||||
ATTR_VALUE,
|
||||
EVENT_NODE_ADDED,
|
||||
EVENT_NODE_CHANGED,
|
||||
)
|
||||
from openzwavemqtt.exceptions import NotFoundError, NotSupportedError
|
||||
from openzwavemqtt.util.lock import clear_usercode, get_code_slots, set_usercode
|
||||
from openzwavemqtt.util.node import (
|
||||
get_config_parameters,
|
||||
get_node_from_manager,
|
||||
set_config_parameter,
|
||||
)
|
||||
import voluptuous as vol
|
||||
import voluptuous_serialize
|
||||
|
||||
from homeassistant.components import websocket_api
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
||||
from .const import ATTR_CONFIG_PARAMETER, ATTR_CONFIG_VALUE, DOMAIN, MANAGER
|
||||
from .lock import ATTR_USERCODE
|
||||
|
||||
DRY_RUN = "dry_run"
|
||||
TYPE = "type"
|
||||
ID = "id"
|
||||
OZW_INSTANCE = "ozw_instance"
|
||||
NODE_ID = "node_id"
|
||||
PARAMETER = ATTR_CONFIG_PARAMETER
|
||||
VALUE = ATTR_CONFIG_VALUE
|
||||
SCHEMA = "schema"
|
||||
|
||||
ATTR_NODE_QUERY_STAGE = "node_query_stage"
|
||||
ATTR_IS_ZWAVE_PLUS = "is_zwave_plus"
|
||||
ATTR_IS_AWAKE = "is_awake"
|
||||
ATTR_IS_FAILED = "is_failed"
|
||||
ATTR_NODE_BAUD_RATE = "node_baud_rate"
|
||||
ATTR_IS_BEAMING = "is_beaming"
|
||||
ATTR_IS_FLIRS = "is_flirs"
|
||||
ATTR_IS_ROUTING = "is_routing"
|
||||
ATTR_IS_SECURITYV1 = "is_securityv1"
|
||||
ATTR_NODE_BASIC_STRING = "node_basic_string"
|
||||
ATTR_NODE_GENERIC_STRING = "node_generic_string"
|
||||
ATTR_NODE_SPECIFIC_STRING = "node_specific_string"
|
||||
ATTR_NODE_MANUFACTURER_NAME = "node_manufacturer_name"
|
||||
ATTR_NODE_PRODUCT_NAME = "node_product_name"
|
||||
ATTR_NEIGHBORS = "neighbors"
|
||||
|
||||
|
||||
@callback
|
||||
def async_register_api(hass):
|
||||
"""Register all of our api endpoints."""
|
||||
websocket_api.async_register_command(hass, websocket_get_instances)
|
||||
websocket_api.async_register_command(hass, websocket_get_nodes)
|
||||
websocket_api.async_register_command(hass, websocket_network_status)
|
||||
websocket_api.async_register_command(hass, websocket_network_statistics)
|
||||
websocket_api.async_register_command(hass, websocket_node_metadata)
|
||||
websocket_api.async_register_command(hass, websocket_node_status)
|
||||
websocket_api.async_register_command(hass, websocket_node_statistics)
|
||||
websocket_api.async_register_command(hass, websocket_refresh_node_info)
|
||||
websocket_api.async_register_command(hass, websocket_get_config_parameters)
|
||||
websocket_api.async_register_command(hass, websocket_set_config_parameter)
|
||||
websocket_api.async_register_command(hass, websocket_set_usercode)
|
||||
websocket_api.async_register_command(hass, websocket_clear_usercode)
|
||||
websocket_api.async_register_command(hass, websocket_get_code_slots)
|
||||
|
||||
|
||||
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])
|
||||
|
||||
|
||||
def _get_config_params(node, *args):
|
||||
raw_values = get_config_parameters(node)
|
||||
config_params = []
|
||||
|
||||
for param in raw_values:
|
||||
schema = {}
|
||||
|
||||
if param["type"] in ("Byte", "Int", "Short"):
|
||||
schema = vol.Schema(
|
||||
{
|
||||
vol.Required(param["label"], default=param["value"]): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=param["min"], max=param["max"])
|
||||
)
|
||||
}
|
||||
)
|
||||
data = {param["label"]: param["value"]}
|
||||
|
||||
if param["type"] == "List":
|
||||
|
||||
for options in param["options"]:
|
||||
if options["Label"] == param["value"]:
|
||||
selected = options
|
||||
break
|
||||
|
||||
schema = vol.Schema(
|
||||
{
|
||||
vol.Required(param["label"],): vol.In(
|
||||
{
|
||||
option["Value"]: option["Label"]
|
||||
for option in param["options"]
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
data = {param["label"]: selected["Value"]}
|
||||
|
||||
config_params.append(
|
||||
{
|
||||
"type": param["type"],
|
||||
"label": param["label"],
|
||||
"parameter": param["parameter"],
|
||||
"help": param["help"],
|
||||
"value": param["value"],
|
||||
"schema": voluptuous_serialize.convert(
|
||||
schema, custom_serializer=cv.custom_serializer
|
||||
),
|
||||
"data": data,
|
||||
}
|
||||
)
|
||||
|
||||
return config_params
|
||||
|
||||
|
||||
@websocket_api.websocket_command({vol.Required(TYPE): "ozw/get_instances"})
|
||||
def websocket_get_instances(hass, connection, msg):
|
||||
"""Get a list of OZW instances."""
|
||||
manager = hass.data[DOMAIN][MANAGER]
|
||||
instances = []
|
||||
|
||||
for instance in manager.collections["instance"]:
|
||||
instances.append(dict(instance.get_status().data, ozw_instance=instance.id))
|
||||
|
||||
connection.send_result(
|
||||
msg[ID],
|
||||
instances,
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/get_nodes",
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
def websocket_get_nodes(hass, connection, msg):
|
||||
"""Get a list of nodes for an OZW instance."""
|
||||
manager = hass.data[DOMAIN][MANAGER]
|
||||
nodes = []
|
||||
|
||||
for node in manager.get_instance(msg[OZW_INSTANCE]).collections["node"]:
|
||||
nodes.append(
|
||||
{
|
||||
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],
|
||||
}
|
||||
)
|
||||
|
||||
connection.send_result(
|
||||
msg[ID],
|
||||
nodes,
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/set_usercode",
|
||||
vol.Required(NODE_ID): vol.Coerce(int),
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
vol.Required(ATTR_CODE_SLOT): vol.Coerce(int),
|
||||
vol.Required(ATTR_USERCODE): cv.string,
|
||||
}
|
||||
)
|
||||
def websocket_set_usercode(hass, connection, msg):
|
||||
"""Set a usercode to a node code slot."""
|
||||
_call_util_function(
|
||||
hass, connection, msg, False, set_usercode, msg[ATTR_CODE_SLOT], ATTR_USERCODE
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/clear_usercode",
|
||||
vol.Required(NODE_ID): vol.Coerce(int),
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
vol.Required(ATTR_CODE_SLOT): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
def websocket_clear_usercode(hass, connection, msg):
|
||||
"""Clear a node code slot."""
|
||||
_call_util_function(
|
||||
hass, connection, msg, False, clear_usercode, msg[ATTR_CODE_SLOT]
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/get_code_slots",
|
||||
vol.Required(NODE_ID): vol.Coerce(int),
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
def websocket_get_code_slots(hass, connection, msg):
|
||||
"""Get status of node's code slots."""
|
||||
_call_util_function(hass, connection, msg, True, get_code_slots)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/get_config_parameters",
|
||||
vol.Required(NODE_ID): vol.Coerce(int),
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
def websocket_get_config_parameters(hass, connection, msg):
|
||||
"""Get a list of configuration parameters for an OZW node instance."""
|
||||
_call_util_function(hass, connection, msg, True, _get_config_params)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/set_config_parameter",
|
||||
vol.Required(NODE_ID): vol.Coerce(int),
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
vol.Required(PARAMETER): vol.Coerce(int),
|
||||
vol.Required(VALUE): vol.Any(
|
||||
vol.All(
|
||||
cv.ensure_list,
|
||||
[
|
||||
vol.All(
|
||||
{
|
||||
vol.Exclusive(ATTR_LABEL, "bit"): cv.string,
|
||||
vol.Exclusive(ATTR_POSITION, "bit"): vol.Coerce(int),
|
||||
vol.Required(ATTR_VALUE): bool,
|
||||
},
|
||||
cv.has_at_least_one_key(ATTR_LABEL, ATTR_POSITION),
|
||||
)
|
||||
],
|
||||
),
|
||||
vol.Coerce(int),
|
||||
bool,
|
||||
cv.string,
|
||||
),
|
||||
}
|
||||
)
|
||||
def websocket_set_config_parameter(hass, connection, msg):
|
||||
"""Set a config parameter to a node."""
|
||||
_call_util_function(
|
||||
hass, connection, msg, True, set_config_parameter, msg[PARAMETER], msg[VALUE]
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/network_status",
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
def websocket_network_status(hass, connection, msg):
|
||||
"""Get Z-Wave network status."""
|
||||
|
||||
manager = hass.data[DOMAIN][MANAGER]
|
||||
status = manager.get_instance(msg[OZW_INSTANCE]).get_status().data
|
||||
connection.send_result(
|
||||
msg[ID],
|
||||
dict(status, ozw_instance=msg[OZW_INSTANCE]),
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/network_statistics",
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
def websocket_network_statistics(hass, connection, msg):
|
||||
"""Get Z-Wave network statistics."""
|
||||
|
||||
manager = hass.data[DOMAIN][MANAGER]
|
||||
statistics = manager.get_instance(msg[OZW_INSTANCE]).get_statistics().data
|
||||
node_count = len(
|
||||
manager.get_instance(msg[OZW_INSTANCE]).collections["node"].collection
|
||||
)
|
||||
connection.send_result(
|
||||
msg[ID],
|
||||
dict(statistics, ozw_instance=msg[OZW_INSTANCE], node_count=node_count),
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/node_status",
|
||||
vol.Required(NODE_ID): vol.Coerce(int),
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
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],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/node_metadata",
|
||||
vol.Required(NODE_ID): vol.Coerce(int),
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
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],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/node_statistics",
|
||||
vol.Required(NODE_ID): vol.Coerce(int),
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
def websocket_node_statistics(hass, connection, msg):
|
||||
"""Get the statistics for a Z-Wave node."""
|
||||
manager = hass.data[DOMAIN][MANAGER]
|
||||
stats = (
|
||||
manager.get_instance(msg[OZW_INSTANCE]).get_node(msg[NODE_ID]).get_statistics()
|
||||
)
|
||||
connection.send_result(
|
||||
msg[ID],
|
||||
{
|
||||
NODE_ID: msg[NODE_ID],
|
||||
"send_count": stats.send_count,
|
||||
"sent_failed": stats.sent_failed,
|
||||
"retries": stats.retries,
|
||||
"last_request_rtt": stats.last_request_rtt,
|
||||
"last_response_rtt": stats.last_response_rtt,
|
||||
"average_request_rtt": stats.average_request_rtt,
|
||||
"average_response_rtt": stats.average_response_rtt,
|
||||
"received_packets": stats.received_packets,
|
||||
"received_dup_packets": stats.received_dup_packets,
|
||||
"received_unsolicited": stats.received_unsolicited,
|
||||
OZW_INSTANCE: msg[OZW_INSTANCE],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required(TYPE): "ozw/refresh_node_info",
|
||||
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int),
|
||||
vol.Required(NODE_ID): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
def websocket_refresh_node_info(hass, connection, msg):
|
||||
"""Tell OpenZWave to re-interview a node."""
|
||||
|
||||
manager = hass.data[DOMAIN][MANAGER]
|
||||
options = manager.options
|
||||
|
||||
@callback
|
||||
def forward_node(node):
|
||||
"""Forward node events to websocket."""
|
||||
if node.node_id != msg[NODE_ID]:
|
||||
return
|
||||
|
||||
forward_data = {
|
||||
"type": "node_updated",
|
||||
ATTR_NODE_QUERY_STAGE: node.node_query_stage,
|
||||
}
|
||||
connection.send_message(websocket_api.event_message(msg["id"], forward_data))
|
||||
|
||||
@callback
|
||||
def async_cleanup() -> None:
|
||||
"""Remove signal listeners."""
|
||||
for unsub in unsubs:
|
||||
unsub()
|
||||
|
||||
connection.subscriptions[msg["id"]] = async_cleanup
|
||||
unsubs = [
|
||||
options.listen(EVENT_NODE_CHANGED, forward_node),
|
||||
options.listen(EVENT_NODE_ADDED, forward_node),
|
||||
]
|
||||
|
||||
instance = manager.get_instance(msg[OZW_INSTANCE])
|
||||
instance.refresh_node(msg[NODE_ID])
|
||||
connection.send_result(msg["id"])
|
@ -245,7 +245,6 @@ FLOWS = [
|
||||
"overkiz",
|
||||
"ovo_energy",
|
||||
"owntracks",
|
||||
"ozw",
|
||||
"p1_monitor",
|
||||
"panasonic_viera",
|
||||
"philips_js",
|
||||
|
9
mypy.ini
9
mypy.ini
@ -2612,15 +2612,6 @@ ignore_errors = true
|
||||
[mypy-homeassistant.components.onvif.sensor]
|
||||
ignore_errors = true
|
||||
|
||||
[mypy-homeassistant.components.ozw]
|
||||
ignore_errors = true
|
||||
|
||||
[mypy-homeassistant.components.ozw.climate]
|
||||
ignore_errors = true
|
||||
|
||||
[mypy-homeassistant.components.ozw.entity]
|
||||
ignore_errors = true
|
||||
|
||||
[mypy-homeassistant.components.philips_js]
|
||||
ignore_errors = true
|
||||
|
||||
|
@ -1905,9 +1905,6 @@ python-mystrom==1.1.2
|
||||
# homeassistant.components.nest
|
||||
python-nest==4.2.0
|
||||
|
||||
# homeassistant.components.ozw
|
||||
python-openzwave-mqtt[mqtt-client]==1.4.0
|
||||
|
||||
# homeassistant.components.picnic
|
||||
python-picnic-api==1.1.0
|
||||
|
||||
|
@ -1226,9 +1226,6 @@ python-miio==0.5.11
|
||||
# homeassistant.components.nest
|
||||
python-nest==4.2.0
|
||||
|
||||
# homeassistant.components.ozw
|
||||
python-openzwave-mqtt[mqtt-client]==1.4.0
|
||||
|
||||
# homeassistant.components.picnic
|
||||
python-picnic-api==1.1.0
|
||||
|
||||
|
@ -112,9 +112,6 @@ IGNORED_MODULES: Final[list[str]] = [
|
||||
"homeassistant.components.onvif.models",
|
||||
"homeassistant.components.onvif.parsers",
|
||||
"homeassistant.components.onvif.sensor",
|
||||
"homeassistant.components.ozw",
|
||||
"homeassistant.components.ozw.climate",
|
||||
"homeassistant.components.ozw.entity",
|
||||
"homeassistant.components.philips_js",
|
||||
"homeassistant.components.philips_js.config_flow",
|
||||
"homeassistant.components.philips_js.device_trigger",
|
||||
|
@ -1 +0,0 @@
|
||||
"""Tests for the OZW integration."""
|
@ -1,62 +0,0 @@
|
||||
"""Helpers for tests."""
|
||||
import json
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.ozw.const import DOMAIN
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def setup_ozw(hass, entry=None, fixture=None):
|
||||
"""Set up OZW and load a dump."""
|
||||
mqtt_entry = MockConfigEntry(
|
||||
domain="mqtt", state=config_entries.ConfigEntryState.LOADED
|
||||
)
|
||||
mqtt_entry.add_to_hass(hass)
|
||||
|
||||
if entry is None:
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="Z-Wave",
|
||||
)
|
||||
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
with patch("homeassistant.components.mqtt.async_subscribe") as mock_subscribe:
|
||||
mock_subscribe.return_value = Mock()
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert "ozw" in hass.config.components
|
||||
assert len(mock_subscribe.mock_calls) == 1
|
||||
receive_message = mock_subscribe.mock_calls[0][1][2]
|
||||
|
||||
if fixture is not None:
|
||||
for line in fixture.split("\n"):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
topic, payload = line.split(",", 1)
|
||||
receive_message(Mock(topic=topic, payload=payload))
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
return receive_message
|
||||
|
||||
|
||||
class MQTTMessage:
|
||||
"""Represent a mock MQTT message."""
|
||||
|
||||
def __init__(self, topic, payload):
|
||||
"""Set up message."""
|
||||
self.topic = topic
|
||||
self.payload = payload
|
||||
|
||||
def decode(self):
|
||||
"""Decode message payload from a string to a json dict."""
|
||||
self.payload = json.loads(self.payload)
|
||||
|
||||
def encode(self):
|
||||
"""Encode message payload into a string."""
|
||||
self.payload = json.dumps(self.payload)
|
@ -1,280 +0,0 @@
|
||||
"""Helpers for tests."""
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
|
||||
from .common import MQTTMessage
|
||||
|
||||
from tests.common import MockConfigEntry, load_fixture
|
||||
from tests.components.light.conftest import mock_light_profiles # noqa: F401
|
||||
|
||||
|
||||
@pytest.fixture(name="generic_data", scope="session")
|
||||
def generic_data_fixture():
|
||||
"""Load generic MQTT data and return it."""
|
||||
return load_fixture("ozw/generic_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="migration_data", scope="session")
|
||||
def migration_data_fixture():
|
||||
"""Load migration MQTT data and return it."""
|
||||
return load_fixture("ozw/migration_fixture.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="fan_data", scope="session")
|
||||
def fan_data_fixture():
|
||||
"""Load fan MQTT data and return it."""
|
||||
return load_fixture("ozw/fan_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="light_data", scope="session")
|
||||
def light_data_fixture():
|
||||
"""Load light dimmer MQTT data and return it."""
|
||||
return load_fixture("ozw/light_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="light_new_ozw_data", scope="session")
|
||||
def light_new_ozw_data_fixture():
|
||||
"""Load light dimmer MQTT data and return it."""
|
||||
return load_fixture("ozw/light_new_ozw_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="light_no_ww_data", scope="session")
|
||||
def light_no_ww_data_fixture():
|
||||
"""Load light dimmer MQTT data and return it."""
|
||||
return load_fixture("ozw/light_no_ww_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="light_no_cw_data", scope="session")
|
||||
def light_no_cw_data_fixture():
|
||||
"""Load light dimmer MQTT data and return it."""
|
||||
return load_fixture("ozw/light_no_cw_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="light_wc_data", scope="session")
|
||||
def light_wc_only_data_fixture():
|
||||
"""Load light dimmer MQTT data and return it."""
|
||||
return load_fixture("ozw/light_wc_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="cover_data", scope="session")
|
||||
def cover_data_fixture():
|
||||
"""Load cover MQTT data and return it."""
|
||||
return load_fixture("ozw/cover_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="cover_gdo_data", scope="session")
|
||||
def cover_gdo_data_fixture():
|
||||
"""Load cover_gdo MQTT data and return it."""
|
||||
return load_fixture("ozw/cover_gdo_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="climate_data", scope="session")
|
||||
def climate_data_fixture():
|
||||
"""Load climate MQTT data and return it."""
|
||||
return load_fixture("ozw/climate_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="lock_data", scope="session")
|
||||
def lock_data_fixture():
|
||||
"""Load lock MQTT data and return it."""
|
||||
return load_fixture("ozw/lock_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="string_sensor_data", scope="session")
|
||||
def string_sensor_fixture():
|
||||
"""Load string sensor MQTT data and return it."""
|
||||
return load_fixture("ozw/sensor_string_value_network_dump.csv")
|
||||
|
||||
|
||||
@pytest.fixture(name="sent_messages")
|
||||
def sent_messages_fixture():
|
||||
"""Fixture to capture sent messages."""
|
||||
sent_messages = []
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.mqtt.async_publish",
|
||||
side_effect=lambda hass, topic, payload: sent_messages.append(
|
||||
{"topic": topic, "payload": json.loads(payload)}
|
||||
),
|
||||
):
|
||||
yield sent_messages
|
||||
|
||||
|
||||
@pytest.fixture(name="fan_msg")
|
||||
async def fan_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a fan actuator message."""
|
||||
fan_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/fan.json")
|
||||
)
|
||||
message = MQTTMessage(topic=fan_json["topic"], payload=fan_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="light_msg")
|
||||
async def light_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a light actuator message."""
|
||||
light_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/light.json")
|
||||
)
|
||||
message = MQTTMessage(topic=light_json["topic"], payload=light_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="light_no_rgb_msg")
|
||||
async def light_no_rgb_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a light actuator message."""
|
||||
light_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/light_no_rgb.json")
|
||||
)
|
||||
message = MQTTMessage(topic=light_json["topic"], payload=light_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="light_rgb_msg")
|
||||
async def light_rgb_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a light actuator message."""
|
||||
light_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/light_rgb.json")
|
||||
)
|
||||
message = MQTTMessage(topic=light_json["topic"], payload=light_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="light_pure_rgb_msg")
|
||||
async def light_pure_rgb_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a pure rgb light actuator message."""
|
||||
light_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/light_pure_rgb.json")
|
||||
)
|
||||
message = MQTTMessage(topic=light_json["topic"], payload=light_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="switch_msg")
|
||||
async def switch_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a switch actuator message."""
|
||||
switch_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/switch.json")
|
||||
)
|
||||
message = MQTTMessage(topic=switch_json["topic"], payload=switch_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="sensor_msg")
|
||||
async def sensor_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a sensor change message."""
|
||||
sensor_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/sensor.json")
|
||||
)
|
||||
message = MQTTMessage(topic=sensor_json["topic"], payload=sensor_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="binary_sensor_msg")
|
||||
async def binary_sensor_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a binary_sensor change message."""
|
||||
sensor_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/binary_sensor.json")
|
||||
)
|
||||
message = MQTTMessage(topic=sensor_json["topic"], payload=sensor_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="binary_sensor_alt_msg")
|
||||
async def binary_sensor_alt_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a binary_sensor change message."""
|
||||
sensor_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/binary_sensor_alt.json")
|
||||
)
|
||||
message = MQTTMessage(topic=sensor_json["topic"], payload=sensor_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="cover_msg")
|
||||
async def cover_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a cover level change message."""
|
||||
sensor_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/cover.json")
|
||||
)
|
||||
message = MQTTMessage(topic=sensor_json["topic"], payload=sensor_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="cover_gdo_msg")
|
||||
async def cover_gdo_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a cover barrier state change message."""
|
||||
sensor_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/cover_gdo.json")
|
||||
)
|
||||
message = MQTTMessage(topic=sensor_json["topic"], payload=sensor_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="climate_msg")
|
||||
async def climate_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a climate mode change message."""
|
||||
sensor_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/climate.json")
|
||||
)
|
||||
message = MQTTMessage(topic=sensor_json["topic"], payload=sensor_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="lock_msg")
|
||||
async def lock_msg_fixture(hass):
|
||||
"""Return a mock MQTT msg with a lock actuator message."""
|
||||
lock_json = json.loads(
|
||||
await hass.async_add_executor_job(load_fixture, "ozw/lock.json")
|
||||
)
|
||||
message = MQTTMessage(topic=lock_json["topic"], payload=lock_json["payload"])
|
||||
message.encode()
|
||||
return message
|
||||
|
||||
|
||||
@pytest.fixture(name="stop_addon")
|
||||
def mock_install_addon():
|
||||
"""Mock stop add-on."""
|
||||
with patch("homeassistant.components.hassio.async_stop_addon") as stop_addon:
|
||||
yield stop_addon
|
||||
|
||||
|
||||
@pytest.fixture(name="uninstall_addon")
|
||||
def mock_uninstall_addon():
|
||||
"""Mock uninstall add-on."""
|
||||
with patch(
|
||||
"homeassistant.components.hassio.async_uninstall_addon"
|
||||
) as uninstall_addon:
|
||||
yield uninstall_addon
|
||||
|
||||
|
||||
@pytest.fixture(name="get_addon_discovery_info")
|
||||
def mock_get_addon_discovery_info():
|
||||
"""Mock get add-on discovery info."""
|
||||
with patch(
|
||||
"homeassistant.components.hassio.async_get_addon_discovery_info"
|
||||
) as get_addon_discovery_info:
|
||||
yield get_addon_discovery_info
|
||||
|
||||
|
||||
@pytest.fixture(name="mqtt")
|
||||
async def mock_mqtt_fixture(hass):
|
||||
"""Mock the MQTT integration."""
|
||||
mqtt_entry = MockConfigEntry(domain="mqtt", state=ConfigEntryState.LOADED)
|
||||
mqtt_entry.add_to_hass(hass)
|
||||
return mqtt_entry
|
@ -1,38 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/37/instance/1/commandclass/113/value/1970325463777300/",
|
||||
"payload": {
|
||||
"Label": "Home Security",
|
||||
"Value": {
|
||||
"List": [
|
||||
{
|
||||
"Value": 0,
|
||||
"Label": "Clear"
|
||||
},
|
||||
{
|
||||
"Value": 8,
|
||||
"Label": "Motion Detected at Unknown Location"
|
||||
}
|
||||
],
|
||||
"Selected": "Motion Detected at Unknown Location",
|
||||
"Selected_id": 8
|
||||
},
|
||||
"Units": "",
|
||||
"Min": 0,
|
||||
"Max": 0,
|
||||
"Type": "List",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_NOTIFICATION",
|
||||
"Index": 7,
|
||||
"Node": 37,
|
||||
"Genre": "User",
|
||||
"Help": "Home Security Alerts",
|
||||
"ValueIDKey": 1970325463777300,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"ValueSet": false,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Event": "valueAdded",
|
||||
"TimeStamp": 1579566891
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/37/instance/1/commandclass/48/value/625737744/",
|
||||
"payload": {
|
||||
"Label": "Sensor",
|
||||
"Value": true,
|
||||
"Units": "",
|
||||
"Min": 0,
|
||||
"Max": 0,
|
||||
"Type": "Bool",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_SENSOR_BINARY",
|
||||
"Index": 0,
|
||||
"Node": 37,
|
||||
"Genre": "User",
|
||||
"Help": "Binary Sensor State",
|
||||
"ValueIDKey": 625737744,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"ValueSet": false,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Event": "valueAdded",
|
||||
"TimeStamp": 1579566891
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/7/instance/1/commandclass/64/value/122683412/",
|
||||
"payload": {
|
||||
"Label": "Mode",
|
||||
"Value": {
|
||||
"List": [
|
||||
{
|
||||
"Value": 0,
|
||||
"Label": "Off"
|
||||
},
|
||||
{
|
||||
"Value": 1,
|
||||
"Label": "Heat"
|
||||
},
|
||||
{
|
||||
"Value": 2,
|
||||
"Label": "Cool"
|
||||
},
|
||||
{
|
||||
"Value": 3,
|
||||
"Label": "Auto"
|
||||
},
|
||||
{
|
||||
"Value": 11,
|
||||
"Label": "Heat Econ"
|
||||
},
|
||||
{
|
||||
"Value": 12,
|
||||
"Label": "Cool Econ"
|
||||
}
|
||||
],
|
||||
"Selected": "Auto",
|
||||
"Selected_id": 3
|
||||
},
|
||||
"Units": "",
|
||||
"Min": 0,
|
||||
"Max": 0,
|
||||
"Type": "List",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_THERMOSTAT_MODE",
|
||||
"Index": 0,
|
||||
"Node": 7,
|
||||
"Genre": "User",
|
||||
"Help": "Set the Thermostat Mode",
|
||||
"ValueIDKey": 122683412,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"ValueSet": false,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Event": "valueAdded",
|
||||
"TimeStamp": 1588264894
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -1,25 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/37/instance/1/commandclass/38/value/625573905/",
|
||||
"payload": {
|
||||
"Label": "Instance 1: Level",
|
||||
"Value": 0,
|
||||
"Units": "",
|
||||
"ValueSet": true,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Min": 0,
|
||||
"Max": 255,
|
||||
"Type": "Byte",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_SWITCH_MULTILEVEL",
|
||||
"Index": 0,
|
||||
"Node": 37,
|
||||
"Genre": "User",
|
||||
"Help": "The Current Level of the Device",
|
||||
"ValueIDKey": 625573905,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"Event": "valueChanged",
|
||||
"TimeStamp": 1593370642
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/6/instance/1/commandclass/102/value/281475083239444/",
|
||||
"payload": {
|
||||
"Label": "Barrier State",
|
||||
"Value": {
|
||||
"List": [
|
||||
{
|
||||
"Value": 0,
|
||||
"Label": "Closed"
|
||||
},
|
||||
{
|
||||
"Value": 1,
|
||||
"Label": "Closing"
|
||||
},
|
||||
{
|
||||
"Value": 2,
|
||||
"Label": "Stopped"
|
||||
},
|
||||
{
|
||||
"Value": 3,
|
||||
"Label": "Opening"
|
||||
},
|
||||
{
|
||||
"Value": 4,
|
||||
"Label": "Opened"
|
||||
},
|
||||
{
|
||||
"Value": 5,
|
||||
"Label": "Unknown"
|
||||
}
|
||||
],
|
||||
"Selected": "Closed",
|
||||
"Selected_id": 0
|
||||
},
|
||||
"Units": "",
|
||||
"ValueSet": true,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Min": 0,
|
||||
"Max": 0,
|
||||
"Type": "List",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_BARRIER_OPERATOR",
|
||||
"Index": 1,
|
||||
"Node": 6,
|
||||
"Genre": "User",
|
||||
"Help": "The Current State of the Barrier",
|
||||
"ValueIDKey": 281475083239444,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"Event": "valueChanged",
|
||||
"TimeStamp": 1593634453
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,25 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/10/instance/1/commandclass/38/value/172589073/",
|
||||
"payload": {
|
||||
"Label": "Level",
|
||||
"Value": 41,
|
||||
"Units": "",
|
||||
"ValueSet": false,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Min": 0,
|
||||
"Max": 255,
|
||||
"Type": "Byte",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_SWITCH_MULTILEVEL",
|
||||
"Index": 0,
|
||||
"Node": 10,
|
||||
"Genre": "User",
|
||||
"Help": "The Current Level of the Device",
|
||||
"ValueIDKey": 172589073,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"Event": "valueAdded",
|
||||
"TimeStamp": 1589997977
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
OpenZWave/1/status/,{ "OpenZWave_Version": "1.6.1123", "OZWDaemon_Version": "0.1.98", "QTOpenZWave_Version": "1.0.0", "QT_Version": "5.12.5", "Status": "driverAllNodesQueried", "TimeStamp": 1589998153, "ManufacturerSpecificDBReady": true, "homeID": 4188283268, "getControllerNodeId": 1, "getSUCNodeId": 1, "isPrimaryController": true, "isBridgeController": false, "hasExtendedTXStatistics": false, "getControllerLibraryVersion": "Z-Wave 4.54", "getControllerLibraryType": "Static Controller", "getControllerPath": "/dev/ttyACM0"}
|
||||
OpenZWave/1/node/10/,{ "NodeID": 10, "NodeQueryStage": "Complete", "isListening": true, "isFlirs": false, "isBeaming": true, "isRouting": true, "isSecurityv1": false, "isZWavePlus": true, "isNIFRecieved": true, "isAwake": true, "isFailed": false, "MetaData": { "OZWInfoURL": "http://www.openzwave.com/device-database/0063:3031:4944", "ZWAProductURL": "", "ProductPic": "images/ge/12724-dimmer.png", "Description": "Transform any home into a smart home with the GE Z-Wave Smart Fan Control. The in-wall fan control easily replaces any standard in-wall switch remotely controls a ceiling fan in your home and features a three-speed control system. Your home will be equipped with ultimate flexibility with the GE Z-Wave Smart Fan Control, capable of being used by itself or with up to four GE add-on switches. Screw terminal installation provides improved space efficiency when replacing existing switches and the integrated LED indicator light allows you to easily locate the switch in a dark room. The GE Z-Wave Smart Fan Control is compatible with any Z-Wave certified gateway, providing access to many popular home automation systems. Take control of your home lighting with GE Z-Wave Smart Lighting Controls!", "ProductManualURL": "https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2506/Binder2.pdf", "ProductPageURL": "http://www.ezzwave.com", "InclusionHelp": "1. Follow the instructions for your Z-Wave certified controller to include a device to the Z-Wave network. 2. Once the controller is ready to include your device, press and release the top or bottom of the smart fan control switch (rocker) to include it in the network. 3. Once your controller has confirmed the device has been included, refresh the Z-Wave network to optimize performance.", "ExclusionHelp": "1. Follow the instructions for your Z-Wave certified controller to exclude a device from the Z-Wave network. 2. Once the controller is ready to Exclude your device, press and release the top or bottom of the wireless smart switch (rocker) to exclude it from the network.", "ResetHelp": "1. Quickly press ON (Top) button three (3) times then immediately press the OFF (Bottom) button three (3) times. The LED will flash ON/OFF 5 times when completed successfully. Note: This should only be used in the event your network’s primary controller is missing or otherwise inoperable.", "WakeupHelp": "", "ProductSupportURL": "", "Frequency": "", "Name": "In-Wall Smart Fan Control" }, "Event": "nodeQueriesComplete", "TimeStamp": 1589998151, "NodeManufacturerName": "GE (Jasco Products)", "NodeProductName": "14287 Fan Control Switch", "NodeBasicString": "Routing Slave", "NodeBasic": 4, "NodeGenericString": "Multilevel Switch", "NodeGeneric": 17, "NodeSpecificString": "Fan Switch", "NodeSpecific": 8, "NodeManufacturerID": "0x0063", "NodeProductType": "0x4944", "NodeProductID": "0x3131", "NodeBaudRate": 100000, "NodeVersion": 4, "NodeGroups": 3, "NodeName": "", "NodeLocation": "", "NodeDeviceTypeString": "Fan Switch", "NodeDeviceType": 1024, "NodeRole": 5, "NodeRoleString": "Always On Slave", "NodePlusType": 0, "NodePlusTypeString": "Z-Wave+ node", "Neighbors": [ 1, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 29, 30, 32, 33 ]}
|
||||
OpenZWave/1/node/10/instance/1/,{ "Instance": 1, "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/38/,{ "Instance": 1, "CommandClassId": 38, "CommandClass": "COMMAND_CLASS_SWITCH_MULTILEVEL", "CommandClassVersion": 1, "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/38/value/172589073/,{ "Label": "Level", "Value": 41, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_SWITCH_MULTILEVEL", "Index": 0, "Node": 10, "Genre": "User", "Help": "The Current Level of the Device", "ValueIDKey": 172589073, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/38/value/281475149299736/,{ "Label": "Bright", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Button", "Instance": 1, "CommandClass": "COMMAND_CLASS_SWITCH_MULTILEVEL", "Index": 1, "Node": 10, "Genre": "User", "Help": "Increase the Brightness of the Device", "ValueIDKey": 281475149299736, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/38/value/562950126010392/,{ "Label": "Dim", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Button", "Instance": 1, "CommandClass": "COMMAND_CLASS_SWITCH_MULTILEVEL", "Index": 2, "Node": 10, "Genre": "User", "Help": "Decrease the Brightness of the Device", "ValueIDKey": 562950126010392, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/38/value/844425111109648/,{ "Label": "Ignore Start Level", "Value": true, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Bool", "Instance": 1, "CommandClass": "COMMAND_CLASS_SWITCH_MULTILEVEL", "Index": 3, "Node": 10, "Genre": "System", "Help": "Ignore the Start Level of the Device when increasing/decreasing brightness", "ValueIDKey": 844425111109648, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/38/value/1125900087820305/,{ "Label": "Start Level", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_SWITCH_MULTILEVEL", "Index": 4, "Node": 10, "Genre": "System", "Help": "Start Level when Changing the Brightness of a Device", "ValueIDKey": 1125900087820305, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/39/,{ "Instance": 1, "CommandClassId": 39, "CommandClass": "COMMAND_CLASS_SWITCH_ALL", "CommandClassVersion": 1, "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/39/value/180994068/,{ "Label": "Switch All", "Value": { "List": [ { "Value": 0, "Label": "Disabled" }, { "Value": 1, "Label": "Off Enabled" }, { "Value": 2, "Label": "On Enabled" }, { "Value": 255, "Label": "On and Off Enabled" } ], "Selected": "On and Off Enabled", "Selected_id": 255 }, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_SWITCH_ALL", "Index": 0, "Node": 10, "Genre": "System", "Help": "Switch All Devices On/Off", "ValueIDKey": 180994068, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/43/,{ "Instance": 1, "CommandClassId": 43, "CommandClass": "COMMAND_CLASS_SCENE_ACTIVATION", "CommandClassVersion": 1, "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/43/value/172670995/,{ "Label": "Scene", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -2147483648, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_SCENE_ACTIVATION", "Index": 0, "Node": 10, "Genre": "User", "Help": "", "ValueIDKey": 172670995, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/43/value/281475149381651/,{ "Label": "Duration", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -2147483648, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_SCENE_ACTIVATION", "Index": 1, "Node": 10, "Genre": "User", "Help": "", "ValueIDKey": 281475149381651, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/94/,{ "Instance": 1, "CommandClassId": 94, "CommandClass": "COMMAND_CLASS_ZWAVEPLUS_INFO", "CommandClassVersion": 1, "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/94/value/181895185/,{ "Label": "ZWave+ Version", "Value": 1, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_ZWAVEPLUS_INFO", "Index": 0, "Node": 10, "Genre": "System", "Help": "ZWave+ Version Supported on the Device", "ValueIDKey": 181895185, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/94/value/281475158605846/,{ "Label": "InstallerIcon", "Value": 1024, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 1, "CommandClass": "COMMAND_CLASS_ZWAVEPLUS_INFO", "Index": 1, "Node": 10, "Genre": "System", "Help": "Icon File to use for the Installer Application", "ValueIDKey": 281475158605846, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/94/value/562950135316502/,{ "Label": "UserIcon", "Value": 1024, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 1, "CommandClass": "COMMAND_CLASS_ZWAVEPLUS_INFO", "Index": 2, "Node": 10, "Genre": "System", "Help": "Icon File to use for the User Application", "ValueIDKey": 562950135316502, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/,{ "Instance": 1, "CommandClassId": 112, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "CommandClassVersion": 1, "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/844425108127764/,{ "Label": "LED Light", "Value": { "List": [ { "Value": 0, "Label": "LED on when light off" }, { "Value": 1, "Label": "LED on when light on" }, { "Value": 2, "Label": "LED always off" } ], "Selected": "LED on when light off", "Selected_id": 0 }, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 2, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 3, "Node": 10, "Genre": "Config", "Help": "Sets when the LED on the switch is lit.", "ValueIDKey": 844425108127764, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/1125900084838420/,{ "Label": "Invert Switch", "Value": { "List": [ { "Value": 0, "Label": "No" }, { "Value": 1, "Label": "Yes" } ], "Selected": "No", "Selected_id": 0 }, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 1, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 4, "Node": 10, "Genre": "Config", "Help": "Change the top of the switch to OFF and the bottom of the switch to ON, if the switch was installed upside down.", "ValueIDKey": 1125900084838420, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/1970325014970385/,{ "Label": "Z-Wave Command Dim Step", "Value": 1, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 1, "Max": 99, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 7, "Node": 10, "Genre": "Config", "Help": "Indicates how many levels the dimmer will change for each dimming step.", "ValueIDKey": 1970325014970385, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/2251799991681041/,{ "Label": "Z-Wave Command Dim Rate", "Value": 3, "Units": "x 10 milliseconds", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 1, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 8, "Node": 10, "Genre": "Config", "Help": "This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change.", "ValueIDKey": 2251799991681041, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/2533274968391697/,{ "Label": "Local Control Dim Step", "Value": 1, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 1, "Max": 99, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 9, "Node": 10, "Genre": "Config", "Help": "Indicates how many levels the dimmer will change for each dimming step.", "ValueIDKey": 2533274968391697, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/2814749945102353/,{ "Label": "Local Control Dim Rate", "Value": 3, "Units": "x 10 milliseconds", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 1, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 10, "Node": 10, "Genre": "Config", "Help": "This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change.", "ValueIDKey": 2814749945102353, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/3096224921813009/,{ "Label": "ALL ON/ALL OFF Dim Step", "Value": 1, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 1, "Max": 99, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 11, "Node": 10, "Genre": "Config", "Help": "Indicates how many levels the dimmer will change for each dimming step.", "ValueIDKey": 3096224921813009, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/3377699898523665/,{ "Label": "ALL ON/ALL OFF Dim Rate", "Value": 3, "Units": "x 10 milliseconds", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 1, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 12, "Node": 10, "Genre": "Config", "Help": "This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change.", "ValueIDKey": 3377699898523665, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/,{ "Instance": 1, "CommandClassId": 114, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "CommandClassVersion": 2, "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/value/182222867/,{ "Label": "Loaded Config Revision", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -2147483648, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "Index": 0, "Node": 10, "Genre": "System", "Help": "Revision of the Config file currently loaded", "ValueIDKey": 182222867, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/value/281475158933523/,{ "Label": "Config File Revision", "Value": 9, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -2147483648, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "Index": 1, "Node": 10, "Genre": "System", "Help": "Revision of the Config file on the File System", "ValueIDKey": 281475158933523, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/value/562950135644179/,{ "Label": "Latest Available Config File Revision", "Value": 9, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -2147483648, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "Index": 2, "Node": 10, "Genre": "System", "Help": "Latest Revision of the Config file available for download", "ValueIDKey": 562950135644179, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/value/844425112354839/,{ "Label": "Device ID", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "Index": 3, "Node": 10, "Genre": "System", "Help": "Manufacturer Specific Device ID/Model", "ValueIDKey": 844425112354839, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/value/1125900089065495/,{ "Label": "Serial Number", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "Index": 4, "Node": 10, "Genre": "System", "Help": "Device Serial Number", "ValueIDKey": 1125900089065495, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/,{ "Instance": 1, "CommandClassId": 115, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "CommandClassVersion": 1, "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/182239252/,{ "Label": "Powerlevel", "Value": { "List": [ { "Value": 0, "Label": "Normal" }, { "Value": 1, "Label": "-1dB" }, { "Value": 2, "Label": "-2dB" }, { "Value": 3, "Label": "-3dB" }, { "Value": 4, "Label": "-4dB" }, { "Value": 5, "Label": "-5dB" }, { "Value": 6, "Label": "-6dB" }, { "Value": 7, "Label": "-7dB" }, { "Value": 8, "Label": "-8dB" }, { "Value": 9, "Label": "-9dB" } ], "Selected": "Normal", "Selected_id": 0 }, "Units": "dB", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 0, "Node": 10, "Genre": "System", "Help": "Output RF PowerLevel", "ValueIDKey": 182239252, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/281475158949905/,{ "Label": "Timeout", "Value": 0, "Units": "seconds", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 1, "Node": 10, "Genre": "System", "Help": "Timeout till the PowerLevel is reset to Normal", "ValueIDKey": 281475158949905, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/562950135660568/,{ "Label": "Set Powerlevel", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Button", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 2, "Node": 10, "Genre": "System", "Help": "Apply the Output PowerLevel and Timeout Values", "ValueIDKey": 562950135660568, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/844425112371217/,{ "Label": "Test Node", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 3, "Node": 10, "Genre": "System", "Help": "Node to Perform a test against", "ValueIDKey": 844425112371217, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/1125900089081876/,{ "Label": "Test Powerlevel", "Value": { "List": [ { "Value": 0, "Label": "Normal" }, { "Value": 1, "Label": "-1dB" }, { "Value": 2, "Label": "-2dB" }, { "Value": 3, "Label": "-3dB" }, { "Value": 4, "Label": "-4dB" }, { "Value": 5, "Label": "-5dB" }, { "Value": 6, "Label": "-6dB" }, { "Value": 7, "Label": "-7dB" }, { "Value": 8, "Label": "-8dB" }, { "Value": 9, "Label": "-9dB" } ], "Selected": "Normal", "Selected_id": 0 }, "Units": "dB", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 4, "Node": 10, "Genre": "System", "Help": "PowerLevel to use for the Test", "ValueIDKey": 1125900089081876, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/1407375065792534/,{ "Label": "Frame Count", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 5, "Node": 10, "Genre": "System", "Help": "How Many Messages to send to the Node for the Test", "ValueIDKey": 1407375065792534, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/1688850042503192/,{ "Label": "Test", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Button", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 6, "Node": 10, "Genre": "System", "Help": "Perform a PowerLevel Test against the a Node", "ValueIDKey": 1688850042503192, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/1970325019213848/,{ "Label": "Report", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Button", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 7, "Node": 10, "Genre": "System", "Help": "Get the results of the latest PowerLevel Test against a Node", "ValueIDKey": 1970325019213848, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/2251799995924500/,{ "Label": "Test Status", "Value": { "List": [ { "Value": 0, "Label": "Failed" }, { "Value": 1, "Label": "Success" }, { "Value": 2, "Label": "In Progress" } ], "Selected": "Failed", "Selected_id": 0 }, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 8, "Node": 10, "Genre": "System", "Help": "The Current Status of the last PowerNode Test Executed", "ValueIDKey": 2251799995924500, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/2533274972635158/,{ "Label": "Acked Frames", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 9, "Node": 10, "Genre": "System", "Help": "Number of Messages successfully Acked by the Target Node", "ValueIDKey": 2533274972635158, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/134/,{ "Instance": 1, "CommandClassId": 134, "CommandClass": "COMMAND_CLASS_VERSION", "CommandClassVersion": 1, "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/134/value/182550551/,{ "Label": "Library Version", "Value": "3", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_VERSION", "Index": 0, "Node": 10, "Genre": "System", "Help": "Z-Wave Library Version", "ValueIDKey": 182550551, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/134/value/281475159261207/,{ "Label": "Protocol Version", "Value": "4.54", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_VERSION", "Index": 1, "Node": 10, "Genre": "System", "Help": "Z-Wave Protocol Version", "ValueIDKey": 281475159261207, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/134/value/562950135971863/,{ "Label": "Application Version", "Value": "5.22", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_VERSION", "Index": 2, "Node": 10, "Genre": "System", "Help": "Application Version", "ValueIDKey": 562950135971863, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/association/1/,{ "Name": "Group 1", "Help": "", "MaxAssociations": 5, "Members": [ "1.0" ], "TimeStamp": 1589997977}
|
||||
OpenZWave/1/node/10/association/2/,{ "Name": "Group 2", "Help": "", "MaxAssociations": 5, "Members": [], "TimeStamp": 1589998004}
|
||||
OpenZWave/1/node/10/association/3/,{ "Name": "Group 3", "Help": "", "MaxAssociations": 5, "Members": [], "TimeStamp": 1589998004}
|
Can't render this file because it contains an unexpected character in line 1 and column 26.
|
File diff suppressed because one or more lines are too long
@ -1,25 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/39/instance/1/commandclass/38/value/659128337/",
|
||||
"payload": {
|
||||
"Label": "Level",
|
||||
"Value": 0,
|
||||
"Units": "",
|
||||
"Min": 0,
|
||||
"Max": 255,
|
||||
"Type": "Byte",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_SWITCH_MULTILEVEL",
|
||||
"Index": 0,
|
||||
"Node": 39,
|
||||
"Genre": "User",
|
||||
"Help": "The Current Level of the Device",
|
||||
"ValueIDKey": 659128337,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"ValueSet": false,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Event": "valueAdded",
|
||||
"TimeStamp": 1579566891
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,25 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/2/instance/1/commandclass/38/value/38371345/",
|
||||
"payload": {
|
||||
"Label": "Level",
|
||||
"Value": 0,
|
||||
"Units": "",
|
||||
"Min": 0,
|
||||
"Max": 255,
|
||||
"Type": "Byte",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_SWITCH_MULTILEVEL",
|
||||
"Index": 0,
|
||||
"Node": 2,
|
||||
"Genre": "User",
|
||||
"Help": "The Current Level of the Device",
|
||||
"ValueIDKey": 38371345,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"ValueSet": false,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Event": "valueAdded",
|
||||
"TimeStamp": 1579566891
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -1,25 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/7/instance/1/commandclass/51/value/122470423/",
|
||||
"payload": {
|
||||
"Label": "Color",
|
||||
"Value": "#ff00000000",
|
||||
"Units": "#RRGGBBWW",
|
||||
"ValueSet": false,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Min": 0,
|
||||
"Max": 0,
|
||||
"Type": "String",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_COLOR",
|
||||
"Index": 0,
|
||||
"Node": 7,
|
||||
"Genre": "User",
|
||||
"Help": "Color (in RGB format)",
|
||||
"ValueIDKey": 122470423,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"Event": "valueAdded",
|
||||
"TimeStamp": 1597142799
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/39/instance/1/commandclass/51/value/659341335/",
|
||||
"payload": {
|
||||
"Label": "Color",
|
||||
"Value": "#000000FF00",
|
||||
"Units": "#RRGGBBWWCW",
|
||||
"Min": 0,
|
||||
"Max": 0,
|
||||
"Type": "String",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_COLOR",
|
||||
"Index": 0,
|
||||
"Node": 39,
|
||||
"Genre": "User",
|
||||
"Help": "Color (in RGB format)",
|
||||
"ValueIDKey": 659341335,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"ValueSet": false,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Event": "valueAdded",
|
||||
"TimeStamp": 1579566891
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -1,25 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/10/instance/1/commandclass/98/value/173572112/",
|
||||
"payload": {
|
||||
"Label": "Lock",
|
||||
"Value": false,
|
||||
"Units": "",
|
||||
"Min": 0,
|
||||
"Max": 0,
|
||||
"Type": "Bool",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_DOOR_LOCK",
|
||||
"Index": 0,
|
||||
"Node": 10,
|
||||
"Genre": "User",
|
||||
"Help": "Lock / Unlock Device",
|
||||
"ValueIDKey": 173572112,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"ValueSet": false,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Event": "valueAdded",
|
||||
"TimeStamp": 1579566891
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
OpenZWave/1/status/,{ "OpenZWave_Version": "1.6.1131", "OZWDaemon_Version": "0.1.101", "QTOpenZWave_Version": "1.0.0", "QT_Version": "5.12.5", "Status": "driverAllNodesQueriedSomeDead", "TimeStamp": 1590178891, "ManufacturerSpecificDBReady": true, "homeID": 4075923038, "getControllerNodeId": 1, "getSUCNodeId": 0, "isPrimaryController": false, "isBridgeController": false, "hasExtendedTXStatistics": true, "getControllerLibraryVersion": "Z-Wave 4.05", "getControllerLibraryType": "Static Controller", "getControllerPath": "/dev/zwave"}
|
||||
OpenZWave/1/node/10/,{ "NodeID": 10, "NodeQueryStage": "Complete", "isListening": false, "isFlirs": true, "isBeaming": true, "isRouting": true, "isSecurityv1": false, "isZWavePlus": true, "isNIFRecieved": true, "isAwake": true, "isFailed": false, "MetaData": { "OZWInfoURL": "", "ZWAProductURL": "", "ProductPic": "", "Description": "", "ProductManualURL": "", "ProductPageURL": "", "InclusionHelp": "", "ExclusionHelp": "", "ResetHelp": "", "WakeupHelp": "", "ProductSupportURL": "", "Frequency": "", "Name": "", "ProductPicBase64": "" }, "Event": "nodeQueriesComplete", "TimeStamp": 1590178891, "NodeManufacturerName": "Poly-control", "NodeProductName": "Danalock V3 BTZE", "NodeBasicString": "Routing Slave", "NodeBasic": 4, "NodeGenericString": "Entry Control", "NodeGeneric": 64, "NodeSpecificString": "Secure Keypad Door Lock", "NodeSpecific": 3, "NodeManufacturerID": "0x010e", "NodeProductType": "0x0009", "NodeProductID": "0x0001", "NodeBaudRate": 100000, "NodeVersion": 4, "NodeName": "", "NodeLocation": "", "NodeGroups": 1, "NodeDeviceTypeString": "Door Lock Keypad", "NodeDeviceType": 768, "NodeRole": 7, "NodeRoleString": "Listening Sleeping Slave", "NodePlusType": 0, "NodePlusTypeString": "Z-Wave+ node", "Neighbors": [ 1, 5, 9 ]}
|
||||
OpenZWave/1/node/10/instance/1/,{ "Instance": 1, "TimeStamp": 1590178857}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/,{ "Instance": 1, "CommandClassId": 112, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "CommandClassVersion": 1, "TimeStamp": 1590178855}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/281475154706452/,{ "Label": "Twist Assist", "Value": { "List": [ { "Value": 0, "Label": "Disabled" }, { "Value": 1, "Label": "Enabled" } ], "Selected": "Disabled", "Selected_id": 0 }, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 1, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 1, "Node": 10, "Genre": "Config", "Help": "", "ValueIDKey": 281475154706452, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178855}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/562950131417107/,{ "Label": "Hold and Release", "Value": 0, "Units": "seconds", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 2, "Node": 10, "Genre": "Config", "Help": "0 Disable. 1 to 2147483647 Enable, time in seconds.", "ValueIDKey": 562950131417107, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178855}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/844425108127764/,{ "Label": "Block to Block", "Value": { "List": [ { "Value": 0, "Label": "Disable" }, { "Value": 1, "Label": "Enable" } ], "Selected": "Disable", "Selected_id": 0 }, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 1, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 3, "Node": 10, "Genre": "Config", "Help": "", "ValueIDKey": 844425108127764, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178855}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/1125900084838419/,{ "Label": "BLE Temporary Allowed", "Value": 0, "Units": "seconds", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 4, "Node": 10, "Genre": "Config", "Help": "0 Disable. 1 to 2147483647 Enable, time in seconds.", "ValueIDKey": 1125900084838419, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178855}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/1407375061549076/,{ "Label": "BLE Always Allowed", "Value": { "List": [ { "Value": 0, "Label": "Disable" }, { "Value": 1, "Label": "Enable" } ], "Selected": "Disable", "Selected_id": 0 }, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 1, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 5, "Node": 10, "Genre": "Config", "Help": "", "ValueIDKey": 1407375061549076, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178855}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/112/value/1688850038259731/,{ "Label": "Autolock", "Value": 0, "Units": "seconds", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 6, "Node": 10, "Genre": "Config", "Help": "0 Disable. 1 to 2147483647 Enable, time in seconds.", "ValueIDKey": 1688850038259731, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/94/,{ "Instance": 1, "CommandClassId": 94, "CommandClass": "COMMAND_CLASS_ZWAVEPLUS_INFO", "CommandClassVersion": 1, "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/94/value/181895185/,{ "Label": "ZWave+ Version", "Value": 1, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_ZWAVEPLUS_INFO", "Index": 0, "Node": 10, "Genre": "System", "Help": "ZWave+ Version Supported on the Device", "ValueIDKey": 181895185, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/94/value/281475158605846/,{ "Label": "InstallerIcon", "Value": 768, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 1, "CommandClass": "COMMAND_CLASS_ZWAVEPLUS_INFO", "Index": 1, "Node": 10, "Genre": "System", "Help": "Icon File to use for the Installer Application", "ValueIDKey": 281475158605846, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/94/value/562950135316502/,{ "Label": "UserIcon", "Value": 768, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 1, "CommandClass": "COMMAND_CLASS_ZWAVEPLUS_INFO", "Index": 2, "Node": 10, "Genre": "System", "Help": "Icon File to use for the User Application", "ValueIDKey": 562950135316502, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/98/,{ "Instance": 1, "CommandClassId": 98, "CommandClass": "COMMAND_CLASS_DOOR_LOCK", "CommandClassVersion": 1, "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/98/value/173572112/,{ "Label": "Locked", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Bool", "Instance": 1, "CommandClass": "COMMAND_CLASS_DOOR_LOCK", "Index": 0, "Node": 10, "Genre": "User", "Help": "State of the Lock", "ValueIDKey": 173572112, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590345913}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/98/value/281475150282772/,{ "Label": "Locked (Advanced)", "Value": { "List": [ { "Value": 0, "Label": "Unsecure" }, { "Value": 1, "Label": "Unsecured with Timeout" }, { "Value": 2, "Label": "Inside Handle Unsecured" }, { "Value": 3, "Label": "Inside Handle Unsecured with Timeout" }, { "Value": 4, "Label": "Outside Handle Unsecured" }, { "Value": 5, "Label": "Outside Handle Unsecured with Timeout" }, { "Value": 6, "Label": "Secured" }, { "Value": 255, "Label": "Invalid" } ], "Selected": "Unsecure", "Selected_id": 0 }, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_DOOR_LOCK", "Index": 1, "Node": 10, "Genre": "User", "Help": "State of the Lock (Advanced)", "ValueIDKey": 281475150282772, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590345913}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/98/value/562950135382036/,{ "Label": "Timeout Mode", "Value": { "List": [ { "Value": 1, "Label": "No Timeout" }, { "Value": 2, "Label": "Secure Lock after Timeout" } ], "Selected": "No Timeout", "Selected_id": 1 }, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_DOOR_LOCK", "Index": 2, "Node": 10, "Genre": "System", "Help": "Timeout Mode for Reverting Lock State", "ValueIDKey": 562950135382036, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/98/value/1407375065514001/,{ "Label": "Outside Handle Control", "Value": 1, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_DOOR_LOCK", "Index": 5, "Node": 10, "Genre": "System", "Help": "State of the Exterior Handle Control", "ValueIDKey": 1407375065514001, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/98/value/1688850042224657/,{ "Label": "Inside Handle Control", "Value": 1, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_DOOR_LOCK", "Index": 6, "Node": 10, "Genre": "System", "Help": "State of the Interior Handle Control", "ValueIDKey": 1688850042224657, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/,{ "Instance": 1, "CommandClassId": 99, "CommandClass": "COMMAND_CLASS_USER_CODE", "CommandClassVersion": 1, "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/72339069196615702/,{ "Label": "Code Count", "Value": 20, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 257, "Node": 10, "Genre": "System", "Help": "Number of User Codes supported by the Device", "ValueIDKey": 72339069196615702, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/71776119243194392/,{ "Label": "Refresh All UserCodes", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Button", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 255, "Node": 10, "Genre": "System", "Help": "Refresh All UserCodes Stored on Device", "ValueIDKey": 71776119243194392, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/72057594219905046/,{ "Label": "Remove User Code", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 256, "Node": 10, "Genre": "System", "Help": "Remove A UserCode at the Specified Index", "ValueIDKey": 72057594219905046, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/173588503/,{ "Label": "Enrollment Code", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 0, "Node": 10, "Genre": "User", "Help": "Enrollment Code", "ValueIDKey": 173588503, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/281475150299159/,{ "Label": "Code 1:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 1, "Node": 10, "Genre": "User", "Help": "UserCode 1", "ValueIDKey": 281475150299159, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/562950127009815/,{ "Label": "Code 2:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 2, "Node": 10, "Genre": "User", "Help": "UserCode 2", "ValueIDKey": 562950127009815, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/844425103720471/,{ "Label": "Code 3:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 3, "Node": 10, "Genre": "User", "Help": "UserCode 3", "ValueIDKey": 844425103720471, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/1125900080431127/,{ "Label": "Code 4:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 4, "Node": 10, "Genre": "User", "Help": "UserCode 4", "ValueIDKey": 1125900080431127, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/1407375057141783/,{ "Label": "Code 5:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 5, "Node": 10, "Genre": "User", "Help": "UserCode 5", "ValueIDKey": 1407375057141783, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/1688850033852439/,{ "Label": "Code 6:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 6, "Node": 10, "Genre": "User", "Help": "UserCode 6", "ValueIDKey": 1688850033852439, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/1970325010563095/,{ "Label": "Code 7:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 7, "Node": 10, "Genre": "User", "Help": "UserCode 7", "ValueIDKey": 1970325010563095, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/2251799987273751/,{ "Label": "Code 8:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 8, "Node": 10, "Genre": "User", "Help": "UserCode 8", "ValueIDKey": 2251799987273751, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/2533274963984407/,{ "Label": "Code 9:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 9, "Node": 10, "Genre": "User", "Help": "UserCode 9", "ValueIDKey": 2533274963984407, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/2814749940695063/,{ "Label": "Code 10:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 10, "Node": 10, "Genre": "User", "Help": "UserCode 10", "ValueIDKey": 2814749940695063, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/3096224917405719/,{ "Label": "Code 11:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 11, "Node": 10, "Genre": "User", "Help": "UserCode 11", "ValueIDKey": 3096224917405719, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/3377699894116375/,{ "Label": "Code 12:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 12, "Node": 10, "Genre": "User", "Help": "UserCode 12", "ValueIDKey": 3377699894116375, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/3659174870827031/,{ "Label": "Code 13:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 13, "Node": 10, "Genre": "User", "Help": "UserCode 13", "ValueIDKey": 3659174870827031, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/3940649847537687/,{ "Label": "Code 14:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 14, "Node": 10, "Genre": "User", "Help": "UserCode 14", "ValueIDKey": 3940649847537687, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/4222124824248343/,{ "Label": "Code 15:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 15, "Node": 10, "Genre": "User", "Help": "UserCode 15", "ValueIDKey": 4222124824248343, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/4503599800958999/,{ "Label": "Code 16:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 16, "Node": 10, "Genre": "User", "Help": "UserCode 16", "ValueIDKey": 4503599800958999, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/4785074777669655/,{ "Label": "Code 17:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 17, "Node": 10, "Genre": "User", "Help": "UserCode 17", "ValueIDKey": 4785074777669655, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/5066549754380311/,{ "Label": "Code 18:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 18, "Node": 10, "Genre": "User", "Help": "UserCode 18", "ValueIDKey": 5066549754380311, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/5348024731090967/,{ "Label": "Code 19:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 19, "Node": 10, "Genre": "User", "Help": "UserCode 19", "ValueIDKey": 5348024731090967, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/99/value/5629499707801623/,{ "Label": "Code 20:", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_USER_CODE", "Index": 20, "Node": 10, "Genre": "User", "Help": "UserCode 20", "ValueIDKey": 5629499707801623, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/,{ "Instance": 1, "CommandClassId": 114, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "CommandClassVersion": 2, "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/value/182222867/,{ "Label": "Loaded Config Revision", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -2147483648, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "Index": 0, "Node": 10, "Genre": "System", "Help": "Revision of the Config file currently loaded", "ValueIDKey": 182222867, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/value/281475158933523/,{ "Label": "Config File Revision", "Value": 15, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -2147483648, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "Index": 1, "Node": 10, "Genre": "System", "Help": "Revision of the Config file on the File System", "ValueIDKey": 281475158933523, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/value/562950135644179/,{ "Label": "Latest Available Config File Revision", "Value": 15, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -2147483648, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "Index": 2, "Node": 10, "Genre": "System", "Help": "Latest Revision of the Config file available for download", "ValueIDKey": 562950135644179, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/value/844425112354839/,{ "Label": "Device ID", "Value": "", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "Index": 3, "Node": 10, "Genre": "System", "Help": "Manufacturer Specific Device ID/Model", "ValueIDKey": 844425112354839, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/114/value/1125900089065495/,{ "Label": "Serial Number", "Value": "3b548b972bf8", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "Index": 4, "Node": 10, "Genre": "System", "Help": "Device Serial Number", "ValueIDKey": 1125900089065495, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178857}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/,{ "Instance": 1, "CommandClassId": 115, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "CommandClassVersion": 1, "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/182239252/,{ "Label": "Powerlevel", "Value": { "List": [ { "Value": 0, "Label": "Normal" }, { "Value": 1, "Label": "-1dB" }, { "Value": 2, "Label": "-2dB" }, { "Value": 3, "Label": "-3dB" }, { "Value": 4, "Label": "-4dB" }, { "Value": 5, "Label": "-5dB" }, { "Value": 6, "Label": "-6dB" }, { "Value": 7, "Label": "-7dB" }, { "Value": 8, "Label": "-8dB" }, { "Value": 9, "Label": "-9dB" } ], "Selected": "Normal", "Selected_id": 0 }, "Units": "dB", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 0, "Node": 10, "Genre": "System", "Help": "Output RF PowerLevel", "ValueIDKey": 182239252, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/281475158949905/,{ "Label": "Timeout", "Value": 0, "Units": "seconds", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 1, "Node": 10, "Genre": "System", "Help": "Timeout till the PowerLevel is reset to Normal", "ValueIDKey": 281475158949905, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/562950135660568/,{ "Label": "Set Powerlevel", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Button", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 2, "Node": 10, "Genre": "System", "Help": "Apply the Output PowerLevel and Timeout Values", "ValueIDKey": 562950135660568, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/844425112371217/,{ "Label": "Test Node", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 3, "Node": 10, "Genre": "System", "Help": "Node to Perform a test against", "ValueIDKey": 844425112371217, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/1125900089081876/,{ "Label": "Test Powerlevel", "Value": { "List": [ { "Value": 0, "Label": "Normal" }, { "Value": 1, "Label": "-1dB" }, { "Value": 2, "Label": "-2dB" }, { "Value": 3, "Label": "-3dB" }, { "Value": 4, "Label": "-4dB" }, { "Value": 5, "Label": "-5dB" }, { "Value": 6, "Label": "-6dB" }, { "Value": 7, "Label": "-7dB" }, { "Value": 8, "Label": "-8dB" }, { "Value": 9, "Label": "-9dB" } ], "Selected": "Normal", "Selected_id": 0 }, "Units": "dB", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 4, "Node": 10, "Genre": "System", "Help": "PowerLevel to use for the Test", "ValueIDKey": 1125900089081876, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/1407375065792534/,{ "Label": "Frame Count", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 5, "Node": 10, "Genre": "System", "Help": "How Many Messages to send to the Node for the Test", "ValueIDKey": 1407375065792534, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/1688850042503192/,{ "Label": "Test", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Button", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 6, "Node": 10, "Genre": "System", "Help": "Perform a PowerLevel Test against the a Node", "ValueIDKey": 1688850042503192, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/1970325019213848/,{ "Label": "Report", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Button", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 7, "Node": 10, "Genre": "System", "Help": "Get the results of the latest PowerLevel Test against a Node", "ValueIDKey": 1970325019213848, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/2251799995924500/,{ "Label": "Test Status", "Value": { "List": [ { "Value": 0, "Label": "Failed" }, { "Value": 1, "Label": "Success" }, { "Value": 2, "Label": "In Progress" } ], "Selected": "Failed", "Selected_id": 0 }, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 8, "Node": 10, "Genre": "System", "Help": "The Current Status of the last PowerNode Test Executed", "ValueIDKey": 2251799995924500, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/115/value/2533274972635158/,{ "Label": "Acked Frames", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 1, "CommandClass": "COMMAND_CLASS_POWERLEVEL", "Index": 9, "Node": 10, "Genre": "System", "Help": "Number of Messages successfully Acked by the Target Node", "ValueIDKey": 2533274972635158, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/128/,{ "Instance": 1, "CommandClassId": 128, "CommandClass": "COMMAND_CLASS_BATTERY", "CommandClassVersion": 1, "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/128/value/174063633/,{ "Label": "Battery Level", "Value": 94, "Units": "%", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_BATTERY", "Index": 0, "Node": 10, "Genre": "User", "Help": "Current Battery Level", "ValueIDKey": 174063633, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178891}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/134/,{ "Instance": 1, "CommandClassId": 134, "CommandClass": "COMMAND_CLASS_VERSION", "CommandClassVersion": 1, "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/134/value/182550551/,{ "Label": "Library Version", "Value": "3", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_VERSION", "Index": 0, "Node": 10, "Genre": "System", "Help": "Z-Wave Library Version", "ValueIDKey": 182550551, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178857}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/134/value/281475159261207/,{ "Label": "Protocol Version", "Value": "4.61", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_VERSION", "Index": 1, "Node": 10, "Genre": "System", "Help": "Z-Wave Protocol Version", "ValueIDKey": 281475159261207, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178857}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/134/value/562950135971863/,{ "Label": "Application Version", "Value": "1.02", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_VERSION", "Index": 2, "Node": 10, "Genre": "System", "Help": "Application Version", "ValueIDKey": 562950135971863, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178857}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/139/,{ "Instance": 1, "CommandClassId": 139, "CommandClass": "COMMAND_CLASS_TIME_PARAMETERS", "CommandClassVersion": 1, "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/139/value/182632471/,{ "Label": "Date", "Value": "22/05/2020", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_TIME_PARAMETERS", "Index": 0, "Node": 10, "Genre": "System", "Help": "Current Date", "ValueIDKey": 182632471, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178858}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/139/value/281475159343127/,{ "Label": "Time", "Value": "20:20:57", "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "String", "Instance": 1, "CommandClass": "COMMAND_CLASS_TIME_PARAMETERS", "Index": 1, "Node": 10, "Genre": "System", "Help": "Current Time", "ValueIDKey": 281475159343127, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590178858}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/139/value/562950136053784/,{ "Label": "Set Date/Time", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Button", "Instance": 1, "CommandClass": "COMMAND_CLASS_TIME_PARAMETERS", "Index": 2, "Node": 10, "Genre": "System", "Help": "Set the Date/Time", "ValueIDKey": 562950136053784, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/139/value/844425112764440/,{ "Label": "Refresh Date/Time", "Value": false, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Button", "Instance": 1, "CommandClass": "COMMAND_CLASS_TIME_PARAMETERS", "Index": 3, "Node": 10, "Genre": "System", "Help": "Refresh the Date/Time", "ValueIDKey": 844425112764440, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/152/,{ "Instance": 1, "CommandClassId": 152, "CommandClass": "COMMAND_CLASS_SECURITY", "CommandClassVersion": 1, "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/152/value/182845456/,{ "Label": "Secured", "Value": true, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "Bool", "Instance": 1, "CommandClass": "COMMAND_CLASS_SECURITY", "Index": 0, "Node": 10, "Genre": "System", "Help": "Is Communication with Device Encrypted", "ValueIDKey": 182845456, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178856}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/113/,{ "Instance": 1, "CommandClassId": 113, "CommandClass": "COMMAND_CLASS_NOTIFICATION", "CommandClassVersion": 8, "TimeStamp": 1590178857}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/113/value/72057594211745809/,{ "Label": "Previous Event Cleared", "Value": 0, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_NOTIFICATION", "Index": 256, "Node": 10, "Genre": "User", "Help": "Previous Event that was sent", "ValueIDKey": 72057594211745809, "ReadOnly": false, "WriteOnly": false, "Event": "valueAdded", "TimeStamp": 1590178857}
|
||||
OpenZWave/1/node/10/instance/1/commandclass/113/value/1688850034081812/,{ "Label": "Access Control", "Value": { "List": [ { "Value": 0, "Label": "Clear" }, { "Value": 1, "Label": "Manual Lock Operation" }, { "Value": 2, "Label": "Manual Unlock Operation" }, { "Value": 3, "Label": "Wireless Lock Operation" }, { "Value": 4, "Label": "Wireless Unlock Operation" }, { "Value": 9, "Label": "Auto Lock" }, { "Value": 11, "Label": "Lock Jammed" } ], "Selected": "Wireless Unlock Operation", "Selected_id": 4 }, "Units": "", "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_NOTIFICATION", "Index": 6, "Node": 10, "Genre": "User", "Help": "Access Control Alerts", "ValueIDKey": 1688850034081812, "ReadOnly": false, "WriteOnly": false, "Event": "valueChanged", "TimeStamp": 1590345911}
|
||||
OpenZWave/1/node/10/association/1/,{ "Name": "Lifeline", "Help": "", "MaxAssociations": 1, "Members": [ "1.0" ], "TimeStamp": 1590178858}
|
Can't render this file because it contains an unexpected character in line 1 and column 26.
|
@ -1,9 +0,0 @@
|
||||
OpenZWave/1/status/,{ "OpenZWave_Version": "1.6.1008", "OZWDeamon_Version": "0.1", "QTOpenZWave_Version": "1.0.0", "QT_Version": "5.12.5", "Status": "driverAllNodesQueried", "TimeStamp": 1579566933, "ManufacturerSpecificDBReady": true, "homeID": 3245146787, "getControllerNodeId": 1, "getSUCNodeId": 1, "isPrimaryController": true, "isBridgeController": false, "hasExtendedTXStatistics": true, "getControllerLibraryVersion": "Z-Wave 3.95", "getControllerLibraryType": "Static Controller", "getControllerPath": "/dev/zwave"}
|
||||
OpenZWave/1/node/32/,{ "NodeID": 32, "NodeQueryStage": "Complete", "isListening": true, "isFlirs": false, "isBeaming": true, "isRouting": true, "isSecurityv1": false, "isZWavePlus": true, "isNIFRecieved": true, "isAwake": true, "isFailed": false, "MetaData": { "OZWInfoURL": "http://www.openzwave.com/device-database/0208:0005:0101", "ZWAProductURL": "", "ProductPic": "images/hank/hkzw-so01-smartplug.png", "Description": "fixture description", "WakeupHelp": "", "ProductSupportURL": "", "Frequency": "", "Name": "Smart Plug", "ProductPicBase64": "iVBORggg==" }, "Event": "nodeQueriesComplete", "TimeStamp": 1579566933, "NodeManufacturerName": "HANK Electronics Ltd", "NodeProductName": "HKZW-SO01 Smart Plug", "NodeBasicString": "Routing Slave", "NodeBasic": 4, "NodeGenericString": "Binary Switch", "NodeGeneric": 16, "NodeSpecificString": "Binary Power Switch", "NodeSpecific": 1, "NodeManufacturerID": "0x0208", "NodeProductType": "0x0101", "NodeProductID": "0x0005", "NodeBaudRate": 100000, "NodeVersion": 4, "NodeGroups": 1, "NodeName": "", "NodeLocation": "", "NodeDeviceTypeString": "On/Off Power Switch", "NodeDeviceType": 1792, "NodeRole": 5, "NodeRoleString": "Always On Slave", "NodePlusType": 0, "NodePlusTypeString": "Z-Wave+ node", "Neighbors": [ 1, 33, 36, 37, 39 ]}
|
||||
OpenZWave/1/node/32/instance/1/,{ "Instance": 1, "TimeStamp": 1579566891}
|
||||
OpenZWave/1/node/32/instance/1/commandclass/50/,{ "Instance": 1, "CommandClassId": 50, "CommandClass": "COMMAND_CLASS_METER", "TimeStamp": 1579566891}
|
||||
OpenZWave/1/node/32/instance/1/commandclass/50/value/562950495305746/,{ "Label": "Electric - W", "Value": 0.0, "Units": "W", "Min": 0, "Max": 0, "Type": "Decimal", "Instance": 1, "CommandClass": "COMMAND_CLASS_METER", "Index": 2, "Node": 32, "Genre": "User", "Help": "", "ValueIDKey": 562950495305746, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
|
||||
OpenZWave/1/node/36/,{ "NodeID": 36, "NodeQueryStage": "CacheLoad", "isListening": false, "isFlirs": false, "isBeaming": true, "isRouting": true, "isSecurityv1": false, "isZWavePlus": false, "isNIFRecieved": true, "isAwake": true, "isFailed": false, "MetaData": { "OZWInfoURL": "http://www.openzwave.com/device-database/0086:007A:0102", "ZWAProductURL": "", "ProductPic": "images/aeotec/zw122.png", "Description": "fixture description", "WakeupHelp": "Pressing the Action Button once will trigger sending the Wake up notification command. If press and hold the Z-Wave button for 3 seconds, the Water Sensor will wake up for 10 minutes.", "ProductSupportURL": "", "Frequency": "", "Name": "Water Sensor 6", "ProductPicBase64": "kSuQmCC" }, "Event": "nodeNaming", "TimeStamp": 1579566891, "NodeManufacturerName": "AEON Labs", "NodeProductName": "ZW122 Water Sensor 6", "NodeBasicString": "Routing Slave", "NodeBasic": 4, "NodeGenericString": "Notification Sensor", "NodeGeneric": 7, "NodeSpecificString": "Notification Sensor", "NodeSpecific": 1, "NodeManufacturerID": "0x0086", "NodeProductType": "0x0102", "NodeProductID": "0x007a", "NodeBaudRate": 100000, "NodeVersion": 4, "NodeGroups": 4}
|
||||
OpenZWave/1/node/36/instance/1/,{ "Instance": 1, "TimeStamp": 1579566891}
|
||||
OpenZWave/1/node/36/instance/1/commandclass/128/,{ "Instance": 1, "CommandClassId": 128, "CommandClass": "COMMAND_CLASS_BATTERY", "TimeStamp": 1579566891}
|
||||
OpenZWave/1/node/36/instance/1/commandclass/128/value/610271249/,{ "Label": "Battery Level", "Value": 100, "Units": "%", "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_BATTERY", "Index": 0, "Node": 36, "Genre": "User", "Help": "Current Battery Level", "ValueIDKey": 610271249, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
|
Can't render this file because it contains an unexpected character in line 1 and column 26.
|
@ -1,38 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/36/instance/1/commandclass/113/value/1407375493578772/",
|
||||
"payload": {
|
||||
"Label": "Instance 1: Water",
|
||||
"Value": {
|
||||
"List": [
|
||||
{
|
||||
"Value": 0,
|
||||
"Label": "Clear"
|
||||
},
|
||||
{
|
||||
"Value": 2,
|
||||
"Label": "Water Leak at Unknown Location"
|
||||
}
|
||||
],
|
||||
"Selected": "Clear",
|
||||
"Selected_id": 0
|
||||
},
|
||||
"Units": "",
|
||||
"Min": 0,
|
||||
"Max": 0,
|
||||
"Type": "List",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_NOTIFICATION",
|
||||
"Index": 5,
|
||||
"Node": 36,
|
||||
"Genre": "User",
|
||||
"Help": "Water Alerts",
|
||||
"ValueIDKey": 1407375493578772,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"ValueSet": false,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Event": "valueAdded",
|
||||
"TimeStamp": 1579566891
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -1,25 +0,0 @@
|
||||
{
|
||||
"topic": "OpenZWave/1/node/32/instance/1/commandclass/37/value/541671440/",
|
||||
"payload": {
|
||||
"Label": "Switch",
|
||||
"Value": false,
|
||||
"Units": "",
|
||||
"Min": 0,
|
||||
"Max": 0,
|
||||
"Type": "Bool",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_SWITCH_BINARY",
|
||||
"Index": 0,
|
||||
"Node": 32,
|
||||
"Genre": "User",
|
||||
"Help": "Turn On/Off Device",
|
||||
"ValueIDKey": 541671440,
|
||||
"ReadOnly": false,
|
||||
"WriteOnly": false,
|
||||
"ValueSet": false,
|
||||
"ValuePolled": false,
|
||||
"ChangeVerified": false,
|
||||
"Event": "valueAdded",
|
||||
"TimeStamp": 1579566891
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
"""Test Z-Wave Sensors."""
|
||||
from homeassistant.components.binary_sensor import (
|
||||
DOMAIN as BINARY_SENSOR_DOMAIN,
|
||||
BinarySensorDeviceClass,
|
||||
)
|
||||
from homeassistant.components.ozw.const import DOMAIN
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from .common import setup_ozw
|
||||
|
||||
|
||||
async def test_binary_sensor(hass, generic_data, binary_sensor_msg):
|
||||
"""Test setting up config entry."""
|
||||
receive_msg = await setup_ozw(hass, fixture=generic_data)
|
||||
|
||||
# Test Legacy sensor (disabled by default)
|
||||
registry = er.async_get(hass)
|
||||
entity_id = "binary_sensor.trisensor_sensor"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is None
|
||||
entry = registry.async_get(entity_id)
|
||||
assert entry
|
||||
assert entry.disabled
|
||||
assert entry.disabled_by is er.RegistryEntryDisabler.INTEGRATION
|
||||
|
||||
# Test enabling legacy entity
|
||||
updated_entry = registry.async_update_entity(
|
||||
entry.entity_id, **{"disabled_by": None}
|
||||
)
|
||||
assert updated_entry != entry
|
||||
assert updated_entry.disabled is False
|
||||
|
||||
# Test Sensor for Notification CC
|
||||
state = hass.states.get("binary_sensor.trisensor_home_security_motion_detected")
|
||||
assert state
|
||||
assert state.state == "off"
|
||||
assert state.attributes[ATTR_DEVICE_CLASS] == BinarySensorDeviceClass.MOTION
|
||||
|
||||
# Test incoming state change
|
||||
receive_msg(binary_sensor_msg)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("binary_sensor.trisensor_home_security_motion_detected")
|
||||
assert state.state == "on"
|
||||
|
||||
|
||||
async def test_sensor_enabled(hass, generic_data, binary_sensor_alt_msg):
|
||||
"""Test enabling a legacy binary_sensor."""
|
||||
|
||||
registry = er.async_get(hass)
|
||||
|
||||
entry = registry.async_get_or_create(
|
||||
BINARY_SENSOR_DOMAIN,
|
||||
DOMAIN,
|
||||
"1-37-625737744",
|
||||
suggested_object_id="trisensor_sensor_instance_1_sensor",
|
||||
disabled_by=None,
|
||||
)
|
||||
assert entry.disabled is False
|
||||
|
||||
receive_msg = await setup_ozw(hass, fixture=generic_data)
|
||||
receive_msg(binary_sensor_alt_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entry.entity_id)
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
@ -1,327 +0,0 @@
|
||||
"""Test Z-Wave Multi-setpoint Climate entities."""
|
||||
from homeassistant.components.climate import ATTR_TEMPERATURE
|
||||
from homeassistant.components.climate.const import (
|
||||
ATTR_CURRENT_TEMPERATURE,
|
||||
ATTR_FAN_MODE,
|
||||
ATTR_FAN_MODES,
|
||||
ATTR_HVAC_ACTION,
|
||||
ATTR_HVAC_MODES,
|
||||
ATTR_PRESET_MODE,
|
||||
ATTR_PRESET_MODES,
|
||||
ATTR_TARGET_TEMP_HIGH,
|
||||
ATTR_TARGET_TEMP_LOW,
|
||||
CURRENT_HVAC_IDLE,
|
||||
HVAC_MODE_COOL,
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_HEAT_COOL,
|
||||
HVAC_MODE_OFF,
|
||||
)
|
||||
|
||||
from .common import setup_ozw
|
||||
|
||||
|
||||
async def test_climate(hass, climate_data, sent_messages, climate_msg, caplog):
|
||||
"""Test setting up config entry."""
|
||||
receive_message = await setup_ozw(hass, fixture=climate_data)
|
||||
|
||||
# Test multi-setpoint thermostat (node 7 in dump)
|
||||
# mode is heat, this should be single setpoint
|
||||
state = hass.states.get("climate.ct32_thermostat_mode")
|
||||
assert state is not None
|
||||
assert state.state == HVAC_MODE_HEAT
|
||||
assert state.attributes[ATTR_HVAC_MODES] == [
|
||||
HVAC_MODE_OFF,
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_COOL,
|
||||
HVAC_MODE_HEAT_COOL,
|
||||
]
|
||||
assert state.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_IDLE
|
||||
assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 23.1
|
||||
assert state.attributes[ATTR_TEMPERATURE] == 21.1
|
||||
assert state.attributes.get(ATTR_TARGET_TEMP_LOW) is None
|
||||
assert state.attributes.get(ATTR_TARGET_TEMP_HIGH) is None
|
||||
assert state.attributes[ATTR_FAN_MODE] == "Auto Low"
|
||||
assert state.attributes[ATTR_FAN_MODES] == ["Auto Low", "On Low"]
|
||||
|
||||
# Test set target temperature
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_temperature",
|
||||
{"entity_id": "climate.ct32_thermostat_mode", "temperature": 26.1},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 1
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
# Celsius is converted to Fahrenheit here!
|
||||
assert round(msg["payload"]["Value"], 2) == 78.98
|
||||
assert msg["payload"]["ValueIDKey"] == 281475099443218
|
||||
|
||||
# Test hvac_mode with set_temperature
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_temperature",
|
||||
{
|
||||
"entity_id": "climate.ct32_thermostat_mode",
|
||||
"temperature": 24.1,
|
||||
"hvac_mode": "cool",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 3 # 2 messages
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
# Celsius is converted to Fahrenheit here!
|
||||
assert round(msg["payload"]["Value"], 2) == 75.38
|
||||
assert msg["payload"]["ValueIDKey"] == 281475099443218
|
||||
|
||||
# Test set mode
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_hvac_mode",
|
||||
{"entity_id": "climate.ct32_thermostat_mode", "hvac_mode": HVAC_MODE_HEAT_COOL},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 4
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 3, "ValueIDKey": 122683412}
|
||||
|
||||
# Test set missing mode
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_hvac_mode",
|
||||
{"entity_id": "climate.ct32_thermostat_mode", "hvac_mode": "fan_only"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 4
|
||||
assert "Received an invalid hvac mode: fan_only" in caplog.text
|
||||
|
||||
# Test set fan mode
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_fan_mode",
|
||||
{"entity_id": "climate.ct32_thermostat_mode", "fan_mode": "On Low"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 5
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 1, "ValueIDKey": 122748948}
|
||||
|
||||
# Test set invalid fan mode
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_fan_mode",
|
||||
{"entity_id": "climate.ct32_thermostat_mode", "fan_mode": "invalid fan mode"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 5
|
||||
assert "Received an invalid fan mode: invalid fan mode" in caplog.text
|
||||
|
||||
# Test incoming mode change to auto,
|
||||
# resulting in multiple setpoints
|
||||
receive_message(climate_msg)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("climate.ct32_thermostat_mode")
|
||||
assert state is not None
|
||||
assert state.state == HVAC_MODE_HEAT_COOL
|
||||
assert state.attributes.get(ATTR_TEMPERATURE) is None
|
||||
assert state.attributes[ATTR_TARGET_TEMP_LOW] == 21.1
|
||||
assert state.attributes[ATTR_TARGET_TEMP_HIGH] == 25.6
|
||||
|
||||
# Test setting high/low temp on multiple setpoints
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_temperature",
|
||||
{
|
||||
"entity_id": "climate.ct32_thermostat_mode",
|
||||
"target_temp_low": 20,
|
||||
"target_temp_high": 25,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 7 # 2 messages !
|
||||
msg = sent_messages[-2] # low setpoint
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert round(msg["payload"]["Value"], 2) == 68.0
|
||||
assert msg["payload"]["ValueIDKey"] == 281475099443218
|
||||
msg = sent_messages[-1] # high setpoint
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert round(msg["payload"]["Value"], 2) == 77.0
|
||||
assert msg["payload"]["ValueIDKey"] == 562950076153874
|
||||
|
||||
# Test basic/single-setpoint thermostat (node 16 in dump)
|
||||
state = hass.states.get("climate.komforthaus_spirit_z_wave_plus_mode")
|
||||
assert state is not None
|
||||
assert state.state == HVAC_MODE_HEAT
|
||||
assert state.attributes[ATTR_HVAC_MODES] == [
|
||||
HVAC_MODE_OFF,
|
||||
HVAC_MODE_HEAT,
|
||||
]
|
||||
assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 17.3
|
||||
assert round(state.attributes[ATTR_TEMPERATURE], 0) == 19
|
||||
assert state.attributes.get(ATTR_TARGET_TEMP_LOW) is None
|
||||
assert state.attributes.get(ATTR_TARGET_TEMP_HIGH) is None
|
||||
assert state.attributes[ATTR_PRESET_MODES] == [
|
||||
"none",
|
||||
"Heat Eco",
|
||||
"Full Power",
|
||||
"Manufacturer Specific",
|
||||
]
|
||||
|
||||
# Test set target temperature
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_temperature",
|
||||
{
|
||||
"entity_id": "climate.komforthaus_spirit_z_wave_plus_mode",
|
||||
"temperature": 28.0,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 8
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": 28.0,
|
||||
"ValueIDKey": 281475250438162,
|
||||
}
|
||||
|
||||
# Test set preset mode
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_preset_mode",
|
||||
{
|
||||
"entity_id": "climate.komforthaus_spirit_z_wave_plus_mode",
|
||||
"preset_mode": "Heat Eco",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 9
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": 11,
|
||||
"ValueIDKey": 273678356,
|
||||
}
|
||||
|
||||
# Test set preset mode None
|
||||
# This preset should set and return to current hvac mode
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_preset_mode",
|
||||
{
|
||||
"entity_id": "climate.komforthaus_spirit_z_wave_plus_mode",
|
||||
"preset_mode": "none",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 10
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": 1,
|
||||
"ValueIDKey": 273678356,
|
||||
}
|
||||
|
||||
# Test set invalid preset mode
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_preset_mode",
|
||||
{
|
||||
"entity_id": "climate.komforthaus_spirit_z_wave_plus_mode",
|
||||
"preset_mode": "invalid preset mode",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 10
|
||||
assert "Received an invalid preset mode: invalid preset mode" in caplog.text
|
||||
|
||||
# test thermostat device without a mode commandclass
|
||||
state = hass.states.get("climate.danfoss_living_connect_z_v1_06_014g0013_heating_1")
|
||||
assert state is not None
|
||||
assert state.state == HVAC_MODE_HEAT
|
||||
assert state.attributes[ATTR_HVAC_MODES] == [
|
||||
HVAC_MODE_HEAT,
|
||||
]
|
||||
assert state.attributes.get(ATTR_CURRENT_TEMPERATURE) is None
|
||||
assert round(state.attributes[ATTR_TEMPERATURE], 0) == 21
|
||||
assert state.attributes.get(ATTR_TARGET_TEMP_LOW) is None
|
||||
assert state.attributes.get(ATTR_TARGET_TEMP_HIGH) is None
|
||||
assert state.attributes.get(ATTR_PRESET_MODE) is None
|
||||
assert state.attributes.get(ATTR_PRESET_MODES) is None
|
||||
|
||||
# Test set target temperature
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_temperature",
|
||||
{
|
||||
"entity_id": "climate.danfoss_living_connect_z_v1_06_014g0013_heating_1",
|
||||
"temperature": 28.0,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 11
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": 28.0,
|
||||
"ValueIDKey": 281475116220434,
|
||||
}
|
||||
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_hvac_mode",
|
||||
{
|
||||
"entity_id": "climate.danfoss_living_connect_z_v1_06_014g0013_heating_1",
|
||||
"hvac_mode": HVAC_MODE_HEAT,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 11
|
||||
assert "does not support setting a mode" in caplog.text
|
||||
|
||||
# test thermostat device without a mode commandclass
|
||||
state = hass.states.get("climate.secure_srt321_zwave_stat_tx_heating_1")
|
||||
assert state is not None
|
||||
assert state.state == HVAC_MODE_HEAT
|
||||
assert state.attributes[ATTR_HVAC_MODES] == [
|
||||
HVAC_MODE_HEAT,
|
||||
]
|
||||
assert state.attributes.get(ATTR_CURRENT_TEMPERATURE) == 29.0
|
||||
assert round(state.attributes[ATTR_TEMPERATURE], 0) == 16
|
||||
assert state.attributes.get(ATTR_TARGET_TEMP_LOW) is None
|
||||
assert state.attributes.get(ATTR_TARGET_TEMP_HIGH) is None
|
||||
assert state.attributes.get(ATTR_PRESET_MODE) is None
|
||||
assert state.attributes.get(ATTR_PRESET_MODES) is None
|
||||
|
||||
# Test set target temperature
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_temperature",
|
||||
{
|
||||
"entity_id": "climate.secure_srt321_zwave_stat_tx_heating_1",
|
||||
"temperature": 28.0,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 12
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": 28.0,
|
||||
"ValueIDKey": 281475267215378,
|
||||
}
|
||||
|
||||
await hass.services.async_call(
|
||||
"climate",
|
||||
"set_hvac_mode",
|
||||
{
|
||||
"entity_id": "climate.secure_srt321_zwave_stat_tx_heating_1",
|
||||
"hvac_mode": HVAC_MODE_HEAT,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 12
|
||||
assert "does not support setting a mode" in caplog.text
|
@ -1,502 +0,0 @@
|
||||
"""Test the Z-Wave over MQTT config flow."""
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.hassio import HassioServiceInfo
|
||||
from homeassistant.components.hassio.handler import HassioAPIError
|
||||
from homeassistant.components.ozw.config_flow import TITLE
|
||||
from homeassistant.components.ozw.const import DOMAIN
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
ADDON_DISCOVERY_INFO = HassioServiceInfo(
|
||||
config={
|
||||
"addon": "OpenZWave",
|
||||
"host": "host1",
|
||||
"port": 1234,
|
||||
"username": "name1",
|
||||
"password": "pass1",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(name="supervisor")
|
||||
def mock_supervisor_fixture():
|
||||
"""Mock Supervisor."""
|
||||
with patch("homeassistant.components.hassio.is_hassio", return_value=True):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(name="addon_info")
|
||||
def mock_addon_info():
|
||||
"""Mock Supervisor add-on info."""
|
||||
with patch("homeassistant.components.hassio.async_get_addon_info") as addon_info:
|
||||
addon_info.return_value = {}
|
||||
yield addon_info
|
||||
|
||||
|
||||
@pytest.fixture(name="addon_running")
|
||||
def mock_addon_running(addon_info):
|
||||
"""Mock add-on already running."""
|
||||
addon_info.return_value["state"] = "started"
|
||||
return addon_info
|
||||
|
||||
|
||||
@pytest.fixture(name="addon_installed")
|
||||
def mock_addon_installed(addon_info):
|
||||
"""Mock add-on already installed but not running."""
|
||||
addon_info.return_value["state"] = "stopped"
|
||||
addon_info.return_value["version"] = "1.0"
|
||||
return addon_info
|
||||
|
||||
|
||||
@pytest.fixture(name="addon_options")
|
||||
def mock_addon_options(addon_info):
|
||||
"""Mock add-on options."""
|
||||
addon_info.return_value["options"] = {}
|
||||
return addon_info.return_value["options"]
|
||||
|
||||
|
||||
@pytest.fixture(name="set_addon_options")
|
||||
def mock_set_addon_options():
|
||||
"""Mock set add-on options."""
|
||||
with patch(
|
||||
"homeassistant.components.hassio.async_set_addon_options"
|
||||
) as set_options:
|
||||
yield set_options
|
||||
|
||||
|
||||
@pytest.fixture(name="install_addon")
|
||||
def mock_install_addon():
|
||||
"""Mock install add-on."""
|
||||
with patch("homeassistant.components.hassio.async_install_addon") as install_addon:
|
||||
yield install_addon
|
||||
|
||||
|
||||
@pytest.fixture(name="start_addon")
|
||||
def mock_start_addon():
|
||||
"""Mock start add-on."""
|
||||
with patch("homeassistant.components.hassio.async_start_addon") as start_addon:
|
||||
yield start_addon
|
||||
|
||||
|
||||
async def test_user_not_supervisor_create_entry(hass, mqtt):
|
||||
"""Test the user step creates an entry not on Supervisor."""
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ozw.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == TITLE
|
||||
assert result["data"] == {
|
||||
"usb_path": None,
|
||||
"network_key": None,
|
||||
"use_addon": False,
|
||||
"integration_created_addon": False,
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_mqtt_not_setup(hass):
|
||||
"""Test that mqtt is required."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "mqtt_required"
|
||||
|
||||
|
||||
async def test_one_instance_allowed(hass):
|
||||
"""Test that only one instance is allowed."""
|
||||
entry = MockConfigEntry(domain=DOMAIN, data={}, title=TITLE)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "single_instance_allowed"
|
||||
|
||||
|
||||
async def test_not_addon(hass, supervisor, mqtt):
|
||||
"""Test opting out of add-on on Supervisor."""
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ozw.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"use_addon": False}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == TITLE
|
||||
assert result["data"] == {
|
||||
"usb_path": None,
|
||||
"network_key": None,
|
||||
"use_addon": False,
|
||||
"integration_created_addon": False,
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_addon_running(hass, supervisor, addon_running, addon_options):
|
||||
"""Test add-on already running on Supervisor."""
|
||||
addon_options["device"] = "/test"
|
||||
addon_options["network_key"] = "abc123"
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ozw.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"use_addon": True}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == TITLE
|
||||
assert result["data"] == {
|
||||
"usb_path": "/test",
|
||||
"network_key": "abc123",
|
||||
"use_addon": True,
|
||||
"integration_created_addon": False,
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_addon_info_failure(hass, supervisor, addon_info):
|
||||
"""Test add-on info failure."""
|
||||
addon_info.side_effect = HassioAPIError()
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"use_addon": True}
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "addon_info_failed"
|
||||
|
||||
|
||||
async def test_addon_installed(
|
||||
hass, supervisor, addon_installed, addon_options, set_addon_options, start_addon
|
||||
):
|
||||
"""Test add-on already installed but not running on Supervisor."""
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"use_addon": True}
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ozw.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"usb_path": "/test", "network_key": "abc123"}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == TITLE
|
||||
assert result["data"] == {
|
||||
"usb_path": "/test",
|
||||
"network_key": "abc123",
|
||||
"use_addon": True,
|
||||
"integration_created_addon": False,
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_set_addon_config_failure(
|
||||
hass, supervisor, addon_installed, addon_options, set_addon_options
|
||||
):
|
||||
"""Test add-on set config failure."""
|
||||
set_addon_options.side_effect = HassioAPIError()
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"use_addon": True}
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"usb_path": "/test", "network_key": "abc123"}
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "addon_set_config_failed"
|
||||
|
||||
|
||||
async def test_start_addon_failure(
|
||||
hass, supervisor, addon_installed, addon_options, set_addon_options, start_addon
|
||||
):
|
||||
"""Test add-on start failure."""
|
||||
start_addon.side_effect = HassioAPIError()
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"use_addon": True}
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"usb_path": "/test", "network_key": "abc123"}
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["errors"] == {"base": "addon_start_failed"}
|
||||
|
||||
|
||||
async def test_addon_not_installed(
|
||||
hass,
|
||||
supervisor,
|
||||
addon_installed,
|
||||
install_addon,
|
||||
addon_options,
|
||||
set_addon_options,
|
||||
start_addon,
|
||||
):
|
||||
"""Test add-on not installed."""
|
||||
addon_installed.return_value["version"] = None
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"use_addon": True}
|
||||
)
|
||||
|
||||
assert result["type"] == "progress"
|
||||
|
||||
# Make sure the flow continues when the progress task is done.
|
||||
await hass.async_block_till_done()
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "start_addon"
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ozw.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"usb_path": "/test", "network_key": "abc123"}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == TITLE
|
||||
assert result["data"] == {
|
||||
"usb_path": "/test",
|
||||
"network_key": "abc123",
|
||||
"use_addon": True,
|
||||
"integration_created_addon": True,
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_install_addon_failure(hass, supervisor, addon_installed, install_addon):
|
||||
"""Test add-on install failure."""
|
||||
addon_installed.return_value["version"] = None
|
||||
install_addon.side_effect = HassioAPIError()
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"use_addon": True}
|
||||
)
|
||||
|
||||
assert result["type"] == "progress"
|
||||
|
||||
# Make sure the flow continues when the progress task is done.
|
||||
await hass.async_block_till_done()
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "addon_install_failed"
|
||||
|
||||
|
||||
async def test_supervisor_discovery(hass, supervisor, addon_running, addon_options):
|
||||
"""Test flow started from Supervisor discovery."""
|
||||
|
||||
addon_options["device"] = "/test"
|
||||
addon_options["network_key"] = "abc123"
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
data=ADDON_DISCOVERY_INFO,
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ozw.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == TITLE
|
||||
assert result["data"] == {
|
||||
"usb_path": "/test",
|
||||
"network_key": "abc123",
|
||||
"use_addon": True,
|
||||
"integration_created_addon": False,
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_clean_discovery_on_user_create(
|
||||
hass, supervisor, addon_running, addon_options
|
||||
):
|
||||
"""Test discovery flow is cleaned up when a user flow is finished."""
|
||||
|
||||
addon_options["device"] = "/test"
|
||||
addon_options["network_key"] = "abc123"
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
data=ADDON_DISCOVERY_INFO,
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ozw.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"use_addon": False}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.config_entries.flow.async_progress()) == 0
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == TITLE
|
||||
assert result["data"] == {
|
||||
"usb_path": None,
|
||||
"network_key": None,
|
||||
"use_addon": False,
|
||||
"integration_created_addon": False,
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_abort_discovery_with_user_flow(
|
||||
hass, supervisor, addon_running, addon_options
|
||||
):
|
||||
"""Test discovery flow is aborted if a user flow is in progress."""
|
||||
|
||||
await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
data=ADDON_DISCOVERY_INFO,
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "already_in_progress"
|
||||
assert len(hass.config_entries.flow.async_progress()) == 1
|
||||
|
||||
|
||||
async def test_abort_discovery_with_existing_entry(
|
||||
hass, supervisor, addon_running, addon_options
|
||||
):
|
||||
"""Test discovery flow is aborted if an entry already exists."""
|
||||
|
||||
entry = MockConfigEntry(domain=DOMAIN, data={}, title=TITLE, unique_id=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
data=ADDON_DISCOVERY_INFO,
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_discovery_addon_not_running(
|
||||
hass, supervisor, addon_installed, addon_options, set_addon_options, start_addon
|
||||
):
|
||||
"""Test discovery with add-on already installed but not running."""
|
||||
addon_options["device"] = None
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
data=ADDON_DISCOVERY_INFO,
|
||||
)
|
||||
|
||||
assert result["step_id"] == "hassio_confirm"
|
||||
assert result["type"] == "form"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
|
||||
assert result["step_id"] == "start_addon"
|
||||
assert result["type"] == "form"
|
||||
|
||||
|
||||
async def test_discovery_addon_not_installed(
|
||||
hass, supervisor, addon_installed, install_addon, addon_options
|
||||
):
|
||||
"""Test discovery with add-on not installed."""
|
||||
addon_installed.return_value["version"] = None
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
data=ADDON_DISCOVERY_INFO,
|
||||
)
|
||||
|
||||
assert result["step_id"] == "hassio_confirm"
|
||||
assert result["type"] == "form"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
|
||||
assert result["step_id"] == "install_addon"
|
||||
assert result["type"] == "progress"
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "start_addon"
|
@ -1,177 +0,0 @@
|
||||
"""Test Z-Wave Covers."""
|
||||
from homeassistant.components.cover import ATTR_CURRENT_POSITION
|
||||
from homeassistant.components.ozw.cover import VALUE_SELECTED_ID
|
||||
|
||||
from .common import setup_ozw
|
||||
|
||||
VALUE_ID = "Value"
|
||||
|
||||
|
||||
async def test_cover(hass, cover_data, sent_messages, cover_msg):
|
||||
"""Test setting up config entry."""
|
||||
receive_message = await setup_ozw(hass, fixture=cover_data)
|
||||
# Test loaded
|
||||
state = hass.states.get("cover.roller_shutter_3_instance_1_level")
|
||||
assert state is not None
|
||||
assert state.state == "closed"
|
||||
assert state.attributes[ATTR_CURRENT_POSITION] == 0
|
||||
|
||||
# Test setting position
|
||||
await hass.services.async_call(
|
||||
"cover",
|
||||
"set_cover_position",
|
||||
{"entity_id": "cover.roller_shutter_3_instance_1_level", "position": 50},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 1
|
||||
msg = sent_messages[0]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 50, "ValueIDKey": 625573905}
|
||||
|
||||
# Feedback on state
|
||||
cover_msg.decode()
|
||||
cover_msg.payload["Value"] = 50
|
||||
cover_msg.encode()
|
||||
receive_message(cover_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Test opening
|
||||
await hass.services.async_call(
|
||||
"cover",
|
||||
"open_cover",
|
||||
{"entity_id": "cover.roller_shutter_3_instance_1_level"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 2
|
||||
msg = sent_messages[1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": True, "ValueIDKey": 281475602284568}
|
||||
|
||||
# Test stopping after opening
|
||||
await hass.services.async_call(
|
||||
"cover",
|
||||
"stop_cover",
|
||||
{"entity_id": "cover.roller_shutter_3_instance_1_level"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 4
|
||||
msg = sent_messages[2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": False, "ValueIDKey": 281475602284568}
|
||||
|
||||
msg = sent_messages[3]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": False, "ValueIDKey": 562950578995224}
|
||||
|
||||
# Test closing
|
||||
await hass.services.async_call(
|
||||
"cover",
|
||||
"close_cover",
|
||||
{"entity_id": "cover.roller_shutter_3_instance_1_level"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 5
|
||||
msg = sent_messages[4]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": True, "ValueIDKey": 562950578995224}
|
||||
|
||||
# Test stopping after closing
|
||||
await hass.services.async_call(
|
||||
"cover",
|
||||
"stop_cover",
|
||||
{"entity_id": "cover.roller_shutter_3_instance_1_level"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 7
|
||||
msg = sent_messages[5]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": False, "ValueIDKey": 281475602284568}
|
||||
|
||||
msg = sent_messages[6]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": False, "ValueIDKey": 562950578995224}
|
||||
|
||||
# Test stopping after no open/close
|
||||
await hass.services.async_call(
|
||||
"cover",
|
||||
"stop_cover",
|
||||
{"entity_id": "cover.roller_shutter_3_instance_1_level"},
|
||||
blocking=True,
|
||||
)
|
||||
# both stop open/close messages sent
|
||||
assert len(sent_messages) == 9
|
||||
msg = sent_messages[7]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": False, "ValueIDKey": 281475602284568}
|
||||
|
||||
msg = sent_messages[8]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": False, "ValueIDKey": 562950578995224}
|
||||
|
||||
# Test converting position to zwave range for position > 0
|
||||
await hass.services.async_call(
|
||||
"cover",
|
||||
"set_cover_position",
|
||||
{"entity_id": "cover.roller_shutter_3_instance_1_level", "position": 100},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 10
|
||||
msg = sent_messages[9]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 99, "ValueIDKey": 625573905}
|
||||
|
||||
# Test converting position to zwave range for position = 0
|
||||
await hass.services.async_call(
|
||||
"cover",
|
||||
"set_cover_position",
|
||||
{"entity_id": "cover.roller_shutter_3_instance_1_level", "position": 0},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 11
|
||||
msg = sent_messages[10]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 0, "ValueIDKey": 625573905}
|
||||
|
||||
|
||||
async def test_barrier(hass, cover_gdo_data, sent_messages, cover_gdo_msg):
|
||||
"""Test setting up config entry."""
|
||||
receive_message = await setup_ozw(hass, fixture=cover_gdo_data)
|
||||
# Test loaded
|
||||
state = hass.states.get("cover.gd00z_4_barrier_state")
|
||||
assert state is not None
|
||||
assert state.state == "closed"
|
||||
|
||||
# Test opening
|
||||
await hass.services.async_call(
|
||||
"cover",
|
||||
"open_cover",
|
||||
{"entity_id": "cover.gd00z_4_barrier_state"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 1
|
||||
msg = sent_messages[0]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 4, "ValueIDKey": 281475083239444}
|
||||
|
||||
# Feedback on state
|
||||
cover_gdo_msg.decode()
|
||||
cover_gdo_msg.payload[VALUE_ID][VALUE_SELECTED_ID] = 4
|
||||
cover_gdo_msg.encode()
|
||||
receive_message(cover_gdo_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("cover.gd00z_4_barrier_state")
|
||||
assert state is not None
|
||||
assert state.state == "open"
|
||||
|
||||
# Test closing
|
||||
await hass.services.async_call(
|
||||
"cover",
|
||||
"close_cover",
|
||||
{"entity_id": "cover.gd00z_4_barrier_state"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 2
|
||||
msg = sent_messages[1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 0, "ValueIDKey": 281475083239444}
|
@ -1,120 +0,0 @@
|
||||
"""Test Z-Wave Fans."""
|
||||
|
||||
from .common import setup_ozw
|
||||
|
||||
|
||||
async def test_fan(hass, fan_data, fan_msg, sent_messages, caplog):
|
||||
"""Test fan."""
|
||||
receive_message = await setup_ozw(hass, fixture=fan_data)
|
||||
|
||||
# Test loaded
|
||||
state = hass.states.get("fan.in_wall_smart_fan_control_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
|
||||
# Test turning off
|
||||
await hass.services.async_call(
|
||||
"fan",
|
||||
"turn_off",
|
||||
{"entity_id": "fan.in_wall_smart_fan_control_level"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(sent_messages) == 1
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 0, "ValueIDKey": 172589073}
|
||||
|
||||
# Feedback on state
|
||||
fan_msg.decode()
|
||||
fan_msg.payload["Value"] = 0
|
||||
fan_msg.encode()
|
||||
receive_message(fan_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("fan.in_wall_smart_fan_control_level")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
# Test turning on
|
||||
await hass.services.async_call(
|
||||
"fan",
|
||||
"turn_on",
|
||||
{"entity_id": "fan.in_wall_smart_fan_control_level", "percentage": 66},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(sent_messages) == 2
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": 66,
|
||||
"ValueIDKey": 172589073,
|
||||
}
|
||||
|
||||
# Feedback on state
|
||||
fan_msg.decode()
|
||||
fan_msg.payload["Value"] = 66
|
||||
fan_msg.encode()
|
||||
receive_message(fan_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("fan.in_wall_smart_fan_control_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["percentage"] == 66
|
||||
|
||||
# Test turn on without speed
|
||||
await hass.services.async_call(
|
||||
"fan",
|
||||
"turn_on",
|
||||
{"entity_id": "fan.in_wall_smart_fan_control_level"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(sent_messages) == 3
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": 255,
|
||||
"ValueIDKey": 172589073,
|
||||
}
|
||||
|
||||
# Feedback on state
|
||||
fan_msg.decode()
|
||||
fan_msg.payload["Value"] = 99
|
||||
fan_msg.encode()
|
||||
receive_message(fan_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("fan.in_wall_smart_fan_control_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["percentage"] == 100
|
||||
|
||||
# Test set percentage to 0
|
||||
await hass.services.async_call(
|
||||
"fan",
|
||||
"set_percentage",
|
||||
{"entity_id": "fan.in_wall_smart_fan_control_level", "percentage": 0},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(sent_messages) == 4
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": 0,
|
||||
"ValueIDKey": 172589073,
|
||||
}
|
||||
|
||||
# Feedback on state
|
||||
fan_msg.decode()
|
||||
fan_msg.payload["Value"] = 0
|
||||
fan_msg.encode()
|
||||
receive_message(fan_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("fan.in_wall_smart_fan_control_level")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
@ -1,238 +0,0 @@
|
||||
"""Test integration initialization."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.hassio.handler import HassioAPIError
|
||||
from homeassistant.components.ozw import DOMAIN, PLATFORMS, const
|
||||
from homeassistant.const import ATTR_RESTORED, STATE_UNAVAILABLE
|
||||
|
||||
from .common import setup_ozw
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_init_entry(hass, generic_data):
|
||||
"""Test setting up config entry."""
|
||||
await setup_ozw(hass, fixture=generic_data)
|
||||
|
||||
# Verify integration + platform loaded.
|
||||
assert "ozw" in hass.config.components
|
||||
for platform in PLATFORMS:
|
||||
assert platform in hass.config.components, platform
|
||||
assert f"{platform}.{DOMAIN}" in hass.config.components, f"{platform}.{DOMAIN}"
|
||||
|
||||
# Verify services registered
|
||||
assert hass.services.has_service(DOMAIN, const.SERVICE_ADD_NODE)
|
||||
assert hass.services.has_service(DOMAIN, const.SERVICE_REMOVE_NODE)
|
||||
|
||||
|
||||
async def test_setup_entry_without_mqtt(hass):
|
||||
"""Test setting up config entry without mqtt integration setup."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="OpenZWave",
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert not await hass.config_entries.async_setup(entry.entry_id)
|
||||
|
||||
|
||||
async def test_publish_without_mqtt(hass, caplog):
|
||||
"""Test publish without mqtt integration setup."""
|
||||
with patch("homeassistant.components.ozw.OZWOptions") as ozw_options:
|
||||
await setup_ozw(hass)
|
||||
|
||||
send_message = ozw_options.call_args[1]["send_message"]
|
||||
|
||||
mqtt_entries = hass.config_entries.async_entries("mqtt")
|
||||
mqtt_entry = mqtt_entries[0]
|
||||
await hass.config_entries.async_remove(mqtt_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert not hass.config_entries.async_entries("mqtt")
|
||||
|
||||
# Sending a message should not error with the MQTT integration not set up.
|
||||
send_message("test_topic", "test_payload")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert "MQTT integration is not set up" in caplog.text
|
||||
|
||||
|
||||
async def test_unload_entry(hass, generic_data, switch_msg, caplog):
|
||||
"""Test unload the config entry."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="Z-Wave",
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
assert entry.state is config_entries.ConfigEntryState.NOT_LOADED
|
||||
|
||||
receive_message = await setup_ozw(hass, entry=entry, fixture=generic_data)
|
||||
|
||||
assert entry.state is config_entries.ConfigEntryState.LOADED
|
||||
assert len(hass.states.async_entity_ids("switch")) == 1
|
||||
|
||||
await hass.config_entries.async_unload(entry.entry_id)
|
||||
|
||||
assert entry.state is config_entries.ConfigEntryState.NOT_LOADED
|
||||
entities = hass.states.async_entity_ids("switch")
|
||||
assert len(entities) == 1
|
||||
for entity in entities:
|
||||
assert hass.states.get(entity).state == STATE_UNAVAILABLE
|
||||
assert hass.states.get(entity).attributes.get(ATTR_RESTORED)
|
||||
|
||||
# Send a message for a switch from the broker to check that
|
||||
# all entity topic subscribers are unsubscribed.
|
||||
receive_message(switch_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_entity_ids("switch")) == 1
|
||||
for entity in entities:
|
||||
assert hass.states.get(entity).state == STATE_UNAVAILABLE
|
||||
assert hass.states.get(entity).attributes.get(ATTR_RESTORED)
|
||||
|
||||
# Load the integration again and check that there are no errors when
|
||||
# adding the entities.
|
||||
# This asserts that we have unsubscribed the entity addition signals
|
||||
# when unloading the integration previously.
|
||||
await setup_ozw(hass, entry=entry, fixture=generic_data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert entry.state is config_entries.ConfigEntryState.LOADED
|
||||
assert len(hass.states.async_entity_ids("switch")) == 1
|
||||
for record in caplog.records:
|
||||
assert record.levelname != "ERROR"
|
||||
|
||||
|
||||
async def test_remove_entry(hass, stop_addon, uninstall_addon, caplog):
|
||||
"""Test remove the config entry."""
|
||||
# test successful remove without created add-on
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="Z-Wave",
|
||||
data={"integration_created_addon": False},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
assert entry.state is config_entries.ConfigEntryState.NOT_LOADED
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||
|
||||
await hass.config_entries.async_remove(entry.entry_id)
|
||||
|
||||
assert entry.state is config_entries.ConfigEntryState.NOT_LOADED
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 0
|
||||
|
||||
# test successful remove with created add-on
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="Z-Wave",
|
||||
data={"integration_created_addon": True},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||
|
||||
await hass.config_entries.async_remove(entry.entry_id)
|
||||
|
||||
assert stop_addon.call_count == 1
|
||||
assert uninstall_addon.call_count == 1
|
||||
assert entry.state is config_entries.ConfigEntryState.NOT_LOADED
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 0
|
||||
stop_addon.reset_mock()
|
||||
uninstall_addon.reset_mock()
|
||||
|
||||
# test add-on stop failure
|
||||
entry.add_to_hass(hass)
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||
stop_addon.side_effect = HassioAPIError()
|
||||
|
||||
await hass.config_entries.async_remove(entry.entry_id)
|
||||
|
||||
assert stop_addon.call_count == 1
|
||||
assert uninstall_addon.call_count == 0
|
||||
assert entry.state is config_entries.ConfigEntryState.NOT_LOADED
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 0
|
||||
assert "Failed to stop the OpenZWave add-on" in caplog.text
|
||||
stop_addon.side_effect = None
|
||||
stop_addon.reset_mock()
|
||||
uninstall_addon.reset_mock()
|
||||
|
||||
# test add-on uninstall failure
|
||||
entry.add_to_hass(hass)
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||
uninstall_addon.side_effect = HassioAPIError()
|
||||
|
||||
await hass.config_entries.async_remove(entry.entry_id)
|
||||
|
||||
assert stop_addon.call_count == 1
|
||||
assert uninstall_addon.call_count == 1
|
||||
assert entry.state is config_entries.ConfigEntryState.NOT_LOADED
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 0
|
||||
assert "Failed to uninstall the OpenZWave add-on" in caplog.text
|
||||
|
||||
|
||||
async def test_setup_entry_with_addon(hass, get_addon_discovery_info):
|
||||
"""Test set up entry using OpenZWave add-on."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="OpenZWave",
|
||||
data={"use_addon": True},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
with patch("homeassistant.components.ozw.MQTTClient", autospec=True) as mock_client:
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_client.return_value.start_client.call_count == 1
|
||||
|
||||
# Verify integration + platform loaded.
|
||||
assert "ozw" in hass.config.components
|
||||
for platform in PLATFORMS:
|
||||
assert platform in hass.config.components, platform
|
||||
assert f"{platform}.{DOMAIN}" in hass.config.components, f"{platform}.{DOMAIN}"
|
||||
|
||||
# Verify services registered
|
||||
assert hass.services.has_service(DOMAIN, const.SERVICE_ADD_NODE)
|
||||
assert hass.services.has_service(DOMAIN, const.SERVICE_REMOVE_NODE)
|
||||
|
||||
|
||||
async def test_setup_entry_without_addon_info(hass, get_addon_discovery_info):
|
||||
"""Test set up entry using OpenZWave add-on but missing discovery info."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="OpenZWave",
|
||||
data={"use_addon": True},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
get_addon_discovery_info.return_value = None
|
||||
|
||||
with patch("homeassistant.components.ozw.MQTTClient", autospec=True) as mock_client:
|
||||
assert not await hass.config_entries.async_setup(entry.entry_id)
|
||||
|
||||
assert mock_client.return_value.start_client.call_count == 0
|
||||
assert entry.state is config_entries.ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_unload_entry_with_addon(
|
||||
hass, get_addon_discovery_info, generic_data, switch_msg, caplog
|
||||
):
|
||||
"""Test unload the config entry using the OpenZWave add-on."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="OpenZWave",
|
||||
data={"use_addon": True},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert entry.state is config_entries.ConfigEntryState.NOT_LOADED
|
||||
|
||||
with patch("homeassistant.components.ozw.MQTTClient", autospec=True) as mock_client:
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_client.return_value.start_client.call_count == 1
|
||||
assert entry.state is config_entries.ConfigEntryState.LOADED
|
||||
|
||||
await hass.config_entries.async_unload(entry.entry_id)
|
||||
|
||||
assert entry.state is config_entries.ConfigEntryState.NOT_LOADED
|
@ -1,683 +0,0 @@
|
||||
"""Test Z-Wave Lights."""
|
||||
from homeassistant.components.light import SUPPORT_TRANSITION
|
||||
from homeassistant.components.ozw.light import byte_to_zwave_brightness
|
||||
|
||||
from .common import setup_ozw
|
||||
|
||||
|
||||
async def test_light(hass, light_data, light_msg, light_rgb_msg, sent_messages):
|
||||
"""Test setting up config entry."""
|
||||
receive_message = await setup_ozw(hass, fixture=light_data)
|
||||
|
||||
# Test loaded
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
assert state.attributes["supported_features"] == SUPPORT_TRANSITION
|
||||
assert state.attributes["supported_color_modes"] == ["color_temp", "hs"]
|
||||
|
||||
# Test turning on
|
||||
# Beware that due to rounding, a roundtrip conversion does not always work
|
||||
new_brightness = 44
|
||||
new_transition = 0
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": "light.led_bulb_6_multi_colour_level",
|
||||
"brightness": new_brightness,
|
||||
"transition": new_transition,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 2
|
||||
|
||||
msg = sent_messages[0]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 0, "ValueIDKey": 1407375551070225}
|
||||
|
||||
msg = sent_messages[1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": byte_to_zwave_brightness(new_brightness),
|
||||
"ValueIDKey": 659128337,
|
||||
}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(new_brightness)
|
||||
light_msg.encode()
|
||||
receive_message(light_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["brightness"] == new_brightness
|
||||
assert state.attributes["color_mode"] == "color_temp"
|
||||
|
||||
# Test turning off
|
||||
new_transition = 6553
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_off",
|
||||
{
|
||||
"entity_id": "light.led_bulb_6_multi_colour_level",
|
||||
"transition": new_transition,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 4
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 237, "ValueIDKey": 1407375551070225}
|
||||
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 0, "ValueIDKey": 659128337}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = 0
|
||||
light_msg.encode()
|
||||
receive_message(light_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
# Test turn on without brightness
|
||||
new_transition = 127.0
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": "light.led_bulb_6_multi_colour_level",
|
||||
"transition": new_transition,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 6
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 127, "ValueIDKey": 1407375551070225}
|
||||
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": 255,
|
||||
"ValueIDKey": 659128337,
|
||||
}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(new_brightness)
|
||||
light_msg.encode()
|
||||
receive_message(light_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["brightness"] == new_brightness
|
||||
assert state.attributes["color_mode"] == "color_temp"
|
||||
|
||||
# Test set brightness to 0
|
||||
new_brightness = 0
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": "light.led_bulb_6_multi_colour_level",
|
||||
"brightness": new_brightness,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 7
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": byte_to_zwave_brightness(new_brightness),
|
||||
"ValueIDKey": 659128337,
|
||||
}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(new_brightness)
|
||||
light_msg.encode()
|
||||
receive_message(light_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
# Test setting color_name
|
||||
new_color = "blue"
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": "light.led_bulb_6_multi_colour_level", "color_name": new_color},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 9
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": "#0000ff0000", "ValueIDKey": 659341335}
|
||||
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 255, "ValueIDKey": 659128337}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(255)
|
||||
light_msg.encode()
|
||||
light_rgb_msg.decode()
|
||||
light_rgb_msg.payload["Value"] = "#0000ff0000"
|
||||
light_rgb_msg.encode()
|
||||
receive_message(light_msg)
|
||||
receive_message(light_rgb_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["rgb_color"] == (0, 0, 255)
|
||||
assert state.attributes["color_mode"] == "hs"
|
||||
|
||||
# Test setting hs_color
|
||||
new_color = [300, 70]
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": "light.led_bulb_6_multi_colour_level", "hs_color": new_color},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 11
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 255, "ValueIDKey": 659128337}
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": "#ff4cff0000", "ValueIDKey": 659341335}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(255)
|
||||
light_msg.encode()
|
||||
light_rgb_msg.decode()
|
||||
light_rgb_msg.payload["Value"] = "#ff4cff0000"
|
||||
light_rgb_msg.encode()
|
||||
receive_message(light_msg)
|
||||
receive_message(light_rgb_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["hs_color"] == (300.0, 70.196)
|
||||
assert state.attributes["color_mode"] == "hs"
|
||||
|
||||
# Test setting rgb_color
|
||||
new_color = [255, 154, 0]
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": "light.led_bulb_6_multi_colour_level", "rgb_color": new_color},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 13
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 255, "ValueIDKey": 659128337}
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": "#ff99000000", "ValueIDKey": 659341335}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(255)
|
||||
light_msg.encode()
|
||||
light_rgb_msg.decode()
|
||||
light_rgb_msg.payload["Value"] = "#ff99000000"
|
||||
light_rgb_msg.encode()
|
||||
receive_message(light_msg)
|
||||
receive_message(light_rgb_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["rgb_color"] == (255, 153, 0)
|
||||
assert state.attributes["color_mode"] == "hs"
|
||||
|
||||
# Test setting xy_color
|
||||
new_color = [0.52, 0.43]
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": "light.led_bulb_6_multi_colour_level", "xy_color": new_color},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 15
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 255, "ValueIDKey": 659128337}
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": "#ffbb370000", "ValueIDKey": 659341335}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(255)
|
||||
light_msg.encode()
|
||||
light_rgb_msg.decode()
|
||||
light_rgb_msg.payload["Value"] = "#ffbb370000"
|
||||
light_rgb_msg.encode()
|
||||
receive_message(light_msg)
|
||||
receive_message(light_rgb_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["xy_color"] == (0.519, 0.429)
|
||||
assert state.attributes["color_mode"] == "hs"
|
||||
|
||||
# Test setting color temp
|
||||
new_color = 200
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": "light.led_bulb_6_multi_colour_level", "color_temp": new_color},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 17
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 255, "ValueIDKey": 659128337}
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": "#00000037c8", "ValueIDKey": 659341335}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(255)
|
||||
light_msg.encode()
|
||||
light_rgb_msg.decode()
|
||||
light_rgb_msg.payload["Value"] = "#00000037c8"
|
||||
light_rgb_msg.encode()
|
||||
receive_message(light_msg)
|
||||
receive_message(light_rgb_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["color_temp"] == 200
|
||||
assert state.attributes["color_mode"] == "color_temp"
|
||||
|
||||
# Test setting invalid color temp
|
||||
new_color = 120
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": "light.led_bulb_6_multi_colour_level", "color_temp": new_color},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 19
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 255, "ValueIDKey": 659128337}
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": "#00000000ff", "ValueIDKey": 659341335}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(255)
|
||||
light_msg.encode()
|
||||
light_rgb_msg.decode()
|
||||
light_rgb_msg.payload["Value"] = "#00000000ff"
|
||||
light_rgb_msg.encode()
|
||||
receive_message(light_msg)
|
||||
receive_message(light_rgb_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["color_temp"] == 153
|
||||
assert state.attributes["color_mode"] == "color_temp"
|
||||
|
||||
|
||||
async def test_pure_rgb_dimmer_light(
|
||||
hass, light_data, light_pure_rgb_msg, sent_messages
|
||||
):
|
||||
"""Test light with no color channels command class."""
|
||||
receive_message = await setup_ozw(hass, fixture=light_data)
|
||||
|
||||
# Test loaded
|
||||
state = hass.states.get("light.kitchen_rgb_strip_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["supported_features"] == 0
|
||||
assert state.attributes["supported_color_modes"] == ["hs"]
|
||||
assert state.attributes["color_mode"] == "hs"
|
||||
|
||||
# Test setting hs_color
|
||||
new_color = [300, 70]
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": "light.kitchen_rgb_strip_level", "hs_color": new_color},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 2
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 255, "ValueIDKey": 122257425}
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": "#ff4cff00", "ValueIDKey": 122470423}
|
||||
|
||||
# Feedback on state
|
||||
light_pure_rgb_msg.decode()
|
||||
light_pure_rgb_msg.payload["Value"] = "#ff4cff00"
|
||||
light_pure_rgb_msg.encode()
|
||||
receive_message(light_pure_rgb_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.kitchen_rgb_strip_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["hs_color"] == (300.0, 70.196)
|
||||
assert state.attributes["color_mode"] == "hs"
|
||||
|
||||
|
||||
async def test_no_rgb_light(hass, light_data, light_no_rgb_msg, sent_messages):
|
||||
"""Test setting up config entry."""
|
||||
receive_message = await setup_ozw(hass, fixture=light_data)
|
||||
|
||||
# Test loaded no RGBW support (dimmer only)
|
||||
state = hass.states.get("light.master_bedroom_l_level")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
assert state.attributes["supported_features"] == 0
|
||||
assert state.attributes["supported_color_modes"] == ["brightness"]
|
||||
|
||||
# Turn on the light
|
||||
new_brightness = 44
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": "light.master_bedroom_l_level", "brightness": new_brightness},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 1
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {
|
||||
"Value": byte_to_zwave_brightness(new_brightness),
|
||||
"ValueIDKey": 38371345,
|
||||
}
|
||||
|
||||
# Feedback on state
|
||||
|
||||
light_no_rgb_msg.decode()
|
||||
light_no_rgb_msg.payload["Value"] = byte_to_zwave_brightness(new_brightness)
|
||||
light_no_rgb_msg.encode()
|
||||
receive_message(light_no_rgb_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.master_bedroom_l_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["brightness"] == new_brightness
|
||||
assert state.attributes["color_mode"] == "brightness"
|
||||
|
||||
|
||||
async def test_no_ww_light(
|
||||
hass, light_no_ww_data, light_msg, light_rgb_msg, sent_messages
|
||||
):
|
||||
"""Test setting up config entry."""
|
||||
receive_message = await setup_ozw(hass, fixture=light_no_ww_data)
|
||||
|
||||
# Test loaded no ww support
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
assert state.attributes["supported_features"] == 0
|
||||
assert state.attributes["supported_color_modes"] == ["rgbw"]
|
||||
|
||||
# Turn on the light
|
||||
white_color = 190
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": "light.led_bulb_6_multi_colour_level",
|
||||
"rgbw_color": [0, 0, 0, white_color],
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 2
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": "#00000000be", "ValueIDKey": 659341335}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(255)
|
||||
light_msg.encode()
|
||||
light_rgb_msg.decode()
|
||||
light_rgb_msg.payload["Value"] = "#00000000be"
|
||||
light_rgb_msg.encode()
|
||||
receive_message(light_msg)
|
||||
receive_message(light_rgb_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["color_mode"] == "rgbw"
|
||||
assert state.attributes["rgbw_color"] == (0, 0, 0, 190)
|
||||
|
||||
|
||||
async def test_no_cw_light(
|
||||
hass, light_no_cw_data, light_msg, light_rgb_msg, sent_messages
|
||||
):
|
||||
"""Test setting up config entry."""
|
||||
receive_message = await setup_ozw(hass, fixture=light_no_cw_data)
|
||||
|
||||
# Test loaded no cw support
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
assert state.attributes["supported_features"] == 0
|
||||
assert state.attributes["supported_color_modes"] == ["rgbw"]
|
||||
|
||||
# Turn on the light
|
||||
white_color = 190
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": "light.led_bulb_6_multi_colour_level",
|
||||
"rgbw_color": [0, 0, 0, white_color],
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 2
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": "#000000be", "ValueIDKey": 659341335}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(255)
|
||||
light_msg.encode()
|
||||
light_rgb_msg.decode()
|
||||
light_rgb_msg.payload["Value"] = "#000000be"
|
||||
light_rgb_msg.encode()
|
||||
receive_message(light_msg)
|
||||
receive_message(light_rgb_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["color_mode"] == "rgbw"
|
||||
assert state.attributes["rgbw_color"] == (0, 0, 0, 190)
|
||||
|
||||
|
||||
async def test_wc_light(hass, light_wc_data, light_msg, light_rgb_msg, sent_messages):
|
||||
"""Test setting up config entry."""
|
||||
receive_message = await setup_ozw(hass, fixture=light_wc_data)
|
||||
|
||||
# Test loaded only white LED support
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
assert state.attributes["supported_features"] == 0
|
||||
assert state.attributes["supported_color_modes"] == ["color_temp", "hs"]
|
||||
|
||||
assert state.attributes["min_mireds"] == 153
|
||||
assert state.attributes["max_mireds"] == 370
|
||||
|
||||
# Turn on the light
|
||||
new_color = 190
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{"entity_id": "light.led_bulb_6_multi_colour_level", "color_temp": new_color},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 2
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": "#0000002bd4", "ValueIDKey": 659341335}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = byte_to_zwave_brightness(255)
|
||||
light_msg.encode()
|
||||
light_rgb_msg.decode()
|
||||
light_rgb_msg.payload["Value"] = "#0000002bd4"
|
||||
light_rgb_msg.encode()
|
||||
receive_message(light_msg)
|
||||
receive_message(light_rgb_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
assert state.attributes["color_temp"] == 190
|
||||
assert state.attributes["color_mode"] == "color_temp"
|
||||
|
||||
|
||||
async def test_new_ozw_light(hass, light_new_ozw_data, light_msg, sent_messages):
|
||||
"""Test setting up config entry."""
|
||||
receive_message = await setup_ozw(hass, fixture=light_new_ozw_data)
|
||||
|
||||
# Test loaded only white LED support
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
assert state.attributes["supported_features"] == SUPPORT_TRANSITION
|
||||
assert state.attributes["supported_color_modes"] == ["color_temp", "hs"]
|
||||
|
||||
# Test turning on with new duration (newer openzwave)
|
||||
new_transition = 4180
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": "light.led_bulb_6_multi_colour_level",
|
||||
"transition": new_transition,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 2
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 4180, "ValueIDKey": 1407375551070225}
|
||||
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 255, "ValueIDKey": 659128337}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = 255
|
||||
light_msg.encode()
|
||||
receive_message(light_msg)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state.attributes["color_mode"] == "color_temp"
|
||||
|
||||
# Test turning off with new duration (newer openzwave)(new max)
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_off",
|
||||
{"entity_id": "light.led_bulb_6_multi_colour_level"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 4
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 7621, "ValueIDKey": 1407375551070225}
|
||||
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 0, "ValueIDKey": 659128337}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = 0
|
||||
light_msg.encode()
|
||||
receive_message(light_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Test turning on with new duration (newer openzwave)(factory default)
|
||||
new_transition = 8000
|
||||
await hass.services.async_call(
|
||||
"light",
|
||||
"turn_on",
|
||||
{
|
||||
"entity_id": "light.led_bulb_6_multi_colour_level",
|
||||
"transition": new_transition,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 6
|
||||
|
||||
msg = sent_messages[-2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 6553, "ValueIDKey": 1407375551070225}
|
||||
|
||||
msg = sent_messages[-1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 255, "ValueIDKey": 659128337}
|
||||
|
||||
# Feedback on state
|
||||
light_msg.decode()
|
||||
light_msg.payload["Value"] = 255
|
||||
light_msg.encode()
|
||||
receive_message(light_msg)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("light.led_bulb_6_multi_colour_level")
|
||||
assert state.attributes["color_mode"] == "color_temp"
|
@ -1,83 +0,0 @@
|
||||
"""Test Z-Wave Locks."""
|
||||
from .common import setup_ozw
|
||||
|
||||
|
||||
async def test_lock(hass, lock_data, sent_messages, lock_msg, caplog):
|
||||
"""Test lock."""
|
||||
receive_message = await setup_ozw(hass, fixture=lock_data)
|
||||
|
||||
# Test loaded
|
||||
state = hass.states.get("lock.danalock_v3_btze_locked")
|
||||
assert state is not None
|
||||
assert state.state == "unlocked"
|
||||
|
||||
# Test locking
|
||||
await hass.services.async_call(
|
||||
"lock", "lock", {"entity_id": "lock.danalock_v3_btze_locked"}, blocking=True
|
||||
)
|
||||
assert len(sent_messages) == 1
|
||||
msg = sent_messages[0]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": True, "ValueIDKey": 173572112}
|
||||
|
||||
# Feedback on state
|
||||
lock_msg.decode()
|
||||
lock_msg.payload["Value"] = True
|
||||
lock_msg.encode()
|
||||
receive_message(lock_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("lock.danalock_v3_btze_locked")
|
||||
assert state is not None
|
||||
assert state.state == "locked"
|
||||
|
||||
# Test unlocking
|
||||
await hass.services.async_call(
|
||||
"lock", "unlock", {"entity_id": "lock.danalock_v3_btze_locked"}, blocking=True
|
||||
)
|
||||
assert len(sent_messages) == 2
|
||||
msg = sent_messages[1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": False, "ValueIDKey": 173572112}
|
||||
|
||||
# Test set_usercode
|
||||
await hass.services.async_call(
|
||||
"ozw",
|
||||
"set_usercode",
|
||||
{
|
||||
"entity_id": "lock.danalock_v3_btze_locked",
|
||||
"usercode": 123456,
|
||||
"code_slot": 1,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 3
|
||||
msg = sent_messages[2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": "123456", "ValueIDKey": 281475150299159}
|
||||
|
||||
# Test clear_usercode
|
||||
await hass.services.async_call(
|
||||
"ozw",
|
||||
"clear_usercode",
|
||||
{"entity_id": "lock.danalock_v3_btze_locked", "code_slot": 1},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 5
|
||||
msg = sent_messages[4]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 1, "ValueIDKey": 72057594219905046}
|
||||
|
||||
# Test set_usercode invalid length
|
||||
await hass.services.async_call(
|
||||
"ozw",
|
||||
"set_usercode",
|
||||
{
|
||||
"entity_id": "lock.danalock_v3_btze_locked",
|
||||
"usercode": "123",
|
||||
"code_slot": 1,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 5
|
||||
assert "User code must be at least 4 digits" in caplog.text
|
@ -1,89 +0,0 @@
|
||||
"""Test Z-Wave (central) Scenes."""
|
||||
from .common import MQTTMessage, setup_ozw
|
||||
|
||||
from tests.common import async_capture_events
|
||||
|
||||
|
||||
async def test_scenes(hass, generic_data, sent_messages):
|
||||
"""Test setting up config entry."""
|
||||
|
||||
receive_message = await setup_ozw(hass, fixture=generic_data)
|
||||
events = async_capture_events(hass, "ozw.scene_activated")
|
||||
|
||||
# Publish fake scene event on mqtt
|
||||
message = MQTTMessage(
|
||||
topic="OpenZWave/1/node/39/instance/1/commandclass/43/value/562950622511127/",
|
||||
payload={
|
||||
"Label": "Scene",
|
||||
"Value": 16,
|
||||
"Units": "",
|
||||
"Min": -2147483648,
|
||||
"Max": 2147483647,
|
||||
"Type": "Int",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_SCENE_ACTIVATION",
|
||||
"Index": 0,
|
||||
"Node": 7,
|
||||
"Genre": "User",
|
||||
"Help": "",
|
||||
"ValueIDKey": 122339347,
|
||||
"ReadOnly": False,
|
||||
"WriteOnly": False,
|
||||
"ValueSet": False,
|
||||
"ValuePolled": False,
|
||||
"ChangeVerified": False,
|
||||
"Event": "valueChanged",
|
||||
"TimeStamp": 1579630367,
|
||||
},
|
||||
)
|
||||
message.encode()
|
||||
receive_message(message)
|
||||
# wait for the event
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 1
|
||||
assert events[0].data["scene_value_id"] == 16
|
||||
|
||||
# Publish fake central scene event on mqtt
|
||||
message = MQTTMessage(
|
||||
topic="OpenZWave/1/node/39/instance/1/commandclass/91/value/281476005806100/",
|
||||
payload={
|
||||
"Label": "Scene 1",
|
||||
"Value": {
|
||||
"List": [
|
||||
{"Value": 0, "Label": "Inactive"},
|
||||
{"Value": 1, "Label": "Pressed 1 Time"},
|
||||
{"Value": 2, "Label": "Key Released"},
|
||||
{"Value": 3, "Label": "Key Held down"},
|
||||
],
|
||||
"Selected": "Pressed 1 Time",
|
||||
"Selected_id": 1,
|
||||
},
|
||||
"Units": "",
|
||||
"Min": 0,
|
||||
"Max": 0,
|
||||
"Type": "List",
|
||||
"Instance": 1,
|
||||
"CommandClass": "COMMAND_CLASS_CENTRAL_SCENE",
|
||||
"Index": 1,
|
||||
"Node": 61,
|
||||
"Genre": "User",
|
||||
"Help": "",
|
||||
"ValueIDKey": 281476005806100,
|
||||
"ReadOnly": False,
|
||||
"WriteOnly": False,
|
||||
"ValueSet": False,
|
||||
"ValuePolled": False,
|
||||
"ChangeVerified": False,
|
||||
"Event": "valueChanged",
|
||||
"TimeStamp": 1579640710,
|
||||
},
|
||||
)
|
||||
message.encode()
|
||||
receive_message(message)
|
||||
# wait for the event
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 2
|
||||
assert events[1].data["scene_id"] == 1
|
||||
assert events[1].data["scene_label"] == "Scene 1"
|
||||
assert events[1].data["scene_value_label"] == "Pressed 1 Time"
|
||||
assert events[1].data["instance_id"] == 1
|
@ -1,93 +0,0 @@
|
||||
"""Test Z-Wave Sensors."""
|
||||
from homeassistant.components.ozw.const import DOMAIN
|
||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN, SensorDeviceClass
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from .common import setup_ozw
|
||||
|
||||
|
||||
async def test_sensor(hass, generic_data):
|
||||
"""Test setting up config entry."""
|
||||
await setup_ozw(hass, fixture=generic_data)
|
||||
|
||||
# Test standard sensor
|
||||
state = hass.states.get("sensor.smart_plug_electric_v")
|
||||
assert state is not None
|
||||
assert state.state == "123.9"
|
||||
assert state.attributes["unit_of_measurement"] == "V"
|
||||
|
||||
# Test device classes
|
||||
state = hass.states.get("sensor.trisensor_relative_humidity")
|
||||
assert state.attributes[ATTR_DEVICE_CLASS] == SensorDeviceClass.HUMIDITY
|
||||
state = hass.states.get("sensor.trisensor_pressure")
|
||||
assert state.attributes[ATTR_DEVICE_CLASS] == SensorDeviceClass.PRESSURE
|
||||
state = hass.states.get("sensor.trisensor_fake_power")
|
||||
assert state.attributes[ATTR_DEVICE_CLASS] == SensorDeviceClass.POWER
|
||||
state = hass.states.get("sensor.trisensor_fake_energy")
|
||||
assert state.attributes[ATTR_DEVICE_CLASS] == SensorDeviceClass.POWER
|
||||
state = hass.states.get("sensor.trisensor_fake_electric")
|
||||
assert state.attributes[ATTR_DEVICE_CLASS] == SensorDeviceClass.POWER
|
||||
|
||||
# Test ZWaveListSensor disabled by default
|
||||
registry = er.async_get(hass)
|
||||
entity_id = "sensor.water_sensor_6_instance_1_water"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is None
|
||||
|
||||
entry = registry.async_get(entity_id)
|
||||
assert entry
|
||||
assert entry.disabled
|
||||
assert entry.disabled_by is er.RegistryEntryDisabler.INTEGRATION
|
||||
|
||||
# Test enabling entity
|
||||
updated_entry = registry.async_update_entity(
|
||||
entry.entity_id, **{"disabled_by": None}
|
||||
)
|
||||
assert updated_entry != entry
|
||||
assert updated_entry.disabled is False
|
||||
|
||||
|
||||
async def test_sensor_enabled(hass, generic_data, sensor_msg):
|
||||
"""Test enabling an advanced sensor."""
|
||||
|
||||
registry = er.async_get(hass)
|
||||
|
||||
entry = registry.async_get_or_create(
|
||||
SENSOR_DOMAIN,
|
||||
DOMAIN,
|
||||
"1-36-1407375493578772",
|
||||
suggested_object_id="water_sensor_6_instance_1_water",
|
||||
disabled_by=None,
|
||||
)
|
||||
assert entry.disabled is False
|
||||
|
||||
receive_msg = await setup_ozw(hass, fixture=generic_data)
|
||||
receive_msg(sensor_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entry.entity_id)
|
||||
assert state is not None
|
||||
assert state.state == "0"
|
||||
assert state.attributes["label"] == "Clear"
|
||||
|
||||
|
||||
async def test_string_sensor(hass, string_sensor_data):
|
||||
"""Test so the returned type is a string sensor."""
|
||||
|
||||
registry = er.async_get(hass)
|
||||
|
||||
entry = registry.async_get_or_create(
|
||||
SENSOR_DOMAIN,
|
||||
DOMAIN,
|
||||
"1-49-73464969749610519",
|
||||
suggested_object_id="id_150_z_wave_module_user_code",
|
||||
disabled_by=None,
|
||||
)
|
||||
|
||||
await setup_ozw(hass, fixture=string_sensor_data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entry.entity_id)
|
||||
assert state is not None
|
||||
assert state.state == "asdfgh"
|
@ -1,115 +0,0 @@
|
||||
"""Test Z-Wave Services."""
|
||||
from openzwavemqtt.const import ATTR_POSITION, ATTR_VALUE
|
||||
from openzwavemqtt.exceptions import InvalidValueError, NotFoundError, WrongTypeError
|
||||
import pytest
|
||||
|
||||
from .common import setup_ozw
|
||||
|
||||
|
||||
async def test_services(hass, light_data, sent_messages):
|
||||
"""Test services on lock."""
|
||||
await setup_ozw(hass, fixture=light_data)
|
||||
|
||||
# Test set_config_parameter list by label
|
||||
await hass.services.async_call(
|
||||
"ozw",
|
||||
"set_config_parameter",
|
||||
{"node_id": 39, "parameter": 1, "value": "Disable"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 1
|
||||
msg = sent_messages[0]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 0, "ValueIDKey": 281475641245716}
|
||||
|
||||
# Test set_config_parameter list by index int
|
||||
await hass.services.async_call(
|
||||
"ozw",
|
||||
"set_config_parameter",
|
||||
{"node_id": 39, "parameter": 1, "value": 1},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 2
|
||||
msg = sent_messages[1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 1, "ValueIDKey": 281475641245716}
|
||||
|
||||
# Test set_config_parameter int
|
||||
await hass.services.async_call(
|
||||
"ozw",
|
||||
"set_config_parameter",
|
||||
{"node_id": 39, "parameter": 3, "value": 55},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 3
|
||||
msg = sent_messages[2]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 55, "ValueIDKey": 844425594667027}
|
||||
|
||||
# Test set_config_parameter invalid list int
|
||||
with pytest.raises(NotFoundError):
|
||||
assert await hass.services.async_call(
|
||||
"ozw",
|
||||
"set_config_parameter",
|
||||
{"node_id": 39, "parameter": 1, "value": 12},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 3
|
||||
|
||||
# Test set_config_parameter invalid list value
|
||||
with pytest.raises(NotFoundError):
|
||||
assert await hass.services.async_call(
|
||||
"ozw",
|
||||
"set_config_parameter",
|
||||
{"node_id": 39, "parameter": 1, "value": "Blah"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 3
|
||||
|
||||
# Test set_config_parameter invalid list value type
|
||||
with pytest.raises(WrongTypeError):
|
||||
assert await hass.services.async_call(
|
||||
"ozw",
|
||||
"set_config_parameter",
|
||||
{
|
||||
"node_id": 39,
|
||||
"parameter": 1,
|
||||
"value": {ATTR_VALUE: True, ATTR_POSITION: 1},
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 3
|
||||
|
||||
# Test set_config_parameter int out of range
|
||||
with pytest.raises(InvalidValueError):
|
||||
assert await hass.services.async_call(
|
||||
"ozw",
|
||||
"set_config_parameter",
|
||||
{"node_id": 39, "parameter": 3, "value": 2147483657},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 3
|
||||
|
||||
# Test set_config_parameter short
|
||||
await hass.services.async_call(
|
||||
"ozw",
|
||||
"set_config_parameter",
|
||||
{"node_id": 39, "parameter": 81, "value": 3000},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 4
|
||||
msg = sent_messages[3]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 3000, "ValueIDKey": 22799473778098198}
|
||||
|
||||
# Test set_config_parameter byte
|
||||
await hass.services.async_call(
|
||||
"ozw",
|
||||
"set_config_parameter",
|
||||
{"node_id": 39, "parameter": 16, "value": 20},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(sent_messages) == 5
|
||||
msg = sent_messages[4]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": 20, "ValueIDKey": 4503600291905553}
|
@ -1,41 +0,0 @@
|
||||
"""Test Z-Wave Switches."""
|
||||
from .common import setup_ozw
|
||||
|
||||
|
||||
async def test_switch(hass, generic_data, sent_messages, switch_msg):
|
||||
"""Test setting up config entry."""
|
||||
receive_message = await setup_ozw(hass, fixture=generic_data)
|
||||
|
||||
# Test loaded
|
||||
state = hass.states.get("switch.smart_plug_switch")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
# Test turning on
|
||||
await hass.services.async_call(
|
||||
"switch", "turn_on", {"entity_id": "switch.smart_plug_switch"}, blocking=True
|
||||
)
|
||||
assert len(sent_messages) == 1
|
||||
msg = sent_messages[0]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": True, "ValueIDKey": 541671440}
|
||||
|
||||
# Feedback on state
|
||||
switch_msg.decode()
|
||||
switch_msg.payload["Value"] = True
|
||||
switch_msg.encode()
|
||||
receive_message(switch_msg)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("switch.smart_plug_switch")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
|
||||
# Test turning off
|
||||
await hass.services.async_call(
|
||||
"switch", "turn_off", {"entity_id": "switch.smart_plug_switch"}, blocking=True
|
||||
)
|
||||
assert len(sent_messages) == 2
|
||||
msg = sent_messages[1]
|
||||
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
|
||||
assert msg["payload"] == {"Value": False, "ValueIDKey": 541671440}
|
@ -1,387 +0,0 @@
|
||||
"""Test OpenZWave Websocket API."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from openzwavemqtt.const import (
|
||||
ATTR_CODE_SLOT,
|
||||
ATTR_LABEL,
|
||||
ATTR_OPTIONS,
|
||||
ATTR_POSITION,
|
||||
ATTR_VALUE,
|
||||
ValueType,
|
||||
)
|
||||
|
||||
from homeassistant.components.ozw.const import ATTR_CONFIG_PARAMETER
|
||||
from homeassistant.components.ozw.lock import ATTR_USERCODE
|
||||
from homeassistant.components.ozw.websocket_api import (
|
||||
ATTR_IS_AWAKE,
|
||||
ATTR_IS_BEAMING,
|
||||
ATTR_IS_FAILED,
|
||||
ATTR_IS_FLIRS,
|
||||
ATTR_IS_ROUTING,
|
||||
ATTR_IS_SECURITYV1,
|
||||
ATTR_IS_ZWAVE_PLUS,
|
||||
ATTR_NEIGHBORS,
|
||||
ATTR_NODE_BASIC_STRING,
|
||||
ATTR_NODE_BAUD_RATE,
|
||||
ATTR_NODE_GENERIC_STRING,
|
||||
ATTR_NODE_QUERY_STAGE,
|
||||
ATTR_NODE_SPECIFIC_STRING,
|
||||
ID,
|
||||
NODE_ID,
|
||||
OZW_INSTANCE,
|
||||
PARAMETER,
|
||||
SCHEMA,
|
||||
TYPE,
|
||||
VALUE,
|
||||
)
|
||||
from homeassistant.components.websocket_api.const import (
|
||||
ERR_INVALID_FORMAT,
|
||||
ERR_NOT_FOUND,
|
||||
ERR_NOT_SUPPORTED,
|
||||
)
|
||||
|
||||
from .common import MQTTMessage, setup_ozw
|
||||
|
||||
|
||||
async def test_websocket_api(hass, generic_data, hass_ws_client, mqtt_mock):
|
||||
"""Test the ozw websocket api."""
|
||||
await setup_ozw(hass, fixture=generic_data)
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
# Test instance list
|
||||
await client.send_json({ID: 4, TYPE: "ozw/get_instances"})
|
||||
msg = await client.receive_json()
|
||||
assert len(msg["result"]) == 1
|
||||
result = msg["result"][0]
|
||||
assert result[OZW_INSTANCE] == 1
|
||||
assert result["Status"] == "driverAllNodesQueried"
|
||||
assert result["OpenZWave_Version"] == "1.6.1008"
|
||||
|
||||
# Test network status
|
||||
await client.send_json({ID: 5, TYPE: "ozw/network_status"})
|
||||
msg = await client.receive_json()
|
||||
result = msg["result"]
|
||||
|
||||
assert result["Status"] == "driverAllNodesQueried"
|
||||
assert result[OZW_INSTANCE] == 1
|
||||
|
||||
# Test node status
|
||||
await client.send_json({ID: 6, TYPE: "ozw/node_status", NODE_ID: 32})
|
||||
msg = await client.receive_json()
|
||||
result = msg["result"]
|
||||
|
||||
assert result[OZW_INSTANCE] == 1
|
||||
assert result[NODE_ID] == 32
|
||||
assert result[ATTR_NODE_QUERY_STAGE] == "Complete"
|
||||
assert result[ATTR_IS_ZWAVE_PLUS]
|
||||
assert result[ATTR_IS_AWAKE]
|
||||
assert not result[ATTR_IS_FAILED]
|
||||
assert result[ATTR_NODE_BAUD_RATE] == 100000
|
||||
assert result[ATTR_IS_BEAMING]
|
||||
assert not result[ATTR_IS_FLIRS]
|
||||
assert result[ATTR_IS_ROUTING]
|
||||
assert not result[ATTR_IS_SECURITYV1]
|
||||
assert result[ATTR_NODE_BASIC_STRING] == "Routing Slave"
|
||||
assert result[ATTR_NODE_GENERIC_STRING] == "Binary Switch"
|
||||
assert result[ATTR_NODE_SPECIFIC_STRING] == "Binary Power Switch"
|
||||
assert result[ATTR_NEIGHBORS] == [1, 33, 36, 37, 39]
|
||||
|
||||
await client.send_json({ID: 7, TYPE: "ozw/node_status", NODE_ID: 999})
|
||||
msg = await client.receive_json()
|
||||
result = msg["error"]
|
||||
assert result["code"] == ERR_NOT_FOUND
|
||||
|
||||
# Test node statistics
|
||||
await client.send_json({ID: 8, TYPE: "ozw/node_statistics", NODE_ID: 39})
|
||||
msg = await client.receive_json()
|
||||
result = msg["result"]
|
||||
|
||||
assert result[OZW_INSTANCE] == 1
|
||||
assert result[NODE_ID] == 39
|
||||
assert result["send_count"] == 57
|
||||
assert result["sent_failed"] == 0
|
||||
assert result["retries"] == 1
|
||||
assert result["last_request_rtt"] == 26
|
||||
assert result["last_response_rtt"] == 38
|
||||
assert result["average_request_rtt"] == 29
|
||||
assert result["average_response_rtt"] == 37
|
||||
assert result["received_packets"] == 3594
|
||||
assert result["received_dup_packets"] == 12
|
||||
assert result["received_unsolicited"] == 3546
|
||||
|
||||
# Test node metadata
|
||||
await client.send_json({ID: 9, TYPE: "ozw/node_metadata", NODE_ID: 39})
|
||||
msg = await client.receive_json()
|
||||
result = msg["result"]
|
||||
assert result["metadata"]["ProductPic"] == "images/aeotec/zwa002.png"
|
||||
|
||||
await client.send_json({ID: 10, TYPE: "ozw/node_metadata", NODE_ID: 999})
|
||||
msg = await client.receive_json()
|
||||
result = msg["error"]
|
||||
assert result["code"] == ERR_NOT_FOUND
|
||||
|
||||
# Test network statistics
|
||||
await client.send_json({ID: 11, TYPE: "ozw/network_statistics"})
|
||||
msg = await client.receive_json()
|
||||
result = msg["result"]
|
||||
assert result["readCnt"] == 92220
|
||||
assert result[OZW_INSTANCE] == 1
|
||||
assert result["node_count"] == 5
|
||||
|
||||
# Test get nodes
|
||||
await client.send_json({ID: 12, TYPE: "ozw/get_nodes"})
|
||||
msg = await client.receive_json()
|
||||
result = msg["result"]
|
||||
assert len(result) == 5
|
||||
assert result[2][ATTR_IS_AWAKE]
|
||||
assert not result[1][ATTR_IS_FAILED]
|
||||
|
||||
# Test get config parameters
|
||||
await client.send_json({ID: 13, TYPE: "ozw/get_config_parameters", NODE_ID: 39})
|
||||
msg = await client.receive_json()
|
||||
result = msg["result"]
|
||||
assert len(result) == 8
|
||||
for config_param in result:
|
||||
assert config_param["type"] in (
|
||||
ValueType.LIST.value,
|
||||
ValueType.BOOL.value,
|
||||
ValueType.INT.value,
|
||||
ValueType.BYTE.value,
|
||||
ValueType.SHORT.value,
|
||||
ValueType.BITSET.value,
|
||||
)
|
||||
|
||||
# Test set config parameter
|
||||
config_param = result[0]
|
||||
current_val = config_param[ATTR_VALUE]
|
||||
new_val = next(
|
||||
option[0]
|
||||
for option in config_param[SCHEMA][0][ATTR_OPTIONS]
|
||||
if option[0] != current_val
|
||||
)
|
||||
new_label = next(
|
||||
option[1]
|
||||
for option in config_param[SCHEMA][0][ATTR_OPTIONS]
|
||||
if option[1] != current_val and option[0] != new_val
|
||||
)
|
||||
await client.send_json(
|
||||
{
|
||||
ID: 14,
|
||||
TYPE: "ozw/set_config_parameter",
|
||||
NODE_ID: 39,
|
||||
PARAMETER: config_param[ATTR_CONFIG_PARAMETER],
|
||||
VALUE: new_val,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
await client.send_json(
|
||||
{
|
||||
ID: 15,
|
||||
TYPE: "ozw/set_config_parameter",
|
||||
NODE_ID: 39,
|
||||
PARAMETER: config_param[ATTR_CONFIG_PARAMETER],
|
||||
VALUE: new_label,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
|
||||
# Test OZW Instance not found error
|
||||
await client.send_json(
|
||||
{ID: 16, TYPE: "ozw/get_config_parameters", OZW_INSTANCE: 999, NODE_ID: 1}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
result = msg["error"]
|
||||
assert result["code"] == ERR_NOT_FOUND
|
||||
|
||||
# Test OZW Node not found error
|
||||
await client.send_json(
|
||||
{
|
||||
ID: 18,
|
||||
TYPE: "ozw/set_config_parameter",
|
||||
NODE_ID: 999,
|
||||
PARAMETER: 0,
|
||||
VALUE: "test",
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
result = msg["error"]
|
||||
assert result["code"] == ERR_NOT_FOUND
|
||||
|
||||
# Test parameter not found
|
||||
await client.send_json(
|
||||
{
|
||||
ID: 19,
|
||||
TYPE: "ozw/set_config_parameter",
|
||||
NODE_ID: 39,
|
||||
PARAMETER: 45,
|
||||
VALUE: "test",
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
result = msg["error"]
|
||||
assert result["code"] == ERR_NOT_FOUND
|
||||
|
||||
# Test list value not found
|
||||
await client.send_json(
|
||||
{
|
||||
ID: 20,
|
||||
TYPE: "ozw/set_config_parameter",
|
||||
NODE_ID: 39,
|
||||
PARAMETER: config_param[ATTR_CONFIG_PARAMETER],
|
||||
VALUE: "test",
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
result = msg["error"]
|
||||
assert result["code"] == ERR_NOT_FOUND
|
||||
|
||||
# Test value type invalid
|
||||
await client.send_json(
|
||||
{
|
||||
ID: 21,
|
||||
TYPE: "ozw/set_config_parameter",
|
||||
NODE_ID: 39,
|
||||
PARAMETER: 3,
|
||||
VALUE: 0,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
result = msg["error"]
|
||||
assert result["code"] == ERR_NOT_SUPPORTED
|
||||
|
||||
# Test invalid bitset format
|
||||
await client.send_json(
|
||||
{
|
||||
ID: 22,
|
||||
TYPE: "ozw/set_config_parameter",
|
||||
NODE_ID: 39,
|
||||
PARAMETER: 3,
|
||||
VALUE: {ATTR_POSITION: 1, ATTR_VALUE: True, ATTR_LABEL: "test"},
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
result = msg["error"]
|
||||
assert result["code"] == ERR_INVALID_FORMAT
|
||||
|
||||
# Test valid bitset format passes validation
|
||||
await client.send_json(
|
||||
{
|
||||
ID: 23,
|
||||
TYPE: "ozw/set_config_parameter",
|
||||
NODE_ID: 39,
|
||||
PARAMETER: 10000,
|
||||
VALUE: {ATTR_POSITION: 1, ATTR_VALUE: True},
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
result = msg["error"]
|
||||
assert result["code"] == ERR_NOT_FOUND
|
||||
|
||||
|
||||
async def test_ws_locks(hass, lock_data, hass_ws_client, mqtt_mock):
|
||||
"""Test lock websocket apis."""
|
||||
await setup_ozw(hass, fixture=lock_data)
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
await client.send_json(
|
||||
{
|
||||
ID: 1,
|
||||
TYPE: "ozw/get_code_slots",
|
||||
NODE_ID: 10,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
|
||||
await client.send_json(
|
||||
{
|
||||
ID: 2,
|
||||
TYPE: "ozw/set_usercode",
|
||||
NODE_ID: 10,
|
||||
ATTR_CODE_SLOT: 1,
|
||||
ATTR_USERCODE: "1234",
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
|
||||
await client.send_json(
|
||||
{
|
||||
ID: 3,
|
||||
TYPE: "ozw/clear_usercode",
|
||||
NODE_ID: 10,
|
||||
ATTR_CODE_SLOT: 1,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["success"]
|
||||
|
||||
|
||||
async def test_refresh_node(
|
||||
hass, generic_data, sent_messages, hass_ws_client, mqtt_mock
|
||||
):
|
||||
"""Test the ozw refresh node api."""
|
||||
receive_message = await setup_ozw(hass, fixture=generic_data)
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
# Send the refresh_node_info command
|
||||
await client.send_json({ID: 9, TYPE: "ozw/refresh_node_info", NODE_ID: 39})
|
||||
msg = await client.receive_json()
|
||||
|
||||
assert len(sent_messages) == 1
|
||||
assert msg["success"]
|
||||
|
||||
# Receive a mock status update from OZW
|
||||
message = MQTTMessage(
|
||||
topic="OpenZWave/1/node/39/",
|
||||
payload={"NodeID": 39, "NodeQueryStage": "initializing"},
|
||||
)
|
||||
message.encode()
|
||||
receive_message(message)
|
||||
|
||||
# Verify we got expected data on the websocket
|
||||
msg = await client.receive_json()
|
||||
result = msg["event"]
|
||||
assert result["type"] == "node_updated"
|
||||
assert result["node_query_stage"] == "initializing"
|
||||
|
||||
# Send another mock status update from OZW
|
||||
message = MQTTMessage(
|
||||
topic="OpenZWave/1/node/39/",
|
||||
payload={"NodeID": 39, "NodeQueryStage": "versions"},
|
||||
)
|
||||
message.encode()
|
||||
receive_message(message)
|
||||
|
||||
# Send a mock status update for a different node
|
||||
message = MQTTMessage(
|
||||
topic="OpenZWave/1/node/35/",
|
||||
payload={"NodeID": 35, "NodeQueryStage": "fake_shouldnt_be_received"},
|
||||
)
|
||||
message.encode()
|
||||
receive_message(message)
|
||||
|
||||
# Verify we received the message for node 39 but not for node 35
|
||||
msg = await client.receive_json()
|
||||
result = msg["event"]
|
||||
assert result["type"] == "node_updated"
|
||||
assert result["node_query_stage"] == "versions"
|
||||
|
||||
|
||||
async def test_refresh_node_unsubscribe(hass, generic_data, hass_ws_client, mqtt_mock):
|
||||
"""Test unsubscribing the ozw refresh node api."""
|
||||
await setup_ozw(hass, fixture=generic_data)
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
with patch("openzwavemqtt.OZWOptions.listen") as mock_listen:
|
||||
# Send the refresh_node_info command
|
||||
await client.send_json({ID: 9, TYPE: "ozw/refresh_node_info", NODE_ID: 39})
|
||||
await client.receive_json()
|
||||
|
||||
# Send the unsubscribe command
|
||||
await client.send_json({ID: 10, TYPE: "unsubscribe_events", "subscription": 9})
|
||||
await client.receive_json()
|
||||
|
||||
assert mock_listen.return_value.called
|
Loading…
x
Reference in New Issue
Block a user