In Need of Parse Alternatives? Let’s Look at Firebase!

Until recently, Parse has been the go-to solution for mobile developers who needed to persist application data to the cloud without having to set up and run a custom API backend. All of this changed in January 2016, when Parse announced that they would be ending the service in 2017. Even before Parse announced its termination, Google’s Firebase has gained popularity as an alternative. Despite the fact that Firebase does not offer a direct conversion mechanism from Parse, we decided to evaluate it for Bookdash, an open source project that we contribute to.

What is Firebase?

firebase_logo
In a nutshell: Firebase is a cloud-based NoSQL data storage service with close to real time updates. It offers features such as automatic updates, syncing, and caching mechanisms for mobile clients. In addition, it also has mechanisms for user authentication and authorization to data. All of the data can be viewed with the Firebase console in a JSON tree structure and all authentication and authorization logic is written in JSON.

What Are Its Strengths?

This list is not exhaustive, but an application with the following characteristics would be ideal for Firebase:

  • Simple data structures
  • Simple authorization and authentication rules
  • The need to quickly update data between clients that share data
  • The need to scale

Given that most mobile applications fall into one or more of these categories, Firebase makes it easy to get started and be productive.

What About Complex Data Structures?

Granted, things do get a bit more interesting when your application has complex data structures. Since Firebase is a NoSQL data store that uses data, there is nothing to stop you from storing nested data in a format. Consider the following example:

{"Books":
    [{'author' : {
        'name': 'Matz'
        'publishers' : [{
              'company_name' : 'Pearson'
              'company_addresses' : [{
                   'address1' : '1 ruby way'
                    }]
              }],
         'author website' : 'www.ruby.com'
         }}
     'title' : 'Ruby Rocks'
    }]
}

In this example, we use a nested data structure to store data about a book. Let’s say that we have a very simple application that gives users a list of books along with the respective authors. Theoretically, you could simply store the data in a nested JSON structure. At first glance, it might seem like the obvious thing to do if you’re receiving all of the data from another source in a nested feed. There are, however, two problems with this. allie_programFirst, what happens if some common biographical information about a author needs to be changed (for example, the author’s website)? With the current data structure, we’ll need to update every book that we have in the data store. This might be a reasonable trade off if we have 10 books, but what if we have 1,000 or 1,000,000 books? If we have a mobile application that writes directly to Firebase, this would clearly be data intensive and highly impractical. Secondly, if we attempt to retrieve a list of book titles and authors only, a query against the data store will also return a lot of unnecessary nested data (such as the publisher, publication date, etc.) Again, this can cause the application to have excessive data usage and slow down query times. One way to fix this would be to normalize the data.

{'Books':
   [{'author' : 1,
        'title' : 'Ruby Rocks'
   }],
'authors' :{
    1 : {
         'name': 'Matz'
         'publishers' : 1,
         'author website' : 'www.ruby.com'
        }}
    },
'publishers' : {
    1 : {
        'company_name' : 'Pearson'
        'company_addresses' : 1
        },
'company_addresses' : {
     1 : {
          'address1' : '1 ruby way'
         }
    }
}

This resolves one problem, but now we need to query against two top level JSON objects in order to get a book title and author. Two queries will not be a large performance burden, but what if our application needs a list of the book author, title, publisher name, and publisher address? We’re up to 4 queries. Now, what if we have a normalized data structure that spans 7 or 10 objects?

Denormalization

To fix the multiple query problem, we may need to have redundant data in multiple objects. For example, we may create one top level object in Firebase that has a nested data structure and another that has the normalized structure. If Firebase is only hooked up to one web application that manages all of this, it may add a bit of complexity, but it would remain manageable. One major advantage of using Firebase is that you don’t have to stand up your own server. It has native clients for Android and iOS that do a lot of the heavy lifting around getting, putting and offline data access for your Firebase DataStore.

Many Clients

If you have only one application that can write data, the data structure may be a reasonable trade off. IMG_0454 (2)But, what if you have an iOS and Android Client that also has the ability to edit the address for Pearson? More importantly, what if there are a few thousand book titles in your repository that were published by Pearson? This would, again, create two problems. First, a mobile client might have to update a lot of records. Second, it increases the chance for out of sync data, since two codebases need to stay in sync with the updated data structure.

Using a Hybrid Approach

One possible solution is to set up your own server to manage writes between the mobile applications and Firebase store. You’d have to deal with maintaining another application stack, scaling it for traffic, and manually deal with data writes from the application. You could still have your app directly read from Firebase (which has a lot of advantages), but you would also add complexity to the system.
.

Should I Use Firebase?

Firebase is a good choice for many applications. scrumIf you have a simple data structure, it will handle a lot of the data sync and caching for you, and create a very robust back end that can deal with a lot of traffic. If you have a complex data structure or a lot of sophisticated authorization rules, things may not be as cut and dry. There are a lot of benefits to using it, and in our opinion, they often tip the scales in favor of Firebase. That said, there might be other compelling reasons, such as a desire to version your API, increase security, or integrate with other platforms, where it would be more advantageous to create a custom API on your own server instance.

Posted in Android, Architecture, Database, Development, IOS Tagged with: , , ,

Purr Programming Shirt Part 4 — Adding Android Wear Support

In the first three parts of this series we discussed how to create a wearable garment (in our case, a t-shirt) with LEDs, how to connect it to an Android device using MetaWear, and how to make it change colors and flash when someone tweets at you. Now, let’s add another fun feature: Triggering color changes and making the LEDs flash by using an AndroidWear smartwatch. In this example, the app is going to listen for a speech command, check what is said, and prompt the colors to change and flash if the command is valid.

How Does It Work?

Screen Shot 2016-04-14 at 2.38.47 AM

When you open the watch application, it launches a voice prompt. The user can state which pattern to use, such as “rubyfuza”. If the app recognizes the command, a Wearable.MessageApi message is sent. That message will then be read by an instance of WearableListenerService on the phone. The service creates a Broadcast Intent and sends it to the MetaWear Service, which, in turn, sends commands to the shirt to change colors or flash the LEDs in the specified pattern.

Setting Up the Wear App and Adding Voice Recognition

screen (3)
To get started, you need to add an AndroidWear module to your application.

When we open the application, we’re immediately going to launch a prompt for the user’s voice command. To do that, we create a ACTION_RECOGNIZE_SPEECH intent and pass it into startActivityForResult.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        .
        .
        .
        val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
        // Start the activity, the intent will be populated with the speech text
        startActivityForResult(intent, SPEECH_REQUEST_CODE)

    }

When voice recognition is complete, it calls onActivityResult with the results. We’re able to read the results by overriding this method, and if it is a SPEECH_REQUEST, we can call getStringArrayListExtra on the Intent object returned in the method. The first item in the array is a string representing the user’s speech.

   override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
        if (requestCode == SPEECH_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            val results = data.getStringArrayListExtra(
                    RecognizerIntent.EXTRA_RESULTS)
            val spokenText = results[0]
            Log.i("Speech ", spokenText)
        }

Sending the Command to the Phone

In order to send commands to a phone, we need to include the play-services dependency in the dependencies section of our wear build.gradle file.

compile 'com.google.android.gms:play-services-wearable:8.4.0'

In the main activity, we implement the GoogleApiClient.ConnectionCallbacks and GoogleApiClient.OnConnectionFailedListener interfaces.

class MainActivity : WearableActivity(), GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
    .
    .
    .
    override fun onConnected(bundle: Bundle?) {
        Log.i("on connected", "here")
    }

    override fun onConnectionSuspended(i: Int) {

    }

    override fun onConnectionFailed(connectionResult: ConnectionResult) {
        Log.i("On conneced", "failed")
    }
}

Since AndroidWear supports multiple Wear devices paired to the same phone, you need to identify which device you want to send a message to. This can be achieved by performing an AsyncTask, called at startup, that gets a list of all connected nodes. (To keep things simple in this example, we only support the user having one Android Wear device paired to the phone.) We then store the ID in a class variable to tell the messageApi which device to send a message to.

   override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        .
        .
        .
        StartWearableActivityTask().execute()
    }

   private inner class StartWearableActivityTask : AsyncTask<Void, Void, Void>() {

        override fun doInBackground(vararg args: Void): Void? {
            getNode()
            return null
        }
    }

    private fun getNode() {
        val nodes = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await()

        if (nodes.nodes.size > 0) {
            messageNodeId = nodes.nodes[0].id
        }
    }

Finally, we use WearableApi.sendMessage to send commands to the phone.

Wearable.MessageApi.sendMessage(mGoogleApiClient, messageNodeId,
                        command, null).setResultCallback { sendMessageResult -> Log.i("Message Sent", sendMessageResult.status.isSuccess.toString()) }

Receiving the Message

In the application on our phone, we now need to register a service that implements the WearableListenerService abstract class.

        <service
           android:name=".WatchDataListenerService"
           android:enabled="true">
                <intent-filter>
                    <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
                </intent-filter>
        </service>

When messages are received, we parse the message path and send it as the command via a broadcast intent to the PurrProgrammingNotificationListenerService, which prompts the LEDs on the t-shirt to blink and change colors.

class WatchDataListenerService : WearableListenerService() {
    val SERVICE_NOTIFICATION = "com.polyglotprogramminginc.purrprogramming.SERVICE_NOTIFICATION"

    override fun onMessageReceived(messageEvent: MessageEvent?) {
        Log.i("message received", messageEvent!!.path)
        super.onMessageReceived(messageEvent)
        val i: Intent = Intent(SERVICE_NOTIFICATION)
        i.putExtra("command", messageEvent!!.path)
        sendBroadcast(i)
    }

}

User Feedback

screen (2)

Once a command is recognized, the user gets feedback similar to the message at the right. Instead of creating a mechanism in our AndroidWear app to prompt the user for another command, we opted for a design that requires the user to close the app via a swipe motion, and reopen it to issue another command. Please note, however, that this is not something that we would recommend for a production app.

You can find the code for our app here.

Posted in Android, Android Wear, Development, Kotlin, MetaWear, Mobile, Wearables Tagged with: , , , ,

Purr Programming Shirt Part 3 – Changing Colors Based On Twitter Notifications

In the previous installment of this blog series, we talked about setting up a service to talk to the MetaWear board. In the app, we flash and change the colors of the LEDs on the t-shirt by sending broadcast intents from the activity to the service. But, wouldn’t it be cool if the colors could change when we receive tweets, likes or mentions on social media? As it turns out, Twitter can send Android notifications that we, in turn, can listen to in the app. Let’s take a look at the details of setting this up.

Screen Shot 2016-04-14 at 2.35.53 AM

Overriding NLServiceReceiver

Previously, we set up a service to override NotificationListenerService. This yields us a method called onNotificationPosted, which gets called whenever a new Android notification is received on the device. The method passes in a StatusBarNotification object. A Twitter notification always has a packageName of com.twitter.android and its .notification.extras includes a field called “android.text” that contains a string with the name of the intended Twitter account. Using this, we’re able to look at the notification and respond to Twitter notifications for specific accounts that we wish to monitor.

For example, if our Twitter client is logged in to both our @rubyfuza and @lgleasain accounts and someone tweets at @rubyfuza, the message will come in with a packageName of “com.twitter.android” and an “android.text” field under .notification.extras with the text “@rubyfuza”.

override fun onNotificationPosted(sbn: StatusBarNotification) {

    val i: Intent = Intent(ACTIVITY_NOTIFICATION);
    i.putExtra("notification_event", "onNotificationPosted :" + sbn.getPackageName() + "\n");

    if (sbn.packageName.equals("com.twitter.android")) {
        // turn into rubyfuza
        Log.i(TAG, "aaaand the text is " + sbn.notification.extras.get("android.text"))

        if (sbn.notification.extras.get("android.text").equals("@rubyfuza")){
 
            Log.i(TAG, "sending ruby intent")
            val i: Intent = Intent(SERVICE_NOTIFICATION)
            i.putExtra("command", "ruby")
            sendBroadcast(i)
         
        }
     }
}

Note that we cannot directly call MetaWear methods in this service because it will throw a threading exception. Instead, we send a broadcast intent with an extra field called “command”, which has the value “ruby”. The broadcast receiver that we talked about before will receive the intent and send a command to flash the LEDs.

In a typical application we’d probably set this up in its own service, but NLServiceReceiver requires application permissions that can be enabled via Settings->Sound&notification->Notification access. When you enable notifications for the app, it starts the service, and when you disable notifications, it ends the service. Normally, you’d add a control to the main application in order to start and stop the service. However, since this is a proof of concept wearables project, we kept them together to ensure that a bug doesn’t cause the service to consume more battery when we’re not using the shirt. You can find a video of what we have so far over here.

Stay tuned for the next post when we’ll talk about adding AndroidWear support to the app.

Posted in Android, Android Notifications, Development, Kotlin, MetaWear, Mobile, Wearables Tagged with: , , , , ,

Purr Programming Shirt Part 2 — Communicating with the MetaWear

In Part 1 of this series, we talked about the hardware for our Purr Programming t-shirt and how we connected all of the components. Now let’s talk about the Android app that controls the shirt’s LEDs.

Our app has the ability to:

  1. Give the user a series of buttons that allows him or her to flash a few different patterns on the NeoPixels, along with flashing the swirls.
  2. Flash the pixels and swirls in distinct patterns if someone tweets at Twitter accounts that are registered to receive notifications on the phone.
  3. Allow the user to use voice control on an Android Wear watch in order to manually launch the patterns when triggered by a tweet.

Screen Shot 2016-04-14 at 2.30.23 AM

Because we want to change LED patterns based on the particular Twitter account targeted, we wanted to handle MetaWear commands in a service so that the app doesn’t need to be in the foreground in order to respond to new Twitter notifications. We also decided to use Kotlin instead of Java. If you’re interested in learning more about Kotlin, this is a great resource.

Setting up the Service

In the AndroidManifest.xml we need to set up a service along with the MetaWear BLE service.

<service android:name="com.mbientlab.metawear.MetaWearBleService" />

<service
   android:name=".PurrProgrammingNotificationListenerService"
   android:label="notifications"
   android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
    <intent-filter>
        <action android:name="android.service.notification.NotificationListenerService" />
    </intent-filter>
</service>

In this instance, we’re calling the service PurrProgrammingNotificationListenerService and it will override NotificationListenerService and ServiceConnection.

class PurrProgrammingNotificationListenerService : NotificationListenerService(), ServiceConnection {

}

Our service is going to register a broadcast receiver that will receive messages from our app activity and smart watch.

internal inner class NLServiceReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.getStringExtra("command").equals("clearall")) {

    }
           
    }

Instead of binding the MetaWear BLE service in Activity, we do it in onCreate for the service.

override fun onCreate() {
    super.onCreate();
    nlservicereciver = NLServiceReceiver();
    val filter: IntentFilter = IntentFilter();
    filter.addAction(SERVICE_NOTIFICATION);
    registerReceiver(nlservicereciver, filter);
    bindService(Intent(this, MetaWearBleService::class.java),
            this, Context.BIND_AUTO_CREATE)
}

Because this is a one-time event, we have hard coded the MAC address and immediately try to connect to the board once the service is bound. With our connection handler, we use logic to automatically reconnect the board if it gets disconnected. If this was a production application, we would add some logic to only connect and stay connected when actively sending commands to the board. That said, this is not efficient, as we found during our tests that, anecdotally, the battery life on a Nexus 5 took about a 20% hit.

private val connectionStateHandler = object : MetaWearBoard.ConnectionStateHandler() {
    override fun failure(status: Int, error: Throwable?) {
        super.failure(status, error)
    }
    override fun disconnected() {
        mwBoard!!.connect()
        Log.i("Purr Programming Service", "disconnected")
    }
    override fun connected() {
        Log.i("Purr Programming Service", "connected")
        if (!connected) {
            Log.i("Main Activity", "Initializing neoPixels")
            connected = true
        }
        val result = mwBoard!!.readRssi()
        result.onComplete(object : AsyncOperation.CompletionHandler<Int>() {
            override fun success(rssi: Int) {
                Log.i("RSSI is ", Integer.toString(rssi))
            }
        })
    }
}

Flashing the Swirls

The swirling LEDs are controlled individually via FETS that are connected to GPIO pins 1 and 2. These are turned on by setting the pin and turned off by clearing it.

private fun turnOnSwirl(pin: Int) {
    gpIO.setDigitalOut(pin.toByte())
}
private fun turnOffSwirl(pin: Int) {
    gpIO.clearDigitalOut(pin.toByte())
}

Setting Up the NeoPixels

First, we need to initialize the strand. In the app, the user needs to manually trigger this.

npModule = mwBoard!!.getModule(NeoPixel::class.java)
npModule.initializeStrand(STRAND, NeoPixel.ColorOrdering.MW_WS2811_GRB,
        NeoPixel.StrandSpeed.SLOW, GPIO_PIN, 8)

Once the strand is initialized, pixels are set with the setPixel command.

npModule.setPixel(STRAND, (pixels[index] + 1).toByte(),
        colors[index]!!.get(RED)!!,
        colors[index]!!.get(GREEN)!!,
        colors[index]!!.get(BLUE)!!)

We then loop through the pixels that we want to set in a method.

private fun setRubyScreen(colorIndex: Int) {
    try {
        val color: Map<String, Byte> = computerScreenRuby[colorIndex]!!
        for (pixel in 2..5) {
            npModule.setPixel(STRAND, pixel.toByte(),
                    color[RED]!!,
                    color[GREEN]!!,
                    color[BLUE]!!)
        }
    } catch(e: Exception) {
        Log.i("problem with ", e.toString())
    }
}

Next, we call these from a timer to get the flashing effects.

private fun startRubyScreen() {
    currentWorkFlow = STATE.RUBY_SCREEN
    object : CountDownTimer(30000, 2000) {
        override public fun onTick(millisUntilFinished: Long) {
            setRubyScreen((rubyIndex++).mod(3))
            setCatEye(1, rubyIndex.mod(5))
            setPaw(rubyIndex.mod(2))
        }
        override public fun onFinish() {
            flashSwirls()
        }
    }.start();
}

The main app is then wired in by sending a broadcast intent. The intent is picked up by the service, which, in turn, executes the requested light pattern on the shirt.

val i: Intent = Intent(SERVICE_NOTIFICATION)
i.putExtra("command", "eyes")
sendBroadcast(i)

The source code for our working application can be found over here. Stay tuned for the next post where we’ll talk about how to listen to notifications in the service.

Posted in Android, Development, Kotlin, MetaWear, Mobile, Wearables Tagged with: , , , ,

Purr Programming Shirt Part 1 — The Hardware

If you’ve met the folks at Polyglot Programming, you know that we love cats, t-shirts, and wearables. Which is, of course, exactly why we recently came up with an idea to combine all three into a project. No, we didn’t decide to create a wearable for a cat (granted, we gave it serious consideration.) Instead, we settled on the next best thing… a Purr Programming t-shirt with LED lights that can be controlled with a MetaWear board. The concept further evolved to make the LEDs flash and change color when someone tweets to us or mentions our hashtags on Twitter.

Screen Shot 2016-03-05 at 1.03.53 AM

Parts Needed

For this project, we chose to use MbientLab’s MetaWear R board, some NeoPixels and printed LEDs from Nth Light.

The complete list of parts consists of:

Laying Out the Circuit

Before sewing and wiring, we laid out the circuit. The MetaWear has onboard voltage and can switch low current loads, but NeoPixels and printed LED strips are bright and can draw more power than the board is designed to handle. For this reason, we opted to wire the NeoPixels directly to the battery and used an I2C line to control the strip. The printed LEDs need to stay in a 3V-range (else they will burn out) and are controlled individually by hooking each one to a GPIO pin. Since a LiPo battery operates above 3V, we added a voltage regulator to that part of the circuit, along with a FET to both of the light strips to control them.

circuit_shirt

Putting it All Together

Sewing requires a certain skill level, but sewing wearables pose unique challenges because you’re creating circuits. Some things to keep in mind:

  • Conductive thread has higher resistance than wire. A seemingly short run can add a noticeable amount of resistance that can affect the circuit’s operation.
  • Make sure that you use low resistance thread and keep circuit runs short.
  • While you can double up your thread in order to lower the amount of resistance, it can make the thread more difficult to work with.
  • It’s a good idea to add backing to your design to add stiffness and prevent your circuits from shorting out

Have a look at our next post where we discuss how to create an Android app to control the shirt. If you want a sneak peek at the code you can find it over here.

Screen Shot 2016-03-05 at 8.23.37 PM

Posted in Android, Development, MetaWear, Mobile, Uncategorized, Wearables Tagged with: , , ,

Measuring Your Heart Rate on Android Using MetaWear

MetaWear Heart Rate Screenshot While the MbientLab MetaWear has a number of sensors built into the board, it also has the ability to interface with a host of analog sensors. With many wearable devices focusing on fitness, you might find yourself needing to integrate a heart rate sensor into your board.

Getting Started

To get started you will need to have a heart rate sensor in addition to a MetaWear board. This post on the MbientLab projects page will give you information on where to find and how to wire up the sensor to your board. Once you are done with this you will need to set up your project to include the MetaWear API, app permissions etc.. Our post on logging thermistor data here goes over the steps to set up your project and connect to the board.

Reading The Data

Now that you are able to connect to the board you will need to read analog data from a GPIO pin. To do that we first need to get the GPIO module.

try {
      gpio = metaWearBoard.getModule(Gpio.class);
    } catch (UnsupportedModuleException e) {
      Log.e("HeartRateSensorFragment", e.toString());
      return false;
    }

For this application we are going to stream the data the GPIO pin to a stream that we will call HEART_RATE and pass in CompletionHandler called gpioHandler that will set up the rest of the chain once the route has been configured.

private final byte GPIO_PIN = 0;
private final String HEART_RATE = "heart_rate";
   
gpio.routeData().fromAnalogIn(GPIO_PIN, Gpio.AnalogReadMode.ADC).stream(HEART_RATE)
                .commit().onComplete(gpioHandler);

Our CompletionHandler is going to do a couple of things in a over-ridden success method. First it is gonig to subscribe to our stream with a data handler that will process reads from the pin (more on that handler later in this post).

result.subscribe(HEART_RATE, dataHandler);

Then it needs to set up a timer to periodically get a reading from the pin.

private final int SCAN_INTERVAL = 50;

try {
     AsyncOperation<Timer.Controller> taskResult = metaWearBoard.getModule(Timer.class).scheduleTask(
        new Timer.Task() {
            @Override
            public void commands() {
                 gpio.readAnalogIn(GPIO_PIN, Gpio.AnalogReadMode.ADC);
            }
        }, SCAN_INTERVAL, false);
     taskResult.onComplete(
        new AsyncOperation.CompletionHandler<Timer.Controller>() {
            @Override
            public void success(Timer.Controller result) {
                  result.start();
            }
          }
        );
    } catch (UnsupportedModuleException e) {
        Log.e("HeartRateSensorFragment", e.toString());
    }

The entire handler ends up looking like this.

    private final AsyncOperation.CompletionHandler<RouteManager> gpioHandler = new AsyncOperation.CompletionHandler<RouteManager>() {
        @Override
        public void success(RouteManager result) {
            result.subscribe(HEART_RATE, dataHandler);
            try {
                AsyncOperation<Timer.Controller> taskResult = metaWearBoard.getModule(Timer.class).scheduleTask(
                        new Timer.Task() {
                            @Override
                            public void commands() {
                                gpio.readAnalogIn(GPIO_PIN, Gpio.AnalogReadMode.ADC);
                            }
                        }, SCAN_INTERVAL, false);
                taskResult.onComplete(
                        new AsyncOperation.CompletionHandler<Timer.Controller>() {
                            @Override
                            public void success(Timer.Controller result) {
                                result.start();
                            }
                        }
                );
            } catch (UnsupportedModuleException e) {
                Log.e("HeartRateSensorFragment", e.toString());
            }
        }

    };

Then our MessageHandler (what we refer to as our dataHandler) will look like this.

    private final RouteManager.MessageHandler dataHandler = new RouteManager.MessageHandler() {
        @Override
        public void process(Message message) {
            short rawValue = message.getData(Short.class);
            Log.i("HeartRateSensorFragment", String.valueOf(rawValue));

            .
            .
            . heart rate calculations
            .
            .

            getActivity().runOnUiThread(
                    new Runnable() {
                        @Override
                        public void run() {
                            bpmView.setText(String.valueOf(bpm));
                        }
                    }
            );
            Log.i("HRSFragment BPM", String.valueOf(bpm));

        }
    };

You can find the code here . Feel free to fork it and make it your own. The application can also be found on the play store here.

Posted in Android, MetaWear, Mobile, Wearables Tagged with: , ,

Logging Thermistor Data With The MetaWear

Screenshot_20151228-234310
The MetaWear board allows you to easily create bluetooth enabled low power wearable devices. Unlike many solutions, as an Android developer you can write applications that program, and interact with the board using a API. We recently created an application using their new Android API to log thermistor temperature readings. The readings are read at one minute intervals and store the values on the board for retrieval from the phone.

The new API simplifies the process significantly from the previous version. So lets take a look at what is needed to get your application going with it.

Setting Things Up

To get started you need to add a reference to the Mbientlab repositories in the project level gradle file.

    repositories {
        jcenter()
        ivy {
            url "http://ivyrep.mbientlab.com"
            layout "gradle"
        }
    }

Then you are going to need to add a dependency to it in the app level file. The compile directive for com.mbientlab.metawear is required. The one for com.mbientlab.bletoolbox is optional but makes it easier to establish bluetooth connections as you will see later on.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.mbientlab:metawear:2.2.0'
    compile 'com.mbientlab.bletoolbox:scanner:0.2.0'
}

The API uses a service to communicate with the board. To use this you will need to add a reference to it in your applications manifest.xml file.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.polyglotprogramminginc.andevcon">

    <application
       android:allowBackup="true"
       android:icon="@mipmap/ic_launcher"
       android:label="@string/app_name"
       android:supportsRtl="true"
       android:theme="@style/AppTheme">

        <service android:name="com.mbientlab.metawear.MetaWearBleService" />
        <activity
           android:name=".MainActivity"
           android:label="@string/app_name"
           android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Next you will need to bind the service to your application using an intent in the onCreate method of your Activity.

        getApplicationContext().bindService(new Intent(this, MetaWearBleService.class),
                this, Context.BIND_AUTO_CREATE);

Then you will need to get a reference to the binder once the service is connected by implementing ServiceConnection and over-riding the onServiceConnected method.

   @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        ///< Get a reference to the MetaWear service from the binder
        mwBinder = (MetaWearBleService.LocalBinder) service;
        Log.i("Main Activity", "Service Connected");
    }

Connecting To The Board

To make finding and connecting to our board easier we are using the BleToolbox scanner which you can find here. For our example we created scanner DialogFragment that has a reference to the BleToolbox in the layout file.

     <fragment xmlns:tools="http://schemas.android.com/tools" android:id="@+id/metawear_blescanner_popup_fragment"
       android:name="com.mbientlab.bletoolbox.scanner.BleScannerFragment"
       tools:layout="@layout/blescan_device_list" android:layout_width="match_parent"
       android:layout_height="match_parent" />

To scan for a board we display our fragment.

   if (mwScannerFragment == null) {
        mwScannerFragment = new ScannerFragment();
        mwScannerFragment.show(getFragmentManager(), "metawear_scanner_fragment");
   } else {
        mwScannerFragment.show(getFragmentManager(), "metawear_scanner_fragment");
   }

Then we implement a few callbacks to manage the scanner settings and to connect the board once we have finished scanning.

    /**
     * callbacks for Bluetooth device scan
     */

    @Override
    public void onDeviceSelected(BluetoothDevice device) {
        connect(device);
        Fragment metawearBlescannerPopup = getFragmentManager().findFragmentById(R.id.metawear_blescanner_popup_fragment);
        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        fragmentTransaction.remove(metawearBlescannerPopup);
        fragmentTransaction.commit();
        mwScannerFragment.dismiss();
        Toast.makeText(this, String.format(Locale.US, "Selected device: %s",
                device.getAddress()), Toast.LENGTH_LONG).show();
    }

    @Override
    public UUID[] getFilterServiceUuids() {
        ///< Only return MetaWear boards in the scan
        return new UUID[]{UUID.fromString("326a9000-85cb-9195-d9dd-464cfbbae75a")};
    }

    @Override
    public long getScanDuration() {
        ///< Scan for 10000ms (10 seconds)
        return 10000;
    }

These need to be implemented in the activity that initiated the fragment. This activity also needs to implement BleScannerFragment.ScannerCommunicationBus. The getFilterServiceUuids tells the fragment to only scan for boards with the specified UUID values. In our example we are only scanning for MetaWear boards. The getScanDuration tells it how long to scan for devices and the onDeviceSelected is called when you select a device. This hands you a BluetoothDevice object that you can use to connect to the board.

Connecting is then a matter of getting a reference to the board by passing in a reference to your BluetoothDevice, setting up a connectionStateHandler for callbacks when the board is connected/disconnected and then calling connect() on the board.

    /**
     * Connection callbacks
     */

    private MetaWearBoard.ConnectionStateHandler connectionStateHandler = new MetaWearBoard.ConnectionStateHandler() {
        @Override
        public void connected() {
            Log.i("Metawear Controller", "Device Connected");
            runOnUiThread(new Runnable() {
                              @Override
                              public void run() {
                                  DeviceConfirmationFragment deviceConfirmationFragment = new DeviceConfirmationFragment();
                                  deviceConfirmationFragment.flashDeviceLight(mwBoard, getFragmentManager());

                                  Toast.makeText(getApplicationContext(), R.string.toast_connected, Toast.LENGTH_SHORT).show();
                              }
                          }
            );

        }

        @Override
        public void disconnected() {
            Log.i("Metawear Controler", "Device Disconnected");
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), R.string.toast_disconnected, Toast.LENGTH_SHORT).show();
                }
            });

        }
    };

    private void connect(BluetoothDevice metaWearDevice){
        mwBoard = mwBinder.getMetaWearBoard(metaWearDevice);
        mwBoard.setConnectionStateHandler(connectionStateHandler);
        mwBoard.connect();
    }

Reading And Logging Data

The MetaWear Android API lets you access the sensors and logging with modules. First we need to get a reference to the thermistor module and set a source for it.

        try {
            tempModule = mwBoard.getModule(MultiChannelTemperature.class);
        } catch (UnsupportedModuleException e){
            Log.e("Thermistor Fragment", e.toString());
            return false;
        }

        List<MultiChannelTemperature.Source> tempSources= tempModule.getSources();
        MultiChannelTemperature.Source tempSource = tempSources.get(MultiChannelTemperature.MetaWearRChannel.NRF_DIE);

Each module has the ability to route data via a DSL. In our example we are going to route our data from our MultiChannelTemperature module to a log with a id of “log_stream” and when the route has successfully been registered set up the rest of the process.

tempModule.routeData().fromSource(tempSource).log("log_stream")
        .commit().onComplete(temperatureHandler);

In our callback we will set up a timer that reads the temperature at a set interval and start it.

    private final AsyncOperation.CompletionHandler<RouteManager> temperatureHandler = new AsyncOperation.CompletionHandler<RouteManager>() {
        @Override
        public void success(RouteManager result) {
            result.setLogMessageHandler("log_stream", loggingMessageHandler);

            // Read temperature from the NRF soc chip
            try {
                AsyncOperation<Timer.Controller> taskResult = mwBoard.getModule(Timer.class)
                        .scheduleTask(new Timer.Task() {
                            @Override
                            public void commands() {
                                tempModule.readTemperature(tempModule.getSources().get(MultiChannelTemperature.MetaWearRChannel.NRF_DIE));
                            }
                        }, TIME_DELAY_PERIOD, false);
                taskResult.onComplete(new AsyncOperation.CompletionHandler<Timer.Controller>() {
                    @Override
                    public void success(Timer.Controller result) {
                        // start executing the task
                        result.start();
                    }
                });
            }catch (UnsupportedModuleException e){
                Log.e("Temperature Fragment", e.toString());
            }

        }
    };

We are also setting a log message handler. This is simply a callback that processes each log entry as it comes from the board. Our implementation logs the entry and saves it to a SqlLite Table.

   private final RouteManager.MessageHandler loggingMessageHandler =  new RouteManager.MessageHandler() {
                @Override
                public void process(Message msg) {
                    Log.i("MainActivity", String.format("Ext thermistor: %.3fC",

                            msg.getData(Float.class)));
                    java.sql.Date date = new java.sql.Date(msg.getTimestamp().getTimeInMillis());
                    TemperatureSample sample = new TemperatureSample(date,  msg.getData(Float.class).longValue(), mwBoard.getMacAddress());
                    sample.save();
                }
            };

The final part is to call downloadLog on the loggingModule when we want to retrieve the logs from the board.

        loggingModule.downloadLog((float)0.1, new Logging.DownloadHandler() {
            @Override
            public void onProgressUpdate(int nEntriesLeft, int totalEntries) {
                Log.i("Thermistor", String.format("Progress= %d / %d", nEntriesLeft,
                        totalEntries));
                //mwController.waitToClose(false);
                thermistorCallback.totalDownloadEntries(totalEntries);
                thermistorCallback.downloadProgress(totalEntries - nEntriesLeft);
                if(nEntriesLeft == 0) {
                    GraphFragment graphFragment = thermistorCallback.getGraphFragment();
                    graphFragment.updateGraph();
                    thermistorCallback.downloadFinished();
                }
            }
        });

This method takes a callback that will give you a progress update on the data download along with a float indicating the percentage interval to give you a status update. For example if you set this value at .10 and have 100 entries to download, it will call this method each time 10 records have been transferred. BLE is a much slower than standard Bluetooth, so a large number of data points can easily take more than a minute to transfer to your Android device. In the code above we are using this to trigger a callback that updates the UI on the download progress.

Persisting Board State Between sessions

Now that we have our board logging the temperature and an app that can download it we need to make sure we can persist the references to our logging when our app pauses/stops and then restarts. We can persist the majority of the app state from the MetaWearBoard object using the serializeState method. In our application we did this in the onSaveInstanceState lifecycle method of our activity.

    @Override
    protected void onSaveInstanceState(Bundle state) {
        super.onSaveInstanceState(state);
        if (mwBoard != null) {
            mwBoard.disconnect();
            state.putByteArray(mwBoard.getMacAddress(), mwBoard.serializeState());
        }
    }

Our logging callback will not be serialized in the serializeState method. This becomes a problem when we restore our app state because we need to have a reference to the routeManager so that we can add our logging callback when restarting the app. To fix this we will need to persist the RouteManager id in our temperature handler success callback.

bundle.putInt(mwBoard.getMacAddress() + "_log_id", result.id());

Now when we restore our app state we can deserialize the state for our board.

            String boardState = bundleState.getString(bleMacAddress, null);
            if (boardState != null) {
                mwBoard.deserializeState(boardState.getBytes());
                Log.i("connect device", "Found instance state");
            }

After deserializing we will need to get the route manager that we had initially used for our logs via the RouteManager id and add the logging message handler to it.

        RouteManager route = mwBoard.getRouteManager(sharedPreferences.getInt(mwBoard.getMacAddress() + "_log_id", 0));
        route.setLogMessageHandler("log_stream", loggingMessageHandler);

You can see a working application that uses this here. All of the code is available on Github over here so that you can make it your own.

Posted in Android, MetaWear, Mobile, Wearables Tagged with: , ,

Using MetaWear with Node.js

Back in October 2014 I attended a talk by Erica Stanley called “Open Source and the Internet of Things” at the All Things Open conference in Raleigh. We were just starting to do wearable development beyond Android Wear and Google Glass and had been playing with some prototyping boards. At the time, working with boards that included any kind of wireless chipset posed a challenge: You needed to write code that could run on the board whilst developing a protocol to communicate between the two devices. In addition, most boards, albeit smaller than an Arduino, were still fairly sizable if you were trying to develop a wearable type of application.
IMG_20151210_001737
In Erica’s talk she mentioned a board called the MetaWear that seemed perfect for wearable applications. It’s small and the base unit has built-in Bluetooth radio, an accelerometer, temperature sensor, LED, switch, LiPo charging circuit, haptic driver, 4 digital/analog pins, 4 digital pins, GPIO support and can even act as a beacon. Also, you can simply use their Android or iOS API to program and read data from the board without having to write C++ sketches. All of that for a mere $45! Before the end of the talk, I had ordered a MetaWear. Soon thereafter, I began using it for projects and started doing conference talks that featured the board. MetaWear has since expanded their offerings to include boards with additional sensors.

Going Beyond iOS and Android

Most wearable devices will likely interface with an iOS or Android-based device, but developers doing Node.js and Windows development didn’t always have an easy way to communicate with, and use, these devices. That recently changed with the release of the C++ API, a C# wrapper, and Node.js NPM package. We’ve also been working on a Cordova plugin. The cool thing about the Node and Cordova efforts are that they are driven by enthusiasts in the community.

Getting Started

We have personally tested the Node.js package on MacOS, Ubuntu (running under Crouton in Chrome OS), and on a Raspberry Pi. It works great on all three platforms with a few minor tweaks. Note, however, that MetaWear uses Bluetooth 4.0 to communicate with other devices, so make sure that your device supports Bluetooth 4.0.

Mac OS

I tested the MetaWear board on a Mac that has Bluetooth 4.0 support. In theory, it would be possible to use a third party adapter, but you may need to tweak some settings. On a standard Mac is it really easy, assuming that you have a recent version of Node.

git clone git@github.com:brainexe/node-metawear.git
cd node-metawear
npm install
DEBUG="noble-device" node examples/all.js

Running this code snippet will clone the repo, install the Node modules and create a test app called all.js. If you have a MetaWear that is running (but not currently connected to another device), and within range of your Mac, you can expect to see the light on it start to flash and some sensor output on your terminal. If it doesn’t immediately work correctly, you may need to close and restart Node.

Ubuntu in Crouton under Chrome OS

Again, I conducted the test with a Chromebook Pixel LS that has built-in Bluetooth 4.0 support. It should, however, work on other machines.

sudo setcap cap_net_raw+eip $(eval readlink -f `which node`)
git clone git@github.com:brainexe/node-metawear.git
cd node-metawear
npm install
export DEBUG="noble-device"
host-dbus node examples/all.js

The main difference here is that you’ll need to run Node through host-dbus, since it’s accessing the Bluetooth adapter attached through Chrome OS.

Raspberry Pi Running Raspbien

Finally, I tested the board using a Pi Zero with a WiFi and BLE dongle. I opted to clone the Node repo and build it on the platform (yes, it does take a while). Once that was done, the rest was easy.

sudo setcap cap_net_raw+eip $(eval readlink -f `which node`)
git clone git@github.com:brainexe/node-metawear.git
cd node-metawear
npm install
export DEBUG="noble-device"
node examples/all.js

Personally, I consider Pi Zero to be the most interesting use for a Node.js integration with Metawear. Unlike previous Pi releases, it has a lower power consumption profile and a small size, which, in theory, might be useful when creating wearable devices that interact with MetaWear.

In Summary

IMG_20151210_034705

Support for Node.js is still somewhat limited and it would require adding lots of additional features in order to go beyond basic experimentation. As with any open source project, if you want to see a specific feature implemented, you can always do it yourself and submit it as a pull request. If you’re interested in using Cordova/Phone Gap to interact with your MetaWear, be sure to look out for an upcoming blog post and introduction to using our library.

Posted in ChromeOS, Development, Javascript, MetaWear, Node.js, Raspberry Pi, Ubuntu, Wearables Tagged with: , , , , ,

Adventures in 3D Printing

IMG_20151209_130801
About a year ago we decided to get a 3D printer. Although there are lots of pre-made options available, it’s much less expensive to get a RepRap Prusa I3 kit and build one yourself. The Prusa I3 is an open source 3D printer design that allows anybody to make components for it, and the community members, in turn, contribute plans for print heads, cases etc. It’s a pretty neat concept: The main controller is an Arduino mega board, the software is open source, and you can order the printer preassembled or as a DIY kit. This, of course, means that the printer can actually print parts for another printer, which can then go on to print parts for another, and so on.

We opted to put it together ourselves. The good news is that we learned a lot about 3D printing. The bad news is that it took a LOT of time. Building the kit, installing the software, and calibrating the printer took approximately 80 hours. Now, in fairness, some of that effort was also dedicated toward getting familiar with 3D printing in general.
IMG_20151209_130504
Once we had the printer up and running, the first project was to create some extra parts for the printer. We started without cable guides, so we went to ThingVerse, found a design and voila! Next, we used ABS plastic to print a case for the controller boards as well as one for the power supply. Along the way, we learned a few valuable lessons.

Firstly, you need to buy a special ramps shield for your Arduino to interface with the various motors and sensors on the printer. Die-hard enthusiasts may opt to solder components to their own board, but we decided to buy a pre-made one and it worked great… well, initially. Because we were printing ABS, we needed to have a heated print bed, which is controlled via this board. After a week, the bed stopped working and upon closer inspection we noticed that the terminal for the heater had turned black. IMG_20151209_164603

A component on this board called a MOSFET was drawing a lot of current through it, and it obviously became very hot. It really should have had a heat sink on it, but the instructions online were not clear about this and the board didn’t come with one installed. So we ordered a new ramps and continued to print more parts for the printer. Before the cable chains were done, we had already had a wire failure on the head bed from repeated flexing. So what to print next?

How About a Full Size Chair?

Your first question might be: “How can you do that with a small desktop printer?” The answer comes from a group called Bits and Parts who created a open source design for a chair constructed from 85 individual puzzle pieces that interlock together.
IMG_20151126_200208

It looked like a great way to use the printer for something utilitarian. Albeit reasonably simple, in retrospect it was a very time consuming project, because it required printing plastic supports for overhangs. Each of these took between 30 minutes and an hour to cut and file.

Other Printer Problems Along the Way

Like most DIY projects created from kits, we ran into a few issues with components. First, the cheap aluminum nozzle developed a second hole that rendered it unusable. We learned about a small shop in Pennsylvania that sells brass ones. The store’s proprietor is actually the designer of these heads, so it was worth the extra money spent. After installing it, we also needed to add a different thermistor because the original one differs from the one in the head. Things went great until the thermistor wire to the print nozzle broke (due to a bad cable routing that flexes too much) and the plastic assembly in the head melted. Again, we ordered a new part from the Pennsylvania shop, rewired the thermistor, did some calibration, and continued to print puzzle pieces when we had some spare time.
FIN1FKGHCAXRZX5.MEDIUM
One day, however, we tried to turn on the printer and none of the components worked. After a lot of digging, we discovered that the kit’s cheap power supply had died. We replaced it with a higher-rated PC power supply. As a nice side bonus, it also reduced some of the printer noise.

Putting It All Together

Finally, after many hours hours of printing, sanding, finishing some broomsticks as chair legs, and some minor glueing and tweaking, we ended up with a complete chair. It looks great in the living room, and yes, you can sit in it!

IMG_20151127_004256IMG_20151209_130615 (1)

Posted in 3d printing, Arduino, Development, Maker, RepRap Tagged with: , , , ,

Adding Gradients to Android Graphs with MPAndroidChart and DecoView

Recently, we worked on a project that required us to add graphs with gradients to an Android application. Below is an example of one such graph that we needed to create:

Android graphs with gradients

There are lots of examples online that show how to create graphs with gradated backgrounds, but we quickly discovered that it’s nearly impossible to find information on how to incorporate a gradient effect as part of the axis, trend line, or doughnut. We finally figured out how to do it, so let’s go over the steps and it’ll hopefully make things easier for you if you’d like to try a similar project.

MPAndroidChart

Our go-to tool for graphing in Android applications is typically MPAndroidChart. It’s a versatile and powerful open source charting library that’s fairly straight forward to use. (The line graph shown in our screenshot was created with it.) Now, say we want to create a chart that shows how many minutes someone is active each hour of the day. The MPAndroidChart documentation found here offers good instructions on setting up the main parts of the graph. But how do you add vertical shading to the data?

If you delve deeper into the library, you’ll discover that the line chart uses Android’s Paint to render its lines. Among other things, you can set a shader in a Paint object to paint everything using that specific shader. To learn more about Android graphics and shaders, take a look at this post. Armed with this knowledge, we can now add a shader to the Paint object for our graph, which will give us a line gradient.

Paint paint = lineChart.getRenderer().getPaintRender();
int height = 200;

LinearGradient linGrad = new LinearGradient(0, 0, 0, height,
       getResources().getColor(R.color.lineGraphHigh),
       getResources().getColor(R.color.lineGraphLow),
       Shader.TileMode.REPEAT);
       paint.setShader(linGrad);

This gets us most of what we need. The chart renders, and if our graph has a height of 200px, it’ll also produce a gradient that changes from dark blue (our lineGraphLow color) to yellow (our lineGraphHigh color). However, one problem is that most Android applications need to adjust the size it objects on the screen to account for various screen sizes. In our test app, we used a weightSum along with layout_weights in a LinearLayout object. A fixed shading height would therefore result in a repeated pattern if the graph height extends beyond 200 pixels. In order to solve this, we need to obtain the height of our graph.

int height = lineChart.getHeight();

By adding this code snippet to a call that’s part of onStart, you’ll end up with a height of zero and no gradient.

Screen Shot 2015-12-09 at 12.51.55 AM

So, we need to populate our chart data and get the size after the view has rendered, which can be done via the POST method on the view.

    @Override
    public void onStart(){
        super.onStart();
        getView().post(new Runnable() {
            @Override
            public void run() {
                drawLineGraph();
            }
        });
    }
    /**
     *  The code for creating the line graph
     */

    private void drawLineGraph(){
        setupLineChart();

        // Get the paint renderer to create the line shading.
        Paint paint = lineChart.getRenderer().getPaintRender();
        int height = lineChart.getHeight();

        LinearGradient linGrad = new LinearGradient(0, 0, 0, height,
                getResources().getColor(R.color.lineGraphHigh),
                getResources().getColor(R.color.lineGraphLow),
                Shader.TileMode.REPEAT);
        paint.setShader(linGrad);

        setupLineChartData();

        // Don't forget to refresh the drawing
        lineChart.invalidate();
    }

Now we have a dynamically resizable graph that gives us a line with shading that changes from dark blue to yellow!

DecoView

After accomplishing part one, we also wanted to add a shaded arc graph to another part of our application. Unfortunately, MPAndroidChart couldn’t do what we wanted, so we turned to DecoView. DecoView is a focused library that allows you to create animated circular graphs. Alas, again, the documentation didn’t clearly explain how to add a gradient to a graph.

For DecoView, you add a series to define arcs for a graph. The series are added via a Builder object that can take either one or two colors in the constructor. All of the examples only show one color, but if you add in a second, you actually end up with a gradient. Then you simply add in a range that specifies the values that correspond to the starting and ending color.

 int seriesIndex = decoView.addSeries(
       new SeriesItem.Builder(getResources().getColor(R.color.lineGraphLow),
       getResources().getColor(R.color.lineGraphHigh))
                .setRange(0, stepGoal, 0)
                .setInitialVisibility(false)
                .setLineWidth(getDimension(18f))
                .build());

The end result is a arc graph with a gradient that changes from blue to yellow. You can find documentation for DecoView here , and an example app with both of these graphs over here.

Posted in analytics, Android, Data Science, Development, Mobile Tagged with: , , , , ,