1
mirror of https://github.com/home-assistant/core synced 2024-08-02 23:40:32 +02:00
ha-core/homeassistant/components/ozw/discovery.py
2020-11-18 15:18:59 +01:00

357 lines
14 KiB
Python

"""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