Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00f6b28342 | ||
|
|
acdd14aaeb |
No files matched your search
@@ -153,6 +153,10 @@ vertex_2:
|
|||||||
class: Vertex2
|
class: Vertex2
|
||||||
priority: 5
|
priority: 5
|
||||||
|
|
||||||
|
virtual_sensors:
|
||||||
|
sensors:
|
||||||
|
binary_sensor.projector_screen_down: cover.living_room_projection_screen.current_position < 90
|
||||||
|
|
||||||
input_config:
|
input_config:
|
||||||
default:
|
default:
|
||||||
name: None
|
name: None
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ virtual_sensors:
|
|||||||
|
|
||||||
# home cinema sensors
|
# home cinema sensors
|
||||||
binary_sensor.projector_on: switch.living_room_projector_plug and sensor.living_room_projector_plug_power > 50
|
binary_sensor.projector_on: switch.living_room_projector_plug and sensor.living_room_projector_plug_power > 50
|
||||||
binary_sensor.projector_screen_down: cover.living_room_projection_screen.current_position < 90
|
|
||||||
continuous_condition.projector_off_for_a_while:
|
continuous_condition.projector_off_for_a_while:
|
||||||
time: 90
|
time: 90
|
||||||
default_value: on
|
default_value: on
|
||||||
|
|||||||
+24
-6
@@ -11,6 +11,8 @@ from urllib.parse import urlparse
|
|||||||
|
|
||||||
class Vertex2(SmartObject):
|
class Vertex2(SmartObject):
|
||||||
def on_initialize_smart_object(self):
|
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._interrupt_stop = threading.Event()
|
||||||
self._status_requested = threading.Event()
|
self._status_requested = threading.Event()
|
||||||
self._tx0_recovery_attempted = False
|
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.vertex2_tcp_port = int(self.args.get('vertex2_tcp_port', 2220))
|
||||||
self._interrupt_thread = threading.Thread(
|
self._interrupt_thread = threading.Thread(
|
||||||
target=self._interrupt_listener,
|
target=self._interrupt_listener,
|
||||||
|
args=(self._interrupt_stop,),
|
||||||
name=f'{self.name}_interrupt_listener',
|
name=f'{self.name}_interrupt_listener',
|
||||||
daemon=True,
|
daemon=True,
|
||||||
)
|
)
|
||||||
self.update_vertex2_states()
|
self.update_vertex2_states()
|
||||||
self._interrupt_thread.start()
|
self._interrupt_thread.start()
|
||||||
|
|
||||||
def _interrupt_listener(self):
|
def _interrupt_listener(self, interrupt_stop):
|
||||||
address = urlparse(self.args['vertex2_address'])
|
address = urlparse(self.args['vertex2_address'])
|
||||||
host = address.hostname
|
host = address.hostname
|
||||||
status_fields = ('rx0', 'rx1', 'tx0', 'tx1', 'tx0sink', 'tx1sink', 'aud0', 'aud1', 'audout', 'spd0', 'spd1')
|
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',)
|
commands = tuple(f'get status {field}' for field in status_fields) + ('get insel',)
|
||||||
expected = set(status_fields) | {'insel'}
|
expected = set(status_fields) | {'insel'}
|
||||||
|
|
||||||
while not self._interrupt_stop.is_set():
|
while not interrupt_stop.is_set():
|
||||||
try:
|
try:
|
||||||
with socket.create_connection((host, self.vertex2_tcp_port), timeout=10) as connection:
|
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.
|
# Detect a silent reboot/network loss without polling HDMI status.
|
||||||
connection.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
connection.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
||||||
connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 10)
|
connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 10)
|
||||||
@@ -178,7 +183,7 @@ class Vertex2(SmartObject):
|
|||||||
previous_snapshot = None
|
previous_snapshot = None
|
||||||
previous_snapshot_generation = 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():
|
if status_started is None and self._status_requested.is_set():
|
||||||
self._status_requested.clear()
|
self._status_requested.clear()
|
||||||
status = {}
|
status = {}
|
||||||
@@ -195,6 +200,8 @@ class Vertex2(SmartObject):
|
|||||||
raise OSError('Vertex2 TCP status response timed out')
|
raise OSError('Vertex2 TCP status response timed out')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if interrupt_stop.is_set():
|
||||||
|
break
|
||||||
if not data:
|
if not data:
|
||||||
raise OSError('Vertex2 closed the IP INTERRUPT connection')
|
raise OSError('Vertex2 closed the IP INTERRUPT connection')
|
||||||
|
|
||||||
@@ -251,7 +258,7 @@ class Vertex2(SmartObject):
|
|||||||
raise OSError('Vertex2 TCP status response timed out')
|
raise OSError('Vertex2 TCP status response timed out')
|
||||||
|
|
||||||
except (OSError, ValueError) as error:
|
except (OSError, ValueError) as error:
|
||||||
if self._interrupt_stop.is_set():
|
if interrupt_stop.is_set():
|
||||||
break
|
break
|
||||||
self.unreachable_sensor.set_state(state='on')
|
self.unreachable_sensor.set_state(state='on')
|
||||||
self.video_tx_signal_sensor.set_state(state='unavailable')
|
self.video_tx_signal_sensor.set_state(state='unavailable')
|
||||||
@@ -262,7 +269,7 @@ class Vertex2(SmartObject):
|
|||||||
sensor.set_state(state='unavailable')
|
sensor.set_state(state='unavailable')
|
||||||
self.audio_out_signal_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.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):
|
def trigger_tx0_stuck_workaround(self, kwargs):
|
||||||
if self._tx0_recovery_attempted:
|
if self._tx0_recovery_attempted:
|
||||||
@@ -288,13 +295,24 @@ class Vertex2(SmartObject):
|
|||||||
self.log_info('Vertex2 TX0 +5V workaround: restoring TX0 +5V FORCE')
|
self.log_info('Vertex2 TX0 +5V workaround: restoring TX0 +5V FORCE')
|
||||||
self.force_tx0_plus5(True)
|
self.force_tx0_plus5(True)
|
||||||
|
|
||||||
def terminate(self):
|
def _stop_interrupt_listener(self):
|
||||||
interrupt_stop = getattr(self, '_interrupt_stop', None)
|
interrupt_stop = getattr(self, '_interrupt_stop', None)
|
||||||
if interrupt_stop is not None:
|
if interrupt_stop is not None:
|
||||||
interrupt_stop.set()
|
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)
|
restore_handle = getattr(self, '_tx0_recovery_restore_handle', None)
|
||||||
if restore_handle is not None:
|
if restore_handle is not None:
|
||||||
self.cancel_timer(restore_handle)
|
self.cancel_timer(restore_handle)
|
||||||
|
self._tx0_recovery_restore_handle = None
|
||||||
|
|
||||||
|
def terminate(self):
|
||||||
|
self._stop_interrupt_listener()
|
||||||
super().terminate()
|
super().terminate()
|
||||||
|
|
||||||
def generate_input_selected_sensor_name(self,i):
|
def generate_input_selected_sensor_name(self,i):
|
||||||
|
|||||||
Reference in new issue
Block a user