def launch(self): """ Launches/connects to required servers and runs the script """ if "servers" in self.config_dict: self._launch_servers() if not ('script_server' in self.config_dict and self.config_dict['script_server'] == 'False'): self._launch_script_server() hide_console() self._launch_scripts()
def _connect_matched_servers(self, matches, module, config_name, config, auto_connect, optional_clients): """ Connects to a list of servers that have been matched to a given device module. :param matches: (list) list of matching server modules :param module: (str) name of module to launch (e.g. nidaqmx) :param config_name: (str) name of the config file for the device server :param config: (dict) actual config dict for the server :param auto_connect: (bool) whether or not to automatically connect to the device/server :param optional_clients: (bool) whether the current script should still run if it cannot connect to a desired client server """ device_id = config['device_id'] num_matches = len(matches) module_name = module if 'auto_launch' in config and config['auto_launch'] == 'False': launch_stop = True else: launch_stop = False #specify the number of times we want to try to connect to a server if 'num_connect_tries' in self.config_dict: NUM_TRIES = self.config_dict['num_connect_tries'] else: NUM_TRIES = 10 # If there are no matches, launch and connect to the server manually if num_matches == 0: if launch_stop: self.logger.info( f'No No active servers matching module {module_name}' 'were found. Please instantiate manually.') if (not optional_clients): raise Exception( 'Server must be launched manually prior to script') else: self.logger.info( f'No active servers matching module {module_name}' ' were found. Instantiating a new server.') host, port = launch_device_server( server=module, dev_config=config_name, log_ip=self.log_ip, log_port=self.log_port, server_port=np.random.randint(1024, 49151), debug=self.server_debug, logger=self.logger) tries = 0 while tries < NUM_TRIES: try: self._connect_to_server(module, host, port, device_id) tries = NUM_TRIES + 1 except ConnectionRefusedError: time.sleep(0.1) tries += 1 if tries == NUM_TRIES: self.logger.error(f'Failed to connect to {module}') # If there is exactly 1 match, try to connect automatically elif num_matches == 1 and auto_connect: self.logger.info(f'Found exactly 1 match for {module_name}.') self._connect_to_server(module, matches[0].ip, matches[0].port, device_id) # If there are multiple matches, force the user to choose in the launched console else: msg_str = 'Found relevant server(s) already running.\n' self.logger.info(msg_str) for index, match in enumerate(matches): msg_str = ('------------------------------------------\n' + ' ({}) \n'. format(index + 1) + match.summarize()) self.logger.info(msg_str) self.logger.info('------------------------------------------\n\n' 'Which server would you like to connect to?\n' 'Please enter a choice from {} to {}.'.format( 1, len(matches))) app, popup = fresh_popup(index=int) self.waiting_flag = True popup.parameters.connect(self.find_index) while self.waiting_flag: app.processEvents() self.logger.info(f'User chose ({self.use_index})') # If the user's choice falls within a relevant GUI, attempt to connect. try: if self.use_index - 1 < 0: raise IndexError host, port = matches[self.use_index - 1].ip, matches[self.use_index - 1].port self._connect_to_server(module, host, port, device_id) # If the user's choice did not exist, just launch a new GUI except IndexError: self.logger.info('Launching new server') host, port = launch_device_server( server=module, dev_config=config_name, log_ip=self.log_ip, log_port=self.log_port, server_port=np.random.randint(1024, 49151), debug=self.server_debug, logger=self.logger) tries = 0 while tries < NUM_TRIES: try: self._connect_to_server(module, host, port, device_id) tries = NUM_TRIES + 1 except ConnectionRefusedError: time.sleep(0.1) tries += 1 if tries == NUM_TRIES: self.logger.error(f'Failed to connect to {module}') hide_console()
def __init__(self, proxy=False, master=False, staticproxy=False): """ Initializes launch control GUI """ self.operating_system = get_os() self.app = QtWidgets.QApplication(sys.argv) self.app.setWindowIcon( QtGui.QIcon( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'devices.ico'))) # Instantiate GUI application if self.operating_system == 'Windows': ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID( 'pylabnet') self.main_window = LaunchWindow(self.app, self, gui_template=self.LOGGER_UI) self.main_window.stop_button.clicked.connect(self._kill) if self.operating_system not in ['Linux', 'Windows']: raise UnsupportedOSException try: if sys.argv[1] == '-m' or master: self.master = True else: self.master = False except IndexError: if master: self.master = True else: self.master = False try: if sys.argv[1] == '-p' or proxy: self.proxy = True else: self.proxy = False except IndexError: if proxy: self.proxy = True else: self.proxy = False try: if sys.argv[1] == '-sp' or staticproxy: self.staticproxy = True else: self.staticproxy = False except IndexError: if staticproxy: self.staticproxy = True else: self.staticproxy = False self.host = get_ip() self.update_index = 0 # Retrieve static port info. if self.master: try: static_proxy_dict = load_config('static_proxy') except: print('No config found named static_proxy.json') time.sleep(10) raise self.log_port = static_proxy_dict['master_log_port'] self.gui_port = static_proxy_dict['master_gui_port'] hide_console() elif self.proxy: popup = ParameterPopup(host=str, log_port=str, gui_port=str) self.waiting_flag = True popup.parameters.connect(self.fill_parameters) while self.waiting_flag: self.app.processEvents() elif self.staticproxy: try: static_proxy_dict = load_config('static_proxy') except: print('No config found named static_proxy.json') time.sleep(10) raise self.host = static_proxy_dict['master_ip'] self.log_port = static_proxy_dict['master_log_port'] self.gui_port = static_proxy_dict['master_gui_port'] self.proxy = True hide_console() else: self.log_port = self.LOG_PORT self.gui_port = self.GUI_PORT self.log_service = None self.log_server = None self.gui_client = None self.gui_logger = None self.gui_service = None self.gui_server = None self.client_list = {} self.port_list = {} self.script_list = {} self.client_data = {} self.disconnection = False self.debug = False self.debug_level = None self.autoscroll_off = False # date string is None if not logging to file, and gives today's date if logging to file. # For day-chopping purposes self.logfile_date_str = None self.filenamepath = None self.MAX_LOG_FILE_SIZE = 5000000 # 5MB self.last_seen_buffer = "" # setting selection mode for server list to multi-select self.main_window.client_list.setSelectionMode( QtWidgets.QAbstractItemView.ExtendedSelection)
def main(): # parse command line arguments args = parse_args() try: log_port = int(args['logport']) except IndexError: raise IndexError( 'Please provide command line arguments in the form\n"' 'python launch_gui.py --logport 1234 --serverport 5678 --server servername' ) if 'serverport' in args: server_port = int(args['serverport']) else: server_port = None if 'server' in args: server = args['server'] else: raise IndexError( 'Please provide command line arguments in the form\n"' 'python launch_gui.py --logport 1234 --serverport 5678 --server servername' ) if 'logip' in args: log_ip = args['logip'] else: log_ip = 'localhost' # If pylabnet.server is launched directly, it might not use a configs flag. if 'config' in args: config = args['config'] else: config = None device_id = args['device_id'] logger_tag = server + '_server' + '_' + device_id # Instantiate logger. This creates a client_data entry in the LogServer # that is populated with the server name, port. server_logger = LogClient(host=log_ip, port=log_port, module_tag=logger_tag, server_port=server_port) # Add device ID of server to LogClient data dict server_logger.update_data(data=dict(device_id=device_id)) # Retrieve debug flag. debug = int(args['debug']) # Halt execution and wait for debugger connection if debug flag is up. if debug: # 5678 is the default attach port in the VS Code debug configurations server_logger.info( f"Waiting for debugger to attach to PID {os.getpid()} (pylabnet_server)" ) ptvsd.enable_attach(address=('localhost', 5678)) ptvsd.wait_for_attach() breakpoint() # Register new exception hook. def log_exceptions(exc_type, exc_value, exc_traceback): """Handler for unhandled exceptions that will write to the logs""" error_msg = ''.join( traceback.format_exception(exc_type, exc_value, exc_traceback)) server_logger.error(f"Uncaught exception: {error_msg}") sys.excepthook = log_exceptions # Instantiate module try: mod_inst = importlib.import_module(f'servers.{server}') except ModuleNotFoundError: server_logger.error( f'No module found in pylabnet.launchers.servers named {server}.py') raise tries = 0 update_flag = False while tries < 10: if server_port is None: server_port = np.random.randint(1024, 49151) update_flag = True try: mod_inst.launch(logger=server_logger, port=server_port, device_id=device_id, config=config) if update_flag: server_logger.update_data(data=dict(port=server_port)) tries = 10 except OSError: server_logger.warn( f'Failed to launch server at port: {server_port}') tries += 1 if tries == 10: raise hide_console()
def main(): """ Runs the launch controller """ hide_console() log_controller = Controller() run(log_controller)