Computing stuff tied to the physical world

Remote compilation

In Software on Jan 30, 2013 at 00:01

Now we’re cookin’ …

I’ve implemented the following with a new “compile” module in HouseMon – based on, which is also available for the Raspberry Pi via Debian apt:

JC's Grid, page 62

In other words, this allows uploading the source code of an Arduino sketch through a web browser, manage these uploaded files from the browser, and compile + upload the sketch to a server-side JeeNode / Arduino. All interaction is browser based…

Only proof of concept, but it opens up some fascinating options. Here’s an example of use:

Screen Shot 2013-01-29 at 21.54.13

(note that both avr-gcc + avrdude output and the exit status show up in the browser!)

The processing flow is fairly complex, given the number of different tasks involved, yet the way Node’s asynchronous system calls, SocketStream’s client-server connectivity, and Angular’s two-way webpage bindings work together is absolutely mind-blowing, IMO.

Here’s the main code, running on the server as briqs/ =
  name: 'jcw-compile'
  description: 'Compile for embedded systems'
  menus: [
    title: 'Compile'
    controller: 'CompileCtrl'

state = require '../server/state'
fs = require 'fs'
child_process = require 'child_process'
ss = require 'socketstream'

# TODO hardcoded paths for now
SKETCHDIR = switch process.platform
  when 'darwin' then '/Users/jcw/Tools/sketch'
  when 'linux' then '/home/pi/sketchbook/sketch'

# callable from client as: rpc.exec 'host.api', 'compile', path
ss.api.add 'compile', (path, cb) ->
  # TODO totally unsafe, will accept any path as input file
  wr = fs.createWriteStream "#{SKETCHDIR}/sketch.ino"
  fs.createReadStream(path).pipe wr
  wr.on 'close', ->
    make = child_process.spawn 'make', ['upload'], cwd: SKETCHDIR
    make.stdout.on 'data', (data) ->
      ss.api.publish.all 'ss-output', 'stdout', "#{data}"
    make.stderr.on 'data', (data) ->
      ss.api.publish.all 'ss-output', 'stderr', "#{data}"
    make.on 'exit', (code) ->
      cb? null, code

# triggered when bodyParser middleware finishes processing a file upload
state.on 'upload', (url, files) ->
  for file, info of files 'uploads',
      key: info.path
      file: file
      size: info.size
      date: Date.parse(info.lastModifiedDate)

# triggered when the uploads collection changes, used to clean up files
state.on 'store.uploads', (obj, oldObj) ->
  unless obj.key # only act on deletions
    fs.unlink oldObj.key

The client-side code needed to implement all this is even shorter: see the controller code and the page definition on GitHub.

There’s no error handling in here yet, so evidently this code is not ready for prime time.

PS – Verified to also work on the Raspberry Pi – yippie!

  1. I just stumbled on something similar:

    • Thx, but note that this is in the cloud, whereas the post is about running on a local machine / RPi.

  2. Perhaps you have seen ? Its great for editing those simple sketches. Easy to embed into your node app frontend.

  3. Totally unrelated question: I like your hand drawn diagrams, the pen strokes seems soft and a joy to write with. Which pens do you use?

    • Heh – an iPad with the Bamboo Paper app and this (mostly because it has a fine tip). The fact that I can zoom in and undo has won me over…

  4. Your enormous productivity and enthusiasm is unbelievable! Helps to keep me connected to this stuff, although I’m not actively participating (for now).

  5. Having a full-featured linux box attached to the AVR opens up all sorts of options. I like doing all my development in Visual Studio because sometimes my projects can be quite large. I’ve used a a web browser to upload code and flash an attached AVR over SPI, but even easier is using SSH to just execute avrdude remotely: plink bmayland@rpi avrdude -p m328p -c arduino -P /dev/ttyUSB1 -V -D -Uflash:w:-:i < “%1″

    I never thought to have it compile on the Pi, that’s sweet for small sketches!

Comments are closed.