-
Notifications
You must be signed in to change notification settings - Fork 0
/
HTSManager.java
147 lines (128 loc) · 6.23 KB
/
HTSManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* Copyright (c) 2015, Nordic Semiconductor
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package no.nordicsemi.android.nrftoolbox.hts;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import java.util.Deque;
import java.util.LinkedList;
import java.util.UUID;
import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.parser.TemperatureMeasurementParser;
import no.nordicsemi.android.nrftoolbox.utility.DebugLogger;
/**
* HTSManager class performs BluetoothGatt operations for connection, service discovery, enabling indication and reading characteristics. All operations required to connect to device with BLE HT
* Service and reading health thermometer values are performed here. HTSActivity implements HTSManagerCallbacks in order to receive callbacks of BluetoothGatt operations
*/
public class HTSManager extends BleManager<HTSManagerCallbacks> {
private static final String TAG = "HTSManager";
/** Health Thermometer service UUID */
public final static UUID HT_SERVICE_UUID = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb");
/** Health Thermometer Measurement characteristic UUID */
private static final UUID HT_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb");
private BluetoothGattCharacteristic mHTCharacteristic;
private final static int HIDE_MSB_8BITS_OUT_OF_32BITS = 0x00FFFFFF;
private final static int HIDE_MSB_8BITS_OUT_OF_16BITS = 0x00FF;
private final static int SHIFT_LEFT_8BITS = 8;
private final static int SHIFT_LEFT_16BITS = 16;
private final static int GET_BIT24 = 0x00400000;
private final static int FIRST_BIT_MASK = 0x01;
public HTSManager(final Context context) {
super(context);
}
@Override
protected BleManagerGattCallback getGattCallback() {
return mGattCallback;
}
/**
* BluetoothGatt callbacks for connection/disconnection, service discovery, receiving indication, etc
*/
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
requests.add(Request.newEnableIndicationsRequest(mHTCharacteristic));
return requests;
}
@Override
protected boolean isRequiredServiceSupported(final BluetoothGatt gatt) {
final BluetoothGattService service = gatt.getService(HT_SERVICE_UUID);
if (service != null) {
mHTCharacteristic = service.getCharacteristic(HT_MEASUREMENT_CHARACTERISTIC_UUID);
}
return mHTCharacteristic != null;
}
@Override
protected void onDeviceDisconnected() {
mHTCharacteristic = null;
}
@Override
public void onCharacteristicIndicated(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
Logger.a(mLogSession, "\"" + TemperatureMeasurementParser.parse(characteristic) + "\" received");
try {
final double tempValue = decodeTemperature(characteristic.getValue());
mCallbacks.onHTValueReceived(gatt.getDevice(), tempValue);
} catch (Exception e) {
DebugLogger.e(TAG, "Invalid temperature value", e);
}
}
};
/**
* This method decode temperature value received from Health Thermometer device First byte {0} of data is flag and first bit of flag shows unit information of temperature. if bit 0 has value 1
* then unit is Fahrenheit and Celsius otherwise Four bytes {1 to 4} after Flag bytes represent the temperature value in IEEE-11073 32-bit Float format
*/
private double decodeTemperature(byte[] data) throws Exception {
double temperatureValue;
byte flag = data[0];
byte exponential = data[4];
short firstOctet = convertNegativeByteToPositiveShort(data[1]);
short secondOctet = convertNegativeByteToPositiveShort(data[2]);
short thirdOctet = convertNegativeByteToPositiveShort(data[3]);
int mantissa = ((thirdOctet << SHIFT_LEFT_16BITS) | (secondOctet << SHIFT_LEFT_8BITS) | (firstOctet)) & HIDE_MSB_8BITS_OUT_OF_32BITS;
mantissa = getTwosComplimentOfNegativeMantissa(mantissa);
temperatureValue = (mantissa * Math.pow(10, exponential));
/*
* Conversion of temperature unit from Fahrenheit to Celsius if unit is in Fahrenheit
* Celsius = (Fahrenheit -32) 5/9
*/
if ((flag & FIRST_BIT_MASK) != 0) {
temperatureValue = (float) ((temperatureValue - 32) * (5 / 9.0));
}
return temperatureValue;
}
private short convertNegativeByteToPositiveShort(byte octet) {
if (octet < 0) {
return (short) (octet & HIDE_MSB_8BITS_OUT_OF_16BITS);
} else {
return octet;
}
}
private int getTwosComplimentOfNegativeMantissa(int mantissa) {
if ((mantissa & GET_BIT24) != 0) {
return ((((~mantissa) & HIDE_MSB_8BITS_OUT_OF_32BITS) + 1) * (-1));
} else {
return mantissa;
}
}
}