xref: /btstack/platform/daemon/binding/java/example/com/bluekitchen/LEStreamerClient.java (revision 1cd21c057137995a21f6fd7708e229fa9b7f8094)
131ee742eSMatthias Ringwald package com.bluekitchen;
231ee742eSMatthias Ringwald 
331ee742eSMatthias Ringwald import com.bluekitchen.btstack.BD_ADDR;
431ee742eSMatthias Ringwald import com.bluekitchen.btstack.BT_UUID;
531ee742eSMatthias Ringwald import com.bluekitchen.btstack.BTstack;
631ee742eSMatthias Ringwald import com.bluekitchen.btstack.GATTCharacteristic;
731ee742eSMatthias Ringwald import com.bluekitchen.btstack.GATTService;
831ee742eSMatthias Ringwald import com.bluekitchen.btstack.Packet;
931ee742eSMatthias Ringwald import com.bluekitchen.btstack.PacketHandler;
1031ee742eSMatthias Ringwald import com.bluekitchen.btstack.Util;
1131ee742eSMatthias Ringwald import com.bluekitchen.btstack.event.BTstackEventState;
1231ee742eSMatthias Ringwald import com.bluekitchen.btstack.event.GAPEventAdvertisingReport;
1331ee742eSMatthias Ringwald import com.bluekitchen.btstack.event.GATTEventCharacteristicQueryResult;
1431ee742eSMatthias Ringwald import com.bluekitchen.btstack.event.GATTEventCharacteristicValueQueryResult;
1531ee742eSMatthias Ringwald import com.bluekitchen.btstack.event.GATTEventNotification;
1631ee742eSMatthias Ringwald import com.bluekitchen.btstack.event.GATTEventQueryComplete;
1731ee742eSMatthias Ringwald import com.bluekitchen.btstack.event.GATTEventServiceQueryResult;
1831ee742eSMatthias Ringwald import com.bluekitchen.btstack.event.HCIEventDisconnectionComplete;
1931ee742eSMatthias Ringwald import com.bluekitchen.btstack.event.HCIEventLEConnectionComplete;
2031ee742eSMatthias Ringwald import com.bluekitchen.btstack.event.SMEventJustWorksRequest;
2131ee742eSMatthias Ringwald 
2231ee742eSMatthias Ringwald import java.nio.charset.StandardCharsets;
2331ee742eSMatthias Ringwald 
2431ee742eSMatthias Ringwald public class LEStreamerClient implements PacketHandler {
2531ee742eSMatthias Ringwald 
2631ee742eSMatthias Ringwald 	private enum STATE {
2731ee742eSMatthias Ringwald 		w4_btstack_working, w4_scan_result, w4_connected, w4_services_complete, w4_characteristic_complete,
2831ee742eSMatthias Ringwald 		w4_write_client_config_characteristic_complete, active
2931ee742eSMatthias Ringwald 	};
3031ee742eSMatthias Ringwald 
3131ee742eSMatthias Ringwald 	private BTstack btstack;
3231ee742eSMatthias Ringwald 	private STATE state;
3331ee742eSMatthias Ringwald 	private int testAddrType;
3431ee742eSMatthias Ringwald 	private BD_ADDR testAddr = new BD_ADDR("00:1A:7D:DA:71:01");
3531ee742eSMatthias Ringwald 	private int connectionHandle;
3631ee742eSMatthias Ringwald 
3731ee742eSMatthias Ringwald 	private BT_UUID testServiceUUID        = new BT_UUID("0000FF10-0000-1000-8000-00805F9B34FB");
3831ee742eSMatthias Ringwald 	private BT_UUID testCharacteristicUUID = new BT_UUID("0000FF11-0000-1000-8000-00805F9B34FB");
3931ee742eSMatthias Ringwald 	private byte    testNotification = 1;
4031ee742eSMatthias Ringwald 
4131ee742eSMatthias Ringwald 	private GATTService testService;
4231ee742eSMatthias Ringwald 	private GATTCharacteristic testCharacteristic;
4331ee742eSMatthias Ringwald 
handlePacket(Packet packet)4431ee742eSMatthias Ringwald 	public void handlePacket(Packet packet){
4531ee742eSMatthias Ringwald 
4631ee742eSMatthias Ringwald 		System.out.println("Event " + packet);
4731ee742eSMatthias Ringwald 
4831ee742eSMatthias Ringwald 		if (packet instanceof SMEventJustWorksRequest){
4931ee742eSMatthias Ringwald 			SMEventJustWorksRequest event = (SMEventJustWorksRequest) packet;
5031ee742eSMatthias Ringwald 			System.out.println("Received Just Works pairing request from " + event.getAddress() + " -> auto-accept");
5131ee742eSMatthias Ringwald 			btstack.SMJustWorksConfirm(event.getHandle());
5231ee742eSMatthias Ringwald 			return;
5331ee742eSMatthias Ringwald 		}
5431ee742eSMatthias Ringwald 
5531ee742eSMatthias Ringwald 		if (packet instanceof HCIEventDisconnectionComplete){
5631ee742eSMatthias Ringwald 			System.out.println("Received dissconnect, restart scannning.");
5731ee742eSMatthias Ringwald 			state = STATE.w4_scan_result;
5831ee742eSMatthias Ringwald 			btstack.GAPLEScanStart();
5931ee742eSMatthias Ringwald 			return;
6031ee742eSMatthias Ringwald 		}
6131ee742eSMatthias Ringwald 
6231ee742eSMatthias Ringwald 		switch (state){
6331ee742eSMatthias Ringwald 			case w4_btstack_working:
6431ee742eSMatthias Ringwald 				if (packet instanceof BTstackEventState){
6531ee742eSMatthias Ringwald 					BTstackEventState event = (BTstackEventState) packet;
6631ee742eSMatthias Ringwald 					if (event.getState() == 2)	{
6731ee742eSMatthias Ringwald 						System.out.println("BTstack working, start scanning.");
6831ee742eSMatthias Ringwald 						state = STATE.w4_scan_result;
6931ee742eSMatthias Ringwald 						btstack.GAPLEScanStart();
7031ee742eSMatthias Ringwald 					}
7131ee742eSMatthias Ringwald 				}
7231ee742eSMatthias Ringwald 				break;
7331ee742eSMatthias Ringwald 			case w4_scan_result:
7431ee742eSMatthias Ringwald 				if (packet instanceof GAPEventAdvertisingReport){
7531ee742eSMatthias Ringwald 					// Advertisement received. Connect to the found BT address.
7631ee742eSMatthias Ringwald 					GAPEventAdvertisingReport report = (GAPEventAdvertisingReport) packet;
7731ee742eSMatthias Ringwald 					System.out.println(String.format("Adv: type %d, addr %s\ndata: %s\n", report.getAddressType(), report.getAddress(), Util.asHexdump(report.getData())));
7831ee742eSMatthias Ringwald 					// hack to find 'LE Streamer'
7931ee742eSMatthias Ringwald 					if (new String(report.getData(), StandardCharsets.UTF_8).indexOf("LE Streamer") > 0){
8031ee742eSMatthias Ringwald 						testAddrType = report.getAddressType();
8131ee742eSMatthias Ringwald 						testAddr = report.getAddress();
8231ee742eSMatthias Ringwald 						System.out.println(String.format("LE Streamer found, connect to %s\n", testAddr));
8331ee742eSMatthias Ringwald 						btstack.GAPLEScanStop();
8431ee742eSMatthias Ringwald 						state = STATE.w4_connected;
8531ee742eSMatthias Ringwald 						btstack.GAPLEConnect(testAddrType, testAddr);
8631ee742eSMatthias Ringwald 					}
8731ee742eSMatthias Ringwald 				}
8831ee742eSMatthias Ringwald 				break;
8931ee742eSMatthias Ringwald 			case w4_connected:
9031ee742eSMatthias Ringwald 				if (packet instanceof HCIEventLEConnectionComplete){
9131ee742eSMatthias Ringwald 					HCIEventLEConnectionComplete event = (HCIEventLEConnectionComplete) packet;
9231ee742eSMatthias Ringwald 					if (event.getStatus() != 0) {
9331ee742eSMatthias Ringwald 						System.out.println(testAddr + String.format(" - connection failed, status %d.\nRestart scanning.", event.getStatus()));
9431ee742eSMatthias Ringwald 						state = STATE.w4_scan_result;
9531ee742eSMatthias Ringwald 						btstack.GAPLEScanStart();
9631ee742eSMatthias Ringwald 						break;
9731ee742eSMatthias Ringwald 					}
9831ee742eSMatthias Ringwald 
9931ee742eSMatthias Ringwald 					// Query test service.
10031ee742eSMatthias Ringwald 					state = STATE.w4_services_complete;
10131ee742eSMatthias Ringwald 					connectionHandle = event.getConnectionHandle();
10231ee742eSMatthias Ringwald 					System.out.println(testAddr + String.format(" - connected %x.\nQuery streamer service.", connectionHandle));
10331ee742eSMatthias Ringwald 					btstack.GATTDiscoverPrimaryServicesByUUID128(connectionHandle, testServiceUUID);
10431ee742eSMatthias Ringwald 				}
10531ee742eSMatthias Ringwald 				break;
10631ee742eSMatthias Ringwald 			case w4_services_complete:
10731ee742eSMatthias Ringwald 				if (packet instanceof GATTEventServiceQueryResult){
10831ee742eSMatthias Ringwald 					// Store streamer service. Wait for GATTEventQueryComplete event to send next GATT command.
10931ee742eSMatthias Ringwald 					GATTEventServiceQueryResult event = (GATTEventServiceQueryResult) packet;
11031ee742eSMatthias Ringwald 					System.out.println(testAddr + String.format(" - streamer service %s", event.getService().getUUID()));
11131ee742eSMatthias Ringwald 					testService = event.getService();
11231ee742eSMatthias Ringwald 					break;
11331ee742eSMatthias Ringwald 				}
11431ee742eSMatthias Ringwald 				if (packet instanceof GATTEventQueryComplete){
11531ee742eSMatthias Ringwald 					// Check if streamer service is found.
11631ee742eSMatthias Ringwald 					if (testService == null) {
11731ee742eSMatthias Ringwald 						System.out.println(testAddr + " - no streamer service. \nRestart scanning.");
11831ee742eSMatthias Ringwald 						state = STATE.w4_scan_result;
11931ee742eSMatthias Ringwald 						btstack.GAPLEScanStart();
12031ee742eSMatthias Ringwald 						break;
12131ee742eSMatthias Ringwald 					}
12231ee742eSMatthias Ringwald 					System.out.println(testAddr + " - query streamer characteristic.");
12331ee742eSMatthias Ringwald 					state = STATE.w4_characteristic_complete;
12431ee742eSMatthias Ringwald 					btstack.GATTDiscoverCharacteristicsForServiceByUUID128(connectionHandle, testService, testCharacteristicUUID);
12531ee742eSMatthias Ringwald 				}
12631ee742eSMatthias Ringwald 				break;
12731ee742eSMatthias Ringwald 			case w4_characteristic_complete:
12831ee742eSMatthias Ringwald 				if (packet instanceof GATTEventCharacteristicQueryResult){
12931ee742eSMatthias Ringwald 					// Store streamer characteristic. Wait for GATTEventQueryComplete event to send next GATT command.
13031ee742eSMatthias Ringwald 					GATTEventCharacteristicQueryResult event = (GATTEventCharacteristicQueryResult) packet;
13131ee742eSMatthias Ringwald 					testCharacteristic = event.getCharacteristic();
13231ee742eSMatthias Ringwald 					System.out.println(testAddr + " - streamer characteristic found.");
13331ee742eSMatthias Ringwald 					break;
13431ee742eSMatthias Ringwald 				}
13531ee742eSMatthias Ringwald 
13631ee742eSMatthias Ringwald 				if (!(packet instanceof GATTEventQueryComplete)) break;
13731ee742eSMatthias Ringwald 
13831ee742eSMatthias Ringwald 				if (testCharacteristic == null) {
13931ee742eSMatthias Ringwald 					System.out.println("No streamer characteristic found");
14031ee742eSMatthias Ringwald 					break;
14131ee742eSMatthias Ringwald 				}
14231ee742eSMatthias Ringwald 				System.out.println(testAddr + " - enable notifications.");
14331ee742eSMatthias Ringwald 				state = STATE.w4_write_client_config_characteristic_complete;
14431ee742eSMatthias Ringwald 				btstack.GATTWriteClientCharacteristicConfiguration(connectionHandle, testCharacteristic, this.testNotification);
14531ee742eSMatthias Ringwald 				break;
14631ee742eSMatthias Ringwald 
14731ee742eSMatthias Ringwald 			case w4_write_client_config_characteristic_complete:
14831ee742eSMatthias Ringwald 				if (packet instanceof GATTEventQueryComplete){
14931ee742eSMatthias Ringwald 					System.out.println(testAddr + " - notification enabled.");
15031ee742eSMatthias Ringwald 					state = STATE.active;
15131ee742eSMatthias Ringwald 				}
15231ee742eSMatthias Ringwald 				break;
15331ee742eSMatthias Ringwald 
15431ee742eSMatthias Ringwald 			case active:
15531ee742eSMatthias Ringwald 				if (packet instanceof GATTEventNotification){
156*1cd21c05SMatthias Ringwald 					GATTEventNotification event = (GATTEventNotification) packet;
15731ee742eSMatthias Ringwald 					System.out.println("Data:");
158*1cd21c05SMatthias Ringwald 					Util.hexdump(event.getValue());
15931ee742eSMatthias Ringwald 				}
16031ee742eSMatthias Ringwald 				break;
16131ee742eSMatthias Ringwald 
16231ee742eSMatthias Ringwald 			default:
16331ee742eSMatthias Ringwald 				break;
16431ee742eSMatthias Ringwald 		}
16531ee742eSMatthias Ringwald 	}
16631ee742eSMatthias Ringwald 
test()16731ee742eSMatthias Ringwald 	void test(){
16831ee742eSMatthias Ringwald 
16931ee742eSMatthias Ringwald 		System.out.println("LE Streamer Client");
17031ee742eSMatthias Ringwald 
17131ee742eSMatthias Ringwald 		// connect to BTstack Daemon via default port on localhost
17231ee742eSMatthias Ringwald 		btstack = new BTstack();
17331ee742eSMatthias Ringwald 		btstack.setTcpPort(BTstack.DEFAULT_TCP_PORT);
17431ee742eSMatthias Ringwald 		btstack.registerPacketHandler(this);
17531ee742eSMatthias Ringwald 		boolean ok = btstack.connect();
17631ee742eSMatthias Ringwald 		if (!ok) {
17731ee742eSMatthias Ringwald 			System.out.println("Failed to connect to BTstack Server");
17831ee742eSMatthias Ringwald 			return;
17931ee742eSMatthias Ringwald 		}
18031ee742eSMatthias Ringwald 
18131ee742eSMatthias Ringwald 		System.out.println("BTstackSetPowerMode(1)");
18231ee742eSMatthias Ringwald 
18331ee742eSMatthias Ringwald 		// btstack.SMSetAuthenticationRequirements(8 | 4);
18431ee742eSMatthias Ringwald 		// btstack.SMSetIoCapabilities(4);
18531ee742eSMatthias Ringwald 
18631ee742eSMatthias Ringwald 		state = STATE.w4_btstack_working;
18731ee742eSMatthias Ringwald 		btstack.BTstackSetPowerMode(1);
18831ee742eSMatthias Ringwald 	}
18931ee742eSMatthias Ringwald 
main(String args[])19031ee742eSMatthias Ringwald 	public static void main(String args[]){
19131ee742eSMatthias Ringwald 		new LEStreamerClient().test();
19231ee742eSMatthias Ringwald 	}
19331ee742eSMatthias Ringwald }
194