Compare commits

..
2 Commits
Author SHA1 Message Date
Pierre bcfaa83f10 One remote to rule them all 2026-09-26 19:29:28 +02:00
Pierre db12c81f6d fix a few home cinema sensors 2026-09-26 19:21:43 +02:00
4 changed files with 98 additions and 6 deletions

No files matched your search

+49
View File
@@ -2,6 +2,11 @@ samsung_the_frame:
module: samsungtheframe
class: SamsungTheFrame
volume_up_events:
- the_frame_volume_up
volume_down_events:
- the_frame_volume_down
ip_address: 10.0.0.58
#broadcast_address: 10.0.0.255
#mac_address: 98:06:3C:85:93:38
@@ -231,3 +236,47 @@ apple_remote:
toggle_use_bravia_theater_for_the_frame:
event_name: toggle_use_bravia_theater_for_the_frame
event_condition: binary_sensor.is_tv_on and binary_sensor.ir_bridge_apple_tv_mute_button_short_press
# Volume buttons received by the IR bridge: Bravia > TV > Sonos.
homecinema_volume:
module: eventsforwarder
class: EventsForwarder
priority: 100
forwarders:
volume_up:
events_to_listen:
- esphome.ir_bridge_volume_up
events_to_send:
the_frame:
event_name: the_frame_volume_up
event_condition: not (media_player.bravia_theatre == 'on' or media_player.bravia_theatre == 'playing' or media_player.bravia_theatre == 'paused' or media_player.bravia_theatre == 'idle') and binary_sensor.is_tv_on == 'on'
services_to_call:
bravia:
service: media_player/volume_up
event_condition: (media_player.bravia_theatre == 'on' or media_player.bravia_theatre == 'playing' or media_player.bravia_theatre == 'paused' or media_player.bravia_theatre == 'idle')
data:
entity_id: media_player.bravia_theatre
sonos:
service: media_player/volume_up
event_condition: not (media_player.bravia_theatre == 'on' or media_player.bravia_theatre == 'playing' or media_player.bravia_theatre == 'paused' or media_player.bravia_theatre == 'idle') and binary_sensor.is_tv_on != 'on'
data:
entity_id: media_player.living_room_sonos
volume_down:
events_to_listen:
- esphome.ir_bridge_volume_down
events_to_send:
the_frame:
event_name: the_frame_volume_down
event_condition: not (media_player.bravia_theatre == 'on' or media_player.bravia_theatre == 'playing' or media_player.bravia_theatre == 'paused' or media_player.bravia_theatre == 'idle') and binary_sensor.is_tv_on == 'on'
services_to_call:
bravia:
service: media_player/volume_down
event_condition: (media_player.bravia_theatre == 'on' or media_player.bravia_theatre == 'playing' or media_player.bravia_theatre == 'paused' or media_player.bravia_theatre == 'idle')
data:
entity_id: media_player.bravia_theatre
sonos:
service: media_player/volume_down
event_condition: not (media_player.bravia_theatre == 'on' or media_player.bravia_theatre == 'playing' or media_player.bravia_theatre == 'paused' or media_player.bravia_theatre == 'idle') and binary_sensor.is_tv_on != 'on'
data:
entity_id: media_player.living_room_sonos
+3 -3
View File
@@ -52,9 +52,9 @@ virtual_sensors:
disable_conditions: binary_sensor.vertex2_unreachable
sensor_attributes:
icon: sensor.vertex2_input_selected_icon
binary_sensor.is_using_apple_tv: binary_sensor.is_apple_tv_on and binary_sensor.vertex2_has_input_signal #and select.hdfury_vertex2_07_port_select_tx0 == 0
binary_sensor.is_using_xbox: binary_sensor.is_xbox_on and binary_sensor.vertex2_has_input_signal #and select.hdfury_vertex2_07_port_select_tx0 == 1
binary_sensor.is_using_playstation: binary_sensor.is_playstation_on and binary_sensor.vertex2_has_input_signal #and select.hdfury_vertex2_07_port_select_tx0 == 2
binary_sensor.is_using_apple_tv: binary_sensor.is_apple_tv_on and binary_sensor.vertex2_has_input_signal and sensor.vertex2_input_selected == 'AppleTV'
binary_sensor.is_using_xbox: binary_sensor.is_xbox_on and binary_sensor.vertex2_has_input_signal and sensor.vertex2_input_selected == 'Xbox'
binary_sensor.is_using_playstation: binary_sensor.is_playstation_on and binary_sensor.vertex2_has_input_signal and sensor.vertex2_input_selected == 'Playstation'
continuous_condition.is_vertex2_content_idle:
+45 -2
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
@@ -46,6 +48,13 @@ class SamsungTheFrame(SmartObject):
self.listen_state(self.update_sensors_cb,self.power_plug_power)
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:
if state_evaluator[0].evaluate(False) == SmartCondition.Result.Succeeded:
@@ -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)