JavaScript

Alexa Skills Kit SDK 2.0 with 3rd party APIs

At SPR (the company I work at), once a quarter we host a Solution Day – a day we set aside for people from different teams to spend together in the office “learning by doing”.  At a recent Solution Day, I had the pleasure of working with a few of my colleagues on improving an Alexa skill that lets us interact with an IoT device we built at a previous Solution Day.  The IoT device was built using a Particle Photon (https://www.particle.io/products/hardware/photon-wifi/) and provides us telemetric data about our office Kegerator: what’s on tap, how cold the beer is, and how much beer is left. The original version of the skill in question was ported from another installation that only featured a single faucet and was written using Node.js.  Our office kegerator has two faucets.  The resulting user experience was sub-optimal from both a performance and user experience perspective.  The goal of this Solution Day was to make improvements to both.

During the course of implementing these improvements, we upgraded the Alexa Skills Kit SDK to the latest version (^2.0.0 from ^1.0.0). The purpose of the blog post is to outline a specific problem we faced (and solution we came up with) for integrating a Node.js Alexa skill written with Alexa Skills Kit SDK ^2.0.0 (https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs) and an asynchronous 3rd party REST API call. While this applies to any asynchronous function, in this post we’ll cover an example that used the Particle Cloud API (https://docs.particle.io/reference/api/). Like nearly every other post I’ve written, a lot of this isn’t new information – there’s a lot of “standing on the shoulders of giants” in here – I’m hoping the value is in being able to find this information in one place.

A key change in the latest SDK version is how an AWS Lambda invoked as part of a Skill request terminates and reports results.  In Alexa SDK ^1.0.0, returning results involved emitting an event, like the example below:

  self.emit(':tell', 'The keg is ' + tempVal + ' percent full.');
  lambdaContext.done(null, 'Request for beer quantity successful');

Terminating/reporting results in this manner makes integration with 3rd party REST APIs very easy.  These lines can simply be placed in a callback or a promise.  When the API responds and results are returned, an event can be emitted, and the context is told we’re done.  Here is a more complete example:


'HowMuchBeerIsLeft': function () {
  var tempVal = 0, self = this;
    request(consumptionMonitorUrl).then(function (body) {
      body = JSON.parse(body);
      //other logic
      self.emit(':tell', 'The keg is ' + tempVal + ' percent full.');
      lambdaContext.done(null, 'Request for beer quantity successful');
    });
},

The same is not true in Alexa SDK ^2.0.0 – with the new handler model, terminating a skill request and returning results requires actual ‘return’ statements at the end of the function. You can see there’s not a whole lot of documentation either (https://www.npmjs.com/package/ask-sdk), but there are plenty of example projects (https://github.com/alexa). The new handler model looks like the example below, which is the default ErrorHandler from an example project (https://github.com/alexa/skill-sample-nodejs-berry-bash):


const ErrorHandler = {
  canHandle() {
    return true;
  },
  handle(handlerInput, error) {
    return handlerInput.responseBuilder
      .speak('Sorry, I can\'t understand the command. Please say again.')
      .getResponse();
  },
};

This model is more difficult to use with a skill that requires integrating with a third party API because a ‘return’ requires us to essentially force our code to wait for our asynchronous API call to respond before returning.  Using a ‘return’ statement in a callback or promise won’t work – the function will likely end before the ‘return’ statement is executed.  One of probably a dozen solutions to this problem involves async/await syntax, introduced in Javascript ES7.  A good explanation of async/await can be found here: http://nikgrozev.com/2017/10/01/async-await/, though our examples do not use the request-promise (https://github.com/request/request-promise) library as this site does.

Our example solution will show a handler function waiting for a response from another function that returns a Promise.  Our function returns a Promise because again, we’re not using the request-promise library(though we could).  Our example also includes a ‘bodyTemplateMaker’ function (which is included below), because our skill runs on an Echo Spot, which has a screen. The ‘bodyTemplateMaker’ function (and it’s related functions) is a helper function for building a response that has visual components.  This  function is pulled from an example skill on Github (https://github.com/alexa/skill-sample-nodejs-berry-bash). It is largely untouched.

Libraries we used:


const Alexa = require('ask-sdk-core');
const request = require('request');
const AWS = require('aws-sdk');

Handler (for Alexa skill):


const TempHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
      && handlerInput.requestEnvelope.request.intent.name === 'TempIntent';
  },
  async handle(handlerInput) {
    let temperature = await tempLookup();
      return bodyTemplateMaker(
        'BodyTemplate1',
        handlerInput,
        mainImage,
        'How cold is the beer?',
        `Current Temp: ${temperature} F`,
        null,
        null,
        `The beer is being served at ${temperature} degrees Fahrenheit.`,
        null,
        null,
        mainImgBlurBG,
        false
      );
    }
};

 
Async function (for 3rd party API call):


const tempLookup = () => {
  return new Promise(function(resolve, reject) {
    request(servingTempUrl, function(error, response, body){
      body = JSON.parse(body);
      resolve(parseFloat(body.result).toFixed(2));
    });
  });
}

Helper function (bodyTemplateMaker and friends):


function bodyTemplateMaker(pBodyTemplateType, pHandlerInput, pImg, pTitle, pText1, pText2, pText3, pOutputSpeech, pReprompt, pHint, pBackgroundIMG, pEndSession) {
  const response = pHandlerInput.responseBuilder;
  const image = imageMaker("", pImg);
  const richText = richTextMaker(pText1, pText2, pText3);
  const backgroundImage = imageMaker("", pBackgroundIMG);
  const title = pTitle;
    response.addRenderTemplateDirective({
      type: pBodyTemplateType,
      backButton: 'visible',
      image,
      backgroundImage,
      title,
      textContent: richText,
    });
    if (pHint)
      response.addHintDirective(pHint);
    if (pOutputSpeech)
      response.speak(pOutputSpeech);
    if (pReprompt)
      response.reprompt(pReprompt)
    if (pEndSession)
      response.withShouldEndSession(pEndSession);
    return response.getResponse();
}

function imageMaker(pDesc, pSource) {
  const myImage = new Alexa.ImageHelper()
    .withDescription(pDesc)
    .addImageInstance(pSource)
    .getImage();
  return myImage;
}

function richTextMaker(pPrimaryText, pSecondaryText, pTertiaryText) {
  const myTextContent = new Alexa.RichTextContentHelper();
  if (pPrimaryText)
    myTextContent.withPrimaryText(pPrimaryText);
  if (pSecondaryText)
    myTextContent.withSecondaryText(pSecondaryText);
  if (pTertiaryText)
    myTextContent.withTertiaryText(pTertiaryText);
  return myTextContent.getTextContent();
}

Unfortunately, we can’t share the entire codebase for this solution because it contains proprietary and/or private information that we can’t share.  However, one thing we found difficult was navigating various source code repos to cobble our solution together.  We’re hoping this is a succinct, yet complete, solution that others will find helpful.

Enjoy and good luck!

Advertisements

As a reviewer…

One of the other things I spent time on last year was acting as a reviewer for a book that was recently published by Packt Publishing. I was approached by Packt early in the summer to volunteer to help review a work in progress called Enterprise Application Development with Spring and ExtJs. I was skeptical at first, so I did some research. Easily the majority of blog and message board content on the subject of being an unpaid reviewer, especially for Packt for some reason, was negative. This was an obvious red flag. However, I read a fair number of technical books, and I do enjoy writing, so I thought it might be an interesting thing to participate in, especially if I ever wanted to be an author in the future. In the back of my head I knew that if it became too much, especially given that it was volunteer time, that I could simply back out. I agreed to participate and off we went.

Here’s the basic deal: you get a couple of chapters to go through every 4 days. They give you a questionnaire to fill out with your comments. The publisher encourages feedback on many different levels – sentence structure and grammar, chapter-level organization and content, even the order of the chapters and higher level things. All fairly reasonable.

In all, I didn’t have a problem with the process. It was very interesting to see a book as a work in progress. By the time I was involved, it was clear the tools, table of contents and topics covered were fairly well set. Obviously, getting paid would have been nice, but I knew I was volunteering (well, I was getting a free ebook). I also knew the subject matter, which made things much easier. I was able to bypass the learning part of reading the book and focus on the content, how it was organized, and what type of an experience a reader would have with it.

On the book itself – it’s not bad, it’s just presented in a way that would be hard for me, personally, to digest. For a topic like this, I like to start with a clear goal – working through a project to learn a new technology. Additionally, I prefer consuming new information in small pieces and repeating that consumption, reinforcing foundational concepts while slowly increasing complexity, all the while verifying my progress with test cases. Some examples of books written in this fashion that I enjoyed: Agile Web Development with Rails, Grails in Action. This book is presented in a very waterfall-ish way in the name of Enterprise Application Development, and I think this is where I had the hardest time. Developing apps in the Enterprise does not require big up-front design or a waterfall development methodology. The reader is consuming huge new pieces of knowledge in each chapter, and we’re not doing anything to verify them as we go. The book has the reader waiting for a few layers of the application to be developed before performing integration tests. My concern here is that a reader will be trying to troubleshoot something they wrote two chapters ago, and that they just learned within the last few hours. That sounds frustrating!

Side note: I wasn’t a huge fan of the tools used in the book either. I feel like they are complex enough to be a distraction, that there are more modern/simple choices (Ivy, Eclipse, Spring Data) that would have possibly let the reader focus more on learning Spring and ExtJs.

In short, it was a great experience, I’m glad I did it, and I learned a lot, but if I ever do this again, I’ll make sure my own views and development/learning style are in better alignment with the author’s goals for the book.

On resolutions…

2013 came and went, and I definitely did not get around to learning much of what I planned to learn/write about.  I still have the books, and they’re electronic, so they’re not collecting dust, but instead of continuing to dig into new languages and frameworks for the JVM, I spent much of 2013 learning new technology based on client demand.  Not bad things, just unexpected.  I sharpened my javascript skills, and spent a few months in the .NET world. (pro tip – INSTALL ReSharper ON THE FIRST DAY)

This year I’d like to get through that Play/Scala exploration and check out the Reactor (the asynchronous app toolkit by the Spring team).

When will I stop thinking that putting it in writing will be motivation enough to actually do this stuff?

Tips For The ExtJS Beginner

If you haven’t already, learn more about Javascript before you start
I wrote a decent amount of Javascript before I started using ExtJS. I’ve used Prototype, jQuery, & Dojo, but I’ve never written as much Javascript as I have on this project, and I’ve never unit tested any Javascript I’ve written until now. The learning curve for ExtJS is not steep, but first learning the basics of Javascript – best practices, common mistakes, design patterns – will drastically improve the quality of your code. You can write a fully-functioning and beautiful ExtJS app in messy and error-prone Javascript. I recommend Javascript: The Good Parts (http://shop.oreilly.com/product/9780596517748.do) and Javascript Patterns (http://shop.oreilly.com/product/9780596806767.do) for reading. I also use a JSHint plugin in my IDE, and I use Jasmine and Phantom for unit testing. I also recommend rolling the execution of each of these into your project’s CI process.

Read the License Agreement
The license agreement changed a few times early in the life of ExtJS, and can be restrictive depending on how you intend to use the product. The Sencha licensing FAQ site does a good job explaining the specifics. https://www.sencha.com/store/licensing-faq/

Use Sencha CMD
Several tools that are packaged with ExtJS require the app to be organized in a specific way. It is possible to use a custom directory structure for your application, but it can be a maintenance concern in the long term as the framework matures and is upgraded. For instance, in the last two upgrades, 4.0->4.1 & 4.1->4.2, the expected structure of the app changed significantly as new tools and concepts are introduced. The example that comes to mind in the last upgrade was the introduction of packages. Starting your project by creating an app using the Sencha CMD tool, and then using it to upgrade the app (which then is responsible for changing the app’s directory structure, if necessary) can be a major time saver.

Use Refs
Not only do they give you conveniently named accessors for view elements to use in place of lengthy dom queries, but they give you a level of abstraction – limiting references to a potentially changing UI/DOM to one place, and saving the price of continual DOM queries by holding references to DOM elements.

Use the framework to build your UI, don’t build a UI and then try to use the framework
Don’t fight the framework. If you’re working with a UI/UX person, be sure they are at least familiar with ExtJS and have read through the examples. Building interfaces using ExtJS constructs as the building blocks instead of building an interface and forcing the framework behind it can save a lot of time and go far in managing the expectations of users.

Be sure you know which browsers you’re supporting and test in all of them
ExtJS is cross-platform, but like almost anything, there are performance differences and gotchas – mostly in IE8 and IE9 – that you need to watch for. The performance issues are expected, but there are some functional differences as well. The two that come to mind are animation issues and issues detecting native Javascript functionality. Test in all of your supported browsers early and often.

Extend base classes, do not edit them
Occasionally, there will be the need to tweak how base classes function to suit your needs or to make up for default functionality that changed between versions of the framework. To save yourself from upgrade pain in the future, use Ext.override (http://docs.sencha.com/extjs/4.2.1/#!/api/Ext-method-override) and change only what you need to change and only where need it. This will prevent any undesirable behavior in places where the out of the box functionality does suit your needs, and/or where it is used internally by the framework.

Do not be afraid to dig into the source
You will see cryptic error messages, and sometimes they’ll originate from Ext files rather than those of your app, especially if they happen while the app is starting up. Learning how to navigate the source while debugging and also from the API docs is a great help. The source is obviously the truth for what is happening in the framework, but also serves as a great location to find implementation examples that you can use in your app.

Grid performance
In our application, we have only one source of consistent performance issues in ExtJS – data grids. The main thing to keep in mind is the amount of time it takes to render the full width and height of the grid. If you need to load a lot of data in your grid, limit the amount of data that is rendered by using the buffered renderer plugin (http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.grid.plugin.BufferedRenderer). Also, try to limit the number of columns in your grid either by not displaying them at all, or by allowing the user to configure what is displayed. Both of these will help prevent unnecessary rendering of off-screen elements when the grid is rendered and re-rendered (for instance, when the window is resized).

Learn to read the API docs
The ExtJS API is quite rich, and learning how to read the API will help you be productive every day. The docs are presented in a very slick way, and allow you to quickly search for classes, filter elements within a class, view the source from any listing in the API doc, and they include working examples.

Book Report: JavaScript Patterns

Before picking up what I actually had on my list to learn this year, and finding myself writing more JavaScript than ever at my current client, I thought it would be wise to take a deep dive into the language, it’s lesser-known features, and it’s best practices. I knew a fair amount, but I was not prepared for what was contained in JavaScript Patterns by Stoyan Stefanov.

The book started with an overview of general best practice patterns in javascript – things like using a cached length in for loops, single var declarations, equality checks, namespacing, and quickly moved to advanced object creation patterns, functional patterns like memoization and currying, and coverage of most of the Gang of Four patterns. At each step along the way, examples and detailed explanations drove individual points home and provide good future reference.

While all of the information in this book is well-written and valuable, much of it is good in theory but probably wouldn’t see the light of day in most projects (Module pattern, Constructor patterns, Inheritance strategies), unless you are not using an existing framework or are rolling your own. It is very valuable to learn how things operate behind the scenes, and some of these patterns are now recognizable for me even in the ExtJs source, but I’m not sure I’ll have opportunities to use many of them while writing new code. That said, the items that will see the light of day – implementing best practice patterns, some of the GOF patterns, and explaining scope and other common misconceptions developers have with the language are absolutely critical – good for newbies and good refreshers for veterans. I know tools like JSLint encourage you to leverage most of these practices/patterns, but having a deep understanding of why you should leverage them is even better.

This is next-level JavaScript understanding that I previously did not have. I highly recommend this book, and I recommend keeping it handy if you’re writing JavaScript regularly.