Vertex2 tweaking

This commit is contained in:
Pierre committed 2026-10-09 22:47:26 +02:00
1 parent 6d2fd26f66
commit dd4335c811
4 files changed
+76 -76

No files matched your search

+64 -73
View File
@@ -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')