def upload_file(local_path: str, remote_path: str) -> None: esp_port = __get_upload_port() print(f"Found esp device at port {esp_port}") pyb = Pyboard(esp_port, rawdelay=1) f = Files(pyb) print(f.ls()) with open(local_path, 'rb') as local_file: f.put(remote_path, local_file.read())
def make_dirs(files: Files, path: str, created_cache: Set[str] = None) -> None: """Make all the directories the specified relative path consists of.""" if path == '.': return if created_cache is None: created_cache = set() parent = os.path.dirname(path) if parent and parent not in created_cache: make_dirs(files, parent, created_cache) with suppress(DirectoryExistsError): files.mkdir(path) created_cache.add(path)
def _check_onboard_file(self) -> None: ''' Check wether the file exist on the board. ''' board = Files(self._pyboard) ls = board.ls(long_format=False) if ''.join(['/', self.CAN_MODULE]) not in ls: print( f'The file `{self.CAN_MODULE}` is being written to the board.') path = os.path.dirname(__file__) with open(os.path.join(path, self.CAN_MODULE), "rb") as infile: data = infile.read() board.put(self.CAN_MODULE, data)
def main(args: List[str]) -> None: opts = docopt(__doc__, argv=args) port = opts['PORT'] force = opts['--force'] print('Connecting to {}'.format(port), file=sys.stderr) board = Pyboard(port) files = Files(board) # Specifying subdirectories DOES NOT work as they will be deleted when the # parent directory is deleted. Specifying top level directories DOES work. exclude_files = ['boot.py'] print('Removing the contents of the file system') wait_for_board() for name in files.ls(long_format=False): if force or name not in exclude_files: try: files.rm(name) except (RuntimeError, PyboardError): try: files.rmdir(name) except (RuntimeError, PyboardError): print('Unknown Error removing file {}'.format(name), file=sys.stderr) print('Done')
def put(): """ Uploads all necessary files to the pyboard. """ if len(argv) < 2: print( "Pyboard COM port not specified. Usage: led_panel_client_put /dev/tty.wchusbserial1410" ) exit(1) pyboard_pyboard = Pyboard(argv[1]) pyboard_files = Files(pyboard_pyboard) files_to_put = led_panel_client() | max7219() for file_path in files_to_put: name = basename(file_path) with open(file_path) as file_object: data = file_object.read() pyboard_files.put(name, data)
def main(args: List[str]) -> None: global verbose opts = docopt(__doc__, argv=args) verbose = opts['--verbose'] root = opts['PATH'] chdir = opts['--chdir'] if chdir: os.chdir(chdir) port = opts['PORT'] print('Connecting to {}'.format(port), file=sys.stderr) board = Pyboard(port) files = Files(board) rel_root = os.path.relpath(root, os.getcwd()) wait_for_board() if os.path.isdir(root): to_upload = [ os.path.join(rel_root, x) for x in list_files(root, opts['--exclude']) ] else: to_upload = [rel_root] created_cache = set() for path in progress('Uploading files', to_upload): local_path = os.path.abspath(path) remote_path = os.path.normpath(path).replace(os.path.sep, '/') if verbose: print('\n{} -> {}'.format(local_path, remote_path), file=sys.stderr, flush=True) remote_dir = os.path.dirname(path) if remote_dir: make_dirs(files, remote_dir, created_cache) with open(local_path, 'rb') as fd: files.put(remote_path, fd.read()) print('Soft reboot', file=sys.stderr, flush=True) soft_reset(board)
def connect(self, port): """Connect to the selected port and fill window infos""" for button in self.buttons.winfo_children(): button.config(state=NORMAL) self.board_bar.entryconfig(0, state=NORMAL) self.board_bar.entryconfig(1, label="Disconnect", command=self.disconnect) # Shortcuts self.bind("<Control-S>", lambda e: self.disconnect()) self.bind("<Control-s>", lambda e: self.disconnect()) self.port = port self.board = Pyboard(self.port) self.files = Files(self.board) self.connected = True self.refresh()
def main(args: List[str]) -> None: opts = docopt(__doc__, argv=args) port = opts['PORT'] print('Connecting to {}'.format(port), file=sys.stderr) board = Pyboard(port) files = Files(board) print('Removing the contents of the file system') wait_for_board() for name in files.ls(): try: files.rm(name) except (RuntimeError, PyboardError): files.rmdir(name) print('Done')
class AmpyGUI(Tk): def __init__(self): # Report all exceptions to a MessageBox. Tk.report_callback_exception = self.show_error super(AmpyGUI, self).__init__() # region GUI. self.title("AmpyGUI - Version 1.1.0") self.geometry("650x250") self.minsize(650, 250) if sys.platform == "win32": self.iconbitmap("data/AmpyGUI_icon.ico") elif sys.platform == "linux": self.icon = Image("photo", file="data/AmpyGUI_icon.png") self.tk.call("wm", "iconphoto", self._w, self.icon) menu_bar = Menu(self) self.board_bar = Menu(menu_bar, tearoff=0) self.board_bar.add_command(label="Put MPY", command=lambda: PutFiles(self, mpy=True), state=DISABLED, accelerator=" Ctrl+M") self.board_bar.add_command(label="Connect", command=lambda: SelectPort(self), accelerator=" Ctrl+S") self.board_bar.add_command(label="WebREPL", command=lambda: webbrowser.open("http://micropython.org/webrepl/")) self.board_bar.add_separator() self.board_bar.add_command(label="Close", command=self.quit, accelerator=" Alt+F4") help_bar = Menu(menu_bar, tearoff=0) help_bar.add_command(label="GitHub page", command=lambda: webbrowser.open("https://github.com/FlorianPoot/AmpyGUI")) help_bar.add_command(label="About", command=lambda: About(self)) menu_bar.add_cascade(label="Board", menu=self.board_bar) menu_bar.add_cascade(label="Help", menu=help_bar) self.config(menu=menu_bar) self.tree_view = ttk.Treeview(self, selectmode=BROWSE) vsb = ttk.Scrollbar(self, orient="vertical", command=self.tree_view.yview) vsb.grid(column=1, row=0, sticky=N+S) self.tree_view.configure(yscrollcommand=vsb.set) self.tree_view["columns"] = ("type", "size") self.tree_view.column("type", width=50, minwidth=50, stretch=NO) self.tree_view.column("size", width=150, minwidth=150, stretch=NO) self.tree_view.heading("#0", text="Name", anchor=W) self.tree_view.heading("type", text="Type", anchor=W) self.tree_view.heading("size", text="Size", anchor=W) self.tree_view.grid(column=0, row=0, sticky=N+S+E+W) self.tree_view.bind("<ButtonRelease-1>", self.select_item) ttk.Separator(orient=HORIZONTAL).grid(column=0, row=1, columnspan=2, sticky=N+S+E+W) memory = Frame(self, bd=1, relief=GROOVE) self.total_label = Label(memory, text="Total: N/A MB") self.total_label.pack(expand=YES, fill=BOTH, side="left", padx=10) self.free_label = Label(memory, text="Free: N/A MB") self.free_label.pack(expand=YES, fill=BOTH, side="left", padx=10) self.used_label = Label(memory, text="Used: N/A %") self.used_label.pack(expand=YES, fill=BOTH, side="left", padx=10) memory.grid(column=0, row=2, columnspan=2, pady=5) self.buttons = Frame(self) self.get_button = ttk.Button(self.buttons, text="Get", takefocus=False, command=self.get, state=DISABLED) self.get_button.grid(column=0, row=0, sticky=E+W, padx=5) ttk.Button(self.buttons, text="Put", takefocus=False, command=lambda: PutFiles(self), state=DISABLED).grid(column=1, row=0, sticky=E+W, padx=5) ttk.Button(self.buttons, text="MkDir", takefocus=False, command=lambda: MkDir(self), state=DISABLED).grid(column=2, row=0, sticky=E+W, padx=5) ttk.Button(self.buttons, text="Reset", takefocus=False, command=self.reset, state=DISABLED).grid(column=3, row=0, sticky=E+W, padx=5) self.remove_button = ttk.Button(self.buttons, text="Remove", takefocus=False, command=self.remove, state=DISABLED) self.remove_button.grid(column=4, row=0, sticky=E+W, padx=5) ttk.Button(self.buttons, text="Format", takefocus=False, command=self.format, state=DISABLED).grid(column=5, row=0, sticky=E+W, padx=5) for i in range(6): self.buttons.columnconfigure(i, weight=1) self.buttons.grid(column=0, row=3, columnspan=2, sticky=N+S+E+W, padx=10, pady=5) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) # endregion # region Attributes. self.loboris_port = False self.port = None self.board = None self.files = None self.connected = False self.real_paths = dict() # ID: Path # endregion # region Shortcuts self.bind("<Control-S>", lambda e: SelectPort(self)) self.bind("<Control-s>", lambda e: SelectPort(self)) self.bind("<Control-M>", lambda e: PutFiles(self, mpy=True) if self.connected else None) self.bind("<Control-m>", lambda e: PutFiles(self, mpy=True) if self.connected else None) # endregion self.update() # Start port popup SelectPort(self) self.protocol("WM_DELETE_WINDOW", self.close) self.mainloop() def select_item(self, event=None): """Enable buttons if an item is selected in tree view.""" item = self.tree_view.item(self.tree_view.focus())["text"] if self.connected and item != "": self.remove_button.config(state=NORMAL) # Folders are determined by the lack of extension. if "." in item: self.get_button.config(state=NORMAL) else: self.get_button.config(state=DISABLED) else: self.remove_button.config(state=DISABLED) self.get_button.config(state=DISABLED) def connect(self, port): """Connect to the selected port and fill window infos""" for button in self.buttons.winfo_children(): button.config(state=NORMAL) self.board_bar.entryconfig(0, state=NORMAL) self.board_bar.entryconfig(1, label="Disconnect", command=self.disconnect) # Shortcuts self.bind("<Control-S>", lambda e: self.disconnect()) self.bind("<Control-s>", lambda e: self.disconnect()) self.port = port self.board = Pyboard(self.port) self.files = Files(self.board) self.connected = True self.refresh() def disconnect(self): """Disable buttons and release COM port""" for button in self.buttons.winfo_children(): button.config(state=DISABLED) self.board_bar.entryconfig(0, state=DISABLED) self.board_bar.entryconfig(1, label="Connect", command=lambda: SelectPort(self)) # Shortcuts self.bind("<Control-S>", lambda e: SelectPort(self)) self.bind("<Control-s>", lambda e: SelectPort(self)) self.board.close() self.connected = False def get_path(self): """Get path of selected item.""" name = self.tree_view.item(self.tree_view.focus())["text"] item = self.tree_view.focus() if self.loboris_port and (name == "" or "." in name): name = "/flash" for key, values in self.real_paths.items(): if name == values: item = key # Folders are determined by the lack of extension. if item != "" and "." not in name: return self.real_paths[item] + "/" else: return "/" def list_dir(self): """Listdir board and insert result into tree view""" directories = {"": ""} files = self.files.ls(recursive=True) for file in files: name, size = file.split(" - ") directory = name.split("/")[:-1] for index in range(1, len(directory)): if "/".join(directory[:index + 1])[1:] not in directories: _id = self.tree_view.insert(directories["/".join(directory[:index])[1:]], "end", text=directory[index]) self.real_paths[_id] = "/".join(directory[:index + 1]) directories["/".join(directory[:index + 1])[1:]] = _id for file in files: name, size = file.split(" - ") directory = name.split("/")[:-1] directory = "/".join(directory)[1:] # Folders are determined by the lack of extension. if "." in name: _id = self.tree_view.insert(directories[directory], "end", text=name.split("/")[-1], values=(name.split("/")[-1].split(".")[1].upper(), size)) else: _id = self.tree_view.insert(directories[directory], "end", text=name.split("/")[-1]) self.real_paths[_id] = name def clear(self): """Clear tree view""" self.real_paths = dict() self.tree_view.delete(*self.tree_view.get_children()) def time_out(self): """Close board and spread an error popup if delay is over.""" self.board.close() self.disconnect() def get_space_info(self): """Get total space, free space and used space.""" command = """ import uos print(uos.statvfs("{}")) """.format("/" if not self.loboris_port else "/flash") self.board.enter_raw_repl() out = self.board.exec_(textwrap.dedent(command)).decode("utf-8") self.board.exit_raw_repl() out = ast.literal_eval(out) total = round((out[0] * out[2]) / 1024**2, 2) if total == 0: # Loboris port. self.loboris_port = True return self.get_space_info() self.total_label.config(text=f"Total: {total} MB") free = round((out[0] * out[3]) / 1024**2, 2) self.free_label.config(text=f"Free: {free} MB") used = round(((total - free) / total) * 100, 2) self.used_label.config(text=f"Used: {used} %") def refresh(self): """Clear treeview, Listdir and get space info.""" # Start timer timer = threading.Timer(10, self.time_out) timer.start() self.clear() self.list_dir() self.select_item() self.get_space_info() timer.cancel() def get(self): """Download selected item to selected directory.""" def get_thread(): try: with open(path + "/" + name, "wb") as file: file.write(self.files.get(self.real_paths[item])) except Exception as e: self.show_error(e) loading.close() name = self.tree_view.item(self.tree_view.focus())["text"] item = self.tree_view.focus() path = filedialog.askdirectory() loading = Loading(self, title="Downloading") threading.Thread(target=get_thread).start() def remove(self): """Remove selected file or folder.""" if not messagebox.askyesno("Remove", "Are you sure you want to remove the selected file or folder ?"): return item = self.tree_view.focus() # Folders are determined by the lack of extension. if "." not in self.real_paths[item]: self.files.rmdir(self.real_paths[item]) else: self.files.rm(self.real_paths[item]) del self.real_paths[item] self.tree_view.delete(self.tree_view.focus()) self.select_item() self.get_space_info() def reset(self): """Perform a soft reset.""" self.board.serial.write(b"\x03\x04") def format(self): """Remove all files except boot.py.""" def format_thread(): if not self.loboris_port: try: for value in self.real_paths.values(): if value != "/boot.py" and "/" not in value[1:]: # Folders are determined by the lack of extension. if "." not in value: self.files.rmdir(value) else: self.files.rm(value) self.refresh() except Exception as e: self.show_error(e) else: try: self.files.rmdir("/flash") self.refresh() except (Exception, RuntimeError): pass loading.close() if not messagebox.askyesno("Format", "Are you sure you want to remove all files except boot.py ?"): return loading = Loading(self, title="Formatting") threading.Thread(target=format_thread).start() def close(self): """Close board and destroy window.""" try: self.board.close() except AttributeError: pass self.destroy() @staticmethod def show_error(*args): messagebox.showerror("Exception", args)