The problem and program that led me to become programmer

Hunter Hartline
Coinmonks
6 min readAug 7, 2018

--

GUI for my first ever application and extensive programming project

My interests have always been what I would call varied and broad in scope. When it comes to “tech”-related things, I would say that it’s actually somewhat limited, or rather, specific where my interests align. The real fun is in the idea of learning “language” — in the most general sense of the word, and acquiring skills that are challenging and allow one to overcome so-called real-world problems. Problem-solving, logic, symbols, and fun aesthetics all playing part to be immensely interesting and, hopefully, potentially beneficial to humankind.

While attempting to earn additional income to pay off my overwhelming amount of debt, my girlfriend and I decided to open an ebay store, offering a service that flashed vintage game files to micro-SD cards. The business did quite well for awhile, eventually becoming too much of a burden relative to profit made. At its peak, the business had me flashing a mean of 5 cards per day — meaning my girlfriend or I would have to pay attention to my macBook and/or Raspberry Pi for ~4 hours or more, in order to keep the flashing process going.

Photo by Christian Fregnan

At the time, I was using an awesome program, Etcher, to flash the cards. To my surprise, there was not an option to flash an image file (foo.img) to multiple devices. I should quickly note that Etcher would eventually be updated to include this feature, and it works nicely — good job Etcher team. Up to this point, my programming experience had involved programming Arduinos, atTinys, Raspberry Pis, and a little bit of Python and Linux programming. When this problem arose, and I realized that there had to be a better way…I immediately thought of how fun it would be to fix my problem by creating a program that flashes multiple devices at once.

Etcher is an awesome program — kudos to this team.

Considering the language I had the most familiarity with was Arduino’s ‘C-like’ language, and I’m not quite up to learning C or C++ at the moment, I decided to use a language I had not too recently been exposed to — a language that was named after a favorite thing of mine: Python.

Although done in haste, I began the process by writing an action plan and denoting ‘certainly desirable features/methods’.

There would be a graphical user interface (GUI), minimum of 4 devices to be selectable, and be quick and reliable.

The GUI is what I began to research first, with my discovering something called ‘TKinter/tkinter’ — the defacto GUI framework for Python. It was relatively easy to pick up, with my acquiring enough information to get a basic GUI working within an hour.

In fact, a lot of the actual GUI layout and methods involved were not too difficult nor frustrating. The real problem involved complex processes for multi-threading and, even more so, learning about the subprocess module in an attempt to manipulate the command prompt. The manipulating involves invoking the dcfldd command with the necessary following arguments to flash the intended file if= — note that if= is actually an initialism for input file — to multiple devices with the of= parameter, with of= meaning output file.

The subprocess module would prove to be quite confusing at first, and I was apprehensive/cautious in coding methods that manipulated the command prompt. After practicing use of the subprocess module and its methods Popen, call, communicate , and reading several articles on using subprocess (many of the articles were mostly confusing, seemingly just the same article rehashed), I finally figured out a way to invoke the necessary system commands and use their input, output, error pipes in a meaningful way:

Variables for the if=, of=, and /dev/disk{}\n".format(device_name) are set by user input values in the GUI. Once the user has selected a file to be flashed, the devices to flash to, and hits the “Flash” button a text file with the .sh extension is created and opened by the dd_exe_f = open(file location, "w") — with “w” meaning create the text file to write to. This is followed by the for i in range(1): , which is a one-shot loop of the nested command which writes the combo_fmt content: dcfldd if="inputFile" of="outputDevice1" of="outputDevice2" of="ouputDevice3" of="outputDevice4" to the recently created file from above.

A screenshot of a small part of my uSD duplicator program — temporary BASH script creating and executing.

Above is a snippet from my microSD duplicating application that determines which and what variables are to be included in a bash script that will be created and ran once, then discarded — the process invoked in $BASH will continue to run as a threaded process (multi-threading).

When I finally figured out what had to be done in order to invoke dcfldd command in $BASH, and in an asynchronous fashion, I was set to have a working program. The next problems had to do with safely injecting commands to the terminal, and not halting the whole program as it ran the actual flashing process.

To prevent the program from becoming unresponsive upon starting the flashing process via dcfldd cli tool, a second thread is defined and the methods involved invoked upon the “Flash” button being pressed.

Here’s the solution to another problem involved with threading. Once the process is set into to motion asynchronously, there are no safeguards in place to prevent the “Flash” button to be pressed again, invoking the dcfldd command again, interrupting the sensitive process of flashing data to a memory storage device. To prevent this, I included an argument that prevents any other threads to begin, once the “Flash” button has been pressed.

flash function includes stoprequest.set() that stops any additional thread requests, therefore, preventing anything from happening when pressing the flash button during an already occurring flash process

The actual declaration of the stoprequest function is included in another function that deals with listening for usb device, change events before the flashing process begins. This process is also only necessary before the flashing event, and is also required to be asynchronous, which is accomplished by threading — device changes are detected and if the device is present an icon is placed next to the device in the GUI. Once the flashing process has begun, there is no need for this threaded process, so the threading.Event() is defined in the dev_status function block, and invoked upon the press of “Flash” button, resulting in the while loop to return false and exiting the loop.

This whole process of figuring out one problem at a time, to get at a much bigger problem and handle an arduous task that when looked at collectively as one is so daunting that it seems quite impossible — it’s an incredible experience. Such an incredible experience that it significantly influenced my deciding to pursue programming as a career.

Stay tuned for the next post about this project — it will be coming soon. I will go further into figuring out and implementing the bash scripting and executing with Python.

Thanks for reading! すごいです!

--

--