25package trial.org.direct_bt;
27import java.nio.charset.StandardCharsets;
28import java.util.ArrayList;
29import java.util.Arrays;
30import java.util.concurrent.atomic.AtomicInteger;
32import org.direct_bt.AdapterSettings;
33import org.direct_bt.AdapterStatusListener;
34import org.direct_bt.BTMode;
35import org.direct_bt.BTSecurityLevel;
36import org.direct_bt.BTAdapter;
37import org.direct_bt.BTDevice;
38import org.direct_bt.BTSecurityRegistry;
39import org.direct_bt.BTUtils;
40import org.direct_bt.DBGattChar;
41import org.direct_bt.DBGattDesc;
42import org.direct_bt.DBGattServer;
43import org.direct_bt.DBGattService;
44import org.direct_bt.DBGattValue;
45import org.direct_bt.DiscoveryPolicy;
46import org.direct_bt.EIRDataTypeSet;
47import org.direct_bt.EInfoReport;
48import org.direct_bt.GAPFlags;
49import org.direct_bt.GattCharPropertySet;
50import org.direct_bt.HCIStatusCode;
51import org.direct_bt.LE_Features;
52import org.direct_bt.LE_PHYs;
53import org.direct_bt.PairingMode;
54import org.direct_bt.SMPIOCapability;
55import org.direct_bt.SMPPairingState;
56import org.direct_bt.ScanType;
57import org.jau.io.PrintUtil;
58import org.jau.net.EUI48;
59import org.jau.sys.Clock;
60import org.jau.util.BasicTypes;
61import org.junit.Assert;
67 final boolean GATT_VERBOSE =
false;
68 private final String adapterShortName =
"TDev1Srv";
70 private final boolean SHOW_UPDATE_EVENTS =
false;
72 private String adapterName =
"TestDev1_Srv";
73 private EUI48 useAdapter = EUI48.ALL_DEVICE;
75 private boolean use_SC =
true;
77 private final MyAdapterStatusListener myAdapterStatusListener =
new MyAdapterStatusListener();
78 private final MyGATTServerListener gattServerListener =
new MyGATTServerListener();
80 private final Object sync_lock =
new Object();
81 private volatile BTDevice connectedDevice;
83 private final AtomicInteger disconnectCount =
new AtomicInteger(0);
84 private final AtomicInteger servedProtocolSessionsTotal =
new AtomicInteger(0);
85 private final AtomicInteger servedProtocolSessionsSuccess =
new AtomicInteger(0);
86 private final AtomicInteger servingProtocolSessionsLeft =
new AtomicInteger(1);
88 private final boolean do_disconnect_randomly;
90 public DBTServer01(
final String adapterName,
final EUI48 useAdapter,
final BTMode btMode,
final boolean use_SC,
final BTSecurityLevel adapterSecurityLevel,
final boolean do_disconnect_randomly) {
91 this.adapterName = adapterName;
92 this.useAdapter = useAdapter;
95 this.adapterSecurityLevel = adapterSecurityLevel;
96 this.do_disconnect_randomly = do_disconnect_randomly;
101 this(adapterName, useAdapter, btMode, use_SC, adapterSecurityLevel,
false );
105 public String
getName() {
return adapterName; }
112 this.serverAdapter = serverAdapter;
119 servingProtocolSessionsLeft.set(v);
123 return servingProtocolSessionsLeft.get();
127 return servedProtocolSessionsTotal.get();
131 return servedProtocolSessionsSuccess.get();
136 return this.disconnectCount.get();
139 private final void setDevice(
final BTDevice cd) {
140 synchronized( sync_lock ) {
141 connectedDevice = cd;
145 private final BTDevice getDevice() {
146 synchronized( sync_lock ) {
147 return connectedDevice;
151 private boolean matches(
final BTDevice device) {
152 final BTDevice d = getDevice();
153 return null != d ? d.equals(device) :
false;
156 static Thread executeOffThread(
final Runnable runobj,
final String threadName,
final boolean detach) {
157 final Thread t =
new Thread( runobj, threadName );
158 t.setDaemon( detach );
162 static Thread executeOffThread(
final Runnable runobj,
final boolean detach) {
163 final Thread t =
new Thread( runobj );
164 t.setDaemon( detach );
170 private final DBGattServer dbGattServer =
new DBGattServer(
173 new DBGattService (
true ,
174 DBGattService.UUID16.GENERIC_ACCESS ,
176 new DBGattChar( DBGattChar.UUID16.DEVICE_NAME ,
177 new GattCharPropertySet(GattCharPropertySet.Type.Read),
178 new ArrayList<DBGattDesc>( ),
179 DBGattValue.make(adapterName, 128) ),
180 new DBGattChar( DBGattChar.UUID16.APPEARANCE ,
181 new GattCharPropertySet(GattCharPropertySet.Type.Read),
182 new ArrayList<DBGattDesc>( ),
183 DBGattValue.make((
short)0) )
185 new DBGattService (
true ,
186 DBGattService.UUID16.DEVICE_INFORMATION ,
188 new DBGattChar( DBGattChar.UUID16.MANUFACTURER_NAME_STRING ,
189 new GattCharPropertySet(GattCharPropertySet.Type.Read),
190 new ArrayList<DBGattDesc>( ),
191 DBGattValue.make(
"Gothel Software") ),
192 new DBGattChar( DBGattChar.UUID16.MODEL_NUMBER_STRING ,
193 new GattCharPropertySet(GattCharPropertySet.Type.Read),
194 new ArrayList<DBGattDesc>( ),
195 DBGattValue.make(
"3.2.0-pre") ),
196 new DBGattChar( DBGattChar.UUID16.SERIAL_NUMBER_STRING ,
197 new GattCharPropertySet(GattCharPropertySet.Type.Read),
198 new ArrayList<DBGattDesc>( ),
199 DBGattValue.make(
"sn:0123456789") ),
200 new DBGattChar( DBGattChar.UUID16.HARDWARE_REVISION_STRING ,
201 new GattCharPropertySet(GattCharPropertySet.Type.Read),
202 new ArrayList<DBGattDesc>( ),
203 DBGattValue.make(
"hw:0123456789") ),
204 new DBGattChar( DBGattChar.UUID16.FIRMWARE_REVISION_STRING ,
205 new GattCharPropertySet(GattCharPropertySet.Type.Read),
206 new ArrayList<DBGattDesc>( ),
207 DBGattValue.make(
"fw:0123456789") ),
208 new DBGattChar( DBGattChar.UUID16.SOFTWARE_REVISION_STRING ,
209 new GattCharPropertySet(GattCharPropertySet.Type.Read),
210 new ArrayList<DBGattDesc>( ),
211 DBGattValue.make(
"sw:0123456789") )
213 new DBGattService (
true ,
217 new GattCharPropertySet(GattCharPropertySet.Type.Read),
219 new DBGattDesc( DBGattDesc.UUID16.USER_DESC, DBGattValue.make(
"DATA_STATIC") )
221 DBGattValue.make(
"Proprietary Static Data 0x00010203") ),
223 new GattCharPropertySet(GattCharPropertySet.Type.WriteNoAck).set(GattCharPropertySet.Type.WriteWithAck),
225 new DBGattDesc( DBGattDesc.UUID16.USER_DESC, DBGattValue.make(
"COMMAND") )
227 DBGattValue.make(128, 64) ),
229 new GattCharPropertySet(GattCharPropertySet.Type.Notify).set(GattCharPropertySet.Type.Indicate),
231 new DBGattDesc( DBGattDesc.UUID16.USER_DESC, DBGattValue.make(
"RESPONSE") ),
232 DBGattDesc.createClientCharConfig()
234 DBGattValue.make((
short)0) ),
236 new GattCharPropertySet(GattCharPropertySet.Type.Notify).set(GattCharPropertySet.Type.Indicate),
238 new DBGattDesc( DBGattDesc.UUID16.USER_DESC, DBGattValue.make(
"DATA_PULSE") ),
239 DBGattDesc.createClientCharConfig()
241 DBGattValue.make(
"Synthethic Sensor 01") )
246 class MyAdapterStatusListener
extends AdapterStatusListener {
248 public void adapterSettingsChanged(
final BTAdapter adapter,
final AdapterSettings oldmask,
249 final AdapterSettings newmask,
final AdapterSettings changedmask,
final long timestamp) {
250 final boolean initialSetting = oldmask.isEmpty();
251 if( initialSetting ) {
252 PrintUtil.println(System.err,
"****** Server SETTINGS_INITIAL: "+oldmask+
" -> "+newmask+
", changed "+changedmask);
254 PrintUtil.println(System.err,
"****** Server SETTINGS_CHANGED: "+oldmask+
" -> "+newmask+
", changed "+changedmask);
256 final boolean justPoweredOn = changedmask.isSet(AdapterSettings.SettingType.POWERED) &&
257 newmask.isSet(AdapterSettings.SettingType.POWERED);
258 if( justPoweredOn && serverAdapter.
equals(adapter) ) {
260 "Server DBT-StartAdvertising-"+adapter.getAddressAndType(),
true );
263 PrintUtil.println(System.err,
"Server Status Adapter:");
264 PrintUtil.println(System.err, adapter.toString());
268 public void discoveringChanged(
final BTAdapter adapter,
final ScanType currentMeta,
final ScanType changedType,
final boolean changedEnabled,
final DiscoveryPolicy policy,
final long timestamp) {
269 PrintUtil.println(System.err,
"****** Server DISCOVERING: meta "+currentMeta+
", changed["+changedType+
", enabled "+changedEnabled+
", policy "+policy+
"] on "+adapter);
273 public boolean deviceFound(
final BTDevice device,
final long timestamp) {
274 PrintUtil.println(System.err,
"****** Server FOUND__-1: NOP "+device.toString());
279 public void deviceUpdated(
final BTDevice device,
final EIRDataTypeSet updateMask,
final long timestamp) {
280 if( SHOW_UPDATE_EVENTS ) {
281 PrintUtil.println(System.err,
"****** Server UPDATED: "+updateMask+
" of "+device);
286 public void deviceConnected(
final BTDevice device,
final boolean discovered,
final long timestamp) {
287 PrintUtil.println(System.err,
"****** Server CONNECTED (served "+disconnectCount.get()+
", left "+servingProtocolSessionsLeft.get()+
"): discovered "+discovered+
": "+device+
" on "+device.getAdapter());
288 final boolean available =
null == getDevice();
295 public void devicePairingState(
final BTDevice device,
final SMPPairingState state,
final PairingMode mode,
final long timestamp) {
296 PrintUtil.println(System.err,
"****** Server PAIRING_STATE: state "+state+
", mode "+mode+
": "+device);
304 case REQUESTED_BY_RESPONDER:
307 case FEATURE_EXCHANGE_STARTED:
310 case FEATURE_EXCHANGE_COMPLETED:
313 case PASSKEY_EXPECTED: {
314 final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getStartOf(device.getAddressAndType().address,
"");
315 if(
null != sec && sec.getPairingPasskey() != BTSecurityRegistry.NO_PASSKEY ) {
316 executeOffThread( () -> { device.setPairingPasskey( sec.getPairingPasskey() ); },
"DBT-SetPasskey-"+device.getAddressAndType(),
true );
318 executeOffThread( () -> { device.setPairingPasskey( 0 ); },
"DBT-SetPasskey-"+device.getAddressAndType(),
true );
323 case NUMERIC_COMPARE_EXPECTED: {
324 final BTSecurityRegistry.Entry sec = BTSecurityRegistry.getStartOf(device.getAddressAndType().address,
"");
326 executeOffThread( () -> { device.setPairingNumericComparison( sec.getPairingNumericComparison() ); },
"DBT-SetNumericComp-"+device.getAddressAndType(),
true );
328 executeOffThread( () -> { device.setPairingNumericComparison(
false ); },
"DBT-SetNumericCompFalse-"+device.getAddressAndType(),
true );
335 case KEY_DISTRIBUTION:
347 public void deviceReady(
final BTDevice device,
final long timestamp) {
348 PrintUtil.println(System.err,
"****** Server READY-1: NOP " + device.toString());
352 public void deviceDisconnected(
final BTDevice device,
final HCIStatusCode reason,
final short handle,
final long timestamp) {
353 PrintUtil.println(System.err,
"****** Server DISCONNECTED (served "+(1+disconnectCount.get())+
", left "+servingProtocolSessionsLeft.get()+
"): Reason "+reason+
", old handle 0x"+Integer.toHexString(handle)+
": "+device+
" on "+device.getAdapter());
354 final boolean match = matches(device);
358 executeOffThread( () -> { processDisconnectedDevice(device); },
359 "Server DBT-Disconnected-"+device.getAdapter().getAddressAndType(),
true );
363 public String toString() {
364 return "Server AdapterStatusListener[user, per-adapter]";
368 class MyGATTServerListener
extends DBGattServer.Listener implements AutoCloseable {
369 private final Thread pulseSenderThread;
370 private volatile boolean stopPulseSenderFlag =
false;
372 private volatile short handlePulseDataNotify = 0;
373 private volatile short handlePulseDataIndicate = 0;
374 private volatile short handleResponseDataNotify = 0;
375 private volatile short handleResponseDataIndicate = 0;
377 private int usedMTU = 23;
379 private void clear() {
380 synchronized( sync_lock ) {
381 handlePulseDataNotify = 0;
382 handlePulseDataIndicate = 0;
383 handleResponseDataNotify = 0;
384 handleResponseDataIndicate = 0;
391 private boolean shallStopPulseSender() {
392 synchronized( sync_lock ) {
393 return stopPulseSenderFlag;
396 private void pulseSender() {
398 final BTDevice connectedDevice_ = getDevice();
399 final String connectedDeviceStr =
null != connectedDevice_ ? connectedDevice_.toString() :
"n/a";
400 PrintUtil.fprintf_td(System.err,
"****** Server GATT::PULSE Start %s\n", connectedDeviceStr);
402 while( !shallStopPulseSender() ) {
403 final BTDevice connectedDevice_ = getDevice();
404 if(
null != connectedDevice_ && connectedDevice_.getConnected() ) {
405 if( 0 != handlePulseDataNotify || 0 != handlePulseDataIndicate ) {
406 final String data = String.format(
"Dynamic Data Example. Elapsed Milliseconds: %,9d", Clock.elapsedTimeMillis());
407 final byte[] v = data.getBytes(StandardCharsets.UTF_8);
408 if( 0 != handlePulseDataNotify ) {
410 PrintUtil.fprintf_td(System.err,
"****** Server GATT::sendNotification: PULSE to %s\n", connectedDevice_.toString());
412 connectedDevice_.sendNotification(handlePulseDataNotify, v);
414 if( 0 != handlePulseDataIndicate ) {
416 PrintUtil.fprintf_td(System.err,
"****** Server GATT::sendIndication: PULSE to %s\n", connectedDevice_.toString());
418 connectedDevice_.sendIndication(handlePulseDataIndicate, v);
422 if( !shallStopPulseSender() ) {
425 }
catch (
final InterruptedException e) { }
429 final BTDevice connectedDevice_ = getDevice();
430 final String connectedDeviceStr =
null != connectedDevice_ ? connectedDevice_.toString() :
"n/a";
431 PrintUtil.fprintf_td(System.err,
"****** Server GATT::PULSE End %s\n", connectedDeviceStr);
435 private void sendResponse(
final byte[] data) {
436 final BTDevice connectedDevice_ = getDevice();
437 if(
null != connectedDevice_ && connectedDevice_.getConnected() ) {
438 if( 0 != handleResponseDataNotify || 0 != handleResponseDataIndicate ) {
439 if( 0 != handleResponseDataNotify ) {
441 PrintUtil.fprintf_td(System.err,
"****** Server GATT::sendNotification: %s to %s\n",
442 BasicTypes.bytesHexString(data, 0, data.length,
true ), connectedDevice_.toString());
444 connectedDevice_.sendNotification(handleResponseDataNotify, data);
446 if( 0 != handleResponseDataIndicate ) {
448 PrintUtil.fprintf_td(System.err,
"****** Server GATT::sendIndication: %s to %s\n",
449 BasicTypes.bytesHexString(data, 0, data.length,
true ), connectedDevice_.toString());
451 connectedDevice_.sendIndication(handleResponseDataIndicate, data);
457 private void disconnectDeviceRandomly() {
459 final int sleep_min = 100;
460 final int sleep_max = 1500;
461 final int sleep_dur = (int) ( Math.random() * ( sleep_max - sleep_min + 1 ) + sleep_min );
463 Thread.sleep(sleep_dur);
464 }
catch (
final InterruptedException e) { }
466 final BTDevice connectedDevice_ = getDevice();
467 if(
null != connectedDevice_ ) {
468 PrintUtil.fprintf_td(System.err,
"****** Server i470 disconnectDevice(delayed %d ms): client %s\n", sleep_dur, connectedDevice_.toString());
469 connectedDevice_.disconnect();
471 PrintUtil.fprintf_td(System.err,
"****** Server i470 disconnectDevice(delayed %d ms): client null\n", sleep_dur);
475 public MyGATTServerListener() {
476 pulseSenderThread = executeOffThread( () -> { pulseSender(); },
"GattServer-PulseSender",
false );
480 public void close() {
481 synchronized( sync_lock ) {
483 stopPulseSenderFlag =
true;
486 pulseSenderThread.join(1000);
487 }
catch (
final InterruptedException e) { }
492 public void connected(
final BTDevice device,
final int initialMTU) {
493 final boolean match = matches(device);
494 PrintUtil.fprintf_td(System.err,
"****** Server GATT::connected(match %b): initMTU %d, %s\n",
495 match, initialMTU, device.toString());
497 synchronized( sync_lock ) {
498 usedMTU = initialMTU;
504 public void disconnected(
final BTDevice device) {
505 final boolean match = matches(device);
506 PrintUtil.fprintf_td(System.err,
"****** Server GATT::disconnected(match %b): %s\n", match, device.toString());
513 public void mtuChanged(
final BTDevice device,
final int mtu) {
514 final boolean match = matches(device);
515 final int usedMTU_old = usedMTU;
517 synchronized( sync_lock ) {
521 PrintUtil.fprintf_td(System.err,
"****** Server GATT::mtuChanged(match %b, served %d, left %d): %d -> %d, %s\n",
522 match, servedProtocolSessionsTotal.get(), servingProtocolSessionsLeft.get(),
523 match ? usedMTU_old : 0, mtu, device.toString());
524 if( do_disconnect_randomly ) {
525 executeOffThread( () -> { disconnectDeviceRandomly(); },
"GattServer-DisconnectDevice",
true );
530 public boolean readCharValue(
final BTDevice device,
final DBGattService s,
final DBGattChar c) {
531 final boolean match = matches(device);
533 PrintUtil.fprintf_td(System.err,
"****** Server GATT::readCharValue(match %b): to %s, from\n %s\n %s\n",
534 match, device.toString(), s.toString(), c.toString());
540 public boolean readDescValue(
final BTDevice device,
final DBGattService s,
final DBGattChar c,
final DBGattDesc d) {
541 final boolean match = matches(device);
543 PrintUtil.fprintf_td(System.err,
"****** Server GATT::readDescValue(match %b): to %s, from\n %s\n %s\n %s\n",
544 match, device.toString(), s.toString(), c.toString(), d.toString());
550 public boolean writeCharValue(
final BTDevice device,
final DBGattService s,
final DBGattChar c,
final byte[] value,
final int value_offset) {
551 final boolean match = matches(device);
553 final String value_s = BasicTypes.bytesHexString(value, 0, value.length,
true )+
554 " '"+BTUtils.decodeUTF8String(value, 0, value.length)+
"'";
555 PrintUtil.fprintf_td(System.err,
"****** Server GATT::writeCharValue(match %b): %s @ %d from %s, to\n %s\n %s\n",
556 match, value_s, value_offset,
557 device.toString(), s.toString(), c.toString());
563 public void writeCharValueDone(
final BTDevice device,
final DBGattService s,
final DBGattChar c) {
564 final boolean match = matches(device);
565 final DBGattValue value = c.getValue();
566 final byte[] data = value.data();
567 boolean isFinalHandshake =
false;
568 boolean isFinalHandshakeSuccess =
false;
572 ( 0 != handleResponseDataNotify || 0 != handleResponseDataIndicate ) )
574 isFinalHandshakeSuccess = Arrays.equals(
DBTConstants.SuccessHandshakeCommandData, data);
575 isFinalHandshake = isFinalHandshakeSuccess ||
576 Arrays.equals(
DBTConstants.FailHandshakeCommandData, data);
578 if( isFinalHandshake ) {
579 if( isFinalHandshakeSuccess ) {
580 servedProtocolSessionsSuccess.addAndGet(1);
582 servedProtocolSessionsTotal.addAndGet(1);
583 if( servingProtocolSessionsLeft.get() > 0 ) {
584 servingProtocolSessionsLeft.decrementAndGet();
587 executeOffThread( () -> { sendResponse( data ); },
true );
589 if( GATT_VERBOSE || isFinalHandshake ) {
590 PrintUtil.fprintf_td(System.err,
"****** Server GATT::writeCharValueDone(match %b, finalCmd %b, sessions [%d ok / %d total], left %d): From %s, to\n %s\n %s\n Char-Value: %s\n",
591 match, isFinalHandshake, servedProtocolSessionsSuccess.get(), servedProtocolSessionsTotal.get(), servingProtocolSessionsLeft.get(),
592 device.toString(), s.toString(), c.toString(), value.toString());
597 public boolean writeDescValue(
final BTDevice device,
final DBGattService s,
final DBGattChar c,
final DBGattDesc d,
598 final byte[] value,
final int value_offset)
600 final boolean match = matches(device);
602 final String value_s = BasicTypes.bytesHexString(value, 0, value.length,
true )+
603 " '"+BTUtils.decodeUTF8String(value, 0, value.length)+
"'";
604 PrintUtil.fprintf_td(System.err,
"****** Server GATT::writeDescValue(match %b): %s @ %d from %s\n %s\n %s\n %s\n",
605 match, value_s, value_offset,
606 device.toString(), s.toString(), c.toString(), d.toString());
612 public void writeDescValueDone(
final BTDevice device,
final DBGattService s,
final DBGattChar c,
final DBGattDesc d) {
614 final boolean match = matches(device);
615 final DBGattValue value = d.getValue();
616 PrintUtil.fprintf_td(System.err,
"****** Server GATT::writeDescValueDone(match %b): From %s\n %s\n %s\n %s\n Desc-Value: %s\n",
617 match, device.toString(), s.toString(), c.toString(), d.toString(), value.toString());
622 public void clientCharConfigChanged(
final BTDevice device,
final DBGattService s,
final DBGattChar c,
final DBGattDesc d,
623 final boolean notificationEnabled,
final boolean indicationEnabled)
625 final boolean match = matches(device);
627 final DBGattValue value = d.getValue();
628 PrintUtil.fprintf_td(System.err,
"****** Server GATT::clientCharConfigChanged(match %b): notify %b, indicate %b from %s\n %s\n %s\n %s\n Desc-Value: %s\n",
629 match, notificationEnabled, indicationEnabled,
630 device.toString(), s.toString(), c.toString(), d.toString(), value.toString());
633 final String value_type = c.getValueType();
634 final short value_handle = c.getValueHandle();
636 synchronized( sync_lock ) {
637 handlePulseDataNotify = notificationEnabled ? value_handle : 0;
638 handlePulseDataIndicate = indicationEnabled ? value_handle : 0;
640 }
else if( value_type.equals(
DBTConstants.ResponseUUID ) ) {
641 synchronized( sync_lock ) {
642 handleResponseDataNotify = notificationEnabled ? value_handle : 0;
643 handleResponseDataIndicate = indicationEnabled ? value_handle : 0;
649 static final short adv_interval_min=(short)160;
650 static final short adv_interval_max=(short)480;
651 static final byte adv_type=(byte)0;
652 static final byte adv_chan_map=(byte)0x07;
653 static final byte filter_policy=(byte)0x00;
656 public void close(
final String msg) {
657 PrintUtil.println(System.err,
"****** Server Close.0: "+msg);
660 stopAdvertising(msg);
661 final BTDevice connectedDevice_ = getDevice();
662 if(
null != connectedDevice_ ) {
667 gattServerListener.close();
669 stopAdvertising(msg);
670 PrintUtil.println(System.err,
"****** Server Close.X: "+msg);
675 PrintUtil.println(System.err,
"****** Server Stop advertising ("+msg+
") result: "+status+
": "+serverAdapter.
toString());
701 if(
null != gattDevNameChar ) {
702 final byte[] aname_bytes = serverAdapter.
getName().getBytes(StandardCharsets.UTF_8);
703 gattDevNameChar.
setValue(aname_bytes, 0, aname_bytes.length, 0);
706 PrintUtil.println(System.err,
"****** Server Start advertising ("+msg+
"): EIR "+eir.
toString());
707 PrintUtil.println(System.err,
"****** Server Start advertising ("+msg+
"): adv "+adv_mask.
toString()+
", scanrsp "+scanrsp_mask.
toString());
710 adv_interval_min, adv_interval_max,
711 adv_type, adv_chan_map, filter_policy);
712 PrintUtil.println(System.err,
"****** Server Start advertising ("+msg+
") result: "+status+
": "+serverAdapter.
toString());
714 PrintUtil.println(System.err, dbGattServer.toFullString());
719 private void processDisconnectedDevice(
final BTDevice device) {
720 PrintUtil.println(System.err,
"****** Server Disconnected Device (count "+(1+disconnectCount.get())+
721 ", served "+servedProtocolSessionsTotal.get()+
", left "+servingProtocolSessionsLeft.get()+
"): Start "+device.
toString());
724 stopAdvertising(
"device-disconnected");
727 disconnectCount.addAndGet(1);
731 }
catch (
final InterruptedException e) { }
733 if( servingProtocolSessionsLeft.get() > 0 ) {
737 PrintUtil.println(System.err,
"****** Server Disonnected Device: End "+device.
toString());
743 PrintUtil.fprintf_td(System.err,
"initServerAdapter: Adapter not selected: %s\n", adapter.
toString());
752 PrintUtil.fprintf_td(System.err,
"initServerAdapter: initialization failed: %s: %s\n",
753 status.toString(), adapter.
toString());
757 PrintUtil.fprintf_td(System.err,
"initServerAdapter: setPower.1 off failed: %s\n", adapter.
toString());
761 PrintUtil.println(System.err,
"initServerAdapter.1: "+adapter.
toString());
766 PrintUtil.fprintf_td(System.err,
"initServerAdapter: setLocalName OK: %s\n", adapter.
toString());
768 PrintUtil.fprintf_td(System.err,
"initServerAdapter: setLocalName failed: %s\n", adapter.
toString());
774 PrintUtil.fprintf_td(System.err,
"initServerAdapter: setSecureConnections OK: %s\n", adapter.
toString());
776 PrintUtil.fprintf_td(System.err,
"initServerAdapter: setSecureConnections failed: %s\n", adapter.
toString());
780 final short conn_min_interval = 8;
781 final short conn_max_interval = 40;
782 final short conn_latency = 0;
783 final short supervision_timeout = 50;
784 status = adapter.
setDefaultConnParam(conn_min_interval, conn_max_interval, conn_latency, supervision_timeout);
786 PrintUtil.fprintf_td(System.err,
"initServerAdapter: setDefaultConnParam OK: %s\n", adapter.
toString());
788 PrintUtil.fprintf_td(System.err,
"initServerAdapter: setDefaultConnParam UNKNOWN_COMMAND (ignored): %s\n", adapter.
toString());
790 PrintUtil.fprintf_td(System.err,
"initServerAdapter: setDefaultConnParam failed: %s, %s\n", status.toString(), adapter.
toString());
795 PrintUtil.fprintf_td(System.err,
"initServerAdapter: setPower.2 on failed: %s\n", adapter.
toString());
800 PrintUtil.println(System.err,
"initServerAdapter.2: "+adapter.
toString());
804 PrintUtil.fprintf_td(System.err,
"initServerAdapter: LE_Features %s\n", le_feats.
toString());
811 PrintUtil.fprintf_td(System.err,
"initServerAdapter: Set Default LE PHY: status %s: Tx %s, Rx %s\n",
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2021 Gothel Software e.K.
Selected standard GATT characteristic numbers in UUID16 format as defined.
static String DEVICE_NAME
Representing a Gatt Characteristic object from the GATT server perspective.
native boolean setValue(final byte[] source, final int source_pos, final int source_len, final int dest_pos)
Set this characteristic's native value.
synchronized boolean addListener(final Listener l)
Selected standard GATT service service numbers in UUID16 format as defined.
static String GENERIC_ACCESS
This service contains generic information about the device.
Representing a Gatt Service object from the ::GATTRole::Server perspective.
Bit mask of 'Extended Inquiry Response' (EIR) data fields, indicating a set of related data.
void set(final DataType bit)
Collection of 'Extended Advertising Data' (EAD), 'Advertising Data' (AD) or 'Extended Inquiry Respons...
native void setConnInterval(final short min, final short max)
Set slave connection interval range.
native String toString(final boolean includeServices)
final void addFlag(final GAPFlags.Bit f)
native void setName(final String name)
native void setServicesComplete(final boolean v)
native void addService(final String uuid)
Bit mask of 'Extended Inquiry Response' (EIR) data fields, indicating a set of related data.
LE Link Layer Feature Set (bitmask)
LE Transport PHY bit values (bitmask)
static final String SERVER_KEY_PATH
static final String DataServiceUUID
This peripheral BTRole::Slave test participant works with DBTClient00.
DBTServer01(final String adapterName, final EUI48 useAdapter, final BTMode btMode, final boolean use_SC, final BTSecurityLevel adapterSecurityLevel, final boolean do_disconnect_randomly)
int getProtocolSessionsDoneTotal()
BTAdapter getAdapter()
Return the adapter for this endpoint.
HCIStatusCode startAdvertising(final String msg)
DBTServer01(final String adapterName, final EUI48 useAdapter, final BTMode btMode, final boolean use_SC, final BTSecurityLevel adapterSecurityLevel)
int getProtocolSessionsDoneSuccess()
int getProtocolSessionsLeft()
String getName()
Return name of this endpoint, which becomes the adapter's name.
boolean initAdapter(final BTAdapter adapter)
Initialize the given adapter for this endpoint.
void setProtocolSessionsLeft(final int v)
void close(final String msg)
void setAdapter(final BTAdapter serverAdapter)
Set the server adapter for this endpoint.
BTSecurityLevel getSecurityLevel()
Bluetooth adapter operating mode.
DUAL
Dual Bluetooth mode, i.e.
Bluetooth Security Level.
UNSET
Security Level not set, value 0.
Each enum represents a 'Extended Inquiry Response' (EIR) data field type bit.
Each enum represents a 'Extended Inquiry Response' (EIR) data field type bit.
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.
UNSET
Denoting unset value, i.e.
BTAdapter represents one local Bluetooth Controller.
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().
HCIStatusCode startAdvertising(final DBGattServer gattServerData, final EInfoReport eir, final EIRDataTypeSet adv_mask, final EIRDataTypeSet scanrsp_mask, final short adv_interval_min, final short adv_interval_max, final byte adv_type, final byte adv_chan_map, final byte filter_policy)
Starts advertising.
HCIStatusCode setSecureConnections(final boolean enable)
Enable or disable Secure Connections (SC) of the adapter.
String getName()
Returns the name.
void setSMPKeyPath(final String path)
Set the adapter's persistent storage directory for SMPKeyBin files.
void setServerConnSecurity(final BTSecurityLevel sec_level, final SMPIOCapability io_cap)
Sets the given ::BTSecurityLevel and ::SMPIOCapability for connecting device when in server (peripher...
boolean addStatusListener(final AdapterStatusListener listener)
Add the given AdapterStatusListener to the list if not already present.
HCIStatusCode setDefaultConnParam(final short conn_interval_min, final short conn_interval_max, final short conn_latency, final short supervision_timeout)
Set default connection parameter of incoming connections for this adapter when in server mode,...
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.
HCIStatusCode stopAdvertising()
Ends advertising.
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.
BTDevice represents one remote Bluetooth device.
boolean remove()
Remove this device from the system (like an unpair).
HCIStatusCode disconnect()
jau.direct_bt: Disconnect the LE or BREDR peer's GATT and HCI connection.