【问题标题】:How to display the RSSI of a BLE device continously?如何连续显示BLE设备的RSSI?
【发布时间】:2017-04-20 12:47:47
【问题描述】:

我正在尝试实现一个扫描 BLE 设备的 android 应用程序。因为我需要某种信标的距离信息,所以我想连续读取 RSSI。目前我可以显示 RSSI,但值不会改变。应用程序读取该值一次并且不更新该值。我使用了来自 gitHub 的示例 BLE 应用程序作为基础。

这是我的蓝牙设备:

  class DeviceHolder{
    BluetoothDevice device;
    int rssi;
    public DeviceHolder(BluetoothDevice device, int rssi){
        this. device = device;
        this.rssi = rssi;
    }
}

列表适配器:

 private class LeDeviceListAdapter extends BaseAdapter {
    private ArrayList<BluetoothDevice> mLeDevices;
    private ArrayList<DeviceHolder> mLeHolders;
    private LayoutInflater mInflator;

    public LeDeviceListAdapter() {
        super();
        mLeDevices = new ArrayList<BluetoothDevice>();
        mLeHolders = new ArrayList<DeviceHolder>();
        mInflator = DeviceScanActivity.this.getLayoutInflater();
    }
    public void addDevice(DeviceHolder deviceHolder) {
        if(!mLeDevices.contains(deviceHolder.device)) {
            mLeDevices.add(deviceHolder.device);
            mLeHolders.add(deviceHolder);
        }
    }

以及扫描回调:

private BluetoothAdapter.LeScanCallback mLeScanCallback =
        new BluetoothAdapter.LeScanCallback() {

            @Override
            public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
                DeviceHolder deviceHolder = new DeviceHolder(device,rssi);
                runOnUiThread(new DeviceAddTask( deviceHolder ) );
            }
        };

class DeviceAddTask implements Runnable {
    DeviceHolder deviceHolder;

    public DeviceAddTask( DeviceHolder deviceHolder ) {
        this.deviceHolder = deviceHolder;
    }

    public void run() {
        mLeDeviceListAdapter.addDevice(deviceHolder);
        mLeDeviceListAdapter.notifyDataSetChanged();
    }
}

BluetoothLeService Activity 中的 Bluetooth GattCallback 如下所示:

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        String intentAction;
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            intentAction = ACTION_GATT_CONNECTED;
            mConnectionState = STATE_CONNECTED;
            boolean rssiStatus = mBluetoothGatt.readRemoteRssi();
            broadcastUpdate(intentAction);
            Log.i(TAG, "Connected to GATT server.");
            // Attempts to discover services after successful connection.
            Log.i(TAG, "Attempting to start service discovery:" +
                    mBluetoothGatt.discoverServices());

        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            intentAction = ACTION_GATT_DISCONNECTED;
            mConnectionState = STATE_DISCONNECTED;
            Log.i(TAG, "Disconnected from GATT server.");
            broadcastUpdate(intentAction);
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
        } else {
            Log.w(TAG, "onServicesDiscovered received: " + status);
        }
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
                                     BluetoothGattCharacteristic characteristic,
                                     int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,
                                        BluetoothGattCharacteristic characteristic) {
        broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
    }

    public void onReadRemoteRssi(BluetoothGatt gatt,
                                 int rssi, int status){
        super.onReadRemoteRssi(gatt, rssi, status);
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.d(TAG, String.format("BluetoothGatt ReadRssi[%d]", rssi));
        } else {
            Log.w(TAG, "onReadRemoteRssi received: " + status);
        }
        broadcastUpdate(ACTION_RSSI_VALUE_READ, rssi);

    }
};

private void broadcastUpdate(final String action) {
    final Intent intent = new Intent(action);
    sendBroadcast(intent);
}

private void broadcastUpdate(final String action, int rssi){
    Log.d(TAG, "broadcastUpdate - rssi");
    final Intent intent = new Intent(action);
    intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_RSSI, rssi);
    intent.setAction(ACTION_RSSI_VALUE_READ);
    sendBroadcast(intent);
}

我在 Internet 和 Stackoverflow 上查找指导,但提供的解决方案对我不起作用。我正在使用搭载 Android 6.01 的三星 Galaxy S5。 有没有人提示如何为未连接的设备(扫描时)连续显示 RSSI?也欢迎任何有关错误实施的提示。

非常感谢您的帮助!

萨尤斯

PS:实现 onReadRemoteRssi 是因为我想在设备连接时读取 RSSI。这个功能目前并不重要,只是很高兴拥有。

【问题讨论】:

    标签: java android bluetooth-lowenergy rssi


    【解决方案1】:

    您的应用程序会读取一次 RSSI 值并且不会更新它,因为当您将新的 BluetoothDevice 添加到适配器时,它会检查它是否已经包含一个。

        if(!mLeDevices.contains(deviceHolder.device)) {
            mLeDevices.add(deviceHolder.device);
            mLeHolders.add(deviceHolder);
        }
    

    相反,我会创建一个Map&lt;BluetoothDevice,Integer&gt;,您可以在其中更新设备的 rssi 值:mDeviceRssi.put(device, rssi)

    【讨论】:

    • 非常感谢您的回答!现在我明白了这个问题。而且我也明白我应该只更新列出的设备。由于我是 android 开发的新手,如果您能提供更多关于 Map 以及如何在我的代码中使用它的信息,我将非常感激。一个有用的链接也足够了。再次感谢!
    猜你喜欢
    • 2013-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多