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()