Turn on the light from a Pebble smart watch

Turn on the light from a Pebble smart watch

You have most probably already read about the Pebble smart watch, which connects to your phone to let you know about new emails, text messages, incoming calls, etc. A year after the original announcement, Pebble has eventually published the SDK to create an active “Watch App” for this watch. We thought it would be fun and convenient to be able to control our environment directly from a watch. So, to test this new SDK, we have written a small Pebble application that controls the light bulb that we used a couple of weeks ago with the Yocto-LatchedRelay.


For this project, we use a Pebble watch, an Android smartphone, a YoctoHub-Ethernet and a Yocto-LatchedRelay. The purpose of the YoctoHub-Ethernet is to make the Yocto-LatchedRelay accessible to any machine on the LAN. Practically, a YoctoHub-Ethernet behaves like a PC running the VirtualHub, but is much smaller and consumes even 3 times less energy than a Raspberry Pi. The YoctoHub-Ethernet is not yet available for sale, but a few prototype units are already being tested by some of our customers. If everything goes well, we should be able to announce the availability of this product in a few weeks.




The Pebble App

For our application, we display information about available relays one by one. The upper and lower buttons are used to navigate between the relays. The center button is used to toggle the state of the selected relay. Most of the complexity is pushed away on to the Android App: the watch sends a message for each button pressed, and the Android app carries on the requested operations and sends the updated data to the watch.

Screenshot of the Pebble app
Screenshot of the Pebble app



Writing a Pebble application is more complex than writing a standard smartphone app. First, you need to install the PebbleKit. This requires a Mac OS X or Linux machine, as Windows is not yet supported, and the installation process is a pain. Once this is done, you can start coding your Pebble “Watch App”. A Pebble application is written in vanilla C: without dynamic allocation, without persistent storage, without printf, without anything... except of course a nice lot of well-documented functions to display stuff on the watch and to exchange messages with the phone. But developers used to high-level languages might feel a bit lost at the beginning.

Like for an Android app, we define callbacks that are automatically invoked by the watch depending on the events (button pressed, programming message from the phone, etc). The code of our Pebble app is simple but nevertheless quite long, so we won’t go over it in detail in this post. If you want to have a deep look at it, the full source code is available on GitHub.

The Android app

As for the Android application, we keep it very simple. The app lists the relays found on the YoctoHub-Ethernet, and responds to any touch by toggling the corresponding relay. We initialize the Yoctopuce API to use the YoctoHub-Ethernet by calling YAPI.RegisterHub() with the IP address (or hostame) of the YoctoHub-Ethernet, instead of the traditional "usb". All other library functions work exactly as if the relays were connected directly by USB.

Unfortunately, Android OS is not as friendly as our library for network access. First, you need to get blessed for using the Internet. To do that, add <uses-permission android:name="android.permission.INTERNET" /> in AndroidManifest.xml file. Moreover, Android doesn't allow you to access the network from the main thread. So you must either implement a Service, or use AsyncTask when calling Yoctopuce API functions.

Screenshot of the Android app
Screenshot of the Android app



To let our Android app receive messages from the watch, we have to implement and register a BroadcastReceiver that is invoked every time that the watch sends a message to the phone. Depending on the command, the app either updates the current relay pointer or toggles the relay state. At the end, the application sends back to the watch updated data with the new relay state.

public void onReceive(Context context, Intent intent)
{
  if (intent.getAction().equals(Constants.INTENT_APP_RECEIVE)) {
    final UUID receivedUuid = (UUID) intent.getSerializableExtra(Constants.APP_UUID);

    // Pebble-enabled apps are expected to be good citizens and only
    // inspect broadcasts containing their UUID
    if (!PEBBLE_APP_UUID.equals(receivedUuid)) {
      return;
    }

    final int transactionId = intent.getIntExtra(Constants.TRANSACTION_ID, -1);
    final String jsonData = intent.getStringExtra(Constants.MSG_DATA);
    if (jsonData == null || jsonData.isEmpty()) {
      return;
    }
    int cmd=PREVIOUS_RELAY;
    try {
      final PebbleDictionary data = PebbleDictionary.fromJson(jsonData);
      cmd = data.getUnsignedInteger(CMD_KEY).intValue();
    } catch (JSONException e) { return;}
    Log.i(TAG, "receive command" + cmd);
    // acknowledge the command
    PebbleKit.sendAckToPebble(context, transactionId);
    RelayListStorage singleton = RelayListStorage.get(context);
    Relay relay;
    switch(cmd){
    case PREVIOUS_RELAY:
      singleton.pebblePrevious();
      break;
    case TOGGLE_RELAY:
      relay = singleton.pebbleGetCurrent();
      if(relay==null)
        break;
      relay.toggle();
      singleton.notfyChanges();
      // send message to the  application service
      Intent serviceintent = new Intent(context, YoctoService.class);
      serviceintent.putExtra(YoctoService.EXTRA_TOGGLE, relay.getHwId());
      context.startService(serviceintent);
      break;
    case NEXT_RELAY:
      singleton.pebbleNext();
      break;
    default:
    }
    relay = singleton.pebbleGetCurrent();
    if (relay !=null) {
      PebbleDictionary dictionary = relay.toPebbleDictionary();
      PebbleKit.sendDataToPebble(context, PEBBLE_APP_UUID, dictionary);
    } else {
      PebbleDictionary dictionary = Relay.getEmtpyPebbleDictionary();
      PebbleKit.sendDataToPebble(context, PEBBLE_APP_UUID, dictionary);
    }
  }
}



The code of this Android app will be added to the examples included in our Android library.

To conclude, here is the new version of the Yocto-LatchedRelay product demo, now featuring a Pebble smart-watch driven remote control.

  



We have intentionally kept this example simple, as its main purpose was to test the Pebble API. We don’t intend to impress anyone by switching a light bulb screwed on wood board. But based on this first successful experiment, the feasibility and usability of a watch-driven environment control system becomes quite appealing and calls for more experiments. You wouldn’t mind opening your garage door from your watch, would you ?

Add a comment No comment yet Back to blog












Yoctopuce, get your stuff connected.