In the previous articles in this series we have learned about the various steps we need to undergo before we get temperature and humidity data from a ti sensortag. In the last article in this series, we will complete the registration and receive Sensortag notifications and receive temperature and humidity data.
Receive data:
Now that the local proxy component knows what the sensor is offering, we can start using the services. To use them, we first need to get the service, then the features that the service contains, and finally the descriptor of the feature.
A GATT service is represented as a Bluetoothgattservice object, which we need to derive from the Bluetoothgatt instance through the appropriate UUID; an GATT feature is represented as a bluetoothgattcharacteristic object, which we can get from bluetoothgattservice with the appropriate UUID; a GATT descriptor behaves as a Bluetoothgattdescriptor object, We can get from the Bluetoothgattcharacteristic object with the appropriate UUID:
private static final UUID Uuid_humidity_service = uuid.fromstring ("f000aa20-0451-4000-b000-000000000000");p rivate STA Tic final uuid Uuid_humidity_data = uuid.fromstring ("f000aa21-0451-4000-b000-000000000000");p rivate static final UUID uuid_humidity_conf = uuid.fromstring ("f000aa22-0451-4000-b000-000000000000");p rivate static final UUID UUID_CCC = Uuid.fromstring ("00002902-0000-1000-8000-00805F9B34FB"); private void Subscribe (Bluetoothgatt GATT) { Bluetoothgattservice Humidityservice = Gatt.getservice (Uuid_humidity_service); if (humidityservice! = null) {bluetoothgattcharacteristic humiditycharacteristic = humidityservice.getc Haracteristic (Uuid_humidity_data); Bluetoothgattcharacteristic humidityconf = humidityservice.getcharacteristic (uuid_humidity_conf); if (humiditycharacteristic = null && humidityconf! = null) {bluetoothgattdescriptor config = Humiditycharacteristic.getdeScriptor (UUID_CCC); if (config! = null) {}}}}
To make the sample code clear, I have removed all the error message presentation code, but in the actual application you should consider how to notify the user of the error message.
UUID_HUMIDITY_DATA
reading data from a feature is a simple matter, just call the Gatt.readcharacteristic (humiditycharacteristic) method, and in Bluetoothgattcallback Implementation of the On-class replication Onreadcharacteristic method (again, this is an asynchronous operation, so you can call the Readcharacteristic () method on the UI thread). This one-time operation is fine, but our application constantly monitors the temperature and humidity values and reports them to the user. It is more effective to call readcharacteristic () for periodic polling than the registered listener feature value (Translator Note: feel that the reverse, we can look at the original text, do not know if I translated the wrong: Instead we can get notifications Whenever the value changes, which is much more efficient that polling and performing a readCharacteristic()
periodically.).
Notification of registered monitoring feature value changes we have to do three things. First we have to open the sensor so that Sensortag starts collecting the appropriate data (in fact, if we use the Readcharacteristic () method, we also open the sensor). Then we have to register the sensor and the local agent we need to notify. This step is specifically for sensortag, other devices may not need this, or they may need another method.
In order to open the sensor, we must write a 0x01 value to the uuid_humidity_conf feature; In order to receive the notification, we must first call Bluetoothgatt The Setcharacteristicnotification () method of the instance, and then writes a value of {0x00,0x01} (two bytes) to the UUID_CCC descriptor. As we mentioned earlier, the UUID_CCC descriptor is not sensortag specific (just like any other UUID), which is the UUID of a standard shutdown or open notification.
So far, we have greatly benefited from BLE's asynchronous API, because we don't need to worry about calling it from the UI thread. Unfortunately, it puts us in the face of some minor problems. We want the following code to do what we asked for, but running it will not start receiving notifications:
Gatt.setcharacteristicnotification (humiditycharacteristic, True); Humidityconf.setvalue (ENABLE_SENSOR); Gatt.writecharacteristic (humidityconf); Config.setvalue (Bluetoothgattdescriptor.enable_notification_value); Gatt.writedescriptor (config);
The reason is that our sensor writes the value of the operation is executed asynchronously, that does not work, we must wait for a write operation before we can start the next. If we cannot wait for the second value to be written while the first value is being written, the second value is lost. To overcome him is not difficult, we can maintain a write queue, when we receive the previous write operation has been completed notification after the next write operation:
private static final byte[] Enable_sensor = {0x01};p rivate static final queue<object> swritequeue = new Concurre Ntlinkedqueue<object> ();p rivate static Boolean siswriting = false;private Bluetoothgattcallback mGattCallback = New Bluetoothgattcallback () {. . . @Override public void Oncharacteristicwrite (Bluetoothgatt GATT, bluetoothgattcharacteristic characteristic, int status) {LOG.V (TAG, "oncharacteristicwrite:" + status); Siswriting = false; Nextwrite (); } @Override public void Ondescriptorwrite (Bluetoothgatt GATT, Bluetoothgattdescriptor descriptor, in T status) {LOG.V (TAG, "ondescriptorwrite:" + status); Siswriting = false; Nextwrite (); }}...private void Subscribe (Bluetoothgatt GATT) {Bluetoothgattservice Humidityservice = Gatt.getservice (UUID_H Umidity_service); if (humidityservice! = null) {bluetoothgattcharacteristic humiditycharacteristic= Humidityservice.getcharacteristic (Uuid_humidity_data); Bluetoothgattcharacteristic humidityconf = humidityservice.getcharacteristic (uuid_humidity_conf); if (humiditycharacteristic! = NULL && humidityconf! = null) {bluetoothgattdescriptor config = Humiditycharacteristic.getdescriptor (UUID_CCC); if (config! = null) {gatt.setcharacteristicnotification (humiditycharacteristic, true); Humidityconf.setvalue (Enable_sensor); Write (humidityconf); Config.setvalue (Bluetoothgattdescriptor.enable_notification_value); Write (config); }}}}private synchronized void write (Object o) {if (Swritequeue.isempty () &&!siswriting) {D Owrite (o); } else {swritequeue.add (o); }}private synchronized void Nextwrite () {if (!swritequeue.isempty () &&!siswriting) {Dowrite (Swritequeue.poll ()); }}private synchronized void Dowrite (Object o) {if (o instanceof bluetoothgattcharacteristic) {siswriting = True ; Mgatt.writecharacteristic ((bluetoothgattcharacteristic) o); } else if (o instanceof bluetoothgattdescriptor) {siswriting = true; Mgatt.writedescriptor ((bluetoothgattdescriptor) o); } else {nextwrite (); }}
So after joining this simple write queue, we just need to add the appropriate callback method to our Bluetoothgattcallback implementation class to turn on the listener notification event.
Private Bluetoothgattcallback Mgattcallback = new Bluetoothgattcallback () {. . . @Override public void oncharacteristicchanged (Bluetoothgatt GATT, bluetoothgattcharacteristic characteristic) { LOG.V (TAG, "oncharacteristicchanged:" + characteristic.getuuid ()); if (Characteristic.getuuid (). Equals (Uuid_humidity_data)) {int t = shortunsignedatoffset (characteristic, 0); int h = shortunsignedatoffset (characteristic, 2); t = t-(t% 4); H = h-(h% 4); float humidity = ( -6f) + 125f * (h/65535f); Float temperature = -46.85f + 175.72f/65536f * (float) t; LOG.D (TAG, "Value:" + humidity + ":" + temperature); Message msg = Message.obtain (null, msg_device_data); MSG.ARG1 = (int) (temperature * 100); MSG.ARG2 = (int) (humidity * 100); SendMessage (msg); }}}private static Integer Shortunsignedatoffset ( bluetoothgattcharacteristic characteristic, int offset) {Integer lowerbyte = Characteristic.getintvalue (Blue Toothgattcharacteristic.format_uint8, offset); Integer upperbyte = Characteristic.getintvalue (bluetoothgattcharacteristic.format_uint8, offset + 1); Return (Upperbyte << 8) + Lowerbyte;}
The data in the GATT feature includes the temperature value (in the No. 0 byte and the 1th byte) and the humidity value (in 2nd and 3rd bytes). Then we remove any unnecessary status bits. The calculation method comes directly from the Sensortag document.
To show this data on the interface, we use the arg1 and arg2 two member variables of the Message, and we multiply it by 100 before converting it to the desired int value. After that, we'll divide by 100 to return a float value. As before, the code for the UI will not be shown here, but it will be in the source code.
If we run the program, we can see the Celsius temperature and humidity percentage of the display processing "video on YouTube, need to traverse to see Oh":
Http://www.youtube.com/embed/dyr01b2iy-I?version=3&rel=1&fs=1&showsearch=0&showinfo=1&iv_ Load_policy=1&wmode=transparent
Bluetooth LE (Low power bluetooth®)-sixth part (end)