Added logging and fixed CPU thrashing
This commit is contained in:
parent
cfa7c3687c
commit
16ead63221
4 changed files with 83 additions and 20 deletions
|
|
@ -139,7 +139,6 @@ class ControllerProtocol():
|
||||||
|
|
||||||
# Parsing the Switch's message
|
# Parsing the Switch's message
|
||||||
message = SwitchReportParser(data)
|
message = SwitchReportParser(data)
|
||||||
# print(message.response)
|
|
||||||
|
|
||||||
# Responding to the parsed message
|
# Responding to the parsed message
|
||||||
if message.response == SwitchResponses.REQUEST_DEVICE_INFO:
|
if message.response == SwitchResponses.REQUEST_DEVICE_INFO:
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ import socket
|
||||||
import fcntl
|
import fcntl
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import traceback
|
|
||||||
import queue
|
import queue
|
||||||
|
import logging
|
||||||
|
|
||||||
from .controller import Controller, ControllerTypes
|
from .controller import Controller, ControllerTypes
|
||||||
from ..bluez import BlueZ
|
from ..bluez import BlueZ
|
||||||
|
|
@ -18,6 +18,10 @@ class ControllerServer():
|
||||||
state=None, task_queue=None, lock=None, colour_body=None,
|
state=None, task_queue=None, lock=None, colour_body=None,
|
||||||
colour_buttons=None):
|
colour_buttons=None):
|
||||||
|
|
||||||
|
self.logger = logging.getLogger('nxbt')
|
||||||
|
# Cache logging level to increase performance on checks
|
||||||
|
self.logger_level = self.logger.level
|
||||||
|
|
||||||
if state:
|
if state:
|
||||||
self.state = state
|
self.state = state
|
||||||
else:
|
else:
|
||||||
|
|
@ -100,8 +104,8 @@ class ControllerServer():
|
||||||
# Attempt to get output from Switch
|
# Attempt to get output from Switch
|
||||||
try:
|
try:
|
||||||
reply = itr.recv(50)
|
reply = itr.recv(50)
|
||||||
if len(reply) > 40:
|
if self.logger_level <= logging.DEBUG and len(reply) > 40:
|
||||||
print(format_msg_switch(reply))
|
self.logger.debug(format_msg_switch(reply))
|
||||||
except BlockingIOError:
|
except BlockingIOError:
|
||||||
reply = None
|
reply = None
|
||||||
|
|
||||||
|
|
@ -125,8 +129,8 @@ class ControllerServer():
|
||||||
self.input.set_protocol_input(state=self.state)
|
self.input.set_protocol_input(state=self.state)
|
||||||
msg = self.protocol.get_report()
|
msg = self.protocol.get_report()
|
||||||
|
|
||||||
if reply and len(reply) > 45:
|
if self.logger_level <= logging.DEBUG and reply and len(reply) > 45:
|
||||||
print(format_msg_controller(msg))
|
self.logger.debug(format_msg_controller(msg))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
itr.sendall(msg)
|
itr.sendall(msg)
|
||||||
|
|
@ -155,7 +159,7 @@ class ControllerServer():
|
||||||
|
|
||||||
while self.reconnect_counter < 2:
|
while self.reconnect_counter < 2:
|
||||||
try:
|
try:
|
||||||
print("Attempting to reconnect")
|
self.logger.debug("Attempting to reconnect")
|
||||||
# Reinitialize the protocol
|
# Reinitialize the protocol
|
||||||
self.protocol = ControllerProtocol(
|
self.protocol = ControllerProtocol(
|
||||||
self.controller_type,
|
self.controller_type,
|
||||||
|
|
@ -172,12 +176,12 @@ class ControllerServer():
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
except OSError:
|
except OSError:
|
||||||
self.reconnect_counter += 1
|
self.reconnect_counter += 1
|
||||||
print(error)
|
self.logger.exception(error)
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
# If we can't reconnect, transition to attempting
|
# If we can't reconnect, transition to attempting
|
||||||
# to connect to any Switch.
|
# to connect to any Switch.
|
||||||
print("Connecting")
|
self.logger.debug("Connecting to any Switch")
|
||||||
self.reconnect_counter = 0
|
self.reconnect_counter = 0
|
||||||
|
|
||||||
# Reinitialize the protocol
|
# Reinitialize the protocol
|
||||||
|
|
@ -189,9 +193,14 @@ class ControllerServer():
|
||||||
self.input.reassign_protocol(self.protocol)
|
self.input.reassign_protocol(self.protocol)
|
||||||
|
|
||||||
# Since we were forced to attempt a reconnection
|
# Since we were forced to attempt a reconnection
|
||||||
# we need to press the L and R buttons before
|
# we need to press the L/SL and R/SR buttons before
|
||||||
# we can proceed with any input.
|
# we can proceed with any input.
|
||||||
self.input.current_macro_commands = "L R 0.0s".strip(" ").split(" ")
|
if self.controller_type == ControllerTypes.PRO_CONTROLLER:
|
||||||
|
self.input.current_macro_commands = "L R 0.0s".strip(" ").split(" ")
|
||||||
|
elif self.controller_type == ControllerTypes.JOYCON_L:
|
||||||
|
self.input.current_macro_commands = "JCL_SL JCL_SR 0.0s".strip(" ").split(" ")
|
||||||
|
elif self.controller_type == ControllerTypes.JOYCON_R:
|
||||||
|
self.input.current_macro_commands = "JCR_SL JCR_SR 0.0s".strip(" ").split(" ")
|
||||||
|
|
||||||
if self.lock:
|
if self.lock:
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
|
|
@ -255,16 +264,16 @@ class ControllerServer():
|
||||||
# Attempt to get output from Switch
|
# Attempt to get output from Switch
|
||||||
try:
|
try:
|
||||||
reply = itr.recv(50)
|
reply = itr.recv(50)
|
||||||
if len(reply) > 40:
|
if self.logger_level <= logging.DEBUG and len(reply) > 40:
|
||||||
print(format_msg_switch(reply))
|
self.logger.debug(format_msg_switch(reply))
|
||||||
except BlockingIOError:
|
except BlockingIOError:
|
||||||
reply = None
|
reply = None
|
||||||
|
|
||||||
self.protocol.process_commands(reply)
|
self.protocol.process_commands(reply)
|
||||||
msg = self.protocol.get_report()
|
msg = self.protocol.get_report()
|
||||||
|
|
||||||
if reply:
|
if self.logger_level <= logging.DEBUG and reply:
|
||||||
print(format_msg_controller(msg))
|
self.logger.debug(format_msg_controller(msg))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
itr.sendall(msg)
|
itr.sendall(msg)
|
||||||
|
|
|
||||||
30
nxbt/logging.py
Normal file
30
nxbt/logging.py
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def create_logger(debug=False, log_to_file=False, disable_logging=False):
|
||||||
|
|
||||||
|
logger = logging.getLogger('nxbt')
|
||||||
|
|
||||||
|
if disable_logging:
|
||||||
|
null_handler = logging.NullHandler()
|
||||||
|
logger.addHandler(null_handler)
|
||||||
|
return logger
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
if log_to_file:
|
||||||
|
file_handler = logging.FileHandler(f'./nxbt {datetime.now()}.log')
|
||||||
|
file_handler.setFormatter(
|
||||||
|
logging.Formatter("[%(asctime)s] %(levelname)s in %(module)s: %(message)s")
|
||||||
|
)
|
||||||
|
logger.addHandler(file_handler)
|
||||||
|
else:
|
||||||
|
stream_handler = logging.StreamHandler()
|
||||||
|
stream_handler.setFormatter(
|
||||||
|
logging.Formatter("[%(asctime)s] %(levelname)s in %(module)s: %(message)s")
|
||||||
|
)
|
||||||
|
logger.addHandler(stream_handler)
|
||||||
|
|
||||||
|
return logger
|
||||||
35
nxbt/nxbt.py
35
nxbt/nxbt.py
|
|
@ -4,6 +4,8 @@ from enum import Enum
|
||||||
import atexit
|
import atexit
|
||||||
import signal
|
import signal
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
import dbus
|
import dbus
|
||||||
|
|
||||||
|
|
@ -12,6 +14,7 @@ from .controller import ControllerTypes
|
||||||
from .bluez import find_objects, toggle_input_plugin
|
from .bluez import find_objects, toggle_input_plugin
|
||||||
from .bluez import find_devices_by_alias
|
from .bluez import find_devices_by_alias
|
||||||
from .bluez import SERVICE_NAME, ADAPTER_INTERFACE
|
from .bluez import SERVICE_NAME, ADAPTER_INTERFACE
|
||||||
|
from .logging import create_logger
|
||||||
|
|
||||||
|
|
||||||
JOYCON_L = ControllerTypes.JOYCON_L
|
JOYCON_L = ControllerTypes.JOYCON_L
|
||||||
|
|
@ -82,7 +85,23 @@ class Nxbt():
|
||||||
This allows for thread-safe control of emulated controllers.
|
This allows for thread-safe control of emulated controllers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, debug=False, log_to_file=False, disable_logging=False):
|
||||||
|
"""Initializes the necessary multiprocessing resources and starts
|
||||||
|
the multiprocessing processes.
|
||||||
|
|
||||||
|
:param debug: Enables the debugging functionality of
|
||||||
|
nxbt, defaults to False
|
||||||
|
:type debug: bool, optional
|
||||||
|
:param log_to_file: A boolean value that indiciates whether or not
|
||||||
|
a log should be saved to the current working directory, defaults to False
|
||||||
|
:type log_to_file: bool, optional
|
||||||
|
:param disable_logging: Routes all logging calls to a null log handler.
|
||||||
|
:type disable_logging: bool, optional, defaults to False.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.debug = debug
|
||||||
|
self.logger = create_logger(
|
||||||
|
debug=self.debug, log_to_file=log_to_file, disable_logging=disable_logging)
|
||||||
|
|
||||||
# Main queue for nbxt tasks
|
# Main queue for nbxt tasks
|
||||||
self.task_queue = Queue()
|
self.task_queue = Queue()
|
||||||
|
|
@ -93,7 +112,7 @@ class Nxbt():
|
||||||
# Creates/manages shared resources
|
# Creates/manages shared resources
|
||||||
self.resource_manager = Manager()
|
self.resource_manager = Manager()
|
||||||
# Shared dictionary for viewing overall nxbt state.
|
# Shared dictionary for viewing overall nxbt state.
|
||||||
# Should only be read by threads and wrote to by
|
# Should treated as read-only except by
|
||||||
# the main nxbt multiprocessing process.
|
# the main nxbt multiprocessing process.
|
||||||
self.manager_state = self.resource_manager.dict()
|
self.manager_state = self.resource_manager.dict()
|
||||||
self.manager_state_lock = Lock()
|
self.manager_state_lock = Lock()
|
||||||
|
|
@ -156,12 +175,12 @@ class Nxbt():
|
||||||
cm = __ControllerManager__(state, self.__bluetooth_lock__)
|
cm = __ControllerManager__(state, self.__bluetooth_lock__)
|
||||||
# Ensure a SystemExit exception is raised on SIGTERM
|
# Ensure a SystemExit exception is raised on SIGTERM
|
||||||
# so that we can gracefully shutdown.
|
# so that we can gracefully shutdown.
|
||||||
signal.signal(signal.SIGTERM, lambda sigterm_handler: quit())
|
signal.signal(signal.SIGTERM, lambda sigterm_handler: sys.exit(0))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
msg = task_queue.get_nowait()
|
msg = task_queue.get(timeout=5)
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
msg = None
|
msg = None
|
||||||
|
|
||||||
|
|
@ -192,7 +211,7 @@ class Nxbt():
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
cm.shutdown()
|
cm.shutdown()
|
||||||
quit()
|
sys.exit(0)
|
||||||
|
|
||||||
def macro(self, controller_index, macro, block=True):
|
def macro(self, controller_index, macro, block=True):
|
||||||
"""Used to input a given macro on a specified controller.
|
"""Used to input a given macro on a specified controller.
|
||||||
|
|
@ -241,6 +260,8 @@ class Nxbt():
|
||||||
if macro_id in finished:
|
if macro_id in finished:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
time.sleep(1/120) # Wait one Pro Controller cycle
|
||||||
|
|
||||||
return macro_id
|
return macro_id
|
||||||
|
|
||||||
def press_buttons(self, controller_index, buttons, down=0.1, up=0.1, block=True):
|
def press_buttons(self, controller_index, buttons, down=0.1, up=0.1, block=True):
|
||||||
|
|
@ -358,6 +379,8 @@ class Nxbt():
|
||||||
if macro_id in finished:
|
if macro_id in finished:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
time.sleep(1/120)
|
||||||
|
|
||||||
def clear_macros(self, controller_index):
|
def clear_macros(self, controller_index):
|
||||||
"""Clears all running and queued macros on a specified
|
"""Clears all running and queued macros on a specified
|
||||||
controller.
|
controller.
|
||||||
|
|
@ -468,6 +491,8 @@ class Nxbt():
|
||||||
state["state"] == "reconnecting" or
|
state["state"] == "reconnecting" or
|
||||||
state["state"] == "crashed"):
|
state["state"] == "crashed"):
|
||||||
break
|
break
|
||||||
|
|
||||||
|
time.sleep(1/30)
|
||||||
finally:
|
finally:
|
||||||
self.__controller_lock__.release()
|
self.__controller_lock__.release()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue