def close(self): self._close() printing.printf('Closed connection with', self.name, style=printing.STATUS, log=True, logtag='Connection.close')
def _get(self, api_call): get = self.session.get(self.url + api_call).json() if 'Errors' in get: printing.printf('Invalid TBA API call: ', api_call, '\n', get['Errors'], style=printing.YELLOW) return None return get
def close(self): self.connecting = False for connection in self.clients: connection.close() self.clients.clear() self.server_sock.close() printing.printf('Closed server', style=printing.STATUS, log=True, logtag='socketctl.close')
def __init__(self, socket, name, on_receive, on_closed): self.socket = socket self.name = name self.on_receive = on_receive self.on_closed = on_closed printing.printf('Accepted connection from', name, style=printing.CONNECTED, log=True, logtag='Connection.init')
def _run(command): try: process = sub.Popen(command, shell=True, stdout=sub.PIPE, stderr=sub.PIPE) return process.communicate() except Exception as e: printing.printf('Unknown exception on system._run(' + command + '):', end=' ', style=printing.ERROR, log=True, logtag='system._run.error') printing.printf(e, style=printing.ERROR)
def mount(): devs = find_usb_partitions() if not devs: return None dev = [d for d in devs if d not in find_mounted_usbs()] if not dev: loc = get_mount_point(devs[0]) if loc: printing.printf('Drive ' + devs[0] + ' already mounted to ' + loc, style=printing.YELLOW, log=True, logtag='system.mount') return loc else: return None done = 0 printing.printf('Found drive at ' + dev[0] + ', attempting to mount ...', end=' ', style=printing.FLASH_DRIVE) while done < 10: p = _run('udisksctl mount -b ' + dev[0]) error_string = p[1].decode('utf-8').strip('\n') if 'AlreadyMounted' in error_string: loc = get_mount_point(dev[0]) printing.printf('Drive ' + dev[0] + ' already mounted to ' + loc, style=printing.YELLOW, log=True, logtag='system.mount') return loc elif error_string: sleep(.2) done += 1 else: message = p[0].decode('utf-8').strip('\n') printing.printf(message, style=printing.FLASH_DRIVE, log=True, logtag='system.mount') return message.split('at')[1].strip('. ') printing.printf('Error mounting: ' + error_string, style=printing.ERROR, log=True, logtag='system.mount.error') return None
def gethostMAC(): out = '' try: if platform == 'linux': out = _run('hcitool dev') return out[0].decode('utf8').split('\n')[1].split()[1] elif platform == 'darwin': #macOS # Mac is not yet fully supported out = _run('system_profiler SPBluetoothDataType') return out[0].decode('utf8').split('\n')[5].split()[1] else: printing.printf('Server only runs on Linux, not Windows', style=printing.WARNING, log=True, logtag='system.gethostMAC') except IndexError: if out[0]: printing.printf('No bluetooth adapter available', style=printing.ERROR, log=True, logtag='system.gethostMAC.error') else: printing.printf( 'hcitool/system_profiler not found, please install it or edit systemctl.py to use something else', style=printing.ERROR, log=True, logtag='system.gethostMAC.error')
def main(self): self.input_handler.start_listening() printing.printf('Waiting for connections', style=printing.STATUS, log=True, logtag='server.main') self.socketctl.start_connecting() while True: try: self.data_controller.update() except KeyboardInterrupt: # Make sure everything made it into the data file self.data_controller.update() self.socketctl.close() log('server.main', 'Server stopped') log('server.main', '-' * 20) # Quit everything (closes all the many threads) osexit(1)
def unmount(): for dev in find_mounted_usbs(): printing.printf('Unmounting drive from ' + dev + ' ...', end=' ', style=printing.FLASH_DRIVE, log=True, logtag='system.unmount') p = _run('udisksctl unmount -b ' + dev) if p[1]: printing.printf('Error unmounting: ' + p[1].decode('utf-8'), style=printing.ERROR, log=True, logtag='system.unmount.error') else: printing.printf('Unmounting successful, remove device', style=printing.FLASH_DRIVE_SUCCESS, log=True, logtag='system.unmount')
def copy(fin, fout): printing.printf('Copying ' + fin + ' to ' + fout + ' ...', end=' ', style=printing.FLASH_DRIVE, log=True, logtag='system.copy') # with open(fout, 'w') as f: # f.write(open(fin).read()) #copyfile(fin, fout) p = _run('cp ' + fin + ' ' + fout) if p[1]: printing.printf('Error copying: ' + p[1].decode('utf-8'), style=printing.ERROR, log=True, logtag='system.copy.error') else: printing.printf('Copying successful', style=printing.FLASH_DRIVE, log=True, logtag='system.copy')
def _closed(self, error): self._close() printing.printf('Disconnected from', self.name, style=printing.DISCONNECTED, log=True, logtag='Connection.closed') if type(error) not in (ConnectionResetError, TimeoutError, OSError): print(error) try: printing.printf('Unexpected disconnect error:', str(error), style=printing.ERROR, log=True, logtag='Con.closed.error') except TypeError: printing.printf('Unknown disconnect error', style=printing.ERROR, log=True, logtag='Con.closed.error') self.on_closed()
def invalid_msg(msg, client): printing.printf('Invalid message from', client.name, ':', str(msg), style=printing.YELLOW, log=True, logtag='msgctl.invalid_msg')
def find_missing(self, schedule=None): teams_by_match = dict() for device in self.data.values(): for m in device.values(): match = m[max(m.keys(), key=int)] if match[Fields.MATCH] not in teams_by_match: teams_by_match[match[Fields.MATCH]] = [] teams_by_match[match[Fields.MATCH]].append(match[Fields.TEAM]) max_match = max(teams_by_match.keys(), key=int) for i in range(1, int(max_match)): if str(i) not in teams_by_match: teams_by_match[str(i)] = [] for match, teams in sorted(teams_by_match.items(), key=lambda x: int(x[0])): if int(match) <= int(max_match): if schedule: expected = schedule[match]['red'] + schedule[match]['blue'] missing = [] extra = [] for e in expected: if not e in teams: missing.append(e) for t in teams: if not t in expected: extra.append(t) if missing: printing.printf( f'{match:2}: missing data for team{"s" if len(missing)>1 else ""} {", ".join(missing)}', style=printing.YELLOW) if extra: printing.printf( f'{match:2}: data for team{"s" if len(extra)>1 else ""} not in match: {", ".join(extra)}', style=printing.YELLOW) else: if len(set(teams)) < 6: printing.printf( f'{match:2}: missing data, only have team{"s" if len(set(teams))>1 else ""} {", ".join(teams)}', style=printing.YELLOW) elif len(set(teams)) > 6: printing.printf( f'{match:2}: extra data, have teams {", ".join(teams)}', style=printing.YELLOW) if len(set(teams)) != len(teams): printing.printf( f'{match:2}: duplicate data, have entries for: {", ".join(teams)}', style=printing.YELLOW) printing.printf(f'Data found through match {max_match}', style=printing.TEAL)
def missing_field(f, t, r): printing.printf(f'Missing field {f} from data entry {t}.{r}', style=printing.ERROR, log=True, logtag='datactl.error') return 'ERROR'
def quit_(self, *args): printing.printf('Are you sure you want to quit? (y/n)', style=printing.QUIT, end=' ') if input() == 'y': self.running = False interrupt_main()
def print_header(width=None): # Fill width of screen if not width: width = get_terminal_size(fallback=(100, 24))[0] logo = LOGO.replace('\n', '\n' + ' ' * int((width - 50) / 2)) printing.printf(logo, style=printing.LOGO) printing.printf(('{:^' + str(width) + '}').format('FRC Team 449: The Blair Robot Project'), style=printing.HEADER) printing.printf('=' * width, style=printing.HEADER) printing.printf( ('{:^' + str(width) + '}').format('Bluetooth Scouting Server'), style=printing.TITLE) printing.printf() printing.printf( ('{:^' + str(width) + '}').format('Runs with Python3 on Linux'), style=printing.INSTRUCTIONS) printing.printf('-' * width + '\n', style=printing.INSTRUCTIONS) tw = TextWrapper(width=width) printing.printf(tw.fill('Commands:') + '\n' + tw.fill( 'q:\tquit' ) + '\n' + tw.fill( 'd:\trequest drive update (should be automatic when you insert a drive)' ) + '\n' + tw.fill('tba:\tupdate team list and match schedule from tba') + '\n' + tw.fill('st:\tsend team list to all connected devices') + '\n' + tw.fill( 'ss:\tsend match schedule to all connected devices') + '\n' + tw.fill('s m:\tget strat summary for match m') + '\n' + tw.fill('s t t ...: get strat summary for teams') + '\n' + tw.fill('m:\tcheck for missing and duplicate data') + '\n' + '\n' + 'If there are any issues, try restarting the server first', style=printing.INSTRUCTIONS) printing.printf('-' * width + '\n\n', style=printing.UNDERLINE)
def send_schedule(self, *args): schedule = self.server.tba.match_schedule() if schedule: self.server.socketctl.blanket_send(make_message(MsgTypes.SCHEDULE, schedule)) else: printing.printf("Schedule not available for event:", EVENT, style=printing.YELLOW)
def send_teams(self, *args): teams = self.server.tba.team_list() if teams: self.server.socketctl.blanket_send(make_message(MsgTypes.TEAM_LIST, teams)) else: printing.printf("Team list not availible for event:",EVENT, style=printing.YELLOW)
def summarize_data(data, client_name): printing.printf(('Data' if data[Fields.REVISION] == 0 else 'Edit') + ' from ' + data[Fields.SCOUT_NAME] + ' on ' + client_name + ' for team ' + str(data[Fields.TEAM]) + ' in match ' + str(data[Fields.MATCH]), style=printing.NEW_DATA, log=True, logtag='msgctl.handle_msg')
def strat(self, *args, **kwargs): if len(args) == 1: printing.printf(strategy(self.server.tba.teams_in_match(*args)), style=printing.DATA_OUTPUT) else: printing.printf(strategy(args), style=printing.DATA_OUTPUT)