fix issue with vertex2 reconnection after HA reboot

This commit is contained in:
Pierre committed 2026-09-27 08:52:03 +02:00
1 parent acdd14aaeb
commit 00f6b28342
1 file changed
+24 -6
+24 -6
View File
@@ -11,6 +11,8 @@ from urllib.parse import urlparse
class Vertex2(SmartObject):
def on_initialize_smart_object(self):
# HASS can call initialize() again without calling terminate() first.
self._stop_interrupt_listener()
self._interrupt_stop = threading.Event()
self._status_requested = threading.Event()
self._tx0_recovery_attempted = False
@@ -143,22 +145,25 @@ class Vertex2(SmartObject):
self.vertex2_tcp_port = int(self.args.get('vertex2_tcp_port', 2220))
self._interrupt_thread = threading.Thread(
target=self._interrupt_listener,
args=(self._interrupt_stop,),
name=f'{self.name}_interrupt_listener',
daemon=True,
)
self.update_vertex2_states()
self._interrupt_thread.start()
def _interrupt_listener(self):
def _interrupt_listener(self, interrupt_stop):
address = urlparse(self.args['vertex2_address'])
host = address.hostname
status_fields = ('rx0', 'rx1', 'tx0', 'tx1', 'tx0sink', 'tx1sink', 'aud0', 'aud1', 'audout', 'spd0', 'spd1')
commands = tuple(f'get status {field}' for field in status_fields) + ('get insel',)
expected = set(status_fields) | {'insel'}
while not self._interrupt_stop.is_set():
while not interrupt_stop.is_set():
try:
with socket.create_connection((host, self.vertex2_tcp_port), timeout=10) as connection:
if interrupt_stop.is_set():
break
# Detect a silent reboot/network loss without polling HDMI status.
connection.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 10)
@@ -178,7 +183,7 @@ class Vertex2(SmartObject):
previous_snapshot = None
previous_snapshot_generation = None
while not self._interrupt_stop.is_set():
while not interrupt_stop.is_set():
if status_started is None and self._status_requested.is_set():
self._status_requested.clear()
status = {}
@@ -195,6 +200,8 @@ class Vertex2(SmartObject):
raise OSError('Vertex2 TCP status response timed out')
continue
if interrupt_stop.is_set():
break
if not data:
raise OSError('Vertex2 closed the IP INTERRUPT connection')
@@ -251,7 +258,7 @@ class Vertex2(SmartObject):
raise OSError('Vertex2 TCP status response timed out')
except (OSError, ValueError) as error:
if self._interrupt_stop.is_set():
if interrupt_stop.is_set():
break
self.unreachable_sensor.set_state(state='on')
self.video_tx_signal_sensor.set_state(state='unavailable')
@@ -262,7 +269,7 @@ class Vertex2(SmartObject):
sensor.set_state(state='unavailable')
self.audio_out_signal_sensor.set_state(state='unavailable')
self.log(f'Vertex2 IP INTERRUPT unavailable: {error}', level='WARNING')
self._interrupt_stop.wait(5)
interrupt_stop.wait(5)
def trigger_tx0_stuck_workaround(self, kwargs):
if self._tx0_recovery_attempted:
@@ -288,13 +295,24 @@ class Vertex2(SmartObject):
self.log_info('Vertex2 TX0 +5V workaround: restoring TX0 +5V FORCE')
self.force_tx0_plus5(True)
def terminate(self):
def _stop_interrupt_listener(self):
interrupt_stop = getattr(self, '_interrupt_stop', None)
if interrupt_stop is not None:
interrupt_stop.set()
interrupt_thread = getattr(self, '_interrupt_thread', None)
if interrupt_thread is not None:
# Allow the 10s connect timeout or 1s recv timeout to finish.
interrupt_thread.join(timeout=12)
if interrupt_thread.is_alive():
raise RuntimeError('Previous Vertex2 IP INTERRUPT listener did not stop')
self._interrupt_thread = None
restore_handle = getattr(self, '_tx0_recovery_restore_handle', None)
if restore_handle is not None:
self.cancel_timer(restore_handle)
self._tx0_recovery_restore_handle = None
def terminate(self):
self._stop_interrupt_listener()
super().terminate()
def generate_input_selected_sensor_name(self,i):