Addison FattorCharlie Summers
Published © GPL3+

Pebble to Edison

Use the Pebble to control executable files on the Intel Edison.

IntermediateWork in progress1,075
Pebble to Edison

Things used in this project

Hardware components

Pebble Watch
Pebble Watch
×1
LED (generic)
LED (generic)
×3
Breadboard (generic)
Breadboard (generic)
×1
Jumper wires (generic)
Jumper wires (generic)
×7

Story

Read more

Code

Pebble App main.c

C/C++
This is the main C code for the Pebble app that controls the parts hooked up to the Intel Edison
/*
 * App uses 2 windows:
 *   main window with the menu
 *   option window with the title and the modes
 */
#include <pebble.h>

#define NUM_ROWS 3
#define NUM_MODES 2

typedef struct {
 char *title;
 char *subtitle;
} ROW;

// Options to choose from menu.
static ROW options[] = {
 { .title = "LED 1", .subtitle = "Change led 1" },
 { .title = "LED 2", .subtitle = "Change led 2" },
 { .title = "LED 3", .subtitle = "Change led 3" }
};

// Modes that LED's can be in.
static char *s_textlayer_modes[] = {
  "off",
  "on"
};

// Remembers modes of LED's when you change rows
static int s_current_modes[] = {
  0,0,0
};

static Window *s_main_window, *s_option_window;
static MenuLayer *s_menu_layer;
static TextLayer *s_text_layer;
static TextLayer *s_title, *s_mode;

// Store the index of the current row.
static int s_current_option;

static void inbox_received_callback(DictionaryIterator *iterator, void *context) {
  APP_LOG(APP_LOG_LEVEL_INFO, "Inbox Received!");
}

static void inbox_dropped_callback(AppMessageResult reason, void* context) {
  APP_LOG(APP_LOG_LEVEL_ERROR, "Message dropped!");
}

static void outbox_failed_callback(DictionaryIterator *iterator, AppMessageResult reason, void *context) {
  APP_LOG(APP_LOG_LEVEL_ERROR, "Outbox send failed!");
}

static void outbox_sent_callback(DictionaryIterator *iterator, void *context) {
  APP_LOG(APP_LOG_LEVEL_INFO, "Outbox send success!");
}

// Get number of rows
static uint16_t get_num_rows(struct MenuLayer* menu_layer, uint16_t section_index, void *callback_context) {
  return NUM_ROWS;
}

// Draw rows of menu.
static void draw_row(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *callback_context) {
  ROW *row_array = (ROW*) callback_context;
  ROW *this_row = &row_array[cell_index->row];

  menu_cell_basic_draw(ctx, cell_layer, this_row->title, this_row->subtitle, NULL);
}

// What to do when a row is clicked
static void select_click(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) {
  s_current_option = cell_index->row;

  window_stack_push(s_option_window, true);
}

// Load main menu.
static void main_window_load(Window *window) {
  Layer *window_layer = window_get_root_layer(window);

  s_menu_layer = menu_layer_create(layer_get_bounds(window_layer));
  menu_layer_set_callbacks(s_menu_layer, options, (MenuLayerCallbacks) {
    .get_num_rows = get_num_rows,
    .draw_row = draw_row,
    .select_click = select_click
  });
  menu_layer_set_click_config_onto_window(s_menu_layer, window);

  layer_add_child(window_layer, menu_layer_get_layer(s_menu_layer));
}

// Unload main menu
static void main_window_unload(Window *window) {
  menu_layer_destroy(s_menu_layer);
}

// Update the option window with title and mode
static void show_selected_title_and_mode() {
  ROW *choice = &options[s_current_option];

  // Update the title
  text_layer_set_text(s_title, options[s_current_option].title);
    
  
  //Somehow get message of whether the led is currently on or off?
  //That would be nice
  text_layer_set_text(s_mode, s_textlayer_modes[s_current_modes[s_current_option]]);
}

// What to do when the select button is pressed. Cycle through modes and should send message to turn on/off LED
static void select_click_handler(ClickRecognizerRef recognizer, void *context) {
  s_current_modes[s_current_option]++;
  if ((unsigned)s_current_modes[s_current_option] >= NUM_MODES) {
    s_current_modes[s_current_option] = 0;
  }
  
  DictionaryIterator *iterator;
  app_message_outbox_begin(&iterator);
  
  int key1 = 1;
  int value1 = s_current_option;
  dict_write_int(iterator, key1, &value1, sizeof(int), true);
  
  int key2 = 2;
  int value2 = s_current_modes[s_current_option];
  dict_write_int(iterator, key2, &value2, sizeof(int), true);
  
  app_message_outbox_send();
  show_selected_title_and_mode();
}

// When looking at an option, do this when the up button is clicked
static void up_click_handler(ClickRecognizerRef recognizer, void *context) {
  s_current_option--;
  if (s_current_option < 0) {
    s_current_option = NUM_ROWS - 1;
  }

  MenuIndex idx = menu_layer_get_selected_index(s_menu_layer);
  idx.row = s_current_option;
  menu_layer_set_selected_index(s_menu_layer, idx, MenuRowAlignCenter, false);
  
  show_selected_title_and_mode();
}

// When looking at an option, do this when the down button is pressed
static void down_click_handler(ClickRecognizerRef recognizer, void *context) {
  s_current_option++;
  if ((unsigned)s_current_option >= NUM_ROWS) {
    s_current_option = 0;
  }

  MenuIndex idx = menu_layer_get_selected_index(s_menu_layer);
  idx.row = s_current_option;
  menu_layer_set_selected_index(s_menu_layer, idx, MenuRowAlignCenter, false);
  
  show_selected_title_and_mode();
}

// Configure clicking when in app
static void click_config_provider(void *context) {
  window_single_click_subscribe(BUTTON_ID_SELECT, (ClickHandler)select_click_handler);
  window_single_click_subscribe(BUTTON_ID_UP, (ClickHandler)up_click_handler);
  window_single_click_subscribe(BUTTON_ID_DOWN, (ClickHandler)down_click_handler);
}

static void option_window_load(Window *window) {
  // Define some event handlers for clicks
  window_set_click_config_provider(window, (ClickConfigProvider) click_config_provider);

  Layer *window_layer = window_get_root_layer(window);
  GRect window_bounds = layer_get_bounds(window_layer);

  // Arrange the three text layers on top of each other
  window_bounds.size.h -= 40;
  s_text_layer = text_layer_create(window_bounds);

  s_title = text_layer_create(GRect(5, 38, 139, 50));
  text_layer_set_background_color(s_title, GColorWhite);
  text_layer_set_text_color(s_title, GColorBlack);
  text_layer_set_font(s_title, fonts_get_system_font(FONT_KEY_DROID_SERIF_28_BOLD));
  text_layer_set_text_alignment(s_title, GTextAlignmentCenter);
  
  s_mode = text_layer_create(GRect(5, 74, 139, 96));
  text_layer_set_background_color(s_mode, GColorWhite);
  text_layer_set_text_color(s_mode, GColorBlack);
  text_layer_set_font(s_mode, fonts_get_system_font(FONT_KEY_GOTHIC_24));
  text_layer_set_text_alignment(s_mode, GTextAlignmentCenter);
  
  // Add the child layer to the current window (s_option_window)
  layer_add_child(window_layer, text_layer_get_layer(s_text_layer));
  layer_add_child(window_layer, text_layer_get_layer(s_title));
  layer_add_child(window_layer, text_layer_get_layer(s_mode));

  // Update the text in the layers
  show_selected_title_and_mode();
}

// Unload window
static void option_window_unload(Window *window) {
  layer_remove_child_layers(window_get_root_layer(window));

  text_layer_destroy(s_text_layer);
}

static void init() {
  s_main_window = window_create();
  window_set_window_handlers(s_main_window, (WindowHandlers) {
    .load = main_window_load,
    .unload = main_window_unload
  });

  s_option_window = window_create();
  window_set_window_handlers(s_option_window, (WindowHandlers) {
    .load = option_window_load,
    .unload = option_window_unload
  });

  window_stack_push(s_main_window, true);
  
  app_message_register_inbox_received(inbox_received_callback);
  app_message_register_inbox_dropped(inbox_dropped_callback);
  app_message_register_outbox_failed(outbox_failed_callback);
  app_message_register_outbox_sent(outbox_sent_callback);
  
  app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());
}

static void deinit() {
  window_destroy(s_option_window);
  window_destroy(s_main_window);
}

int main(void) {
  init();
  app_event_loop();
  deinit();
}

Pebble App SendGet.js

JavaScript
This is the Pebble Javascript file that sent the get request which triggered the IFTTT event to execute the file on the Intel Edison
var xhrRequest = function (url, type, callback) {
  var xhr = new XMLHttpRequest();
  xhr.onload = function () {
    callback(this.responseText);
  };
  xhr.open(type, url);
  xhr.send();
};

function getRequest(pos, toggle) {
  // Construct URL
  var url = 'https://maker.ifttt.com/trigger/ToggleLED/with/key/dWqDNCPc3fXu3etvPwobbs?value1=' + (pos+1);

  xhrRequest(url, 'GET', 
    function(responseText) {
    });
}

Pebble.addEventListener('appmessage',
  function(e) {
    getRequest(e.payload.position);
  }
);

Arduino TurnOnLight

Plain text
Programmed in Arduino language.
void setup() {
  // initialize digital pins as outputs.
  pinMode(8, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  // turn the LEDs on (HIGH is the voltage level)
  digitalWrite(8, HIGH);   
  digitalWrite(12, HIGH);   
  digitalWrite(13, HIGH);   
}

Edison and Arduino Board

Plain text
No preview (download only).

Edison and Arduino Board

Plain text
No preview (download only).

Pebble Watch

Plain text
No preview (download only).

Credits

Addison Fattor

Addison Fattor

1 project • 0 followers
Charlie Summers

Charlie Summers

1 project • 0 followers
Budding full stack developer and data analyst from Portland, OR. Going to school at Fordham in the BX. Get at me.

Comments