Add device_id parameter to LCN actions (service calls) (#129590)
parent
c06bc53724
commit
a46a0ad2b4
|
@ -31,6 +31,7 @@ from .const import (
|
|||
CONF_SK_NUM_TRIES,
|
||||
CONF_TRANSITION,
|
||||
CONNECTION,
|
||||
DEVICE_CONNECTIONS,
|
||||
DOMAIN,
|
||||
PLATFORMS,
|
||||
)
|
||||
|
@ -102,6 +103,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
|||
_LOGGER.debug('LCN connected to "%s"', config_entry.title)
|
||||
hass.data[DOMAIN][config_entry.entry_id] = {
|
||||
CONNECTION: lcn_connection,
|
||||
DEVICE_CONNECTIONS: {},
|
||||
ADD_ENTITIES_CALLBACKS: {},
|
||||
}
|
||||
# Update config_entry with LCN device serials
|
||||
|
|
|
@ -20,6 +20,7 @@ DEFAULT_NAME = "pchk"
|
|||
|
||||
ADD_ENTITIES_CALLBACKS = "add_entities_callbacks"
|
||||
CONNECTION = "connection"
|
||||
DEVICE_CONNECTIONS = "device_connections"
|
||||
CONF_HARDWARE_SERIAL = "hardware_serial"
|
||||
CONF_SOFTWARE_SERIAL = "software_serial"
|
||||
CONF_HARDWARE_TYPE = "hardware_type"
|
||||
|
|
|
@ -38,6 +38,7 @@ from .const import (
|
|||
CONF_SCENES,
|
||||
CONF_SOFTWARE_SERIAL,
|
||||
CONNECTION,
|
||||
DEVICE_CONNECTIONS,
|
||||
DOMAIN,
|
||||
LED_PORTS,
|
||||
LOGICOP_PORTS,
|
||||
|
@ -237,7 +238,7 @@ def register_lcn_address_devices(
|
|||
identifiers = {(DOMAIN, generate_unique_id(config_entry.entry_id, address))}
|
||||
|
||||
if device_config[CONF_ADDRESS][2]: # is group
|
||||
device_model = f"LCN group (g{address[0]:03d}{address[1]:03d})"
|
||||
device_model = "LCN group"
|
||||
sw_version = None
|
||||
else: # is module
|
||||
hardware_type = device_config[CONF_HARDWARE_TYPE]
|
||||
|
@ -245,10 +246,10 @@ def register_lcn_address_devices(
|
|||
hardware_name = pypck.lcn_defs.HARDWARE_DESCRIPTIONS[hardware_type]
|
||||
else:
|
||||
hardware_name = pypck.lcn_defs.HARDWARE_DESCRIPTIONS[-1]
|
||||
device_model = f"{hardware_name} (m{address[0]:03d}{address[1]:03d})"
|
||||
device_model = f"{hardware_name}"
|
||||
sw_version = f"{device_config[CONF_SOFTWARE_SERIAL]:06X}"
|
||||
|
||||
device_registry.async_get_or_create(
|
||||
device_entry = device_registry.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
identifiers=identifiers,
|
||||
via_device=host_identifiers,
|
||||
|
@ -258,6 +259,10 @@ def register_lcn_address_devices(
|
|||
model=device_model,
|
||||
)
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id][DEVICE_CONNECTIONS][
|
||||
device_entry.id
|
||||
] = get_device_connection(hass, address, config_entry)
|
||||
|
||||
|
||||
async def async_update_device_config(
|
||||
device_connection: DeviceConnectionType, device_config: ConfigType
|
||||
|
|
|
@ -8,12 +8,21 @@ import voluptuous as vol
|
|||
from homeassistant.const import (
|
||||
CONF_ADDRESS,
|
||||
CONF_BRIGHTNESS,
|
||||
CONF_DEVICE_ID,
|
||||
CONF_HOST,
|
||||
CONF_STATE,
|
||||
CONF_UNIT_OF_MEASUREMENT,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.core import (
|
||||
HomeAssistant,
|
||||
ServiceCall,
|
||||
ServiceResponse,
|
||||
SupportsResponse,
|
||||
)
|
||||
from homeassistant.exceptions import ServiceValidationError
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
|
||||
from .const import (
|
||||
CONF_KEYS,
|
||||
|
@ -30,6 +39,7 @@ from .const import (
|
|||
CONF_TRANSITION,
|
||||
CONF_VALUE,
|
||||
CONF_VARIABLE,
|
||||
DEVICE_CONNECTIONS,
|
||||
DOMAIN,
|
||||
LED_PORTS,
|
||||
LED_STATUS,
|
||||
|
@ -53,7 +63,13 @@ from .helpers import (
|
|||
class LcnServiceCall:
|
||||
"""Parent class for all LCN service calls."""
|
||||
|
||||
schema = vol.Schema({vol.Required(CONF_ADDRESS): is_address})
|
||||
schema = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_DEVICE_ID): cv.string,
|
||||
vol.Optional(CONF_ADDRESS): is_address,
|
||||
}
|
||||
)
|
||||
supports_response = SupportsResponse.NONE
|
||||
|
||||
def __init__(self, hass: HomeAssistant) -> None:
|
||||
"""Initialize service call."""
|
||||
|
@ -61,8 +77,37 @@ class LcnServiceCall:
|
|||
|
||||
def get_device_connection(self, service: ServiceCall) -> DeviceConnectionType:
|
||||
"""Get address connection object."""
|
||||
address, host_name = service.data[CONF_ADDRESS]
|
||||
if CONF_DEVICE_ID not in service.data and CONF_ADDRESS not in service.data:
|
||||
raise ServiceValidationError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="no_device_identifier",
|
||||
)
|
||||
|
||||
if CONF_DEVICE_ID in service.data:
|
||||
device_id = service.data[CONF_DEVICE_ID]
|
||||
device_registry = dr.async_get(self.hass)
|
||||
if not (device := device_registry.async_get(device_id)):
|
||||
raise ServiceValidationError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="invalid_device_id",
|
||||
translation_placeholders={"device_id": device_id},
|
||||
)
|
||||
|
||||
return self.hass.data[DOMAIN][device.primary_config_entry][
|
||||
DEVICE_CONNECTIONS
|
||||
][device_id]
|
||||
|
||||
async_create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
"deprecated_address_parameter",
|
||||
breaks_in_ha_version="2025.6.0",
|
||||
is_fixable=False,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_address_parameter",
|
||||
)
|
||||
|
||||
address, host_name = service.data[CONF_ADDRESS]
|
||||
for config_entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||
if config_entry.data[CONF_HOST] == host_name:
|
||||
device_connection = get_device_connection(
|
||||
|
@ -73,7 +118,7 @@ class LcnServiceCall:
|
|||
return device_connection
|
||||
raise ValueError("Invalid host name.")
|
||||
|
||||
async def async_call_service(self, service: ServiceCall) -> None:
|
||||
async def async_call_service(self, service: ServiceCall) -> ServiceResponse:
|
||||
"""Execute service call."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
|
|
@ -2,8 +2,76 @@
|
|||
|
||||
output_abs:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: &device_selector
|
||||
device:
|
||||
filter:
|
||||
- integration: lcn
|
||||
model: LCN group
|
||||
- integration: lcn
|
||||
model: UnknownModuleType
|
||||
- integration: lcn
|
||||
model: LCN-SW1.0
|
||||
- integration: lcn
|
||||
model: LCN-SW1.1
|
||||
- integration: lcn
|
||||
model: LCN-UP1.0
|
||||
- integration: lcn
|
||||
model: LCN-UP2
|
||||
- integration: lcn
|
||||
model: LCN-SW2
|
||||
- integration: lcn
|
||||
model: LCN-UP-Profi1-Plus
|
||||
- integration: lcn
|
||||
model: LCN-DI12
|
||||
- integration: lcn
|
||||
model: LCN-HU
|
||||
- integration: lcn
|
||||
model: LCN-SH
|
||||
- integration: lcn
|
||||
model: LCN-UP2
|
||||
- integration: lcn
|
||||
model: LCN-UPP
|
||||
- integration: lcn
|
||||
model: LCN-SK
|
||||
- integration: lcn
|
||||
model: LCN-LD
|
||||
- integration: lcn
|
||||
model: LCN-SH-Plus
|
||||
- integration: lcn
|
||||
model: LCN-UPS
|
||||
- integration: lcn
|
||||
model: LCN_UPS24V
|
||||
- integration: lcn
|
||||
model: LCN-GTM
|
||||
- integration: lcn
|
||||
model: LCN-SHS
|
||||
- integration: lcn
|
||||
model: LCN-ESD
|
||||
- integration: lcn
|
||||
model: LCN-EB2
|
||||
- integration: lcn
|
||||
model: LCN-MRS
|
||||
- integration: lcn
|
||||
model: LCN-EB11
|
||||
- integration: lcn
|
||||
model: LCN-UMR
|
||||
- integration: lcn
|
||||
model: LCN-UPU
|
||||
- integration: lcn
|
||||
model: LCN-UMR24V
|
||||
- integration: lcn
|
||||
model: LCN-SHD
|
||||
- integration: lcn
|
||||
model: LCN-SHU
|
||||
- integration: lcn
|
||||
model: LCN-SR6
|
||||
- integration: lcn
|
||||
model: LCN-UMF
|
||||
- integration: lcn
|
||||
model: LCN-WBH
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -34,8 +102,10 @@ output_abs:
|
|||
|
||||
output_rel:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -58,8 +128,10 @@ output_rel:
|
|||
|
||||
output_toggle:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -83,8 +155,10 @@ output_toggle:
|
|||
|
||||
relays:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -96,8 +170,10 @@ relays:
|
|||
|
||||
led:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -130,8 +206,10 @@ led:
|
|||
|
||||
var_abs:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -197,8 +275,10 @@ var_abs:
|
|||
|
||||
var_reset:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -230,8 +310,10 @@ var_reset:
|
|||
|
||||
var_rel:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -321,8 +403,10 @@ var_rel:
|
|||
|
||||
lock_regulator:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -355,8 +439,10 @@ lock_regulator:
|
|||
|
||||
send_keys:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -402,8 +488,10 @@ send_keys:
|
|||
|
||||
lock_keys:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -445,8 +533,10 @@ lock_keys:
|
|||
|
||||
dyn_text:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
@ -464,8 +554,10 @@ dyn_text:
|
|||
|
||||
pck:
|
||||
fields:
|
||||
device_id:
|
||||
example: "91aa039a2fb6e0b9f9ec7eb219a6b7d2"
|
||||
selector: *device_selector
|
||||
address:
|
||||
required: true
|
||||
example: "myhome.s0.m7"
|
||||
selector:
|
||||
text:
|
||||
|
|
|
@ -70,6 +70,10 @@
|
|||
"deprecated_keylock_sensor": {
|
||||
"title": "Deprecated LCN key lock binary sensor",
|
||||
"description": "Your LCN key lock binary sensor entity `{entity}` is beeing used in automations or scripts. A key lock switch entity is available and should be used going forward.\n\nPlease adjust your automations or scripts to fix this issue."
|
||||
},
|
||||
"deprecated_address_parameter": {
|
||||
"title": "Deprecated 'address' parameter",
|
||||
"description": "The 'address' parameter in the LCN service calls is deprecated. The 'devide_id' parameter should be used going forward.\n\nPlease adjust your automations or scripts to fix this issue."
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
|
@ -77,6 +81,10 @@
|
|||
"name": "Output absolute brightness",
|
||||
"description": "Sets absolute brightness of output port in percent.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "The device_id of the LCN module or group."
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "Module address."
|
||||
|
@ -99,6 +107,10 @@
|
|||
"name": "Output relative brightness",
|
||||
"description": "Sets relative brightness of output port in percent.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -117,6 +129,10 @@
|
|||
"name": "Toggle output",
|
||||
"description": "Toggles output port.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -135,6 +151,10 @@
|
|||
"name": "Relays",
|
||||
"description": "Sets the relays status.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -149,6 +169,10 @@
|
|||
"name": "LED",
|
||||
"description": "Sets the led state.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -167,6 +191,10 @@
|
|||
"name": "Set absolute variable",
|
||||
"description": "Sets absolute value of a variable or setpoint.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -189,6 +217,10 @@
|
|||
"name": "Reset variable",
|
||||
"description": "Resets value of variable or setpoint.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -203,6 +235,10 @@
|
|||
"name": "Shift variable",
|
||||
"description": "Shift value of a variable, setpoint or threshold.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -229,6 +265,10 @@
|
|||
"name": "Lock regulator",
|
||||
"description": "Locks a regulator setpoint.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -247,6 +287,10 @@
|
|||
"name": "Send keys",
|
||||
"description": "Sends keys (which executes bound commands).",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -273,6 +317,10 @@
|
|||
"name": "Lock keys",
|
||||
"description": "Locks keys.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -299,6 +347,10 @@
|
|||
"name": "Dynamic text",
|
||||
"description": "Sends dynamic text to LCN-GTxD displays.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -317,6 +369,10 @@
|
|||
"name": "PCK",
|
||||
"description": "Sends arbitrary PCK command.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:common::config_flow::data::device%]",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::device_id::description%]"
|
||||
},
|
||||
"address": {
|
||||
"name": "Address",
|
||||
"description": "[%key:component::lcn::services::output_abs::fields::address::description%]"
|
||||
|
@ -326,6 +382,39 @@
|
|||
"description": "PCK command (without address header)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"address_to_device_id": {
|
||||
"name": "Address to device id",
|
||||
"description": "Convert LCN address to device id.",
|
||||
"fields": {
|
||||
"id": {
|
||||
"name": "Module or group id",
|
||||
"description": "Target module or group id."
|
||||
},
|
||||
"segment_id": {
|
||||
"name": "Segment id",
|
||||
"description": "Target segment id."
|
||||
},
|
||||
"type": {
|
||||
"name": "Type",
|
||||
"description": "Target type."
|
||||
},
|
||||
"host": {
|
||||
"name": "Host name",
|
||||
"description": "Host name as given in the integration panel."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"exceptions": {
|
||||
"no_device_identifier": {
|
||||
"message": "No device identifier provided. Please provide the device id."
|
||||
},
|
||||
"invalid_address": {
|
||||
"message": "LCN device for given address has not been configured."
|
||||
},
|
||||
"invalid_device_id": {
|
||||
"message": "LCN device for given device id has not been configured."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,22 +26,37 @@ from homeassistant.components.lcn.services import LcnService
|
|||
from homeassistant.const import (
|
||||
CONF_ADDRESS,
|
||||
CONF_BRIGHTNESS,
|
||||
CONF_DEVICE_ID,
|
||||
CONF_STATE,
|
||||
CONF_UNIT_OF_MEASUREMENT,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
import homeassistant.helpers.issue_registry as ir
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .conftest import (
|
||||
MockConfigEntry,
|
||||
MockModuleConnection,
|
||||
MockPchkConnectionManager,
|
||||
get_device,
|
||||
init_integration,
|
||||
)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_output_abs(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
||||
def device_config(
|
||||
hass: HomeAssistant, entry: MockConfigEntry, config_type: str
|
||||
) -> dict[str, str]:
|
||||
"""Return test device config depending on type."""
|
||||
if config_type == CONF_ADDRESS:
|
||||
return {CONF_ADDRESS: "pchk.s0.m7"}
|
||||
return {CONF_DEVICE_ID: get_device(hass, entry, (0, 7, False)).id}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_output_abs(
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test output_abs service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
@ -51,7 +66,7 @@ async def test_service_output_abs(hass: HomeAssistant, entry: MockConfigEntry) -
|
|||
DOMAIN,
|
||||
LcnService.OUTPUT_ABS,
|
||||
{
|
||||
CONF_ADDRESS: "pchk.s0.m7",
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_OUTPUT: "output1",
|
||||
CONF_BRIGHTNESS: 100,
|
||||
CONF_TRANSITION: 5,
|
||||
|
@ -62,8 +77,12 @@ async def test_service_output_abs(hass: HomeAssistant, entry: MockConfigEntry) -
|
|||
dim_output.assert_awaited_with(0, 100, 9)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_output_rel(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_output_rel(
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test output_rel service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
@ -73,7 +92,7 @@ async def test_service_output_rel(hass: HomeAssistant, entry: MockConfigEntry) -
|
|||
DOMAIN,
|
||||
LcnService.OUTPUT_REL,
|
||||
{
|
||||
CONF_ADDRESS: "pchk.s0.m7",
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_OUTPUT: "output1",
|
||||
CONF_BRIGHTNESS: 25,
|
||||
},
|
||||
|
@ -83,9 +102,11 @@ async def test_service_output_rel(hass: HomeAssistant, entry: MockConfigEntry) -
|
|||
rel_output.assert_awaited_with(0, 25)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_output_toggle(
|
||||
hass: HomeAssistant, entry: MockConfigEntry
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test output_toggle service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
|
@ -96,7 +117,7 @@ async def test_service_output_toggle(
|
|||
DOMAIN,
|
||||
LcnService.OUTPUT_TOGGLE,
|
||||
{
|
||||
CONF_ADDRESS: "pchk.s0.m7",
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_OUTPUT: "output1",
|
||||
CONF_TRANSITION: 5,
|
||||
},
|
||||
|
@ -106,8 +127,12 @@ async def test_service_output_toggle(
|
|||
toggle_output.assert_awaited_with(0, 9)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_relays(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_relays(
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test relays service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
@ -116,7 +141,7 @@ async def test_service_relays(hass: HomeAssistant, entry: MockConfigEntry) -> No
|
|||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
LcnService.RELAYS,
|
||||
{CONF_ADDRESS: "pchk.s0.m7", CONF_STATE: "0011TT--"},
|
||||
{**device_config(hass, entry, config_type), CONF_STATE: "0011TT--"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
@ -126,8 +151,12 @@ async def test_service_relays(hass: HomeAssistant, entry: MockConfigEntry) -> No
|
|||
control_relays.assert_awaited_with(relay_states)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_led(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_led(
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test led service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
@ -136,7 +165,11 @@ async def test_service_led(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
|||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
LcnService.LED,
|
||||
{CONF_ADDRESS: "pchk.s0.m7", CONF_LED: "led6", CONF_STATE: "blink"},
|
||||
{
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_LED: "led6",
|
||||
CONF_STATE: "blink",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
@ -146,8 +179,12 @@ async def test_service_led(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
|||
control_led.assert_awaited_with(led, led_state)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_var_abs(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_var_abs(
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test var_abs service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
@ -157,7 +194,7 @@ async def test_service_var_abs(hass: HomeAssistant, entry: MockConfigEntry) -> N
|
|||
DOMAIN,
|
||||
LcnService.VAR_ABS,
|
||||
{
|
||||
CONF_ADDRESS: "pchk.s0.m7",
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_VARIABLE: "var1",
|
||||
CONF_VALUE: 75,
|
||||
CONF_UNIT_OF_MEASUREMENT: "%",
|
||||
|
@ -170,8 +207,12 @@ async def test_service_var_abs(hass: HomeAssistant, entry: MockConfigEntry) -> N
|
|||
)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_var_rel(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_var_rel(
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test var_rel service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
@ -181,7 +222,7 @@ async def test_service_var_rel(hass: HomeAssistant, entry: MockConfigEntry) -> N
|
|||
DOMAIN,
|
||||
LcnService.VAR_REL,
|
||||
{
|
||||
CONF_ADDRESS: "pchk.s0.m7",
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_VARIABLE: "var1",
|
||||
CONF_VALUE: 10,
|
||||
CONF_UNIT_OF_MEASUREMENT: "%",
|
||||
|
@ -198,8 +239,12 @@ async def test_service_var_rel(hass: HomeAssistant, entry: MockConfigEntry) -> N
|
|||
)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_var_reset(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_var_reset(
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test var_reset service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
@ -208,16 +253,18 @@ async def test_service_var_reset(hass: HomeAssistant, entry: MockConfigEntry) ->
|
|||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
LcnService.VAR_RESET,
|
||||
{CONF_ADDRESS: "pchk.s0.m7", CONF_VARIABLE: "var1"},
|
||||
{**device_config(hass, entry, config_type), CONF_VARIABLE: "var1"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
var_reset.assert_awaited_with(pypck.lcn_defs.Var["VAR1"])
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_lock_regulator(
|
||||
hass: HomeAssistant, entry: MockConfigEntry
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test lock_regulator service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
|
@ -228,7 +275,7 @@ async def test_service_lock_regulator(
|
|||
DOMAIN,
|
||||
LcnService.LOCK_REGULATOR,
|
||||
{
|
||||
CONF_ADDRESS: "pchk.s0.m7",
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_SETPOINT: "r1varsetpoint",
|
||||
CONF_STATE: True,
|
||||
},
|
||||
|
@ -238,8 +285,12 @@ async def test_service_lock_regulator(
|
|||
lock_regulator.assert_awaited_with(0, True)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_send_keys(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_send_keys(
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test send_keys service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
@ -248,7 +299,11 @@ async def test_service_send_keys(hass: HomeAssistant, entry: MockConfigEntry) ->
|
|||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
LcnService.SEND_KEYS,
|
||||
{CONF_ADDRESS: "pchk.s0.m7", CONF_KEYS: "a1a5d8", CONF_STATE: "hit"},
|
||||
{
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_KEYS: "a1a5d8",
|
||||
CONF_STATE: "hit",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
@ -260,9 +315,11 @@ async def test_service_send_keys(hass: HomeAssistant, entry: MockConfigEntry) ->
|
|||
send_keys.assert_awaited_with(keys, pypck.lcn_defs.SendKeyCommand["HIT"])
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_send_keys_hit_deferred(
|
||||
hass: HomeAssistant, entry: MockConfigEntry
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test send_keys (hit_deferred) service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
|
@ -281,7 +338,7 @@ async def test_service_send_keys_hit_deferred(
|
|||
DOMAIN,
|
||||
LcnService.SEND_KEYS,
|
||||
{
|
||||
CONF_ADDRESS: "pchk.s0.m7",
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_KEYS: "a1a5d8",
|
||||
CONF_TIME: 5,
|
||||
CONF_TIME_UNIT: "s",
|
||||
|
@ -304,7 +361,7 @@ async def test_service_send_keys_hit_deferred(
|
|||
DOMAIN,
|
||||
LcnService.SEND_KEYS,
|
||||
{
|
||||
CONF_ADDRESS: "pchk.s0.m7",
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_KEYS: "a1a5d8",
|
||||
CONF_STATE: "make",
|
||||
CONF_TIME: 5,
|
||||
|
@ -314,8 +371,12 @@ async def test_service_send_keys_hit_deferred(
|
|||
)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_lock_keys(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_lock_keys(
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test lock_keys service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
@ -324,7 +385,11 @@ async def test_service_lock_keys(hass: HomeAssistant, entry: MockConfigEntry) ->
|
|||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
LcnService.LOCK_KEYS,
|
||||
{CONF_ADDRESS: "pchk.s0.m7", CONF_TABLE: "a", CONF_STATE: "0011TT--"},
|
||||
{
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_TABLE: "a",
|
||||
CONF_STATE: "0011TT--",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
@ -334,9 +399,11 @@ async def test_service_lock_keys(hass: HomeAssistant, entry: MockConfigEntry) ->
|
|||
lock_keys.assert_awaited_with(0, lock_states)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_lock_keys_tab_a_temporary(
|
||||
hass: HomeAssistant, entry: MockConfigEntry
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test lock_keys (tab_a_temporary) service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
|
@ -350,7 +417,7 @@ async def test_service_lock_keys_tab_a_temporary(
|
|||
DOMAIN,
|
||||
LcnService.LOCK_KEYS,
|
||||
{
|
||||
CONF_ADDRESS: "pchk.s0.m7",
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_STATE: "0011TT--",
|
||||
CONF_TIME: 10,
|
||||
CONF_TIME_UNIT: "s",
|
||||
|
@ -376,7 +443,7 @@ async def test_service_lock_keys_tab_a_temporary(
|
|||
DOMAIN,
|
||||
LcnService.LOCK_KEYS,
|
||||
{
|
||||
CONF_ADDRESS: "pchk.s0.m7",
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_TABLE: "b",
|
||||
CONF_STATE: "0011TT--",
|
||||
CONF_TIME: 10,
|
||||
|
@ -386,8 +453,12 @@ async def test_service_lock_keys_tab_a_temporary(
|
|||
)
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_dyn_text(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_dyn_text(
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test dyn_text service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
@ -396,15 +467,23 @@ async def test_service_dyn_text(hass: HomeAssistant, entry: MockConfigEntry) ->
|
|||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
LcnService.DYN_TEXT,
|
||||
{CONF_ADDRESS: "pchk.s0.m7", CONF_ROW: 1, CONF_TEXT: "text in row 1"},
|
||||
{
|
||||
**device_config(hass, entry, config_type),
|
||||
CONF_ROW: 1,
|
||||
CONF_TEXT: "text in row 1",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
dyn_text.assert_awaited_with(0, "text in row 1")
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_pck(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
||||
@pytest.mark.parametrize("config_type", [CONF_ADDRESS, CONF_DEVICE_ID])
|
||||
async def test_service_pck(
|
||||
hass: HomeAssistant,
|
||||
entry: MockConfigEntry,
|
||||
config_type: str,
|
||||
) -> None:
|
||||
"""Test pck service."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
@ -413,14 +492,13 @@ async def test_service_pck(hass: HomeAssistant, entry: MockConfigEntry) -> None:
|
|||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
LcnService.PCK,
|
||||
{CONF_ADDRESS: "pchk.s0.m7", CONF_PCK: "PIN4"},
|
||||
{**device_config(hass, entry, config_type), CONF_PCK: "PIN4"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
pck.assert_awaited_with("PIN4")
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_service_called_with_invalid_host_id(
|
||||
hass: HomeAssistant, entry: MockConfigEntry
|
||||
) -> None:
|
||||
|
@ -437,3 +515,20 @@ async def test_service_called_with_invalid_host_id(
|
|||
)
|
||||
|
||||
pck.assert_not_awaited()
|
||||
|
||||
|
||||
async def test_service_with_deprecated_address_parameter(
|
||||
hass: HomeAssistant, entry: MockConfigEntry, issue_registry: ir.IssueRegistry
|
||||
) -> None:
|
||||
"""Test service puts issue in registry if called with address parameter."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
await init_integration(hass, entry)
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
LcnService.PCK,
|
||||
{CONF_ADDRESS: "pchk.s0.m7", CONF_PCK: "PIN4"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert issue_registry.async_get_issue(DOMAIN, "deprecated_address_parameter")
|
||||
|
|
Loading…
Reference in New Issue