My life with Android :-)

Friday, December 19, 2014

Parsing BLE advertisement packets

Ever since I created the Gas Sensor demo (post here, video here, presentation here), I had the feeling of an unfinished business. That demo sent the sensor data in BLE advertisement packets so the client never connected to the sensor but received data from the sensor in a broadcast-like fashion. The implementation looked like this:

        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
            String deviceName = device.getName();
...
                int addDataOffs = deviceName.length() + 16;
                int siteid = ((int)scanRecord[addDataOffs]) & 0xFF;
                int ad1 = ((int)scanRecord[addDataOffs+1]) & 0xFF;

This was a quick & dirty solution that remained there from my earliest prototypes. It sort of assumes that the structure of the BLE advertisement packet is fixed so the sensor data can always be found at fixed locations of the advertisement packet. This does not have to be the case, Bluetooth 4.0 Core Specification, Part C, Appendix C (or Core Specification Supplement in case of 4.2 version) describes, how the fields of the advertisement packets look like. It just so happens that with the given version of the RFDuino BLE module, the Manufacturer Specific Data field where RFDuino puts the user data for the advertisement packet can always be found at a specific location.

The proper way is of course to parse this data format according to the referred appendix of the specification and in this post I will show you how I implemented it.

The example programs are attached to the end of this post. You have to be logged to Sfonge site to access them.

Let's see first the BLEScan project. The parser code is under the hu.uw.pallergabor.ble.adparser package. Then you just give the scanRecord array to AdParser's parseAdData method like this:

            ArrayList<AdElement> ads = AdParser.parseAdData(scanRecord);

and then you get an array of objects, each describing an element in the scan record. These objects can also produce printable representation like this:



Now let's see the revised GasSensorDemo project, how the gas sensor measurement is properly parsed out of the scan record. First we parse the scan packet fields:

                ArrayList<AdElement> ads = AdParser.parseAdData(scanRecord);

Then we look for a TypeManufacturerData element which corresponds to a Manufacturer Specific Data field in BLE. We make an extra check to make sure that the manufacturer field in the Manufacturer Specific Data is 0x0000 because RFDuino always creates a Manufacturer Specific Data field like that if the application programmer specifies additional advertisement data.

                    AdElement e = ads.get(i);
                    if( e instanceof TypeManufacturerData ) {
                        TypeManufacturerData em = (TypeManufacturerData)e;
                        if( em.getManufacturer() == 0x0000) {


It would be tempting to use a custom manufacturer field or better, a Service Data field. But then we run into another limitation of RFDuino because RFDuino with its default firmware is only able to create advertisement packets like in the previous example. This is not bad because it allows the programmer to achieve quick success but later on, we will need more flexibility and that will need another BLE module.

Friday, November 21, 2014

Motor boat control with Bluetooth Low Energy

 My previous post about Bluetooth Low Energy applications with RFDuino and Android presented a connectionless gas sensor. That prototype was based solely on BLE advertisements, no connection was built between the scanner device (Android phone or tablet) and the sensor. While this connection-less operation is advantageous for sensors that just broadcast their measurement data, more complex scenarios that e.g. require authentication or build a communication session cannot be implemented in this model. The prototype I am going to present in this post demonstrates connection-oriented operation between RFDuino and an Android application.

Watch this video to see what the application is about.



The story behind this motor boat project is that I bought this RC-controlled model boat while I worked in the UK. But when we moved back to Hungary, I lost the RC controller. So the boat had been unused for years until I realized how great it would be to use an Android device as a controller. Hence I quickly integrated the RFDuino with the motor boat's original control circuitry and wrote the necessary software. As you can see in the video, it has quite respectable range even though I did not dare go into the October water of Lake Balaton where the second part of the video was shot (water temperature: some 10 degrees centigrade).

First about the "hardware". I did not have the circuit schema of the original RC controller in the boat so I had to experiment a bit. By following the motors' cables I quickly found two three-legged stocky elements that looked like switching transistors (although the labels on them were not readable after all those years in service). I removed one end of the resistors that I thought connected the base of these transistors to the rest of the RC control circuit and tried out, how much current is needed to switch on the motors. To my pleasant surprise, 1 mA current was enough so I rather believe that these are actually not transistors but power switching ICs. Anyway, RFDuino outputs can provide 1 mA switching current so I just connected the other end of those removed resistors to two spare RFDuino I/O ports. Lo and behold, it worked. If RFDuino raises any of these pin to 1, the respective motor starts. One minor additional problem was about the power supply of RFDuino. The motor boat employs an 7.2 Volt battery and RFDuino needs 3.3 V. I added an LM1117-3.3V power regulator circuit between the battery and RFDuino and the "hardware" was ready.



Do you know about BLE concepts like service and characteristics? If not, please read this presentation for a quick introduction. In short: BLE services (also called GATT profiles) are composed of characteristics which are key-value pairs decorated by meta-information that the BLE specification calls descriptors. RFDuino with its default firmware is not able to implement any standard GATT profile except for its own custom GATT profile. This is a major disadvantage in product-level development but makes RFDuino code super-easy because the programmer does not have to deal with BLE details. In the RFDuino custom service, a "read" and a "write" characteristic is defined. Whatever the client (in our case, the Android application) writes into the "write" characteristic appears for the RFDuino code as incoming data callback. If the RFDuino code calls the RFduinoBLE.send(v) method, the data appears in the "read" characteristic. The Android client can register a callback for data manipulations of the "read" characteristic so it will receive callbacks when RFDuino code invokes the RFduinoBLE.send() method. There are additional callbacks for service connections and disconnections.

You can download the Android project and the RFDuino source at the end of this post. You have to be logged to the Sfonge site to access these.

First about the RFDuino code.  Beside the familiar setup() and loop() functions, you will see three functions characteristic to RFDuino. RFduinoBLE_onConnect() is called if a client connects to the RFDuino BLE service, RFduinoBLE_onDisconnect() is called on disconnection and RFduinoBLE_onReceive() is called when there is incoming data. There is only one complication in the code that requires explanation: this is a powerful motorboat and it can go out of BLE radio range very quickly. In the early versions the boat became uncontrollable in this case meaning that it just continued with the last command received. That was not a nice feature so I implemented a heartbeat message feature which is sent in every 5 second. The loop() method starts by sending the heartbeat to the client and goes to sleep. It wakes up after 5 seconds and if it finds that the client did not send back the heartbeat, it stops the motors. Otherwise the client just sends a bit mask about which motors to stop or start and the RFDuino just responds with the same mask informing the client that the motors were indeed started or stopped. This means that the arrows on the user interface showing which motors are running represent the actual state of the boat which is advantageous if something goes wrong.

Then about the Android side. The code starts by discovering the device. Once the device is discovered, we connect to the device with the connectGatt() method then discover its services with gatt.discoverServices() method. Once the service discovery callback arrives, we retrieve the RFDuino service (getService(), we expect this custom service) and obtain the characteristic handles (getCharacteristic()). We use the "read" characteristic's client configuration descriptor to enable notifications from the RFDuino server to the Android client so that we get a callback when the RFDuino side sends something to us.

Disconnection is worth detailing because there's an RFDuino speciality here. Normally, one can just disconnect from the service with the disconnect() method invocation. RFDuino however is left in a limbo state in this case: the BLE session is disconnected but the RFDuino application does not receive a callback and cannot accept a new connection request. The "disconnect" characteristic has to be written to (the value does not matter) for the RFDuino server to properly disconnect.

Friday, October 3, 2014

Award for our Android Gas Sensor

I just got a mail that our gas sensor entry (a gas sensor with Bluetooth Low Energy connectivity and the associated Android application) has just won 3rd place on the We Know RFDuino contest. Thanks to everyone who viewed our video and thus helped us to compete successfully! Meanwhile the source code of the prototype was made open source so you may want to check out that too!

Monday, September 29, 2014

Gas sensor prototype explained

The "We know RFDuino" contest has not ended yet but its end is sufficiently close so that I can explain our prototype application. Our entry is a Bluetooth Low Energy-connected gas sensor and it is presented in the video below. Make sure that you watch it, you help us win the competition.



The prototype demonstrates a unique capability of Bluetooth Low Energy device advertisement messages: you can embed user data into these broadcasts. These come handy if you just want to send out some measurement data to whoever cares to listen without creating a session between the BLE client and server. This broadcast-type data transfer may support unlimited number of clients with very low energy consumption on the sensor side.

Click here to download the Android client application project.

Click here to download the RFDuino source code.

The prototype works like the following. The microcontroller presented in the video measures the Lower Explosion Limit and sends this value to the RFDuino microcontroller over a super-simpe serial protocol. A message of this protocol looks like this:

0xA5 <seq_no> <LEL%>

where seq_no is an increasing value and LEL% is the measured Lower Explosion Limit value. The microcontroller code is not shared here but you can get the idea. The RFDuino code receives the LEL% value over the serial port it creates on GPIO pins 3 and 4, creates a custom data structure for BLE advertisements consisting of the site ID and the LEL% value then starts advertising. This is performed cyclically so the LEL% value is updated in the sensor's BLE advertisement every second.

Now let's see what happens on the Android side. This is a non-trivial application with multiple activities but the Real Thing (TM) happens in the MapScreenActivity, in the onLeScan method. This method is called every time the Android device's BLE stack discovers a device. In this case we check whether the device's name is "g" (this is how we identify our sensor) and we retrieve the LEL% data from the advertisement packet.  We also handle the Received Signal Strenght Indicator (rssi) value for proximity indication. Bluetooth device discovery is restarted in every 2 seconds so that we can retrieve the latest LEL% value. The rest is just Plain Old Android Programming.

The identification of the sensor and the encoding of the sensor data is obviously very naive but this is not really the point. You can make it as complex as you like, e.g. you can protect the sensor data with a hash and place that hash also into the advertisement so that the receiver can make sure that it gets data from an authorized sensor and not a fake one. The important thing is that the entire framework is sufficiently flexible so that relatively complex functionality can be implemented and RFDuino really simplifies sensor programming a lot.

If you enjoyed the example application, make sure you watch the video (many times if possible :-)) and if you happen to be in London on 2014 November 19, you might as well come to the Londroid meetup where I present this and another BLE project (a connection-oriented one, called MotorBoat).

Saturday, September 6, 2014

Camera shot on charger connection

Somebody came to me with an idea whether a cheap Android phone can be turned into an automatic camera. Some external sensor would send a signal to the phone and the phone would take a picture automatically. We started to discuss the possible connection of the external sensor and an interesting idea came up: the charger connection.

Android delivers an event whenever the charging power is connected or disconnected: can it be used to send a binary signal to an application in a very simple way, without fiddling with Bluetooth or USB?

Click here to download the example application.

You have to start the application once. Then whenever you connect the charger, it takes a picture. When the application is in the foreground, a preview is shown but as long as the application is active (not destroyed) it works from the background too.

Here are the experiences:

  • On my high-end device the application reacted quickly to charger connection, the reaction time from connecting the charger to the camera shot was less than a second. But when the application was tested on the very low-end Android target device, the picture was much less rosy: the delay increased to 3-4 seconds, effectively making the solution unusable.
  • In order for this application to work, it has to be started at least once manually. This pretty much kills all unattended use cases.
  • The shutter sound is almost impossible to remove. Update: on certain devices (Nexus 4 and Nexus 7 confirmed) there is no shutter sound in silent mode.
The takeaway for us was to reject the idea. But I share the example program anyway, maybe it can be useful for somebody.


Tuesday, September 2, 2014

Android gas sensor application with Bluetooth Low Energy/RFDuino

I have always had a fascination with sensors linked up with mobile devices so it seemed just a good opportunity to try out the latest fashionable technology in the area, Bluetooth Low Energy in the context of a competition. SemiconductorStore.com announced the "We know RFDuino" competition for applications of the RFDuino module. RFDuino is an Arduino module with Bluetooth Low Energy (BLE) support. It is ideal to act as an interface between a sensor and a BLE-enabled mobile device like the Nexus 7.

Eventually I will publish the entire source code of this prototype application on this blog. But as this is a contest, I will wait until the contest ends (Sept. 30). Till then, watch the (very amateurish) video we have prepared about our sensor and the Android application. The entry with the most views wins the contest so if you like the concept, share the video with others! Thanks in advance. :-)