Exemplo n.º 1
0
    def __get_user_rate(self, type, port):
        old_completer = readline.get_completer()

        rates = []
        for rate in Connection.BAUDRATES:
            rates.append(str(rate))

        compl_rates = Completer(rates)
        readline.set_completer(compl_rates.list_completer)
        rate = None
        while rate is None:
            rate = input(f'{Fore.YELLOW}{type} rate:{Fore.RESET} ').strip()
            if rate in ['q', 'exit']:
                break
            elif rate == '':
                rate = Connection.get_baudrate(port)
            elif rate not in rates:
                error(f'Rate {rate} is not valid.')
                warning('Valid baudrates:')
                for rate in rates:
                    warning('\t' + rate)
                warning('Type \'exit\' to return.')
                rate = None
            else:
                rate = int(rate)

        readline.set_completer(old_completer)
        return rate
Exemplo n.º 2
0
    def get_ack(self, timeout):
        length = b''
        while length == b'':
            length = self.connection.read(2)
            time.sleep(0.01)

        self.connection.read(1)  # Checksum
        self.connection.read(1)  # 0x00
        response = self.connection.read(1)

        while response not in [OPCODE.ACK, OPCODE.NACK]:
            if self.start_time == 0:
                self.start_time = time.perf_counter()

            if time.perf_counter() - self.start_time > timeout:
                response = None
                break

            response = self.connection.read(1)
            time.sleep(0.01)

        self.start_time = 0

        if response == OPCODE.ACK:
            return True
        elif response == OPCODE.NACK:
            error('Received NACK')
            return False
        else:
            error('Received unexpected data or timeout!')
            return False
Exemplo n.º 3
0
    def do_listen(self, args=''):
        '''
        Start listener and parser thread

        Starting listener on connected ports. If mmWave is not configured,
        default configuration will be send first.

        Look \'connect\' and \'autoconnect\' command for connecting to mmWave.

        Usage:
        >> listen
        '''
        if args != '':
            error('Unknown arguments.')
            return

        if not self.configured:
            warning('mmWave not configured.')
            return

        with self.listening_lock:
            if self.listening:
                warning('Listener already started.')
                return

        with self.listening_lock:
            self.listening = True

        self.__listen_thread()
        self.__parse_thread()
Exemplo n.º 4
0
    def __get_user_port(self, type):
        old_completer = readline.get_completer()

        ports = []
        for port in serial.tools.list_ports.comports():
            ports.append(port[0])

        compl_ports = Completer(ports)
        readline.set_completer_delims('\t')
        readline.parse_and_bind('tab: complete')
        readline.set_completer(compl_ports.list_completer)

        port = None
        while port is None:
            port = input(f'{Fore.YELLOW}{type} port:{Fore.RESET} ').strip()
            if port in ['q', 'exit']:
                return
            elif port not in ports:
                error(f'Port {port} is not valid.')
                warning('Valid ports:')
                for port in ports:
                    warning('\t' + port)
                warning('Type \'exit\' to return.')
                port = None

        readline.set_completer(old_completer)
        return port
Exemplo n.º 5
0
    def do_train(self, args=''):
        '''
        Train neural network

        Command will first load cached X and y data located in
        'mmwave/data/.X_data' and 'mmwave/data/.y_data' files. This data will be
        used for the training process. If you want to read raw .csv files,
        provide \'refresh\' (this will take few minutes).

        Usage:
        >> train
        >> train refresh
        '''

        if len(args.split()) > 1:
            error('Unknown arguments.')
            return

        if args == '':
            refresh_data = False
        elif args == 'refresh':
            refresh_data = True
        else:
            warning(f'Unknown argument: {args}')
            return

        X, y = Logger.get_all_data(refresh_data=refresh_data)
        Logger.get_stats(X, y)
        X_train, X_val, y_train, y_val = train_test_split(X,
                                                          y,
                                                          test_size=.3,
                                                          stratify=y,
                                                          random_state=12)
        self.model.train(X_train, y_train, X_val, y_val)
Exemplo n.º 6
0
    def do_print(self, args=''):
        '''
        Pretty print

        Printing received frames. Listener should be started before using
        this command. Use <Ctrl-C> to stop this command.

        Usage:
        >> print
        '''
        if args != '':
            error('Unknown arguments.')
            return

        with self.listening_lock:
            if not self.listening:
                error('Listener not started.')
                return

        with self.printing_lock:
            self.printing = True

        self.console_queue.get()

        with self.printing_lock:
            self.printing = False
Exemplo n.º 7
0
    def do_predict(self, args=''):
        '''
        Start prediction

        Passing received frames through neural network and printing results.
        Listener should be started before using this command.
        Use <Ctrl-C> to stop this command.

        Usage:
        >> predict
        '''
        if args != '':
            error('Unknown arguments.')
            return

        with self.listening_lock:
            if not self.listening:
                error('Listener not started.')
                return

        if not self.__model_loaded():
            self.model.load()
            print()

        with self.predicting_lock:
            self.predicting = True

        self.__predict_thread()

        self.console_queue.get()

        with self.predicting_lock:
            self.predicting = False

        self.model_queue.put(None)
Exemplo n.º 8
0
    def do_remove(self, args=''):
        '''
        Remove last sample

        Removing last gesture sample. Data will be removed from
        \'mmwave/data/gesture_foder\' folder.
        Possible options: \'up\', \'down\', \'left\', \'right\', \'cw\',
                          \'ccw\', \'s\', \'z\', \'x\'
        Usage:
        >> remove up
        >> remove ccw
        >> remove z
        '''
        if args == '':
            error('too few arguments.')
            return

        if len(args.split()) > 1:
            error('Unknown arguments.')
            return

        if not GESTURE.check(args):
            warning(f'Unknown argument: {args}')
            return

        self.logger.set_gesture(args)
        self.logger.discard_last_sample()
Exemplo n.º 9
0
 def default(self, line):
     '''
     Called on an input line when the command prefix is not recognized.
     In that case we execute the line as Python code.
     '''
     try:
         exec(line) in self._locals, self._globals
     except Exception:
         error('Unknown arguments.')
         return
Exemplo n.º 10
0
    def do_send(self, args=''):
        '''
        Sending configuration to mmWave

        Configuring mmWave with given configuration file. All configuration
        files should be placed in \'mmwave/communication/profiles\' folder.
        Use <Tab> for autocompletion on available configuration files.
        All configuration files should have .cfg extension.
        If no configuration is provided, default configuration file will be
        used.

        Usage:
        >> send
        >> send profile
        '''
        if args == '':
            args = self.default_config

        if len(args.split()) > 1:
            error('Too many arguments.')
            return

        if not self.__is_connected():
            error('Not connected.')
            return

        cfg = os.path.join(self.config_dir, args + '.cfg')
        if cfg not in glob.glob(os.path.join(self.config_dir, '*.cfg')):
            print('Unknown profile.')
            return

        mmwave_configured = False
        cnt = 0
        while not mmwave_configured and cnt < 5:
            mmwave_configured = self.mmwave.configure(cfg)
            if not mmwave_configured:
                signal_cnt = 0
                while signal_cnt < 5:
                    if not self.console_queue.empty():
                        self.console_queue.get()
                        return
                    time.sleep(.2)
                    signal_cnt += 1
            cnt += 1

        if not mmwave_configured:
            return

        if os.path.basename(cfg) == 'stop.cfg':
            self.configured = False
        else:
            self.configured = True
        self.config = cfg
Exemplo n.º 11
0
    def do_exit(self, args):
        '''Exits from the console'''

        if args != '':
            error('Unknown arguments.')
            return

        self.do_stop()

        if self.__is_connected():
            self.mmwave.disconnect()

        os._exit(0)
Exemplo n.º 12
0
    def send_cmd(self, command, get_status=False, resp=True):
        self.send_packet(command)
        if not self.get_ack(command.timeout):
            error('Command was not successful!')
            return

        if get_status:
            self.send_packet(CMD(OPCODE.GET_STATUS))

        response = ''
        if resp:
            response = self.get_response()
        return response
Exemplo n.º 13
0
    def do_get_model(self, args=''):
        '''
        Get current model type.

        Usage:
        >> get_model
        '''

        if args != '':
            error('Unknown arguments.')
            return

        print(f'Current model type: {self.model_type}')
Exemplo n.º 14
0
    def do_eval(self, args=''):
        '''
        Evaluate neural network

        Command will first load cached X and y data located in
        \'mmwave/data/.X_data\' and \'mmwave/data/.y_data\' files. This data
        will be used for the evaluating process. If you want to read raw .csv
        files, provide \'refresh\' (this will take few minutes).

        Usage:
        >> eval
        >> eval refresh
        '''

        if len(args.split()) > 1:
            error('Unknown arguments.')
            return

        if args == '':
            refresh_data = False
        elif args == 'refresh':
            refresh_data = True
        else:
            warning(f'Unknown argument: {args}')
            return

        X, y = Logger.get_all_data(refresh_data=refresh_data)
        Logger.get_stats(X, y)

        X_train, X_val, y_train, y_val = train_test_split(X,
                                                          y,
                                                          test_size=.3,
                                                          stratify=y,
                                                          random_state=12)

        if not self.__model_loaded():
            self.model.load()
            print()

        print('Eval validation dataset:')
        self.model.evaluate(X_val, y_val)
        print()

        print('Eval train dataset:')
        self.model.evaluate(X_train, y_train)
        print()

        print('Eval full dataset:')
        self.model.evaluate(X, y)
        print()
Exemplo n.º 15
0
    def get_response(self):
        header = self.connection.read(3)
        packet_size, checksum = struct.unpack('>HB', header)
        packet_size -= 2  # Compensate for the header

        payload = self.connection.read(packet_size)

        self.connection.write(OPCODE.ACK, size=0)  # Ack the packet

        calculated_checksum = sum(payload) & 0xff
        if (calculated_checksum != checksum):
            error('Checksum error on received packet.')
            return

        return payload
Exemplo n.º 16
0
    def do_connect(self, args=''):
        '''
        Manually connecting to mmWave

        Command will ask you to manualy type ports and baudrates.
        Use <Tab> for autocompletion on available ports and baudrates.
        Type \'exit\' for exiting manual connection.
        If you only press enter on baudrates, console will try to find
        baudrate automatically. Note that this will work only if connection
        is already opened from both sides. (On mmWave startup only cli port
        is open, and data port will open only after \'senstrStart\' command)

        Look \'autoconnect\' command for automatic connection.

        Usage:
        >> connect
        cli port: /dev/ttyACM0
        cli rate: 115200
        data port: /dev/ttyACM1
        data rate: 921600
        '''

        if args != '':
            error('Unknown arguments.')
            return

        if self.__is_connected():
            self.mmwave.disconnect()
            print()

        port = self.__get_user_port('cli')
        if port is not None:
            self.cli_port = port
            self.cli_rate = self.__get_user_rate('cli', port)
        else:
            return

        port = self.__get_user_port('data')
        if port is not None:
            self.data_port = port
            self.data_rate = self.__get_user_rate('data', port)
        else:
            return

        self.__mmwave_init()
Exemplo n.º 17
0
    def do_plot(self, args=''):
        '''
        Start plotter

        Plotting received frames. Listener should be started before using
        this command. Use \'stop plot\' to stop this command.

        Usage:
        >> plot
        '''
        if args != '':
            error('Unknown arguments.')
            return

        self.plotter_queues['cli'].put('init')

        with self.plotting_lock:
            self.plotting = True
Exemplo n.º 18
0
    def do_redraw(self, args=''):
        '''
        Redraw sample

        Redrawing last captured gesture file.
        Possible options: \'up\', \'down\', \'left\', \'right\', \'cw\',
                          \'ccw\', \'s\', \'z\', \'x\'

        Usage:
        >> redraw up
        >> redraw ccw
        >> redraw z
        '''
        if args == '':
            error('too few arguments.')
            return

        if len(args.split()) > 1:
            error('Unknown arguments.')
            return

        with self.plotting_lock:
            if not self.plotting:
                error('Plotter not started.')
                return

        if not GESTURE.check(args):
            warning(f'Unknown argument: {args}')
            return

        self.plotter_queues['cli'].put('redraw')
        self.plotter_queues['cli'].put(args)
Exemplo n.º 19
0
    def do_flash(self, args=''):
        '''
        Sending .bin files to mmWave

        Flashing bin files to connected mmWave. It is possible to specify up to
        4 meta files. SOP0 and SOP2 have be closed and power reseted before
        running this command.

        Look \'connect\' and \'autoconnect\' command for connecting to mmWave.

        Usage:
        >> flash xwr16xx_mmw_demo.bin
        '''
        if len(args.split()) > 4:
            error('Too many arguments.')
            return

        if args == '':
            error('Too few arguments.')
            return

        filepaths = []
        for arg in args.split():
            filepath = os.path.join(self.firmware_dir, arg)
            if not os.path.isfile(filepath):
                error(f'File \'{filepath}\' doesn\'t exist.')
                return
            filepaths.append(filepath)

        if not self.__is_connected():
            error('Not connected.')
            return

        print('Ping mmWave...', end='')
        response = self.flasher.send_cmd(CMD(OPCODE.PING), resp=False)
        if response is None:
            warning('Check if SOP0 and SOP2 are closed, and reset the power.')
            return
        print(f'{Fore.GREEN}Done.')

        print('Get version...', end='')
        response = self.flasher.send_cmd(CMD(OPCODE.GET_VERSION))
        if response is None:
            return
        print(f'{Fore.GREEN}Done.')
        print(f'{Fore.BLUE}Version:', binascii.hexlify(response))
        print()

        self.flasher.flash(filepaths, erase=True)
        print(f'{Fore.GREEN}Done.')
Exemplo n.º 20
0
    def do_set_model(self, args=''):
        '''
        Set model type used for prediction. Available models are
        \'conv\' (convolutional 1D), \'lstm\' (long short-term memory) and
        \'trans\' (transformer). Default is lstm.

        Usage:
        >> set_model conv
        >> set_model lstm
        >> set_model trans
        '''

        if len(args.split()) > 1:
            error('Too many arguments.')
            return

        if args not in ['conv', 'lstm', 'trans']:
            warning(f'Unknown argument: {args}')
            return

        self.model_type = args
        self.__set_model(args)
Exemplo n.º 21
0
    def do_start(self, args=''):
        '''
        Start listener, plotter and prediction.

        If mmWave is not configured, default configuration will be send
        first. Use <Ctrl-C> to stop this command.

        Usage:
        >> start
        '''
        if args != '':
            error('Unknown arguments.')
            return

        if not self.__model_loaded():
            self.model.load()
            print()

        self.do_send(self.default_config)
        self.do_listen()
        self.do_plot()
        self.do_predict()
        self.do_stop()
Exemplo n.º 22
0
    def do_autoconnect(self, args=''):
        '''
        Auto connecting to mmWave

        Automatically looking for \'XDS\' ports and connecting with default
        baudrates. Auto-detection is only applicable for eval boards with
        XDS110.

        Look \'connect\' command for manual connection.

        Usage:
        >> autoconnect
        '''
        if args != '':
            error('Unknown arguments.')
            return

        if self.__is_connected():
            warning('Already connected.')
            print('Reconnecting...')

        self.cli_port = None
        self.data_port = None
        self.__mmwave_init()
Exemplo n.º 23
0
    def do_log(self, args=''):
        '''
        Log data

        Logging specified gesture. Data will be saved in
        \'mmwave/data/gesture_foder/sameple_num.csv\' file.
        Possible options: \'up\', \'down\', \'left\', \'right\', \'cw\',
                          \'ccw\', \'s\', \'z\', \'x\'

        Usage:
        >> log up
        >> log ccw
        >> log z
        '''
        if args == '':
            error('too few arguments.')
            return

        if len(args.split()) > 1:
            error('Unknown arguments.')
            return

        with self.listening_lock:
            if not self.listening:
                error('Listener not started.')
                return

        if not GESTURE.check(args):
            warning(f'Unknown argument: {args}')
            return

        self.logger.set_gesture(args)

        with self.logging_lock:
            self.logging = True

        self.__logging_thread().join()

        with self.logging_lock:
            self.logging = False
Exemplo n.º 24
0
    def flash(self,
              files,
              file_id=4,
              storage='SFLASH',
              mirror_enabled=0,
              erase=False):
        if not isinstance(files, list):
            files = [files]

        if erase:
            print('Formating flash...', end='')
            self.erase()
            print(f'{Fore.GREEN}Done.')

        for file in files:
            file_size = os.path.getsize(file)
            print(
                f'Writing {list(Flasher.FILES)[file_id]} [{file_size} bytes]')

            if file_size < 0 and file_size > Flasher.MAX_FILE_SIZE:
                error('Invalid file size')
                return False

            with open(file, 'rb') as f:
                resp = self.send_cmd(CMD(
                    OPCODE.OPEN_FILE,
                    data=(struct.pack('>I', file_size) +
                          Flasher.STORAGES[storage] +
                          list(Flasher.FILES.values())[file_id] +
                          struct.pack('>I', mirror_enabled))),
                                     get_status=True)
                if resp != OPCODE.RET_SUCCESS:
                    error('Opening file failed.')
                    return False

                pbar = tqdm(total=file_size // Flasher.BLOCK_SIZE + 1,
                            desc='Blocks')
                offset = 0
                while offset < file_size:
                    block = f.read(Flasher.BLOCK_SIZE)
                    if (storage == 'SRAM'):
                        resp = self.send_cmd(CMD(OPCODE.WRITE_FILE_RAM,
                                                 data=block),
                                             get_status=True)
                    else:
                        resp = self.send_cmd(CMD(OPCODE.WRITE_FILE,
                                                 data=block),
                                             get_status=True)

                    if resp != OPCODE.RET_SUCCESS:
                        error('Sending file failed.')
                        return False

                    offset += len(block)
                    pbar.update(1)
            pbar.close()

            self.send_cmd(CMD(OPCODE.CLOSE_FILE,
                              data=list(Flasher.FILES.values())[file_id]),
                          resp=False)

            file_id += 1
            if file_id > 7:
                break

        return True
Exemplo n.º 25
0
 def do_history(self, args):
     '''Print a list of commands that have been entered'''
     if args != '':
         error('Unknown arguments.')
         return
     print(self._hist)