Although this is a tutorial of how I did it, I think it would be appropriate to give a review of MIT App Inventor at the same time (as it was my first time using it). Keep this is mind as you will always find a mix of both while reading this post. I stumbled upon MIT App Inventor here on Hackster.io while reading this blog. It caught my attention right away as just that weekend I was creating an app to interface with my Wahoo Tickr. Don't get me wrong, it's not like I haven't used BLE with a mobile app before. I have created some Bluetooth Low Energy apps before in Xamarin with the LightBlue Bean from Punch Through. What really got me excited to get started was the drag and drop component. As a previous user of platforms such as Matlab Simulink, Node-Red and Lego NXT programming, drag and drop IS MY JAM!! I work eight hours a day with VB.Net and Matlab, and my designated coding free time (yes thats a real thing) goes to Python and Xamarin. So sometimes its very soothing to just not have to deal with all that...ssstuff, you know? I had already sunk a few hours into my Xamarin implementation when I decided to pick up the development speed and use the MIT App Inventor. Now lets dive right into it.
The first and probably most important step of this project was finding the Service UUID and Characteristic UUID to get the heart rate data from the Wahoo Tickr. In a previous blog (here) I wrote about how to scan for BLE devices and see their services and characteristics using Monkey.Robotics BLE library for Xamarin. Using this I found that the Service UUID was "0000180d-0000-1000-8000-00805f9b34fb" and the Characteristic UUID was "00002a37-0000-1000-8000-00805f9b34fb". Of course to verify we could look at actual specifications, if you're into that sorta thing. Through some research I found that there is a pretty standard protocol to how Bluetooth HRMs send their data. This is why you're able to connect many different types to the same apps such as Endomondo. The specifications I am talking about can be found here. Within the specification you can see all the bytes within the packet along with their definitions. Upon reading the specs one would notice the most important byte for this project is the second one (as it is the one that contains the heart rate monitor data). Now that we know the Service UUID, Characteristic UUID and the the byte we would like to access we can move on to drag and drop land.
Now its time to head over to http://appinventor.mit.edu/explore and click "Create Apps" in the top right corner. Login with your email account and try to explore a bit! I highly recommend following some of the tutorials here first before continuing with this one. These tutorials show you how to connect your phone to the website for development (wireless development?! Who needs hoverboards) as well as some more basic tutorials to get you more comfortable with the software. Take your time going through them, don't worry I'll wait.
Alright now we're back to the good stuff.
- Download the ble_hrm_app.aia thats in the attachments of this blog.
- Go to the MIT App Inventor Interface and navigate to the top right corner. Click My Projects>Import project (.aia) from my computer ...
- From here browse your computer for the .aia file you downloaded from this blog.
- Now go to the Extensions tab on the left Palette. If you do not see BluetoothLE within the extensions follow the next step!
- Download the .aix file from the attachments in this blog. Click on "Import Extension", choose the destination from your computer and locate the downlaoded .aix file.
- Now let's break down the code a bit. I would like to give credit to this blog for some of the code samples that I am about to explain.
- When the designer initializes the BluetoothLE1 begins to scan for devices. We have also set up a global variable "device" that will hold the value for the selected bluetooth device later.
- On BluetoothLE1.DeviceFound the ListPicker will be updated with the all the found devices. Every time a new device is found it will be added to the ListPicker
- The user can click on the ListPicker and select a device (in this case we select the Wahoo Tickr that should be present within the ListPicker)
- In the above image you can see how the Wahoo Tickr will show up in the ListPicker
- Once the BluetoothLE1 has officially connected to the Wahoo HRM we can enable the Clock. The clock plays an important role on updating the user with the current heart rate value coming in.
- In this block we use the knowledge researched from before to get the value from the connected device. We know the service uuid and characteristic uuid, and we know that the heart rate value is in the second byte (which in this case is byte 1 because we count from 0) therefore the intOffset is 1. This happens every time Clock1.Timer hits its cycle which in this case is every 1000 miliseconds or 1 second (chosen within the designer, click on Clock1 to see more details).
- Now the purpose of the app I made is to be able to see the average and peak Beats per minute (BPM) during a set. So for this implementation the user must start and stop the set manually. Likewise there is a "Next Workout" button to keep track of what exercises you were doing. The blocks on the right are global variables used during the process of finding the average and peak BPMs for each set. "hr_list" holds the current list of heart rate values, "avg_hr_list" holds the list of outputs that will be displayed to the user containing the exercise number, set number, average heart rate and peak heart rate within a set. "is_in_set" is a variable that is only on when the user has previously clicked "Start Set". One will notice in the BluetoothLE1.IntValueChanged that the values being read from the Wahoo Tickr only get stored within "hr_list" when the user is in their set. This way you make sure you're not storing data while they're resting.
- The last block I will discuss is for the button that controls stopping and staring a set. As mentioned before when you start the set the "is_in_set" variable is set to true and values read are stored. Once the set is stopped a few operations must be done to calculate peak and average BPMs. A for loop is used to go through all the values collected by the "hr_list" during the set. The values are summed and then divided by the size of the data list to get an average BPM. Then to find the peak we just do a simple check to see if the current value being iterated is larger than the previously known peak value. If so we swap them. Then we use a "join" to collect all the data together and we feed to "avg_hr_list" that is used to update the ListView.
- This really is the gist of it. After successfully connecting and getting a few sets in the app will start to look something like this:
Although easily fixable, as of right now there is a bug that prevents you from scanning for devices when the your app is built as an .APK. This is happening because the developers of the extension did not add the Bluetooth permission, whoops! To be able to scan and see your beautiful app flourish simply go to the Palette and select one of the Bluetooth components under Connectivity (either BluetoothClient or BluetoothServer as shown below).
Drag one of these components into the designer to add it to the project. You do not actually have to use this component, it is just there so that when the app builds it will include the component's permissions. One of which being, you guessed it, bluetooth permissions. More info can be found here.
By the end of this tutorial you should have a better understanding of how MIT App Inventor works and also how BluetoothLE HRMs work. I truly believe the MIT App Inventor is best for helping the user understand what they're doing. When programming in more complicated languages it is sometimes easy to forget the point of what you're coding. Drag and Drop allows you to see those key words that helps you make the connection between code and application. However, simplicity comes with its drawbacks. I found that the blocks start to become very large once you start doing pretty trivial things (such as for loops and combining text). This would become a huge issue when you have to combine your code with issues from professional softwares such as input validation. Likewise, the choices you have for designs and layouts are very slim at the moment. For the reasons above I would like to conclude that the MIT App Launcher is a very great software and I definitely see myself using in the future to create quick apps for personal use or understanding new concepts. Heck, I know there is a lot of hardware guys out there playing with their Arduinos and Raspberry Pis dreaming for the day they can easily connect to their devices without having to learn Java, Objective-C, Swift, or C#. I strongly believe this would be perfect for them. However, where I see it being most powerful is in prototyping. If you're creating an idea for an app or eve an idea for a device and theres only three days left until the Innovative Design Contest or Entrepreneur presentation Contest, theres no way you'll make it on time using conventional mobile development methods. You could work super hard on your presentation but people want to see functionality and results. I suggest your time whipping up a demo app in MIT App Inventor, enough to get the judges attention and give the audience a better understanding of what your product will do. The best part is if they don't like your idea, you didn't spend months developing a useless software! Well thats it for this tutorial. I hope you enjoyed it. Please leave any comments or questions below. Thank you.