diff --git a/platform/daemon/binding/java/build.xml b/platform/daemon/binding/java/build.xml index cbdee87fd..a0cf2647b 100644 --- a/platform/daemon/binding/java/build.xml +++ b/platform/daemon/binding/java/build.xml @@ -8,7 +8,7 @@ - + diff --git a/platform/daemon/binding/java/example/com/bluekitchen/LEStreamerClient.java b/platform/daemon/binding/java/example/com/bluekitchen/LEStreamerClient.java new file mode 100644 index 000000000..7d2b13b80 --- /dev/null +++ b/platform/daemon/binding/java/example/com/bluekitchen/LEStreamerClient.java @@ -0,0 +1,192 @@ +package com.bluekitchen; + +import com.bluekitchen.btstack.BD_ADDR; +import com.bluekitchen.btstack.BT_UUID; +import com.bluekitchen.btstack.BTstack; +import com.bluekitchen.btstack.GATTCharacteristic; +import com.bluekitchen.btstack.GATTService; +import com.bluekitchen.btstack.Packet; +import com.bluekitchen.btstack.PacketHandler; +import com.bluekitchen.btstack.Util; +import com.bluekitchen.btstack.event.BTstackEventState; +import com.bluekitchen.btstack.event.GAPEventAdvertisingReport; +import com.bluekitchen.btstack.event.GATTEventCharacteristicQueryResult; +import com.bluekitchen.btstack.event.GATTEventCharacteristicValueQueryResult; +import com.bluekitchen.btstack.event.GATTEventNotification; +import com.bluekitchen.btstack.event.GATTEventQueryComplete; +import com.bluekitchen.btstack.event.GATTEventServiceQueryResult; +import com.bluekitchen.btstack.event.HCIEventDisconnectionComplete; +import com.bluekitchen.btstack.event.HCIEventLEConnectionComplete; +import com.bluekitchen.btstack.event.SMEventJustWorksRequest; + +import java.nio.charset.StandardCharsets; + +public class LEStreamerClient implements PacketHandler { + + private enum STATE { + w4_btstack_working, w4_scan_result, w4_connected, w4_services_complete, w4_characteristic_complete, + w4_write_client_config_characteristic_complete, active + }; + + private BTstack btstack; + private STATE state; + private int testAddrType; + private BD_ADDR testAddr = new BD_ADDR("00:1A:7D:DA:71:01"); + private int connectionHandle; + + private BT_UUID testServiceUUID = new BT_UUID("0000FF10-0000-1000-8000-00805F9B34FB"); + private BT_UUID testCharacteristicUUID = new BT_UUID("0000FF11-0000-1000-8000-00805F9B34FB"); + private byte testNotification = 1; + + private GATTService testService; + private GATTCharacteristic testCharacteristic; + + public void handlePacket(Packet packet){ + + System.out.println("Event " + packet); + + if (packet instanceof SMEventJustWorksRequest){ + SMEventJustWorksRequest event = (SMEventJustWorksRequest) packet; + System.out.println("Received Just Works pairing request from " + event.getAddress() + " -> auto-accept"); + btstack.SMJustWorksConfirm(event.getHandle()); + return; + } + + if (packet instanceof HCIEventDisconnectionComplete){ + System.out.println("Received dissconnect, restart scannning."); + state = STATE.w4_scan_result; + btstack.GAPLEScanStart(); + return; + } + + switch (state){ + case w4_btstack_working: + if (packet instanceof BTstackEventState){ + BTstackEventState event = (BTstackEventState) packet; + if (event.getState() == 2) { + System.out.println("BTstack working, start scanning."); + state = STATE.w4_scan_result; + btstack.GAPLEScanStart(); + } + } + break; + case w4_scan_result: + if (packet instanceof GAPEventAdvertisingReport){ + // Advertisement received. Connect to the found BT address. + GAPEventAdvertisingReport report = (GAPEventAdvertisingReport) packet; + System.out.println(String.format("Adv: type %d, addr %s\ndata: %s\n", report.getAddressType(), report.getAddress(), Util.asHexdump(report.getData()))); + // hack to find 'LE Streamer' + if (new String(report.getData(), StandardCharsets.UTF_8).indexOf("LE Streamer") > 0){ + testAddrType = report.getAddressType(); + testAddr = report.getAddress(); + System.out.println(String.format("LE Streamer found, connect to %s\n", testAddr)); + btstack.GAPLEScanStop(); + state = STATE.w4_connected; + btstack.GAPLEConnect(testAddrType, testAddr); + } + } + break; + case w4_connected: + if (packet instanceof HCIEventLEConnectionComplete){ + HCIEventLEConnectionComplete event = (HCIEventLEConnectionComplete) packet; + if (event.getStatus() != 0) { + System.out.println(testAddr + String.format(" - connection failed, status %d.\nRestart scanning.", event.getStatus())); + state = STATE.w4_scan_result; + btstack.GAPLEScanStart(); + break; + } + + // Query test service. + state = STATE.w4_services_complete; + connectionHandle = event.getConnectionHandle(); + System.out.println(testAddr + String.format(" - connected %x.\nQuery streamer service.", connectionHandle)); + btstack.GATTDiscoverPrimaryServicesByUUID128(connectionHandle, testServiceUUID); + } + break; + case w4_services_complete: + if (packet instanceof GATTEventServiceQueryResult){ + // Store streamer service. Wait for GATTEventQueryComplete event to send next GATT command. + GATTEventServiceQueryResult event = (GATTEventServiceQueryResult) packet; + System.out.println(testAddr + String.format(" - streamer service %s", event.getService().getUUID())); + testService = event.getService(); + break; + } + if (packet instanceof GATTEventQueryComplete){ + // Check if streamer service is found. + if (testService == null) { + System.out.println(testAddr + " - no streamer service. \nRestart scanning."); + state = STATE.w4_scan_result; + btstack.GAPLEScanStart(); + break; + } + System.out.println(testAddr + " - query streamer characteristic."); + state = STATE.w4_characteristic_complete; + btstack.GATTDiscoverCharacteristicsForServiceByUUID128(connectionHandle, testService, testCharacteristicUUID); + } + break; + case w4_characteristic_complete: + if (packet instanceof GATTEventCharacteristicQueryResult){ + // Store streamer characteristic. Wait for GATTEventQueryComplete event to send next GATT command. + GATTEventCharacteristicQueryResult event = (GATTEventCharacteristicQueryResult) packet; + testCharacteristic = event.getCharacteristic(); + System.out.println(testAddr + " - streamer characteristic found."); + break; + } + + if (!(packet instanceof GATTEventQueryComplete)) break; + + if (testCharacteristic == null) { + System.out.println("No streamer characteristic found"); + break; + } + System.out.println(testAddr + " - enable notifications."); + state = STATE.w4_write_client_config_characteristic_complete; + btstack.GATTWriteClientCharacteristicConfiguration(connectionHandle, testCharacteristic, this.testNotification); + break; + + case w4_write_client_config_characteristic_complete: + if (packet instanceof GATTEventQueryComplete){ + System.out.println(testAddr + " - notification enabled."); + state = STATE.active; + } + break; + + case active: + if (packet instanceof GATTEventNotification){ + System.out.println("Data:"); + System.out.println(packet.toString()); + } + break; + + default: + break; + } + } + + void test(){ + + System.out.println("LE Streamer Client"); + + // connect to BTstack Daemon via default port on localhost + btstack = new BTstack(); + btstack.setTcpPort(BTstack.DEFAULT_TCP_PORT); + btstack.registerPacketHandler(this); + boolean ok = btstack.connect(); + if (!ok) { + System.out.println("Failed to connect to BTstack Server"); + return; + } + + System.out.println("BTstackSetPowerMode(1)"); + + // btstack.SMSetAuthenticationRequirements(8 | 4); + // btstack.SMSetIoCapabilities(4); + + state = STATE.w4_btstack_working; + btstack.BTstackSetPowerMode(1); + } + + public static void main(String args[]){ + new LEStreamerClient().test(); + } +}