2016/04/23

Partial Intents and Conversational Tone

As I read through the Alexa UX testing guidelines prior to submitting my new skill for certification, I realized I had not handled partial intents.  The challenge I had was that two different intents each specified a numeric slot type and, based on the state of the skill, the user might have said either prior to saying a number.

The First Attempt

After some playing around, I settled on three core intents:

FooIntent foo {MyNumber}
BarIntent bar {MyNumber}
NumberIntent {MyNumber}

This allowed me to catch the user filling in the numeric slot while saying foo or bar.  It also allowed me to ask the user to provide a number if they did not when saying foo or bar.  I thought this was fairly solid and updated the intent implementations to handle the user leaving out a number:

exports.handleFooAction = function(intent, session) {
    var myNumber = parseMyNumber(intent);

    if (typeof myNumber === 'undefined') {
        setPriorAction(session, 'FOO');
        return { 'view': 'Error_FooToUnspecifiedNumberView', 'data': data };
    }
    ...

}

I added code for the new intent:

exports.handleNumberAction = function(intent, session) {
    var priorAction = getPriorAction(session);
    if (priorAction === 'FOO') {
        clearPriorAction(session);
        return exports.handleFooAction(intent, session);
    } else if (priorAction === 'BAR') {
        clearPriorAction(session);
        return exports.handleBarAction(intent, session);
    } else {
        return { 'view': 'OK_HelpView', 'data': data};
    }
}

In the case of no prior action, the code sends help text to the user, so they can understand how to use the application (we'll come back to this shortly).  After running through a number of tests, I was confident that it behaved as expected and submitted the skill for certification.

Getting Feedback

I did not pass certification ("Alexa, Sad Trombone") due to the NumberIntent triggering the help text when invoked directly.

I'll admit, my first thought was, "Well, yes, if the user does not understand how to give the skill commands, it tries to give them help."

My second thought was, "Forcing the user to say things in an arbitrary order is not good UX, I should fix this."

Back to the Drawing Board

I reworked the code so that, if there is no possibility the user meant bar, the skill assumes the user meant foo.  Otherwise, the user is asked if they would like foo or bar:

exports.handleNumberAction = function(intent, session) {
    ...
    } else {
        if (!isBarAllowed(session)) {
            return exports.handleFooAction(intent, session);
        } else {
            var myNumber = parseMyNumber(intent);
            ...
            setPriorNumber(session, myNumber);
            return { 'view': 'Error_FooOrBarRequired', 'data': data };
        }
    }
}

Both the foo and bar action handlers were updated to account for prior numbers having been provided:

// Check if a prior number was given.
var myNumber = getPriorNumber(session);
if (typeof myNumber !== 'undefined') {
    clearPriorNumber(session);
} else {
    myNumber = parseMyNumber(intent);
}

After some play testing and debugging, the skill appears stable and the interactions feel more natural for having made this change.

Conclusion

I think I'm ready for my next attempt at passing certification.  The lesson I took away is that there is no substitute for user testing when building user experiences.

2015/02/16

OctoGlow - a PiGlow plugin for OctoPrint

Originally I worked out how to use a PiGlow to display OctoPrint progress.  Based on OctoPrint's suggestion I took a look at the tutorial on writing a plugin and revisited the code.  If you are interested in writing a plugin, I definitely recommend checking out the tutorial; I was able to have the hello world example up and running in no time.

A big advantage of running as a plugin is that I can spawn a thread to update the LEDs independently of the event callbacks.  This enables me to enhance the display of status and progress by animating the LEDs.  I put together a short video demonstrating how this looks:



I am still testing the code and working out if I want to handle additional status changes.  However, you can check out the source code on GitHub and install the plugin if you are interested in using a PiGlow with OctoPrint.

2015/02/02

How To Display OctoPrint Progress on a PiGlow

I've been using OctoPrint/OctoPi and a Raspberry Pi to drive my PrintrBot 1405 and it's been working well.  There are times when being able to glance over and see the progress of the print without using a web browser would be nice, so I added a Pimoroni PiGlow.

PrintrBot with PiGlow

2012/03/20

Adafruit IoT Printer Box Drawing Cheatsheet

I realized I wanted a cheat sheet for working with box drawing on Adafruit's Internet of Things Printer while I was playing around with making the Pachube data feed look swanky. This is my attempt to capture the character codes for the various types of possible boxes. This was gathered from a combination of the printer's test printout, Anders's work on this forum thread, and the Unicode section of Wikipedia's entry on box drawing. If you can think of additional characters or a different breakdown in the information that would make the cheat sheet more useful, please feel free to leave feedback in the comments section

Single Lines
UnicodeCharUnicodeDescription
┌0xDAU+250CTop Left Corner
┐0xBFU+2510Top Right Corner
└0xC0U+2514Bottom Left Corner
┘0xD9U+2518Bottom Right Corner
├0xC3U+251CRight Facing Tee
┤0xB4U+2524Left Facing Tee
┬0xC2U+252CBottom Facing Tee
┴0xC1U+2534Top Facing Tee
┼0xC5U+253CPlus
━0xC4U+2501Horizontal Line
│0xB3U+2502Vertical Line

Double Lines
UnicodeCharUnicodeDescription
╔0xC9U+2554Top Left Corner
╗0xBBU+2557Top Right Corner
╚0xC8U+255ABottom Left Corner
╝0xBCU+255DBottom Right Corner
╠0xCCU+2560Right Facing Tee
╣0xB9U+2563Left Facing Tee
╦0xCBU+2566Bottom Facing Tee
╩0xCAU+2569Top Facing Tee
╬0xCEU+256CPlus
═0xCDU+2550Horizontal Line
║0xBAU+2551Vertical Line

Double Vertical / Single Horizontal Lines
UnicodeCharUnicodeDescription
╓0xD6U+2553Top Left Corner
╖0xB7U+2556Top Right Corner
╙0xD3U+2559Bottom Left Corner
╜0xBDU+255CBottom Right Corner
╟0xC7U+255FRight Facing Tee
╢0xB6U+2562Left Facing Tee
╥0xD2U+2565Bottom Facing Tee
╨0xD0U+2568Top Facing Tee
╫0xD7U+256BPlus

Single Vertical / Double Horizontal Lines
UnicodeCharUnicodeDescription
╒0xD5U+2552Top Left Corner
╕0xB8U+2555Top Right Corner
╘0xD4U+2558Bottom Left Corner
╛0xBEU+255BBottom Right Corner
╞0xC6U+255ERight Facing Tee
╡0xB5U+2561Left Facing Tee
╤0xD1U+2564Bottom Facing Tee
╧0xCFU+2567Top Facing Tee
╪0xD8U+256APlus

Here's some sample code that prints out each style of box line:
And the resulting printout:

2012/03/14

PWM Backlight Workaround for LCD Backpack

I really like the Adafruit LCD Backpack, but I've been wanting to play around with adjusting the LCD backlight brightness programatically.  After much mulling and reading of forum posts, I decided to just operate the backlight using one extra wire to a PWM pin on the Arduino.  To try and keep things tidy, I ordered some extra 3-pin terminal blocks so I could make a 6-pin block instead of the normal 5-pin block.  Just to up the stakes, I'm doing this with my brand new 20x4 LCD.
All the Bits and Pieces

First up, I broke off 15 header pins instead of 16 and soldered them into openings 1-15, leaving opening 16 empty; this is labeled "K" on my LCD.  According to the tutorial at Adafruit, this is the backlight ground connection.  I then cut a length of wire, stripped one end and soldered it through opening 16.
Backpack with Pins and Wire Soldered

I "folded" over the wire end and soldered it to the pad on the LCD.  This required a little bit of finagling with my third hand's alligator clips, but wasn't too rough.
Backlight Ground Wire Soldered to LCD

I swapped two 3-pin terminal blocks for the 2-pin and 3-pin terminal block that came with the LCD backpack
Terminal Blocks

I soldered the resulting 6-pin terminal block to the backpack with the extra pin overhanging the PCB on the side.
Terminal Block Soldered in Place

Next up was trimming the wire to fit the length of the backpack PCB and soldering it to the extra pin.  This proved to be a bit of a pain, and I ended up with the LCD in a panavise, the backpack held by the third hands, a soldering iron in one hand, and needlenose pliers in the other.  I'm sure there's an easier approach...
Backlight Ground Wire Soldered to Backpack
Finally, I soldered the regular pins in place; overall, I'm happy with the way this turned out.  I am thinking of putting some insulation on the exposed extra pin / wire end.
Finished Backpack in Place
The code I used to test this is just the Arduino Basics/Fade example sketch and Adafruit's LiquidCrystal/HelloWorld_i2c example sketch mashed together:

2012/03/11

Turning Off the LCD at Night

I like the brightness level of the LCD I'm using on my vivarium project; but, it was giving the living room a distinct glow at night.  It turned out to be a quick fix to turn the LCD off when the ambient light level was low.  I ordered a Photocell from Adafruit and followed the tutorial on wiring it up along with a pull-down resistor (the concept of pull-down and pull-up resistors is something I'm just finally getting my head around).
Photocell and 10K Pulldown Resistor on Pin A3

Then I added a simple check in the loop to test the brightness level:
For my environment, simply splitting the range in half has worked well.

2012/03/08

Pachube on Adafruit's IoT Printer

I've been meaning to check out pachube for a while now and it seemed like fiddling with Adafruit's Internet of Things Printer was a perfect chance.  The JSON parsing code from the Gutenbird sketch lent itself nicely to tweaking for the pachube datastream JSON feed.  Pachube was also very easy to get up and running with between the developer documentation, easy API key generation, and each feed page having buttons to see the various formats (XML, CSV,  JSON).  The end result is that I can get a print out of air quality data for Boston:
(https://pachube.com/feeds/23716 - "Air Quality Index and pollutant data for Boston, Massachusetts webscraped from http://www.airnow.gov/. AIRNow observational data are not fully verified or validated; these data are subject to change and should be considered preliminary. If observational data are used for analyses, displayed on web pages, or used for other programs or products, the analysis results, displays, or products must indicate that these data are preliminary.")

It's still definitely a work in progress - I'd like to format the dates a bit and there seems to be an intermittent bug with the fetch/parse process.  Nonetheless, I've put the code up on github for anyone interested in playing around with it.  There are a couple section of code that I think are a bit interesting.

Adding the pachube API key is as simple as setting one additional header in the HTTP request.
The pachube feed does contain a last updated field for the feed; unfortunately, it is the last field in the feed.  I wanted to stick with (for lack of a better term) the SAX style parsing of the JSON that the original Gutenbird sketch uses rather than do a DOM style load of the data.  Each entry does have a timestamp, but I was looking for something that would tell me when the feed as a whole had been updated.

I ended up looking at the HTTP response header for Last-Modified (I'm considering whether to refactor the code to just store a hash of the value since I'm only using it to decided whether to print the feed or not).  If the value has changed, I save it and return true to indicate the feed should be printed.
Looking through the pachube API feed, the structuring of the interesting data is close enough to the twitter feed that reusing the Gutenbird parsing code made a lot of sense to me.  As an aside, Jenkins build feeds seem to follow this same "object which contains a single array of interesting shallow objects" (JSON-SAISO anyone? no?):
It took me a couple reads to understand the original code from Gutenbird; but, once I grokked it, I think it's a really elegant approach.  It's looking in the JSON for a given name, which will have an array as the value.  When in each object, it looks for specific names and saves the values. Finally, at the end of each object, it handles the data for that object.

I tweaked it as below for the name/value pairs I'm interested in (and I'm using a callback function for printing).  Again, very few modifications were needed to switch from parsing twitter to parsing pachube.
I'm curious to see what data feeds other IoT owners will find interesting.  I'm guessing that as time passes, there'll be more and more sketches available to track different data.

[Updated]
Welcome Adafruit and Flickr readers - here's a little bonus content :)

The same feed as above, but with swanky outlining:

And the relevant code changes to printEntryToPrinter :


And setup :