mirror of
https://github.com/home-assistant/core.git
synced 2025-06-25 01:21:51 +02:00
@ -12,7 +12,7 @@ from aiolyric import Lyric
|
||||
from aiolyric.exceptions import LyricAuthenticationException, LyricException
|
||||
from aiolyric.objects.device import LyricDevice
|
||||
from aiolyric.objects.location import LyricLocation
|
||||
from aiolyric.objects.priority import LyricAccessories, LyricRoom
|
||||
from aiolyric.objects.priority import LyricAccessory, LyricRoom
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
@ -80,11 +80,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
await lyric.get_locations()
|
||||
await asyncio.gather(
|
||||
*(
|
||||
lyric.get_thermostat_rooms(location.locationID, device.deviceID)
|
||||
lyric.get_thermostat_rooms(
|
||||
location.location_id, device.device_id
|
||||
)
|
||||
for location in lyric.locations
|
||||
for device in location.devices
|
||||
if device.deviceClass == "Thermostat"
|
||||
and device.deviceID.startswith("LCC")
|
||||
if device.device_class == "Thermostat"
|
||||
and device.device_id.startswith("LCC")
|
||||
)
|
||||
)
|
||||
|
||||
@ -143,7 +145,7 @@ class LyricEntity(CoordinatorEntity[DataUpdateCoordinator[Lyric]]):
|
||||
super().__init__(coordinator)
|
||||
self._key = key
|
||||
self._location = location
|
||||
self._mac_id = device.macID
|
||||
self._mac_id = device.mac_id
|
||||
self._update_thermostat = coordinator.data.update_thermostat
|
||||
self._update_fan = coordinator.data.update_fan
|
||||
|
||||
@ -155,7 +157,7 @@ class LyricEntity(CoordinatorEntity[DataUpdateCoordinator[Lyric]]):
|
||||
@property
|
||||
def location(self) -> LyricLocation:
|
||||
"""Get the Lyric Location."""
|
||||
return self.coordinator.data.locations_dict[self._location.locationID]
|
||||
return self.coordinator.data.locations_dict[self._location.location_id]
|
||||
|
||||
@property
|
||||
def device(self) -> LyricDevice:
|
||||
@ -173,7 +175,7 @@ class LyricDeviceEntity(LyricEntity):
|
||||
identifiers={(dr.CONNECTION_NETWORK_MAC, self._mac_id)},
|
||||
connections={(dr.CONNECTION_NETWORK_MAC, self._mac_id)},
|
||||
manufacturer="Honeywell",
|
||||
model=self.device.deviceModel,
|
||||
model=self.device.device_model,
|
||||
name=f"{self.device.name} Thermostat",
|
||||
)
|
||||
|
||||
@ -187,7 +189,7 @@ class LyricAccessoryEntity(LyricDeviceEntity):
|
||||
location: LyricLocation,
|
||||
device: LyricDevice,
|
||||
room: LyricRoom,
|
||||
accessory: LyricAccessories,
|
||||
accessory: LyricAccessory,
|
||||
key: str,
|
||||
) -> None:
|
||||
"""Initialize the Honeywell Lyric accessory entity."""
|
||||
@ -207,7 +209,7 @@ class LyricAccessoryEntity(LyricDeviceEntity):
|
||||
},
|
||||
manufacturer="Honeywell",
|
||||
model="RCHTSENSOR",
|
||||
name=f"{self.room.roomName} Sensor",
|
||||
name=f"{self.room.room_name} Sensor",
|
||||
via_device=(dr.CONNECTION_NETWORK_MAC, self._mac_id),
|
||||
)
|
||||
|
||||
@ -217,7 +219,7 @@ class LyricAccessoryEntity(LyricDeviceEntity):
|
||||
return self.coordinator.data.rooms_dict[self._mac_id][self._room_id]
|
||||
|
||||
@property
|
||||
def accessory(self) -> LyricAccessories:
|
||||
def accessory(self) -> LyricAccessory:
|
||||
"""Get the Lyric Device."""
|
||||
return next(
|
||||
accessory
|
||||
|
@ -132,7 +132,7 @@ async def async_setup_entry(
|
||||
LyricClimate(
|
||||
coordinator,
|
||||
ClimateEntityDescription(
|
||||
key=f"{device.macID}_thermostat",
|
||||
key=f"{device.mac_id}_thermostat",
|
||||
name=device.name,
|
||||
),
|
||||
location,
|
||||
@ -185,7 +185,7 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
) -> None:
|
||||
"""Initialize Honeywell Lyric climate entity."""
|
||||
# Define thermostat type (TCC - e.g., Lyric round; LCC - e.g., T5,6)
|
||||
if device.changeableValues.thermostatSetpointStatus:
|
||||
if device.changeable_values.thermostat_setpoint_status:
|
||||
self._attr_thermostat_type = LyricThermostatType.LCC
|
||||
else:
|
||||
self._attr_thermostat_type = LyricThermostatType.TCC
|
||||
@ -202,15 +202,15 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
self._attr_hvac_modes = [HVACMode.OFF]
|
||||
|
||||
# Add supported lyric thermostat features
|
||||
if LYRIC_HVAC_MODE_HEAT in device.allowedModes:
|
||||
if LYRIC_HVAC_MODE_HEAT in device.allowed_modes:
|
||||
self._attr_hvac_modes.append(HVACMode.HEAT)
|
||||
|
||||
if LYRIC_HVAC_MODE_COOL in device.allowedModes:
|
||||
if LYRIC_HVAC_MODE_COOL in device.allowed_modes:
|
||||
self._attr_hvac_modes.append(HVACMode.COOL)
|
||||
|
||||
if (
|
||||
LYRIC_HVAC_MODE_HEAT in device.allowedModes
|
||||
and LYRIC_HVAC_MODE_COOL in device.allowedModes
|
||||
LYRIC_HVAC_MODE_HEAT in device.allowed_modes
|
||||
and LYRIC_HVAC_MODE_COOL in device.allowed_modes
|
||||
):
|
||||
self._attr_hvac_modes.append(HVACMode.HEAT_COOL)
|
||||
|
||||
@ -242,19 +242,19 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
coordinator,
|
||||
location,
|
||||
device,
|
||||
f"{device.macID}_thermostat",
|
||||
f"{device.mac_id}_thermostat",
|
||||
)
|
||||
self.entity_description = description
|
||||
|
||||
@property
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Return the current temperature."""
|
||||
return self.device.indoorTemperature
|
||||
return self.device.indoor_temperature
|
||||
|
||||
@property
|
||||
def hvac_action(self) -> HVACAction | None:
|
||||
"""Return the current hvac action."""
|
||||
action = HVAC_ACTIONS.get(self.device.operationStatus.mode, None)
|
||||
action = HVAC_ACTIONS.get(self.device.operation_status.mode, None)
|
||||
if action == HVACAction.OFF and self.hvac_mode != HVACMode.OFF:
|
||||
action = HVACAction.IDLE
|
||||
return action
|
||||
@ -262,63 +262,63 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
@property
|
||||
def hvac_mode(self) -> HVACMode:
|
||||
"""Return the hvac mode."""
|
||||
return HVAC_MODES[self.device.changeableValues.mode]
|
||||
return HVAC_MODES[self.device.changeable_values.mode]
|
||||
|
||||
@property
|
||||
def target_temperature(self) -> float | None:
|
||||
"""Return the temperature we try to reach."""
|
||||
device = self.device
|
||||
if (
|
||||
device.changeableValues.autoChangeoverActive
|
||||
or HVAC_MODES[device.changeableValues.mode] == HVACMode.OFF
|
||||
device.changeable_values.auto_changeover_active
|
||||
or HVAC_MODES[device.changeable_values.mode] == HVACMode.OFF
|
||||
):
|
||||
return None
|
||||
if self.hvac_mode == HVACMode.COOL:
|
||||
return device.changeableValues.coolSetpoint
|
||||
return device.changeableValues.heatSetpoint
|
||||
return device.changeable_values.cool_setpoint
|
||||
return device.changeable_values.heat_setpoint
|
||||
|
||||
@property
|
||||
def target_temperature_high(self) -> float | None:
|
||||
"""Return the highbound target temperature we try to reach."""
|
||||
device = self.device
|
||||
if (
|
||||
not device.changeableValues.autoChangeoverActive
|
||||
or HVAC_MODES[device.changeableValues.mode] == HVACMode.OFF
|
||||
not device.changeable_values.auto_changeover_active
|
||||
or HVAC_MODES[device.changeable_values.mode] == HVACMode.OFF
|
||||
):
|
||||
return None
|
||||
return device.changeableValues.coolSetpoint
|
||||
return device.changeable_values.cool_setpoint
|
||||
|
||||
@property
|
||||
def target_temperature_low(self) -> float | None:
|
||||
"""Return the lowbound target temperature we try to reach."""
|
||||
device = self.device
|
||||
if (
|
||||
not device.changeableValues.autoChangeoverActive
|
||||
or HVAC_MODES[device.changeableValues.mode] == HVACMode.OFF
|
||||
not device.changeable_values.auto_changeover_active
|
||||
or HVAC_MODES[device.changeable_values.mode] == HVACMode.OFF
|
||||
):
|
||||
return None
|
||||
return device.changeableValues.heatSetpoint
|
||||
return device.changeable_values.heat_setpoint
|
||||
|
||||
@property
|
||||
def preset_mode(self) -> str | None:
|
||||
"""Return current preset mode."""
|
||||
return self.device.changeableValues.thermostatSetpointStatus
|
||||
return self.device.changeable_values.thermostat_setpoint_status
|
||||
|
||||
@property
|
||||
def min_temp(self) -> float:
|
||||
"""Identify min_temp in Lyric API or defaults if not available."""
|
||||
device = self.device
|
||||
if LYRIC_HVAC_MODE_COOL in device.allowedModes:
|
||||
return device.minCoolSetpoint
|
||||
return device.minHeatSetpoint
|
||||
if LYRIC_HVAC_MODE_COOL in device.allowed_modes:
|
||||
return device.min_cool_setpoint
|
||||
return device.min_heat_setpoint
|
||||
|
||||
@property
|
||||
def max_temp(self) -> float:
|
||||
"""Identify max_temp in Lyric API or defaults if not available."""
|
||||
device = self.device
|
||||
if LYRIC_HVAC_MODE_HEAT in device.allowedModes:
|
||||
return device.maxHeatSetpoint
|
||||
return device.maxCoolSetpoint
|
||||
if LYRIC_HVAC_MODE_HEAT in device.allowed_modes:
|
||||
return device.max_heat_setpoint
|
||||
return device.max_cool_setpoint
|
||||
|
||||
@property
|
||||
def fan_mode(self) -> str | None:
|
||||
@ -339,7 +339,7 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW)
|
||||
target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH)
|
||||
|
||||
if device.changeableValues.mode == LYRIC_HVAC_MODE_HEAT_COOL:
|
||||
if device.changeable_values.mode == LYRIC_HVAC_MODE_HEAT_COOL:
|
||||
if target_temp_low is None or target_temp_high is None:
|
||||
raise HomeAssistantError(
|
||||
"Could not find target_temp_low and/or target_temp_high in"
|
||||
@ -349,7 +349,7 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
# If TCC device pass the heatCoolMode value, otherwise
|
||||
# if LCC device can skip the mode altogether
|
||||
if self._attr_thermostat_type is LyricThermostatType.TCC:
|
||||
mode = HVAC_MODES[device.changeableValues.heatCoolMode]
|
||||
mode = HVAC_MODES[device.changeable_values.heat_cool_mode]
|
||||
else:
|
||||
mode = None
|
||||
|
||||
@ -401,7 +401,7 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
# otherwise it turns to Auto briefly and then reverts to Off.
|
||||
# This is the behavior that happens with the native app as well,
|
||||
# so likely a bug in the api itself.
|
||||
if HVAC_MODES[self.device.changeableValues.mode] == HVACMode.OFF:
|
||||
if HVAC_MODES[self.device.changeable_values.mode] == HVACMode.OFF:
|
||||
_LOGGER.debug(
|
||||
"HVAC mode passed to lyric: %s",
|
||||
HVAC_MODES[LYRIC_HVAC_MODE_COOL],
|
||||
@ -427,7 +427,7 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
else:
|
||||
_LOGGER.debug(
|
||||
"HVAC mode passed to lyric: %s",
|
||||
HVAC_MODES[self.device.changeableValues.mode],
|
||||
HVAC_MODES[self.device.changeable_values.mode],
|
||||
)
|
||||
await self._update_thermostat(
|
||||
self.location, self.device, autoChangeoverActive=True
|
||||
@ -448,7 +448,7 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
# otherwise leave unchanged.
|
||||
if (
|
||||
LYRIC_HVAC_MODES[hvac_mode] == LYRIC_HVAC_MODE_HEAT_COOL
|
||||
and not self.device.changeableValues.autoChangeoverActive
|
||||
and not self.device.changeable_values.auto_changeover_active
|
||||
):
|
||||
auto_changeover = True
|
||||
else:
|
||||
|
@ -22,5 +22,5 @@
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["aiolyric"],
|
||||
"quality_scale": "silver",
|
||||
"requirements": ["aiolyric==1.1.0"]
|
||||
"requirements": ["aiolyric==2.0.1"]
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ from datetime import datetime, timedelta
|
||||
from aiolyric import Lyric
|
||||
from aiolyric.objects.device import LyricDevice
|
||||
from aiolyric.objects.location import LyricLocation
|
||||
from aiolyric.objects.priority import LyricAccessories, LyricRoom
|
||||
from aiolyric.objects.priority import LyricAccessory, LyricRoom
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
@ -55,8 +55,8 @@ class LyricSensorEntityDescription(SensorEntityDescription):
|
||||
class LyricSensorAccessoryEntityDescription(SensorEntityDescription):
|
||||
"""Class describing Honeywell Lyric room sensor entities."""
|
||||
|
||||
value_fn: Callable[[LyricRoom, LyricAccessories], StateType | datetime]
|
||||
suitable_fn: Callable[[LyricRoom, LyricAccessories], bool]
|
||||
value_fn: Callable[[LyricRoom, LyricAccessory], StateType | datetime]
|
||||
suitable_fn: Callable[[LyricRoom, LyricAccessory], bool]
|
||||
|
||||
|
||||
DEVICE_SENSORS: list[LyricSensorEntityDescription] = [
|
||||
@ -65,8 +65,8 @@ DEVICE_SENSORS: list[LyricSensorEntityDescription] = [
|
||||
translation_key="indoor_temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_fn=lambda device: device.indoorTemperature,
|
||||
suitable_fn=lambda device: device.indoorTemperature,
|
||||
value_fn=lambda device: device.indoor_temperature,
|
||||
suitable_fn=lambda device: device.indoor_temperature,
|
||||
),
|
||||
LyricSensorEntityDescription(
|
||||
key="indoor_humidity",
|
||||
@ -74,16 +74,16 @@ DEVICE_SENSORS: list[LyricSensorEntityDescription] = [
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_fn=lambda device: device.indoorHumidity,
|
||||
suitable_fn=lambda device: device.indoorHumidity,
|
||||
value_fn=lambda device: device.indoor_humidity,
|
||||
suitable_fn=lambda device: device.indoor_humidity,
|
||||
),
|
||||
LyricSensorEntityDescription(
|
||||
key="outdoor_temperature",
|
||||
translation_key="outdoor_temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_fn=lambda device: device.outdoorTemperature,
|
||||
suitable_fn=lambda device: device.outdoorTemperature,
|
||||
value_fn=lambda device: device.outdoor_temperature,
|
||||
suitable_fn=lambda device: device.outdoor_temperature,
|
||||
),
|
||||
LyricSensorEntityDescription(
|
||||
key="outdoor_humidity",
|
||||
@ -91,29 +91,30 @@ DEVICE_SENSORS: list[LyricSensorEntityDescription] = [
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_fn=lambda device: device.displayedOutdoorHumidity,
|
||||
suitable_fn=lambda device: device.displayedOutdoorHumidity,
|
||||
value_fn=lambda device: device.displayed_outdoor_humidity,
|
||||
suitable_fn=lambda device: device.displayed_outdoor_humidity,
|
||||
),
|
||||
LyricSensorEntityDescription(
|
||||
key="next_period_time",
|
||||
translation_key="next_period_time",
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
value_fn=lambda device: get_datetime_from_future_time(
|
||||
device.changeableValues.nextPeriodTime
|
||||
device.changeable_values.next_period_time
|
||||
),
|
||||
suitable_fn=lambda device: (
|
||||
device.changeableValues and device.changeableValues.nextPeriodTime
|
||||
device.changeable_values and device.changeable_values.next_period_time
|
||||
),
|
||||
),
|
||||
LyricSensorEntityDescription(
|
||||
key="setpoint_status",
|
||||
translation_key="setpoint_status",
|
||||
value_fn=lambda device: get_setpoint_status(
|
||||
device.changeableValues.thermostatSetpointStatus,
|
||||
device.changeableValues.nextPeriodTime,
|
||||
device.changeable_values.thermostat_setpoint_status,
|
||||
device.changeable_values.next_period_time,
|
||||
),
|
||||
suitable_fn=lambda device: (
|
||||
device.changeableValues and device.changeableValues.thermostatSetpointStatus
|
||||
device.changeable_values
|
||||
and device.changeable_values.thermostat_setpoint_status
|
||||
),
|
||||
),
|
||||
]
|
||||
@ -133,7 +134,7 @@ ACCESSORY_SENSORS: list[LyricSensorAccessoryEntityDescription] = [
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_fn=lambda room, _: room.roomAvgHumidity,
|
||||
value_fn=lambda room, _: room.room_avg_humidity,
|
||||
suitable_fn=lambda _, accessory: accessory.type == "IndoorAirSensor",
|
||||
),
|
||||
]
|
||||
@ -182,7 +183,7 @@ async def async_setup_entry(
|
||||
)
|
||||
for location in coordinator.data.locations
|
||||
for device in location.devices
|
||||
for room in coordinator.data.rooms_dict.get(device.macID, {}).values()
|
||||
for room in coordinator.data.rooms_dict.get(device.mac_id, {}).values()
|
||||
for accessory in room.accessories
|
||||
for accessory_sensor in ACCESSORY_SENSORS
|
||||
if accessory_sensor.suitable_fn(room, accessory)
|
||||
@ -206,7 +207,7 @@ class LyricSensor(LyricDeviceEntity, SensorEntity):
|
||||
coordinator,
|
||||
location,
|
||||
device,
|
||||
f"{device.macID}_{description.key}",
|
||||
f"{device.mac_id}_{description.key}",
|
||||
)
|
||||
self.entity_description = description
|
||||
if description.device_class == SensorDeviceClass.TEMPERATURE:
|
||||
@ -233,7 +234,7 @@ class LyricAccessorySensor(LyricAccessoryEntity, SensorEntity):
|
||||
location: LyricLocation,
|
||||
parentDevice: LyricDevice,
|
||||
room: LyricRoom,
|
||||
accessory: LyricAccessories,
|
||||
accessory: LyricAccessory,
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
super().__init__(
|
||||
@ -242,7 +243,7 @@ class LyricAccessorySensor(LyricAccessoryEntity, SensorEntity):
|
||||
parentDevice,
|
||||
room,
|
||||
accessory,
|
||||
f"{parentDevice.macID}_room{room.id}_acc{accessory.id}_{description.key}",
|
||||
f"{parentDevice.mac_id}_room{room.id}_acc{accessory.id}_{description.key}",
|
||||
)
|
||||
self.entity_description = description
|
||||
if description.device_class == SensorDeviceClass.TEMPERATURE:
|
||||
|
@ -285,7 +285,7 @@ aiolivisi==0.0.19
|
||||
aiolookin==1.0.0
|
||||
|
||||
# homeassistant.components.lyric
|
||||
aiolyric==1.1.0
|
||||
aiolyric==2.0.1
|
||||
|
||||
# homeassistant.components.mealie
|
||||
aiomealie==0.8.1
|
||||
|
@ -267,7 +267,7 @@ aiolivisi==0.0.19
|
||||
aiolookin==1.0.0
|
||||
|
||||
# homeassistant.components.lyric
|
||||
aiolyric==1.1.0
|
||||
aiolyric==2.0.1
|
||||
|
||||
# homeassistant.components.mealie
|
||||
aiomealie==0.8.1
|
||||
|
Reference in New Issue
Block a user