Added connection reset watchdog

This commit is contained in:
Brikwerk 2021-09-10 01:23:07 +01:00
commit bef7180b88

View file

@ -6,11 +6,11 @@ import queue
import logging import logging
import traceback import traceback
import atexit import atexit
from threading import Thread
import numpy as np import statistics as stat
from .controller import Controller, ControllerTypes from .controller import Controller, ControllerTypes
from ..bluez import BlueZ from ..bluez import BlueZ, find_devices_by_alias
from .protocol import ControllerProtocol from .protocol import ControllerProtocol
from .input import InputParser from .input import InputParser
from .utils import format_msg_controller, format_msg_switch from .utils import format_msg_controller, format_msg_switch
@ -104,9 +104,13 @@ class ControllerServer():
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass
except Exception: except Exception:
self.state["state"] = "crashed" try:
self.state["errors"] = traceback.format_exc() self.state["state"] = "crashed"
return self.state self.state["errors"] = traceback.format_exc()
return self.state
except Exception as e:
self.logger.debug("Error during graceful shutdown:")
self.logger.debug(traceback.format_exc())
def mainloop(self, itr, ctrl): def mainloop(self, itr, ctrl):
@ -181,9 +185,10 @@ class ControllerServer():
self.times.append(elapsed_time) self.times.append(elapsed_time)
if len(self.times) > 100: if len(self.times) > 100:
self.times.pop() self.times.pop()
mean_time = np.mean(self.times) mean_time = stat.mean(self.times)
self.logger.debug(self.tick, 1/mean_time) self.logger.debug(
f"Tick: {self.tick}, Mean Time: {str(1/mean_time)}")
def save_connection(self, error, state=None): def save_connection(self, error, state=None):
@ -250,6 +255,39 @@ class ControllerServer():
return itr, ctrl return itr, ctrl
def connection_reset_watchdog(self):
connected_devices = []
connected_devices_count = {}
while self._crw_running:
paths = self.bt.find_connected_devices(alias_filter="Nintendo Switch")
# Keep track of Switches that connect
if len(paths) > 0:
connected_devices = list(set(connected_devices + paths))
# Increment a counter if a Switch connected and disconnected
disconnected = list(set(connected_devices) - set(paths))
if len(disconnected) > 0:
for path in disconnected:
if path not in connected_devices_count.keys():
connected_devices_count[path] = 1
else:
connected_devices_count[path] += 1
connected_devices = list(set(connected_devices) - set(disconnected))
# Delete Switches that connect/disconnect twice.
# This behaviour is characteristic of connection issues and is corrected
# by removing the Switch's connection to the system.
if len(connected_devices_count.keys()) > 0:
for key in connected_devices_count.keys():
if connected_devices_count[key] >= 2:
self.logger.debug(
"A Nintendo Switch disconnected. Resetting Connection...")
self.logger.debug(f"Removing {str(key)}")
self.bt.remove_device(key)
connected_devices_count[key] = 0
time.sleep(0.25)
def connect(self): def connect(self):
"""Configures as a specified controller, pairs with a Nintendo Switch, """Configures as a specified controller, pairs with a Nintendo Switch,
and creates/accepts sockets for communication with the Switch. and creates/accepts sockets for communication with the Switch.
@ -286,9 +324,15 @@ class ControllerServer():
# the class will be reset to the default value. # the class will be reset to the default value.
self.bt.set_class("0x02508") self.bt.set_class("0x02508")
self._crw_running = True
crw = Thread(target = self.connection_reset_watchdog)
crw.start()
itr, itr_address = s_itr.accept() itr, itr_address = s_itr.accept()
ctrl, ctrl_address = s_ctrl.accept() ctrl, ctrl_address = s_ctrl.accept()
self._crw_running = False
# Send an empty input report to the Switch to prompt a reply # Send an empty input report to the Switch to prompt a reply
self.protocol.process_commands(None) self.protocol.process_commands(None)
msg = self.protocol.get_report() msg = self.protocol.get_report()