コード例 #1
0
ファイル: main.py プロジェクト: tren01t/Smartto-Tool
class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.serial_list = None
        self.updator = None
        self.news_list = None
        self.firmware_list = None

        # initialize widgets/UI
        self.createWindow(master, 1280, 800)
        self.createWidget(master)

        try:
            self.network_manager = NetworkManager(self)
            profile_path = os.path.join(
                os.path.join(os.path.split(os.path.realpath(__file__))[0]),
                "net.conf")
            profile_u_path = path_2_unicode(profile_path)
            self.network_manager.detect_network_queue()
            self.network_manager.load_config(profile_u_path)
            self.network_manager.run_tasks()
            self.network_manager.detect_serial_port()
            self.network_manager.detect_news()
            self.output_to_panel('success',
                                 'Connecting remote end successfully!\n')
        except Exception as e:
            self.output_to_panel(
                'error',
                'Network manager setup failed! Details: ' + str(e) + '\n')

        self.init_ad_board()
        self.init_output_board()

    def show_firmware_details(self, event):
        lbx = event.widget
        index = lbx.curselection()
        size = len(index)
        if size > 0:
            for i in index[::-1]:
                self.firmware_text.delete(1.0, END)
                self.firmware_text.insert(
                    END,
                    'Firmware:\n' + self.firmware_list[i]["name"] + '\n\n')
                self.firmware_text.see(END)
                details = self.firmware_list[i]["details"]
                for item in details:
                    if item["type"] == "feature":
                        self.firmware_text.insert(END, 'Features:\n')
                        self.firmware_text.see(END)
                        for index, descs in enumerate(item["description"]):
                            self.firmware_text.insert(END, descs + '\n\n')
                            self.firmware_text.see(END)
                    elif item["type"] == "bug":
                        self.firmware_text.insert(END, 'Bugs:\n')
                        self.firmware_text.see(END)
                        for index, descs in enumerate(item["description"]):
                            self.firmware_text.insert(END, descs + '\n\n')
                            self.firmware_text.see(END)
                self.firmware_text.see(END)

    def init_output_board(self):
        prompt_conf = {
            "info": "blue",
            "progress": "yellow",
            "success": "green",
            "error": "red"
        }
        for tag, color in prompt_conf.items():
            self.info_text.tag_config(tag, foreground=color)

    def init_ad_board(self):
        prompt_conf = {"info": "blue", "warning": "yellow", "solved": "green"}
        for tag, color in prompt_conf.items():
            self.news_text.tag_config(tag, foreground=color)

    def show_notice(self, level, msg):
        prompt = {}
        (prompt['info'], prompt['warning'], prompt['solved']) = ["☼", "☢", "☑"]
        if level in ['info', 'warning', 'solved']:
            self.news_text.insert(END, prompt[level], level)
            self.news_text.insert(END, ' ' + msg)
            self.news_text.see(END)

    def output_to_panel(self, level, msg):
        prompt = {}
        (prompt['info'], prompt['progress'], prompt['success'],
         prompt['error']) = ["☼", "➢", "✔", "✘"]
        if level in ['info', 'progress', 'success', 'error']:
            self.info_text.insert(END, prompt[level], level)
            self.info_text.insert(END, ' ' + msg)
            self.info_text.see(END)

    def createWindow(self, root, width, height):
        screenwidth = root.winfo_screenwidth()
        screenheight = root.winfo_screenheight()
        size = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2,
                                (screenheight - height) / 2)
        root.geometry(size)
        root.maxsize(width, height)
        root.minsize(width, height)

    def createWidget(self, master):

        ft = tkFont.Font(family='Lucida Console', size=15)

        self.news_panel = Frame(master, width=450)
        self.news_panel.pack(side=LEFT, fill=Y)

        self.news_upper_menu = Frame(self.news_panel, height=10)
        self.news_upper_menu.pack(side=TOP, fill=X, pady=5)

        self.btn_connect_to_remote = Button(self.news_upper_menu,
                                            width=64,
                                            text="Reconnect to remote",
                                            height=1,
                                            command=self.reconnect_to_remote)
        self.btn_connect_to_remote.pack(side=LEFT, anchor="n", padx=10)

        self.news_board = Frame(self.news_panel)
        self.news_board.pack(side=TOP, fill=X, pady=5)

        self.news_text = ScrolledText(self.news_board,
                                      state="normal",
                                      width=66,
                                      height=10,
                                      font=ft,
                                      highlightbackground='black',
                                      highlightthickness=1)
        self.news_text.pack(side=LEFT, anchor="n", padx=5)

        self.firmware_board = Frame(self.news_panel)
        self.firmware_board.pack(side=TOP, fill=X, pady=5)

        firmware_list_ft = tkFont.Font(family='Lucida Console', size=12)
        self.lbx_firmware = Listbox(self.firmware_board,
                                    width=29,
                                    height=32,
                                    font=firmware_list_ft)
        self.lbx_firmware.pack(side=LEFT, anchor="n", padx=5)
        self.lbx_firmware.bind('<<ListboxSelect>>', self.show_firmware_details)

        self.firmware_text = ScrolledText(self.firmware_board,
                                          state="normal",
                                          width=44,
                                          height=34,
                                          font=firmware_list_ft,
                                          highlightbackground='black',
                                          highlightthickness=1)
        self.firmware_text.pack(side=LEFT, anchor="n", padx=5)

        self.news_lower_menu = Frame(self.news_panel, height=10)
        self.news_lower_menu.pack(side=TOP, fill=X, pady=5)

        self.btn_upgrade_from_remote = Button(
            self.news_lower_menu,
            width=64,
            text="Upgrade from remote",
            height=1,
            command=self.create_remote_upgrade_thread)
        self.btn_upgrade_from_remote.pack(side=LEFT, anchor="n", padx=10)

        self.user_panel = Frame(master)
        self.user_panel.pack(side=LEFT, fill=Y)

        self.user_upper_menu = Frame(self.user_panel, height=10)
        self.user_upper_menu.pack(side=TOP, fill=X, pady=5)

        self.lb_port_list = Label(self.user_upper_menu,
                                  text="Port:",
                                  width=6,
                                  height=1)
        self.lb_port_list.pack(side=LEFT, anchor="n", padx=5)
        self.port_item = StringVar()
        self.cb_port_list = ttk.Combobox(self.user_upper_menu,
                                         width=25,
                                         textvariable=self.port_item,
                                         state="readonly")
        self.cb_port_list["values"] = self.serial_list or ("Empty")
        self.cb_port_list.current(0)
        self.cb_port_list.pack(side=LEFT, anchor="w", padx=5)

        self.btn_select = Button(self.user_upper_menu,
                                 text="Select",
                                 height=1,
                                 width=18,
                                 command=self.select_firmware)
        self.btn_select.pack(side=LEFT, anchor="w", padx=10)

        self.btn_clear = Button(self.user_upper_menu,
                                text="Clear",
                                height=1,
                                width=8,
                                command=self.clear_info_text)
        self.btn_clear.pack(side=LEFT, anchor="w", padx=10)

        self.display_board = Frame(self.user_panel)
        self.display_board.pack(side=TOP, fill=X, pady=5)

        self.info_text = ScrolledText(self.display_board,
                                      state="normal",
                                      width=70,
                                      height=39,
                                      font=ft,
                                      highlightbackground='black',
                                      highlightthickness=1)
        self.info_text.bind("<KeyPress>", lambda e: "break")
        self.info_text.pack(side=LEFT, anchor="n", padx=5)
        self.info_text.drop_target_register('DND_Files')
        self.info_text.dnd_bind('<<Drop>>', self.drop_file)

        self.user_lower_menu = Frame(self.user_panel, height=10)
        self.user_lower_menu.pack(side=TOP, fill=X, pady=5)

        self.btn_upgrade_from_local = Button(
            self.user_lower_menu,
            width=64,
            text="Upgrade from local",
            height=1,
            command=self.create_upgrade_thread)
        self.btn_upgrade_from_local.pack(side=LEFT, anchor="n", padx=10)

        self.output_to_panel('info',
                             "Drag and drop local firmware into here.\n")

    def drop_file(self, event):
        self.file_path = event.data
        if self.file_path is not None and self.file_path != "":
            self.output_to_panel('success',
                                 "Selected path: " + self.file_path + '\n')

    def select_firmware(self):
        self.file_path = filedialog.askopenfilename(
            filetypes=[('BIN', 'bin'), ('HEX', 'hex')])
        if self.file_path is not None and self.file_path != "":
            self.output_to_panel('success',
                                 "Selected path: " + self.file_path + '\n')

    def clear_info_text(self):
        self.info_text.delete(1.0, END)

    def create_remote_upgrade_thread(self):
        index = self.lbx_firmware.curselection()
        size = len(index)
        if size > 0:
            remote_upgrade_thread = threading.Thread(
                target=self.start_to_remote_upgrade, args=(index))
            remote_upgrade_thread.setDaemon(True)
            remote_upgrade_thread.start()
        else:
            self.output_to_panel(
                'error', "You haven't selected any remote firmware!\n")

    def start_to_remote_upgrade(self, firmware_index):
        '''
        self.btn_upgrade_from_local["state"] = "disabled"
        self.btn_upgrade_from_remote["state"] = "disabled"
        self.btn_connect_to_remote["state"] = "disabled"
        self.btn_select["state"] = "disabled"
        self.btn_clear["state"] = "disabled"
        '''

        try:
            url = self.firmware_list[firmware_index]["url"]
            self.output_to_panel('info',
                                 'Start to get firmware from remote...\n')
            r = requests.get(url)
            if r.status_code == 200:
                firmware_path = os.path.join(
                    os.path.join(os.path.split(os.path.realpath(__file__))[0]),
                    "Firmware", "origin", "firmware.zip")
                firmware_u_path = path_2_unicode(firmware_path)
                with open(firmware_u_path, "wb") as code:
                    code.write(r.content)
                self.output_to_panel(
                    'success', 'Firmware downloaded to Firmware/origin/\n')
            elif r.status_code == 404:
                self.output_to_panel('error', 'Firmware doesn\'t exist\n')
                return
            else:
                self.output_to_panel(
                    'error', 'Firmware downloaded error! Details: code--%d\n' %
                    r.status_code)
                return
        except Exception as e:
            self.output_to_panel(
                'error',
                'Firmware downloaded error! Details: ' + str(e) + '\n')
            return

        self.output_to_panel('info', 'Start to extract files from zip...\n')
        firmware_extract_path = os.path.join(
            os.path.join(os.path.split(os.path.realpath(__file__))[0]),
            "Firmware", "extract")
        firmware_extract_u_path = path_2_unicode(firmware_extract_path)

        self.target_file_list = []

        try:
            f = zipfile.ZipFile(firmware_u_path, 'r')
            for file in f.namelist():
                if '_S_' in file or 'hex' in file or 'HEX' in file:
                    self.target_file_list.append(file)
                f.extract(file, firmware_extract_u_path)
            self.output_to_panel('success',
                                 'Firmware extracted to Firmware/extract\n')
        except Exception as e:
            self.output_to_panel(
                'error', 'Firmware extracted error! Details: ' + str(e) + '\n')
            return

        self.updator = FirmwareUpdator(self.info_text)

        profile_path = os.path.join(
            os.path.join(os.path.split(os.path.realpath(__file__))[0]),
            "default.conf")
        profile_u_path = path_2_unicode(profile_path)

        self.file_path = path_2_unicode(
            os.path.join(firmware_extract_path, self.target_file_list[0]))
        self.updator.update_firmware(profile_u_path, self.port_item.get(),
                                     self.file_path)
        '''
        self.btn_upgrade_from_local["state"] = "normal"
        self.btn_upgrade_from_remote["state"] = "normal"
        self.btn_connect_to_remote["state"] = "normal"
        self.btn_select["state"] = "normal"
        self.btn_clear["state"] = "normal"
        '''

    def create_upgrade_thread(self):
        if hasattr(self, 'file_path'):
            upgrade_thread = threading.Thread(target=self.start_to_upgrade,
                                              args=())
            upgrade_thread.setDaemon(True)
            upgrade_thread.start()
        else:
            self.output_to_panel('error',
                                 "You haven't selected any firmware files!\n")

    def start_to_upgrade(self):
        self.btn_upgrade_from_local["state"] = "disabled"
        self.btn_upgrade_from_remote["state"] = "disabled"
        self.btn_connect_to_remote["state"] = "disabled"
        self.btn_select["state"] = "disabled"
        self.btn_clear["state"] = "disabled"
        self.updator = FirmwareUpdator(self.info_text)

        profile = os.path.join(
            os.path.split(os.path.realpath(__file__))[0], "default.conf")
        profile_path = os.path.join(
            os.path.join(os.path.split(os.path.realpath(__file__))[0]),
            "default.conf")
        profile_u_path = path_2_unicode(profile_path)

        self.updator.update_firmware(profile_u_path, self.port_item.get(),
                                     self.file_path)
        self.btn_upgrade_from_local["state"] = "normal"
        self.btn_upgrade_from_remote["state"] = "normal"
        self.btn_connect_to_remote["state"] = "normal"
        self.btn_select["state"] = "normal"
        self.btn_clear["state"] = "normal"

    def reconnect_to_remote(self):
        self.network_manager.run_tasks()
        self.output_to_panel('success',
                             'Reconnecting remote end successfully!\n')

    def close_connection(self):
        if self.updator is not None:
            self.updator.close_serial()