blob: 2c124034b7862f21dbfd25083a1e0d9c562855ca [file] [log] [blame]
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.bluetooth;
17
Jakub Pawlowski8d312a82016-03-01 18:50:27 -080018import android.os.Parcel;
Jakub Pawlowski8d312a82016-03-01 18:50:27 -080019import android.os.ParcelUuid;
Jack Hea355e5e2017-08-22 16:06:54 -070020import android.os.Parcelable;
21
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080022import java.util.ArrayList;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080023import java.util.List;
24import java.util.UUID;
25
26/**
Matthew Xieddf7e472013-03-01 18:41:02 -080027 * Represents a Bluetooth GATT Characteristic
Matthew Xie33ec9842013-04-03 00:29:27 -070028 *
29 * <p>A GATT characteristic is a basic data element used to construct a GATT service,
30 * {@link BluetoothGattService}. The characteristic contains a value as well as
31 * additional information and optional GATT descriptors, {@link BluetoothGattDescriptor}.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080032 */
Jakub Pawlowski8d312a82016-03-01 18:50:27 -080033public class BluetoothGattCharacteristic implements Parcelable {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080034
35 /**
36 * Characteristic proprty: Characteristic is broadcastable.
37 */
38 public static final int PROPERTY_BROADCAST = 0x01;
39
40 /**
41 * Characteristic property: Characteristic is readable.
42 */
43 public static final int PROPERTY_READ = 0x02;
44
45 /**
46 * Characteristic property: Characteristic can be written without response.
47 */
48 public static final int PROPERTY_WRITE_NO_RESPONSE = 0x04;
49
50 /**
51 * Characteristic property: Characteristic can be written.
52 */
53 public static final int PROPERTY_WRITE = 0x08;
54
55 /**
56 * Characteristic property: Characteristic supports notification
57 */
58 public static final int PROPERTY_NOTIFY = 0x10;
59
60 /**
61 * Characteristic property: Characteristic supports indication
62 */
63 public static final int PROPERTY_INDICATE = 0x20;
64
65 /**
66 * Characteristic property: Characteristic supports write with signature
67 */
68 public static final int PROPERTY_SIGNED_WRITE = 0x40;
69
70 /**
71 * Characteristic property: Characteristic has extended properties
72 */
73 public static final int PROPERTY_EXTENDED_PROPS = 0x80;
74
75 /**
76 * Characteristic read permission
77 */
78 public static final int PERMISSION_READ = 0x01;
79
80 /**
81 * Characteristic permission: Allow encrypted read operations
82 */
83 public static final int PERMISSION_READ_ENCRYPTED = 0x02;
84
85 /**
86 * Characteristic permission: Allow reading with man-in-the-middle protection
87 */
88 public static final int PERMISSION_READ_ENCRYPTED_MITM = 0x04;
89
90 /**
91 * Characteristic write permission
92 */
93 public static final int PERMISSION_WRITE = 0x10;
94
95 /**
96 * Characteristic permission: Allow encrypted writes
97 */
98 public static final int PERMISSION_WRITE_ENCRYPTED = 0x20;
99
100 /**
101 * Characteristic permission: Allow encrypted writes with man-in-the-middle
102 * protection
103 */
104 public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 0x40;
105
106 /**
107 * Characteristic permission: Allow signed write operations
108 */
109 public static final int PERMISSION_WRITE_SIGNED = 0x80;
110
111 /**
112 * Characteristic permission: Allow signed write operations with
113 * man-in-the-middle protection
114 */
115 public static final int PERMISSION_WRITE_SIGNED_MITM = 0x100;
116
117 /**
118 * Write characteristic, requesting acknoledgement by the remote device
119 */
120 public static final int WRITE_TYPE_DEFAULT = 0x02;
121
122 /**
123 * Wrtite characteristic without requiring a response by the remote device
124 */
125 public static final int WRITE_TYPE_NO_RESPONSE = 0x01;
126
127 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800128 * Write characteristic including authentication signature
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800129 */
130 public static final int WRITE_TYPE_SIGNED = 0x04;
131
132 /**
133 * Characteristic value format type uint8
134 */
135 public static final int FORMAT_UINT8 = 0x11;
136
137 /**
138 * Characteristic value format type uint16
139 */
140 public static final int FORMAT_UINT16 = 0x12;
141
142 /**
143 * Characteristic value format type uint32
144 */
145 public static final int FORMAT_UINT32 = 0x14;
146
147 /**
148 * Characteristic value format type sint8
149 */
150 public static final int FORMAT_SINT8 = 0x21;
151
152 /**
153 * Characteristic value format type sint16
154 */
155 public static final int FORMAT_SINT16 = 0x22;
156
157 /**
158 * Characteristic value format type sint32
159 */
160 public static final int FORMAT_SINT32 = 0x24;
161
162 /**
163 * Characteristic value format type sfloat (16-bit float)
164 */
165 public static final int FORMAT_SFLOAT = 0x32;
166
167 /**
168 * Characteristic value format type float (32-bit float)
169 */
170 public static final int FORMAT_FLOAT = 0x34;
171
172
173 /**
174 * The UUID of this characteristic.
Jack Hea355e5e2017-08-22 16:06:54 -0700175 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800176 * @hide
177 */
178 protected UUID mUuid;
179
180 /**
181 * Instance ID for this characteristic.
Jack Hea355e5e2017-08-22 16:06:54 -0700182 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800183 * @hide
184 */
185 protected int mInstance;
186
187 /**
188 * Characteristic properties.
Jack Hea355e5e2017-08-22 16:06:54 -0700189 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800190 * @hide
191 */
192 protected int mProperties;
193
194 /**
195 * Characteristic permissions.
Jack Hea355e5e2017-08-22 16:06:54 -0700196 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800197 * @hide
198 */
199 protected int mPermissions;
200
201 /**
202 * Key size (default = 16).
Jack Hea355e5e2017-08-22 16:06:54 -0700203 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800204 * @hide
205 */
206 protected int mKeySize = 16;
207
208 /**
209 * Write type for this characteristic.
210 * See WRITE_TYPE_* constants.
Jack Hea355e5e2017-08-22 16:06:54 -0700211 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800212 * @hide
213 */
214 protected int mWriteType;
215
216 /**
217 * Back-reference to the service this characteristic belongs to.
Jack Hea355e5e2017-08-22 16:06:54 -0700218 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800219 * @hide
220 */
221 protected BluetoothGattService mService;
222
223 /**
224 * The cached value of this characteristic.
Jack Hea355e5e2017-08-22 16:06:54 -0700225 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800226 * @hide
227 */
228 protected byte[] mValue;
229
230 /**
231 * List of descriptors included in this characteristic.
232 */
233 protected List<BluetoothGattDescriptor> mDescriptors;
234
235 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800236 * Create a new BluetoothGattCharacteristic.
237 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
238 *
239 * @param uuid The UUID for this characteristic
240 * @param properties Properties of this characteristic
241 * @param permissions Permissions for this characteristic
242 */
243 public BluetoothGattCharacteristic(UUID uuid, int properties, int permissions) {
244 initCharacteristic(null, uuid, 0, properties, permissions);
245 }
246
247 /**
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800248 * Create a new BluetoothGattCharacteristic
Jack Hea355e5e2017-08-22 16:06:54 -0700249 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800250 * @hide
251 */
252 /*package*/ BluetoothGattCharacteristic(BluetoothGattService service,
Jack Hea355e5e2017-08-22 16:06:54 -0700253 UUID uuid, int instanceId,
254 int properties, int permissions) {
Matthew Xieddf7e472013-03-01 18:41:02 -0800255 initCharacteristic(service, uuid, instanceId, properties, permissions);
256 }
257
Jakub Pawlowski8d312a82016-03-01 18:50:27 -0800258 /**
259 * Create a new BluetoothGattCharacteristic
Jack Hea355e5e2017-08-22 16:06:54 -0700260 *
Jakub Pawlowski8d312a82016-03-01 18:50:27 -0800261 * @hide
262 */
263 public BluetoothGattCharacteristic(UUID uuid, int instanceId,
Jack Hea355e5e2017-08-22 16:06:54 -0700264 int properties, int permissions) {
Jakub Pawlowski8d312a82016-03-01 18:50:27 -0800265 initCharacteristic(null, uuid, instanceId, properties, permissions);
266 }
267
Matthew Xieddf7e472013-03-01 18:41:02 -0800268 private void initCharacteristic(BluetoothGattService service,
Jack Hea355e5e2017-08-22 16:06:54 -0700269 UUID uuid, int instanceId,
270 int properties, int permissions) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800271 mUuid = uuid;
272 mInstance = instanceId;
273 mProperties = properties;
274 mPermissions = permissions;
275 mService = service;
276 mValue = null;
277 mDescriptors = new ArrayList<BluetoothGattDescriptor>();
278
279 if ((mProperties & PROPERTY_WRITE_NO_RESPONSE) != 0) {
280 mWriteType = WRITE_TYPE_NO_RESPONSE;
281 } else {
282 mWriteType = WRITE_TYPE_DEFAULT;
283 }
284 }
285
Jack He2992cd02017-08-22 21:21:23 -0700286 @Override
Jakub Pawlowski8d312a82016-03-01 18:50:27 -0800287 public int describeContents() {
288 return 0;
289 }
290
Jack He2992cd02017-08-22 21:21:23 -0700291 @Override
Jakub Pawlowski8d312a82016-03-01 18:50:27 -0800292 public void writeToParcel(Parcel out, int flags) {
293 out.writeParcelable(new ParcelUuid(mUuid), 0);
294 out.writeInt(mInstance);
295 out.writeInt(mProperties);
296 out.writeInt(mPermissions);
Jakub Pawlowski2168fc22016-04-01 07:17:15 -0700297 out.writeInt(mKeySize);
298 out.writeInt(mWriteType);
Jakub Pawlowski8d312a82016-03-01 18:50:27 -0800299 out.writeTypedList(mDescriptors);
300 }
301
Jack He2992cd02017-08-22 21:21:23 -0700302 public static final Parcelable.Creator<BluetoothGattCharacteristic> CREATOR =
303 new Parcelable.Creator<BluetoothGattCharacteristic>() {
Jakub Pawlowski8d312a82016-03-01 18:50:27 -0800304 public BluetoothGattCharacteristic createFromParcel(Parcel in) {
305 return new BluetoothGattCharacteristic(in);
306 }
307
308 public BluetoothGattCharacteristic[] newArray(int size) {
309 return new BluetoothGattCharacteristic[size];
310 }
311 };
312
313 private BluetoothGattCharacteristic(Parcel in) {
Jack Hea355e5e2017-08-22 16:06:54 -0700314 mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
Jakub Pawlowski8d312a82016-03-01 18:50:27 -0800315 mInstance = in.readInt();
316 mProperties = in.readInt();
317 mPermissions = in.readInt();
Jakub Pawlowski2168fc22016-04-01 07:17:15 -0700318 mKeySize = in.readInt();
319 mWriteType = in.readInt();
Jakub Pawlowski8d312a82016-03-01 18:50:27 -0800320
321 mDescriptors = new ArrayList<BluetoothGattDescriptor>();
322
323 ArrayList<BluetoothGattDescriptor> descs =
324 in.createTypedArrayList(BluetoothGattDescriptor.CREATOR);
325 if (descs != null) {
Jack Hea355e5e2017-08-22 16:06:54 -0700326 for (BluetoothGattDescriptor desc : descs) {
Jakub Pawlowski8d312a82016-03-01 18:50:27 -0800327 desc.setCharacteristic(this);
328 mDescriptors.add(desc);
329 }
330 }
331 }
332
333 /**
Jakub Pawlowskid75f5122016-04-01 07:51:45 -0700334 * Returns the desired key size.
Jack Hea355e5e2017-08-22 16:06:54 -0700335 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800336 * @hide
337 */
Jakub Pawlowskid75f5122016-04-01 07:51:45 -0700338 public int getKeySize() {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800339 return mKeySize;
340 }
341
342 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800343 * Adds a descriptor to this characteristic.
344 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
345 *
346 * @param descriptor Descriptor to be added to this characteristic.
347 * @return true, if the descriptor was added to the characteristic
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800348 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800349 public boolean addDescriptor(BluetoothGattDescriptor descriptor) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800350 mDescriptors.add(descriptor);
Matthew Xieddf7e472013-03-01 18:41:02 -0800351 descriptor.setCharacteristic(this);
352 return true;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800353 }
354
355 /**
Andre Eisenbach25b9cf92013-07-08 23:58:16 -0700356 * Get a descriptor by UUID and isntance id.
Jack Hea355e5e2017-08-22 16:06:54 -0700357 *
Andre Eisenbach25b9cf92013-07-08 23:58:16 -0700358 * @hide
359 */
360 /*package*/ BluetoothGattDescriptor getDescriptor(UUID uuid, int instanceId) {
Jack Hea355e5e2017-08-22 16:06:54 -0700361 for (BluetoothGattDescriptor descriptor : mDescriptors) {
Andre Eisenbach25b9cf92013-07-08 23:58:16 -0700362 if (descriptor.getUuid().equals(uuid)
Jack Hea355e5e2017-08-22 16:06:54 -0700363 && descriptor.getInstanceId() == instanceId) {
Andre Eisenbach25b9cf92013-07-08 23:58:16 -0700364 return descriptor;
365 }
366 }
367 return null;
368 }
369
370 /**
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800371 * Returns the service this characteristic belongs to.
Jack Hea355e5e2017-08-22 16:06:54 -0700372 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800373 * @return The asscociated service
374 */
375 public BluetoothGattService getService() {
376 return mService;
377 }
378
379 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800380 * Sets the service associated with this device.
Jack Hea355e5e2017-08-22 16:06:54 -0700381 *
Matthew Xieddf7e472013-03-01 18:41:02 -0800382 * @hide
383 */
384 /*package*/ void setService(BluetoothGattService service) {
385 mService = service;
386 }
387
388 /**
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800389 * Returns the UUID of this characteristic
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800390 *
391 * @return UUID of this characteristic
392 */
393 public UUID getUuid() {
394 return mUuid;
395 }
396
397 /**
398 * Returns the instance ID for this characteristic.
399 *
400 * <p>If a remote device offers multiple characteristics with the same UUID,
401 * the instance ID is used to distuinguish between characteristics.
402 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800403 * @return Instance ID of this characteristic
404 */
405 public int getInstanceId() {
406 return mInstance;
407 }
408
409 /**
Jakub Pawlowskid75f5122016-04-01 07:51:45 -0700410 * Force the instance ID.
Jack Hea355e5e2017-08-22 16:06:54 -0700411 *
Jakub Pawlowskid75f5122016-04-01 07:51:45 -0700412 * @hide
413 */
414 public void setInstanceId(int instanceId) {
415 mInstance = instanceId;
416 }
417
418 /**
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800419 * Returns the properties of this characteristic.
420 *
421 * <p>The properties contain a bit mask of property flags indicating
422 * the features of this characteristic.
423 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800424 * @return Properties of this characteristic
425 */
426 public int getProperties() {
427 return mProperties;
428 }
429
430 /**
431 * Returns the permissions for this characteristic.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800432 *
433 * @return Permissions of this characteristic
434 */
435 public int getPermissions() {
436 return mPermissions;
437 }
438
439 /**
440 * Gets the write type for this characteristic.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800441 *
442 * @return Write type for this characteristic
443 */
444 public int getWriteType() {
445 return mWriteType;
446 }
447
448 /**
449 * Set the write type for this characteristic
450 *
451 * <p>Setting the write type of a characteristic determines how the
452 * {@link BluetoothGatt#writeCharacteristic} function write this
453 * characteristic.
454 *
Jack Hea355e5e2017-08-22 16:06:54 -0700455 * @param writeType The write type to for this characteristic. Can be one of: {@link
456 * #WRITE_TYPE_DEFAULT}, {@link #WRITE_TYPE_NO_RESPONSE} or {@link #WRITE_TYPE_SIGNED}.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800457 */
458 public void setWriteType(int writeType) {
459 mWriteType = writeType;
460 }
461
462 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800463 * Set the desired key size.
Jack Hea355e5e2017-08-22 16:06:54 -0700464 *
Matthew Xieddf7e472013-03-01 18:41:02 -0800465 * @hide
466 */
467 public void setKeySize(int keySize) {
468 mKeySize = keySize;
469 }
470
471 /**
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800472 * Returns a list of descriptors for this characteristic.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800473 *
474 * @return Descriptors for this characteristic
475 */
476 public List<BluetoothGattDescriptor> getDescriptors() {
477 return mDescriptors;
478 }
479
480 /**
481 * Returns a descriptor with a given UUID out of the list of
482 * descriptors for this characteristic.
483 *
Jack Hea355e5e2017-08-22 16:06:54 -0700484 * @return GATT descriptor object or null if no descriptor with the given UUID was found.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800485 */
486 public BluetoothGattDescriptor getDescriptor(UUID uuid) {
Jack Hea355e5e2017-08-22 16:06:54 -0700487 for (BluetoothGattDescriptor descriptor : mDescriptors) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800488 if (descriptor.getUuid().equals(uuid)) {
489 return descriptor;
490 }
491 }
492 return null;
493 }
494
495 /**
496 * Get the stored value for this characteristic.
497 *
498 * <p>This function returns the stored value for this characteristic as
Matthew Xieddf7e472013-03-01 18:41:02 -0800499 * retrieved by calling {@link BluetoothGatt#readCharacteristic}. The cached
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800500 * value of the characteristic is updated as a result of a read characteristic
501 * operation or if a characteristic update notification has been received.
502 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800503 * @return Cached value of the characteristic
504 */
505 public byte[] getValue() {
506 return mValue;
507 }
508
509 /**
510 * Return the stored value of this characteristic.
511 *
512 * <p>The formatType parameter determines how the characteristic value
513 * is to be interpreted. For example, settting formatType to
514 * {@link #FORMAT_UINT16} specifies that the first two bytes of the
515 * characteristic value at the given offset are interpreted to generate the
516 * return value.
517 *
Jack Hea355e5e2017-08-22 16:06:54 -0700518 * @param formatType The format type used to interpret the characteristic value.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800519 * @param offset Offset at which the integer value can be found.
Jack Hea355e5e2017-08-22 16:06:54 -0700520 * @return Cached value of the characteristic or null of offset exceeds value size.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800521 */
522 public Integer getIntValue(int formatType, int offset) {
523 if ((offset + getTypeLen(formatType)) > mValue.length) return null;
524
525 switch (formatType) {
526 case FORMAT_UINT8:
527 return unsignedByteToInt(mValue[offset]);
528
529 case FORMAT_UINT16:
Jack Hea355e5e2017-08-22 16:06:54 -0700530 return unsignedBytesToInt(mValue[offset], mValue[offset + 1]);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800531
532 case FORMAT_UINT32:
Jack Hea355e5e2017-08-22 16:06:54 -0700533 return unsignedBytesToInt(mValue[offset], mValue[offset + 1],
534 mValue[offset + 2], mValue[offset + 3]);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800535 case FORMAT_SINT8:
536 return unsignedToSigned(unsignedByteToInt(mValue[offset]), 8);
537
538 case FORMAT_SINT16:
539 return unsignedToSigned(unsignedBytesToInt(mValue[offset],
Jack Hea355e5e2017-08-22 16:06:54 -0700540 mValue[offset + 1]), 16);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800541
542 case FORMAT_SINT32:
543 return unsignedToSigned(unsignedBytesToInt(mValue[offset],
Jack Hea355e5e2017-08-22 16:06:54 -0700544 mValue[offset + 1], mValue[offset + 2], mValue[offset + 3]), 32);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800545 }
546
547 return null;
548 }
549
550 /**
551 * Return the stored value of this characteristic.
552 * <p>See {@link #getValue} for details.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800553 *
Jack Hea355e5e2017-08-22 16:06:54 -0700554 * @param formatType The format type used to interpret the characteristic value.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800555 * @param offset Offset at which the float value can be found.
Jack Hea355e5e2017-08-22 16:06:54 -0700556 * @return Cached value of the characteristic at a given offset or null if the requested offset
557 * exceeds the value size.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800558 */
559 public Float getFloatValue(int formatType, int offset) {
560 if ((offset + getTypeLen(formatType)) > mValue.length) return null;
561
562 switch (formatType) {
563 case FORMAT_SFLOAT:
Jack Hea355e5e2017-08-22 16:06:54 -0700564 return bytesToFloat(mValue[offset], mValue[offset + 1]);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800565
566 case FORMAT_FLOAT:
Jack Hea355e5e2017-08-22 16:06:54 -0700567 return bytesToFloat(mValue[offset], mValue[offset + 1],
568 mValue[offset + 2], mValue[offset + 3]);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800569 }
570
571 return null;
572 }
573
574 /**
575 * Return the stored value of this characteristic.
576 * <p>See {@link #getValue} for details.
Matthew Xieddf7e472013-03-01 18:41:02 -0800577 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800578 * @param offset Offset at which the string value can be found.
579 * @return Cached value of the characteristic
580 */
581 public String getStringValue(int offset) {
Andre Eisenbach0fd06a12014-12-09 16:42:14 -0800582 if (mValue == null || offset > mValue.length) return null;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800583 byte[] strBytes = new byte[mValue.length - offset];
Jack Hea355e5e2017-08-22 16:06:54 -0700584 for (int i = 0; i != (mValue.length - offset); ++i) strBytes[i] = mValue[offset + i];
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800585 return new String(strBytes);
586 }
587
588 /**
589 * Updates the locally stored value of this characteristic.
590 *
591 * <p>This function modifies the locally stored cached value of this
592 * characteristic. To send the value to the remote device, call
593 * {@link BluetoothGatt#writeCharacteristic} to send the value to the
594 * remote device.
595 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800596 * @param value New value for this characteristic
Jack Hea355e5e2017-08-22 16:06:54 -0700597 * @return true if the locally stored value has been set, false if the requested value could not
598 * be stored locally.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800599 */
600 public boolean setValue(byte[] value) {
601 mValue = value;
602 return true;
603 }
604
605 /**
606 * Set the locally stored value of this characteristic.
607 * <p>See {@link #setValue(byte[])} for details.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800608 *
609 * @param value New value for this characteristic
610 * @param formatType Integer format type used to transform the value parameter
611 * @param offset Offset at which the value should be placed
612 * @return true if the locally stored value has been set
613 */
614 public boolean setValue(int value, int formatType, int offset) {
615 int len = offset + getTypeLen(formatType);
616 if (mValue == null) mValue = new byte[len];
617 if (len > mValue.length) return false;
618
619 switch (formatType) {
620 case FORMAT_SINT8:
621 value = intToSignedBits(value, 8);
622 // Fall-through intended
623 case FORMAT_UINT8:
Jack Hea355e5e2017-08-22 16:06:54 -0700624 mValue[offset] = (byte) (value & 0xFF);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800625 break;
626
627 case FORMAT_SINT16:
628 value = intToSignedBits(value, 16);
629 // Fall-through intended
630 case FORMAT_UINT16:
Jack Hea355e5e2017-08-22 16:06:54 -0700631 mValue[offset++] = (byte) (value & 0xFF);
632 mValue[offset] = (byte) ((value >> 8) & 0xFF);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800633 break;
634
635 case FORMAT_SINT32:
636 value = intToSignedBits(value, 32);
637 // Fall-through intended
638 case FORMAT_UINT32:
Jack Hea355e5e2017-08-22 16:06:54 -0700639 mValue[offset++] = (byte) (value & 0xFF);
640 mValue[offset++] = (byte) ((value >> 8) & 0xFF);
641 mValue[offset++] = (byte) ((value >> 16) & 0xFF);
642 mValue[offset] = (byte) ((value >> 24) & 0xFF);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800643 break;
644
645 default:
646 return false;
647 }
648 return true;
649 }
650
651 /**
652 * Set the locally stored value of this characteristic.
653 * <p>See {@link #setValue(byte[])} for details.
Matthew Xieddf7e472013-03-01 18:41:02 -0800654 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800655 * @param mantissa Mantissa for this characteristic
Jack Hea355e5e2017-08-22 16:06:54 -0700656 * @param exponent exponent value for this characteristic
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800657 * @param formatType Float format type used to transform the value parameter
658 * @param offset Offset at which the value should be placed
659 * @return true if the locally stored value has been set
660 */
661 public boolean setValue(int mantissa, int exponent, int formatType, int offset) {
662 int len = offset + getTypeLen(formatType);
663 if (mValue == null) mValue = new byte[len];
664 if (len > mValue.length) return false;
665
666 switch (formatType) {
667 case FORMAT_SFLOAT:
668 mantissa = intToSignedBits(mantissa, 12);
669 exponent = intToSignedBits(exponent, 4);
Jack Hea355e5e2017-08-22 16:06:54 -0700670 mValue[offset++] = (byte) (mantissa & 0xFF);
671 mValue[offset] = (byte) ((mantissa >> 8) & 0x0F);
672 mValue[offset] += (byte) ((exponent & 0x0F) << 4);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800673 break;
674
675 case FORMAT_FLOAT:
676 mantissa = intToSignedBits(mantissa, 24);
677 exponent = intToSignedBits(exponent, 8);
Jack Hea355e5e2017-08-22 16:06:54 -0700678 mValue[offset++] = (byte) (mantissa & 0xFF);
679 mValue[offset++] = (byte) ((mantissa >> 8) & 0xFF);
680 mValue[offset++] = (byte) ((mantissa >> 16) & 0xFF);
681 mValue[offset] += (byte) (exponent & 0xFF);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800682 break;
683
684 default:
685 return false;
686 }
687
688 return true;
689 }
690
691 /**
692 * Set the locally stored value of this characteristic.
693 * <p>See {@link #setValue(byte[])} for details.
Matthew Xieddf7e472013-03-01 18:41:02 -0800694 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800695 * @param value New value for this characteristic
696 * @return true if the locally stored value has been set
697 */
698 public boolean setValue(String value) {
699 mValue = value.getBytes();
700 return true;
701 }
702
703 /**
704 * Returns the size of a give value type.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800705 */
706 private int getTypeLen(int formatType) {
707 return formatType & 0xF;
708 }
709
710 /**
711 * Convert a signed byte to an unsigned int.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800712 */
713 private int unsignedByteToInt(byte b) {
714 return b & 0xFF;
715 }
716
717 /**
718 * Convert signed bytes to a 16-bit unsigned int.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800719 */
720 private int unsignedBytesToInt(byte b0, byte b1) {
721 return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8));
722 }
723
724 /**
725 * Convert signed bytes to a 32-bit unsigned int.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800726 */
727 private int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) {
728 return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8))
Jack Hea355e5e2017-08-22 16:06:54 -0700729 + (unsignedByteToInt(b2) << 16) + (unsignedByteToInt(b3) << 24);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800730 }
731
732 /**
733 * Convert signed bytes to a 16-bit short float value.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800734 */
735 private float bytesToFloat(byte b0, byte b1) {
736 int mantissa = unsignedToSigned(unsignedByteToInt(b0)
Jack Hea355e5e2017-08-22 16:06:54 -0700737 + ((unsignedByteToInt(b1) & 0x0F) << 8), 12);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800738 int exponent = unsignedToSigned(unsignedByteToInt(b1) >> 4, 4);
Jack Hea355e5e2017-08-22 16:06:54 -0700739 return (float) (mantissa * Math.pow(10, exponent));
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800740 }
741
742 /**
743 * Convert signed bytes to a 32-bit short float value.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800744 */
745 private float bytesToFloat(byte b0, byte b1, byte b2, byte b3) {
746 int mantissa = unsignedToSigned(unsignedByteToInt(b0)
Jack Hea355e5e2017-08-22 16:06:54 -0700747 + (unsignedByteToInt(b1) << 8)
748 + (unsignedByteToInt(b2) << 16), 24);
749 return (float) (mantissa * Math.pow(10, b3));
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800750 }
751
752 /**
753 * Convert an unsigned integer value to a two's-complement encoded
754 * signed value.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800755 */
756 private int unsignedToSigned(int unsigned, int size) {
Jack Hea355e5e2017-08-22 16:06:54 -0700757 if ((unsigned & (1 << size - 1)) != 0) {
758 unsigned = -1 * ((1 << size - 1) - (unsigned & ((1 << size - 1) - 1)));
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800759 }
760 return unsigned;
761 }
762
763 /**
764 * Convert an integer into the signed bits of a given length.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800765 */
766 private int intToSignedBits(int i, int size) {
767 if (i < 0) {
Jack Hea355e5e2017-08-22 16:06:54 -0700768 i = (1 << size - 1) + (i & ((1 << size - 1) - 1));
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800769 }
770 return i;
771 }
772}