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 :