1 package com.bluekitchen.lescan; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.util.Log; 6 import android.view.Menu; 7 import android.widget.TextView; 8 9 import com.bluekitchen.btstack.BD_ADDR; 10 import com.bluekitchen.btstack.BT_UUID; 11 import com.bluekitchen.btstack.BTstack; 12 import com.bluekitchen.btstack.GATTCharacteristic; 13 import com.bluekitchen.btstack.GATTService; 14 import com.bluekitchen.btstack.Packet; 15 import com.bluekitchen.btstack.PacketHandler; 16 import com.bluekitchen.btstack.Util; 17 import com.bluekitchen.btstack.event.BTstackEventState; 18 import com.bluekitchen.btstack.event.GAPEventAdvertisingReport; 19 import com.bluekitchen.btstack.event.GATTEventCharacteristicQueryResult; 20 import com.bluekitchen.btstack.event.GATTEventCharacteristicValueQueryResult; 21 import com.bluekitchen.btstack.event.GATTEventNotification; 22 import com.bluekitchen.btstack.event.GATTEventQueryComplete; 23 import com.bluekitchen.btstack.event.GATTEventServiceQueryResult; 24 import com.bluekitchen.btstack.event.HCIEventCommandComplete; 25 import com.bluekitchen.btstack.event.HCIEventDisconnectionComplete; 26 import com.bluekitchen.btstack.event.HCIEventLEConnectionComplete; 27 28 public class MainActivity extends Activity implements PacketHandler { 29 30 private static final String BTSTACK_TAG = "BTstack"; 31 32 private enum STATE { 33 w4_btstack_working, w4_scan_result, w4_connected, w4_services_complete, w4_characteristic_complete, w4_characteristic_read 34 , w4_characteristic_write, w4_acc_service_result, w4_acc_enable_characteristic_result, w4_write_acc_enable_result, w4_acc_client_config_characteristic_result, w4_acc_client_config_result, 35 w4_acc_data, w4_connected_acc, w4_disconnect, track_rssi, battery_data 36 }; 37 38 private TextView tv; 39 private BTstack btstack; 40 private STATE state; 41 private int testAddrType; 42 private BD_ADDR deviceAddr; 43 private int connectionHandle; 44 private GATTService testService; 45 private GATTCharacteristic testCharacteristic; 46 private int service_count = 0; 47 private int characteristic_count = 0; 48 private int test_run_count = 0; 49 private String onScreenMessage = ""; 50 51 BD_ADDR sensor_tag_addr = new BD_ADDR("1C:BA:8C:20:C7:F6"); 52 // Accelerometer 53 private byte[] acc_service_uuid = new byte[] {(byte)0xf0, 0, (byte)0xaa, (byte)0x10, 4, (byte)0x51, (byte)0x40, 0, (byte)0xb0, 0, 0, 0, 0, 0, 0, 0}; 54 private byte[] acc_chr_client_config_uuid = new byte[] {(byte)0xf0, 0, (byte)0xaa, (byte)0x11, 4, (byte)0x51, (byte)0x40, 0, (byte)0xb0, 0, 0, 0, 0, 0, 0, 0}; 55 private byte[] acc_chr_enable_uuid = new byte[] {(byte)0xf0, 0, (byte)0xaa, (byte)0x12, 4, (byte)0x51, (byte)0x40, 0, (byte)0xb0, 0, 0, 0, 0, 0, 0, 0}; 56 private byte[] acc_enable = new byte[] {1}; 57 private byte acc_notification = 1; 58 private GATTService accService; 59 private GATTCharacteristic enableCharacteristic; 60 private GATTCharacteristic configCharacteristic; 61 62 // Battery 63 private GATTService batteryService; 64 private GATTCharacteristic batteryLevelCharacteristic; 65 //private byte[] battery_service_uuid = new byte[] {0, 0, (byte)0x18, (byte)0x0F, 0, 0, (byte)0x10, 0, (byte)0x80, 0, 0, (byte)0x80, (byte)0x5f, (byte)0x9b, (byte)0x34, (byte)0xfb}; 66 private byte[] battery_level_chr_uuid = new byte[] {0, 0, (byte)0x2a, (byte)0x1b, 0, 0, (byte)0x10, 0, (byte)0x80, 0, 0, (byte)0x80, (byte)0x5f, (byte)0x9b, (byte)0x34, (byte)0xfb}; 67 GATTEventCharacteristicValueQueryResult battery; 68 private int batteryLevel = 0; 69 private int counter; 70 71 72 @Override 73 protected void onCreate(Bundle savedInstanceState) { 74 super.onCreate(savedInstanceState); 75 setContentView(R.layout.activity_main); 76 77 tv = new TextView(this); 78 setContentView(tv); 79 80 test(); 81 } 82 83 void addMessage(final String message){ 84 onScreenMessage = onScreenMessage + "\n" + message; 85 Log.d(BTSTACK_TAG, message); 86 runOnUiThread(new Runnable(){ 87 public void run(){ 88 tv.setText(onScreenMessage); 89 } 90 }); 91 } 92 93 94 void addTempMessage(final String message){ 95 Log.d(BTSTACK_TAG, message); 96 runOnUiThread(new Runnable(){ 97 public void run(){ 98 tv.setText(onScreenMessage +"\n" + message); 99 } 100 }); 101 } 102 103 void clearMessages(){ 104 onScreenMessage = ""; 105 runOnUiThread(new Runnable(){ 106 public void run(){ 107 tv.setText(onScreenMessage); 108 } 109 }); 110 } 111 112 113 @Override 114 public boolean onCreateOptionsMenu(Menu menu) { 115 // Inflate the menu; this adds items to the action bar if it is present. 116 getMenuInflater().inflate(R.menu.main, menu); 117 return true; 118 } 119 120 121 public void testCharacteristics(Packet packet){ 122 123 switch (state){ 124 case w4_btstack_working: 125 if (packet instanceof BTstackEventState){ 126 BTstackEventState event = (BTstackEventState) packet; 127 if (event.getState() == 2) { 128 addMessage("GAPLEScanStart()"); 129 state = STATE.w4_scan_result; 130 btstack.GAPLEScanStart(); 131 } 132 } 133 break; 134 case w4_scan_result: 135 if (packet instanceof GAPEventAdvertisingReport){ 136 GAPEventAdvertisingReport report = (GAPEventAdvertisingReport) packet; 137 testAddrType = report.getAddressType(); 138 deviceAddr = report.getAddress(); 139 addMessage(String.format("Adv: type %d, addr %s", testAddrType, deviceAddr)); 140 addMessage(String.format("Data: %s", Util.asHexdump(report.getData()))); 141 addMessage("GAPLEScanStop()"); 142 btstack.GAPLEScanStop(); 143 addMessage("GAPLEConnect(...)"); 144 state = STATE.w4_connected; 145 btstack.GAPLEConnect(testAddrType, deviceAddr); 146 } 147 break; 148 case w4_connected: 149 if (packet instanceof HCIEventLEConnectionComplete){ 150 HCIEventLEConnectionComplete event = (HCIEventLEConnectionComplete) packet; 151 connectionHandle = event.getConnectionHandle(); 152 addMessage(String.format("Connection complete, status %d, handle %x", event.getStatus(), connectionHandle)); 153 state = STATE.w4_services_complete; 154 addMessage("GATTDiscoverPrimaryServices(...)"); 155 btstack.GATTDiscoverPrimaryServices(connectionHandle); 156 } 157 break; 158 case w4_services_complete: 159 if (packet instanceof GATTEventServiceQueryResult){ 160 GATTEventServiceQueryResult event = (GATTEventServiceQueryResult) packet; 161 if (testService == null){ 162 addMessage(String.format("First service UUID %s", event.getService().getUUID())); 163 testService = event.getService(); 164 } 165 Log.d(BTSTACK_TAG, "Service: " + event.getService()); 166 service_count++; 167 } 168 if (packet instanceof GATTEventQueryComplete){ 169 addMessage(String.format("Service query complete, total %d services", service_count)); 170 state = STATE.w4_characteristic_complete; 171 btstack.GATTDiscoverCharacteristicsForService(connectionHandle, testService); 172 } 173 break; 174 175 case w4_characteristic_complete: 176 if (packet instanceof GATTEventCharacteristicQueryResult){ 177 GATTEventCharacteristicQueryResult event = (GATTEventCharacteristicQueryResult) packet; 178 if (testCharacteristic == null){ 179 addMessage(String.format("First characteristic UUID %s", event.getCharacteristic().getUUID())); 180 testCharacteristic = event.getCharacteristic(); 181 } 182 Log.d(BTSTACK_TAG, "Characteristic: " + event.getCharacteristic()); 183 characteristic_count++; 184 } 185 if (packet instanceof GATTEventQueryComplete){ 186 addMessage(String.format("Characteristic query complete, total %d characteristics", characteristic_count)); 187 if (characteristic_count > 0){ 188 state = STATE.w4_characteristic_read; 189 btstack.GATTReadValueOfCharacteristic(connectionHandle, testCharacteristic); 190 } else { 191 state = STATE.w4_disconnect; 192 btstack.GAPDisconnect(connectionHandle); 193 } 194 } 195 break; 196 197 case w4_characteristic_read: 198 if (packet instanceof GATTEventCharacteristicValueQueryResult){ 199 addMessage("Read complete"); 200 Log.d(BTSTACK_TAG, packet.toString()); 201 state = STATE.w4_characteristic_write; 202 byte [] data = { 'B', 'T', 's', 't', 'a', 'c', 'k'}; 203 btstack.GATTWriteValueOfCharacteristic(connectionHandle, testCharacteristic, data.length, data); 204 } 205 break; 206 case w4_characteristic_write: 207 if (packet instanceof GATTEventQueryComplete){ 208 addMessage("Write complete, disconnect now."); 209 state = STATE.w4_disconnect; 210 // btstack.GAPDisconnect(testHandle); 211 } 212 break; 213 case w4_disconnect: 214 if (packet instanceof HCIEventDisconnectionComplete){ 215 addMessage("Disconnected."); 216 } 217 break; 218 default: 219 break; 220 } 221 } 222 223 public void testAccelerometer(Packet packet){ 224 switch (state){ 225 case w4_btstack_working: 226 if (packet instanceof BTstackEventState){ 227 BTstackEventState event = (BTstackEventState) packet; 228 if (event.getState() == 2) { 229 addMessage("GAPLEScanStart()"); 230 state = STATE.w4_scan_result; 231 btstack.GAPLEScanStart(); 232 } 233 } 234 break; 235 case w4_scan_result: 236 if (packet instanceof GAPEventAdvertisingReport){ 237 GAPEventAdvertisingReport report = (GAPEventAdvertisingReport) packet; 238 testAddrType = report.getAddressType(); 239 deviceAddr = report.getAddress(); 240 if (deviceAddr.toString().equalsIgnoreCase(sensor_tag_addr.toString())){ 241 addMessage(String.format("Adv: type %d, addr %s", testAddrType, deviceAddr)); 242 addMessage(String.format("Data: %s", Util.asHexdump(report.getData()))); 243 addMessage("GAPLEScanStop()"); 244 btstack.GAPLEScanStop(); 245 addMessage("GAPLEConnect(...)"); 246 state = STATE.w4_connected_acc; 247 btstack.GAPLEConnect(testAddrType, deviceAddr); 248 } 249 } 250 break; 251 252 253 254 case w4_connected_acc: 255 if (packet instanceof HCIEventLEConnectionComplete){ 256 HCIEventLEConnectionComplete event = (HCIEventLEConnectionComplete) packet; 257 connectionHandle = event.getConnectionHandle(); 258 addMessage(String.format("Connection complete, status %d, handle %x", event.getStatus(), connectionHandle)); 259 addMessage("Search for ACC service"); 260 state = STATE.w4_acc_service_result; 261 byte [] uuid = new byte[16]; 262 Util.flipX(this.acc_service_uuid, uuid); 263 btstack.GATTDiscoverPrimaryServicesByUUID128(connectionHandle, new BT_UUID(uuid)); 264 } 265 break; 266 267 case w4_acc_service_result: 268 clearMessages(); 269 addMessage(String.format("w4_acc_service_result state")); 270 if (packet instanceof GATTEventServiceQueryResult){ 271 GATTEventServiceQueryResult event = (GATTEventServiceQueryResult) packet; 272 addMessage(String.format("ACC service found %s", event.getService().getUUID())); 273 accService = event.getService(); 274 break; 275 } 276 if (packet instanceof GATTEventQueryComplete){ 277 if (accService == null) { 278 addMessage("No acc service found"); 279 break; 280 } 281 addMessage("ACC Service found, searching for acc enable characteristic"); 282 state = STATE.w4_acc_enable_characteristic_result; 283 byte [] uuid = new byte[16]; 284 Util.flipX(this.acc_chr_enable_uuid, uuid); 285 btstack.GATTDiscoverCharacteristicsForServiceByUUID128(connectionHandle, accService, new BT_UUID(uuid)); 286 } 287 break; 288 289 case w4_acc_enable_characteristic_result: 290 if (packet instanceof GATTEventCharacteristicQueryResult){ 291 GATTEventCharacteristicQueryResult event = (GATTEventCharacteristicQueryResult) packet; 292 enableCharacteristic = event.getCharacteristic(); 293 addMessage("Enable ACC Characteristic found "); 294 } 295 if (packet instanceof GATTEventQueryComplete){ 296 if (enableCharacteristic == null) { 297 addMessage("No acc enable chr found"); 298 break; 299 } 300 addMessage("Write enable acc characteristic"); 301 state = STATE.w4_write_acc_enable_result; 302 btstack.GATTWriteValueOfCharacteristic(connectionHandle, enableCharacteristic, 1, this.acc_enable); 303 } 304 break; 305 case w4_write_acc_enable_result: 306 if (packet instanceof GATTEventQueryComplete){ 307 addMessage("Acc enabled,searching for acc client config characteristic"); 308 byte [] uuid = new byte[16]; 309 Util.flipX(this.acc_chr_client_config_uuid, uuid); 310 btstack.GATTDiscoverCharacteristicsForServiceByUUID128(connectionHandle, accService, new BT_UUID(uuid)); 311 state = STATE.w4_acc_client_config_characteristic_result; 312 } 313 break; 314 315 case w4_acc_client_config_characteristic_result: 316 if (packet instanceof GATTEventCharacteristicQueryResult){ 317 GATTEventCharacteristicQueryResult event = (GATTEventCharacteristicQueryResult) packet; 318 configCharacteristic = event.getCharacteristic(); 319 addMessage("ACC Client Config Characteristic found"); 320 } 321 if (packet instanceof GATTEventQueryComplete){ 322 if (configCharacteristic == null) { 323 addMessage("No acc config chr found"); 324 break; 325 } 326 addMessage("Write ACC Client Config Characteristic"); 327 state = STATE.w4_acc_data; 328 btstack.GATTWriteClientCharacteristicConfiguration(connectionHandle, configCharacteristic, this.acc_notification); 329 } 330 break; 331 332 case w4_acc_data: 333 if (packet instanceof GATTEventQueryComplete){ 334 addMessage("Acc configured for notification"); 335 break; 336 } 337 338 if (packet instanceof GATTEventNotification){ 339 addTempMessage("Acc Value"); 340 Log.d(BTSTACK_TAG, packet.toString()); 341 //state = STATE.w4_btstack_working; 342 //btstack.GAPDisconnect(connectionHandle); 343 } 344 break; 345 346 default: 347 break; 348 } 349 } 350 351 public void testConnectDisconnect(Packet packet){ 352 if (packet instanceof HCIEventDisconnectionComplete){ 353 if (state != STATE.w4_disconnect) { 354 state = STATE.w4_scan_result; 355 btstack.GAPLEScanStart(); 356 clearMessages(); 357 HCIEventDisconnectionComplete event = (HCIEventDisconnectionComplete) packet; 358 addMessage(String.format("Unexpected disconnect %x. Start scan.", event.getConnectionHandle())); 359 return; 360 } 361 } 362 363 switch (state){ 364 case w4_btstack_working: 365 if (packet instanceof BTstackEventState){ 366 BTstackEventState event = (BTstackEventState) packet; 367 if (event.getState() == 2) { 368 // addMessage("GAPLEScanStart()"); 369 // state = STATE.w4_scan_result; 370 // btstack.GAPLEScanStart(); 371 // runOnUiThread(new Runnable(){ 372 // public void run(){ 373 addMessage("BTstack dissconnect."); 374 btstack.disconnect(); 375 376 // runOnUiThread(new Runnable(){ 377 // public void run(){ 378 try { 379 Thread.sleep(5000); 380 } catch (InterruptedException e) { 381 e.printStackTrace(); 382 } 383 btstack.connect(); 384 addMessage("Power on BTstack."); 385 state = STATE.w4_btstack_working; 386 test_run_count = 0; 387 btstack.BTstackSetPowerMode(1); 388 // } 389 // }); 390 } 391 } 392 break; 393 case w4_scan_result: 394 if (packet instanceof GAPEventAdvertisingReport){ 395 BD_ADDR sensor_tag_addr = new BD_ADDR("1C:BA:8C:20:C7:F6"); 396 //BD_ADDR pts_dongle = new BD_ADDR("00:1B:DC:07:32:EF"); 397 398 GAPEventAdvertisingReport report = (GAPEventAdvertisingReport) packet; 399 BD_ADDR reportAddr = report.getAddress(); 400 if (reportAddr.toString().equalsIgnoreCase(sensor_tag_addr.toString())){ 401 testAddrType = report.getAddressType(); 402 deviceAddr = report.getAddress(); 403 addMessage(String.format("Adv: type %d, addr %s", testAddrType, deviceAddr)); 404 addMessage(String.format("Data: %s", Util.asHexdump(report.getData()))); 405 406 addMessage("GAPLEScanStop()"); 407 btstack.GAPLEScanStop(); 408 addMessage("GAPLEConnect(...)"); 409 state = STATE.w4_connected; 410 411 btstack.GAPLEConnect(testAddrType, deviceAddr); 412 } 413 } 414 break; 415 case w4_connected: 416 if (packet instanceof HCIEventLEConnectionComplete){ 417 HCIEventLEConnectionComplete event = (HCIEventLEConnectionComplete) packet; 418 419 connectionHandle = event.getConnectionHandle(); 420 addMessage(String.format("Connection complete, status %d, handle %x", event.getStatus(), connectionHandle)); 421 state = STATE.w4_services_complete; 422 addMessage("GATTDiscoverPrimaryServices(...)"); 423 btstack.GATTDiscoverPrimaryServices(connectionHandle); 424 425 } 426 break; 427 case w4_services_complete: 428 if (packet instanceof GATTEventServiceQueryResult){ 429 GATTEventServiceQueryResult event = (GATTEventServiceQueryResult) packet; 430 if (testService == null){ 431 addMessage(String.format("First service UUID %s", event.getService().getUUID())); 432 testService = event.getService(); 433 } 434 Log.d(BTSTACK_TAG, "Service: " + event.getService()); 435 service_count++; 436 } 437 if (packet instanceof GATTEventQueryComplete){ 438 addMessage(String.format("Service query complete, total %d services", service_count)); 439 state = STATE.w4_disconnect; 440 test_run_count++; 441 btstack.GAPDisconnect(connectionHandle); 442 } 443 break; 444 case w4_disconnect: 445 Log.d(BTSTACK_TAG, packet.toString()); 446 if (packet instanceof HCIEventDisconnectionComplete){ 447 clearMessages(); 448 addMessage("BTstack dissconnect."); 449 btstack.disconnect(); 450 try { 451 Thread.sleep(15000); 452 } catch (InterruptedException e) { 453 e.printStackTrace(); 454 } 455 456 btstack.connect(); 457 addMessage("Power on BTstack."); 458 state = STATE.w4_btstack_working; 459 test_run_count = 0; 460 btstack.BTstackSetPowerMode(1); 461 462 463 /*if (test_run_count%10 == 0){ 464 addMessage("Power off BTstack."); 465 state = STATE.w4_btstack_working; 466 btstack.BTstackSetPowerMode(0); 467 try { 468 Thread.sleep(15000); 469 } catch (InterruptedException e) { 470 e.printStackTrace(); 471 } 472 addMessage("Power on BTstack."); 473 btstack.BTstackSetPowerMode(1); 474 } else { 475 addMessage("GAPLEScanStart()"); 476 state = STATE.w4_scan_result; 477 btstack.GAPLEScanStart(); 478 }*/ 479 } 480 break; 481 default: 482 break; 483 } 484 } 485 486 public void trackRSSI(Packet packet){ 487 switch (state){ 488 case w4_btstack_working: 489 if (packet instanceof BTstackEventState){ 490 BTstackEventState event = (BTstackEventState) packet; 491 if (event.getState() == 2) { 492 addMessage("GAPLEScanStart()"); 493 state = STATE.w4_scan_result; 494 btstack.GAPLEScanStart(); 495 } 496 } 497 break; 498 case w4_scan_result: 499 if (packet instanceof GAPEventAdvertisingReport){ 500 clearMessages(); 501 GAPEventAdvertisingReport report = (GAPEventAdvertisingReport) packet; 502 testAddrType = report.getAddressType(); 503 deviceAddr = report.getAddress(); 504 addMessage(String.format("Adv: type %d, addr %s", testAddrType, deviceAddr)); 505 addMessage(String.format("Data: %s", Util.asHexdump(report.getData()))); 506 addMessage("GAPLEScanStop()"); 507 btstack.GAPLEScanStop(); 508 addMessage("GAPLEConnect(...)"); 509 state = STATE.w4_connected; 510 btstack.GAPLEConnect(testAddrType, deviceAddr); 511 } 512 break; 513 case w4_connected: 514 if (packet instanceof HCIEventLEConnectionComplete){ 515 HCIEventLEConnectionComplete event = (HCIEventLEConnectionComplete) packet; 516 if (event.getStatus() != 0) { 517 addMessage(String.format("Connection didn't succeed, status %d, restart scanning.", event.getStatus())); 518 state = STATE.w4_scan_result; 519 btstack.GAPLEScanStart(); 520 break; 521 } 522 523 state = STATE.track_rssi; 524 connectionHandle = event.getConnectionHandle(); 525 addMessage(String.format("Connection complete, status %d, handle %x. Start RSSI query.", event.getStatus(), connectionHandle)); 526 counter = 0; 527 new Thread(new Runnable(){ 528 @Override 529 public void run() { 530 try { 531 while(state == STATE.track_rssi){ 532 Thread.sleep(1000); 533 btstack.HCIReadRssi(connectionHandle); 534 } 535 } catch (InterruptedException e) {} 536 } 537 }).start(); 538 } 539 break; 540 case track_rssi: 541 if (packet instanceof HCIEventDisconnectionComplete){ 542 clearMessages(); 543 addMessage(String.format("Received dissconnect. Start scannning.")); 544 state = STATE.w4_scan_result; 545 btstack.GAPLEScanStart(); 546 break; 547 } 548 549 if (!(packet instanceof HCIEventCommandComplete)) break; 550 HCIEventCommandComplete event = (HCIEventCommandComplete) packet; 551 int opcode = event.getCommandOpcode(); 552 if (opcode != 0X1405) break; 553 counter = counter + 1; 554 byte data[] = event.getReturnParameters(); 555 addTempMessage(String.format("counter %d, status %d, RSSI: %ddBm", counter, Util.readByte(data, 0), data[3])); 556 break; 557 558 default: 559 break; 560 } 561 } 562 563 public void queryBatteryLevel(Packet packet){ 564 // Restart scanning on disconnect. 565 if (packet instanceof HCIEventDisconnectionComplete){ 566 clearMessages(); 567 addMessage(String.format("Received dissconnect. Start scannning.")); 568 state = STATE.w4_scan_result; 569 btstack.GAPLEScanStart(); 570 return; 571 } 572 573 switch (state){ 574 case w4_btstack_working: 575 if (packet instanceof BTstackEventState){ 576 BTstackEventState event = (BTstackEventState) packet; 577 if (event.getState() == 2) { 578 addMessage("BTstack working, start scanning."); 579 state = STATE.w4_scan_result; 580 btstack.GAPLEScanStart(); 581 } 582 } 583 break; 584 case w4_scan_result: 585 if (packet instanceof GAPEventAdvertisingReport){ 586 // Advertisement received. Connect to the found BT address. 587 clearMessages(); 588 GAPEventAdvertisingReport report = (GAPEventAdvertisingReport) packet; 589 testAddrType = report.getAddressType(); 590 deviceAddr = report.getAddress(); 591 addMessage(String.format("Adv: type %d, addr %s\ndata: %s \n Stop scan, initiate connect.", testAddrType, deviceAddr, Util.asHexdump(report.getData()))); 592 btstack.GAPLEScanStop(); 593 state = STATE.w4_connected; 594 btstack.GAPLEConnect(testAddrType, deviceAddr); 595 } 596 break; 597 case w4_connected: 598 if (packet instanceof HCIEventLEConnectionComplete){ 599 HCIEventLEConnectionComplete event = (HCIEventLEConnectionComplete) packet; 600 if (event.getStatus() != 0) { 601 addMessage(String.format("Connection didn't succeed, status %d, restart scanning.", event.getStatus())); 602 state = STATE.w4_scan_result; 603 btstack.GAPLEScanStart(); 604 break; 605 } 606 607 // Query battery service. 608 state = STATE.w4_services_complete; 609 connectionHandle = event.getConnectionHandle(); 610 addMessage(String.format("Connection complete, status %d, handle %x.\nQuery battery service.", event.getStatus(), connectionHandle)); 611 612 //btstack.GATTDiscoverPrimaryServicesByUUID128(connectionHandle, uuid128(this.battery_service_uuid)); 613 btstack.GATTDiscoverPrimaryServicesByUUID16(connectionHandle, 0x180f); 614 } 615 break; 616 617 case w4_services_complete: 618 if (packet instanceof GATTEventServiceQueryResult){ 619 // Store battery service. Wait for GATTEventQueryComplete event to send next GATT command. 620 GATTEventServiceQueryResult event = (GATTEventServiceQueryResult) packet; 621 addMessage(String.format("Battery service found %s", event.getService().getUUID())); 622 batteryService = event.getService(); 623 break; 624 } 625 if (packet instanceof GATTEventQueryComplete){ 626 // Check if battery service is found. 627 if (batteryService == null) { 628 addMessage("No battery service found, restart scanning."); 629 state = STATE.w4_scan_result; 630 btstack.GAPLEScanStart(); 631 break; 632 } 633 addMessage("Battery service is found. Query battery level."); 634 state = STATE.w4_characteristic_complete; 635 btstack.GATTDiscoverCharacteristicsForServiceByUUID128(connectionHandle, batteryService, uuid128(this.battery_level_chr_uuid)); 636 } 637 break; 638 case w4_characteristic_complete: 639 if (packet instanceof GATTEventCharacteristicQueryResult){ 640 // Store battery level characteristic. Wait for GATTEventQueryComplete event to send next GATT command. 641 GATTEventCharacteristicQueryResult event = (GATTEventCharacteristicQueryResult) packet; 642 batteryLevelCharacteristic = event.getCharacteristic(); 643 addMessage("Battery level characteristic found."); 644 break; 645 } 646 647 if (!(packet instanceof GATTEventQueryComplete)) break; 648 if (batteryLevelCharacteristic == null) { 649 addMessage("No battery level characteristic found"); 650 break; 651 } 652 clearMessages(); 653 addMessage("Polling battery."); 654 counter = 0; 655 state = STATE.battery_data; 656 new Thread(new Runnable(){ 657 @Override 658 public void run() { 659 try { 660 while(state == STATE.battery_data){ 661 Thread.sleep(5000); 662 btstack.GATTReadValueOfCharacteristic(connectionHandle, batteryLevelCharacteristic); 663 } 664 } catch (InterruptedException e) {} 665 } 666 }).start(); 667 break; 668 669 case battery_data: 670 clearMessages(); 671 if (packet instanceof GATTEventCharacteristicValueQueryResult){ 672 GATTEventCharacteristicValueQueryResult battery = (GATTEventCharacteristicValueQueryResult) packet; 673 674 if (battery.getValueLength() < 1) break; 675 this.batteryLevel = battery.getValue()[0]; 676 addTempMessage(String.format("Counter %d, battery level: %d", counter, batteryLevel) + "%"); 677 counter = counter + 1; 678 break; 679 680 } 681 if (packet instanceof GATTEventQueryComplete){ 682 GATTEventQueryComplete event = (GATTEventQueryComplete) packet; 683 addMessage(String.format("Counter %d, battery level: %d", counter, batteryLevel) + "%"); 684 if (event.getStatus() != 0){ 685 addMessage("Battery data could not be read - status 0x%02x. Restart scanning." + String.valueOf(event.getStatus())); 686 state = STATE.w4_scan_result; 687 btstack.GAPLEScanStart(); 688 break; 689 } 690 } 691 692 break; 693 default: 694 break; 695 } 696 } 697 698 private BT_UUID uuid128(byte[] att_uuid) { 699 byte [] uuid = new byte[16]; 700 Util.flipX(att_uuid, uuid); 701 return new BT_UUID(uuid); 702 } 703 704 public void handlePacket(Packet packet){ 705 // queryBatteryLevel(packet); 706 // trackRSSI(packet); 707 // testCharacteristics(packet); 708 // testAccelerometer(packet); 709 testConnectDisconnect(packet); 710 } 711 712 void test(){ 713 counter = 0; 714 addMessage("LE Test Application"); 715 716 btstack = new BTstack(); 717 btstack.registerPacketHandler(this); 718 719 boolean ok = btstack.connect(); 720 if (!ok) { 721 addMessage("Failed to connect to BTstack Server"); 722 return; 723 } 724 725 addMessage("BTstackSetPowerMode(1)"); 726 727 state = STATE.w4_btstack_working; 728 btstack.BTstackSetPowerMode(1); 729 } 730 } 731