Use shorthand attributes in Smartthings (#100215)

This commit is contained in:
Joost Lekkerkerker 2023-09-12 19:26:33 +02:00 committed by GitHub
parent e84a4661b0
commit a09372590f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 59 additions and 175 deletions

View file

@ -429,6 +429,17 @@ class SmartThingsEntity(Entity):
"""Initialize the instance.""" """Initialize the instance."""
self._device = device self._device = device
self._dispatcher_remove = None self._dispatcher_remove = None
self._attr_name = device.label
self._attr_unique_id = device.device_id
self._attr_device_info = DeviceInfo(
configuration_url="https://account.smartthings.com",
identifiers={(DOMAIN, device.device_id)},
manufacturer=device.status.ocf_manufacturer_name,
model=device.status.ocf_model_number,
name=device.label,
hw_version=device.status.ocf_hardware_version,
sw_version=device.status.ocf_firmware_version,
)
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""Device added to hass.""" """Device added to hass."""
@ -446,26 +457,3 @@ class SmartThingsEntity(Entity):
"""Disconnect the device when removed.""" """Disconnect the device when removed."""
if self._dispatcher_remove: if self._dispatcher_remove:
self._dispatcher_remove() self._dispatcher_remove()
@property
def device_info(self) -> DeviceInfo:
"""Get attributes about the device."""
return DeviceInfo(
configuration_url="https://account.smartthings.com",
identifiers={(DOMAIN, self._device.device_id)},
manufacturer=self._device.status.ocf_manufacturer_name,
model=self._device.status.ocf_model_number,
name=self._device.label,
hw_version=self._device.status.ocf_hardware_version,
sw_version=self._device.status.ocf_firmware_version,
)
@property
def name(self) -> str:
"""Return the name of the device."""
return self._device.label
@property
def unique_id(self) -> str:
"""Return a unique ID."""
return self._device.device_id

View file

@ -73,28 +73,12 @@ class SmartThingsBinarySensor(SmartThingsEntity, BinarySensorEntity):
"""Init the class.""" """Init the class."""
super().__init__(device) super().__init__(device)
self._attribute = attribute self._attribute = attribute
self._attr_name = f"{device.label} {attribute}"
@property self._attr_unique_id = f"{device.device_id}.{attribute}"
def name(self) -> str: self._attr_device_class = ATTRIB_TO_CLASS[attribute]
"""Return the name of the binary sensor.""" self._attr_entity_category = ATTRIB_TO_ENTTIY_CATEGORY.get(attribute)
return f"{self._device.label} {self._attribute}"
@property
def unique_id(self) -> str:
"""Return a unique ID."""
return f"{self._device.device_id}.{self._attribute}"
@property @property
def is_on(self): def is_on(self):
"""Return true if the binary sensor is on.""" """Return true if the binary sensor is on."""
return self._device.status.is_on(self._attribute) return self._device.status.is_on(self._attribute)
@property
def device_class(self):
"""Return the class of this device."""
return ATTRIB_TO_CLASS[self._attribute]
@property
def entity_category(self):
"""Return the entity category of this device."""
return ATTRIB_TO_ENTTIY_CATEGORY.get(self._attribute)

View file

@ -77,10 +77,8 @@ class SmartThingsCover(SmartThingsEntity, CoverEntity):
def __init__(self, device): def __init__(self, device):
"""Initialize the cover class.""" """Initialize the cover class."""
super().__init__(device) super().__init__(device)
self._device_class = None
self._current_cover_position = None self._current_cover_position = None
self._state = None self._state = None
self._state_attrs = None
self._attr_supported_features = ( self._attr_supported_features = (
CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE
) )
@ -90,6 +88,13 @@ class SmartThingsCover(SmartThingsEntity, CoverEntity):
): ):
self._attr_supported_features |= CoverEntityFeature.SET_POSITION self._attr_supported_features |= CoverEntityFeature.SET_POSITION
if Capability.door_control in device.capabilities:
self._attr_device_class = CoverDeviceClass.DOOR
elif Capability.window_shade in device.capabilities:
self._attr_device_class = CoverDeviceClass.SHADE
elif Capability.garage_door_control in device.capabilities:
self._attr_device_class = CoverDeviceClass.GARAGE
async def async_close_cover(self, **kwargs: Any) -> None: async def async_close_cover(self, **kwargs: Any) -> None:
"""Close cover.""" """Close cover."""
# Same command for all 3 supported capabilities # Same command for all 3 supported capabilities
@ -121,24 +126,21 @@ class SmartThingsCover(SmartThingsEntity, CoverEntity):
async def async_update(self) -> None: async def async_update(self) -> None:
"""Update the attrs of the cover.""" """Update the attrs of the cover."""
if Capability.door_control in self._device.capabilities: if Capability.door_control in self._device.capabilities:
self._device_class = CoverDeviceClass.DOOR
self._state = VALUE_TO_STATE.get(self._device.status.door) self._state = VALUE_TO_STATE.get(self._device.status.door)
elif Capability.window_shade in self._device.capabilities: elif Capability.window_shade in self._device.capabilities:
self._device_class = CoverDeviceClass.SHADE
self._state = VALUE_TO_STATE.get(self._device.status.window_shade) self._state = VALUE_TO_STATE.get(self._device.status.window_shade)
elif Capability.garage_door_control in self._device.capabilities: elif Capability.garage_door_control in self._device.capabilities:
self._device_class = CoverDeviceClass.GARAGE
self._state = VALUE_TO_STATE.get(self._device.status.door) self._state = VALUE_TO_STATE.get(self._device.status.door)
if Capability.window_shade_level in self._device.capabilities: if Capability.window_shade_level in self._device.capabilities:
self._current_cover_position = self._device.status.shade_level self._attr_current_cover_position = self._device.status.shade_level
elif Capability.switch_level in self._device.capabilities: elif Capability.switch_level in self._device.capabilities:
self._current_cover_position = self._device.status.level self._attr_current_cover_position = self._device.status.level
self._state_attrs = {} self._attr_extra_state_attributes = {}
battery = self._device.status.attributes[Attribute.battery].value battery = self._device.status.attributes[Attribute.battery].value
if battery is not None: if battery is not None:
self._state_attrs[ATTR_BATTERY_LEVEL] = battery self._attr_extra_state_attributes[ATTR_BATTERY_LEVEL] = battery
@property @property
def is_opening(self) -> bool: def is_opening(self) -> bool:
@ -156,18 +158,3 @@ class SmartThingsCover(SmartThingsEntity, CoverEntity):
if self._state == STATE_CLOSED: if self._state == STATE_CLOSED:
return True return True
return None if self._state is None else False return None if self._state is None else False
@property
def current_cover_position(self) -> int | None:
"""Return current position of cover."""
return self._current_cover_position
@property
def device_class(self) -> CoverDeviceClass | None:
"""Define this cover as a garage door."""
return self._device_class
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Get additional state attributes."""
return self._state_attrs

View file

@ -52,6 +52,7 @@ class SmartThingsFan(SmartThingsEntity, FanEntity):
"""Define a SmartThings Fan.""" """Define a SmartThings Fan."""
_attr_supported_features = FanEntityFeature.SET_SPEED _attr_supported_features = FanEntityFeature.SET_SPEED
_attr_speed_count = int_states_in_range(SPEED_RANGE)
async def async_set_percentage(self, percentage: int) -> None: async def async_set_percentage(self, percentage: int) -> None:
"""Set the speed percentage of the fan.""" """Set the speed percentage of the fan."""
@ -94,8 +95,3 @@ class SmartThingsFan(SmartThingsEntity, FanEntity):
def percentage(self) -> int: def percentage(self) -> int:
"""Return the current speed percentage.""" """Return the current speed percentage."""
return ranged_value_to_percentage(SPEED_RANGE, self._device.status.fan_speed) return ranged_value_to_percentage(SPEED_RANGE, self._device.status.fan_speed)
@property
def speed_count(self) -> int:
"""Return the number of speeds the fan supports."""
return int_states_in_range(SPEED_RANGE)

View file

@ -75,12 +75,19 @@ class SmartThingsLight(SmartThingsEntity, LightEntity):
_attr_supported_color_modes: set[ColorMode] _attr_supported_color_modes: set[ColorMode]
# SmartThings does not expose this attribute, instead it's
# implemented within each device-type handler. This value is the
# lowest kelvin found supported across 20+ handlers.
_attr_max_mireds = 500 # 2000K
# SmartThings does not expose this attribute, instead it's
# implemented within each device-type handler. This value is the
# highest kelvin found supported across 20+ handlers.
_attr_min_mireds = 111 # 9000K
def __init__(self, device): def __init__(self, device):
"""Initialize a SmartThingsLight.""" """Initialize a SmartThingsLight."""
super().__init__(device) super().__init__(device)
self._brightness = None
self._color_temp = None
self._hs_color = None
self._attr_supported_color_modes = self._determine_color_modes() self._attr_supported_color_modes = self._determine_color_modes()
self._attr_supported_features = self._determine_features() self._attr_supported_features = self._determine_features()
@ -151,17 +158,17 @@ class SmartThingsLight(SmartThingsEntity, LightEntity):
"""Update entity attributes when the device status has changed.""" """Update entity attributes when the device status has changed."""
# Brightness and transition # Brightness and transition
if brightness_supported(self._attr_supported_color_modes): if brightness_supported(self._attr_supported_color_modes):
self._brightness = int( self._attr_brightness = int(
convert_scale(self._device.status.level, 100, 255, 0) convert_scale(self._device.status.level, 100, 255, 0)
) )
# Color Temperature # Color Temperature
if ColorMode.COLOR_TEMP in self._attr_supported_color_modes: if ColorMode.COLOR_TEMP in self._attr_supported_color_modes:
self._color_temp = color_util.color_temperature_kelvin_to_mired( self._attr_color_temp = color_util.color_temperature_kelvin_to_mired(
self._device.status.color_temperature self._device.status.color_temperature
) )
# Color # Color
if ColorMode.HS in self._attr_supported_color_modes: if ColorMode.HS in self._attr_supported_color_modes:
self._hs_color = ( self._attr_hs_color = (
convert_scale(self._device.status.hue, 100, 360), convert_scale(self._device.status.hue, 100, 360),
self._device.status.saturation, self._device.status.saturation,
) )
@ -197,42 +204,11 @@ class SmartThingsLight(SmartThingsEntity, LightEntity):
return list(self._attr_supported_color_modes)[0] return list(self._attr_supported_color_modes)[0]
# The light supports hs + color temp, determine which one it is # The light supports hs + color temp, determine which one it is
if self._hs_color and self._hs_color[1]: if self._attr_hs_color and self._attr_hs_color[1]:
return ColorMode.HS return ColorMode.HS
return ColorMode.COLOR_TEMP return ColorMode.COLOR_TEMP
@property
def brightness(self):
"""Return the brightness of this light between 0..255."""
return self._brightness
@property
def color_temp(self):
"""Return the CT color value in mireds."""
return self._color_temp
@property
def hs_color(self):
"""Return the hue and saturation color value [float, float]."""
return self._hs_color
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
"""Return true if light is on.""" """Return true if light is on."""
return self._device.status.switch return self._device.status.switch
@property
def max_mireds(self):
"""Return the warmest color_temp that this light supports."""
# SmartThings does not expose this attribute, instead it's
# implemented within each device-type handler. This value is the
# lowest kelvin found supported across 20+ handlers.
return 500 # 2000K
@property
def min_mireds(self):
"""Return the coldest color_temp that this light supports."""
# SmartThings does not expose this attribute, instead it's
# implemented within each device-type handler. This value is the
# highest kelvin found supported across 20+ handlers.
return 111 # 9000K

View file

@ -25,6 +25,8 @@ class SmartThingsScene(Scene):
def __init__(self, scene): def __init__(self, scene):
"""Init the scene class.""" """Init the scene class."""
self._scene = scene self._scene = scene
self._attr_name = scene.name
self._attr_unique_id = scene.scene_id
async def async_activate(self, **kwargs: Any) -> None: async def async_activate(self, **kwargs: Any) -> None:
"""Activate scene.""" """Activate scene."""
@ -38,13 +40,3 @@ class SmartThingsScene(Scene):
"color": self._scene.color, "color": self._scene.color,
"location_id": self._scene.location_id, "location_id": self._scene.location_id,
} }
@property
def name(self) -> str:
"""Return the name of the device."""
return self._scene.name
@property
def unique_id(self) -> str:
"""Return a unique ID."""
return self._scene.scene_id

View file

@ -629,44 +629,30 @@ class SmartThingsSensor(SmartThingsEntity, SensorEntity):
attribute: str, attribute: str,
name: str, name: str,
default_unit: str, default_unit: str,
device_class: str, device_class: SensorDeviceClass,
state_class: str | None, state_class: str | None,
entity_category: EntityCategory | None, entity_category: EntityCategory | None,
) -> None: ) -> None:
"""Init the class.""" """Init the class."""
super().__init__(device) super().__init__(device)
self._attribute = attribute self._attribute = attribute
self._name = name self._attr_name = f"{device.label} {name}"
self._device_class = device_class self._attr_unique_id = f"{device.device_id}.{attribute}"
self._attr_device_class = device_class
self._default_unit = default_unit self._default_unit = default_unit
self._attr_state_class = state_class self._attr_state_class = state_class
self._attr_entity_category = entity_category self._attr_entity_category = entity_category
@property
def name(self) -> str:
"""Return the name of the sensor."""
return f"{self._device.label} {self._name}"
@property
def unique_id(self) -> str:
"""Return a unique ID."""
return f"{self._device.device_id}.{self._attribute}"
@property @property
def native_value(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
value = self._device.status.attributes[self._attribute].value value = self._device.status.attributes[self._attribute].value
if self._device_class != SensorDeviceClass.TIMESTAMP: if self.device_class != SensorDeviceClass.TIMESTAMP:
return value return value
return dt_util.parse_datetime(value) return dt_util.parse_datetime(value)
@property
def device_class(self):
"""Return the device class of the sensor."""
return self._device_class
@property @property
def native_unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit this state is expressed in.""" """Return the unit this state is expressed in."""
@ -681,16 +667,8 @@ class SmartThingsThreeAxisSensor(SmartThingsEntity, SensorEntity):
"""Init the class.""" """Init the class."""
super().__init__(device) super().__init__(device)
self._index = index self._index = index
self._attr_name = f"{device.label} {THREE_AXIS_NAMES[index]}"
@property self._attr_unique_id = f"{device.device_id} {THREE_AXIS_NAMES[index]}"
def name(self) -> str:
"""Return the name of the sensor."""
return f"{self._device.label} {THREE_AXIS_NAMES[self._index]}"
@property
def unique_id(self) -> str:
"""Return a unique ID."""
return f"{self._device.device_id}.{THREE_AXIS_NAMES[self._index]}"
@property @property
def native_value(self): def native_value(self):
@ -713,19 +691,16 @@ class SmartThingsPowerConsumptionSensor(SmartThingsEntity, SensorEntity):
"""Init the class.""" """Init the class."""
super().__init__(device) super().__init__(device)
self.report_name = report_name self.report_name = report_name
self._attr_state_class = SensorStateClass.MEASUREMENT self._attr_name = f"{device.label} {report_name}"
if self.report_name != "power": self._attr_unique_id = f"{device.device_id}.{report_name}_meter"
if self.report_name == "power":
self._attr_state_class = SensorStateClass.MEASUREMENT
self._attr_device_class = SensorDeviceClass.POWER
self._attr_native_unit_of_measurement = UnitOfPower.WATT
else:
self._attr_state_class = SensorStateClass.TOTAL_INCREASING self._attr_state_class = SensorStateClass.TOTAL_INCREASING
self._attr_device_class = SensorDeviceClass.ENERGY
@property self._attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
def name(self) -> str:
"""Return the name of the sensor."""
return f"{self._device.label} {self.report_name}"
@property
def unique_id(self) -> str:
"""Return a unique ID."""
return f"{self._device.device_id}.{self.report_name}_meter"
@property @property
def native_value(self): def native_value(self):
@ -737,20 +712,6 @@ class SmartThingsPowerConsumptionSensor(SmartThingsEntity, SensorEntity):
return value[self.report_name] return value[self.report_name]
return value[self.report_name] / 1000 return value[self.report_name] / 1000
@property
def device_class(self):
"""Return the device class of the sensor."""
if self.report_name == "power":
return SensorDeviceClass.POWER
return SensorDeviceClass.ENERGY
@property
def native_unit_of_measurement(self):
"""Return the unit this state is expressed in."""
if self.report_name == "power":
return UnitOfPower.WATT
return UnitOfEnergy.KILO_WATT_HOUR
@property @property
def extra_state_attributes(self): def extra_state_attributes(self):
"""Return specific state attributes.""" """Return specific state attributes."""