mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 05:37:44 +00:00
Fix transition config storage in LCN light and scene platform (#127847)
This commit is contained in:
parent
519a888e82
commit
759fe54132
@ -11,10 +11,13 @@ from pypck.connection import PchkConnectionManager
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE_ID,
|
||||
CONF_DOMAIN,
|
||||
CONF_ENTITIES,
|
||||
CONF_IP_ADDRESS,
|
||||
CONF_PASSWORD,
|
||||
CONF_PORT,
|
||||
CONF_USERNAME,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
@ -24,7 +27,9 @@ from .const import (
|
||||
ADD_ENTITIES_CALLBACKS,
|
||||
CONF_ACKNOWLEDGE,
|
||||
CONF_DIM_MODE,
|
||||
CONF_DOMAIN_DATA,
|
||||
CONF_SK_NUM_TRIES,
|
||||
CONF_TRANSITION,
|
||||
CONNECTION,
|
||||
DOMAIN,
|
||||
PLATFORMS,
|
||||
@ -147,15 +152,25 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) ->
|
||||
config_entry.minor_version,
|
||||
)
|
||||
|
||||
if config_entry.version == 1:
|
||||
new_data = {**config_entry.data}
|
||||
new_data = {**config_entry.data}
|
||||
|
||||
if config_entry.version == 1:
|
||||
# update to 1.2 (add acknowledge flag)
|
||||
if config_entry.minor_version < 2:
|
||||
new_data[CONF_ACKNOWLEDGE] = False
|
||||
|
||||
hass.config_entries.async_update_entry(
|
||||
config_entry, data=new_data, minor_version=2, version=1
|
||||
)
|
||||
# update to 2.1 (fix transitions for lights and switches)
|
||||
new_entities_data = [*new_data[CONF_ENTITIES]]
|
||||
for entity in new_entities_data:
|
||||
if entity[CONF_DOMAIN] in [Platform.LIGHT, Platform.SCENE]:
|
||||
if entity[CONF_DOMAIN_DATA][CONF_TRANSITION] is None:
|
||||
entity[CONF_DOMAIN_DATA][CONF_TRANSITION] = 0
|
||||
entity[CONF_DOMAIN_DATA][CONF_TRANSITION] /= 1000.0
|
||||
new_data[CONF_ENTITIES] = new_entities_data
|
||||
|
||||
hass.config_entries.async_update_entry(
|
||||
config_entry, data=new_data, minor_version=1, version=2
|
||||
)
|
||||
|
||||
_LOGGER.debug(
|
||||
"Migration to configuration version %s.%s successful",
|
||||
|
@ -110,8 +110,8 @@ async def validate_connection(data: ConfigType) -> str | None:
|
||||
class LcnFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a LCN config flow."""
|
||||
|
||||
VERSION = 1
|
||||
MINOR_VERSION = 2
|
||||
VERSION = 2
|
||||
MINOR_VERSION = 1
|
||||
|
||||
async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult:
|
||||
"""Import existing configuration from LCN."""
|
||||
|
@ -90,7 +90,7 @@ class LcnOutputLight(LcnEntity, LightEntity):
|
||||
self.output = pypck.lcn_defs.OutputPort[config[CONF_DOMAIN_DATA][CONF_OUTPUT]]
|
||||
|
||||
self._transition = pypck.lcn_defs.time_to_ramp_value(
|
||||
config[CONF_DOMAIN_DATA][CONF_TRANSITION]
|
||||
config[CONF_DOMAIN_DATA][CONF_TRANSITION] * 1000.0
|
||||
)
|
||||
self.dimmable = config[CONF_DOMAIN_DATA][CONF_DIMMABLE]
|
||||
|
||||
|
@ -87,7 +87,7 @@ class LcnScene(LcnEntity, Scene):
|
||||
self.transition = None
|
||||
else:
|
||||
self.transition = pypck.lcn_defs.time_to_ramp_value(
|
||||
config[CONF_DOMAIN_DATA][CONF_TRANSITION]
|
||||
config[CONF_DOMAIN_DATA][CONF_TRANSITION] * 1000.0
|
||||
)
|
||||
|
||||
async def async_activate(self, **kwargs: Any) -> None:
|
||||
|
@ -95,7 +95,7 @@ DOMAIN_DATA_LIGHT: VolDictType = {
|
||||
vol.Required(CONF_OUTPUT): vol.All(vol.Upper, vol.In(OUTPUT_PORTS + RELAY_PORTS)),
|
||||
vol.Optional(CONF_DIMMABLE, default=False): vol.Coerce(bool),
|
||||
vol.Optional(CONF_TRANSITION, default=0): vol.All(
|
||||
vol.Coerce(float), vol.Range(min=0.0, max=486.0), lambda value: value * 1000
|
||||
vol.Coerce(float), vol.Range(min=0.0, max=486.0)
|
||||
),
|
||||
}
|
||||
|
||||
@ -106,13 +106,8 @@ DOMAIN_DATA_SCENE: VolDictType = {
|
||||
vol.Optional(CONF_OUTPUTS, default=[]): vol.All(
|
||||
cv.ensure_list, [vol.All(vol.Upper, vol.In(OUTPUT_PORTS + RELAY_PORTS))]
|
||||
),
|
||||
vol.Optional(CONF_TRANSITION, default=None): vol.Any(
|
||||
vol.All(
|
||||
vol.Coerce(int),
|
||||
vol.Range(min=0.0, max=486.0),
|
||||
lambda value: value * 1000,
|
||||
),
|
||||
None,
|
||||
vol.Optional(CONF_TRANSITION, default=0): vol.Any(
|
||||
vol.All(vol.Coerce(int), vol.Range(min=0.0, max=486.0))
|
||||
),
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
"domain_data": {
|
||||
"output": "OUTPUT1",
|
||||
"dimmable": true,
|
||||
"transition": 5000.0
|
||||
"transition": 5.0
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -43,7 +43,7 @@
|
||||
"domain_data": {
|
||||
"output": "OUTPUT2",
|
||||
"dimmable": false,
|
||||
"transition": 0
|
||||
"transition": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -145,7 +145,7 @@
|
||||
"register": 0,
|
||||
"scene": 0,
|
||||
"outputs": ["OUTPUT1", "OUTPUT2", "RELAY1"],
|
||||
"transition": null
|
||||
"transition": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -157,7 +157,7 @@
|
||||
"register": 0,
|
||||
"scene": 1,
|
||||
"outputs": ["OUTPUT1", "OUTPUT2", "RELAY1"],
|
||||
"transition": 10
|
||||
"transition": 10.0
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -156,7 +156,7 @@
|
||||
"register": 0,
|
||||
"scene": 1,
|
||||
"outputs": ["OUTPUT1", "OUTPUT2", "RELAY1"],
|
||||
"transition": 10
|
||||
"transition": 10000
|
||||
}
|
||||
},
|
||||
{
|
||||
|
231
tests/components/lcn/fixtures/config_entry_pchk_v1_2.json
Normal file
231
tests/components/lcn/fixtures/config_entry_pchk_v1_2.json
Normal file
@ -0,0 +1,231 @@
|
||||
{
|
||||
"host": "pchk",
|
||||
"ip_address": "192.168.2.41",
|
||||
"port": 4114,
|
||||
"username": "lcn",
|
||||
"password": "lcn",
|
||||
"sk_num_tries": 0,
|
||||
"dim_mode": "STEPS200",
|
||||
"acknowledge": false,
|
||||
"devices": [
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "TestModule",
|
||||
"hardware_serial": -1,
|
||||
"software_serial": -1,
|
||||
"hardware_type": -1
|
||||
},
|
||||
{
|
||||
"address": [0, 5, true],
|
||||
"name": "TestGroup",
|
||||
"hardware_serial": -1,
|
||||
"software_serial": -1,
|
||||
"hardware_type": -1
|
||||
}
|
||||
],
|
||||
"entities": [
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Light_Output1",
|
||||
"resource": "output1",
|
||||
"domain": "light",
|
||||
"domain_data": {
|
||||
"output": "OUTPUT1",
|
||||
"dimmable": true,
|
||||
"transition": 5000.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Light_Output2",
|
||||
"resource": "output2",
|
||||
"domain": "light",
|
||||
"domain_data": {
|
||||
"output": "OUTPUT2",
|
||||
"dimmable": false,
|
||||
"transition": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Light_Relay1",
|
||||
"resource": "relay1",
|
||||
"domain": "light",
|
||||
"domain_data": {
|
||||
"output": "RELAY1",
|
||||
"dimmable": false,
|
||||
"transition": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Switch_Output1",
|
||||
"resource": "output1",
|
||||
"domain": "switch",
|
||||
"domain_data": {
|
||||
"output": "OUTPUT1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Switch_Output2",
|
||||
"resource": "output2",
|
||||
"domain": "switch",
|
||||
"domain_data": {
|
||||
"output": "OUTPUT2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Switch_Relay1",
|
||||
"resource": "relay1",
|
||||
"domain": "switch",
|
||||
"domain_data": {
|
||||
"output": "RELAY1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Switch_Relay2",
|
||||
"resource": "relay2",
|
||||
"domain": "switch",
|
||||
"domain_data": {
|
||||
"output": "RELAY2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 5, true],
|
||||
"name": "Switch_Group5",
|
||||
"resource": "relay1",
|
||||
"domain": "switch",
|
||||
"domain_data": {
|
||||
"output": "RELAY1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Cover_Outputs",
|
||||
"resource": "outputs",
|
||||
"domain": "cover",
|
||||
"domain_data": {
|
||||
"motor": "OUTPUTS",
|
||||
"reverse_time": "RT1200"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Cover_Relays",
|
||||
"resource": "motor1",
|
||||
"domain": "cover",
|
||||
"domain_data": {
|
||||
"motor": "MOTOR1",
|
||||
"reverse_time": "RT1200"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Climate1",
|
||||
"resource": "var1.r1varsetpoint",
|
||||
"domain": "climate",
|
||||
"domain_data": {
|
||||
"source": "VAR1",
|
||||
"setpoint": "R1VARSETPOINT",
|
||||
"lockable": true,
|
||||
"min_temp": 0.0,
|
||||
"max_temp": 40.0,
|
||||
"unit_of_measurement": "°C"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Romantic",
|
||||
"resource": "0.0",
|
||||
"domain": "scene",
|
||||
"domain_data": {
|
||||
"register": 0,
|
||||
"scene": 0,
|
||||
"outputs": ["OUTPUT1", "OUTPUT2", "RELAY1"],
|
||||
"transition": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Romantic Transition",
|
||||
"resource": "0.1",
|
||||
"domain": "scene",
|
||||
"domain_data": {
|
||||
"register": 0,
|
||||
"scene": 1,
|
||||
"outputs": ["OUTPUT1", "OUTPUT2", "RELAY1"],
|
||||
"transition": 10000
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Sensor_LockRegulator1",
|
||||
"resource": "r1varsetpoint",
|
||||
"domain": "binary_sensor",
|
||||
"domain_data": {
|
||||
"source": "R1VARSETPOINT"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Binary_Sensor1",
|
||||
"resource": "binsensor1",
|
||||
"domain": "binary_sensor",
|
||||
"domain_data": {
|
||||
"source": "BINSENSOR1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Sensor_KeyLock",
|
||||
"resource": "a5",
|
||||
"domain": "binary_sensor",
|
||||
"domain_data": {
|
||||
"source": "A5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Sensor_Var1",
|
||||
"resource": "var1",
|
||||
"domain": "sensor",
|
||||
"domain_data": {
|
||||
"source": "VAR1",
|
||||
"unit_of_measurement": "°C"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Sensor_Setpoint1",
|
||||
"resource": "r1varsetpoint",
|
||||
"domain": "sensor",
|
||||
"domain_data": {
|
||||
"source": "R1VARSETPOINT",
|
||||
"unit_of_measurement": "°C"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Sensor_Led6",
|
||||
"resource": "led6",
|
||||
"domain": "sensor",
|
||||
"domain_data": {
|
||||
"source": "LED6",
|
||||
"unit_of_measurement": "NATIVE"
|
||||
}
|
||||
},
|
||||
{
|
||||
"address": [0, 7, false],
|
||||
"name": "Sensor_LogicOp1",
|
||||
"resource": "logicop1",
|
||||
"domain": "sensor",
|
||||
"domain_data": {
|
||||
"source": "LOGICOP1",
|
||||
"unit_of_measurement": "NATIVE"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -139,6 +139,22 @@ async def test_migrate_1_1(hass: HomeAssistant, entry) -> None:
|
||||
|
||||
entry_migrated = hass.config_entries.async_get_entry(entry_v1_1.entry_id)
|
||||
assert entry_migrated.state is ConfigEntryState.LOADED
|
||||
assert entry_migrated.version == 1
|
||||
assert entry_migrated.minor_version == 2
|
||||
assert entry_migrated.version == 2
|
||||
assert entry_migrated.minor_version == 1
|
||||
assert entry_migrated.data == entry.data
|
||||
|
||||
|
||||
@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager)
|
||||
async def test_migrate_1_2(hass: HomeAssistant, entry) -> None:
|
||||
"""Test migration config entry."""
|
||||
entry_v1_2 = create_config_entry("pchk_v1_2", version=(1, 2))
|
||||
entry_v1_2.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(entry_v1_2.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entry_migrated = hass.config_entries.async_get_entry(entry_v1_2.entry_id)
|
||||
assert entry_migrated.state is ConfigEntryState.LOADED
|
||||
assert entry_migrated.version == 2
|
||||
assert entry_migrated.minor_version == 1
|
||||
assert entry_migrated.data == entry.data
|
||||
|
@ -51,7 +51,7 @@ async def test_scene_activate(
|
||||
assert state is not None
|
||||
|
||||
activate_scene.assert_awaited_with(
|
||||
0, 0, [OutputPort.OUTPUT1, OutputPort.OUTPUT2], [RelayPort.RELAY1], None
|
||||
0, 0, [OutputPort.OUTPUT1, OutputPort.OUTPUT2], [RelayPort.RELAY1], 0.0
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user