Monday, October 26, 2015

How to Use Pebble’s New Dictation API

Earlier this month, Pebble released version 3.6 of their SDK. My eyes widened when I discovered it included access to their Dictation API. This API gives all Pebble developers access to dictation from the Pebble Time microphone. I eagerly opened up the CloudPebble editor and began experimenting!

In this article, we'll explore the Dictation API by putting together a watchapp that accepts a dictated message and sends it to a Slack channel via IFTTT.

What You'll Need

In order to step through this guide, you'll need the following:

[author_more]

The Code

There are developers out there who prefer to jump straight into the code. If you are that type of developer, all the code is available on GitHub.

Our watchapp will have two main files:

  • main.c - Our C code manages the dictation, the display of instructions and display of the entered message.
  • pebble-js-app.js - This manages our communication to IFTTT.

IFTTT

I'd recommend setting up your IFTTT Maker channel and Slack rule first, just so the code set up we'll do after this makes more sense.

I've previously covered IFTTT in the articles Connecting LIFX Light Bulbs to the IoT Using IFTTT and Connecting the IoT and Node.js to IFTTT (this second one covers the Maker channel). So if you'd like a more in depth explanation of using IFTTT and the Maker channel, have a read through of those.

Here's a very quick runthrough of what you'll need to set up:

  • Create an IFTTT account if you haven't already got one.
  • Connect the Maker Channel and Slack Channel to your account.
  • Create a new recipe with the Maker channel as the trigger.
  • Choose the "Receive a web request" trigger option and name the event "slack_message".
  • Choose the Slack channel to be the action channel for this IFTTT rule and choose the "Post to channel" action.
  • Select the Slack channel you'd like the message to go to and set the message to only contain {{Value1}}.
  • You can remove the title, or choose something like "Pebble Message Received". I left it blank. I also left the thumbnail URL blank too.
  • Create your action and you should be ready to go! IFTTT is ready to send any messages it receives from that event to the Slack channel you specified.

Our C Code

The main.c file looks like so:

[code language="c"]
#include <pebble.h>

static Window *s_main_window;
static TextLayer *message_layer;

static DictationSession *s_dictation_session;
static char display_message[512];

static void handle_message(char *slack_message) {
DictionaryIterator *iter;
app_message_outbox_begin(&iter);

dict_write_cstring(iter, 0, slack_message);

app_message_outbox_send();
}

static void dictation_session_callback(DictationSession *session, DictationSessionStatus status, char *transcription, void *context) {
if(status == DictationSessionStatusSuccess) {
snprintf(display_message, sizeof(display_message), "Message sent!\n\n\"%s\"", transcription);
text_layer_set_text(message_layer, display_message);
handle_message(transcription);
} else {
static char error_message[128];
snprintf(error_message, sizeof(error_message), "Error code:\n%d", (int)status);
text_layer_set_text(message_layer, error_message);
}
}

static void select_click_handler(ClickRecognizerRef recognizer, void *context) {
dictation_session_start(s_dictation_session);
}

static void click_config_provider(void *context) {
window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler);
}

static void window_load(Window *window) {
Layer *window_layer = window_get_root_layer(window);
GRect bounds = layer_get_bounds(window_layer);

message_layer = text_layer_create(GRect(bounds.origin.x, (bounds.size.h - 72) / 2, bounds.size.w, bounds.size.h));
text_layer_set_text(message_layer, "Press select and tell me your Slack message :)");
text_layer_set_text_alignment(message_layer, GTextAlignmentCenter);
text_layer_set_font(message_layer, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD));
layer_add_child(window_layer, text_layer_get_layer(message_layer));
}

static void window_unload(Window *window) {
text_layer_destroy(message_layer);
}

static void init() {
s_main_window = window_create();
window_set_click_config_provider(s_main_window, click_config_provider);
window_set_window_handlers(s_main_window, (WindowHandlers) {
.load = window_load,
.unload = window_unload,
});
window_stack_push(s_main_window, true);

app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());

s_dictation_session = dictation_session_create(sizeof(display_message), dictation_session_callback, NULL);
}

static void deinit() {
dictation_session_destroy(s_dictation_session);

window_destroy(s_main_window);
}

int main() {
init();
app_event_loop();
deinit();
}
[/code]

Our Dictation Calls

The first bit of code Pebble developers will notice is new is the line which sets up a DictationSession. This is what we store our transcription data and other data related to the Dictation API within:

[code language="c"]
static DictationSession *s_dictation_session;
[/code]

Next, we define a simple char array to store our latest successfully transcribed message:

[code language="c"]
static char display_message[512];
[/code]

Within our init() function, we set up the actual dictation session so that it is ready and waiting for us to request it. It is set to provide space to store our dictated message that matches the length of display_message. It also sets the callback function once we've performed dictation to be dictation_session_callback().

[code language="c"]
s_dictation_session = dictation_session_create(sizeof(display_message), dictation_session_callback, NULL);
[/code]

Running Dictation on Click

We want to set up our dictation to run when the user clicks the select button on their Pebble. We set click functionality via window_set_click_config_provider().

[code language="c"]
window_set_click_config_provider(s_main_window, click_config_provider);
[/code]

That tells our Pebble that our click functions are defined within click_config_provider(). Within that, we initialize the process of dictation via a press of the select button (defined as BUTTON_ID_SELECT in Pebble's SDK). This button action is set up via window_single_click_subscribe() function.

[code language="c"]
static void click_config_provider(void *context) {
window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler);
}
[/code]

Continue reading %How to Use Pebble’s New Dictation API%


by Patrick Catanzariti via SitePoint

No comments:

Post a Comment