B4A Library Pebble Watch Library

This is a B4A wrapper for the official Pebble Android SDK. It is using the SDK from November 2014 (pebblekit-2.6.0-eclipse.jar). Read the SDK documentation.

The PebbleKit object has several events which correspond to the SDK they are;

Sub PK_Connected
Sub PK_Disconnected
Sub PK_ReceiveAck
Sub PK_ReceiveData
Sub PK_ReceiveLogData1
Sub PK_ReceiveLogData2
Sub PK_ReceiveLogData3
Sub PK_ReceiveNack

Pebble
Comment:
B4A Library for Pebble Android SDK.

On Android, all communication between apps and Pebble go through the official Pebble Android application via intents.
PebbleKit Android provides a convenience layer on top of those intents.
You must install the official Pebble Android application to use PebbleKit Android.
PebbleKit Android requires Android SDK version 14 or higher (4.0 and above).
Author: Trevor Hart
Version: 1
  • PebbleAppType
    Fields:
    • GOLF As Int
    • OTHER As Int
    • SPORTS As Int
  • PebbleConstants
    Fields:
    • APP_UUID As String
      The bundle-key used to store a message's UUID.
    • CUST_APP_TYPE As String
      The bundle-key used to store the type of application being customized in a CUSTOMIZE intent.
    • CUST_ICON As String
      The bundle-key used to store the custom icon provided in a CUSTOMIZE intent.
    • CUST_NAME As String
      The bundle-key used to store the custom name provided in a CUSTOMIZE intent.
    • DATA_LOG_TAG As String
      A bundle-key used to store the tag for the corresponding data log.
    • DATA_LOG_TIMESTAMP As String
      The bundle-key used to store the timestamp of when a data log was first created.
    • DATA_LOG_UUID As String
      A bundle-key used to store the UUID that uniquely identifies a data log.
    • GOLF_BACK_KEY As Int
      The Constant GOLF_BACK_KEY.
    • GOLF_CMD_KEY As Int
      The Constant GOLF_CMD_KEY.
    • GOLF_CMD_NEXT As Int
      Command sent by the golf-application to display the previous hole.
    • GOLF_CMD_PREV As Int
      Command sent by the golf-application to display the next hole.
    • GOLF_FRONT_KEY As Int
      The Constant GOLF_FRONT_KEY.
    • GOLF_HOLE_KEY As Int
      The Constant GOLF_HOLE_KEY.
    • GOLF_MID_KEY As Int
      The Constant GOLF_MID_KEY.
    • GOLF_PAR_KEY As Int
      The Constant GOLF_PAR_KEY.
    • GOLF_UUID As UUID
      The UUID corresponding to Pebble's built-in "Golf" application.
    • INTENT_APP_ACK As String
      Intent broadcast to pebble.apk to indicate that a message was received from the watch. To avoid protocol timeouts
      on the watch, applications <em>must</em> ACK or NACK all received messages.
    • INTENT_APP_CUSTOMIZE As String
      Intent broadcast to pebble.apk responsible for customizing the name and icon of the 'stock' Sports and Golf
      applications included in the watch's firmware.
    • INTENT_APP_NACK As String
      Intent broadcast to pebble.apk to indicate that a message was unsuccessfully received from the watch.
    • INTENT_APP_RECEIVE As String
      Intent broadcast from pebble.apk containing one-or-more key-value pairs sent from the watch to the phone.
    • INTENT_APP_RECEIVE_ACK As String
      Intent broadcast from pebble.apk indicating that a sent message was successfully received by a watch app.
    • INTENT_APP_RECEIVE_NACK As String
      Intent broadcast from pebble.apk indicating that a sent message was not received by a watch app.
    • INTENT_APP_SEND As String
      Intent broadcast to pebble.apk containing one-or-more key-value pairs to be sent to the watch from the phone.
    • INTENT_APP_START As String
      Intent broadcast to pebble.apk responsible for launching a watch-app on the connected watch. This intent is
      idempotent.
    • INTENT_APP_STOP As String
      Intent broadcast to pebble.apk responsible for closing a running watch-app on the connected watch. This intent is
      idempotent.
    • INTENT_DL_ACK_DATA As String
      Intent broadcast to pebble.apk implicitly when a unit of data from a data log is received.
    • INTENT_DL_FINISH_SESSION As String
      Intent broadcast from pebble.apk indicating the session has finished.
    • INTENT_DL_RECEIVE_DATA As String
      Intent broadcast from pebble.apk containing a unit of data from a data log.
    • INTENT_DL_REQUEST_DATA As String
      Intent broadcast to pebble.apk to request data logs for a particular app.
    • INTENT_PEBBLE_CONNECTED As String
      Intent broadcast by pebble.apk when a new connection to a Pebble is established.
    • INTENT_PEBBLE_DISCONNECTED As String
      Intent broadcast by pebble.apk when the connection to a Pebble is closed or lost.
    • KIT_STATE_COLUMN_APPMSG_SUPPORT As Int
    • KIT_STATE_COLUMN_CONNECTED As Int
    • KIT_STATE_COLUMN_DATALOGGING_SUPPORT As Int
    • KIT_STATE_COLUMN_VERSION_MAJOR As Int
    • KIT_STATE_COLUMN_VERSION_MINOR As Int
    • KIT_STATE_COLUMN_VERSION_POINT As Int
    • KIT_STATE_COLUMN_VERSION_TAG As Int
    • MSG_DATA As String
      The bundle-key used to store a message's JSON payload send-to or received-from the watch.
    • PBL_DATA_ID As String
      A bundle-key used to store the ID of a unit of data in a data log.
    • PBL_DATA_OBJECT As String
      A bundle-key used to store the value of the data unit.
    • PBL_DATA_TYPE As String
      A bundle-key used to store the data type of the data unit.
    • SPORTS_DATA_KEY As Int
      The PebbleDictionary key corresponding to the 'data' field sent to the Sports watch-app. The data field is paired
      with a variable label and can be used to display any data.
    • SPORTS_DATA_PACE As Int
      PebbleDictionary value corresponding to 'pace' data.
    • SPORTS_DATA_SPEED As Int
      PebbleDictionary value corresponding to 'speed' data.
    • SPORTS_DISTANCE_KEY As Int
      The PebbleDictionary key corresponding to the 'distance' field sent to the Sports watch-app.
    • SPORTS_LABEL_KEY As Int
      The PebbleDictionary key corresponding to the 'label' field sent to the Sports watch-app. The label field
      controls the label above the 'data' field.
    • SPORTS_STATE_END As Int
      The Constant SPORTS_STATE_END.
    • SPORTS_STATE_INIT As Int
      The Constant SPORTS_STATE_INIT.
    • SPORTS_STATE_KEY As Int
      The PebbleDictionary key corresponding to the 'state' field sent to the Sports watch-app. Both the watch and
      phone-app may modify this field. The phone-application is responsible for performing any required state
      transitions to stay in sync with the watch-app's state.
    • SPORTS_STATE_PAUSED As Int
      The Constant SPORTS_STATE_PAUSED.
    • SPORTS_STATE_RUNNING As Int
      The Constant SPORTS_STATE_RUNNING.
    • SPORTS_TIME_KEY As Int
      The PebbleDictionary key corresponding to the 'time' field sent to the Sports watch-app.
    • SPORTS_UNITS_IMPERIAL As Int
      PebbleDictionary value corresponding to 'imperial' units.
    • SPORTS_UNITS_KEY As Int
      The PebbleDictionary key corresponding to the 'units' field sent to the Sports watch-app.
    • SPORTS_UNITS_METRIC As Int
      PebbleDictionary value corresponding to 'metric' units.
    • SPORTS_UUID As UUID
      The UUID corresponding to Pebble's built-in "Sports" application.
    • TRANSACTION_ID As String
      The bundle-key used to store a message's transaction id.
  • PebbleDataType
    Fields:
    • BYTES As Int
    • INT As Int
    • INVALID As Int
    • UINT As Int
  • PebbleDictionary
    Methods:
    • Initialize
    • IsInitialized As Boolean
    • addBytes (key As Int, bytes() As Byte)
    • addInt16 (key As Int, s As Short)
    • addInt32 (key As Int, i As Int)
    • addInt8 (key As Int, b As Byte)
    • addString (key As Int, value As String)
    • addUint16 (key As Int, s As Short)
    • addUint32 (key As Int, i As Int)
    • addUint8 (key As Int, b As Byte)
    • contains (key As Int) As Boolean
    • fromJson (jsonString As String) As Boolean
    • getBytes (key As Int) As Byte[]
    • getInteger (key As Int) As Long
    • getString (key As Int) As String
    • getUnsignedIntegerAsLong (key As Int) As Long
    • remove (key As Int)
    • size As Int
    • toJsonString As String
  • PebbleFirmwareVersionInfo
    Methods:
    • IsInitialized As Boolean
    Properties:
    • Major As Int [read only]
    • Minor As Int [read only]
    • Point As Int [read only]
    • Tag As String [read only]
  • PebbleKit
  • Methods:
    • Deinitialize
      Initializes the PebbleKit and creates the listener from the event name.
    • Initialize (EventName As String, subscribedUuid As String)
      Initializes the PebbleKit and creates the listener from the event name.
    • IsInitialized As Boolean
    • areAppMessagesSupported As Boolean
      Synchronously query the Pebble application to see if the connected watch is running a firmware version that supports PebbleKit messages.
    • closeAppOnPebble (watchappUuid As String)
      Send a message to the connected Pebble to close an application identified by a UUID.
    • customizeWatchApp (appType As PebbleAppType, name As String, icon As Bitmap)
      Send a message to the connected Pebble to "customize" a built-in PebbleKit watch-app.
    • isDataLoggingSupported As Boolean
      Synchronously query the Pebble application to see if the connected watch is running a firmware version that supports PebbleKit data logging.
    • isWatchConnected As Boolean
      Synchronously query the Pebble application to see if an active Bluetooth connection to a watch currently exists.
    • requestDataLogsForApp (watchappUuid As String)
      A convenience function to emit an intent to pebble.apk to request the data logs for a particular app.
    • sendAckToPebble (transactionId As Int)
      Send a message to the connected watch acknowledging the receipt of a PebbleDictionary.
    • sendDataToPebble (watchappUuid As String, data As PebbleDictionary)
      Send one-or-more key-value pairs to the watch-app identified by the provided UUID.
    • sendNackToPebble (transactionId As Int)
      Send a message to the connected watch that the previously sent PebbleDictionary was not received successfully.
    • startAppOnPebble (watchappUuid As String)
      Send a message to the connected Pebble to launch an application identified by a UUID.
    Permissions:
    • android.permission.ACCESS_WIFI_STATE
    • android.permission.INTERNET
    Properties:
    • WatchFWVersion As FirmwareVersionInfo [read only]
      Get the version information of the firmware running on a connected watch.
 

Attachments

  • Pebble.zip
    38.5 KB · Views: 320

postasat

Active Member
Licensed User
Longtime User
Amazing !
Thank you so much.

Now, as first, I must found how to create the dictionary "key-value pairs" to send to Pebble watch.

How to use Pebblekit events ?
 
Last edited:

tchart

Well-Known Member
Licensed User
Longtime User
This example shows you how to use the dictionary. It sends data to the demo weather app (from the SDK - you cant downlaod it here https://github.com/pebble/pebble-sdk-examples/blob/master/weather-demo/weather/build/weather.pbw)

B4X:
#Region  Project Attributes
    #ApplicationLabel: Pebble Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim p As PebbleKit   
    Dim c As PebbleConstants
   
    Dim s As String

    Dim WEATHER_UUID As String = "28AF3DC7-E40D-490F-BEF2-29548C8B0600"   
    Dim ICON_KEY As Int = 0
    Dim TEMP_KEY As Int = 1
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    p.Initialize("Pebble",WEATHER_UUID)
   
    If p.isWatchConnected = True Then
        ToastMessageShow("isWatchConnected = True",False)
    Else
        ToastMessageShow("isWatchConnected = False",False)
    End If
   
    'Dim pfw As PebbleFirmwareVersionInfo
    'pfw = p.WatchFWVersion
   
    'ToastMessageShow(pfw.Major,False)
    'ToastMessageShow(pfw.Minor,False)
    'ToastMessageShow(pfw.Point,False)
    'ToastMessageShow(pfw.Tag,False)   
   
    Dim data As PebbleDictionary
    data.Initialize   
    data.addUint8(ICON_KEY,1)
    data.addUint8(ICON_KEY,2)
    data.addString(TEMP_KEY, "99")
   
    p.sendDataToPebble(WEATHER_UUID, data)   
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
 

tchart

Well-Known Member
Licensed User
Longtime User
Here is how you receive data;

B4X:
Sub Pebble_ReceiveData(transactionId As Int, data As PebbleDictionary)
ToastMessageShow(transactionId,False)
pk.sendAckToPebble(transactionId)

Dim command As String
command = data.getString(1)

If command.ToUpperCase() = "ALL ON" Then
    ll.DWOn(1)
End If
If command.ToUpperCase() = "ALL OFF" Then
    ll.DWOff(1)
End If
'ToastMessageShow("getString = " & data.getString(1),False)

End Sub
 

tchart

Well-Known Member
Licensed User
Longtime User
Here is an example app of how to detect Pebble button pushes. Example includes B4A android app to receive button pushes and pebble app (PBW) to install on your watch.
 

Attachments

  • Pebble Button Click.zip
    8.9 KB · Views: 264

Ph1lJ

Member
Licensed User
Longtime User
Can anyone help, I'm trying to install the Pebble Button watch app provided by tchart, I've tried to find the appropriate method on the Pebble site and configured the watch as required, went to use the native pebble tool as mentioned, but it will no install on my tablet that's running 4.4.2 anyone got any ideas ?
 

Ph1lJ

Member
Licensed User
Longtime User
Oops posted this previously in wrong area, this Lib is great any chance you can create it for B4i as well ?
 

tchart

Well-Known Member
Licensed User
Longtime User
Ph1lJ, I don't have B4i and Im not sure what the process is for developing libraries for B4i. I'll have a look into it but cant promise anything.
 

postasat

Active Member
Licensed User
Longtime User
Hi,
I update my pebble classic and the pebble app for android (pebble time).
Now PebbleKit.isWatchConnected() from the Android SDK always returns false.

If I simply ignore that the call returns false. I can start Pebble apps and send custom messages, everything seems to work.
If I ignore isWatchConnected(), leads my app to crash when the watch isn't connected and I try to use it.

Is it possible to update the library for the last SDK for isWatchConnected() ?

Thank you.
 

nwhitfield

Active Member
Licensed User
Longtime User
Can I just say thanks very much for this. I got a Pebble last week (basic model can be found for £50 these days in the UK, and the Steel for £80), and have managed to get two-way comms between Pebble and one of my existing Android apps up and running really easily.

Great work.
 

techknight

Well-Known Member
Licensed User
Longtime User
How do you create a custom app for the pebble? I basically need the pebble to display and start/stop a timer clock on the tablet. Not sure how to do this?
 

tchart

Well-Known Member
Licensed User
Longtime User
How do you create a custom app for the pebble? I basically need the pebble to display and start/stop a timer clock on the tablet. Not sure how to do this?

You have to use the Pebble Cloud which includes a web based IDE. There is an example above which includes the C code for the pebble app.
 

nwhitfield

Active Member
Licensed User
Longtime User
Here's anther snippet that might be useful to some people. To make life easy for users, I've added the .pbw file associated with my B4A app (app4pebble.pbw here) to the Files tab, so it's added to the phone when the app is installed. I then have a label on the page where people can enable the Pebble option, called pebbleInfo, with a note that a long tap will install the app on their watch.

B4X:
Sub pebbleInfo_LongClick
   ToastMessageShow("Sideloading app to your Pebble",False)
   If File.Exists(File.DirDefaultExternal,"app4pebble.pbw") = False Then
     File.Copy(File.DirAssets,"app4pebble.pbw",File.DirDefaultExternal,"app4pebble.pbw")
   End If   
   Dim i As Intent
   i.Initialize2("file://" & File.Combine(File.DirDefaultExternal,"app4pebble.pbw"),0)
   i.SetComponent("com.getpebble.android")
   i.SetType("application/octet-stream")
   StartActivity(i)
End Sub
 

techknight

Well-Known Member
Licensed User
Longtime User
You have to use the Pebble Cloud which includes a web based IDE. There is an example above which includes the C code for the pebble app.

So in other words, we need a B4P. I dont program in C, so that option is out :-(

That C code in the example looks long and complicated just to handle simple push a button senders.

Regardless, I love the progress being made. its awesome so far!
 
Last edited:

nwhitfield

Active Member
Licensed User
Longtime User
I'm not a C programmer by any stretch of the imagination, but it was surprisingly simple to take the example code and work it into something. There's also a screen designer as part of the CloudPebble service which does a lot of the fiddly work for you. I was able to knock up a pretty reasonable app in a fairly short time. The example code shows how to send the buttons. Use the CloudPebble designer to create some text on the screen of the watch; pick your type size and font, and the position, and it will do all the code behind that for you.

Then, to keep the coding in C to a minimum, you use the sample to send commands to your B4A app, based on the buttons. You use a SELECT to choose what to do with the incoming commands, like stop or start the clock.

Then, you obviously need something that sends info back to the Pebble, which your C app there will put on the display. That's quite easy too. Information is sent as a Pebble Dictionary, which has keys in it, indicating which elements are there, and you add them as ints, or strings. Here's a bit of my code for that

B4X:
Sub updatePebbleDisplay()
   If pk.isWatchConnected = True Then
     Dim pStatus As PebbleDictionary
     pStatus.Initialize
     pStatus.addInt8(P_LEVELA,levelA)
     pStatus.addString(P_MODE,"some string")
     pk.sendDataToPebble(APP_UID,pStatus)
     Log("Data sent to pebble, size " & pStatus.size)
     Log(pStatus.toJsonString)
   End If
End Sub

P_LEVELA and P_MODE are Ints, defined earlier in the code; you add matching values as #defines at the top of the C code in the .h file that's created for you by the designer on CloudPebble. Then you use the inbox_received_callback to update the display, like this, assuming you have a string from the app, "some string" that you want to appear in the text box on the Pebble that you called s_modeinfo:

B4X:
static void inbox_received_callback(DictionaryIterator *iterator, void *context) {
  APP_LOG(APP_LOG_LEVEL_INFO, "Message received!");
  // update the display, based on info from the app 

  Tuple *stimmode = dict_find(iterator, P_MODE) ;

  static char modeinfo[32] ;
  
  if (stimmode) {
  // update mode info
  snprintf(modeinfo,sizeof(modeinfo), "%s", stimmode->value->cstring) ;
  text_layer_set_text(s_modeinfo,modeinfo) ;
  }
  
}

That may look fairly gibberish if you've not done C, but it's pretty straightforward, and if you can do all the hard work in the app on the phone, and merely use the buttons and display on the watch, then this sort of approach won't be too hard - you just need to think about what messages you'll send to the Pebble and how often.
 
Top