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();