Example #1
0
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)
Example #3
0
    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)
Example #4
0
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')
Example #5
0
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)
Example #7
0
    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')
Example #9
0
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)