Playing with Google Glass at Hack2Wear

Hackathon was fantastic, as usual, too much fun… Wrote a nice Google Glass web app, used it to run our presentation at the end. ;o)

(Code's on GitHub, obviously.)

RFP

  1. My teammate, Hanan, proposed a Google Glass app that'll display notes to "unprofessional" lecturers/presenters, sync'ed with their projected slideshows, to improve their presentations. Notes would be realtime reminders about topics or delivery — always visible in the corner of your eye, a heads up display (HUD), freeing your hands, etc.
  2. The Glass touchpad thingy can also control the presentation — swipe to navigate to next/prev slide, instead of having to use the keyboard, or a handheld controller.
  3. We also hoped to play with other "toys" available at the hackathon, like on the the wristwatches, to measure the lecturer's pulse, or something, but we only had 24 hours…

Google Glass

  1. GDK? Hell no! "Native" development is so effing ridiculous… and in a weekend hackathon, from scratch? Forget it. We built a pure web app in about 100LOC, no $#@! XMLs, no obscure directives, no IDE contortions.
  2. Mirror API? Found some resources:
    1. mirror-api (forked by our hackathon organizer!): 150 files, thousands of lines, Python, Dart, and whatnot. Google App Engine and stuff.
    2. Getting started with the Mirror API using node.js [RecursiveRobot]
    3. glass-mirror-nodejs-auth-demo: Node code to "send a simple 'hello world' timeline card with a delete option". Just 180LOCs, neat.
    Took some time to study it, and, WTF? What where they thinking? This was the first, and possibly last, time I wore a Glass device. I don't have time for this over complicated API.
  3. Glass runs Android, so has a fully functional, modern, WebKit based web browser; why not just use that? Nu, Max Firtman set us on our way!
    1. Developing for Google Glass: Mirror API, HTML5 and how to change your mind: so can develop Glass apps as web services (RESTful CRUD like), "mediated" through Google Cloud stuff. Awkward, but more like an independent SaaS (with push notifications, even) than a proprietary SDK. Nu.
    2. Google Glass Browser, HTML5 and Responsive Web Design in your head: fantastic, just do a standard web app. This is the invaluable advice we followed.

Devlog

  1. After hours of wringing, noise, finally signal: sat down to code, web app, Node.
  2. "Designed", very informally, an MVP: features, architecture.
    1. Glass browser (Only way to open it is to find our app/site thru Google search, so linked to it on my blog (above), and had to click. that. link. every. time. Developer unhappiness. Max did say since XE8 update Glassware has card action that will open a URL in the browser, avoiding search, and we had XE12 devices, but I never got around to it.)
    2. Serve the app from Node, running on WebFaction.
    3. Dashboard: open same app on laptop plugged to overhead projector; embedded a Prezi player that we control with its easy API.
  3. Scaffolding, minimalistic: mkdir, git init, package.json, npm install, README.md, server.coffee, mockup.html — is all there is to it.
  4. (Didn't really run npm install because I had these dependencies global already.) Express.IO, CoffeeScript, Stylus. Maybe CoffeeCup.
  5. Responsive Web Design? Nothing much beyond the standard "viewport" header necessary (without it Glass "emulates" a 960px desktop):
    <meta name="viewport" content="width=device-width,initial-scale=1">
    Black background-color leaves the HUD transparent. Glass browser's defaults worked nicely, very readable. Scrolling with Glass's touchpad was fluky, a nuisance (for first time users), but wouldn't want to inundate the user with long texts anyway; paragraph or two fit in nicely.
  6. Thought I'd serve both Glass and Prezi pages from the same dynamic HTML, but was easier to just split to two static HTML files. I'll later hack glass.html to display differently outside of Glass so demo is usable with a device. Maybe use CSS media queries to avoid user agent detection.
  7. Deploying to WebFaction: so easy to create yet another Node website/domain. Copied files with scp. But have to SSH to edit the start script, to set env.PORT, and to stop;start Node after updates. Wouldn't rsync be nicer? Or git push?!
  8. WebSockets: Express.IO/Socket.IO provided us with the simplest API, and realtime performance. Server mostly just relayed messages between the two browsers. Instantaneously; no perceived latency.
  9. Coding incrementally, "stream of consciousness", I ended up with lots of these in server.coffee:
    app.io.route 'scroll_up',(req)->
    	req.io.broadcast 'scroll_up'
    app.io.route 'play',(req)->
    	req.io.broadcast 'play'
    And sio.emit('scroll_up'); and sio.on('pause',function(){, using no data payload, in the browsers. Silly, because if server isn't involved in the logic, no state changes, can encapsulate all these triggers into one message, and have end points differentiate actions by payload.
  10. Hackthon, so unavoidably some quick & dirty programming. In lieu of a nice UI — WYSIWYG (contenteditable) with rich formatting! — I just used a textarea for the notes, and crude parsing:
    $('textarea').on('change',function(){
    	var a=$(this).val().split(/^(\d+):/m);
    	a.shift(); // Lose the first string — either empty or unnumbered.
    	var d={};
    	for (var i=0;i<a.length;i+=2) d[a[i]]=a[i+1];
    	sio.emit('glazing',d);
    });
  11. At first, allowed HTML markup in notes, inserting them into the DOM with $('#glazing').html(notes[d] || '…');, so we could format our presentation just a little, but I guess it's too risky. We also hardcoded the notes dir="rtl" because presented in Hebrew. Nu, Q&D.
  12. Oh, and the client side "assets" (JavaScript, CSS) were mostly inlined. Horrifying practice, but made it slightly easier to repeatedly reload pages during development. Their CoffeeScript and Stylus versions would be so much cleaner, shorter, beautiful. Eventually.

Prezi

  1. Hanan wanted to use Prezi's player, which was very easy to embed and control:
    p=new PreziPlayer('prezpres',{preziId:$('#pid').val(),width:540,height:360,controls:true});
    p.on(PreziPlayer.EVENT_CURRENT_STEP,function(d){
    	sio.emit('player_step',d.value+1); // Zero based, but UI is one based.
    });
  2. And:
    // Listen to Glass scrolls.
    sio.on('scroll_down',function(){p.flyToNextStep();});
    sio.on('scroll_up',function(){p.flyToPreviousStep();});

Conclusions

  1. Time to market! No way developing "native" apps, or even using Google's weird Glassware APIs, can come close to how quick it is to develop over a pure Web stack. (Not a statistically significant indicator, but other hackathon teams, who tried to use native APIs, didn't make it to the finish line.)
  2. Code's a bit dirty, rushed, but seems I can fit everything — CoffeeScript, HTML, Stylus — in about 100 lines of code. And not one isn't business logic, "domain specific"! Technology should keep out of the way, not obstruct progress. I've come to believe DSLs are the solution.

--
The real world is a special case