java: Add spp streamer client

This commit is contained in:
Boris Zweimuelller 2022-04-01 22:41:07 +02:00 committed by Matthias Ringwald
parent a2b4333846
commit 6418890ec2
2 changed files with 209 additions and 1 deletions

View File

@ -8,7 +8,7 @@
<property name="classes.dir" value="${build.dir}/classes"/>
<property name="jar.dir" value="${build.dir}/jar"/>
<property name="test-class" value="com.bluekitchen.LEStreamerClient"/>
<property name="test-class" value="com.bluekitchen.SPPStreamerClient"/>
<target name="clean">
<delete dir="${build.dir}"/>

View File

@ -0,0 +1,208 @@
package com.bluekitchen;
import com.bluekitchen.btstack.BD_ADDR;
import com.bluekitchen.btstack.BTstack;
import com.bluekitchen.btstack.Packet;
import com.bluekitchen.btstack.PacketHandler;
import com.bluekitchen.btstack.RFCOMMDataPacket;
import com.bluekitchen.btstack.Util;
import com.bluekitchen.btstack.event.*;
/**
* Simple demonstration of the Java binding by streaming data over SPP.
*
* This is the same example as the: example/spp_streamer_client.c example.
*
* It can be run against the 'spp_streamer' example.
*
* To run, two dongles are needed, then:
*
* 1. In a first terminal run:
*
* cd port/libusb
* ./spp_streamer
*
* 2. In a second terminal, run the daemon:
*
* cd port/daemon
* ./src/BTdaemon --tcp
*
* 3. In a third terminal, run the java application:
*
* cd platform/daemon/binding/java
*
* Adapt the remote MAC address in:
*
* example/com/bluekitchen/SPPStreamerClient.java
*
* ant run
*
*/
public class SPPStreamerClient implements PacketHandler {
private final static int NUM_ROWS = 25;
private final static int NUM_COLS = 40;
private enum STATE {
BTSTACK_WORKING, SDP_QUERY_RESULT, CONNECTED, SENDING
}
private BTstack btstack;
private STATE state;
private final BD_ADDR remote = new BD_ADDR("00:15:83:D1:17:9F");
private int outgoing_channel_nr = -1;
private int rfcommChannelID = 0;
private final static int REPORT_INTERVAL_MS = 3000;
private long test_data_transferred;
private long test_data_start;
private byte[] sppTestData;
private void createSppTestData(final int mtu) {
byte[] temp = new byte[NUM_ROWS * NUM_COLS];
int x, y;
for (y = 0; y < NUM_ROWS; y++) {
for (x = 0; x < NUM_COLS - 2; x++) {
temp[y * NUM_COLS + x] = (byte) ('0' + (x % 10));
}
temp[y * NUM_COLS + NUM_COLS - 2] = '\n';
temp[y * NUM_COLS + NUM_COLS - 1] = '\r';
}
// cut to MTU
sppTestData = new byte[Math.min(mtu, temp.length)];
System.arraycopy(temp, 0, sppTestData, 0, sppTestData.length);
}
void testReset() {
test_data_start = System.currentTimeMillis();
test_data_transferred = 0;
}
private void calculateSpeedAndLog(int bytesSent){
test_data_transferred += bytesSent;
// evaluate
long now = System.currentTimeMillis();
long timePassed = now - test_data_start;
if (timePassed < REPORT_INTERVAL_MS) return;
// print speed
long bytesPerSecond = test_data_transferred * 1000 / timePassed;
System.out.printf("%d bytes -> %d.%03d kB/s\n", (int) test_data_transferred, (int) bytesPerSecond / 1000, bytesPerSecond % 1000);
// restart
test_data_start = now;
test_data_transferred = 0;
}
private void startSDPQuery() {
state = STATE.SDP_QUERY_RESULT;
int sppUUID = 0x1101;
byte[] serviceSearchPattern = Util.serviceSearchPatternForUUID16(sppUUID);
btstack.SDPClientQueryRFCOMMServices(remote, serviceSearchPattern);
}
public void handlePacket(Packet packet) {
if (packet instanceof HCIEventDisconnectionComplete) {
final HCIEventDisconnectionComplete event = (HCIEventDisconnectionComplete) packet;
System.out.printf("Received disconnect, status %d, handle %x%n", event.getStatus(), event.getConnectionHandle());
btstack.disconnect();
return;
}
switch (state) {
case BTSTACK_WORKING:
if (packet instanceof BTstackEventState) {
final BTstackEventState event = (BTstackEventState) packet;
if (event.getState() == 2) {
System.out.println("BTstack working. Start SDP inquiry.");
startSDPQuery();
}
}
break;
case SDP_QUERY_RESULT:
if (packet instanceof SDPEventQueryRFCOMMService) {
final SDPEventQueryRFCOMMService service = (SDPEventQueryRFCOMMService) packet;
System.out.println("Found RFCOMM channel " + service.getName() + ", channel nr: " + service.getRFCOMMChannel());
outgoing_channel_nr = service.getRFCOMMChannel();
}
if (packet instanceof SDPEventQueryComplete) {
SDPEventQueryComplete complete = (SDPEventQueryComplete) packet;
if (complete.getStatus() != 0) {
System.out.printf("SDP Query failed with status 0x%02x, retry SDP query.%n", complete.getStatus());
startSDPQuery();
break;
}
if (outgoing_channel_nr >= 0) {
state = STATE.CONNECTED;
System.out.println("Connect to channel nr " + outgoing_channel_nr);
btstack.RFCOMMCreateChannel(remote, outgoing_channel_nr);
}
}
break;
case CONNECTED:
if (packet instanceof RFCOMMEventChannelOpened) {
RFCOMMEventChannelOpened e = (RFCOMMEventChannelOpened) packet;
System.out.println("RFCOMMEventChannelOpened with status " + e.getStatus());
if (e.getStatus() != 0) {
System.out.println("RFCOMM channel open failed, status " + e.getStatus());
} else {
state = STATE.SENDING;
rfcommChannelID = e.getRFCOMMCid();
System.out.printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %d, max frame size %d%n", rfcommChannelID, e.getMaxFrameSize());
createSppTestData(e.getMaxFrameSize());
testReset();
btstack.RFCOMMRequestCanSendNow(e.getRFCOMMCid());
}
}
break;
case SENDING:
if (packet instanceof RFCOMMEventCanSendNow) {
btstack.RFCOMMSendData(rfcommChannelID, sppTestData);
calculateSpeedAndLog(sppTestData.length);
btstack.RFCOMMRequestCanSendNow(rfcommChannelID);
}
if (packet instanceof RFCOMMDataPacket) {
// duplex
calculateSpeedAndLog(sppTestData.length);
}
default:
break;
}
}
void stream() {
System.out.println("SPP Streamer Client");
// connect to BTstack Daemon via default port on localhost
// start: src/BTdaemon --tcp
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)");
state = STATE.BTSTACK_WORKING;
btstack.BTstackSetPowerMode(1);
}
public static void main(String[] args) {
new SPPStreamerClient().stream();
}
}