xref: /btstack/platform/daemon/binding/java/example/com/bluekitchen/LEStreamerClient.java (revision 1b464e99afd70ddaf6b75be1ba7cc563a5f5dfd8)
1 package com.bluekitchen;
2 
3 import com.bluekitchen.btstack.BD_ADDR;
4 import com.bluekitchen.btstack.BT_UUID;
5 import com.bluekitchen.btstack.BTstack;
6 import com.bluekitchen.btstack.GATTCharacteristic;
7 import com.bluekitchen.btstack.GATTService;
8 import com.bluekitchen.btstack.Packet;
9 import com.bluekitchen.btstack.PacketHandler;
10 import com.bluekitchen.btstack.Util;
11 import com.bluekitchen.btstack.event.BTstackEventState;
12 import com.bluekitchen.btstack.event.GAPEventAdvertisingReport;
13 import com.bluekitchen.btstack.event.GATTEventCharacteristicQueryResult;
14 import com.bluekitchen.btstack.event.GATTEventCharacteristicValueQueryResult;
15 import com.bluekitchen.btstack.event.GATTEventNotification;
16 import com.bluekitchen.btstack.event.GATTEventQueryComplete;
17 import com.bluekitchen.btstack.event.GATTEventServiceQueryResult;
18 import com.bluekitchen.btstack.event.HCIEventDisconnectionComplete;
19 import com.bluekitchen.btstack.event.HCIEventLEConnectionComplete;
20 import com.bluekitchen.btstack.event.SMEventJustWorksRequest;
21 
22 import java.nio.charset.StandardCharsets;
23 
24 public class LEStreamerClient implements PacketHandler {
25 
26 	private enum STATE {
27 		w4_btstack_working, w4_scan_result, w4_connected, w4_services_complete, w4_characteristic_complete,
28 		w4_write_client_config_characteristic_complete, active
29 	};
30 
31 	private BTstack btstack;
32 	private STATE state;
33 	private int testAddrType;
34 	private BD_ADDR testAddr = new BD_ADDR("00:1A:7D:DA:71:01");
35 	private int connectionHandle;
36 
37 	private BT_UUID testServiceUUID        = new BT_UUID("0000FF10-0000-1000-8000-00805F9B34FB");
38 	private BT_UUID testCharacteristicUUID = new BT_UUID("0000FF11-0000-1000-8000-00805F9B34FB");
39 	private byte    testNotification = 1;
40 
41 	private GATTService testService;
42 	private GATTCharacteristic testCharacteristic;
43 
44 	public void handlePacket(Packet packet){
45 
46 		System.out.println("Event " + packet);
47 
48 		if (packet instanceof SMEventJustWorksRequest){
49 			SMEventJustWorksRequest event = (SMEventJustWorksRequest) packet;
50 			System.out.println("Received Just Works pairing request from " + event.getAddress() + " -> auto-accept");
51 			btstack.SMJustWorksConfirm(event.getHandle());
52 			return;
53 		}
54 
55 		if (packet instanceof HCIEventDisconnectionComplete){
56 			System.out.println("Received dissconnect, restart scannning.");
57 			state = STATE.w4_scan_result;
58 			btstack.GAPLEScanStart();
59 			return;
60 		}
61 
62 		switch (state){
63 			case w4_btstack_working:
64 				if (packet instanceof BTstackEventState){
65 					BTstackEventState event = (BTstackEventState) packet;
66 					if (event.getState() == 2)	{
67 						System.out.println("BTstack working, start scanning.");
68 						state = STATE.w4_scan_result;
69 						btstack.GAPLEScanStart();
70 					}
71 				}
72 				break;
73 			case w4_scan_result:
74 				if (packet instanceof GAPEventAdvertisingReport){
75 					// Advertisement received. Connect to the found BT address.
76 					GAPEventAdvertisingReport report = (GAPEventAdvertisingReport) packet;
77 					System.out.println(String.format("Adv: type %d, addr %s\ndata: %s\n", report.getAddressType(), report.getAddress(), Util.asHexdump(report.getData())));
78 					// hack to find 'LE Streamer'
79 					if (new String(report.getData(), StandardCharsets.UTF_8).indexOf("LE Streamer") > 0){
80 						testAddrType = report.getAddressType();
81 						testAddr = report.getAddress();
82 						System.out.println(String.format("LE Streamer found, connect to %s\n", testAddr));
83 						btstack.GAPLEScanStop();
84 						state = STATE.w4_connected;
85 						btstack.GAPLEConnect(testAddrType, testAddr);
86 					}
87 				}
88 				break;
89 			case w4_connected:
90 				if (packet instanceof HCIEventLEConnectionComplete){
91 					HCIEventLEConnectionComplete event = (HCIEventLEConnectionComplete) packet;
92 					if (event.getStatus() != 0) {
93 						System.out.println(testAddr + String.format(" - connection failed, status %d.\nRestart scanning.", event.getStatus()));
94 						state = STATE.w4_scan_result;
95 						btstack.GAPLEScanStart();
96 						break;
97 					}
98 
99 					// Query test service.
100 					state = STATE.w4_services_complete;
101 					connectionHandle = event.getConnectionHandle();
102 					System.out.println(testAddr + String.format(" - connected %x.\nQuery streamer service.", connectionHandle));
103 					btstack.GATTDiscoverPrimaryServicesByUUID128(connectionHandle, testServiceUUID);
104 				}
105 				break;
106 			case w4_services_complete:
107 				if (packet instanceof GATTEventServiceQueryResult){
108 					// Store streamer service. Wait for GATTEventQueryComplete event to send next GATT command.
109 					GATTEventServiceQueryResult event = (GATTEventServiceQueryResult) packet;
110 					System.out.println(testAddr + String.format(" - streamer service %s", event.getService().getUUID()));
111 					testService = event.getService();
112 					break;
113 				}
114 				if (packet instanceof GATTEventQueryComplete){
115 					// Check if streamer service is found.
116 					if (testService == null) {
117 						System.out.println(testAddr + " - no streamer service. \nRestart scanning.");
118 						state = STATE.w4_scan_result;
119 						btstack.GAPLEScanStart();
120 						break;
121 					}
122 					System.out.println(testAddr + " - query streamer characteristic.");
123 					state = STATE.w4_characteristic_complete;
124 					btstack.GATTDiscoverCharacteristicsForServiceByUUID128(connectionHandle, testService, testCharacteristicUUID);
125 				}
126 				break;
127 			case w4_characteristic_complete:
128 				if (packet instanceof GATTEventCharacteristicQueryResult){
129 					// Store streamer characteristic. Wait for GATTEventQueryComplete event to send next GATT command.
130 					GATTEventCharacteristicQueryResult event = (GATTEventCharacteristicQueryResult) packet;
131 					testCharacteristic = event.getCharacteristic();
132 					System.out.println(testAddr + " - streamer characteristic found.");
133 					break;
134 				}
135 
136 				if (!(packet instanceof GATTEventQueryComplete)) break;
137 
138 				if (testCharacteristic == null) {
139 					System.out.println("No streamer characteristic found");
140 					break;
141 				}
142 				System.out.println(testAddr + " - enable notifications.");
143 				state = STATE.w4_write_client_config_characteristic_complete;
144 				btstack.GATTWriteClientCharacteristicConfiguration(connectionHandle, testCharacteristic, this.testNotification);
145 				break;
146 
147 			case w4_write_client_config_characteristic_complete:
148 				if (packet instanceof GATTEventQueryComplete){
149 					System.out.println(testAddr + " - notification enabled.");
150 					state = STATE.active;
151 				}
152 				break;
153 
154 			case active:
155 				if (packet instanceof GATTEventNotification){
156 					GATTEventNotification event = (GATTEventNotification) packet;
157 					System.out.println("Data:");
158 					Util.hexdump(event.getValue());
159 				}
160 				break;
161 
162 			default:
163 				break;
164 		}
165 	}
166 
167 	void test(){
168 
169 		System.out.println("LE Streamer Client");
170 
171 		// connect to BTstack Daemon via default port on localhost
172 		btstack = new BTstack();
173 		btstack.setTcpPort(BTstack.DEFAULT_TCP_PORT);
174 		btstack.registerPacketHandler(this);
175 		boolean ok = btstack.connect();
176 		if (!ok) {
177 			System.out.println("Failed to connect to BTstack Server");
178 			return;
179 		}
180 
181 		System.out.println("BTstackSetPowerMode(1)");
182 
183 		// btstack.SMSetAuthenticationRequirements(8 | 4);
184 		// btstack.SMSetIoCapabilities(4);
185 
186 		state = STATE.w4_btstack_working;
187 		btstack.BTstackSetPowerMode(1);
188 	}
189 
190 	public static void main(String args[]){
191 		new LEStreamerClient().test();
192 	}
193 }
194