Plumbee engineering

Meet Jessica Karotz

| Comments

Karotz - or as it used to be known Nabaztag - are small electronic devices that you can control programmatically. They contain a camera, speaker, microphone, a collection of LED lights, two rotatable ears, an RFID reader, and a WIFI antenna.

Plumbee’s Karotz is called Jessica. We use Jessica for build state notification: Jessica performs a different action after a success or failure of a build in our continuous integration server, Jenkins. There is a plugin available for Jenkins that sends build state notifications to Karotz, but we cannot use this since we run Jenkins as part of the Cloudbees service, rather than managing it ourselves.

There are two general ways of getting your Karotz to carry out an action:

  1. Write a Javascript program, upload it to the Karotz website, and then install it onto your device.
  2. Switch your Karotz into “interactive mode” and send signed instructions to Karotz’ web API, which forwards the commands to your device. To enable this, you again need to upload a small xml file to the Karotz website and then install that onto your device.

As I am no JavaScript programmer, leafing through the documentation for programming Karotz in JavaScript made it look increasingly hard to build something that could continuously check the Jenkins API. Instead, I decided to use the second method, and ended up with a generic BASH script. 

How to control Karotz in shell / BASH

Following the online tutorial for creating an interaction http://dev.karotz.com/dev/register_app.html, start by registering an app with a very plain descriptor.xml giving access to the parts you want to use:

<descriptor>  
<version>0.0.2</version>  
<accesses>  
  <access>led</access>  
  <access>ears</access>  
  <access>tts</access>  
  <access>button</access>  
  <access>webcam</access>  
  <access>asr</access>  
  <access>http</access>  
  <access>multimedia</access>  
</accesses>  
<editor>Simon Loader</editor>  
<asrName>Plumbee State</asrName>  
<deployment>external</deployment>  
<multiConf>false</multiConf>  
<parameters>  
  <parameter key="showInstallUuid" value="true"/>
</parameters\>  
</descriptor>  

Registering this app on the Karotz website returns an API key and secret key, which are used together with the ‘InstallID’ returned when the app is installed onto the device.  Essentially this descriptor.xml tells the Karotz website we wish to access all features, that this is an external app (Interactive mode), and that the InstallID that we require should be displayed on the install page.

To work in interactive mode, you first have to tell your Karotz that you wish to send commands to the application you have loaded. This is done with the “start” command:

curl http://api.karotz.com/api/karotz/start?apikey=<API_KEY>&installid=<INSTALLID>&once=<RANDOM>&timestamp=<TIMESTAMP>&signature=<SIG>

Note that the start command requires a SHA1 signature with the private key. Fortunately we had done S3 signatures in shell previously (maybe to come in a future post), so we already had some code we could repurpose. The signature required can be generated by:

echo -n apikey=API_KEY&installid=INSTALL_ID&once=RANDOM_NUM&timestamp=`date +%s` | openssl dgst -sha1 -hmac $SECRET_KEY -binary | openssl enc-base64

Note: The result of this line needs URL-escaping before using it in the command above.

The start command returns some XML containing an interactiveId, similar to this:

<VoosMsg>
  <id>SOME UUID</id>
  <recipient>SOME ID</recipient>
  <interactiveMode>
    <action>START</action>
    <interactiveId>1b721fae-85cb-4599-beec-eae0151731c0</interactiveId>
    <configId>CONFIG UUID</configId>
    <access>asr</access><access>button</access><access>ears</access>
    <access>http</access><access>led</access>
    <access>multimedia</access><access>tts</access>
    <access>webcam</access>
  </interactiveMode>
</VoosMsg>

Using the interactiveId it is now possible to send instructions like this:

curl http://api.karotz.com/api/karotz/led?action=light&color=FF0000&interactiveid=1b721fae-85cb-4599-beec-eae0151731c0

This will set the front LED to colour #FF0000 (red) or to rotate the ears:

curl http://api.karotz.com/api/karotz/ears?left=-1000&right=5000&relative=true&interactiveid=1b721fae-85cb-4599-beec-eae0151731c

And don’t forget to send a stop when everything is finished, or you will need to manually reset your Karotz to gain another interactiveId.

curl http://api.karotz.com/api/karotz/interactivemode?action=stop&interactiveid=1b721fae-85cb-4599-beec-eae0151731c0

The script

You can find the script we use to control Jessica on our github page.

https://github.com/plumbee/karotz-shell

Example of script usage:

karotz.sh -s led 'action=light&color=FF0000'    \# turn the led color to FF0000

We use this small shell script at the end of each successful and unsuccessful build in Jenkins. I have a small instruction file which plays an MP3, changes the LED colour and rotates the ears around. This file is used by the shell script in a Jenkins shell job as a list of commands to send to Jessica:

karotz.sh -s -c workingbuild.script

Oddities and future work

Here are some oddities we’ve found along the way:

  1. Occasionally the interactiveId cannot be retrieved, usually because the last running process on the device did not stop (e.g. if it did not get the stop instruction). In this case, reset your Karotz, or wait and it will kill the process.
  2. The LED colour only stays set for the length of time that the app is running on your Karotz. In order to keep the colour constant, your only options are to not send a stop - which blocks every other process - or to write a Javascript app.
  3. Although the documentation is quite good, some things are not obvious, or are missing altogether. For instance, the instructions to make the ears spin were discovered somewhere else: ears(left=-1000,right=5000,relative=true)
  4. I have no idea how to use the “choreography” action.

What we’d like to do in the future:

  1. Remove some nasty Perl one-liners from the script
  2. Switch to a Javascript version instead. This would remove the need to run a process on a machine somewhere (e.g. a Jenkins job). The idea would be to have something that polls Jenkins for updates and then speaks or otherwise notifies what is going on at each stage. (Note: I have since found example Javascript code which polls jenkins for notification of current build states).

- Simon Loader

Comments