Another week has gone by and I’m still trying to create a sender and receiver for a custom BLE service. Why this is necessary is a lesson in itself, and I can’t believe how hard I’m finding this – but I guess old brain is a factor. It’s all supposed to be so easy, but I seem to find gotchas at every touch and turn. One of the issues is that BLE defines new terms that are subtle and confusing.
I’m trying to do something that’s “Oh so simple” – create a custom profile. A profile defines what a physical BLE device does, i.e. how it behaves. The profile is like a contract between the two ends of a BLE radio link that defines how, and what the two devices are going to communicate. It’s the high-level protocol that allows them to understand the meaning of the information they have agreed to exchange. BLE distinguishes the word profile, from protocol. I can’t really see the difference, but clearly a profile defines higher-level semantics, and protocol lover-level. The protocol might describe addressing a routing issues, whereas the profile describes how the data should be interpreted by the application. And what’s an application…? I’m not going there.
The terms server and client are too rigid for BLE. BLE defines the term role. Although in BLE every connection defines one end as master and the other end as slave, there appears to be no reason why a device cannot be both. It can even be both at the same time. Example roles are “heart rate sensor” and “heart rate collector”. This is all a bit too subtle for now, but it’s good to know that there is this verbal gotcha lurking in the woodwork. Client and server are not terms that crop up much.
So… back to the profile. Each profile defines a set of services. Some services are mandatory across all profiles, some are so common that they have been defined by the BLE standard, and others are specialized to the particulars of the device – a custom service.
- One mandatory service provides the human readable string describing the profile, e.g. “Heart Rate Monitor”, or “HRM”.
- A standard, but non-mandatory service, “BAS” provides the state of the battery – an estimate of the charge left in the battery expressed in % or volts.
- A specialized service might provide the state of some sensor, or actuator, e.g. the rate of flow of water through a valve. TS has a special behavior so it has to define a custom service in order to communicate over BLE.
A profile can combine a mixture of mandatory, standard and custom services. So a profile might combine an HRM service and a BAS service. A more elaborate device might add some proprietary extra service call “FOO”.
Now, for me, it all gets a bit arbitrary. For some reason BLE has made some decisions about what services will be standard. I think some of these decisions are based upon who was at the table when the standard was being written. For example the HRM service is defined in the standard, along with the HTP “Heath Thermometer Profile”, and the HID “Human Interface Device” profile.
This is an important distinction because standard services are allowed to use privileged (and shorter) packets to do their work, thus saving power. A standard part of the traffic in each packet is a UUID. This defines the profile, service and characteristic (part of a service) that the packet is about. A standard UUID is 128 bits long – a substantial fraction of a packet that can only be 128 bytes long, and a lot of overhead when you have a tiny battery. So the standard has decreed that some services can use much shorter UUIDs, and they are not to be used for any other purpose. If you want to define your own shorter UUID then I guess you have to cross the palm of BLE with silver.
Anyone can define a new UUID here. They are generated randomly, and so there is a very small chance that two organizations can be allocated the same UUID.
A characteristic is a fancy term for a blob of data – the stuff we actually care about – a heart-rate measurement, or a range measurement for example. Unless you use the standard characteristic types, then each of these requires 128 bits to describe. Fortunately the standard defines a lot of useful characteristics that can be pressed into service.
Just to make things more confusing, there are standard profiles. But standard profiles don’t have a physical manifestation – they are just a collection of services that appear to have no data structure, or type associated with them, so I don’t even see how something that doesn’t ever exist can be standardized – but hey! I think the point of standard profiles is that a manufacturer can define their own private profile that allows their devices to communicate, and prevents others from inter-operating with them. So TS will probably need a custom profile.
TS has to define a custom profile, and one, or more custom services, and maybe some custom characteristics, all of which carry with them this onerous extra overhead that sucks the battery dry.
My plan is to build a collector service that remotely instructs a TS_ranger to turn on it’s ranger; to range the collector; and then to send the resulting range measurement back to the collector. This is about as simple a program as I can define that will require all parts of the software to fit into memory, and to cooperate. If I can’t make this work, then as I keep saying… “we are done”.
Now there are demo examples of how to setup a standard profile using standard services. I have compiled those examples and satisfied myself that they work OK. Now I am trying to incrementally change them so that they use a custom profile and custom service. It ought to be as simple as swapping some short numbers for some longer ones…
So my example is simple. I have a new stunning service called LEDBUTT. LEDBUTT implements one button and one LED. The objective is that when you press the button, a signal is send to a peer device which in turn sends a message back requesting the sender to illuminate it’s LED. Yup – a light switch! When you release the button, another pair of obvious messages are exchanged and the LED turns off.
How hard can this be… well a full week of fiddling has not brought me much closer to success.