This week's assignment goal is to program a multi-platform GUI. Since I already have programming experience I decided to try to solve with my assignment some general problem that FabLabs could be facing. Namely the fact that machines in the FabLab usually require some dedicated PC or Laptop for each machine, and this could grow a little expensive for smaller ones.
FabModules are great in the fact that they don't really need fancy hardware to run. But they still need a monitor, a keyboard and a mouse, also posing an issue in terms of space. Finally, it would be nice if any user in the lab could operate the machine just opening a browser at a specific URL without the need of additional software.
For this reason I tried this week to build a Web-based GUI (for now only for the Modela milling machine) to wrap the FabModules and allow them to run on the Raspberry PI. This way this cheap board could be put on every machine, connected to the network and even operated using a tablet.
My idea would be to replicate the
make_png_rml GUI into a web-based application, providing the following feature set:
I will call the app Pi.Mill, short for Rasberry Pi Milling interface.
As this is already been done for 3D printers, my app can borrow a lot of code from the existing Octoprint project. In order to allow me to do that, it must use the same web framework (stack), namely Flask running on the Tornado webserver. Tornado provides WebSockets allowing to establish a full-duplex communication bus between the server and the client, eliminating the need to "pull" information every once in a while from the server. Finally the Knockout.js framework included in the client allows to use declarative bindings for dynamically updating the interface when the model on the server is updated.
Octoprint has also two great design paradigms implemented: event based communication, so that processing in different modules can happen asynchronously and features "decoupled", and threading, making it possible to run external programs without interrupting the main loop, making the client unresponsive.
The app will need FabModules installed on the Raspberry PI. My choice is to keep the FabModules distribution as-is, so it could also be used natively and updated with newer versions.
Several programs in the FabModules distribution will be invoked by the Python server a separate processes running in their own threads, as currently done in the FabServer app.
For obtaining the path preview it will be enough to invoke the
path_png program. Previewing the actual RML would require implementing the drawing using Canvas element, but the Python implementation of
rml_send_gui could provide a good guidance. This feature will probably come at a later time. In the meanwhile a cleaver workaround could be to convert the generated RML to g-code, using the
The app will have a single page interface, as is usually done with web-based app it's better to dynamically update the browser DOM tree rather then navigating (and initializing) many different pages.
This also means that the application will hold some kind of state on the client, and interact with the Python server via an API, calling several methods to load information dynamically and to perform the various tasks.
The following screenshots / mockups illustrate the different features:
The main screen allows to upload the PNG image and generate a path out of it, the sidebar allows to choose the serial port, preset and other settings
This second screen allows to generate the rml, move the milling head
Pi.Mill will provide the following API, expressed using the HTTP Verbs notation:
This method allows to load the settings stored into the system, plus those read at runtime such as available serial ports. Data to be provided in the form of JSON files.
This method allows to update some settings, including the Serial port used. Settings are specified as key value pairs. Comments in the code define supported settings.
This method allows to upload a new PNG image
This method allows to resize the current PNG image, taking width and height params.
This method allows to invert the current PNG image
This method allows to generate a path for the image. The preset param is one of the labels defined in
config/preset.json and represents the settings used for path generation
This method returns a png image of current generated path, for preview purposes
This method allows to generate an rml file from the current path, using the settings specified by the speed and zjog params.
This method allows to move the head of the mill at the point specified by the x and y parameters.
Using the Raspbian distribution makes this quite easy, as it provides almost all packages available in Debian Stable. Just make sure to have enough space on your memory card, Boost alone takes 100Mb!
You will need to install the packages:
sudo apt-get install build-essential python python-dev \ libgif-dev libpng12-dev libboost-dev libboost-thread-dev bc imagemagick
Then build as usual (make fab), it will take a long time, but will work.
During implementation, which is slowly proceeding, a main problem arose. It turned out that the
path_png doesn't produce an image suitable for preview, and also the gcodeviewer code must be changed a bit to support the gcode produced by the FabModules. This will slow a bit the developement.
I will continue to develop the application before the end of the FabAcademy and hopefully release it soon.
The development has progressed. I completed the following features:
I found a solution for the preview issue, turning the .path file into an EPS file and then generating a preview using Imagemagick convert.
The milling process is handled via a modified version of rml_send_gui, where I added some callbacks to report progress during milling using the SockJS protocol. This is more scalable solution for browser-based sockets, that uses WebSockets when available, providing an alternative implementation for lesser compatible browsers.
I also dropped Knockout.js and Flask favouring a lighter solution, using the Bottle microframework and plain JQuery for client side scripting.
Basically the application is now functional, even if it needs some polishing, as shown in the demo below running on the Raspberry PI.
I'm attaching here a snapshot of the development as of June 10 2014 for archive purposes.
You can find the most updated version, and install instructions in my github repository
All software is MIT licensed, except parts derived from the FabModules which require licensing for commercial usage.