25package trial.org.direct_bt;
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.Iterator;
31import java.util.concurrent.atomic.AtomicInteger;
33import org.direct_bt.AdapterSettings;
34import org.direct_bt.AdapterStatusListener;
35import org.direct_bt.BTMode;
36import org.direct_bt.BTSecurityLevel;
37import org.direct_bt.BTAdapter;
38import org.direct_bt.BTDevice;
39import org.direct_bt.BTDeviceRegistry;
40import org.direct_bt.BTGattChar;
41import org.direct_bt.BTGattCharListener;
42import org.direct_bt.BTGattCmd;
43import org.direct_bt.BTGattDesc;
44import org.direct_bt.BTGattService;
45import org.direct_bt.BTSecurityRegistry;
46import org.direct_bt.BTUtils;
47import org.direct_bt.DiscoveryPolicy;
48import org.direct_bt.EIRDataTypeSet;
49import org.direct_bt.EInfoReport;
50import org.direct_bt.GattCharPropertySet;
51import org.direct_bt.HCIStatusCode;
52import org.direct_bt.LE_Features;
53import org.direct_bt.LE_PHYs;
54import org.direct_bt.PairingMode;
55import org.direct_bt.SMPIOCapability;
56import org.direct_bt.SMPKeyBin;
57import org.direct_bt.SMPPairingState;
58import org.direct_bt.ScanType;
59import org.jau.io.PrintUtil;
60import org.jau.net.EUI48;
61import org.jau.sys.Clock;
62import org.jau.util.BasicTypes;
63import org.junit.Assert;
69 private final boolean GATT_VERBOSE =
false;
71 private final long timestamp_t0 = Clock.startupTimeMillis();
73 private final String adapterShortName =
"TDev2Clt";
75 private final MyAdapterStatusListener myAdapterStatusListener =
new MyAdapterStatusListener();
77 private final byte cmd_arg = (byte)0x44;
79 private String adapterName =
"TestDev2_Clt";
80 private EUI48 useAdapter = EUI48.ALL_DEVICE;
84 private boolean do_disconnect =
true;
86 private boolean do_remove_device =
false;
90 private final AtomicInteger disconnectCount =
new AtomicInteger(0);
91 private final AtomicInteger measurementsLeft =
new AtomicInteger(1);
92 private final AtomicInteger deviceReadyCount =
new AtomicInteger(0);
93 private final AtomicInteger notificationsReceived =
new AtomicInteger(0);
94 private final AtomicInteger indicationsReceived =
new AtomicInteger(0);
95 private final AtomicInteger completedGATTCommands =
new AtomicInteger(0);
96 private final AtomicInteger completedMeasurementsTotal =
new AtomicInteger(0);
97 private final AtomicInteger completedMeasurementsSuccess =
new AtomicInteger(0);
99 private final boolean do_disconnect_randomly;
101 public DBTClient01(
final String adapterName,
final EUI48 useAdapter,
final BTMode btMode,
final boolean do_disconnect_randomly) {
102 this.adapterName = adapterName;
103 this.useAdapter = useAdapter;
104 this.btMode = btMode;
105 this.do_disconnect_randomly = do_disconnect_randomly;
108 this(adapterName, useAdapter, btMode,
false );
112 public String
getName() {
return adapterName; }
116 this.clientAdapter = clientAdapter;
123 measurementsLeft.set(v);
127 return measurementsLeft.get();
131 return completedMeasurementsTotal.get();
135 return completedMeasurementsSuccess.get();
139 return this.disconnectCount.get();
152 do_remove_device = v;
155 static void executeOffThread(
final Runnable runobj,
final String threadName,
final boolean detach) {
156 final Thread t =
new Thread( runobj, threadName );
162 static void execute(
final Runnable task,
final boolean offThread) {
164 final Thread t =
new Thread(task);
172 class MyAdapterStatusListener
extends AdapterStatusListener {
174 public void adapterSettingsChanged(
final BTAdapter adapter,
final AdapterSettings oldmask,
175 final AdapterSettings newmask,
final AdapterSettings changedmask,
final long timestamp) {
176 final boolean initialSetting = oldmask.isEmpty();
177 if( initialSetting ) {
178 PrintUtil.println(System.err,
"****** Client SETTINGS_INITIAL: "+oldmask+
" -> "+newmask+
", changed "+changedmask);
180 PrintUtil.println(System.err,
"****** Client SETTINGS_CHANGED: "+oldmask+
" -> "+newmask+
", changed "+changedmask);
182 final boolean justPoweredOn = changedmask.isSet(AdapterSettings.SettingType.POWERED) &&
183 newmask.isSet(AdapterSettings.SettingType.POWERED);
184 if( justPoweredOn && DiscoveryPolicy.AUTO_OFF != discoveryPolicy && clientAdapter.
equals(adapter) ) {
186 "Client DBT-StartDiscovery-"+adapter.getAddressAndType(),
true );
189 PrintUtil.println(System.err,
"Client Status Adapter:");
190 PrintUtil.println(System.err, adapter.toString());
194 public void discoveringChanged(
final BTAdapter adapter,
final ScanType currentMeta,
final ScanType changedType,
final boolean changedEnabled,
final DiscoveryPolicy policy,
final long timestamp) {
195 PrintUtil.println(System.err,
"****** Client DISCOVERING: meta "+currentMeta+
", changed["+changedType+
", enabled "+changedEnabled+
", policy "+policy+
"] on "+adapter);
199 public boolean deviceFound(
final BTDevice device,
final long timestamp) {
200 if( BTDeviceRegistry.isWaitingForDevice(device.getAddressAndType().address, device.getName()) &&
201 0 < measurementsLeft.get()
204 PrintUtil.println(System.err,
"****** Client FOUND__-0: Connecting "+device.toString());
206 final long td = Clock.currentTimeMillis() - timestamp_t0;
207 PrintUtil.println(System.err,
"PERF: adapter-init -> FOUND__-0 " + td +
" ms");
209 executeOffThread( () -> { connectDiscoveredDevice(device); },
210 "Client DBT-Connect-"+device.getAddressAndType(),
true );
213 PrintUtil.println(System.err,
"****** Client FOUND__-1: NOP "+device.toString());
219 public void deviceUpdated(
final BTDevice device,
final EIRDataTypeSet updateMask,
final long timestamp) {
223 public void deviceConnected(
final BTDevice device,
final boolean discovered,
final long timestamp) {
224 PrintUtil.println(System.err,
"****** Client CONNECTED (discovered "+discovered+
"): "+device.toString());
228 public void devicePairingState(
final BTDevice device,
final SMPPairingState state,
final PairingMode mode,
final long timestamp) {
229 PrintUtil.println(System.err,
"****** Client PAIRING_STATE: state "+state+
", mode "+mode+
": "+device);
236 PrintUtil.println(System.err,
"****** Client PAIRING_STATE: state "+state+
"; Remove key file "+SMPKeyBin.getFilename(
DBTConstants.
CLIENT_KEY_PATH, device)+
", res "+res);
239 case REQUESTED_BY_RESPONDER:
242 case FEATURE_EXCHANGE_STARTED:
245 case FEATURE_EXCHANGE_COMPLETED:
248 case PASSKEY_EXPECTED: {
249 final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getStartOf(device.getAddressAndType().address,
"");
250 if(
null != sec && sec.getPairingPasskey() != BTSecurityRegistry.NO_PASSKEY ) {
251 executeOffThread( () -> { device.setPairingPasskey( sec.getPairingPasskey() ); },
"DBT-SetPasskey-"+device.getAddressAndType(),
true );
253 executeOffThread( () -> { device.setPairingPasskey( 0 ); },
"DBT-SetPasskey-"+device.getAddressAndType(),
true );
258 case NUMERIC_COMPARE_EXPECTED: {
259 final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getStartOf(device.getAddressAndType().address,
"");
261 executeOffThread( () -> { device.setPairingNumericComparison( sec.getPairingNumericComparison() ); },
"DBT-SetNumericComp-"+device.getAddressAndType(),
true );
263 executeOffThread( () -> { device.setPairingNumericComparison(
false ); },
"DBT-SetNumericCompFalse-"+device.getAddressAndType(),
true );
270 case KEY_DISTRIBUTION:
281 private void disconnectDeviceRandomly(
final BTDevice device) {
283 final int sleep_min = 100;
284 final int sleep_max = 1500;
285 final int sleep_dur = (int) ( Math.random() * ( sleep_max - sleep_min + 1 ) + sleep_min );
287 Thread.sleep(sleep_dur);
288 }
catch (
final InterruptedException e) { }
290 PrintUtil.fprintf_td(System.err,
"****** Client i470 disconnectDevice(delayed %d ms): client %s\n", sleep_dur, device.toString());
295 public void deviceReady(
final BTDevice device,
final long timestamp) {
297 deviceReadyCount.incrementAndGet();
298 PrintUtil.println(System.err,
"****** Client READY-0: Processing["+deviceReadyCount.get()+
"] "+device.toString());
300 final long td = Clock.currentTimeMillis() - timestamp_t0;
301 PrintUtil.println(System.err,
"PERF: adapter-init -> READY-0 " + td +
" ms");
305 executeOffThread( () -> { processReadyDevice(device); },
306 "DBT-Process1-"+device.getAddressAndType(),
true );
309 if( do_disconnect_randomly ) {
310 executeOffThread( () -> { disconnectDeviceRandomly(device); },
311 "DBT-Disconnect-"+device.getAddressAndType(),
true );
317 public void deviceDisconnected(
final BTDevice device,
final HCIStatusCode reason,
final short handle,
final long timestamp) {
318 PrintUtil.println(System.err,
"****** Client DISCONNECTED: Reason "+reason+
", old handle 0x"+Integer.toHexString(handle)+
": "+device+
" on "+device.getAdapter());
320 disconnectCount.addAndGet(1);
322 executeOffThread( () -> { removeDevice(device); },
"Client DBT-Remove-"+device.getAddressAndType(),
true );
326 public String toString() {
327 return "Client AdapterStatusListener[user, per-adapter]";
331 class MyGATTEventListener
extends BTGattCharListener {
333 public void notificationReceived(
final BTGattChar charDecl,
334 final byte[] value,
final long timestamp) {
336 final long tR = Clock.currentTimeMillis();
337 PrintUtil.fprintf_td(System.err,
"** Characteristic-Notify: UUID %s, td %d ******\n",
338 charDecl.getUUID(), (tR-timestamp));
339 PrintUtil.fprintf_td(System.err,
"** Characteristic: %s ******\n", charDecl.toString());
340 PrintUtil.fprintf_td(System.err,
"** Value R: size %d, ro: %s ******\n", value.length, BasicTypes.bytesHexString(value, 0, -1,
true));
341 PrintUtil.fprintf_td(System.err,
"** Value S: %s ******\n", BTUtils.decodeUTF8String(value, 0, value.length));
343 notificationsReceived.incrementAndGet();
347 public void indicationReceived(
final BTGattChar charDecl,
348 final byte[] value,
final long timestamp,
final boolean confirmationSent) {
350 final long tR = Clock.currentTimeMillis();
351 PrintUtil.fprintf_td(System.err,
"** Characteristic-Indication: UUID %s, td %d, confirmed %b ******\n",
352 charDecl.getUUID(), (tR-timestamp), confirmationSent);
353 PrintUtil.fprintf_td(System.err,
"** Characteristic: %s ******\n", charDecl.toString());
354 PrintUtil.fprintf_td(System.err,
"** Value R: size %d, ro: %s ******\n", value.length, BasicTypes.bytesHexString(value, 0, -1,
true));
355 PrintUtil.fprintf_td(System.err,
"** Value S: %s ******\n", BTUtils.decodeUTF8String(value, 0, value.length));
357 indicationsReceived.incrementAndGet();
361 private void resetLastProcessingStats() {
362 completedGATTCommands.set(0);
363 notificationsReceived.set(0);
364 indicationsReceived.set(0);
367 private void connectDiscoveredDevice(
final BTDevice device) {
368 PrintUtil.println(System.err,
"****** Client Connecting Device: Start " + device.toString());
370 resetLastProcessingStats();
372 final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getStartOf(device.getAddressAndType().address, device.getName());
374 PrintUtil.println(System.err,
"****** Client Connecting Device: Found SecurityDetail "+sec.toString()+
" for "+device.toString());
376 PrintUtil.println(System.err,
"****** Client Connecting Device: No SecurityDetail for "+device.toString());
378 final BTSecurityLevel req_sec_level =
null != sec ? sec.getSecLevel() : BTSecurityLevel.UNSET;
380 PrintUtil.fprintf_td(System.err,
"****** Client Connecting Device: BTDevice::uploadKeys(...) result %s\n", res.toString());
381 if( HCIStatusCode.SUCCESS != res ) {
383 if( sec.isSecurityAutoEnabled() ) {
384 final boolean r = device.setConnSecurityAuto( sec.getSecurityAutoIOCap() );
385 PrintUtil.println(System.err,
"****** Client Connecting Device: Using SecurityDetail.SEC AUTO "+sec+
" -> set OK "+r);
386 }
else if( sec.isSecLevelOrIOCapSet() ) {
387 final boolean r = device.setConnSecurity(sec.getSecLevel(), sec.getIOCap());
388 PrintUtil.println(System.err,
"****** Client Connecting Device: Using SecurityDetail.Level+IOCap "+sec+
" -> set OK "+r);
390 final boolean r = device.setConnSecurityAuto( SMPIOCapability.KEYBOARD_ONLY );
391 PrintUtil.println(System.err,
"****** Client Connecting Device: Setting SEC AUTO security detail w/ KEYBOARD_ONLY ("+sec+
") -> set OK "+r);
394 final boolean r = device.setConnSecurityAuto( SMPIOCapability.KEYBOARD_ONLY );
395 PrintUtil.println(System.err,
"****** Client Connecting Device: Setting SEC AUTO security detail w/ KEYBOARD_ONLY -> set OK "+r);
398 final EInfoReport eir = device.getEIR();
399 PrintUtil.println(System.err,
"Client EIR-1 "+device.getEIRInd().toString());
400 PrintUtil.println(System.err,
"Client EIR-2 "+device.getEIRScanRsp().toString());
401 PrintUtil.println(System.err,
"Client EIR-+ "+eir.toString());
403 short conn_interval_min = (short)8;
404 short conn_interval_max = (short)12;
405 final short conn_latency = (short)0;
406 if( eir.isSet(EIRDataTypeSet.DataType.CONN_IVAL) ) {
407 final short[] minmax =
new short[2];
408 eir.getConnInterval(minmax);
409 conn_interval_min = minmax[0];
410 conn_interval_max = minmax[1];
412 final short supervision_timeout = BTUtils.getHCIConnSupervisorTimeout(conn_latency, (
int) ( conn_interval_max * 1.25 ) );
413 res = device.connectLE(le_scan_interval, le_scan_window, conn_interval_min, conn_interval_max, conn_latency, supervision_timeout);
415 PrintUtil.println(System.err,
"****** Client Connecting Device Command, res "+res+
": End result "+res+
" of " + device.toString());
418 private void processReadyDevice(
final BTDevice device) {
419 PrintUtil.println(System.err,
"****** Client Processing Ready Device: Start " + device.toString());
420 final long t1 = Clock.currentTimeMillis();
423 final long t2 = Clock.currentTimeMillis();
425 boolean success =
false;
428 final LE_PHYs resTx[] = {
new LE_PHYs() };
429 final LE_PHYs resRx[] = {
new LE_PHYs() };
430 final HCIStatusCode res = device.getConnectedLE_PHY(resTx, resRx);
431 PrintUtil.fprintf_td(System.err,
"****** Client Got Connected LE PHY: status %s: Tx %s, Rx %s\n",
432 res.toString(), resTx[0].toString(), resRx[0].toString());
434 final long t3 = Clock.currentTimeMillis();
440 final List<BTGattService> primServices = device.getGattServices();
441 if(
null == primServices || 0 == primServices.size() ) {
444 throw new RuntimeException(
"Processing Ready Device: getServices() failed " + device.toString());
446 final long t5 = Clock.currentTimeMillis();
448 final long td00 = device.getLastDiscoveryTimestamp() - timestamp_t0;
449 final long td01 = t1 - timestamp_t0;
450 final long td05 = t5 - timestamp_t0;
451 final long tdc1 = t1 - device.getLastDiscoveryTimestamp();
452 final long tdc5 = t5 - device.getLastDiscoveryTimestamp();
453 final long td12 = t2 - t1;
454 final long td23 = t3 - t2;
455 final long td13 = t3 - t1;
456 final long td35 = t5 - t3;
457 PrintUtil.println(System.err, System.lineSeparator()+System.lineSeparator());
458 PrintUtil.println(System.err,
"PERF: GATT primary-services completed"+System.lineSeparator()+
459 "PERF: adapter-init to discovered " + td00 +
" ms,"+System.lineSeparator()+
460 "PERF: adapter-init to processing-start " + td01 +
" ms,"+System.lineSeparator()+
461 "PERF: adapter-init to gatt-complete " + td05 +
" ms,"+System.lineSeparator()+
462 "PERF: discovered to processing-start " + tdc1 +
" ms,"+System.lineSeparator()+
463 "PERF: discovered to gatt-complete " + tdc5 +
" ms,"+System.lineSeparator()+
464 "PERF: SMPKeyBin + LE_PHY " + td13 +
" ms (SMPKeyBin "+td12+
"ms, LE_PHY "+td23+
"ms), "+System.lineSeparator()+
465 "PERF: get-gatt-services " + td35 +
" ms,"+System.lineSeparator());
470 cmd.setVerbose(
true);
471 final boolean cmd_resolved = cmd.isResolved();
472 PrintUtil.println(System.err,
"Client Command test: "+cmd.toString()+
", resolved "+cmd_resolved);
473 final byte[] cmd_data = { cmd_arg };
474 final HCIStatusCode cmd_res = cmd.send(
true , cmd_data, 3000 );
475 if( HCIStatusCode.SUCCESS == cmd_res ) {
476 final byte[] resp = cmd.getResponse();
477 if( 1 == resp.length && resp[0] == cmd_arg ) {
478 PrintUtil.fprintf_td(System.err,
"Client Success: %s -> %s (echo response)\n", cmd.toString(), BasicTypes.bytesHexString(resp, 0, resp.length,
true ));
479 completedGATTCommands.incrementAndGet();
481 PrintUtil.fprintf_td(System.err,
"Client Failure: %s -> %s (different response)\n", cmd.toString(), BasicTypes.bytesHexString(resp, 0, resp.length,
true ));
484 PrintUtil.fprintf_td(System.err,
"Client Failure: %s -> %s\n", cmd.toString(), cmd_res.toString());
489 boolean gattListenerError =
false;
490 final List<BTGattCharListener> gattListener =
new ArrayList<BTGattCharListener>();
495 for(
final Iterator<BTGattService> srvIter = primServices.iterator(); srvIter.hasNext(); i++) {
496 final BTGattService primService = srvIter.next();
498 PrintUtil.fprintf_td(System.err,
" [%02d] Service UUID %s\n", i, primService.getUUID());
499 PrintUtil.fprintf_td(System.err,
" [%02d] %s\n", i, primService.toString());
502 final List<BTGattChar> serviceCharacteristics = primService.getChars();
503 for(
final Iterator<BTGattChar> charIter = serviceCharacteristics.iterator(); charIter.hasNext(); j++) {
504 final BTGattChar serviceChar = charIter.next();
506 PrintUtil.fprintf_td(System.err,
" [%02d.%02d] Characteristic: UUID %s\n", i, j, serviceChar.getUUID());
507 PrintUtil.fprintf_td(System.err,
" [%02d.%02d] %s\n", i, j, serviceChar.toString());
509 final GattCharPropertySet properties = serviceChar.getProperties();
510 if( properties.isSet(GattCharPropertySet.Type.Read) ) {
511 final byte[] value = serviceChar.readValue();
512 final String svalue = BTUtils.decodeUTF8String(value, 0, value.length);
514 PrintUtil.fprintf_td(System.err,
" [%02d.%02d] value: %s ('%s')\n", i, j, BasicTypes.bytesHexString(value, 0, -1,
true), svalue);
518 final List<BTGattDesc> charDescList = serviceChar.getDescriptors();
519 for(
final Iterator<BTGattDesc> descIter = charDescList.iterator(); descIter.hasNext(); k++) {
520 final BTGattDesc charDesc = descIter.next();
522 PrintUtil.fprintf_td(System.err,
" [%02d.%02d.%02d] Descriptor: UUID %s\n", i, j, k, charDesc.getUUID());
523 PrintUtil.fprintf_td(System.err,
" [%02d.%02d.%02d] %s\n", i, j, k, charDesc.toString());
527 final boolean cccdEnableResult[] = {
false,
false };
528 if( serviceChar.enableNotificationOrIndication( cccdEnableResult ) ) {
530 final MyGATTEventListener gattEventListener =
new MyGATTEventListener();
531 final boolean clAdded = serviceChar.addCharListener( gattEventListener );
533 gattListener.add(gattEventListener);
535 gattListenerError =
true;
536 PrintUtil.fprintf_td(System.err,
"Client Error: Failed to add GattListener: %s @ %s, gattListener %d\n",
537 gattEventListener.toString(), serviceChar.toString(), gattListener.size());
540 PrintUtil.fprintf_td(System.err,
" [%02d.%02d] Characteristic-Listener: Notification(%b), Indication(%b): Added %b\n",
541 i, j, cccdEnableResult[0], cccdEnableResult[1], clAdded);
542 PrintUtil.fprintf_td(System.err,
"\n");
548 PrintUtil.fprintf_td(System.err,
"\n");
551 success = notificationsReceived.get() >= 2 || indicationsReceived.get() >= 2;
553 }
catch(
final Exception ex) {
554 PrintUtil.println(System.err,
"****** Client Processing Ready Device: Exception.2 caught for " + device.toString() +
": "+ex.getMessage());
555 ex.printStackTrace();
557 }
while( !success && device.getConnected() && !gattListenerError );
559 success = success && completedGATTCommands.get() >= 1;
561 if( gattListenerError ) {
566 for(
final BTGattCharListener gcl : gattListener) {
567 if( !device.removeCharListener(gcl) ) {
568 PrintUtil.fprintf_td(System.err,
"Client Error: Failed to remove GattListener[%d/%d]: %s @ %s\n",
569 i, gattListener.size(), gcl.toString(), device.toString());
576 if( device.getConnected() ) {
578 final BTGattCmd cmd =
new BTGattCmd(device,
"FinalHandshake",
null ,
DBTConstants.CommandUUID,
DBTConstants.ResponseUUID);
579 cmd.setVerbose(
true);
580 final boolean cmd_resolved = cmd.isResolved();
581 PrintUtil.println(System.err,
"Client FinalCommand test: "+cmd.toString()+
", resolved "+cmd_resolved);
582 final byte[] cmd_data = success ? DBTConstants.SuccessHandshakeCommandData :
DBTConstants.FailHandshakeCommandData;
583 final HCIStatusCode cmd_res = cmd.send(
true , cmd_data, 3000 );
584 if( HCIStatusCode.SUCCESS == cmd_res ) {
585 final byte[] resp = cmd.getResponse();
586 if( Arrays.equals(cmd_data, resp) ) {
587 PrintUtil.fprintf_td(System.err,
"Client Success: %s -> %s (echo response)\n", cmd.toString(), BasicTypes.bytesHexString(resp, 0, resp.length,
true ));
589 PrintUtil.fprintf_td(System.err,
"Client Failure: %s -> %s (different response)\n", cmd.toString(), BasicTypes.bytesHexString(resp, 0, resp.length,
true ));
593 PrintUtil.fprintf_td(System.err,
"Client Failure: %s -> %s\n", cmd.toString(), cmd_res.toString());
598 }
catch (
final Throwable t ) {
599 PrintUtil.println(System.err,
"****** Client Processing Ready Device: Exception.2 caught for " + device.toString() +
": "+t.getMessage());
603 PrintUtil.println(System.err,
"****** Client Processing Ready Device: End-1: Success " + success +
" on " + device.toString());
605 if( DiscoveryPolicy.PAUSE_CONNECTED_UNTIL_DISCONNECTED == discoveryPolicy ) {
606 device.getAdapter().removeDevicePausingDiscovery(device);
609 PrintUtil.println(System.err,
"****** Client Processing Ready Device: End-2: Success " + success +
" on " + device.toString());
610 device.removeAllCharListener();
612 if( do_disconnect ) {
613 if( do_remove_device ) {
620 completedMeasurementsTotal.addAndGet(1);
622 completedMeasurementsSuccess.addAndGet(1);
623 if( 0 < measurementsLeft.get() ) {
624 measurementsLeft.decrementAndGet();
627 PrintUtil.println(System.err,
"****** Client Processing Ready Device: Success "+success+
628 "; Measurements completed "+completedMeasurementsSuccess.get()+
629 ", left "+measurementsLeft.get()+
630 "; Received notitifications "+notificationsReceived.get()+
", indications "+indicationsReceived.get()+
631 "; Completed GATT commands "+completedGATTCommands.get()+
632 ": "+device.getAddressAndType());
635 private void removeDevice(
final BTDevice device) {
636 PrintUtil.println(System.err,
"****** Client Remove Device: removing: "+device.getAddressAndType());
638 if( do_remove_device ) {
643 static final boolean le_scan_active =
true;
644 static final short le_scan_interval = (short)24;
645 static final short le_scan_window = (short)24;
646 static final byte filter_policy = (byte)0;
647 static final boolean filter_dup =
true;
651 resetLastProcessingStats();
653 final HCIStatusCode status = clientAdapter.
startDiscovery(
null, discoveryPolicy, le_scan_active, le_scan_interval, le_scan_window, filter_policy, filter_dup );
654 PrintUtil.println(System.err,
"****** Client Start discovery ("+msg+
") result: "+status);
661 PrintUtil.println(System.err,
"****** Client Stop discovery ("+msg+
") result: "+status);
666 public void close(
final String msg) {
667 PrintUtil.println(System.err,
"****** Client Close: "+msg);
675 PrintUtil.fprintf_td(System.err,
"initClientAdapter: Adapter not selected: %s\n", adapter.
toString());
684 PrintUtil.fprintf_td(System.err,
"initClientAdapter: Adapter initialization failed: %s: %s\n",
685 status.toString(), adapter.
toString());
689 PrintUtil.fprintf_td(System.err,
"initClientAdapter: Already initialized adapter power-off failed:: %s\n", adapter.
toString());
693 PrintUtil.fprintf_td(System.err,
"initClientAdapter.1: %s\n", adapter.
toString());
698 PrintUtil.fprintf_td(System.err,
"initClientAdapter: setLocalName OK: %s\n", adapter.
toString());
700 PrintUtil.fprintf_td(System.err,
"initClientAdapter: setLocalName failed: %s\n", adapter.
toString());
704 PrintUtil.fprintf_td(System.err,
"initClientAdapter: setPower.2 on failed: %s\n", adapter.
toString());
709 PrintUtil.println(System.err,
"initClientAdapter.2: "+adapter.
toString());
713 PrintUtil.fprintf_td(System.err,
"initClientAdapter: LE_Features %s\n", le_feats.
toString());
721 PrintUtil.fprintf_td(System.err,
"initClientAdapter: Set Default LE PHY: status %s: Tx %s, Rx %s\n",
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2021 Gothel Software e.K.
static final String CLIENT_KEY_PATH
LE Link Layer Feature Set (bitmask)
LE Transport PHY bit values (bitmask)
This central BTRole::Master participant works with DBTServer00.
String getName()
Return name of this endpoint, which becomes the adapter's name.
void setRemoveDevice(final boolean v)
Set remove device when disconnecting.
void setAdapter(final BTAdapter clientAdapter)
Set the server adapter for this endpoint.
DBTClient01(final String adapterName, final EUI48 useAdapter, final BTMode btMode)
int getProtocolSessionsDoneSuccess()
void setDisconnectDeviceed(final boolean v)
Set disconnect after processing.
void setDiscoveryPolicy(final DiscoveryPolicy v)
Set DiscoveryPolicy.
boolean initAdapter(final BTAdapter adapter)
Initialize the given adapter for this endpoint.
HCIStatusCode stopDiscovery(final String msg)
int getProtocolSessionsLeft()
HCIStatusCode startDiscovery(final String msg)
void setProtocolSessionsLeft(final int v)
void close(final String msg)
int getProtocolSessionsDoneTotal()
BTAdapter getAdapter()
Return the adapter for this endpoint.
DBTClient01(final String adapterName, final EUI48 useAdapter, final BTMode btMode, final boolean do_disconnect_randomly)
Bluetooth adapter operating mode.
DUAL
Dual Bluetooth mode, i.e.
Discovery policy defines the BTAdapter discovery mode after connecting a remote BTDevice:
PAUSE_CONNECTED_UNTIL_READY
Pause discovery until all connected BTDevice reach readiness inclusive optional SMP pairing (~120ms) ...
BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes.
Each enum represents a 'LE Transport PHY' bit value.
BTAdapter represents one local Bluetooth Controller.
HCIStatusCode stopDiscovery()
Turns off device discovery if it is enabled.
HCIStatusCode startDiscovery()
Starts discovery using all default arguments, see startDiscovery(DiscoveryPolicy, boolean,...
boolean isInitialized()
Returns true, if initialize(BTMode) has already been called for this adapter, otherwise false.
LE_Features getLEFeatures()
Return LE_Features for this controller.
boolean setPowered(final boolean power_on)
Sets the power state the adapter.
boolean equals(final Object obj)
If both types are of BTAdapter, it compares their BDAddressAndType, see getAddressAndType().
boolean addStatusListener(final AdapterStatusListener listener)
Add the given AdapterStatusListener to the list if not already present.
HCIStatusCode setDefaultLE_PHY(final LE_PHYs Tx, final LE_PHYs Rx)
Sets default preference of LE_PHYs.
BDAddressAndType getAddressAndType()
Returns the adapter's public BDAddressAndType.
HCIStatusCode setName(String name, String short_name)
Sets the name and short-name.
boolean removeStatusListener(final AdapterStatusListener l)
Remove the given AdapterStatusListener from the list.
int getBTMajorVersion()
Returns the Bluetooth major version of this adapter.
HCIStatusCode initialize(final BTMode btMode, boolean powerOn)
Initialize the adapter with default values, including power-on.