One remote to rule them all

This commit is contained in:
Pierre committed 2026-09-26 19:29:28 +02:00
1 parent db12c81f6d
commit bcfaa83f10
3 files changed
+97 -5

No files matched your search

+46 -3
View File
@@ -1,5 +1,6 @@
import appdaemon.plugins.hass.hassapi as hass
from ad_toolbox.smartobject import SmartObject
from ad_toolbox.eventhandler import EventHandler
import ad_toolbox.smartcondition as SmartCondition
from samsungtvws import SamsungTVWS
from samsungtvws import exceptions as tv_exceptions
@@ -16,6 +17,7 @@ class SamsungTheFrame(SmartObject):
self.log(f"Initializing TheFrame with ip {self.args['ip_address']}")
#self.need_to_turn_off_when_hdmi_gone = False
self.volume_connection = None
self.requested_state = None
self.requested_state_confirm_cb_handle = None
@@ -44,7 +46,14 @@ class SamsungTheFrame(SmartObject):
self.listen_state(self.update_sensors_cb,self.power_plug)
self.listen_state(self.update_sensors_cb,self.power_plug_power)
self.update_sensors()
self.update_sensors()
self.volume_event_handlers = []
for direction in ('up', 'down'):
config = self.args.get(f'volume_{direction}_events')
if config:
self.volume_event_handlers.append(EventHandler(
self, config, self.on_volume_event, direction))
def on_update_tv_states(self):
for state_evaluator in self.tv_states_evaluators:
@@ -58,9 +67,40 @@ class SamsungTheFrame(SmartObject):
def on_update_tv_state_sensor(self, entity, attribute, old, new, kwargs):
if new != old: self.request_tv_state(new)
def connect(self):
def connect(self, timeout=None):
#self.log(f"Connecting to {self.args['ip_address']}")
return SamsungTVWS(self.args['ip_address'],port = 8002, token_file = os.path.join(str(self.AD.app_dir),"theframe_token.txt"))
return SamsungTVWS(self.args['ip_address'],port = 8002, timeout=timeout, token_file = os.path.join(str(self.AD.app_dir),"theframe_token.txt"))
def close_volume_connection(self):
tv = self.volume_connection
self.volume_connection = None
if tv is not None:
try:
tv.close()
except (OSError, websocket.WebSocketException):
pass
def terminate(self):
self.close_volume_connection()
super().terminate()
def on_volume_event(self, event_name, event_data, direction):
if self.get_state(self.is_on_sensor) != 'on':
self.close_volume_connection()
return
try:
if self.volume_connection is None:
self.volume_connection = self.connect(timeout=1)
# ESPHome already limits repetitions to one per 300 ms. The
# library's default one-second delay would queue button events.
self.volume_connection.send_key(
'KEY_VOLUP' if direction == 'up' else 'KEY_VOLDOWN',
key_press_delay=0)
except (OSError, tv_exceptions.ConnectionFailure, tv_exceptions.ResponseError,
websocket.WebSocketException) as error:
self.log(f"Volume {direction} failed: {error}", level="WARNING")
# Reconnect on the next press, without replaying a failed command.
self.close_volume_connection()
def has_power(self):
return self.get_state(self.power_plug) == 'on' and float(self.get_state(self.power_plug_power)) > 35
@@ -279,6 +319,9 @@ class SamsungTheFrame(SmartObject):
self.log(f"Updating sensor: {self.is_art_mode_sensor} = '{is_art_mode}'")
self.set_state(self.is_art_mode_sensor,state = is_art_mode)
if is_on == 'off':
self.close_volume_connection()
if self.get_state(self.is_on_sensor) != is_on:
self.log(f"Updating sensor: {self.is_on_sensor} = '{is_on}'")
self.set_state(self.is_on_sensor,state = is_on)