Fix AppDaemon 4.5.x compatibility - use entity attributes as dict (#1333)

With update to AppDaemon to 4.5.x (add-on 0.17.x), access to entity
attributes through properties doesn't work anymore - they are a dict.
Refactor the usage to read dict, leverage walrus operator where
applicable.

Fixes #1331
This commit is contained in:
Jan Čermák
2025-05-28 22:24:30 +02:00
committed by GitHub
parent 397932a6bc
commit 16909f7e7f
3 changed files with 48 additions and 48 deletions

View File

@@ -348,8 +348,8 @@ class LuiController(object):
else: else:
apis.ha_api.get_entity(entity_id).call_service("turn_off") apis.ha_api.get_entity(entity_id).call_service("turn_off")
if button_type == "media-shuffle": if button_type == "media-shuffle":
suffle = not apis.ha_api.get_entity(entity_id).attributes.shuffle shuffle = not apis.ha_api.get_entity(entity_id).attributes['shuffle']
apis.ha_api.get_entity(entity_id).call_service("shuffle_set", shuffle=suffle) apis.ha_api.get_entity(entity_id).call_service("shuffle_set", shuffle=shuffle)
if button_type == "volumeSlider": if button_type == "volumeSlider":
pos = int(value) pos = int(value)
# HA wants this value between 0 and 1 as float # HA wants this value between 0 and 1 as float
@@ -366,7 +366,7 @@ class LuiController(object):
if button_type == "colorTempSlider": if button_type == "colorTempSlider":
entity = apis.ha_api.get_entity(entity_id) entity = apis.ha_api.get_entity(entity_id)
#scale 0-100 from slider to color range of lamp #scale 0-100 from slider to color range of lamp
color_val = scale(int(value), (0, 100), (entity.attributes.min_mireds, entity.attributes.max_mireds)) color_val = scale(int(value), (0, 100), (entity.attributes['min_mireds'], entity.attributes['max_mireds']))
apis.ha_api.get_entity(entity_id).call_service("turn_on", color_temp=color_val) apis.ha_api.get_entity(entity_id).call_service("turn_on", color_temp=color_val)
if button_type == "colorWheel": if button_type == "colorWheel":
apis.ha_api.log(value) apis.ha_api.log(value)
@@ -393,9 +393,9 @@ class LuiController(object):
if button_type == "opnSensorNotify": if button_type == "opnSensorNotify":
msg = "" msg = ""
entity = apis.ha_api.get_entity(entity_id) entity = apis.ha_api.get_entity(entity_id)
if "open_sensors" in entity.attributes and entity.attributes.open_sensors is not None: if open_sensors := entity.attributes.get("open_sensors") is not None:
for e in entity.attributes.open_sensors: for e in open_sensors:
msg += f"- {apis.ha_api.get_entity(e).attributes.friendly_name}\r\n" msg += f"- {apis.ha_api.get_entity(e).attributes['friendly_name']}\r\n"
self._pages_gen.send_message_page("opnSensorNotifyRes", "", msg, "", "") self._pages_gen.send_message_page("opnSensorNotifyRes", "", msg, "", "")
# for cardUnlock # for cardUnlock
@@ -412,22 +412,22 @@ class LuiController(object):
if button_type == "mode-preset_modes": if button_type == "mode-preset_modes":
entity = apis.ha_api.get_entity(entity_id) entity = apis.ha_api.get_entity(entity_id)
preset_mode = entity.attributes.preset_modes[int(value)] preset_mode = entity.attributes['preset_modes'][int(value)]
entity.call_service("set_preset_mode", preset_mode=preset_mode) entity.call_service("set_preset_mode", preset_mode=preset_mode)
if button_type == "mode-swing_modes": if button_type == "mode-swing_modes":
entity = apis.ha_api.get_entity(entity_id) entity = apis.ha_api.get_entity(entity_id)
swing_mode = entity.attributes.swing_modes[int(value)] swing_mode = entity.attributes['swing_modes'][int(value)]
entity.call_service("set_swing_mode", swing_mode=swing_mode) entity.call_service("set_swing_mode", swing_mode=swing_mode)
if button_type == "mode-fan_modes": if button_type == "mode-fan_modes":
entity = apis.ha_api.get_entity(entity_id) entity = apis.ha_api.get_entity(entity_id)
fan_mode = entity.attributes.fan_modes[int(value)] fan_mode = entity.attributes['fan_modes'][int(value)]
entity.call_service("set_fan_mode", fan_mode=fan_mode) entity.call_service("set_fan_mode", fan_mode=fan_mode)
if button_type in ["mode-input_select", "mode-select"]: if button_type in ["mode-input_select", "mode-select"]:
entity = apis.ha_api.get_entity(entity_id) entity = apis.ha_api.get_entity(entity_id)
option = entity.attributes.options[int(value)] option = entity.attributes['options'][int(value)]
entity.call_service("select_option", option=option) entity.call_service("select_option", option=option)
if button_type == "mode-light": if button_type == "mode-light":
@@ -439,12 +439,12 @@ class LuiController(object):
if options_list is not None: if options_list is not None:
option = options_list[int(value)] option = options_list[int(value)]
else: else:
option = entity.attributes.effect_list[int(value)] option = entity.attributes['effect_list'][int(value)]
entity.call_service("turn_on", effect=option) entity.call_service("turn_on", effect=option)
if button_type == "mode-media_player": if button_type == "mode-media_player":
entity = apis.ha_api.get_entity(entity_id) entity = apis.ha_api.get_entity(entity_id)
option = entity.attributes.source_list[int(value)] option = entity.attributes['source_list'][int(value)]
entity.call_service("select_source", source=option) entity.call_service("select_source", source=option)
# timer detail page # timer detail page

View File

@@ -266,8 +266,8 @@ def get_icon_ha(entity_id, overwrite=None, stateOverwrite=None):
# based on media_content_type # based on media_content_type
elif ha_type == "media_player": elif ha_type == "media_player":
result_icon = "speaker-off" result_icon = "speaker-off"
if "media_content_type" in entity.attributes: if media_content_type := entity.attributes.get("media_content_type"):
if entity.attributes.media_content_type in media_content_type_mapping: if media_content_type in media_content_type_mapping:
result_icon = media_content_type_mapping[entity.attributes.media_content_type] result_icon = media_content_type_mapping[media_content_type]
return get_icon_char(result_icon) return get_icon_char(result_icon)

View File

@@ -97,13 +97,12 @@ class LuiPagesGen(object):
if state == "sunny": if state == "sunny":
icon_color = 65504 #bright-yellow icon_color = 65504 #bright-yellow
if "rgb_color" in attr and attr["rgb_color"]: if color := attr.get("rgb_color"):
color = attr.rgb_color if brightness := attr.get("brightness"):
if "brightness" in attr and attr["brightness"]: color = rgb_brightness(color, brightness)
color = rgb_brightness(color, attr.brightness)
icon_color = rgb_dec565(color) icon_color = rgb_dec565(color)
elif "brightness" in attr and attr.brightness: elif brightness := attr.get("brightness"):
color = rgb_brightness([253, 216, 53], attr.brightness) color = rgb_brightness([253, 216, 53], brightness)
icon_color = rgb_dec565(color) icon_color = rgb_dec565(color)
return icon_color return icon_color
@@ -276,7 +275,7 @@ class LuiPagesGen(object):
icon_up_status = "disable" icon_up_status = "disable"
icon_stop_status = "disable" icon_stop_status = "disable"
icon_down_status = "disable" icon_down_status = "disable"
bits = entity.attributes.supported_features bits = entity.attributes['supported_features']
pos = entity.attributes.get("current_position") pos = entity.attributes.get("current_position")
if pos is None: if pos is None:
pos_status = entity.state pos_status = entity.state
@@ -383,18 +382,18 @@ class LuiPagesGen(object):
elif entityType == "weather": elif entityType == "weather":
entityTypePanel = "text" entityTypePanel = "text"
unit = get_attr_safe(entity, "temperature_unit", "") unit = get_attr_safe(entity, "temperature_unit", "")
#if type(item.stype) == int and len(entity.attributes.forecast) >= item.stype: if type(item.stype) == int and len(entity.attributes['forecast']) >= item.stype:
# fdate = dp.parse(entity.attributes.forecast[item.stype]['datetime']) fdate = dp.parse(entity.attributes['forecast'][item.stype]['datetime'])
# global babel_spec global babel_spec
# if babel_spec is not None: if babel_spec is not None:
# dateformat = "E" if item.nameOverride is None else item.nameOverride dateformat = "E" if item.nameOverride is None else item.nameOverride
# name = babel.dates.format_datetime(fdate.astimezone(), dateformat, locale=self._locale) name = babel.dates.format_datetime(fdate.astimezone(), dateformat, locale=self._locale)
# else: else:
# dateformat = "%a" if item.nameOverride is None else item.nameOverride dateformat = "%a" if item.nameOverride is None else item.nameOverride
# name = fdate.astimezone().strftime(dateformat) name = fdate.astimezone().strftime(dateformat)
# icon_id = get_icon_ha(entityId, stateOverwrite=entity.attributes.forecast[item.stype]['condition']) icon_id = get_icon_ha(entityId, stateOverwrite=entity.attributes['forecast'][item.stype]['condition'])
# value = f'{entity.attributes.forecast[item.stype].get("temperature", "")}{unit}' value = f'{entity.attributes['forecast'][item.stype].get("temperature", "")}{unit}'
# color = self.get_entity_color(entity, ha_type=entityType, stateOverwrite=entity.attributes.forecast[item.stype]['condition'], overwrite=colorOverride) color = self.get_entity_color(entity, ha_type=entityType, stateOverwrite=entity.attributes['forecast'][item.stype]['condition'], overwrite=colorOverride)
else: else:
value = f'{get_attr_safe(entity, "temperature", "")}{unit}' value = f'{get_attr_safe(entity, "temperature", "")}{unit}'
else: else:
@@ -455,7 +454,7 @@ class LuiPagesGen(object):
command = f"entityUpd~Not found~{navigation}~{item}~check~220~apps.yaml~150~300~5~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Please~your~~" command = f"entityUpd~Not found~{navigation}~{item}~check~220~apps.yaml~150~300~5~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Please~your~~"
else: else:
entity = apis.ha_api.get_entity(item) entity = apis.ha_api.get_entity(item)
heading = title if title != "unknown" else entity.attributes.friendly_name heading = title if title != "unknown" else entity.attributes['friendly_name']
current_temp = get_attr_safe(entity, "current_temperature", "") current_temp = get_attr_safe(entity, "current_temperature", "")
dest_temp = get_attr_safe(entity, "temperature", None) dest_temp = get_attr_safe(entity, "temperature", None)
dest_temp2 = "" dest_temp2 = ""
@@ -537,7 +536,7 @@ class LuiPagesGen(object):
command = f"entityUpd~Not found~{navigation}" command = f"entityUpd~Not found~{navigation}"
else: else:
entity = apis.ha_api.get_entity(item) entity = apis.ha_api.get_entity(item)
heading = title if title != "unknown" else entity.attributes.friendly_name heading = title if title != "unknown" else entity.attributes['friendly_name']
# get data from homeassistant # get data from homeassistant
data_raw = apis.ha_api.get_history(entity_id = item, days = 7) data_raw = apis.ha_api.get_history(entity_id = item, days = 7)
@@ -584,12 +583,12 @@ class LuiPagesGen(object):
else: else:
media_icon = self.generate_entities_item(entity, "cardGrid") media_icon = self.generate_entities_item(entity, "cardGrid")
ha_entity = apis.ha_api.get_entity(entityId) ha_entity = apis.ha_api.get_entity(entityId)
heading = title if title != "unknown" else ha_entity.attributes.friendly_name heading = title if title != "unknown" else ha_entity.attributes['friendly_name']
title = get_attr_safe(ha_entity, "media_title", "") title = get_attr_safe(ha_entity, "media_title", "")
author = get_attr_safe(ha_entity, "media_artist", "") author = get_attr_safe(ha_entity, "media_artist", "")
volume = int(get_attr_safe(ha_entity, "volume_level", 0)*100) volume = int(get_attr_safe(ha_entity, "volume_level", 0)*100)
iconplaypause = get_icon_id("pause") if ha_entity.state == "playing" else get_icon_id("play") iconplaypause = get_icon_id("pause") if ha_entity.state == "playing" else get_icon_id("play")
bits = ha_entity.attributes.supported_features bits = ha_entity.attributes['supported_features']
onoffbutton = "disable" onoffbutton = "disable"
if bits & 0b10000000: if bits & 0b10000000:
if ha_entity.state == "off": if ha_entity.state == "off":
@@ -639,7 +638,7 @@ class LuiPagesGen(object):
if not entity.attributes.get("code_arm_required", False): if not entity.attributes.get("code_arm_required", False):
numpad = "disable" numpad = "disable"
if overwrite_supported_modes is None: if overwrite_supported_modes is None:
bits = entity.attributes.supported_features bits = entity.attributes['supported_features']
if bits & 0b000001: if bits & 0b000001:
supported_modes.append("arm_home") supported_modes.append("arm_home")
if bits & 0b000010: if bits & 0b000010:
@@ -678,7 +677,7 @@ class LuiPagesGen(object):
#add button to show sensor state #add button to show sensor state
add_btn = "" add_btn = ""
if "open_sensors" in entity.attributes and entity.attributes.open_sensors is not None: if entity.attributes.get("open_sensors") is not None:
add_btn=f"{get_icon_id('progress-alert')}~{rgb_dec565([243,179,0])}~" add_btn=f"{get_icon_id('progress-alert')}~{rgb_dec565([243,179,0])}~"
if alarmBtn is not None and type(alarmBtn) is dict: if alarmBtn is not None and type(alarmBtn) is dict:
entity = alarmBtn.get("entity") entity = alarmBtn.get("entity")
@@ -845,25 +844,26 @@ class LuiPagesGen(object):
color_temp = "disable" color_temp = "disable"
color = "disable" color = "disable"
effect_supported = "disable" effect_supported = "disable"
supported_color_modes = entity.attributes['supported_color_modes']
if "onoff" not in entity.attributes.supported_color_modes: if "onoff" not in supported_color_modes:
brightness = 0 brightness = 0
if entity.state == "on": if entity.state == "on":
if "brightness" in entity.attributes and entity.attributes.brightness: if brightness := entity.attributes.get("brightness"):
# scale 0-255 brightness from ha to 0-100 # scale 0-255 brightness from ha to 0-100
brightness = int(scale(entity.attributes.brightness,(0,255),(0,100))) brightness = int(scale(brightness, (0,255), (0,100)))
else: else:
brightness = "disable" brightness = "disable"
if "color_temp" in entity.attributes.supported_color_modes and entity.attributes.supported_color_modes: if "color_temp" in supported_color_modes:
if "color_temp" in entity.attributes and entity.attributes.color_temp: if color_temp := entity.attributes.get("color_temp"):
# scale ha color temp range to 0-100 # scale ha color temp range to 0-100
color_temp = int(scale(entity.attributes.color_temp,(entity.attributes.min_mireds, entity.attributes.max_mireds),(0,100))) color_temp = int(scale(color_temp, (entity.attributes['min_mireds'], entity.attributes['max_mireds']),(0, 100)))
else: else:
color_temp = "unknown" color_temp = "unknown"
else: else:
color_temp = "disable" color_temp = "disable"
list_color_modes = ["xy", "rgb", "rgbw", "hs"] list_color_modes = ["xy", "rgb", "rgbw", "hs"]
if any(item in list_color_modes for item in entity.attributes.supported_color_modes): if any(item in list_color_modes for item in supported_color_modes):
color = "enable" color = "enable"
else: else:
color = "disable" color = "disable"
@@ -903,7 +903,7 @@ class LuiPagesGen(object):
iconTiltRightStatus = "disable" iconTiltRightStatus = "disable"
tilt_pos = "disable" tilt_pos = "disable"
bits = entity.attributes.supported_features bits = entity.attributes['supported_features']
# position supported # position supported
if bits & 0b00001111: if bits & 0b00001111: