Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
DBTGattChar.java
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020 Gothel Software e.K.
4 * Copyright (c) 2020 ZAFENA AB
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26package jau.direct_bt;
27
28import java.lang.ref.WeakReference;
29import java.util.List;
30
31import org.direct_bt.BTException;
32import org.direct_bt.BTGattChar;
33import org.direct_bt.BTGattDesc;
34import org.direct_bt.BTGattService;
35import org.direct_bt.GattCharPropertySet;
36import org.jau.util.BasicTypes;
37import org.direct_bt.BTGattCharListener;
38
39public class DBTGattChar extends DBTObject implements BTGattChar
40{
41 private static final boolean DEBUG = DBTManager.DEBUG;
42
43 /** Characteristics's service weak back-reference */
44 final WeakReference<DBTGattService> wbr_service;
45
46 /**
47 * Characteristic Handle of this instance.
48 * <p>
49 * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
50 * </p>
51 */
52 private final short handle;
53
54 private final GattCharPropertySet properties;
55
56 /* Characteristics Value Type UUID */
57 private final String value_type_uuid;
58
59 /**
60 * Characteristics Value Handle.
61 * <p>
62 * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
63 * </p>
64 */
65 private final short value_handle;
66
67 /* Optional Client Characteristic Configuration index within descriptorList */
68 private final int clientCharacteristicsConfigIndex;
69
70 /* Optional Characteristic User Description index within descriptorList */
71 private final int userDescriptionIndex;
72
73 /* pp */ final List<BTGattDesc> descriptorList;
74
75 boolean enabledNotifyState = false;
76 boolean enabledIndicateState = false;
77
78 /* pp */ DBTGattChar(final long nativeInstance, final DBTGattService service,
79 final short handle, final GattCharPropertySet properties,
80 final String value_type_uuid, final short value_handle,
81 final int clientCharacteristicsConfigIndex,
82 final int userDescriptionIndex)
83 {
84 super(nativeInstance, handle /* hash */);
85 this.wbr_service = new WeakReference<DBTGattService>(service);
86 this.handle = handle;
87
88 this.properties = properties;
89 this.value_type_uuid = value_type_uuid;
90 this.value_handle = value_handle;
91 this.clientCharacteristicsConfigIndex = clientCharacteristicsConfigIndex;
92 this.userDescriptionIndex = userDescriptionIndex;
93 this.descriptorList = getDescriptorsImpl();
94
95 if( DEBUG ) {
96 final boolean hasNotify = properties.isSet(GattCharPropertySet.Type.Notify);
97 final boolean hasIndicate = properties.isSet(GattCharPropertySet.Type.Indicate);
98
99 if( hasNotify || hasIndicate ) {
100 final BTGattCharListener characteristicListener = new BTGattCharListener() {
101 @Override
102 public void notificationReceived(final BTGattChar charDecl, final byte[] value, final long timestamp) {
103 System.err.println("GATTCharacteristicListener.notificationReceived: "+charDecl+
104 ", value[len "+value.length+": "+BasicTypes.bytesHexString(value, 0, -1, true)+"]");
105 }
106 @Override
107 public void indicationReceived(final BTGattChar charDecl, final byte[] value, final long timestamp,
108 final boolean confirmationSent) {
109 System.err.println("GATTCharacteristicListener.indicationReceived: "+charDecl+
110 ", value[len "+value.length+": "+BasicTypes.bytesHexString(value, 0, -1, true)+
111 "], confirmationSent "+confirmationSent);
112 }
113 };
114 this.addCharListener(characteristicListener); // silent, don't enable native GATT ourselves
115 }
116 }
117 }
118 private native List<BTGattDesc> getDescriptorsImpl();
119
120 @Override
121 protected native void deleteImpl(long nativeInstance);
122
123 @Override
124 public synchronized void close() {
125 if( !isNativeValid() ) {
126 return;
127 }
129 super.close();
130 }
131
132 @Override
133 public boolean equals(final Object obj)
134 {
135 if (obj == null || !(obj instanceof DBTGattChar)) {
136 return false;
137 }
138 final DBTGattChar other = (DBTGattChar)obj;
139 return handle == other.handle; /** unique attribute handles */
140 }
141
142 @Override
143 public String getUUID() { return value_type_uuid; }
144
145 @Override
146 public BTGattDesc findGattDesc(final String desc_uuid) {
147 final DBTGattService service = wbr_service.get();
148 if( null == service ) {
149 return null;
150 }
151 final DBTDevice device = service.wbr_device.get();
152 if( null == device ) {
153 return null;
154 }
155 final int size = descriptorList.size();
156 for(int i = 0; i < size; i++ ) {
157 final DBTGattDesc descr = (DBTGattDesc) descriptorList.get(i);
158 if( descr.getUUID().equals(desc_uuid) ) {
159 return descr;
160 }
161 }
162 return null;
163 }
164
165 @Override
166 public final BTGattService getService() { return wbr_service.get(); }
167
168 @Override
169 public final boolean getNotifying(final boolean enabledState[/*2*/]) {
170 enabledState[0] = enabledNotifyState;
171 enabledState[1] = enabledIndicateState;
172 return enabledNotifyState || enabledIndicateState;
173 }
174
175 @Override
176 public final GattCharPropertySet getProperties() { return properties; }
177
178 @Override
179 public final List<BTGattDesc> getDescriptors() { return descriptorList; }
180
181 @Override
182 public final synchronized boolean configNotificationIndication(final boolean enableNotification, final boolean enableIndication, final boolean enabledState[/*2*/])
183 throws IllegalStateException
184 {
185 final boolean hasNotify = properties.isSet(GattCharPropertySet.Type.Notify);
186 final boolean hasIndicate = properties.isSet(GattCharPropertySet.Type.Indicate);
187
188 if( hasNotify || hasIndicate ) {
189 final boolean resEnableNotification = hasNotify && enableNotification;
190 final boolean resEnableIndication = hasIndicate && enableIndication;
191
192 if( resEnableNotification == enabledNotifyState &&
193 resEnableIndication == enabledIndicateState )
194 {
195 enabledState[0] = resEnableNotification;
196 enabledState[1] = resEnableIndication;
197 if( DEBUG ) {
198 System.err.printf("GATTCharacteristic.configNotificationIndication: Unchanged: notification[shall %b, has %b: %b == %b], indication[shall %b, has %b: %b == %b]\n",
199 enableNotification, hasNotify, enabledNotifyState, resEnableNotification,
200 enableIndication, hasIndicate, enabledIndicateState, resEnableIndication);
201 }
202 return true;
203 }
204
205 final boolean res = configNotificationIndicationImpl(enableNotification, enableIndication, enabledState);
206 if( !res ) {
207 enabledState[0] = false;
208 enabledState[1] = false;
209 }
210 if( DEBUG ) {
211 System.err.printf("GATTCharacteristic.configNotificationIndication: res %b, notification[shall %b, has %b: %b -> %b], indication[shall %b, has %b: %b -> %b]\n",
212 res,
213 enableNotification, hasNotify, enabledNotifyState, enabledState[0],
214 enableIndication, hasIndicate, enabledIndicateState, enabledState[1]);
215 }
216 enabledNotifyState = enabledState[0];
217 enabledIndicateState = enabledState[1];
218 return res;
219 } else {
220 enabledState[0] = false;
221 enabledState[1] = false;
222 if( DEBUG ) {
223 System.err.println("GATTCharacteristic.configNotificationIndication: FALSE*: hasNotify "+hasNotify+", hasIndicate "+hasIndicate);
224 }
225 return false;
226 }
227 }
228 private native boolean configNotificationIndicationImpl(boolean enableNotification, boolean enableIndication, final boolean enabledState[/*2*/])
229 throws IllegalStateException;
230
231 @Override
232 public boolean enableNotificationOrIndication(final boolean enabledState[/*2*/])
233 throws IllegalStateException
234 {
235 final boolean enableNotification = properties.isSet(GattCharPropertySet.Type.Notify);
236 final boolean enableIndication = !enableNotification && properties.isSet(GattCharPropertySet.Type.Indicate);
237
238 return configNotificationIndication(enableNotification, enableIndication, enabledState);
239 }
240
241 @Override
242 public boolean disableIndicationNotification() throws IllegalStateException {
243 return configNotificationIndication(false /* enableNotification */, false /* enableIndication */, new boolean[2]);
244 }
245
246 @Override
247 public final boolean addCharListener(final BTGattCharListener listener) {
248 return getService().getDevice().addCharListener( listener, this );
249 }
250
251 @Override
252 public final boolean addCharListener(final BTGattCharListener listener, final boolean enabledState[/*2*/]) {
253 if( !enableNotificationOrIndication(enabledState) ) {
254 return false;
255 }
256 return addCharListener( listener );
257 }
258
259 @Override
260 public final boolean removeCharListener(final BTGattCharListener listener) {
261 return getService().getDevice().removeCharListener( listener );
262 }
263
264 @Override
265 public final int removeAllAssociatedCharListener(final boolean shallDisableIndicationNotification) {
266 if( shallDisableIndicationNotification ) {
268 }
270 }
271
272 /**
273 * Characteristic Handle of this instance.
274 * <p>
275 * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
276 * </p>
277 */
278 public final short getHandle() { return handle; }
279
280 /**
281 * Returns Characteristics Value Handle.
282 * <p>
283 * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
284 * </p>
285 */
286 public final short getValueHandle() { return value_handle; }
287
288 @Override
290 if( 0 > clientCharacteristicsConfigIndex ) {
291 return null;
292 }
293 return descriptorList.get(clientCharacteristicsConfigIndex); // exception if out of bounds
294 }
295
296 @Override
298 if( 0 > userDescriptionIndex ) {
299 return null;
300 }
301 return descriptorList.get(userDescriptionIndex); // exception if out of bounds
302 }
303
304 @Override
305 public final byte[] readValue() throws BTException {
306 return readValueImpl();
307 }
308 private native byte[] readValueImpl() throws BTException;
309
310 @Override
311 public final boolean writeValue(final byte[] value, final boolean withResponse) throws BTException {
312 return writeValueImpl(value, withResponse);
313 }
314 private native boolean writeValueImpl(byte[] argValue, boolean withResponse) throws BTException;
315
316 @Override
317 public final String toString() {
318 if( !isNativeValid() ) {
319 return "Characteristic" + "\u271D" + "[uuid "+getUUID()+", handle 0x"+Integer.toHexString(handle)+"]";
320 }
321 return toStringImpl();
322 }
323 private native String toStringImpl();
324}
final BTGattDesc getUserDescription()
Return the User Description BTGattDesc if available or null.
synchronized void close()
Release the native memory associated with this object The object should not be used following a call ...
BTGattDesc findGattDesc(final String desc_uuid)
Find a BTGattDesc by its desc_uuid.
String getUUID()
Get the UUID of this characteristic.
boolean disableIndicationNotification()
BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3.3 Client Characteristic Configuration.
final List< BTGattDesc > getDescriptors()
Returns a list of BluetoothGattDescriptors this characteristic exposes.
boolean equals(final Object obj)
final short getHandle()
Characteristic Handle of this instance.
final GattCharPropertySet getProperties()
Returns the properties of this characteristic.
final byte[] readValue()
Reads the value of this characteristic.
final boolean addCharListener(final BTGattCharListener listener)
Add the given BTGattCharListener to the listener list if not already present.
boolean enableNotificationOrIndication(final boolean enabledState[])
BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3.3 Client Characteristic Configuration.
final boolean writeValue(final byte[] value, final boolean withResponse)
Writes the value of this characteristic, using one of the following methods depending on withRespons...
final synchronized boolean configNotificationIndication(final boolean enableNotification, final boolean enableIndication, final boolean enabledState[])
BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3.3 Client Characteristic Configuration.
final boolean removeCharListener(final BTGattCharListener listener)
Remove the given associated BTGattCharListener from the listener list if present.
final BTGattDesc getClientCharConfig()
Return the Client Characteristic Configuration BTGattDesc if available or null.
native void deleteImpl(long nativeInstance)
Deletes the native instance.
final BTGattService getService()
Returns the service to which this characteristic belongs to.
final short getValueHandle()
Returns Characteristics Value Handle.
final boolean getNotifying(final boolean enabledState[])
Returns true if notification for changes of this characteristic are activated.
final int removeAllAssociatedCharListener(final boolean shallDisableIndicationNotification)
Disables the notification and/or indication for this characteristic BLE level if disableIndicationNot...
final boolean addCharListener(final BTGattCharListener listener, final boolean enabledState[])
Add the given BTGattCharListener to the listener list if not already present and if enabling the noti...
String getUUID()
Get the UUID of this descriptor.
static final boolean DEBUG
Definition: DBTManager.java:43
BTGattChar event listener for notification and indication events.
Bit mask of GATT Characteristic Properties.
BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.1.1 Characteristic Properties.
boolean removeCharListener(final BTGattCharListener l)
Remove the given BTGattCharListener from the listener list.
boolean addCharListener(final BTGattCharListener listener)
Add the given BTGattCharListener to the listener list if not already present.
int removeAllAssociatedCharListener(final BTGattChar associatedCharacteristic)
Remove all BTGattCharListener from the list, which are associated to the given BTGattChar.
Representing a Gatt Characteristic object from the GATT client perspective.
Definition: BTGattChar.java:49
Representing a Gatt Characteristic Descriptor object from the GATT client perspective.
Definition: BTGattDesc.java:42
Representing a Gatt Service object from the GATT client perspective.
BTDevice getDevice()
Returns the device to which this service belongs to.