Categories

Day 44: hints on Android API and BLE

Since last week (after having rewritten our protocol with a single characteristic), I struggled a lot with Android API for GATT connections. To help you to establish clean connections, here is what I have found.

A BluetoothGatt object is a kind of socket. You open it, then you connect and disconnect it as many times as you want, and then you close it.

In the Android API, the connection occurs as soon as the GATT is opened: it is the purpose of the BluetoothDevice.connectGatt method. BluetoothGatt.connect is only used for reconnections after a disconnection. On the contrary, the disconnect and close operations shouldn’t be done at the same time. Closing a GATT means forgetting it (it would be done by the Garbage Collector, but it is better to do it as soon as you don’t need it anymore, so that ressources can be freed), so what will happen if you receive a “onDisconnected” event for a GATT that you have already closed? A NullPointerException is thrown (see the Android logcat). Then BluetoothGatt.close must be used only after having received the confirmation that the GATT is disconnected (typically, in the onDisconnected callback).

Please note that the S110 SoftDevice (which we use on the nRF51822 chip) only accepts one GATT connection at a time, but it is only a matter of implementation, and not a standard behaviour with Bluetooth Low Energy. Consequently, your phone is able to open and maintain several GATT connections in the same time. And these connections may be established with the same BLE device (even a nRF51822). Technically, what you will have are several BluetoothGatt objects with different UUIDs (each connectGatt creates a new instance). But this is a bad behaviour, and if you maintain several BluetoothGatt objects towards the same nRF51822, after a few iterations you won’t be able to connect anymore. So don’t forget to close GATTs you won’t reconnect with, and keep track of already created GATTs so that you can reconnect them instead of creating new instances.

By the way, the life time of an Android application is not the life time of  your main activity. Even when the application is not visible anymore in the “Recent apps” panel, it may survive, and the only way to kill it properly (without debug options) is to “Force quit” it in the Application options. Consequently, be cautious when recreating a GATT object if you are not sure that the previous one was destroyed (which happens systematically when the app is killed).

A GATT connection must not be confused with pairing and bonding. Here is an extract of nRF51 documentation:

Bonding is when two devices that connect and follow procedures that allow them to cache information inorder to avoid repeating certain set-up procedures on subsequent reconnection(s).

The caching of information can span across layers in the system, for example, keys needed to secure the link on reconnection, GATT Server Configuration. Information with respect to a bonded peer is expected to be retained on power cycle of the device, and is maintained persistently.

In contrast to bonding, the Bluetooth specification defines procedure needed to establish secure link for ongoing session only, called Pairing. No information is cached for paired devices. Please refer to Volume 3 Part H, Section 6.5 of Bluetooth Core Specification 4.0 for more information.

To put it in a nutshell:

– GATT connections/disconnections are short term, when you have a few pieces of data to send.

– GATT objects are middle term, typically for the life time of your Android application.

– Pairing is for establishing secure connections.

– Bonding is long term, when you known your devices will often interact.

I hope I was clear enough, don’t hesitate to ask me if you have questions left, or to tell me if I was wrong on some point.

Back to ROSE

We only said goodbye with words
I died a hundred times
You go back to her
And I go back to…..
I go back to us

Hello World!

Yes, I’m back. Sith Lords are not as powerful as they used to be, so kicking them out of the galaxy has been easier than expected.

Last week end and on Monday, I worked a lot on the Drop Scanner app. I had to learn many things (Scala, Android, Scaloid) and to dive in the code Lauriane had written. When I began to understand how the code was working, I changed a little bit the interface. No breakthrough, but this helped me to put my hands in the code. There are still a lot of things to improve about the UI and the UX. Also, some bugs remain and have to be fixed as soon as possible!

Yesterday, I also started to think about the memory organization. We will have a Flash memory, which means that we have to spread the write requests across the pages not to wear them too fast. So I began to search for existing Flash file systems, in order to take some good ideas. Especially, I found UBIFS and JFFS2 which are popular Linux flash file systems. In the end, I designed a brand new flash file system, called DropFS (stands for Deluxe Rather OPerational File System). We still have to think about a few issues, but the global architecture looks solid. I will explain the whole design in a few days with gorgeous schematics. Stay tuned!

Finally, we decided to think again about our use cases, and clarify them in order to know what we really need to implement in our drops. I was assigned to think about the Cairn use case (the one for hikers). I wrote a little text explaining how the user would use the app, but above all I made an interactive mockup of the app, showing the different screens and interactions. Check it out!

May the force be with you!

Day 35: putting everything together

Hello everybody!

Since my last post, I did a lot of different things.

First, on Android:

– I completed the Drop Scanner app, with four activities dedicated to scanning for BLE devices, displaying services and characteristics, reading, writing on characteristics and asking for notifications. It is already sufficient for reading and writing messages! But the UI is not very user-friendly.

– I added three extra activities on the app to provide a nicer UI for the mailbox. It does not work yet (the notification request on Content is sent, the write request on ID is sent… and the write ACK never comes back) and I don’t understand why, because the message arrives with no problem when I perform these steps by hand with the GATT UI. Maybe there are some timing issues. But I stopped working on it, because we are going to change our protocol for reading messages very soon anyway.

– I discovered the Android version easter egg, thanks to Sam.

– I spent some time with Adele and with Matthieu to help them setting up their environment for Android+Scala+Scaloid. I also did a quick crash course on Scala for Adele, who wasn’t familiar at all with functional programming.

– I know that there are still a lot of issues with this app: bad GATT connection management (at which abstraction level do I have to manage it? how long should it be?), awful design… But right now it is functional enough for us to test any interaction we want with the nRF51822, so I stopped working on it and wait for the others to get familiar with Scaloid.

And for the nRF51822 part:

– I began truly reading the code Matthieu and Adèle have been working on for the nRF51822. With the help of git grep, I understood its architecture, the meaning of the most useful structures, and now I have a good idea of where I should change the code to add features.

– Considering that there was too much copy-paste in the code (which started as a customization of the led button demo), I worked on refactoring it. Tonight, there are no more duplicate lines in the services and characteristics initialization process.

– Now I start working on a new BLE architecture, with only one characteristic for reading and writing messages.

See you soon!

Message in a bottle

I hope that someone gets my
Message in a bottle

Hello World!

On Tuesday, I finished to refactor the LedButton example code. This way, I had reliable foundations on which I could start developing new custom services. Before that, I tested the refactored version with gatttool, and it was working as well as the original one!

The next step was to develop the Message Service. I presented a first architecture to my group:

Message Service v1 - Readarchitecture1_write

We implemented this architecture on Wednesday. I wrote the code for the Bluetooth service, while Adele was handling the persistent storage in RAM. In the end, we had a working prototype and we successfully managed to test it with gatttool.

However we discovered several drawbacks:

  • when we want to write a value, its content is notified even if we don’t want to need it;
  • the maximal length of a notification is 20 characters, so we may need an additional step to read the full message;
  • above all, there are too many exchanges in both read and write operations!!

So yesterday, we argued a lot about the best way to solve this problem. We had many ideas:

  • remove the notification and always perform an additional read request;
  • give with the id characteristic a special bit indicating whether we want to be notified;
  • remove some ACK if we really need to save battery;
  • have two services (ReadMessage and WriteMessage) with different behaviours;
  • have one service with one characteristic and parse the written command in order to infer the operation to perform.

We finally agreed on the last solution. Lauriane will implement it this week end (so that she can put her hands in the code). Personally, I will work on the Android app which is not yet fully functional. I have already read some slides about Android development and browsed the Android developers website. I still have to learn Scala, and then read the code Lauriane has already written.

May the force be with you!

P.S. : yes our logo is official now!!

Day 24: unblocked, at last!

During the week-end, I established BLE communication between a nRF51822 chip flashed by Matthieu and my smartphone (with Scaloid), but I was constrained by the UI: the only display I was able to do was toasts.

So, at the beginning of the week, I decided to explore Android’s View and Adapter. It began well… and then I was stuck for two days on a LayoutParams cast error! After having read lots of source files of Android API and Scaloid, I finally understood what was happening: an AbsListView checks the LayoutParams type of its children, but only when ids are stable (and for an ArrayAdapter, they aren’t). This behaviour is quite strange, I am not sure if it was on purpose, it may be a bug in the API.

I was quite angry at Android for a moment, but I was relieved to have solved my bug, as well.

Then when Sam informed me that my app was flooding his phone, replicating the same device hundreds of times, I was confused, because it only appeared once on mine. I did experiments with all the phones available in the room (Nexus 4/5, Android 4.3/4.4/4.4.2, with or without CyanogenMod), and discovered that I had bought the wrong phone: for hardware reasons, the Nexus 4 receives 100 times less BLE advertising packets than the Nexus 5. Sad, isn’t it?

I lost a lot of time with these two issues, but now I can finally go on with my app development and start implementing services for drop messages. And even if I was a little angry, it was really interesting to solve my problems, since it allowed me to discover a lot more on Android.