added info logging for actions from panels

This commit is contained in:
Johannes Braun
2026-02-21 18:52:54 +01:00
parent 8e6f923839
commit 00f7119cd2
3 changed files with 81 additions and 45 deletions

View File

@@ -1,6 +1,6 @@
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config # https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config
name: NSPanel Lovelace UI Addon name: NSPanel Lovelace UI Addon
version: "4.7.82" version: "4.7.83"
slug: nspanel-lovelace-ui slug: nspanel-lovelace-ui
description: NSPanel Lovelace UI Addon description: NSPanel Lovelace UI Addon
services: services:

View File

@@ -71,12 +71,13 @@ def calculate_dim_values(sleepTracking, sleepTrackingZones, sleepBrightness, scr
else: else:
return dimmode, dimValueNormal return dimmode, dimValueNormal
def handle_buttons(entity_id, btype, value, entity_config=None): def handle_buttons(entity_id, btype, value, entity_config=None, action_context=None):
action_context = action_context or {}
match btype: match btype:
case 'button': case 'button':
button_press(entity_id, value) button_press(entity_id, value, action_context=action_context)
case 'OnOff': case 'OnOff':
on_off(entity_id, value) on_off(entity_id, value, action_context=action_context)
case 'number-set': case 'number-set':
if entity_id.startswith('fan'): if entity_id.startswith('fan'):
attr = libs.home_assistant.get_entity_data(entity_id).get('attributes', []) attr = libs.home_assistant.get_entity_data(entity_id).get('attributes', [])
@@ -84,7 +85,7 @@ def handle_buttons(entity_id, btype, value, entity_config=None):
service_data = { service_data = {
"value": int(value) "value": int(value)
} }
call_ha_service(entity_id, "set_value", service_data=service_data) call_ha_service(entity_id, "set_value", service_data=service_data, action_context=action_context)
case 'up' | 'stop' | 'down' | 'tiltOpen' | 'tiltStop' | 'tiltClose' | 'media-next' | 'media-back' | 'media-pause' | 'timer-cancel' | 'timer-pause' | 'timer-finish': case 'up' | 'stop' | 'down' | 'tiltOpen' | 'tiltStop' | 'tiltClose' | 'media-next' | 'media-back' | 'media-pause' | 'timer-cancel' | 'timer-pause' | 'timer-finish':
action_service_mapping = { action_service_mapping = {
'up': 'open_cover', 'up': 'open_cover',
@@ -101,37 +102,37 @@ def handle_buttons(entity_id, btype, value, entity_config=None):
'timer-finish': 'finish', 'timer-finish': 'finish',
} }
service = action_service_mapping[btype] service = action_service_mapping[btype]
call_ha_service(entity_id, service) call_ha_service(entity_id, service, action_context=action_context)
case 'timer-start': case 'timer-start':
if value: if value:
service_data = { service_data = {
"duration": value "duration": value
} }
call_ha_service(entity_id, "start", service_data=service_data) call_ha_service(entity_id, "start", service_data=service_data, action_context=action_context)
else: else:
call_ha_service(entity_id, "start") call_ha_service(entity_id, "start", action_context=action_context)
case 'positionSlider': case 'positionSlider':
service_data = { service_data = {
"position": int(value) "position": int(value)
} }
call_ha_service(entity_id, "set_cover_position", service_data=service_data) call_ha_service(entity_id, "set_cover_position", service_data=service_data, action_context=action_context)
case 'tiltSlider': case 'tiltSlider':
service_data = { service_data = {
"tilt_position": int(value) "tilt_position": int(value)
} }
call_ha_service(entity_id, "set_cover_tilt_position", service_data=service_data) call_ha_service(entity_id, "set_cover_tilt_position", service_data=service_data, action_context=action_context)
case 'media-OnOff': case 'media-OnOff':
state = libs.home_assistant.get_entity_data(entity_id).get('state', '') state = libs.home_assistant.get_entity_data(entity_id).get('state', '')
if state == "off": if state == "off":
call_ha_service(entity_id, "turn_on") call_ha_service(entity_id, "turn_on", action_context=action_context)
else: else:
call_ha_service(entity_id, "turn_off") call_ha_service(entity_id, "turn_off", action_context=action_context)
case 'media-shuffle': case 'media-shuffle':
suffle = libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get('shuffle') suffle = libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get('shuffle')
service_data = { service_data = {
"shuffle": not suffle "shuffle": not suffle
} }
call_ha_service(entity_id, "set_value", service_data=service_data) call_ha_service(entity_id, "set_value", service_data=service_data, action_context=action_context)
case 'volumeSlider': case 'volumeSlider':
pos = int(value) pos = int(value)
# HA wants to have this value between 0 and 1 as float # HA wants to have this value between 0 and 1 as float
@@ -139,12 +140,12 @@ def handle_buttons(entity_id, btype, value, entity_config=None):
service_data = { service_data = {
"volume_level": pos "volume_level": pos
} }
call_ha_service(entity_id, "volume_set", service_data=service_data) call_ha_service(entity_id, "volume_set", service_data=service_data, action_context=action_context)
case 'speaker-sel': case 'speaker-sel':
service_data = { service_data = {
"volume_level": value "volume_level": value
} }
call_ha_service(entity_id, "select_source", service_data=service_data) call_ha_service(entity_id, "select_source", service_data=service_data, action_context=action_context)
# for light detail page # for light detail page
case 'brightnessSlider': case 'brightnessSlider':
# scale 0-100 to ha brightness range # scale 0-100 to ha brightness range
@@ -152,7 +153,7 @@ def handle_buttons(entity_id, btype, value, entity_config=None):
service_data = { service_data = {
"brightness": brightness "brightness": brightness
} }
call_ha_service(entity_id, "turn_on", service_data=service_data) call_ha_service(entity_id, "turn_on", service_data=service_data, action_context=action_context)
case 'colorTempSlider': case 'colorTempSlider':
attr = libs.home_assistant.get_entity_data(entity_id).get('attributes', []) attr = libs.home_assistant.get_entity_data(entity_id).get('attributes', [])
min_mireds = attr.get("min_mireds") min_mireds = attr.get("min_mireds")
@@ -162,19 +163,19 @@ def handle_buttons(entity_id, btype, value, entity_config=None):
service_data = { service_data = {
"color_temp": color_val "color_temp": color_val
} }
call_ha_service(entity_id, "turn_on", service_data=service_data) call_ha_service(entity_id, "turn_on", service_data=service_data, action_context=action_context)
case 'colorWheel': case 'colorWheel':
value = value.split('|') value = value.split('|')
color = pos_to_color(int(value[0]), int(value[1]), int(value[2])) color = pos_to_color(int(value[0]), int(value[1]), int(value[2]))
service_data = { service_data = {
"rgb_color": color "rgb_color": color
} }
call_ha_service(entity_id, "turn_on", service_data=service_data) call_ha_service(entity_id, "turn_on", service_data=service_data, action_context=action_context)
case 'disarm' | 'arm_home' | 'arm_away' | 'arm_night' | 'arm_vacation': case 'disarm' | 'arm_home' | 'arm_away' | 'arm_night' | 'arm_vacation':
service_data = { service_data = {
"code": value "code": value
} }
call_ha_service(entity_id, f"alarm_{btype}", service_data=service_data) call_ha_service(entity_id, f"alarm_{btype}", service_data=service_data, action_context=action_context)
case 'mode-preset_modes' | 'mode-swing_modes' | 'mode-fan_modes': case 'mode-preset_modes' | 'mode-swing_modes' | 'mode-fan_modes':
attr = libs.home_assistant.get_entity_data(entity_id).get('attributes', []) attr = libs.home_assistant.get_entity_data(entity_id).get('attributes', [])
mapping = { mapping = {
@@ -189,7 +190,7 @@ def handle_buttons(entity_id, btype, value, entity_config=None):
service_data = { service_data = {
mapping[btype][:-1]: mode mapping[btype][:-1]: mode
} }
call_ha_service(entity_id, f"set_{mapping[btype][:-1]}", service_data=service_data) call_ha_service(entity_id, f"set_{mapping[btype][:-1]}", service_data=service_data, action_context=action_context)
case 'mode-input_select' | 'mode-select': case 'mode-input_select' | 'mode-select':
options = libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get("options", []) options = libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get("options", [])
if options: if options:
@@ -197,7 +198,7 @@ def handle_buttons(entity_id, btype, value, entity_config=None):
service_data = { service_data = {
"option": option "option": option
} }
call_ha_service(entity_id, "select_option", service_data=service_data) call_ha_service(entity_id, "select_option", service_data=service_data, action_context=action_context)
case 'mode-media_player': case 'mode-media_player':
options = libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get("source_list", []) options = libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get("source_list", [])
if options: if options:
@@ -205,7 +206,7 @@ def handle_buttons(entity_id, btype, value, entity_config=None):
service_data = { service_data = {
"source": option "source": option
} }
call_ha_service(entity_id, "select_source", service_data=service_data) call_ha_service(entity_id, "select_source", service_data=service_data, action_context=action_context)
case 'mode-light': case 'mode-light':
options = entity_config.get("effectList", libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get("effect_list", [])) options = entity_config.get("effectList", libs.home_assistant.get_entity_data(entity_id).get('attributes', []).get("effect_list", []))
if options: if options:
@@ -213,13 +214,13 @@ def handle_buttons(entity_id, btype, value, entity_config=None):
service_data = { service_data = {
"effect": option "effect": option
} }
call_ha_service(entity_id, "turn_on", service_data=service_data) call_ha_service(entity_id, "turn_on", service_data=service_data, action_context=action_context)
case 'tempUpd': case 'tempUpd':
temp = int(value)/10 temp = int(value)/10
service_data = { service_data = {
"temperature": temp "temperature": temp
} }
call_ha_service(entity_id, "set_temperature", service_data=service_data) call_ha_service(entity_id, "set_temperature", service_data=service_data, action_context=action_context)
case 'tempUpdHighLow': case 'tempUpdHighLow':
value = value.split("|") value = value.split("|")
temp_high = int(value[0])/10 temp_high = int(value[0])/10
@@ -228,16 +229,19 @@ def handle_buttons(entity_id, btype, value, entity_config=None):
"target_temp_high": temp_high, "target_temp_high": temp_high,
"target_temp_low": temp_low, "target_temp_low": temp_low,
} }
call_ha_service(entity_id, "set_temperature", service_data=service_data) call_ha_service(entity_id, "set_temperature", service_data=service_data, action_context=action_context)
case 'hvac_action': case 'hvac_action':
service_data = { service_data = {
"hvac_mode": value "hvac_mode": value
} }
call_ha_service(entity_id, "set_hvac_mode", service_data=service_data) call_ha_service(entity_id, "set_hvac_mode", service_data=service_data, action_context=action_context)
case _: case _:
logging.error("Not implemented: %s", btype) logging.error("Not implemented: %s", btype)
def call_ha_service(entity_id, service, service_data = {}): def call_ha_service(entity_id, service, service_data=None, action_context=None):
if service_data is None:
service_data = {}
action_context = action_context or {}
etype = entity_id.split(".")[0] etype = entity_id.split(".")[0]
ok = libs.home_assistant.call_service( ok = libs.home_assistant.call_service(
entity_name=entity_id, entity_name=entity_id,
@@ -245,6 +249,16 @@ def call_ha_service(entity_id, service, service_data = {}):
service=service, service=service,
service_data=service_data service_data=service_data
) )
if ok:
logging.info(
"Panel action forwarded to Home Assistant: panel='%s', action='%s', value='%s', entity='%s', service='%s', data=%s",
action_context.get("panel", "unknown"),
action_context.get("btype", "unknown"),
action_context.get("value"),
entity_id,
service,
service_data,
)
if not ok: if not ok:
logging.error( logging.error(
"Home Assistant service call failed: entity='%s', service='%s', data=%s", "Home Assistant service call failed: entity='%s', service='%s', data=%s",
@@ -253,29 +267,29 @@ def call_ha_service(entity_id, service, service_data = {}):
service_data, service_data,
) )
def button_press(entity_id, value): def button_press(entity_id, value, action_context=None):
etype = entity_id.split(".")[0] etype = entity_id.split(".")[0]
match etype: match etype:
case 'scene' | 'script': case 'scene' | 'script':
call_ha_service(entity_id, "turn_on") call_ha_service(entity_id, "turn_on", action_context=action_context)
case 'light' | 'switch' | 'input_boolean' | 'automation' | 'fan': case 'light' | 'switch' | 'input_boolean' | 'automation' | 'fan':
call_ha_service(entity_id, "toggle") call_ha_service(entity_id, "toggle", action_context=action_context)
case 'lock': case 'lock':
state = libs.home_assistant.get_entity_data(entity_id).get('state', '') state = libs.home_assistant.get_entity_data(entity_id).get('state', '')
if state == "locked": if state == "locked":
call_ha_service(entity_id, "unlock") call_ha_service(entity_id, "unlock", action_context=action_context)
else: else:
call_ha_service(entity_id, "lock") call_ha_service(entity_id, "lock", action_context=action_context)
case 'button' | 'input_button': case 'button' | 'input_button':
call_ha_service(entity_id, "press") call_ha_service(entity_id, "press", action_context=action_context)
case 'input_select' | 'select': case 'input_select' | 'select':
call_ha_service(entity_id, "select_next") call_ha_service(entity_id, "select_next", action_context=action_context)
case 'vacuum': case 'vacuum':
state = libs.home_assistant.get_entity_data(entity_id).get('state', '') state = libs.home_assistant.get_entity_data(entity_id).get('state', '')
if state == "docked": if state == "docked":
call_ha_service(entity_id, "start") call_ha_service(entity_id, "start", action_context=action_context)
else: else:
call_ha_service(entity_id, "return_to_base") call_ha_service(entity_id, "return_to_base", action_context=action_context)
case _: case _:
logging.error("buttonpress for entity type %s not implemented", etype) logging.error("buttonpress for entity type %s not implemented", etype)
@@ -283,14 +297,14 @@ def button_press(entity_id, value):
# apis.ha_api.call_service(entity_id.replace( # apis.ha_api.call_service(entity_id.replace(
# 'service.', '', 1).replace('.', '/', 1), **entity_config.data) # 'service.', '', 1).replace('.', '/', 1), **entity_config.data)
def on_off(entity_id, value): def on_off(entity_id, value, action_context=None):
etype = entity_id.split(".")[0] etype = entity_id.split(".")[0]
match etype: match etype:
case 'light' | 'switch' | 'input_boolean' | 'automation' | 'fan': case 'light' | 'switch' | 'input_boolean' | 'automation' | 'fan':
service = "turn_off" service = "turn_off"
if value == "1": if value == "1":
service = "turn_on" service = "turn_on"
call_ha_service(entity_id, service) call_ha_service(entity_id, service, action_context=action_context)
case _: case _:
logging.error( logging.error(
"Control action on_off not implemented for %s", entity_id) "Control action on_off not implemented for %s", entity_id)

View File

@@ -242,6 +242,11 @@ class LovelaceUIPanel:
btype = msg[3] btype = msg[3]
value = msg[4] if len(msg) > 4 else None value = msg[4] if len(msg) > 4 else None
entity_config = {} entity_config = {}
action_context = {
"panel": self.name,
"btype": btype,
"value": value,
}
if btype == "bExit": if btype == "bExit":
if entity_id in ["screensaver", "screensaver2"] and self.settings.get("screensaver").get("doubleTapToUnlock") and value == "1": if entity_id in ["screensaver", "screensaver2"] and self.settings.get("screensaver").get("doubleTapToUnlock") and value == "1":
return return
@@ -281,19 +286,36 @@ class LovelaceUIPanel:
self.privious_cards.append(self.current_card) self.privious_cards.append(self.current_card)
self.current_card = self.searchCard(card_iid) self.current_card = self.searchCard(card_iid)
self.render_current_page(switchPages=True) self.render_current_page(switchPages=True)
# send ha stuff to ha # send ha stuff to ha
case _: case _:
ha_control.handle_buttons(entity_id, btype, value, entity_config=entity_config) ha_control.handle_buttons(
entity_id,
btype,
value,
entity_config=entity_config,
action_context=action_context,
)
case 'cardUnlock-unlock': case 'cardUnlock-unlock':
card_iid = entity_id.split(".")[1] card_iid = entity_id.split(".")[1]
if int(self.current_card.config.get("pin")) == int(value): if int(self.current_card.config.get("pin")) == int(value):
self.privious_cards.append(self.current_card) self.privious_cards.append(self.current_card)
self.current_card = self.searchCard(card_iid) self.current_card = self.searchCard(card_iid)
self.render_current_page(switchPages=True) self.render_current_page(switchPages=True)
case 'mode-light': case 'mode-light':
ha_control.handle_buttons(entity_id, btype, value, entity_config=entity_config) ha_control.handle_buttons(
case _: entity_id,
ha_control.handle_buttons(entity_id, btype, value) btype,
value,
entity_config=entity_config,
action_context=action_context,
)
case _:
ha_control.handle_buttons(
entity_id,
btype,
value,
action_context=action_context,
)
if msg[1] == "pageOpenDetail": if msg[1] == "pageOpenDetail":
if len(msg) < 4: if len(msg) < 4: