6
6
import android .bluetooth .BluetoothGatt ;
7
7
import android .bluetooth .BluetoothGattCallback ;
8
8
import android .bluetooth .BluetoothGattCharacteristic ;
9
+ import android .bluetooth .BluetoothGattDescriptor ;
9
10
import android .bluetooth .BluetoothGattService ;
10
11
import android .bluetooth .BluetoothProfile ;
11
12
import android .bluetooth .le .BluetoothLeScanner ;
30
31
import org .godotengine .godot .plugin .GodotPlugin ;
31
32
import org .godotengine .godot .plugin .SignalInfo ;
32
33
34
+ import java .nio .charset .StandardCharsets ;
33
35
import java .util .Arrays ;
34
36
import java .util .HashMap ;
35
37
import java .util .List ;
36
38
import java .util .Map ;
37
39
import java .util .Set ;
40
+ import java .util .UUID ;
38
41
39
42
public class BluetoothManager extends GodotPlugin {
40
43
@@ -101,7 +104,11 @@ public List<String> getPluginMethods() {
101
104
"locationStatus" ,
102
105
"connect" ,
103
106
"disconnect" ,
104
- "listServicesAndCharacteristics" );
107
+ "listServicesAndCharacteristics" ,
108
+ "subscribeToCharacteristic" ,
109
+ "unsubscribeToCharacteristic" ,
110
+ "writeToCharacteristic" ,
111
+ "readFromCharacteristic" );
105
112
}
106
113
107
114
public void sendDebugSignal (String s ) {
@@ -131,6 +138,7 @@ public Set<SignalInfo> getPluginSignals() {
131
138
signals .add (new SignalInfo ("_on_bluetooth_status_change" , String .class ));
132
139
signals .add (new SignalInfo ("_on_location_status_change" , String .class ));
133
140
signals .add (new SignalInfo ("_on_connection_status_change" , String .class ));
141
+ signals .add (new SignalInfo ("_on_characteristic_reading" , String .class ));
134
142
signals .add (new SignalInfo ("_on_characteristic_read" , org .godotengine .godot .Dictionary .class ));
135
143
136
144
return signals ;
@@ -292,8 +300,11 @@ public void onConnectionStateChange(final BluetoothGatt gatt, final int status,
292
300
293
301
break ;
294
302
case BluetoothProfile .STATE_CONNECTED :
295
- emitSignal ("_on_connection_status_change" , "connected" );
296
303
connected = true ;
304
+ // Read services and characteristics
305
+ listServicesAndCharacteristics ();
306
+
307
+ emitSignal ("_on_connection_status_change" , "connected" );
297
308
298
309
break ;
299
310
}
@@ -321,6 +332,9 @@ public void onCharacteristicRead(BluetoothGatt gatt,
321
332
322
333
if (status == BluetoothGatt .GATT_SUCCESS ) {
323
334
sendDebugSignal ("onCharacteristicRead: SUCCESS" );
335
+ } else {
336
+
337
+ sendDebugSignal ("onCharacteristicRead: " + Integer .toString (status ));
324
338
}
325
339
}
326
340
@@ -342,26 +356,43 @@ public void onCharacteristicWrite(BluetoothGatt gatt,
342
356
public void onCharacteristicChanged (BluetoothGatt gatt , BluetoothGattCharacteristic characteristic
343
357
//,byte[] value, For Android Tiramisu we need this
344
358
) {
345
- sendDebugSignal ("onCharacteristicChanged" );
359
+ String uuid = characteristic .getUuid ().toString ();
360
+ byte [] value = characteristic .getValue ();
361
+ String s = Arrays .toString (value );
362
+ String s1 = new String (value , StandardCharsets .ISO_8859_1 );
363
+
364
+ sendDebugSignal ("onCharacteristicChanged " + uuid );
365
+ sendDebugSignal ("onCharacteristicChanged " + Integer .toString (value .length ));
366
+ sendDebugSignal ("onCharacteristicChanged " + s );
367
+ sendDebugSignal ("onCharacteristicChanged " + s1 );
368
+
346
369
}
347
370
};
348
371
349
372
@ SuppressLint ("MissingPermission" )
350
373
public void connect (String address ) {
351
- sendDebugSignal ("Connecting to device with address " + address );
352
- stopScan ();
353
- bluetoothGatt = devices .get (address ).getDevice ().connectGatt (context , false , btleGattCallback );
374
+
375
+ if (!connected ) {
376
+ sendDebugSignal ("Connecting to device with address " + address );
377
+ stopScan ();
378
+ bluetoothGatt = devices .get (address ).getDevice ().connectGatt (context , false , btleGattCallback );
379
+ }
354
380
}
355
381
356
382
@ SuppressLint ("MissingPermission" )
357
383
public void disconnect () {
358
- sendDebugSignal ("Disconnecting device" );
359
- bluetoothGatt .disconnect ();
384
+
385
+ if (connected ) {
386
+ sendDebugSignal ("Disconnecting device" );
387
+ bluetoothGatt .disconnect ();
388
+ }
360
389
}
361
390
362
391
private void sendServicesAndCharacteristics (List <BluetoothGattService > gattServices ) {
363
392
if (gattServices == null ) return ;
364
393
394
+ emitSignal ("_on_characteristic_reading" , "processing" );
395
+
365
396
// Loops through available GATT Services.
366
397
for (BluetoothGattService gattService : gattServices ) {
367
398
@@ -404,13 +435,82 @@ private void sendServicesAndCharacteristics(List<BluetoothGattService> gattServi
404
435
emitSignal ("_on_characteristic_read" , characteristicData );
405
436
}
406
437
}
438
+
439
+ emitSignal ("_on_characteristic_reading" , "done" );
440
+ }
441
+
442
+ // Read from characteristic
443
+ @ SuppressLint ("MissingPermission" )
444
+ private void readFromCharacteristic (String serviceUUID , String characteristicUUID ) {
445
+
446
+ if (connected ) {
447
+
448
+ UUID service = UUID .fromString (serviceUUID );
449
+ UUID characteristic = UUID .fromString (characteristicUUID );
450
+
451
+ BluetoothGattCharacteristic c = bluetoothGatt .getService (service ).getCharacteristic (characteristic );
452
+
453
+ bluetoothGatt .readCharacteristic (c );
454
+ }
407
455
}
408
- }
409
456
410
- /*
457
+ // Write to characteristic, automatically detects the write type
458
+ @ SuppressLint ("MissingPermission" )
459
+ private void writeToCharacteristic (String serviceUUID , String characteristicUUID , String data ) {
460
+
461
+ if (connected ) {
462
+
463
+ UUID service = UUID .fromString (serviceUUID );
464
+ UUID characteristic = UUID .fromString (characteristicUUID );
411
465
466
+ BluetoothGattCharacteristic c = bluetoothGatt .getService (service ).getCharacteristic (characteristic );
467
+ c .setValue (data );
412
468
413
- Received F3:60:26:8A:AD:78
414
- Received Take
469
+ if (c .getWriteType () == BluetoothGattCharacteristic .WRITE_TYPE_DEFAULT ) {
415
470
416
- */
471
+ c .setWriteType (BluetoothGattCharacteristic .WRITE_TYPE_DEFAULT );
472
+
473
+ } else if (c .getWriteType () == BluetoothGattCharacteristic .WRITE_TYPE_NO_RESPONSE ) {
474
+
475
+ c .setWriteType (BluetoothGattCharacteristic .WRITE_TYPE_NO_RESPONSE );
476
+ }
477
+
478
+ bluetoothGatt .writeCharacteristic (c );
479
+ }
480
+ }
481
+
482
+ // Subscribe to characteristic
483
+ @ SuppressLint ("MissingPermission" )
484
+ private void subscribeToCharacteristic (String serviceUUID , String characteristicUUID ) {
485
+
486
+ if (connected ) {
487
+
488
+ UUID service = UUID .fromString (serviceUUID );
489
+ UUID characteristic = UUID .fromString (characteristicUUID );
490
+
491
+ BluetoothGattCharacteristic c = bluetoothGatt .getService (service ).getCharacteristic (characteristic );
492
+ bluetoothGatt .setCharacteristicNotification (c ,true );
493
+
494
+
495
+ // Set the Client Characteristic Config Descriptor to allow server initiated updates
496
+ UUID CONFIG_DESCRIPTOR = UUID .fromString ("00002902-0000-1000-8000-00805f9b34fb" );
497
+ BluetoothGattDescriptor desc = c .getDescriptor (CONFIG_DESCRIPTOR );
498
+ desc .setValue (BluetoothGattDescriptor .ENABLE_NOTIFICATION_VALUE );
499
+ bluetoothGatt .writeDescriptor (desc );
500
+
501
+ }
502
+ }
503
+
504
+ @ SuppressLint ("MissingPermission" )
505
+ private void unsubscribeToCharacteristic (String serviceUUID , String characteristicUUID ) {
506
+
507
+ if (connected ) {
508
+
509
+ UUID service = UUID .fromString (serviceUUID );
510
+ UUID characteristic = UUID .fromString (characteristicUUID );
511
+
512
+ BluetoothGattCharacteristic c = bluetoothGatt .getService (service ).getCharacteristic (characteristic );
513
+ bluetoothGatt .setCharacteristicNotification (c ,false );
514
+ }
515
+ }
516
+ }
0 commit comments