Vertex2 tweaking
This commit is contained in:
1 parent
6d2fd26f66
commit
dd4335c811
4 files changed
+76
-76
No files matched your search
+1
-1
Submodule apps/ad_toolbox updated: ece851f5a0...cf8839db6a.
@@ -154,6 +154,9 @@ vertex_2:
|
||||
priority: 5
|
||||
|
||||
virtual_sensors:
|
||||
default_values:
|
||||
binary_sensor.is_tv_on: false
|
||||
binary_sensor.vertex2_has_input_signal: false
|
||||
sensors:
|
||||
binary_sensor.projector_screen_down: cover.living_room_projection_screen.current_position < 90
|
||||
|
||||
@@ -183,10 +186,14 @@ vertex_2:
|
||||
name: TV
|
||||
icon: mdi:television
|
||||
use_audio_out_audio_flags: input_boolean.use_bravia_theater_for_the_frame
|
||||
force_plus5:
|
||||
trigger_conditions: binary_sensor.is_tv_on or binary_sensor.vertex2_has_input_signal
|
||||
blocking_conditions: not switch.the_frame_power_plug
|
||||
1:
|
||||
name: Projector
|
||||
icon: mdi:projector
|
||||
use_audio_out_audio_flags: True
|
||||
force_plus5: switch.living_room_projector_plug
|
||||
|
||||
# vertex2_power_plug:
|
||||
# entity: switch.fibaro_vertex_plug_51
|
||||
@@ -219,6 +226,8 @@ vertex_2:
|
||||
output_selected_sensor: sensor.vertex2_output_selected
|
||||
input_selected_sensor: sensor.vertex2_input_selected
|
||||
unreachable_sensor: binary_sensor.vertex2_unreachable
|
||||
command_processing_sensor: binary_sensor.vertex2_command_processing
|
||||
command_processing_timeout: 20
|
||||
|
||||
use_bravia_theater_for_the_frame:
|
||||
module: smartswitch
|
||||
|
||||
@@ -110,10 +110,10 @@ virtual_sensors:
|
||||
binary_sensor.is_playstation_on: switch.ps5_136_power
|
||||
sensor.vertex2_input_selected_icon: sensor.vertex2_input_selected.icon
|
||||
retain_condition.vertex2_has_input_signal:
|
||||
retain_time: 20
|
||||
retain_time: 10
|
||||
conditions:
|
||||
trigger_conditions: (sensor.vertex2_video_signal and sensor.vertex2_video_signal != 'no signal') or sensor.vertex2_audio_signal
|
||||
disable_conditions: binary_sensor.vertex2_unreachable
|
||||
disable_conditions: binary_sensor.vertex2_unreachable or binary_sensor.vertex2_command_processing
|
||||
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 sensor.vertex2_input_selected == 'AppleTV'
|
||||
|
||||
+64
-73
@@ -15,10 +15,16 @@ class Vertex2(SmartObject):
|
||||
self._stop_interrupt_listener()
|
||||
self._interrupt_stop = threading.Event()
|
||||
self._status_requested = threading.Event()
|
||||
self._plus5_off_handle = None
|
||||
self._plus5_active_index = None
|
||||
self._input_signal_present = False
|
||||
self.plus5_signal_timeout = max(0, float(self.args.get('plus5_signal_timeout', 60)))
|
||||
self._command_processing_lock = threading.Lock()
|
||||
self._command_processing_handle = None
|
||||
self._command_processing_deadline = None
|
||||
self.command_processing_timeout = max(0, float(self.args.get('command_processing_timeout', 30)))
|
||||
self.command_processing_sensor = None
|
||||
if self.args.get('command_processing_sensor'):
|
||||
self.command_processing_sensor = self.create_entity(
|
||||
self.args['command_processing_sensor'],
|
||||
state='off',
|
||||
)
|
||||
self.video_tx_signal_sensor = self.create_entity(
|
||||
self.args['video_tx_signal_sensor'],
|
||||
state='unavailable',
|
||||
@@ -112,17 +118,23 @@ class Vertex2(SmartObject):
|
||||
output_index = int(output_key)
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
for condition_key in ('use_audio_out_audio_flags',):
|
||||
for condition_key in ('use_audio_out_audio_flags', 'force_plus5'):
|
||||
condition_config = config.get(condition_key)
|
||||
if not condition_config:
|
||||
if condition_config is None:
|
||||
continue
|
||||
callback_options = (
|
||||
{'on_change_cb': self.on_output_plus5_condition_change,
|
||||
'trigger_callback_on_activation': True}
|
||||
if condition_key == 'force_plus5'
|
||||
else {'on_update_cb': self.on_output_config_conditions_update,
|
||||
'trigger_callback_on_activation': False}
|
||||
)
|
||||
self.output_config_conditions.setdefault(output_index, {})[condition_key] = SmartCondition.Evaluator(
|
||||
self,
|
||||
condition_config,
|
||||
condition_name=f'output_config_tx{output_index}_{condition_key}',
|
||||
on_update_cb=self.on_output_config_conditions_update,
|
||||
pass_condition_name_to_cb=str(output_index),
|
||||
trigger_callback_on_activation=False,
|
||||
**callback_options,
|
||||
)
|
||||
|
||||
self.output_selection_evaluators = []
|
||||
@@ -205,6 +217,7 @@ class Vertex2(SmartObject):
|
||||
line, buffer = buffer.split('\n', 1)
|
||||
line = line.strip()
|
||||
if line == 'int':
|
||||
self._refresh_command_processing()
|
||||
self.log_info('Vertex2 IP INTERRUPT received')
|
||||
self._status_requested.set()
|
||||
elif status_started is not None:
|
||||
@@ -253,15 +266,16 @@ class Vertex2(SmartObject):
|
||||
if interrupt_thread.is_alive():
|
||||
raise RuntimeError('Previous Vertex2 IP INTERRUPT listener did not stop')
|
||||
self._interrupt_thread = None
|
||||
plus5_off_handle = getattr(self, '_plus5_off_handle', None)
|
||||
if plus5_off_handle is not None:
|
||||
self.cancel_timer(plus5_off_handle)
|
||||
self._plus5_off_handle = None
|
||||
processing_lock = getattr(self, '_command_processing_lock', None)
|
||||
if processing_lock is not None:
|
||||
with processing_lock:
|
||||
self._command_processing_deadline = None
|
||||
if self._command_processing_handle is not None:
|
||||
self.cancel_timer(self._command_processing_handle)
|
||||
self._command_processing_handle = None
|
||||
|
||||
def terminate(self):
|
||||
self._stop_interrupt_listener()
|
||||
if getattr(self, '_plus5_active_index', None) is not None:
|
||||
self._set_active_output_plus5(None)
|
||||
super().terminate()
|
||||
|
||||
def generate_input_selected_sensor_name(self,i):
|
||||
@@ -309,7 +323,7 @@ class Vertex2(SmartObject):
|
||||
break
|
||||
|
||||
if output_selected is None:
|
||||
self.log_warning("No output_selection condition succeeded; disabling TX0 and TX1 +5V FORCE")
|
||||
self.log_warning("No output_selection condition succeeded; clearing output selection")
|
||||
self.disable_output_selection()
|
||||
return
|
||||
|
||||
@@ -346,7 +360,6 @@ class Vertex2(SmartObject):
|
||||
self.set_edid_video_flags_to_tx0()
|
||||
else:
|
||||
self.set_edid_video_flags_to_tx1()
|
||||
self._set_active_output_plus5(output_index if self._input_signal_present else None)
|
||||
|
||||
def disable_output_selection(self):
|
||||
default_output_config = self.get_output_config(None)
|
||||
@@ -355,60 +368,15 @@ class Vertex2(SmartObject):
|
||||
attributes={"icon": default_output_config["icon"]},
|
||||
)
|
||||
self._refresh_selected_output_signal()
|
||||
self._set_active_output_plus5(None)
|
||||
|
||||
def _set_active_output_plus5(self, output_index):
|
||||
if self._plus5_off_handle is not None:
|
||||
self.cancel_timer(self._plus5_off_handle)
|
||||
self._plus5_off_handle = None
|
||||
|
||||
previous_index = self._plus5_active_index
|
||||
if previous_index == output_index:
|
||||
def on_output_plus5_condition_change(self, output_index, previous_result, result):
|
||||
if result == SmartCondition.Result.Disabled:
|
||||
return
|
||||
|
||||
if previous_index == 0:
|
||||
self.force_tx0_plus5(False)
|
||||
elif previous_index == 1:
|
||||
self.force_tx1_plus5(False)
|
||||
|
||||
self._plus5_active_index = output_index
|
||||
if output_index == 0:
|
||||
# At startup the previous hardware state is unknown; disable the
|
||||
# other output only after a signal confirms the selected TX.
|
||||
self.force_tx1_plus5(False)
|
||||
self.force_tx0_plus5(True)
|
||||
elif output_index == 1:
|
||||
self.force_tx0_plus5(False)
|
||||
self.force_tx1_plus5(True)
|
||||
|
||||
def _update_plus5_from_input_signal(self, has_signal):
|
||||
self._input_signal_present = has_signal
|
||||
selected_name = self.output_selected_sensor.get_state()
|
||||
selected_index = self.output_names.get(selected_name)
|
||||
|
||||
if has_signal:
|
||||
self._set_active_output_plus5(selected_index)
|
||||
elif selected_index in (0, 1) and self._plus5_off_handle is None:
|
||||
self.log_info(
|
||||
f"No input signal; turning selected TX +5V FORCE off in {self.plus5_signal_timeout:g}s"
|
||||
)
|
||||
self._plus5_off_handle = self.run_in(
|
||||
self._turn_off_plus5_after_signal_loss,
|
||||
self.plus5_signal_timeout,
|
||||
)
|
||||
|
||||
def _turn_off_plus5_after_signal_loss(self, kwargs):
|
||||
self._plus5_off_handle = None
|
||||
if self._input_signal_present:
|
||||
return
|
||||
self.log_info("Input signal absent for configured timeout; turning selected TX +5V FORCE off")
|
||||
selected_index = self.output_names.get(self.output_selected_sensor.get_state())
|
||||
if selected_index == 0:
|
||||
self.force_tx0_plus5(False)
|
||||
elif selected_index == 1:
|
||||
self.force_tx1_plus5(False)
|
||||
if self._plus5_active_index == selected_index:
|
||||
self._plus5_active_index = None
|
||||
enabled = result == SmartCondition.Result.Succeeded
|
||||
if int(output_index) == 0:
|
||||
self.force_tx0_plus5(enabled)
|
||||
elif int(output_index) == 1:
|
||||
self.force_tx1_plus5(enabled)
|
||||
|
||||
def on_filmmaker_mode_conditions_change(self,prev_result,result):
|
||||
if result == SmartCondition.Result.Succeeded:
|
||||
@@ -422,8 +390,35 @@ class Vertex2(SmartObject):
|
||||
else:
|
||||
self.turn_off(self.power_plug_entity)
|
||||
|
||||
def _refresh_command_processing(self, start=False):
|
||||
if self.command_processing_sensor is None:
|
||||
return
|
||||
with self._command_processing_lock:
|
||||
if not start and self.command_processing_sensor.get_state() != 'on':
|
||||
return
|
||||
if self._command_processing_handle is not None:
|
||||
self.cancel_timer(self._command_processing_handle)
|
||||
self._command_processing_deadline = time.monotonic() + self.command_processing_timeout
|
||||
if self.command_processing_sensor.get_state() != 'on':
|
||||
self.command_processing_sensor.set_state(state='on')
|
||||
self._command_processing_handle = self.run_in(
|
||||
self._on_command_processing_timeout,
|
||||
self.command_processing_timeout,
|
||||
deadline=self._command_processing_deadline,
|
||||
)
|
||||
|
||||
def _on_command_processing_timeout(self, kwargs):
|
||||
with self._command_processing_lock:
|
||||
# Ignore a callback already queued before a timer reset or shutdown.
|
||||
if kwargs['deadline'] != self._command_processing_deadline:
|
||||
return
|
||||
self._command_processing_handle = None
|
||||
self._command_processing_deadline = None
|
||||
self.command_processing_sensor.set_state(state='off')
|
||||
|
||||
def send_cmd(self,cmd,value = ''):
|
||||
request = f'{self.args["vertex2_address"]}/cmd?{cmd}={value}'
|
||||
self._refresh_command_processing(start=True)
|
||||
try:
|
||||
r = get(request, timeout=5)
|
||||
if cmd == 'edid' and value.startswith(('audiotx', 'audioout')):
|
||||
@@ -535,6 +530,7 @@ class Vertex2(SmartObject):
|
||||
"name": config.get("name", default_config["name"]),
|
||||
"icon": config.get("icon", default_config["icon"]),
|
||||
"use_audio_out_audio_flags": config.get("use_audio_out_audio_flags"),
|
||||
"force_plus5": config.get("force_plus5"),
|
||||
}
|
||||
return {"name": config, "icon": None}
|
||||
|
||||
@@ -644,11 +640,6 @@ class Vertex2(SmartObject):
|
||||
selected_output_index = self.output_names.get(self.output_selected_sensor.get_state())
|
||||
self._refresh_selected_input_sensor(selected_output_index)
|
||||
self._update_output_video_sensors(kwargs['rx0'], kwargs['rx1'])
|
||||
has_input_signal = any(
|
||||
signal.strip().lower() not in ('', 'no signal', 'unavailable')
|
||||
for signal in (kwargs['rx0'], kwargs['rx1'])
|
||||
)
|
||||
self._update_plus5_from_input_signal(has_input_signal)
|
||||
if self.audio_out_signal_sensor.get_state() != audio_out_signal:
|
||||
self.audio_out_signal_sensor.set_state(state=audio_out_signal)
|
||||
self.unreachable_sensor.set_state(state='off')
|
||||
Reference in new issue
Block a user