I developed a client for the PEBBLE Watch, that simply send the keystrokes:
- RIGHT
- LEFT
- ESCAPE
To create the PEBBLE app, I used the WinFormebble C library, that make developing for the Watch more friendly to C# and WinForm developer.
The all source code is part of the library WinFormebble on github.
Here is the C part of the app
/*
* A Pebble Watchface that control a PowerPoint presentation
* using the winRemoteControl api
* Demo for Code Camp 22, MA, USA
* (C) Torres Frederic 2014
* Licence: MIT
*/
#include <pebble.h>
#include <pebble_fonts.h>
#include "WinFormebble.h"
// Api data returned from JavaScript World to C world
// Dictionary properties used in communication with Pebble iOS App
// Metadata defined in project settings
#define KEY_REQUEST_ID 0
#define KEY_REQUEST_ID_NEXT 0
#define KEY_REQUEST_ID_PREVIOUS 1
#define KEY_REQUEST_ID_QUIT 2
#define KEY_REQUEST_ID_OK = 3;
// Data Refresh Rate
#define DEFAULT_STRING_BUFFER_SIZE 16
// Strings and messages
#define WATCH_DIGIT_BUFFER "00:00"
#define WATCH_MAX_WIDTH 144
Form mainForm;
Label lblTime;
Label lblAction;
Label lblPage;
int _pageCounter = 1;
private void butSelect_Click(ClickRecognizerRef recognizer, void *context) {
Label_SetText(lblAction, "Quit");
jsCom_SendIntMessage(KEY_REQUEST_ID, KEY_REQUEST_ID_QUIT);
}
private void butUp_Click(ClickRecognizerRef recognizer, void *context) {
Label_SetText(lblAction, "Previous");
jsCom_SendIntMessage(KEY_REQUEST_ID, KEY_REQUEST_ID_PREVIOUS);
_pageCounter--;
if(_pageCounter == 0)
_pageCounter = 1;
}
private void butDown_Click(ClickRecognizerRef recognizer, void *context) {
Label_SetText(lblAction, "Next");
jsCom_SendIntMessage(KEY_REQUEST_ID, KEY_REQUEST_ID_NEXT);
_pageCounter++;
}
private void mainForm_Load(Window *window) {
int y = 15;
lblTime = Label_New(GRect(0, y, WATCH_MAX_WIDTH, 50), WhiteBackground, GTextAlignmentCenter, FONT_KEY_BITHAM_30_BLACK);
Label_SetText(lblTime, WATCH_DIGIT_BUFFER);
Form_AddLabel(mainForm, lblTime);
y += 45;
lblAction = Label_New(GRect(0, y, WATCH_MAX_WIDTH, 50), WhiteBackground, GTextAlignmentCenter, FONT_KEY_BITHAM_30_BLACK);
Label_SetText(lblAction, "None");
Form_AddLabel(mainForm, lblAction);
y += 45;
lblPage = Label_New(GRect(0, y, WATCH_MAX_WIDTH, 50), WhiteBackground, GTextAlignmentCenter, FONT_KEY_BITHAM_30_BLACK);
Label_SetText(lblPage, "Page: 1");
Form_AddLabel(mainForm, lblPage);
Form_RegisterButtonHandlers(mainForm, butSelect_Click, butUp_Click, butDown_Click);
}
private void mainForm_Unload(Window *window) {
}
private void mainForm_UpdateTime() {
struct tm *tick_time = DateTime_Now();
static char timeBuffer [DEFAULT_STRING_BUFFER_SIZE];
Label_SetText(lblTime, StringFormatTime(tick_time, "%T", timeBuffer));
}
private void mainForm_Timer(struct tm *tick_time, TimeUnits units_changed) {
mainForm_UpdateTime();
}
private void mainForm_InboxReceivedCallback(DictionaryIterator *iterator, void *context) {
static char pageCounterBuffer [DEFAULT_STRING_BUFFER_SIZE];
Tuple * t = dict_read_first(iterator);
while(t != NULL) {
switch(t->key) {
case KEY_REQUEST_ID :
Label_SetText(lblPage, StringFormatInt(_pageCounter, "Page: %d", pageCounterBuffer));
break;
default : APP_LOG(APP_LOG_LEVEL_ERROR, "Key %d not recognized!", (int)t->key); break;
}
t = dict_read_next(iterator);
}
}
int main(void) {
mainForm = Form_New();
Form_Initialize(mainForm, mainForm_Load, mainForm_Unload);
Form_Show(mainForm);
mainForm_UpdateTime();
jsCom_Initialize(mainForm_InboxReceivedCallback);
Form_RegisterWatchFaceTimer(SECOND_UNIT, mainForm_Timer);
app_event_loop();
Form_Destructor(mainForm); // Also clean all associated controls
}
Here is the JavaScript part of the app
/*
* A Pebble Watchface that control a PowerPoint presentation
* using the winRemoteControl api
* Demo for Code Camp 22, MA, USA
* (C) Torres Frederic 2014
* Licence: MIT
*/
var COMPUTER_IP = "137.116.241.239";
var KEY_REQUEST_ID_NEXT = 0;
var KEY_REQUEST_ID_PREVIOUS = 1;
var KEY_REQUEST_ID_QUIT = 2;
var KEY_REQUEST_ID_OK = 3;
var URL = 'http://[IP]:1964/WinRemoteControl?json=';
var URL_JSON_PARAM = '{"Action":2,"Keys":"{[KEY]}"}';
function sendCommand(key) {
var param, keyValue;
switch(key) {
case KEY_REQUEST_ID_NEXT : keyValue = "RIGHT"; break;
case KEY_REQUEST_ID_PREVIOUS : keyValue = "LEFT"; break;
case KEY_REQUEST_ID_QUIT : keyValue = "ESCAPE"; break;
default: return;
}
param = URL_JSON_PARAM.replace("[KEY]", keyValue);
var url = URL.replace('[IP]', COMPUTER_IP);
Trace(url + param);
url += encodeURIComponent(param);
httpGet(url,
function(responseText) {
var dictionary = { KEY_REQUEST_ID : KEY_REQUEST_ID_OK };
sendMessageToWatch(dictionary, "sendCommand");
}
);
}
function Init() {
Pebble.addEventListener('ready', // Listen for when the watchface is opened
function(e) {
Trace("App started, connected:{0}, Browser Agent:{1}".format(e.ready, navigator.userAgent));
}
);
Pebble.addEventListener('appmessage', // Listen for when an AppMessage is received
function(e) {
Trace("Requested From App:"+JSON.stringify(e.payload));
sendCommand(e.payload.KEY_REQUEST_ID);
}
);
}
Init();
