如何使用蓝牙插件读写文本数据

时间:2017-10-24 18:05:18

标签: bluetooth codenameone

有人可以提供有关如何使用蓝牙cn1库读取和写入文本数据的示例代码吗?我尝试查看项目源代码(https://github.com/chen-fishbein/bluetoothle-codenameone)作为示例代码,但找不到任何使用适当的方法读/写文本数据。这些方法也没有任何Java文档。

2 个答案:

答案 0 :(得分:1)

这是我用来发送的代码:

reloadData()

这里接收:

public void sendMessage(String message) {
    if (Display.getInstance().isSimulator()) {
        System.out.println(message);
    } else {
        // System.out.println("Sending message: " + message);
        String b64WriteString = Base64.encode(message.getBytes());
        try {
            bt.write(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent evt) {

                }
            }, deviceAddress, services.get(0), sendDataCharacteristic, b64WriteString, false);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

我为服务和特征UUID定义了字段。此外,可能不再需要callSerially。我想我记得CN1LIB已经更新了,但我确实不记得了。

对于该设备,服务特性为“6E400001-B5A3-F393-E0A9-E50E24DCCA9E”

sendCharacteristic是“0x0002”

receiveCharacteristic是“0x0003”

答案 1 :(得分:0)

在接受了James H的建议,以及更多的试验错误后,我终于设法让Adafruit的Bluefruit LE Friend之间的数据传输一致,至少在Android设备上。虽然不确定iOS,因为我还没有测试过它。以下是所需的关键代码。

首先,您需要服务,TX和RX特性UUID。找到了这些UUID here。注意,这些不一定是大写的。

public static final String UUID_SERVICE = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
public static final String UUID_RX = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";
public static final String UUID_TX = "6e400002-b5a3-f393-e0a9-e50e24dcca9e";

接下来,扫描并找到设备后,调用connect()方法进行实际连接,然后严格调用discover()方法。一旦调用了discover()回调,就添加“subscriber”来接收数据。

private void connect(String address) {
    bleAddress = address; // set the global BLE address

    if (!connected) {
        // start an infinite progress dialog
        final Dialog ip = new InfiniteProgress().showInifiniteBlocking();

        try {
            bt.connect(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent evt) {
                    ip.dispose();

                    Object obj = evt.getSource();
                    print("Connected to Bluetooth LE device ...\n" + obj, true);
                    // must be called on Android devices in order to load on the UUIDs, otherwise there is an error that service can't be found. Won't do anything on ios though?
                    discover(); 

                    connected = true;
                }

            }, address);
        } catch (IOException ex) {
            ip.dispose();

            String message = "Error connecting to bluetooth device: " + address;
            print(message + "\n" + ex.getMessage(), false);
        }
    } else {
        String message = "BLE device already connected to: " + address;
        print(message, false);
    }
}

private void discover() {
    try {
        bt.discover(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
                print("BLE Information Received ...", true);
                addSubscriber();
            }

        }, bleAddress);

    } catch (Exception ex) {
        print(ex.getMessage(), false);
    }

    // if we running on is add the subscriber here since the above bt call
    // does nothing?
    if (Display.getInstance().getPlatformName().equals("ios")) {
        print("Adding subscriber for iOS Device", true);
        addSubscriber();
    }
}

private void addSubscriber() {
    try {
        bt.subscribe(new ActionListener() {
            StringBuilder sb = new StringBuilder();

            @Override
            public void actionPerformed(ActionEvent evt) {
                JSONObject dataIncoming = (JSONObject) evt.getSource();
                String base64Value = "";
                try {
                    if (dataIncoming.getString("status").equals("subscribedResult")) {
                        base64Value = dataIncoming.getString("value");
                    }
                } catch (JSONException e) {
                    console.setText("Error reading data: " + e.getMessage());
                }

                String message = new String(Base64.decode(base64Value.getBytes()));
                sb.append(message);

                if (message.endsWith("\r\n")) {
                    processData(sb.toString());
                    sb = new StringBuilder();
                }
            }

        }, bleAddress, UUID_SERVICE, UUID_RX);

        String message = console.getText() + "\nSubcriber added ...";
        console.setText(message);
    } catch (IOException ex) {
        String message = "Error Subscribing: " + ex.getMessage();
        console.setText(message);
    }
}

因此,这将建立连接,发现服务,最后添加接收数据的订阅者方法,并严格使用缓冲区来收集接收的数据,直到收到CRLF字符。

然而,我遇到的另一个主要问题是BLE规范的默认23字节发送限制(可能只是Android问题?)。如果您尝试发送超过此数量,则连接将被删除,并且不会返回任何有意义的错误消息。为了解决这个问题,我使用了建议here的技术,它需要将数据拆分成20字节数组的块。由于我们发送常规ASCII文本,那么20个字符应该是20个字节,所以我只是将文本拆分成长度为20个字符的字符串。它不是最有效的,它更容易调试。

private void sendText(final String data) {
    try {
        String b64String = Base64.encode(data.getBytes());

        bt.write(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
                if(data.endsWith("\r\n")) {
                    print("Data sent ...", true);
                }
            }

        }, bleAddress, UUID_SERVICE, UUID_TX, b64String, false);
    } catch (IOException ex) {
        String message = "Error sending: " + data + "\n"
                + UUID_SERVICE + "\n"
                + UUID_TX + "\n"
                + ex.getMessage();
        print(message, false);
    }
}

private void splitAndSend(String text) {
    text += "\r\n";

    // first split data in chunk size of 20 chracters
    ArrayList<String> sl = new ArrayList<>();

    char[] data = text.toCharArray();       
    int len = data.length;
    int chunkSize = 20;

    for (int i=0; i < len; i+= chunkSize) {
        sl.add(new String(data, i, Math.min(chunkSize,len - i)));
    }

    // now send chunks amd wait 100 ms to prevent any erros
    for(String word: sl) {
        sendText(word);
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {}
    }
}

可以找到包含GUI内容的完整源代码here,但这绝对是一项正在进行中的工作。