mirror of
https://github.com/google/pebble.git
synced 2025-11-24 16:22:25 -05:00
Import the pebble dev site into devsite/
This commit is contained in:
260
devsite/source/_guides/smartstraps/talking-to-pebble.md
Normal file
260
devsite/source/_guides/smartstraps/talking-to-pebble.md
Normal file
@@ -0,0 +1,260 @@
|
||||
---
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
title: Talking To Pebble
|
||||
description: |
|
||||
Information on how to implement the smartstrap protocol to talk to the Pebble
|
||||
accessory port.
|
||||
guide_group: smartstraps
|
||||
order: 2
|
||||
related_docs:
|
||||
- Smartstrap
|
||||
related_examples:
|
||||
- title: Smartstrap Button Counter
|
||||
url: https://github.com/pebble-examples/smartstrap-button-counter
|
||||
- title: Smartstrap Library Test
|
||||
url: https://github.com/pebble-examples/smartstrap-library-test
|
||||
---
|
||||
|
||||
In order to communicate successfully with Pebble, the smartstrap hardware must
|
||||
correctly implement the smartstrap protocol as defined in
|
||||
{% guide_link smartstraps/smartstrap-protocol %}.
|
||||
|
||||
|
||||
## Arduino Library
|
||||
|
||||
For developers prototyping with some of the most common Arduino boards
|
||||
(based on the AVR ATmega 32U4, 2560, 328, or 328P chips), the simplest way of
|
||||
doing this is to use the
|
||||
[ArduinoPebbleSerial](https://github.com/pebble/arduinopebbleserial) library.
|
||||
This open-source reference implementation takes care of the smartstrap protocol
|
||||
and allows easy communication with the Pebble accessory port.
|
||||
|
||||
Download the library as a .zip file. In the Arduino IDE, go to 'Sketch' ->
|
||||
'Include Library' -> 'Add .ZIP LIbrary...'. Choose the library .zip file. This
|
||||
will import the library into Arduino and add the appropriate include statement
|
||||
at the top of the sketch:
|
||||
|
||||
```c++
|
||||
#include <ArduinoPebbleSerial.h>
|
||||
```
|
||||
|
||||
After including the ArduinoPebbleSerial library, begin the sketch with the
|
||||
standard template functions (these may already exist):
|
||||
|
||||
```c++
|
||||
void setup() {
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Connecting to Pebble
|
||||
|
||||
Declare the buffer to be used for transferring data (of type `uint8_t`), and its
|
||||
maximum length. This should be large enough for managing the largest possible
|
||||
request from the watch, but not so large that there is no memory left for the
|
||||
rest of the program:
|
||||
|
||||
> Note: The buffer **must** be at least 6 bytes in length to handle internal
|
||||
> protocol messages.
|
||||
|
||||
```c++
|
||||
// The buffer for transferring data
|
||||
static uint8_t s_data_buffer[256];
|
||||
```
|
||||
|
||||
Define which service IDs the strap will support. See
|
||||
{% guide_link smartstraps/smartstrap-protocol#generic-service-profile "Generic Service Profile" %}
|
||||
for details on which values may be used here. An example service ID and
|
||||
attribute ID both of value `0x1001` are shown below:
|
||||
|
||||
```c
|
||||
static const uint16_t s_service_ids[] = {(uint16_t)0x1001};
|
||||
static const uint16_t s_attr_ids[] = {(uint16_t)0x1001};
|
||||
```
|
||||
|
||||
The last decision to be made before connection is which baud rate will be used.
|
||||
This will be the speed of the connection, chosen as one of the available baud
|
||||
rates from the `Baud` `enum`:
|
||||
|
||||
```c
|
||||
typedef enum {
|
||||
Baud9600,
|
||||
Baud14400,
|
||||
Baud19200,
|
||||
Baud28800,
|
||||
Baud38400,
|
||||
Baud57600,
|
||||
Baud62500,
|
||||
Baud115200,
|
||||
Baud125000,
|
||||
Baud230400,
|
||||
Baud250000,
|
||||
Baud460800,
|
||||
} Baud;
|
||||
```
|
||||
|
||||
This should be chosen as the highest rate supported by the board used, to allow
|
||||
the watch to save power by sleeping as much as possible. The recommended value
|
||||
is `Baud57600` for most Arduino-like boards.
|
||||
|
||||
|
||||
### Hardware Serial
|
||||
|
||||
If using the hardware UART for the chosen board (the `Serial` library),
|
||||
initialize the ArduinoPebbleSerial library in the `setup()` function to prepare
|
||||
for connection:
|
||||
|
||||
```c++
|
||||
// Setup the Pebble smartstrap connection
|
||||
ArduinoPebbleSerial::begin_hardware(s_data_buffer, sizeof(s_data_buffer),
|
||||
Baud57600, s_service_ids, 1);
|
||||
```
|
||||
|
||||
|
||||
### Software Serial
|
||||
|
||||
Alternatively, software serial emulation can be used for any pin on the chosen
|
||||
board that
|
||||
[supports interrupts](https://www.arduino.cc/en/Reference/AttachInterrupt). In
|
||||
this case, initialize the library in the following manner, where `pin` is the
|
||||
compatible pin number. For example, using Arduino Uno pin D8, specify a value of
|
||||
`8`. As with `begin_hardware()`, the baud rate and supported service IDs must
|
||||
also be provided here:
|
||||
|
||||
```c++
|
||||
int pin = 8;
|
||||
|
||||
// Setup the Pebble smartstrap connection using one wire software serial
|
||||
ArduinoPebbleSerial::begin_software(pin, s_data_buffer, sizeof(s_data_buffer),
|
||||
Baud57600, s_service_ids, 1);
|
||||
```
|
||||
|
||||
|
||||
## Checking Connection Status
|
||||
|
||||
Once the smartstrap has been physically connected to the watch and the
|
||||
connection has been established, calling `ArduinoPebbleSerial::is_connected()`
|
||||
will allow the program to check the status of the connection, and detect
|
||||
disconnection on the smartstrap side. This can be indicated to the wearer using
|
||||
an LED, for example:
|
||||
|
||||
```c++
|
||||
if(ArduinoPebbleSerial::is_connected()) {
|
||||
// Connection is valid, turn LED on
|
||||
digitalWrite(7, HIGH);
|
||||
} else {
|
||||
// Connection is not valid, turn LED off
|
||||
digitalWrite(7, LOW);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Processing Commands
|
||||
|
||||
In each iteration of the `loop()` function, the program must allow the library
|
||||
to process any bytes which have been received over the serial connection using
|
||||
`ArduinoPebbleSerial::feed()`. This function will return `true` if a complete
|
||||
frame has been received, and set the values of the parameters to inform the
|
||||
program of which type of frame was received:
|
||||
|
||||
```c++
|
||||
size_t length;
|
||||
RequestType type;
|
||||
uint16_t service_id;
|
||||
uint16_t attribute_id;
|
||||
|
||||
// Check to see if a frame was received, and for which service and attribute
|
||||
if(ArduinoPebbleSerial::feed(&service_id, &attribute_id, &length, &type)) {
|
||||
// We got a frame!
|
||||
if((service_id == 0) && (attribute_id == 0)) {
|
||||
// This is a raw data service frame
|
||||
// Null-terminate and display what was received in the Arduino terminal
|
||||
s_data_buffer[min(length_read, sizeof(s_data_buffer))] = `\0`;
|
||||
Serial.println(s_data_buffer);
|
||||
} else {
|
||||
// This may be one of our service IDs, check it.
|
||||
if(service_id == s_service_ids[0] && attribute_id == s_attr_ids[0]) {
|
||||
// This frame is for our supported service!
|
||||
s_data_buffer[min(length_read, sizeof(s_data_buffer))] = `\0`;
|
||||
Serial.print("Write to service ID: ");
|
||||
Serial.print(service_id);
|
||||
Serial.print(" Attribute ID: ");
|
||||
Serial.print(attribute_id);
|
||||
Serial.print(": ");
|
||||
Serial.println(s_data_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If the watch is requesting data, the library also allows the Arduino to respond
|
||||
back using `ArduinoPebbleSerial::write()`. This function accepts parameters to
|
||||
tell the connected watch which service and attribute is responding to the read
|
||||
request, as well is whether or not the read was successful:
|
||||
|
||||
> Note: A write to the watch **must** occur during processing for a
|
||||
> `RequestType` of `RequestTypeRead` or `RequestTypeWriteRead`.
|
||||
|
||||
```c++
|
||||
if(type == RequestTypeRead || type == RequestTypeWriteRead) {
|
||||
// The watch is requesting data, send a friendly response
|
||||
char *msg = "Hello, Pebble";
|
||||
|
||||
// Clear the buffer
|
||||
memset(s_data_buffer, 0, sizeof(s_data_buffer));
|
||||
|
||||
// Write the response into the buffer
|
||||
snprintf((char*)s_data_buffer, sizeof(s_data_buffer), "%s", msg);
|
||||
|
||||
// Send the data to the watch for this service and attribute
|
||||
ArduinoPebbleSerial::write(true, s_data_buffer, strlen((char*)s_data_buffer)+1);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Notifying the Watch
|
||||
|
||||
To save power, it is strongly encouraged to design the communication scheme in
|
||||
such a way that avoids needing the watch to constantly query the status of the
|
||||
smartstrap, allowing it to sleep. To aid in this effort, the ArduinoPebbleSerial
|
||||
library includes the `ArduinoPebbleSerial::notify()` function to cause the
|
||||
watchapp to receive a ``SmartstrapNotifyHandler``.
|
||||
|
||||
For example, to notify the watch once a second:
|
||||
|
||||
```c++
|
||||
// The last time the watch was notified
|
||||
static unsigned long s_last_notif_time = 0;
|
||||
|
||||
void loop() {
|
||||
|
||||
/* other code */
|
||||
|
||||
// Notify the watch every second
|
||||
if (millis() - s_last_notif_time > 1000) {
|
||||
// Send notification with our implemented serviceID and attribute ID
|
||||
ArduinoPebbleSerial::notify(s_service_ids[0], s_attr_ids[0]);
|
||||
|
||||
// Record the time of this notification
|
||||
s_last_notif_time = millis();
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user