Esempio n. 1
0
    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()
Esempio n. 2
0
    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()
Esempio n. 3
0
    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)
Esempio n. 4
0
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()
Esempio n. 5
0
def main():
    """ Runs the launch controller """

    hide_console()
    log_controller = Controller()
    run(log_controller)