Skip to content

Instantly share code, notes, and snippets.

@tako2
Created September 28, 2017 09:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tako2/cae1b5e63af1385743d2fe622309fe73 to your computer and use it in GitHub Desktop.
Save tako2/cae1b5e63af1385743d2fe622309fe73 to your computer and use it in GitHub Desktop.
Arduboy HEX File Manager for MacOS
#!/usr/bin/env python
# coding: UTF-8
# Arduboy HEX File Manager
import Tkinter
from ScrolledText import *
from PIL import Image, ImageEnhance, ImageTk
import os
import os.path
import serial
import time
import subprocess
uart_device = '/dev/tty.usbmodem1421'
class ArduboyWriter:
def __init__(self, uart_device):
'''Initialize'''
self.uart = uart_device
avrdude_path = '/Applications/Arduino.app/Contents/Java/hardware/tools/avr/'
self.avrdude_conf = avrdude_path + 'etc/avrdude.conf'
self.avrdude_cmd = avrdude_path + 'bin/avrdude'
def reset(self):
ser = serial.Serial(self.uart, 1200)
ser.write('')
ser.close()
def exec_write_command(self, hex_file):
cmd = [self.avrdude_cmd, '-C' + self.avrdude_conf, '-v',
'-patmega32u4', '-cavr109', '-P' + self.uart, '-b57600',
'-D', '-Uflash:w:%s:i' % hex_file]
subprocess.call(cmd)
def write_hex_file(self, hex_file):
self.reset()
time.sleep(2)
self.exec_write_command(hex_file)
def load_image(path):
image = Image.open(path)
if image.size[1] > 280:
scale = 280.0 / image.size[1]
image = image.resize((int(image.size[0] * scale), 280))
if image.size[0] > 500:
scale = 500.0 / image.size[0]
image = image.resize((500, int(image.size[1] * scale)))
return image.convert('RGB')
def get_hex_info(path):
info = {}
if path.lower().endswith('.arduboy'):
'''.arduboy file'''
pass
else:
if not path.endswith('/'):
path += '/'
files = os.listdir(path)
for file in files:
file = path + file
if file.lower().endswith('.hex'):
info['hex_file'] = file
elif file.lower().endswith('.png'):
info['banner'] = file
elif file.lower().endswith('.txt'):
fp = open(file)
info['description'] = fp.read()
fp.close()
elif file.lower().endswith('.url'):
info['url'] = file
info['files'] = files
return info
def load_filelist(path):
files = os.listdir(path)
filelist = ['..',]
for file in files:
if os.path.isdir(path + file):
filelist.append(file)
elif file.endswith('.arduboy'):
filelist.append(file)
return filelist
class ManagerFrame(Tkinter.Frame):
def __init__(self, path, master=None):
Tkinter.Frame.__init__(self, master)
self.master.title('Arduboy HEX File Manager')
self.width = 800
self.height = 600
self.master.geometry('%dx%d' % (self.width, self.height))
if not path.endswith('/'):
path += '/'
self.path = path
dirname = self.path.split('/')[-2]
# Left Frame
left_frame = Tkinter.Frame(self)
# Directory Name
self.dir_label = Tkinter.Label(left_frame, text=dirname)
self.dir_label.grid(row=0, column=0, columnspan=2, sticky=Tkinter.W)
# File List
filelist = load_filelist(self.path)
self.listbox = Tkinter.Listbox(left_frame, height=30)
self.listbox.grid(row=1, column=0)
self.listbox.bind("<Double-Button-1>", self.select)
self.listbox.insert(Tkinter.END, *filelist)
listbox_scr = Tkinter.Scrollbar(left_frame, orient=Tkinter.VERTICAL, command=self.listbox.yview)
self.listbox['yscrollcommand'] = listbox_scr.set
listbox_scr.grid(row=1, column=1, sticky=Tkinter.N+Tkinter.S)
# Exit Button
def done(event):
self.quit()
btn_done = Tkinter.Button(left_frame, text='Exit')
btn_done.bind('<Button-1>', done)
btn_done.grid(row=2, column=0, columnspan=2, padx=10, pady=10)
left_frame.pack(side=Tkinter.LEFT, fill=Tkinter.Y, padx=10, pady=10)
self.info = {}
self.right_frame = Tkinter.Frame(self)
banner = Tkinter.Label(self.right_frame, text='HEX File details here.', width=self.width)
banner.pack(padx=10, pady=10)
self.right_frame.pack(side=Tkinter.RIGHT, fill=Tkinter.BOTH, padx=10, pady=10)
def nop(self, event):
pass
def download1(self, event):
self.download_btn.configure(text='Writing...', state=Tkinter.DISABLED)
self.download_btn.bind('<Button-1>', self.nop)
def download2(self, event):
'''Download to Arduboy'''
print 'Download ' + self.info['hex_file'] + ' to Arduboy'
global uart_device
writer = ArduboyWriter(uart_device)
writer.write_hex_file(self.info['hex_file'])
self.download_btn.configure(text='Finished')
self.download_btn.bind('<ButtonRelease-1>', self.nop)
def show_details(self, path):
self.right_frame.destroy()
self.right_frame = Tkinter.Frame(self)
self.info = get_hex_info(path)
try:
self.img = load_image(self.info['banner'])
self.banner_img = ImageTk.PhotoImage(self.img)
banner = Tkinter.Label(self.right_frame, image=self.banner_img, bg='black')
banner.pack(padx=10, pady=10)
except:
banner = Tkinter.Label(self.right_frame, text='No Image')
banner.pack(padx=10, pady=10)
description = Tkinter.Text(self.right_frame, height=5)
description.insert(Tkinter.END, self.info['description'])
description.pack(padx=10, pady=10)
files = Tkinter.Listbox(self.right_frame, height=5)
files.insert(Tkinter.END, *self.info['files'])
files.pack(padx=10, pady=10)
idx = 0
for file in self.info['files']:
if file.lower().endswith('.hex'):
files.activate(idx)
idx += 1
self.download_btn = Tkinter.Button(self.right_frame, text='Download to Arduboy')
self.download_btn.bind('<Button-1>', self.download1)
self.download_btn.bind('<ButtonRelease-1>', self.download2)
self.download_btn.pack(padx=10, pady=10)
self.right_frame.pack(side=Tkinter.RIGHT, fill=Tkinter.BOTH, padx=10, pady=10)
def select(self, event):
'''Select Item from File List'''
new_path = self.listbox.get(Tkinter.ACTIVE)
if new_path == '..':
paths = self.path.split('/')
self.path = '/'.join(paths[:-2]) + '/'
filelist = load_filelist(self.path)
self.listbox.delete(0, self.listbox.size())
self.listbox.insert(Tkinter.END, *filelist)
dirname = self.path.split('/')[-2]
self.dir_label.config(text=dirname)
elif new_path.lower().endswith('.arduboy'):
# not implemented
self.right_frame.destroy()
self.right_frame = Tkinter.Frame(self)
label = Tkinter.Label(self.right_frame, text='.arduboy File is not implemented yet.', width=self.width)
label.pack(padx=10, pady=10)
self.right_frame.pack(side=Tkinter.RIGHT, fill=Tkinter.BOTH, padx=10, pady=10)
else:
has_hex = False
for file in os.listdir(self.path + new_path):
if file.endswith('.hex'):
has_hex = True
if has_hex:
'''Renewal'''
self.show_details(self.path + new_path)
else:
self.path = self.path + new_path + '/'
filelist = load_filelist(self.path)
self.listbox.delete(0, self.listbox.size())
self.listbox.insert(Tkinter.END, *filelist)
dirname = self.path.split('/')[-2]
self.dir_label.config(text=dirname)
###############################################################################
from optparse import OptionParser
import sys
if __name__ == '__main__':
parser = OptionParser('usage: %prog (options) ([Path])')
parser.add_option('-v', '--verbose',
action='store_true', dest='verbose', default=False,
help='verbose mode')
parser.add_option("-d", "--device", dest="uart_device",
help="change uart device (default /dev/tty.usbmodem1421)", metavar="DEVICE")
(options, args) = parser.parse_args()
if (len(args) < 1):
path = os.getcwd()
else:
path = args[0]
if options.uart_device:
uart_device = options.uart_device
print uart_device
frame = ManagerFrame(path)
frame.pack()
frame.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment