xref: /btstack/port/mtk/LEScan/src/com/bluekitchen/lescan/MainActivity.java (revision 0561b2d8d5dba972c7daa57d5e677f7a1327edfd)
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