如何从BLE设备读取数据

时间:2019-10-15 19:19:05

标签: java android module bluetooth-lowenergy appcelerator

所以,我一直在努力使用BLE。 我正在开发一个Appcelerator模块,该模块可以启用某些设备与Android平板电脑之间的通信(读/写数据)。 我能够扫描,发现设备,连接到它并发现它的服务。 我无法做的是读取数据。 如下面的代码所示,方法readData()的内容始终返回false。 (writeDescriptor,readCharacteristic,readDescriptor)。无论如何,这总是返回false。从未调用过该回调,而我完全陷入了困境。 我到底在做什么错?如何将readData()上的这些内容设置为true,之后该怎么办? 预先谢谢大家!

我已经多次检查stackOverflow并尝试了此处提出的许多解决方案,但似乎没有任何效果。据我了解,我的步骤是正确的。缺少什么...只是不知道...

public class AndroidbleModule extends KrollModule  {

    private BluetoothManager btManager;
    private BluetoothAdapter btAdapter;
    private BluetoothDevice btDevice;
    private TiApplication appContext;
    private Activity activity;
    private BluetoothLeScanner btScanner;

    public AndroidbleModule() {
        super();
        appContext = TiApplication.getInstance();
        activity = appContext.getCurrentActivity();
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        filter.addAction(BluetoothDevice.ACTION_UUID);
        filter.addAction(BluetoothDevice.ACTION_FOUND);
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        appContext.registerReceiver(new BlutoothStateChangedBroadcastReceiver(AndroidbleModule.this, btAdapter),
                filter);
    }

    private BluetoothGatt bluetoothGatt;
    private BluetoothGattCallbackHandler btGattHandler = new BluetoothGattCallbackHandler(AndroidbleModule.this);

    @Kroll.method
    public void connectToDevice(String device) {

        if (bluetoothGatt != null) {
            bluetoothGatt.disconnect();
        }
        for (String devName : btDevices.keySet()) {

            if(device.equals(devName)) {
                BluetoothDevice deviceAddress = btDevices.get(devName);
                bluetoothGatt = deviceAddress.connectGatt(appContext, false, btGattHandler);
                bluetoothGatt.connect();
                bluetoothGatt.discoverServices();
                deviceAddress.createBond();
                deviceAddress.getBondState();   
                btDevice = deviceAddress;
            }
        }
    }
    BluetoothGattCharacteristic charac;
    BluetoothGattDescriptor desc;

    @Kroll.method
    public void setNotifications() {
        List<BluetoothGattService> btGattServicesList = bluetoothGatt.getServices();
        List<BluetoothGattCharacteristic> btGattCharList = btGattServicesList.get(2).getCharacteristics();
        List<BluetoothGattDescriptor> btDescList = btGattCharList.get(1).getDescriptors();
        BluetoothGattCharacteristic characteristic = btGattCharList.get(1);
        BluetoothGattDescriptor descriptor = btDescList.get(0);

        bluetoothGatt.setCharacteristicNotification(characteristic, true);
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);

        charac = characteristic;
        desc = descriptor;
    }

    @Kroll.method
    public void readData() {
        bluetoothGatt.writeDescriptor(desc);
        bluetoothGatt.readCharacteristic(charac);
        bluetoothGatt.readDescriptor(desc);
    }

    private Set<String> devSet = new LinkedHashSet<String>();

    HashMap<String, BluetoothDevice> btDevices = new HashMap<String, BluetoothDevice>();

    private ScanCallback scanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {

            BluetoothDevice device;
            device = result.getDevice();

            KrollDict kd = new KrollDict();
            kd.put("name", device.getName());
            kd.put("address", device.getAddress());

            System.out.println("Devices Found on Scan: " + kd.toString());

            btDevice = device;
            devSet.add(device.getName());
            btDevices.put(device.getName(), device);
        }
    };

    @Kroll.method
    public void startScanning(@Kroll.argument(optional = true) int _scanmode) {
        if (btAdapter != null) {
            btScanner = btAdapter.getBluetoothLeScanner();
            btScanner.startScan(scanCallback);
            isScanning = true;
        }
    }
}

2 个答案:

答案 0 :(得分:0)

首先,我的connectToDevice()方法,其中提到了更改:

public void connectToDevice(String device) {
    if (bluetoothGatt != null) {
        bluetoothGatt.disconnect();
    }
    for (String devName : btDevices.keySet()) {

        if(device.equals(devName)) {
            BluetoothDevice deviceAddress = btDevices.get(devName);
            bluetoothGatt = deviceAddress.connectGatt(appContext, false, btGattHandler);
            btDevice = deviceAddress;
        }
    }
}

onConnectionStateChanged()回调方法:

public void onConnectionStateChange(final BluetoothGatt gatt,
        final int status, final int newState) {
    gatt.getDevice().createBond();
    KrollDict kd = new KrollDict();
    kd.put("newState", newState);
    kd.put("status", status);
    if (proxy.hasListeners("didConnectionStateChange")) {
        proxy.fireEvent("didConnectionStateChange", kd);
    }
    gatt.discoverServices();
}

onServicesDiscovered()回调方法:

public void onServicesDiscovered(final BluetoothGatt gatt, final int status) {
    BluetoothDevice device = gatt.getDevice();
    KrollDict kdServices = new KrollDict();
    KrollDict kdCharacteristics = new KrollDict();

    List<BluetoothGattService> services = gatt.getServices();
    kdServices.put("device", device.getAddress());
    kdCharacteristics.put("device", device.getAddress());

    Log.i(LCAT, device.getAddress() + " services count: " + services.size());

    ArrayList<Object> listServices = new ArrayList<>();
    HashMap<String, Object> hashChar = new HashMap<String, Object>();

    for (BluetoothGattService service : services) {
        Log.i(LCAT,
                "Service: " + service.getType() + " " + service.getUuid());

        HashMap<String, Object> listService = new HashMap<String, Object>();
        listService.put("serviceType", service.getType());
        listService.put("serviceUuid", service.getUuid());
        listServices.add(listService);

        ArrayList<HashMap<String, Object>> listChars = new ArrayList<HashMap<String, Object>>();
        List<BluetoothGattCharacteristic> characteristics = service
                .getCharacteristics();
        for (BluetoothGattCharacteristic btc : characteristics) {
            Log.i(LCAT, "uuid: " + btc.getUuid());

            HashMap<String, Object> listChar = new HashMap<String, Object>();
            listChar.put("uuid", btc.getUuid());
            listChar.put("value", btc.getValue());

            listChars.add(listChar);
            // TODO not needed at the moment
             byte[] data = btc.getValue();
             if (data != null && data.length > 0) {
             final StringBuilder stringBuilder = new
             StringBuilder(data.length);
             for (byte byteChar : data) {
             stringBuilder.append(String.format("%02X ", byteChar));
             }

             Log.i(LCAT, "String val: " + btc.getUuid() + " " +
             btc.getValue() + " " + stringBuilder.toString());
             }
            gatt.readCharacteristic(btc);
        }
        hashChar.put("serviceUuid", service.getUuid());
        hashChar.put("chars", listChars);
    }
    if (proxy.hasListeners("didDiscoverServices"))
        proxy.fireEvent("didDiscoverServices", kdServices);
    if (proxy.hasListeners("didDiscoverCharacteristicsForService"))
        proxy.fireEvent("didDiscoverCharacteristicsForService",
                kdCharacteristics);
    System.out.println("Services successfully discovered!");
}

我没有动过setNotifications(),如您所见,它对所有内容都返回true。 现在,当我调用readData()(仅剩一个gatt调用,即writeCharacteristic())时,它将返回false,如日志的最后一行所示。看看。

日志:

I/System.out: connectToDevice() called!
I/System.out: Device successfully connected!

BluetoothDevice: createBond() for device FA:45:B9:7C:86:7C called by pid: 6194 tid: 6207

BLE: (Binder:6194_2) [19078,19078] FA:45:B9:7C:86:7C services count: 3
BLE: (Binder:6194_2) [1,19079] Service: 0 00001800-0000-1000-8000-00805f9b34fb
BLE: (Binder:6194_2) [0,19079] uuid: 00002a00-0000-1000-8000-00805f9b34fb
BLE: (Binder:6194_2) [1,19080] uuid: 00002a01-0000-1000-8000-00805f9b34fb
BLE: (Binder:6194_2) [0,19080] uuid: 00002a04-0000-1000-8000-00805f9b34fb
BLE: (Binder:6194_2) [1,19081] uuid: 00002aa6-0000-1000-8000-00805f9b34fb
BLE: (Binder:6194_2) [0,19081] Service: 0 00001801-0000-1000-8000-00805f9b34fb
BLE: (Binder:6194_2) [0,19081] Service: 0 6e400001-b5a3-f393-e0a9-e50e24dcca9e
BLE: (Binder:6194_2) [0,19081] uuid: 6e400002-b5a3-f393-e0a9-e50e24dcca9e
BLE: (Binder:6194_2) [0,19081] uuid: 6e400003-b5a3-f393-e0a9-e50e24dcca9e
I/System.out: Services successfully discovered!

I/System.out: btGattServicesList - [android.bluetooth.BluetoothGattService@c893553, android.bluetooth.BluetoothGattService@5dd2e90, android.bluetooth.BluetoothGattService@6bce389]
I/System.out: btGattCharList - [android.bluetooth.BluetoothGattCharacteristic@b6cf8e, android.bluetooth.BluetoothGattCharacteristic@6e7d3af]
I/System.out: btDescList - [android.bluetooth.BluetoothGattDescriptor@b8ea3bc]

I/System.out: setCharacteristicNotification = true
I/System.out: Enable Notification Value = true
I/System.out: characteristic.addDescriptor(descriptor) = true

I/System.out: bluetoothGatt.writeCharacteristic(charac) false

这里到底是什么东西失踪或出问题了?

答案 1 :(得分:0)

因此,在浪费大量时间后,我想出了办法。 setNotifications只是第一步。我们必须告诉设备开始流数据,以便App可以收集数据。这是通过bluetoothGatt.writeCharacteristic(characteristic)完成的 当然,在我们适当地设定了作品之后。 完成此操作后,字节就一直存在! =)