Smart Strap

La Pebble Time possède une interface série permettant de la relier à des dispositifs électroniques extérieurs. Ce principe est nommé par pebble le SmartStrap.

A) l’Interface :

FYOA6L7IEY3E3JJ.LARGE

Attention aux spécifications :

Characteristic Value
Pin layout (watch face down, left to right) Ground, data, power in/out, ground.
Type of data connection Single wire, open drain serial connection with external pull-up required.
Data voltage level 1.8V input logic level with tolerance for up to 5V.
Baud rate Configurable between 9600 and 460800 bps.
Output voltage (power pin) 3.3V (+/- 10%)
Maximum output current draw (power pin) 20mA
Minimum charging voltage (power pin) 5V (+/- 5%)
Maximum charging current draw 500mA

B) Connexion à un Arduino :

FP4IX6ZIEY3E993.LARGE F8HZHILIEY3E6R0.LARGE FIADWQ5IEY3EGHQ.LARGE

  1. Download and install teensyduino for the Arduino
  2. Download this Library as a .zip by clicking on the « Download ZIP » button on GitHub.
  3. In Arduino, create a new project and go to « Sketch » -> « Include Library » -> « Add .ZIP Library… » Select the .zip you just downloaded.
  4. Create a new Arduino sketch and put the following code to it, select your board type and download the code to the board
 #include <ArduinoPebbleSerial.h>  
 static const char* Button_Values[]= {"NONE","BACK", "UP", "SELECT", "DOWN"};  
 static const uint16_t SUPPORTED_SERVICES[] = {0x0000, 0x1001};  
 static const uint8_t NUM_SERVICES = 2;  
 static uint8_t pebble_buffer[GET_PAYLOAD_BUFFER_SIZE(200)];  
 static String pc_string;  
 void setup() {  
   // General init  
   Serial.begin(115200);  
 #if defined(__AVR_ATmega32U4__)  
   ArduinoPebbleSerial::begin_hardware(pebble_buffer, sizeof(pebble_buffer), Baud57600,  
    SUPPORTED_SERVICES, NUM_SERVICES);  
 #else  
 #error "This example will only work for those 32u4 based boards, e.g. Arduino Micro"  
 #endif  
 }  
 void loop() {  
   // Let the ArduinoPebbleSerial code do its processing  
   size_t length;  
   uint16_t service_id;  
   uint16_t attribute_id;  
   RequestType type;  
   if (ArduinoPebbleSerial::feed(&service_id, &attribute_id, &length, &type)) {  
    if ((service_id == 0x1001) && (attribute_id == 0x1001)) {  
      // we have a raw data frame to process  
      if (type == RequestTypeRead) {//Pebble want to read from Arduino  
       // send a response to the Pebble - reuse the same buffer for the response  
       uint32_t current_time = millis();  
       if(pc_string.length()==0){  
         pc_string = "EMPTY!!";  
       }  
       char buf[50];  
       pc_string.toCharArray(buf, 50);  
       Serial.print("pc_string.length()");  
       Serial.println(pc_string.length());  
       Serial.print("buf");  
       Serial.println(buf);  
       memcpy(pebble_buffer, buf, pc_string.length());  
       pebble_buffer[pc_string.length()]='\0';  
       Serial.print("pebble_buffer");  
       Serial.println(pebble_buffer[0]);  
       ArduinoPebbleSerial::write(true, pebble_buffer, pc_string.length());  
       Serial.print("Sent message to Pebble");  
       Serial.println(pc_string);  
       pc_string = "";  
      } else if (type == RequestTypeWrite) {//Pebble wrote something to Arduino  
       Serial.print("Got New Button event: ");  
       uint8_t button_value = pebble_buffer[0];  
       uint8_t click_type = pebble_buffer[1];  
       if(button_value<=4){  
         Serial.println(Button_Values[button_value]);  
       }  
      }  
    } else {  
      // unsupported attribute - fail the request  
      ArduinoPebbleSerial::write(false, NULL, 0);  
    }  
   }  
   static bool is_connected = false;  
   if (ArduinoPebbleSerial::is_connected()) {  
    if (!is_connected) {  
      Serial.println("Connected to the smartstrap!");  
      is_connected = true;  
    }  
    //scan the usb serial port for new input data  
    if(Serial.available()){  
      char inChar = (char)Serial.read();  
      pc_string +=inChar;  
      if(inChar=='#'){//stop sign  
       Serial.println("Notifying Pebble: ");  
       ArduinoPebbleSerial::notify(0x1001, 0x1001);  
      }  
    }  
   } else {  
    if (is_connected) {  
      Serial.println("Disconnected from the smartstrap!");  
      is_connected = false;  
    }  
   }  
 }  

Sur le Pebble Cloud, créez un fichier main.c

 #include <pebble.h>  
 #define TIMEOUT_MS 1000  
 #define MAX_READ_SIZE 100  
 static Window *s_main_window;  
 static TextLayer *s_status_layer;  
 static TextLayer *s_attr_text_layer;  
 static char s_text_buffer1[20];  
 static SmartstrapAttribute *s_raw_attribute;  
 static SmartstrapAttribute *s_attr_attribute;  
 static void prv_update_text(void) {  
  if (smartstrap_service_is_available(0x1001)) {  
   text_layer_set_text(s_status_layer, "Connected!");  
  } else {  
   text_layer_set_text(s_status_layer, "Connecting...");  
  }  
 }  
 static void prv_did_read(SmartstrapAttribute *attr, SmartstrapResult result,  
                const uint8_t *data, size_t length) {  
  char str[50] = " ";  
  if (attr == s_attr_attribute) {  
   APP_LOG(APP_LOG_LEVEL_DEBUG, "did_read(s_attr_attribute, %d, %d)", result, length);  
   if (result == SmartstrapResultOk ) {  
    memcpy(str, data, length);  
    str[length] = '\0';  
    snprintf(s_text_buffer1, 50, "%s", str);  
    text_layer_set_text(s_attr_text_layer, s_text_buffer1);  
    APP_LOG(APP_LOG_LEVEL_DEBUG, "message: %s)", str);  
   }  
  }else {  
   APP_LOG(APP_LOG_LEVEL_ERROR, "did_read(<%p>, %d)", attr, result);  
  }  
 }  
 static void prv_did_write(SmartstrapAttribute *attr, SmartstrapResult result) {  
  if (attr == s_attr_attribute) {  
   APP_LOG(APP_LOG_LEVEL_DEBUG, "did_write(s_attr_attribute, %d)", result);  
  } else {  
   APP_LOG(APP_LOG_LEVEL_ERROR, "did_write(<%p>, %d)", attr, result);  
  }  
 }  
 static void prv_write_button_action(uint8_t button_value, uint8_t click_type) {  
  SmartstrapResult result;  
  if (!smartstrap_service_is_available(smartstrap_attribute_get_service_id(s_attr_attribute))) {  
   APP_LOG(APP_LOG_LEVEL_DEBUG, "s_attr_attribute is not available");  
   return;  
  }  
  // get the write buffer  
  uint8_t *buffer = NULL;  
  size_t length = 0;  
  result = smartstrap_attribute_begin_write(s_attr_attribute, &buffer, &length);  
  if (result != SmartstrapResultOk) {  
   APP_LOG(APP_LOG_LEVEL_ERROR, "Write of s_attr_attribute failed with result %d", result);  
   return;  
  }  
  // write the data into the buffer  
  buffer[0] = button_value;  
  buffer[1] = click_type;  
  // send it off  
  result = smartstrap_attribute_end_write(s_attr_attribute, 2, false);  
  if (result != SmartstrapResultOk) {  
   APP_LOG(APP_LOG_LEVEL_ERROR, "Write of s_attr_attribute failed with result %d", result);  
  }  
 }  
 static void prv_availablility_status_changed(SmartstrapServiceId service_id, bool is_available) {  
  APP_LOG(APP_LOG_LEVEL_DEBUG, "Availability for 0x%x is %d", service_id, is_available);  
  prv_update_text();  
 }  
 static void prv_notified(SmartstrapAttribute *attr) {  
      SmartstrapResult result;  
  if (attr == s_attr_attribute) {  
   APP_LOG(APP_LOG_LEVEL_DEBUG, "notified(s_attr_attribute)");  
      result = smartstrap_attribute_read(s_attr_attribute);  
      if(result != SmartstrapResultOk) {  
           APP_LOG(APP_LOG_LEVEL_ERROR, "Error reading attribute (<%p>, %d)", attr, result);  
      }  
  } else {  
   APP_LOG(APP_LOG_LEVEL_ERROR, "notified(<%p>)", attr);  
  }  
 }  
 static void up_click_handler(ClickRecognizerRef recognizer, void *context) {  
  prv_write_button_action(0x02, 0x01);  
 }  
 static void select_click_handler(ClickRecognizerRef recognizer, void *context) {  
  prv_write_button_action(0x03, 0x01);  
 }  
 static void down_click_handler(ClickRecognizerRef recognizer, void *context) {  
  prv_write_button_action(0x04, 0x01);  
 }  
 static void click_config_provider(void *context) {  
  window_single_click_subscribe(BUTTON_ID_UP, up_click_handler);  
  window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler);  
  window_single_click_subscribe(BUTTON_ID_DOWN, down_click_handler);  
 }  
 static void prv_main_window_load(Window *window) {  
  s_status_layer = text_layer_create(GRect(0, 15, 144, 40));  
  text_layer_set_font(s_status_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28));  
  prv_update_text();  
  text_layer_set_text_color(s_status_layer, GColorBlack);  
  text_layer_set_background_color(s_status_layer, GColorClear);  
  text_layer_set_text_alignment(s_status_layer, GTextAlignmentCenter);  
  text_layer_set_overflow_mode(s_status_layer, GTextOverflowModeWordWrap);  
  layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_status_layer));  
  s_attr_text_layer = text_layer_create(GRect(0, 60, 144, 40));  
  text_layer_set_font(s_attr_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28));  
  text_layer_set_text(s_attr_text_layer, "-");  
  text_layer_set_text_color(s_attr_text_layer, GColorBlack);  
  text_layer_set_background_color(s_attr_text_layer, GColorClear);  
  text_layer_set_text_alignment(s_attr_text_layer, GTextAlignmentCenter);  
  text_layer_set_overflow_mode(s_attr_text_layer, GTextOverflowModeWordWrap);  
  layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_attr_text_layer));  
 }  
 static void prv_main_window_unload(Window *window) {  
  text_layer_destroy(s_status_layer);  
 }  
 static void prv_init(void) {  
  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 = prv_main_window_load,  
   .unload = prv_main_window_unload  
  });  
  window_stack_push(s_main_window, true);  
  SmartstrapHandlers handlers = (SmartstrapHandlers) {  
   .availability_did_change = prv_availablility_status_changed,  
   .did_write = prv_did_write,  
   .did_read = prv_did_read,  
   .notified = prv_notified  
  };  
  smartstrap_subscribe(handlers);  
  smartstrap_set_timeout(50);  
  s_raw_attribute = smartstrap_attribute_create(0, 0, 2000);  
  s_attr_attribute = smartstrap_attribute_create(0x1001, 0x1001, 20);  
 }  
 static void prv_deinit(void) {  
  window_destroy(s_main_window);  
  smartstrap_unsubscribe();  
  smartstrap_attribute_destroy(s_raw_attribute);  
  smartstrap_attribute_destroy(s_attr_attribute);  
 }  
 int main(void) {  
  prv_init();  
  APP_LOG(APP_LOG_LEVEL_DEBUG, "STARTING APP");  
  if (s_attr_attribute && s_raw_attribute) {  
   app_event_loop();  
  }  
  APP_LOG(APP_LOG_LEVEL_DEBUG, "ENDING APP");  
  prv_deinit();  
 }  

What this demo does?

  1. Keep Arduino connected to computer, use a serial monitor to open Arduino’s serial port
  2. Attach the hacked charging cable to Pebble watch
  3. Run the Pebble app, the watch will show « connected! »
  4. Send a string ends with ‘#’ (e.g. « 123abc# » ) to your Arduino’s serial port and watch it displaying on pebble watch.
  5. Click any of the up/down/select button on pebble and watch it showing on the computer screen.

How it works?

Arduino is receiving string end with‘#’ sign from its usb serial port(Serial) and notify the Watch when ‘#’ sign is detected. The Pebble Watch will then read the string from Arduino.
On the other way the Pebble is sending its 3 button click data to the Arduino, Arduino will print this on the usb serial port.

Références :

http://makezine.com/2015/09/25/hacking-on-the-pebble-smartstrap/

http://www.instructables.com/id/Pebble-time-watch-Smartstrap-Tutorial/

https://developer.getpebble.com/guides/hardware/

https://github.com/pebble/ArduinoPebbleSerial/

Publicité

Votre commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s

Articles récents
Commentaires récents
Catégories
Archives
%d blogueurs aiment cette page :