Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
DBTScanner10.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 
26 import java.lang.reflect.InvocationTargetException;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.concurrent.atomic.AtomicInteger;
32 import java.util.function.Consumer;
33 
39 import org.direct_bt.BTMode;
41 import org.direct_bt.BTAdapter;
42 import org.direct_bt.BTDevice;
45 import org.direct_bt.BTFactory;
46 import org.direct_bt.BTGattChar;
47 import org.direct_bt.BTGattDesc;
49 import org.direct_bt.BTManager;
51 import org.direct_bt.BTType;
52 import org.direct_bt.BTUtils;
54 import org.direct_bt.EUI48;
61 import org.direct_bt.SMPKeyBin;
63 import org.direct_bt.ScanType;
64 
65 import jau.direct_bt.DBTManager;
66 
67 /**
68  * This Java scanner example uses the Direct-BT fully event driven workflow
69  * and adds multithreading, i.e. one thread processes each found device found
70  * as notified via the event listener.
71  * <p>
72  * This example represents the recommended utilization of Direct-BT.
73  * </p>
74  * <p>
75  * See `dbt_scanner10.cpp` for invocation examples, since both apps are fully compatible.
76  * </p>
77  */
78 public class DBTScanner10 {
79  static final String KEY_PATH = "keys";
80 
81  long timestamp_t0;
82 
83  int RESET_ADAPTER_EACH_CONN = 0;
84  AtomicInteger deviceReadyCount = new AtomicInteger(0);
85 
86  AtomicInteger MULTI_MEASUREMENTS = new AtomicInteger(8);
87  boolean KEEP_CONNECTED = true;
88 
89  boolean GATT_PING_ENABLED = false;
90  boolean REMOVE_DEVICE = true;
91  boolean USE_WHITELIST = false;
92  final List<BDAddressAndType> whitelist = new ArrayList<BDAddressAndType>();
93 
94  String charIdentifier = null;
95  int charValue = 0;
96 
97  boolean SHOW_UPDATE_EVENTS = false;
98  boolean QUIET = false;
99 
100  int shutdownTest = 0;
101 
102  boolean matches(final List<BDAddressAndType> cont, final BDAddressAndType mac) {
103  for(final Iterator<BDAddressAndType> it = cont.iterator(); it.hasNext(); ) {
104  if( it.next().matches(mac) ) {
105  return true;
106  }
107  }
108  return false;
109  }
110 
111  static void printf(final String format, final Object... args) {
112  final Object[] args2 = new Object[args.length+1];
113  args2[0] = BTUtils.elapsedTimeMillis();
114  System.arraycopy(args, 0, args2, 1, args.length);
115  System.err.printf("[%,9d] "+format, args2);
116  // System.err.printf("[%,9d] ", BluetoothUtils.getElapsedMillisecond());
117  // System.err.printf(format, args);
118  }
119 
120  static void executeOffThread(final Runnable runobj, final String threadName, final boolean detach) {
121  final Thread t = new Thread( runobj, threadName );
122  if( detach ) {
123  t.setDaemon(true); // detach thread
124  }
125  t.start();
126  }
127  static void execute(final Runnable task, final boolean offThread) {
128  if( offThread ) {
129  final Thread t = new Thread(task);
130  t.setDaemon(true);
131  t.start();
132  } else {
133  task.run();
134  }
135  }
136 
137  class MyAdapterStatusListener extends AdapterStatusListener {
138  @Override
139  public void adapterSettingsChanged(final BTAdapter adapter, final AdapterSettings oldmask,
140  final AdapterSettings newmask, final AdapterSettings changedmask, final long timestamp) {
141  final boolean initialSetting = oldmask.isEmpty();
142  if( initialSetting ) {
143  BTUtils.println(System.err, "****** SETTINGS: "+oldmask+" -> "+newmask+", initial "+changedmask);
144  } else {
145  BTUtils.println(System.err, "****** SETTINGS: "+oldmask+" -> "+newmask+", changed "+changedmask);
146  }
147  BTUtils.println(System.err, "Status Adapter:");
148  BTUtils.println(System.err, adapter.toString());
149  if( !initialSetting &&
150  changedmask.isSet(AdapterSettings.SettingType.POWERED) &&
152  {
153 
154  executeOffThread( () -> { startDiscovery(adapter, "powered-on"); },
155  "DBT-StartDiscovery-"+adapter.getAddressAndType(), true /* detach */);
156  }
157  }
158 
159  @Override
160  public void discoveringChanged(final BTAdapter adapter, final ScanType currentMeta, final ScanType changedType, final boolean changedEnabled, final boolean keepAlive, final long timestamp) {
161  BTUtils.println(System.err, "****** DISCOVERING: meta "+currentMeta+", changed["+changedType+", enabled "+changedEnabled+", keepAlive "+keepAlive+"] on "+adapter);
162  }
163 
164  @Override
165  public boolean deviceFound(final BTDevice device, final long timestamp) {
166  BTUtils.println(System.err, "****** FOUND__: "+device.toString());
167 
170  // Requires BREDR or LE Secure Connection support: WIP
171  BTUtils.println(System.err, "****** FOUND__-2: Skip non 'public LE' and non 'random static public LE' "+device.toString());
172  return false;
173  }
177  ( 0 < MULTI_MEASUREMENTS.get() || !BTDeviceRegistry.isDeviceProcessed(device.getAddressAndType()) )
178  )
179  )
180  )
181  {
182  BTUtils.println(System.err, "****** FOUND__-0: Connecting "+device.toString());
183  {
184  final long td = BTUtils.currentTimeMillis() - timestamp_t0; // adapter-init -> now
185  BTUtils.println(System.err, "PERF: adapter-init -> FOUND__-0 " + td + " ms");
186  }
187  executeOffThread( () -> { connectDiscoveredDevice(device); },
188  "DBT-Connect-"+device.getAddressAndType(), true /* detach */);
189  return true;
190  } else {
191  BTUtils.println(System.err, "****** FOUND__-1: NOP "+device.toString());
192  return false;
193  }
194  }
195 
196  @Override
197  public void deviceUpdated(final BTDevice device, final EIRDataTypeSet updateMask, final long timestamp) {
198  if( SHOW_UPDATE_EVENTS ) {
199  BTUtils.println(System.err, "****** UPDATED: "+updateMask+" of "+device);
200  }
201  }
202 
203  @Override
204  public void deviceConnected(final BTDevice device, final short handle, final long timestamp) {
205  BTUtils.println(System.err, "****** CONNECTED: "+device.toString());
206  }
207 
208  @Override
209  public void devicePairingState(final BTDevice device, final SMPPairingState state, final PairingMode mode, final long timestamp) {
210  BTUtils.println(System.err, "****** PAIRING_STATE: state "+state+", mode "+mode+": "+device);
211  switch( state ) {
212  case NONE:
213  // next: deviceReady(..)
214  break;
215  case FAILED: {
216  final boolean res = SMPKeyBin.remove(KEY_PATH, device.getAddressAndType());
217  BTUtils.println(System.err, "****** PAIRING_STATE: state "+state+"; Remove key file "+SMPKeyBin.getFilename(KEY_PATH, device.getAddressAndType())+", res "+res);
218  // next: deviceReady() or deviceDisconnected(..)
219  } break;
220  case REQUESTED_BY_RESPONDER:
221  // next: FEATURE_EXCHANGE_STARTED
222  break;
223  case FEATURE_EXCHANGE_STARTED:
224  // next: FEATURE_EXCHANGE_COMPLETED
225  break;
226  case FEATURE_EXCHANGE_COMPLETED:
227  // next: PASSKEY_EXPECTED... or KEY_DISTRIBUTION
228  break;
229  case PASSKEY_EXPECTED: {
231  if( null != sec && sec.getPairingPasskey() != BTSecurityRegistry.NO_PASSKEY ) {
232  executeOffThread( () -> { device.setPairingPasskey( sec.getPairingPasskey() ); }, "DBT-SetPasskey-"+device.getAddressAndType(), true /* detach */);
233  } else {
234  executeOffThread( () -> { device.setPairingPasskey( 0 ); }, "DBT-SetPasskey-"+device.getAddressAndType(), true /* detach */);
235  // 3s disconnect: executeOffThread( () -> { device.setPairingPasskeyNegative(); }, "DBT-SetPasskeyNegative-"+device.getAddressAndType(), true /* detach */);
236  }
237  // next: KEY_DISTRIBUTION or FAILED
238  } break;
239  case NUMERIC_COMPARE_EXPECTED: {
241  if( null != sec ) {
242  executeOffThread( () -> { device.setPairingNumericComparison( sec.getPairingNumericComparison() ); }, "DBT-SetNumericComp-"+device.getAddressAndType(), true /* detach */);
243  } else {
244  executeOffThread( () -> { device.setPairingNumericComparison( false ); }, "DBT-SetNumericCompFalse-"+device.getAddressAndType(), true /* detach */);
245  }
246  // next: KEY_DISTRIBUTION or FAILED
247  } break;
248  case OOB_EXPECTED:
249  // FIXME: ABORT
250  break;
251  case KEY_DISTRIBUTION:
252  // next: COMPLETED or FAILED
253  break;
254  case COMPLETED:
255  // next: deviceReady(..)
256  break;
257  default: // nop
258  break;
259  }
260  }
261 
262  @Override
263  public void deviceReady(final BTDevice device, final long timestamp) {
267  ( 0 < MULTI_MEASUREMENTS.get() || !BTDeviceRegistry.isDeviceProcessed(device.getAddressAndType()) )
268  )
269  )
270  )
271  {
272  deviceReadyCount.incrementAndGet();
273  BTUtils.println(System.err, "****** READY-0: Processing["+deviceReadyCount.get()+"] "+device.toString());
274  {
275  final long td = BTUtils.currentTimeMillis() - timestamp_t0; // adapter-init -> now
276  BTUtils.println(System.err, "PERF: adapter-init -> READY-0 " + td + " ms");
277  }
279  processReadyDevice(device); // AdapterStatusListener::deviceReady() explicitly allows prolonged and complex code execution!
280  } else {
281  BTUtils.println(System.err, "****** READY-1: NOP " + device.toString());
282  }
283  }
284 
285  @Override
286  public void deviceDisconnected(final BTDevice device, final HCIStatusCode reason, final short handle, final long timestamp) {
287  BTUtils.println(System.err, "****** DISCONNECTED: Reason "+reason+", old handle 0x"+Integer.toHexString(handle)+": "+device+" on "+device.getAdapter());
288 
289  if( REMOVE_DEVICE ) {
290  executeOffThread( () -> { removeDevice(device); }, "DBT-Remove-"+device.getAddressAndType(), true /* detach */);
291  } else {
293  }
294  if( 0 < RESET_ADAPTER_EACH_CONN && 0 == deviceReadyCount.get() % RESET_ADAPTER_EACH_CONN ) {
295  executeOffThread( () -> { resetAdapter(device.getAdapter(), 1); },
296  "DBT-Reset-"+device.getAdapter().getAddressAndType(), true /* detach */ );
297  }
298  }
299 
300  @Override
301  public String toString() {
302  return "AdapterStatusListener[user, per-adapter]";
303  }
304  };
305 
306  class MyGATTEventListener implements BTGattChar.Listener {
307  private final int i, j;
308 
309  public MyGATTEventListener(final int i_, final int j_) { i=i_; j=j_; }
310 
311  @Override
312  public void notificationReceived(final BTGattChar charDecl,
313  final byte[] value, final long timestamp) {
314  final long tR = BTUtils.currentTimeMillis();
315  printf("**[%02d.%02d] Characteristic-Notify: UUID %s, td %d ******\n",
316  i, j, charDecl.getUUID(), (tR-timestamp));
317  printf("**[%02d.%02d] Characteristic: %s ******\n", i, j, charDecl.toString());
318  printf("**[%02d.%02d] Value R: size %d, ro: %s ******\n", i, j, value.length, BTUtils.bytesHexString(value, 0, -1, true));
319 
320  shutdownTest();
321  }
322 
323  @Override
324  public void indicationReceived(final BTGattChar charDecl,
325  final byte[] value, final long timestamp, final boolean confirmationSent) {
326  final long tR = BTUtils.currentTimeMillis();
327  printf("**[%02d.%02d] Characteristic-Indication: UUID %s, td %d, confirmed %b ******\n",
328  i, j, charDecl.getUUID(), (tR-timestamp), confirmationSent);
329  printf("**[%02d.%02d] Characteristic: %s ******\n", i, j, charDecl.toString());
330  printf("**[%02d.%02d] Value R: size %d, ro: %s ******\n", i, j, value.length, BTUtils.bytesHexString(value, 0, -1, true));
331 
332  shutdownTest();
333  }
334  }
335 
336  private void connectDiscoveredDevice(final BTDevice device) {
337  BTUtils.println(System.err, "****** Connecting Device: Start " + device.toString());
338 
339  // Testing listener lifecycle @ device dtor
341  @Override
342  public void deviceUpdated(final BTDevice device, final EIRDataTypeSet updateMask, final long timestamp) {
343  if( SHOW_UPDATE_EVENTS ) {
344  BTUtils.println(System.err, "****** UPDATED(2): "+updateMask+" of "+device);
345  }
346  }
347  @Override
348  public void deviceConnected(final BTDevice device, final short handle, final long timestamp) {
349  BTUtils.println(System.err, "****** CONNECTED(2): "+device.toString());
350  }
351 
352  @Override
353  public String toString() {
354  return "TempAdapterStatusListener[user, device "+device.getAddressAndType().toString()+"]";
355  } });
356 
357  {
358  final HCIStatusCode r = device.unpair();
359  BTUtils.println(System.err, "****** Connecting Device: Unpair-Pre result: "+r);
360  }
361 
362  {
363  final HCIStatusCode r = device.getAdapter().stopDiscovery();
364  BTUtils.println(System.err, "****** Connecting Device: stopDiscovery result "+r);
365  }
366 
368  if( null != sec ) {
369  BTUtils.println(System.err, "****** Connecting Device: Found SecurityDetail "+sec.toString()+" for "+device.toString());
370  } else {
371  BTUtils.println(System.err, "****** Connecting Device: No SecurityDetail for "+device.toString());
372  }
373  final BTSecurityLevel req_sec_level = null != sec ? sec.getSecLevel() : BTSecurityLevel.UNSET;
374  HCIStatusCode res = SMPKeyBin.readAndApply(KEY_PATH, device, req_sec_level, true /* verbose */);
375  BTUtils.fprintf_td(System.err, "****** Connecting Device: SMPKeyBin::readAndApply(..) result %s\n", res.toString());
376  if( HCIStatusCode.SUCCESS != res ) {
377  if( null != sec ) {
378  if( sec.isSecurityAutoEnabled() ) {
379  final boolean r = device.setConnSecurityAuto( sec.getSecurityAutoIOCap() );
380  BTUtils.println(System.err, "****** Connecting Device: Using SecurityDetail.SEC AUTO "+sec+" -> set OK "+r);
381  } else if( sec.isSecLevelOrIOCapSet() ) {
382  final boolean r = device.setConnSecurityBest(sec.getSecLevel(), sec.getIOCap());
383  BTUtils.println(System.err, "****** Connecting Device: Using SecurityDetail.Level+IOCap "+sec+" -> set OK "+r);
384  } else {
385  final boolean r = device.setConnSecurityAuto( SMPIOCapability.KEYBOARD_ONLY );
386  BTUtils.println(System.err, "****** Connecting Device: Setting SEC AUTO security detail w/ KEYBOARD_ONLY ("+sec+") -> set OK "+r);
387  }
388  } else {
389  final boolean r = device.setConnSecurityAuto( SMPIOCapability.KEYBOARD_ONLY );
390  BTUtils.println(System.err, "****** Connecting Device: Setting SEC AUTO security detail w/ KEYBOARD_ONLY -> set OK "+r);
391  }
392  }
393 
394  if( !USE_WHITELIST ) {
395  res = device.connect();
396  } else {
397  res = HCIStatusCode.SUCCESS;
398  }
399  BTUtils.println(System.err, "****** Connecting Device Command, res "+res+": End result "+res+" of " + device.toString());
400 
401  if( !USE_WHITELIST && 0 == BTDeviceRegistry.getProcessingDeviceCount() && HCIStatusCode.SUCCESS != res ) {
402  startDiscovery(device.getAdapter(), "post-connect");
403  }
404  }
405 
406  void shutdownTest() {
407  switch( shutdownTest ) {
408  case 1:
409  shutdownTest01();
410  break;
411  case 2:
412  shutdownTest02();
413  break;
414  default:
415  // nop
416  }
417  }
418  void shutdownTest01() {
419  execute( () -> {
420  final DBTManager mngr = (DBTManager) DBTManager.getManager();
421  mngr.shutdown();
422  }, true);
423  }
424  void shutdownTest02() {
425  execute( () -> {
426  System.exit(1);
427  }, true);
428  }
429 
430  private void processReadyDevice(final BTDevice device) {
431  BTUtils.println(System.err, "****** Processing Ready Device: Start " + device.toString());
432  {
433  // make sure for pending connections on failed connect*(..) command
434  final HCIStatusCode r = device.getAdapter().stopDiscovery();
435  BTUtils.println(System.err, "****** Processing Ready Device: stopDiscovery result "+r);
436  }
437 
438  final long t1 = BTUtils.currentTimeMillis();
439 
440  SMPKeyBin.createAndWrite(device, KEY_PATH, false /* overwrite */, true /* verbose */);
441 
442  boolean success = false;
443 
444  //
445  // GATT Service Processing
446  //
447  try {
448  final List<BTGattService> primServices = device.getServices(); // implicit GATT connect...
449  if( null == primServices || 0 == primServices.size() ) {
450  // Cheating the flow, but avoiding: goto, do-while-false and lastly unreadable intendations
451  // And it is an error case nonetheless ;-)
452  throw new RuntimeException("Processing Ready Device: getServices() failed " + device.toString());
453  }
454  final long t5 = BTUtils.currentTimeMillis();
455  if( !QUIET ) {
456  final long td01 = t1 - timestamp_t0; // adapter-init -> processing-start
457  final long td15 = t5 - t1; // get-gatt-services
458  final long tdc5 = t5 - device.getLastDiscoveryTimestamp(); // discovered to gatt-complete
459  final long td05 = t5 - timestamp_t0; // adapter-init -> gatt-complete
460  BTUtils.println(System.err, System.lineSeparator()+System.lineSeparator());
461  BTUtils.println(System.err, "PERF: GATT primary-services completed\n");
462  BTUtils.println(System.err, "PERF: adapter-init to processing-start " + td01 + " ms,"+System.lineSeparator()+
463  "PERF: get-gatt-services " + td15 + " ms,"+System.lineSeparator()+
464  "PERF: discovered to gatt-complete " + tdc5 + " ms (connect " + (tdc5 - td15) + " ms),"+System.lineSeparator()+
465  "PERF: adapter-init to gatt-complete " + td05 + " ms"+System.lineSeparator());
466  }
467  {
468  // WIP: Implement a simple Characteristic ping-pong writeValue <-> notify transmission for stress testing.
469  final BTManager manager = device.getAdapter().getManager();
470  if( null != charIdentifier && charIdentifier.length() > 0 ) {
471  final BTGattChar char2 = (BTGattChar)
472  manager.find(BTType.GATT_CHARACTERISTIC, null, charIdentifier, device);
473  BTUtils.println(System.err, "Char UUID "+charIdentifier);
474  BTUtils.println(System.err, " over device : "+char2);
475  if( null != char2 ) {
476  final BTGattChar.Listener charPingPongListener = new BTGattChar.Listener() {
477  @Override
478  public void notificationReceived(final BTGattChar charDecl,
479  final byte[] value, final long timestamp) {
480  BTUtils.println(System.err, "****** PingPong GATT notificationReceived: "+charDecl+
481  ", value "+BTUtils.bytesHexString(value, 0, -1, true));
482  }
483 
484  @Override
485  public void indicationReceived(final BTGattChar charDecl,
486  final byte[] value, final long timestamp, final boolean confirmationSent) {
487  BTUtils.println(System.err, "****** PingPong GATT indicationReceived: "+charDecl+
488  ", value "+BTUtils.bytesHexString(value, 0, -1, true));
489  }
490  };
491  final boolean enabledState[] = { false, false };
492  final boolean addedCharPingPongListenerRes = char2.addCharListener(charPingPongListener, enabledState);
493  if( !QUIET ) {
494  BTUtils.println(System.err, "Added CharPingPongListenerRes: "+addedCharPingPongListenerRes+", enabledState "+Arrays.toString(enabledState));
495  }
496  if( addedCharPingPongListenerRes ) {
497  final byte[] cmd = { (byte)charValue }; // request device model
498  final boolean wres = char2.writeValue(cmd, false /* withResponse */);
499  if( !QUIET ) {
500  BTUtils.println(System.err, "Write response: "+wres);
501  }
502  }
503  }
504  }
505  }
506 
507  try {
508  int i=0;
509  for(final Iterator<BTGattService> srvIter = primServices.iterator(); srvIter.hasNext(); i++) {
510  final BTGattService primService = srvIter.next();
511  if( !QUIET ) {
512  printf(" [%02d] Service UUID %s\n", i, primService.getUUID());
513  printf(" [%02d] %s\n", i, primService.toString());
514  }
515  int j=0;
516  final List<BTGattChar> serviceCharacteristics = primService.getChars();
517  for(final Iterator<BTGattChar> charIter = serviceCharacteristics.iterator(); charIter.hasNext(); j++) {
518  final BTGattChar serviceChar = charIter.next();
519  if( !QUIET ) {
520  printf(" [%02d.%02d] Characteristic: UUID %s\n", i, j, serviceChar.getUUID());
521  printf(" [%02d.%02d] %s\n", i, j, serviceChar.toString());
522  }
523  final GattCharPropertySet properties = serviceChar.getProperties();
524  if( properties.isSet(GattCharPropertySet.Type.Read) ) {
525  final byte[] value = serviceChar.readValue();
526  final String svalue = BTUtils.decodeUTF8String(value, 0, value.length);
527  if( !QUIET ) {
528  printf(" [%02d.%02d] value: %s ('%s')\n", i, j, BTUtils.bytesHexString(value, 0, -1, true), svalue);
529  }
530  }
531  int k=0;
532  final List<BTGattDesc> charDescList = serviceChar.getDescriptors();
533  for(final Iterator<BTGattDesc> descIter = charDescList.iterator(); descIter.hasNext(); k++) {
534  final BTGattDesc charDesc = descIter.next();
535  if( !QUIET ) {
536  printf(" [%02d.%02d.%02d] Descriptor: UUID %s\n", i, j, k, charDesc.getUUID());
537  printf(" [%02d.%02d.%02d] %s\n", i, j, k, charDesc.toString());
538  }
539  }
540  final boolean cccdEnableResult[] = { false, false };
541  final boolean cccdRet = serviceChar.addCharListener( new MyGATTEventListener(i, j), cccdEnableResult );
542  if( !QUIET ) {
543  printf(" [%02d.%02d] Characteristic-Listener: Notification(%b), Indication(%b): Added %b\n",
544  i, j, cccdEnableResult[0], cccdEnableResult[1], cccdRet);
545  printf("\n");
546  }
547  }
548  printf("\n");
549  }
550  } catch( final Exception ex) {
551  BTUtils.println(System.err, "Caught "+ex.getMessage());
552  ex.printStackTrace();
553  }
554  // FIXME sleep 1s for potential callbacks ..
555  try {
556  Thread.sleep(1000);
557  } catch (final InterruptedException e) {
558  e.printStackTrace();
559  }
560  success = true;
561  } catch (final Throwable t ) {
562  BTUtils.println(System.err, "****** Processing Ready Device: Exception caught for " + device.toString() + ": "+t.getMessage());
563  t.printStackTrace();
564  }
565 
566  BTUtils.println(System.err, "****** Processing Ready Device: End-1: Success " + success +
567  " on " + device.toString() + "; devInProc "+BTDeviceRegistry.getProcessingDeviceCount());
568 
570 
571  if( !USE_WHITELIST && 0 == BTDeviceRegistry.getProcessingDeviceCount() ) {
572  startDiscovery(device.getAdapter(), "post-processing-1");
573  }
574 
575  if( KEEP_CONNECTED && GATT_PING_ENABLED && success ) {
576  while( device.pingGATT() ) {
577  BTUtils.println(System.err, "****** Processing Ready Device: pingGATT OK: "+device.getAddressAndType());
578  try {
579  Thread.sleep(1000);
580  } catch (final InterruptedException e) {
581  e.printStackTrace();
582  }
583  }
584  BTUtils.println(System.err, "****** Processing Ready Device: pingGATT failed, waiting for disconnect: "+device.getAddressAndType());
585  // Even w/ GATT_PING_ENABLED, we utilize disconnect event to clean up -> remove
586  }
587 
588  BTUtils.println(System.err, "****** Processing Ready Device: End-2: Success " + success +
589  " on " + device.toString() + "; devInProc "+BTDeviceRegistry.getProcessingDeviceCount());
590  if( success ) {
592  }
593  device.removeAllCharListener();
594 
595  if( !KEEP_CONNECTED ) {
596 
597  {
598  final HCIStatusCode unpair_res = device.unpair();
599  BTUtils.println(System.err, "****** Processing Ready Device: Unpair-Post result: "+unpair_res);
600  }
601 
602  device.remove();
603 
604  if( 0 < RESET_ADAPTER_EACH_CONN && 0 == deviceReadyCount.get() % RESET_ADAPTER_EACH_CONN ) {
605  resetAdapter(device.getAdapter(), 2);
606  } else if( !USE_WHITELIST && 0 == BTDeviceRegistry.getProcessingDeviceCount() ) {
607  startDiscovery(device.getAdapter(), "post-processing-2");
608  }
609  }
610 
611  if( 0 < MULTI_MEASUREMENTS.get() ) {
612  MULTI_MEASUREMENTS.decrementAndGet();
613  BTUtils.println(System.err, "****** Processing Ready Device: MULTI_MEASUREMENTS left "+MULTI_MEASUREMENTS.get()+": "+device.getAddressAndType());
614  }
615  }
616 
617  private void removeDevice(final BTDevice device) {
618  BTUtils.println(System.err, "****** Remove Device: removing: "+device.getAddressAndType());
619  device.getAdapter().stopDiscovery();
620 
622 
623  device.remove();
624 
625  if( !USE_WHITELIST && 0 == BTDeviceRegistry.getProcessingDeviceCount() ) {
626  startDiscovery(device.getAdapter(), "post-remove-device");
627  }
628  }
629 
630  private void resetAdapter(final BTAdapter adapter, final int mode) {
631  BTUtils.println(System.err, "****** Reset Adapter: reset["+mode+"] start: "+adapter.toString());
632  final HCIStatusCode res = adapter.reset();
633  BTUtils.println(System.err, "****** Reset Adapter: reset["+mode+"] end: "+res+", "+adapter.toString());
634  }
635 
636  static boolean le_scan_active = true; // default value
637  static final short le_scan_interval = (short)24; // default value
638  static final short le_scan_window = (short)24; // default value
639  static final byte filter_policy = (byte)0; // default value
640 
641  private boolean startDiscovery(final BTAdapter adapter, final String msg) {
642  final HCIStatusCode status = adapter.startDiscovery( true, le_scan_active, le_scan_interval, le_scan_window, filter_policy );
643  BTUtils.println(System.err, "****** Start discovery ("+msg+") result: "+status);
644  return HCIStatusCode.SUCCESS == status;
645  }
646 
647  private boolean initAdapter(final BTAdapter adapter) {
648  // Even if adapter is not yet powered, listen to it and act when it gets powered-on
649  adapter.addStatusListener(new MyAdapterStatusListener() );
650  // Flush discovered devices after registering our status listener.
651  // This avoids discovered devices before we have registered!
652  adapter.removeDiscoveredDevices();
653 
654  if( !adapter.isPowered() ) { // should have been covered above
655  BTUtils.println(System.err, "Adapter not powered (2): "+adapter.toString());
656  return false;
657  }
658 
659  if( USE_WHITELIST ) {
660  for(final Iterator<BDAddressAndType> wliter = whitelist.iterator(); wliter.hasNext(); ) {
661  final BDAddressAndType addr = wliter.next();
662  final boolean res = adapter.addDeviceToWhitelist(addr, HCIWhitelistConnectType.HCI_AUTO_CONN_ALWAYS);
663  BTUtils.println(System.err, "Added to whitelist: res "+res+", address "+addr);
664  }
665  } else {
666  if( !startDiscovery(adapter, "kick-off") ) {
667  return false;
668  }
669  }
670  return true;
671  }
672 
673  private final BTManager.ChangedAdapterSetListener myChangedAdapterSetListener =
675  @Override
676  public void adapterAdded(final BTAdapter adapter) {
677  if( initAdapter( adapter ) ) {
678  BTUtils.println(System.err, "****** Adapter ADDED__: InitOK. " + adapter);
679  } else {
680  BTUtils.println(System.err, "****** Adapter ADDED__: Ignored " + adapter);
681  }
682  }
683 
684  @Override
685  public void adapterRemoved(final BTAdapter adapter) {
686  BTUtils.println(System.err, "****** Adapter REMOVED: " + adapter);
687  }
688  };
689 
690  public void runTest(final BTManager manager) {
691  timestamp_t0 = BTUtils.currentTimeMillis();
692 
693  boolean done = false;
694 
695  manager.addChangedAdapterSetListener(myChangedAdapterSetListener);
696 
697  while( !done ) {
698  if( 0 == MULTI_MEASUREMENTS.get() ||
699  ( -1 == MULTI_MEASUREMENTS.get() && BTDeviceRegistry.isWaitingForAnyDevice() && BTDeviceRegistry.areAllDevicesProcessed() )
700  )
701  {
702  BTUtils.println(System.err, "****** EOL Test MULTI_MEASUREMENTS left "+MULTI_MEASUREMENTS.get()+
704  BTUtils.println(System.err, "****** WaitForDevices "+BTDeviceRegistry.getWaitForDevicesString());
705  BTUtils.println(System.err, "****** DevicesProcessed "+BTDeviceRegistry.getProcessedDevicesString());
706  done = true;
707  } else {
708  try {
709  Thread.sleep(2000);
710  } catch (final InterruptedException e) {
711  e.printStackTrace();
712  }
713  }
714  }
715 
716  //
717  // just a manually controlled pull down to show status, not required
718  //
719  final List<BTAdapter> adapters = manager.getAdapters();
720 
721  adapters.forEach(new Consumer<BTAdapter>() {
722  @Override
723  public void accept(final BTAdapter a) {
724  BTUtils.println(System.err, "****** EOL Adapter's Devices - pre_ close: " + a);
725  } } );
726  {
727  final int count = manager.removeChangedAdapterSetListener(myChangedAdapterSetListener);
728  BTUtils.println(System.err, "****** EOL Removed ChangedAdapterSetCallback " + count);
729 
730  // All implicit via destructor or shutdown hook!
731  manager.shutdown(); /* implies: adapter.close(); */
732  }
733  adapters.forEach(new Consumer<BTAdapter>() {
734  @Override
735  public void accept(final BTAdapter a) {
736  BTUtils.println(System.err, "****** EOL Adapter's Devices - post close: " + a);
737  } } );
738 
739  }
740 
741  public static void main(final String[] args) throws InterruptedException {
742  for(int i=0; i< args.length; i++) {
743  final String arg = args[i];
744  if( arg.equals("-debug") ) {
745  System.setProperty("org.tinyb.verbose", "true");
746  System.setProperty("org.tinyb.debug", "true");
747  } else if( arg.equals("-verbose") ) {
748  System.setProperty("org.tinyb.verbose", "true");
749  } else if( arg.equals("-dbt_debug") && args.length > (i+1) ) {
750  System.setProperty("direct_bt.debug", args[++i]);
751  } else if( arg.equals("-dbt_verbose") && args.length > (i+1) ) {
752  System.setProperty("direct_bt.verbose", args[++i]);
753  } else if( arg.equals("-dbt_gatt") && args.length > (i+1) ) {
754  System.setProperty("direct_bt.gatt", args[++i]);
755  } else if( arg.equals("-dbt_l2cap") && args.length > (i+1) ) {
756  System.setProperty("direct_bt.l2cap", args[++i]);
757  } else if( arg.equals("-dbt_hci") && args.length > (i+1) ) {
758  System.setProperty("direct_bt.hci", args[++i]);
759  } else if( arg.equals("-dbt_mgmt") && args.length > (i+1) ) {
760  System.setProperty("direct_bt.mgmt", args[++i]);
761  } else if( arg.equals("-btmode") && args.length > (i+1) ) {
762  final BTMode btmode = BTMode.get(args[++i]);
763  System.setProperty("org.tinyb.btmode", btmode.toString());
764  System.err.println("Setting 'org.tinyb.btmode' to "+btmode.toString());
765  }
766  }
767  final BTManager manager;
768  try {
769  manager = BTFactory.getDirectBTManager();
770  } catch (BTException | NoSuchMethodException | SecurityException
771  | IllegalAccessException | IllegalArgumentException
772  | InvocationTargetException | ClassNotFoundException e) {
773  System.err.println("Unable to instantiate DirectBT BluetoothManager");
774  e.printStackTrace();
775  System.exit(-1);
776  return;
777  }
778  BTUtils.println(System.err, "DirectBT BluetoothManager initialized!");
779  BTUtils.println(System.err, "DirectBT Native Version "+BTFactory.getNativeVersion()+" (API "+BTFactory.getNativeAPIVersion()+")");
780  BTUtils.println(System.err, "DirectBT Java Version "+BTFactory.getImplVersion()+" (API "+BTFactory.getAPIVersion()+")");
781 
782  final DBTScanner10 test = new DBTScanner10();
783 
784  boolean waitForEnter=false;
785  {
786  for(int i=0; i< args.length; i++) {
787  final String arg = args[i];
788 
789  if( arg.equals("-wait") ) {
790  waitForEnter = true;
791  } else if( arg.equals("-show_update_events") ) {
792  test.SHOW_UPDATE_EVENTS = true;
793  } else if( arg.equals("-quiet") ) {
794  test.QUIET = true;
795  } else if( arg.equals("-scanPassive") ) {
796  le_scan_active = false;
797  } else if( arg.equals("-shutdown") && args.length > (i+1) ) {
798  test.shutdownTest = Integer.valueOf(args[++i]).intValue();
799  } else if( arg.equals("-dev") && args.length > (i+1) ) {
801  } else if( arg.equals("-wl") && args.length > (i+1) ) {
802  final BDAddressAndType wle = new BDAddressAndType(new EUI48(args[++i]), BDAddressType.BDADDR_LE_PUBLIC);
803  BTUtils.println(System.err, "Whitelist + "+wle);
804  test.whitelist.add(wle);
805  test.USE_WHITELIST = true;
806  } else if( arg.equals("-passkey") && args.length > (i+2) ) {
807  final String addrOrNameSub = args[++i];
808  final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getOrCreate(addrOrNameSub);
809  sec.passkey = Integer.valueOf(args[++i]).intValue();
810  System.err.println("Set passkey in "+sec);
811  } else if( arg.equals("-seclevel") && args.length > (i+2) ) {
812  final String addrOrNameSub = args[++i];
813  final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getOrCreate(addrOrNameSub);
814  final int sec_level_i = Integer.valueOf(args[++i]).intValue();
815  sec.sec_level = BTSecurityLevel.get( (byte)( sec_level_i & 0xff ) );
816  System.err.println("Set sec_level "+sec_level_i+" in "+sec);
817  } else if( arg.equals("-iocap") && args.length > (i+2) ) {
818  final String addrOrNameSub = args[++i];
819  final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getOrCreate(addrOrNameSub);
820  final int io_cap_i = Integer.valueOf(args[++i]).intValue();
821  sec.io_cap = SMPIOCapability.get( (byte)( io_cap_i & 0xff ) );
822  System.err.println("Set io_cap "+io_cap_i+" in "+sec);
823  } else if( arg.equals("-secauto") && args.length > (i+2) ) {
824  final String addrOrNameSub = args[++i];
825  final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getOrCreate(addrOrNameSub);
826  final int io_cap_i = Integer.valueOf(args[++i]).intValue();
827  sec.io_cap_auto = SMPIOCapability.get( (byte)( io_cap_i & 0xff ) );
828  System.err.println("Set SEC AUTO security io_cap "+io_cap_i+" in "+sec);
829  } else if( arg.equals("-charid") && args.length > (i+1) ) {
830  test.charIdentifier = args[++i];
831  } else if( arg.equals("-charval") && args.length > (i+1) ) {
832  test.charValue = Integer.valueOf(args[++i]).intValue();
833  } else if( arg.equals("-disconnect") ) {
834  test.KEEP_CONNECTED = false;
835  } else if( arg.equals("-enableGATTPing") ) {
836  test.GATT_PING_ENABLED = true;
837  } else if( arg.equals("-keepDevice") ) {
838  test.REMOVE_DEVICE = false;
839  } else if( arg.equals("-count") && args.length > (i+1) ) {
840  test.MULTI_MEASUREMENTS.set(Integer.valueOf(args[++i]).intValue());
841  } else if( arg.equals("-single") ) {
842  test.MULTI_MEASUREMENTS.set(-1);
843  } else if( arg.equals("-resetEachCon") && args.length > (i+1) ) {
844  test.RESET_ADAPTER_EACH_CONN = Integer.valueOf(args[++i]).intValue();
845  }
846  }
847  BTUtils.println(System.err, "Run with '[-btmode LE|BREDR|DUAL] "+
848  "[-bluetoothManager <BluetoothManager-Implementation-Class-Name>] "+
849  "[-disconnect] [-enableGATTPing] [-count <number>] [-single] [-show_update_events] [-quiet] "+
850  "[-scanPassive]"+
851  "[-resetEachCon connectionCount] "+
852  "(-dev <device_[address|name]_sub>)* (-wl <device_address>)* "+
853  "(-seclevel <device_[address|name]_sub> <int_sec_level>)* "+
854  "(-iocap <device_[address|name]_sub> <int_iocap>)* "+
855  "(-secauto <device_[address|name]_sub> <int_iocap>)* "+
856  "(-passkey <device_[address|name]_sub> <digits>)* "+
857  "[-charid <uuid>] [-charval <byte-val>] "+
858  "[-verbose] [-debug] "+
859  "[-dbt_verbose true|false] "+
860  "[-dbt_debug true|false|adapter.event,gatt.data,hci.event,hci.scan_ad_eir,mgmt.event] "+
861  "[-dbt_mgmt cmd.timeout=3000,ringsize=64,...] "+
862  "[-dbt_hci cmd.complete.timeout=10000,cmd.status.timeout=3000,ringsize=64,...] "+
863  "[-dbt_gatt cmd.read.timeout=500,cmd.write.timeout=500,cmd.init.timeout=2500,ringsize=128,...] "+
864  "[-dbt_l2cap reader.timeout=10000,restart.count=0,...] "+
865  "[-shutdown <int>]'");
866  }
867 
868  BTUtils.println(System.err, "MULTI_MEASUREMENTS "+test.MULTI_MEASUREMENTS.get());
869  BTUtils.println(System.err, "KEEP_CONNECTED "+test.KEEP_CONNECTED);
870  BTUtils.println(System.err, "RESET_ADAPTER_EACH_CONN "+test.RESET_ADAPTER_EACH_CONN);
871  BTUtils.println(System.err, "GATT_PING_ENABLED "+test.GATT_PING_ENABLED);
872  BTUtils.println(System.err, "REMOVE_DEVICE "+test.REMOVE_DEVICE);
873  BTUtils.println(System.err, "USE_WHITELIST "+test.USE_WHITELIST);
874  BTUtils.println(System.err, "SHOW_UPDATE_EVENTS "+test.SHOW_UPDATE_EVENTS);
875  BTUtils.println(System.err, "QUIET "+test.QUIET);
876  BTUtils.println(System.err, "characteristic-id: "+test.charIdentifier);
877  BTUtils.println(System.err, "characteristic-value: "+test.charValue);
878 
879  BTUtils.println(System.err, "security-details: "+BTSecurityRegistry.allToString() );
880  BTUtils.println(System.err, "waitForDevices: "+BTDeviceRegistry.getWaitForDevicesString());
881 
882  if( waitForEnter ) {
883  BTUtils.println(System.err, "Press ENTER to continue\n");
884  try{ System.in.read();
885  } catch(final Exception e) { }
886  }
887  test.runTest(manager);
888  }
889 }
org.direct_bt.BTGattChar.getUUID
String getUUID()
Get the UUID of this characteristic.
org.direct_bt.BTSecurityRegistry.Entry
Entry specifying SMP security details associated to a device query via EUI48Sub or.
Definition: BTSecurityRegistry.java:43
org.direct_bt.GattCharPropertySet.Type.Read
Read
Definition: GattCharPropertySet.java:45
org.direct_bt.BTAdapter
Provides access to Bluetooth adapters.
Definition: BTAdapter.java:41
org.direct_bt.BTDeviceRegistry.getProcessingDeviceCount
static int getProcessingDeviceCount()
Definition: BTDeviceRegistry.java:303
org.direct_bt.AdapterSettings.isSet
boolean isSet(final SettingType bit)
Definition: AdapterSettings.java:184
org.direct_bt.BTManager.removeChangedAdapterSetListener
int removeChangedAdapterSetListener(final ChangedAdapterSetListener l)
Remove the given ChangedAdapterSetListener from this manager.
org.direct_bt.SMPIOCapability
SMP IO Capability value.
Definition: SMPIOCapability.java:37
org.direct_bt.SMPKeyBin.readAndApply
static HCIStatusCode readAndApply(final String path, final BTDevice device, final BTSecurityLevel minSecLevel, final boolean verbose_)
Create a new SMPKeyBin instance on the fly based upon stored file denoted by path and BTDevice#getAdd...
Definition: SMPKeyBin.java:235
org.direct_bt.BTSecurityRegistry.NO_PASSKEY
static final int NO_PASSKEY
Definition: BTSecurityRegistry.java:38
org.direct_bt.BTSecurityLevel
Bluetooth Security Level.
Definition: BTSecurityLevel.java:38
org.direct_bt.BTUtils.fprintf_td
static void fprintf_td(final PrintStream out, final String format, final Object ... args)
Convenient PrintStream#printf(String, Object...) invocation, prepending the elapsedTimeMillis() times...
Definition: BTUtils.java:68
org.direct_bt.BTDevice.getServices
List< BTGattService > getServices()
Returns a list of BluetoothGattServices available on this device.
org.direct_bt.BTAdapter.isPowered
boolean isPowered()
Returns whether the adapter is valid, plugged in and powered.
org.direct_bt.BTDevice.setConnSecurityAuto
boolean setConnSecurityAuto(final SMPIOCapability iocap_auto)
Set automatic security negotiation of BTSecurityLevel and SMPIOCapability pairing mode.
org.direct_bt.AdapterSettings.isEmpty
boolean isEmpty()
Definition: AdapterSettings.java:183
org.direct_bt
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2020 Gothel Software e.K.
org.direct_bt.BTDeviceRegistry.isWaitingForAnyDevice
static boolean isWaitingForAnyDevice()
Definition: BTDeviceRegistry.java:143
org.direct_bt.PairingMode
Bluetooth secure pairing mode.
Definition: PairingMode.java:40
org.direct_bt.BTGattChar.getProperties
GattCharPropertySet getProperties()
Returns the properties of this characteristic.
org.direct_bt.BTDeviceRegistry
Application toolkit providing BT device registration of processed and awaited devices.
Definition: BTDeviceRegistry.java:40
org.direct_bt.BTType.GATT_CHARACTERISTIC
GATT_CHARACTERISTIC
Definition: BTType.java:30
org.direct_bt.BTDeviceRegistry.getWaitForDevicesString
static String getWaitForDevicesString()
Definition: BTDeviceRegistry.java:149
org.direct_bt.GattCharPropertySet.isSet
boolean isSet(final Type bit)
Definition: GattCharPropertySet.java:63
org.direct_bt.BTDevice.removeAllCharListener
int removeAllCharListener()
Remove all BTGattCharListener from the list.
org.direct_bt.BTAdapter.reset
HCIStatusCode reset()
Reset the adapter.
org.direct_bt.EUI48
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Definition: EUI48.java:37
org.direct_bt.SMPKeyBin.createAndWrite
static boolean createAndWrite(final BTDevice device, final String path, final boolean overwrite, final boolean verbose_)
Create a new SMPKeyBin instance on the fly based upon given BTDevice's BTSecurityLevel,...
Definition: SMPKeyBin.java:179
org.direct_bt.BTFactory
One stop BTManager API entry point.
Definition: BTFactory.java:52
DBTScanner10.main
static void main(final String[] args)
Definition: DBTScanner10.java:741
jau.direct_bt.DBTManager
Definition: DBTManager.java:51
org.direct_bt.HCIWhitelistConnectType
HCI Whitelist connection type.
Definition: HCIWhitelistConnectType.java:32
org.direct_bt.BTDevice.pingGATT
boolean pingGATT()
Issues a GATT ping to the device, validating whether it is still reachable.
org.direct_bt.BDAddressAndType.toString
final String toString()
Definition: BDAddressAndType.java:154
org.direct_bt.SMPKeyBin
Storage for SMP keys including the required connection parameter.
Definition: SMPKeyBin.java:60
org.direct_bt.BTDeviceRegistry.removeFromProcessingDevices
static boolean removeFromProcessingDevices(final BDAddressAndType a)
Definition: BTDeviceRegistry.java:297
jau
org.direct_bt.BTAdapter.removeDiscoveredDevices
int removeDiscoveredDevices()
Remove all the discovered devices found on this adapter.
org.direct_bt.BTGattService
Provides access to Bluetooth GATT characteristic.
Definition: BTGattService.java:41
jau.direct_bt.DBTManager.shutdown
void shutdown()
Release the native memory associated with this object and all related Bluetooth resources.
Definition: DBTManager.java:412
org.direct_bt.BTUtils.println
static void println(final PrintStream out, final String msg)
Convenient PrintStream#println(String) invocation, prepending the elapsedTimeMillis() timestamp.
Definition: BTUtils.java:77
org.direct_bt.BTUtils.currentTimeMillis
static native long currentTimeMillis()
Returns current monotonic time in milliseconds.
org.direct_bt.BLERandomAddressType.STATIC_PUBLIC
STATIC_PUBLIC
Static public 'random' device address 0b11.
Definition: BLERandomAddressType.java:58
org.direct_bt.BTFactory.getAPIVersion
static final String getAPIVersion()
Manifest's Attributes.Name#SPECIFICATION_VERSION or.
Definition: BTFactory.java:124
org.direct_bt.BTGattService.getChars
List< BTGattChar > getChars()
Returns a list of BTGattChar this service exposes.
org.direct_bt.BTManager
Definition: BTManager.java:34
org.direct_bt.AdapterSettings.SettingType.POWERED
POWERED
Definition: AdapterSettings.java:155
org.direct_bt.BTFactory.getNativeAPIVersion
static native String getNativeAPIVersion()
org.direct_bt.EIRDataTypeSet
Bit mask of 'Extended Inquiry Response' (EIR) data fields, indicating a set of related data.
Definition: EIRDataTypeSet.java:33
test
org.direct_bt.BDAddressAndType.type
BDAddressType type
Definition: BDAddressAndType.java:47
org.direct_bt.BTSecurityRegistry.getStartOf
static BTSecurityRegistry.Entry getStartOf(final EUI48 addr, final String name)
Returns a matching BTSecurityRegistry.Entry,.
Definition: BTSecurityRegistry.java:177
org.direct_bt.BTDeviceRegistry.isDeviceProcessing
static boolean isDeviceProcessing(final BDAddressAndType a)
Definition: BTDeviceRegistry.java:300
org.direct_bt.BTDevice.connect
HCIStatusCode connect()
org.direct_bt.AdapterSettings.SettingType
Bits representing 'BTAdapter setting' data fields.
Definition: AdapterSettings.java:153
org.direct_bt.BTDeviceRegistry.addToWaitForDevices
static void addToWaitForDevices(final String addrOrNameSub)
Definition: BTDeviceRegistry.java:133
org.direct_bt.BTGattChar.Listener
BTGattChar event listener for notification and indication events.
Definition: BTGattChar.java:56
org.direct_bt.HCIStatusCode.SUCCESS
SUCCESS
Definition: HCIStatusCode.java:35
org.direct_bt.BTDevice.setPairingNumericComparison
HCIStatusCode setPairingNumericComparison(final boolean equal)
Method sets the numeric comparison result, see PairingMode#NUMERIC_COMPARE_ini.
org.direct_bt.AdapterSettings
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2020 Gothel Software e.K.
Definition: AdapterSettings.java:146
org.direct_bt.BTDevice.addStatusListener
boolean addStatusListener(final AdapterStatusListener listener)
Add the given AdapterStatusListener to the list if not already present, listening only for events mat...
org.direct_bt.BTManager.find
BTObject find(BTType type, String name, String identifier, BTObject parent, long timeoutMS)
Find a BluetoothObject of a type matching type.
org.direct_bt.BTSecurityRegistry.allToString
static String allToString()
Definition: BTSecurityRegistry.java:276
org.direct_bt.SMPPairingState
SMP Pairing Process state definition.
Definition: SMPPairingState.java:38
org.direct_bt.BTAdapter.startDiscovery
HCIStatusCode startDiscovery(final boolean keepAlive, final boolean le_scan_active)
Turns on device discovery if it is disabled.
org.direct_bt.BTMode.get
static BTMode get(final String name)
Maps the specified name to a constant of BTMode.
Definition: BTMode.java:57
org.direct_bt.BTSecurityRegistry.getOrCreate
static BTSecurityRegistry.Entry getOrCreate(final String addrOrNameSub)
Determines whether the given.
Definition: BTSecurityRegistry.java:249
org.direct_bt.BTGattChar.writeValue
boolean writeValue(byte[] argValue, boolean withResponse)
Writes the value of this characteristic, using one of the following methods depending on.
org.direct_bt.BDAddressAndType
Unique Bluetooth EUI48 address and BDAddressType tuple.
Definition: BDAddressAndType.java:36
org.direct_bt.BTSecurityLevel.get
static BTSecurityLevel get(final String name)
Maps the specified name to a constant of BTSecurityLevel.
Definition: BTSecurityLevel.java:63
org.direct_bt.BTDevice.getLastDiscoveryTimestamp
long getLastDiscoveryTimestamp()
Returns the timestamp in monotonic milliseconds when this device instance has discovered or connected...
org.direct_bt.SMPKeyBin.remove
final static boolean remove(final String path, final BDAddressAndType addrAndType_)
Definition: SMPKeyBin.java:417
org.direct_bt.BTDeviceRegistry.areAllDevicesProcessed
static boolean areAllDevicesProcessed(final DeviceQueryMatch m)
Returns.
Definition: BTDeviceRegistry.java:258
org.direct_bt.ScanType
Meta ScanType as derived from BTMode with defined value mask consisting of BDAddressType bits.
Definition: ScanType.java:36
jau.direct_bt.DBTManager.getManager
static BTManager getManager()
Returns an instance of BluetoothManager, to be used instead of constructor.
Definition: DBTManager.java:398
org.direct_bt.BTUtils
Definition: BTUtils.java:29
org.direct_bt.BTSecurityLevel.UNSET
UNSET
Security Level not set, value 0.
Definition: BTSecurityLevel.java:40
org.direct_bt.BTDeviceRegistry.addToProcessedDevices
static void addToProcessedDevices(final BDAddressAndType a, final String n)
Definition: BTDeviceRegistry.java:165
org.direct_bt.GattCharPropertySet.Type
BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.1.1 Characteristic Properties.
Definition: GattCharPropertySet.java:42
org.direct_bt.BTManager.getAdapters
List< BTAdapter > getAdapters()
Returns a list of BluetoothAdapters available in the system.
org.direct_bt.BTUtils.decodeUTF8String
static native String decodeUTF8String(final byte[] buffer, final int offset, final int size)
Returns all valid consecutive UTF-8 characters within buffer in the range offset -> size or until EOS...
org.direct_bt.HCIStatusCode
BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes.
Definition: HCIStatusCode.java:34
org.direct_bt.BTGattChar
Provides access to Bluetooth GATT characteristic.
Definition: BTGattChar.java:40
org.direct_bt.SMPIOCapability.get
static SMPIOCapability get(final String name)
Maps the specified name to a constant of SMPIOCapability.
Definition: SMPIOCapability.java:64
org.direct_bt.BTFactory.getDirectBTManager
static synchronized BTManager getDirectBTManager()
Returns an initialized BluetoothManager instance using the DirectBT implementation.
Definition: BTFactory.java:480
org.direct_bt.SMPKeyBin.getFilename
final static String getFilename(final String path, final BDAddressAndType addrAndType_)
Definition: SMPKeyBin.java:371
org.direct_bt.BTDevice
Provides access to Bluetooth adapters.
Definition: BTDevice.java:42
org.direct_bt.BTGattDesc
Provides access to Bluetooth GATT descriptor.
Definition: BTGattDesc.java:38
org.direct_bt.BTFactory.getNativeVersion
static native String getNativeVersion()
DBTScanner10.runTest
void runTest(final BTManager manager)
Definition: DBTScanner10.java:690
org.direct_bt.BTFactory.getImplVersion
static final String getImplVersion()
Manifest's Attributes.Name#IMPLEMENTATION_VERSION or.
Definition: BTFactory.java:130
org.direct_bt.BDAddressType.BDADDR_LE_PUBLIC
BDADDR_LE_PUBLIC
Bluetooth LE public address.
Definition: BDAddressType.java:57
org
org.direct_bt.BTDeviceRegistry.getProcessedDevicesString
static String getProcessedDevicesString()
Definition: BTDeviceRegistry.java:174
org.direct_bt.BTSecurityRegistry
Application toolkit providing BT security setup and its device association on a pattern matching basi...
Definition: BTSecurityRegistry.java:37
org.direct_bt.BTMode
Bluetooth adapter operating mode.
Definition: BTMode.java:34
org.direct_bt.BTAdapter.stopDiscovery
HCIStatusCode stopDiscovery()
Turns off device discovery if it is enabled.
org.direct_bt.GattCharPropertySet
Bit mask of GATT Characteristic Properties.
Definition: GattCharPropertySet.java:35
org.direct_bt.BTType
Definition: BTType.java:28
org.direct_bt.BTException
Definition: BTException.java:32
org.direct_bt.BTDeviceRegistry.getWaitForDevicesCount
static int getWaitForDevicesCount()
Definition: BTDeviceRegistry.java:146
org.direct_bt.BTUtils.elapsedTimeMillis
static long elapsedTimeMillis()
Returns current elapsed monotonic time in milliseconds since module startup, see startupTimeMillis().
Definition: BTUtils.java:55
org.direct_bt.BTDevice.getAddressAndType
BDAddressAndType getAddressAndType()
Returns the unique device EUI48 address and BDAddressType type.
org.direct_bt.BTDeviceRegistry.isDeviceProcessed
static boolean isDeviceProcessed(final BDAddressAndType a)
Definition: BTDeviceRegistry.java:168
org.direct_bt.BTDeviceRegistry.addToProcessingDevices
static void addToProcessingDevices(final BDAddressAndType a, final String n)
Definition: BTDeviceRegistry.java:294
org.direct_bt.BDAddressType
Bluetooth address type constants.
Definition: BDAddressType.java:53
org.direct_bt.BTDevice.unpair
HCIStatusCode unpair()
Unpairs this device from the adapter while staying connected.
org.direct_bt.BTDevice.setPairingPasskey
HCIStatusCode setPairingPasskey(final int passkey)
Method sets the given passkey entry, see PairingMode#PASSKEY_ENTRY_ini.
org.direct_bt.BTDeviceRegistry.getProcessedDeviceCount
static int getProcessedDeviceCount()
Definition: BTDeviceRegistry.java:171
org.direct_bt.BDAddressAndType.getBLERandomAddressType
BLERandomAddressType getBLERandomAddressType()
Returns the BLERandomAddressType.
Definition: BDAddressAndType.java:85
org.direct_bt.BTAdapter.addStatusListener
boolean addStatusListener(final AdapterStatusListener listener)
Add the given AdapterStatusListener to the list if not already present.
org.direct_bt.BLERandomAddressType
Bluetooth LE random address type constants.
Definition: BLERandomAddressType.java:50
org.direct_bt.BTDeviceRegistry.isWaitingForDevice
static boolean isWaitingForDevice(final EUI48 address, final String name, final DeviceQueryMatch m)
Returns.
Definition: BTDeviceRegistry.java:219
org.direct_bt.BTDevice.setConnSecurityBest
boolean setConnSecurityBest(final BTSecurityLevel sec_level, final SMPIOCapability io_cap)
Convenience method to determine the best practice BTSecurityLevel and SMPIOCapability based on the gi...
org.direct_bt.BTGattCharListener
BTGattChar event listener for notification and indication events.
Definition: BTGattCharListener.java:57
org.direct_bt.BTGattDesc.getUUID
String getUUID()
Get the UUID of this descriptor.
org.direct_bt.BTDevice.getName
String getName()
Returns the remote friendly name of this device.
org.direct_bt.BTAdapter.addDeviceToWhitelist
boolean addDeviceToWhitelist(final BDAddressAndType addressAndType, final HCIWhitelistConnectType ctype, final short conn_interval_min, final short conn_interval_max, final short conn_latency, final short timeout)
Add the given device to the adapter's autoconnect whitelist.
org.direct_bt.BTGattChar.addCharListener
boolean addCharListener(final Listener listener)
Add the given BTGattChar.Listener to the listener list if not already present.
org.direct_bt.BTGattChar.getDescriptors
List< BTGattDesc > getDescriptors()
Returns a list of BluetoothGattDescriptors this characteristic exposes.
org.direct_bt.AdapterStatusListener
BTAdapter status listener for BTDevice discovery events: Added, updated and removed; as well as for c...
Definition: AdapterStatusListener.java:56
org.direct_bt.BTUtils.bytesHexString
static String bytesHexString(final byte[] bytes, final int offset, final int length, final boolean lsbFirst)
Produce a lower-case hexadecimal string representation of the given byte values.
Definition: BTUtils.java:123
org.direct_bt.BTManager.shutdown
void shutdown()
Release the native memory associated with this object and all related Bluetooth resources.
org.direct_bt.BDAddressAndType.address
EUI48 address
Definition: BDAddressAndType.java:46
org.direct_bt.BTDevice.remove
boolean remove()
Remove this device from the system (like an unpair).
jau.direct_bt
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2020 Gothel Software e.K.
Definition: DBTAdapter.java:26
org.direct_bt.BTGattService.getUUID
String getUUID()
Get the UUID of this service.
org.direct_bt.SMPIOCapability.KEYBOARD_ONLY
KEYBOARD_ONLY
Keyboard input only, value 2.
Definition: SMPIOCapability.java:43
DBTScanner10
This Java scanner example uses the Direct-BT fully event driven workflow and adds multithreading,...
Definition: DBTScanner10.java:78
org.direct_bt.BTGattChar.readValue
byte[] readValue()
Reads the value of this characteristic.
org.direct_bt.BTAdapter.getManager
BTManager getManager()
Returns the used singleton BTManager instance, used to create this adapter.
org.direct_bt.BTAdapter.getAddressAndType
BDAddressAndType getAddressAndType()
Returns the adapter's public BDAddressAndType.
org.direct_bt.HCIWhitelistConnectType.HCI_AUTO_CONN_ALWAYS
HCI_AUTO_CONN_ALWAYS
Auto Connect: Only supported for LE on Linux .
Definition: HCIWhitelistConnectType.java:38
org.direct_bt.BTManager.addChangedAdapterSetListener
void addChangedAdapterSetListener(final ChangedAdapterSetListener l)
Add the given ChangedAdapterSetListener to this manager.
org.direct_bt.BTManager.ChangedAdapterSetListener
Event listener to receive change events regarding the system's BTAdapter set, e.g.
Definition: BTManager.java:69
org.direct_bt.BTDevice.getAdapter
BTAdapter getAdapter()
Returns the adapter on which this device was discovered or connected.