不知道为什么,小米的蓝牙鼠标在linux下面安装不是很顺利,系统能够识别出蓝牙鼠标,但是自作多情的识别出了一堆,如图所示:
看着不爽啊,怎么办?祭出bluetoothctl大法,下面是bluetoothctl的执行过程:
$ bluetoothctl
[NEW] Controller A0:C5:89:35:05:CE mibuntu [default]
[NEW] Device FE:8F:AC:55:93:48 MiMouse
[NEW] Device CE:55:BA:B8:65:B9 MiMouse
[NEW] Device EA:36:73:C7:64:C5 MiMouse
[NEW] Device 74:23:44:45:9B:FB 红米手机
[NEW] Device FD:90:32:24:D4:04 MiMouse
[NEW] Device D6:B4:84:9A:05:87 MiMouse
[bluetooth]# help
Available commands:
list List available controllers
show [ctrl] Controller information
select <ctrl> Select default controller
devices List available devices
paired-devices List paired devices
power <on/off> Set controller power
pairable <on/off> Set controller pairable mode
discoverable <on/off> Set controller discoverable mode
agent <on/off/capability> Enable/disable agent with given capability
default-agent Set agent as the default one
set-scan-filter-uuids [uuid1 uuid2 …] Set scan filter uuids
set-scan-filter-rssi [rssi] Set scan filter rssi, and clears pathloss
set-scan-filter-pathloss [pathloss] Set scan filter pathloss, and clears rssi
set-scan-filter-transport [transport] Set scan filter transport
set-scan-filter-clear Clears discovery filter
scan <on/off> Scan for devices
info [dev] Device information
pair [dev] Pair with device
trust [dev] Trust device
untrust [dev] Untrust device
block [dev] Block device
unblock [dev] Unblock device
remove <dev> Remove device
connect <dev> Connect device
disconnect [dev] Disconnect device
list-attributes [dev] List attributes
select-attribute <attribute> Select attribute
attribute-info [attribute] Select attribute
read Read attribute value
write <data=[xx xx …]> Write attribute value
notify <on/off> Notify attribute value
register-profile <UUID …> Register profile to connect
unregister-profile Unregister profile
version Display version
quit Quit program
[bluetooth]# remove D6:B4:84:9A:05:87
[DEL] Device D6:B4:84:9A:05:87 MiMouse
Device has been removed
[bluetooth]# remove FD:90:32:24:D4:04
[DEL] Device FD:90:32:24:D4:04 MiMouse
Device has been removed
[bluetooth]# remove EA:36:73:C7:64:C5
[DEL] Device EA:36:73:C7:64:C5 MiMouse
Device has been removed
[bluetooth]# remove CE:55:BA:B8:65:B9
[DEL] Device CE:55:BA:B8:65:B9 MiMouse
Device has been removed
[bluetooth]# devices
Device FE:8F:AC:55:93:48 MiMouse
Device 74:23:44:45:9B:FB 红米手机
全部删除MiMouse设备,然后重新发现和连接即可。
小经验:最好通过bluetoothctl执行trust指令将MiMouse加入信任设备列表,这样配对的时候不需要验证。
Generic Attribute Profile (GATT)
通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。
Attribute Protocol (ATT)
GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。
Characteristic
Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。
Descriptor
对Characteristic的描述,例如范围、计量单位等。
Service
Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement"的Characteristic。
二、角色和职责:
Android设备与BLE设备交互有两组角色:
中心设备和外围设备(Central vs peripheral);
GATT server vs GATT client
Central vs peripheral:
中心设备和外围设备的概念针对的是BLE连接本身。Central角色负责scan advertisement。而peripheral角色负责make advertisement。
GATT server vs GATT client:
这两种角色取决于BLE连接成功后,两个设备间通信的方式。
举例说明:
现 有一个活动追踪的BLE设备和一个支持BLE的Android设备。Android设备支持Central角色,而BLE设备支持peripheral角 色。创建一个BLE连接需要这两个角色都存在,都仅支持Central角色或者都仅支持peripheral角色则无法建立连接。
当 连接建立后,它们之间就需要传输GATT数据。谁做server,谁做client,则取决于具体数据传输的情况。例如,如果活动追踪的BLE设备需要向 Android设备传输sensor数据,则活动追踪器自然成为了server端;而如果活动追踪器需要从Android设备获取更新信息,则 Android设备作为server端可能更合适。
三、权限及feature:
和经典蓝牙一样,应用使用蓝牙,需要声明BLUETOOTH权限,如果需要扫描设备或者 *** 作蓝牙设置,则还需要BLUETOOTH_ADMIN权限:
<uses-permission android:name="androidpermissionBLUETOOTH"/>
<uses-permission android:name="androidpermissionBLUETOOTH_ADMIN"/>
除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature:
<uses-feature android:name="androidhardwarebluetooth_le" android:required="true"/>
按时required为true时,则应用只能在支持BLE的Android设备上安装运行;required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE feature:
// Use this check to determine whether BLE is supported on the device Then
// you can selectively disable BLE-related features
if (!getPackageManager()hasSystemFeature(PackageManagerFEATURE_BLUETOOTH_LE)) {
ToastmakeText(this, Rstringble_not_supported, ToastLENGTH_SHORT)show();
finish();
}
四、启动蓝牙:
在使用蓝牙BLE之前,需要确认Android设备是否支持BLE feature(required为false时),另外要需要确认蓝牙是否打开。
如果发现不支持BLE,则不能使用BLE相关的功能。如果支持BLE,但是蓝牙没打开,则需要打开蓝牙。
打开蓝牙的步骤:
1、获取BluetoothAdapter
BluetoothAdapter是Android系统中所有蓝牙 *** 作都需要的,它对应本地Android设备的蓝牙模块,在整个系统中BluetoothAdapter是单例的。当你获取到它的示例之后,就能进行相关的蓝牙 *** 作了。
获取BluetoothAdapter代码示例如下:
// Initializes Bluetooth adapter
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(ContextBLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManagergetAdapter();
注:这里通过getSystemService获取BluetoothManager,再通过BluetoothManager获取BluetoothAdapter。BluetoothManager在Android43以上支持(API level 18)。
2、判断是否支持蓝牙,并打开蓝牙
获取到BluetoothAdapter之后,还需要判断是否支持蓝牙,以及蓝牙是否打开。
如果没打开,需要让用户打开蓝牙:
private BluetoothAdapter mBluetoothAdapter;
// Ensures Bluetooth is available on the device and it is enabled If not,
// displays a dialog requesting user permission to enable Bluetooth
if (mBluetoothAdapter == null || !mBluetoothAdapterisEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapterACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
五、搜索BLE设备:
通过调用BluetoothAdapter的startLeScan()搜索BLE设备。调用此方法时需要传入 BluetoothAdapterLeScanCallback参数。
因此你需要实现 BluetoothAdapterLeScanCallback接口,BLE设备的搜索结果将通过这个callback返回。
由于搜索需要尽量减少功耗,因此在实际使用时需要注意:
1、当找到对应的设备后,立即停止扫描;
2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。
搜索的示例代码如下:
/
Activity for scanning and displaying available BLE devices
/
public class DeviceScanActivity extends ListActivity {
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
// Stops scanning after 10 seconds
private static final long SCAN_PERIOD = 10000;
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period
mHandlerpostDelayed(new Runnable() {
@Override
public void run() {
mScanning = false;
mBluetoothAdapterstopLeScan(mLeScanCallback);
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapterstartLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapterstopLeScan(mLeScanCallback);
}
}
}
如果你只需要搜索指定UUID的外设,你可以调用 startLeScan(UUID[], BluetoothAdapterLeScanCallback)方法。
其中UUID数组指定你的应用程序所支持的GATT Services的UUID。
BluetoothAdapterLeScanCallback的实现示例如下:
private LeDeviceListAdapter mLeDeviceListAdapter;
// Device scan callback
private BluetoothAdapterLeScanCallback mLeScanCallback =
new BluetoothAdapterLeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mLeDeviceListAdapteraddDevice(device);
mLeDeviceListAdapternotifyDataSetChanged();
}
});
}
};
注意:搜索时,你只能搜索传统蓝牙设备或者BLE设备,两者完全独立,不可同时被搜索。
六、连接GATT Server:
两个设备通过BLE通信,首先需要建立GATT连接。这里我们讲的是Android设备作为client端,连接GATT Server。
连接GATT Server,你需要调用BluetoothDevice的connectGatt()方法。此函数带三个参数:Context、autoConnect(boolean)和BluetoothGattCallback对象。调用示例:
mBluetoothGatt = deviceconnectGatt(this, false, mGattCallback);
函数成功,返回BluetoothGatt对象,它是GATT profile的封装。通过这个对象,我们就能进行GATT Client端的相关 *** 作。BluetoothGattCallback用于传递一些连接状态及结果。
BluetoothGatt常规用到的几个 *** 作示例:
connect() :连接远程设备。
discoverServices() : 搜索连接设备所支持的service。
disconnect():断开与远程设备的GATT连接。
close():关闭GATT Client端。
readCharacteristic(characteristic) :读取指定的characteristic。
setCharacteristicNotification(characteristic, enabled) :设置当指定characteristic值变化时,发出通知。
getServices() :获取远程设备所支持的services。
等等。
注:
1、某些函数调用之间存在先后关系。例如首先需要connect上才能discoverServices。
2、 一些函数调用是异步的,需要得到的值不会立即返回,而会在BluetoothGattCallback的回调函数中返回。例如 discoverServices与onServicesDiscovered回调,readCharacteristic与 onCharacteristicRead回调,setCharacteristicNotification与 onCharacteristicChanged回调等。
Generic Attribute Profile (GATT)
通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。
Attribute Protocol (ATT)
GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。
Characteristic
Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。
Descriptor
对Characteristic的描述,例如范围、计量单位等。
Service
Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement"的Characteristic。
二、角色和职责:
Android设备与BLE设备交互有两组角色:
中心设备和外围设备(Central vs peripheral);
GATT server vs GATT client
Central vs peripheral:
中心设备和外围设备的概念针对的是BLE连接本身。Central角色负责scan advertisement。而peripheral角色负责make advertisement。
GATT server vs GATT client:
这两种角色取决于BLE连接成功后,两个设备间通信的方式。
举例说明:
现 有一个活动追踪的BLE设备和一个支持BLE的Android设备。Android设备支持Central角色,而BLE设备支持peripheral角 色。创建一个BLE连接需要这两个角色都存在,都仅支持Central角色或者都仅支持peripheral角色则无法建立连接。
当 连接建立后,它们之间就需要传输GATT数据。谁做server,谁做client,则取决于具体数据传输的情况。例如,如果活动追踪的BLE设备需要向 Android设备传输sensor数据,则活动追踪器自然成为了server端;而如果活动追踪器需要从Android设备获取更新信息,则 Android设备作为server端可能更合适。
三、权限及feature:
和经典蓝牙一样,应用使用蓝牙,需要声明BLUETOOTH权限,如果需要扫描设备或者 *** 作蓝牙设置,则还需要BLUETOOTH_ADMIN权限:
<uses-permission android:name="androidpermissionBLUETOOTH"/>
<uses-permission android:name="androidpermissionBLUETOOTH_ADMIN"/>
除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature:
<uses-feature android:name="androidhardwarebluetooth_le" android:required="true"/>
按时required为true时,则应用只能在支持BLE的Android设备上安装运行;required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE feature:
// Use this check to determine whether BLE is supported on the device Then
// you can selectively disable BLE-related features
if (!getPackageManager()hasSystemFeature(PackageManagerFEATURE_BLUETOOTH_LE)) {
ToastmakeText(this, Rstringble_not_supported, ToastLENGTH_SHORT)show();
finish();
}
四、启动蓝牙:
在使用蓝牙BLE之前,需要确认Android设备是否支持BLE feature(required为false时),另外要需要确认蓝牙是否打开。
如果发现不支持BLE,则不能使用BLE相关的功能。如果支持BLE,但是蓝牙没打开,则需要打开蓝牙。
打开蓝牙的步骤:
1、获取BluetoothAdapter
BluetoothAdapter是Android系统中所有蓝牙 *** 作都需要的,它对应本地Android设备的蓝牙模块,在整个系统中BluetoothAdapter是单例的。当你获取到它的示例之后,就能进行相关的蓝牙 *** 作了。
获取BluetoothAdapter代码示例如下:
// Initializes Bluetooth adapter
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(ContextBLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManagergetAdapter();
注:这里通过getSystemService获取BluetoothManager,再通过BluetoothManager获取BluetoothAdapter。BluetoothManager在Android43以上支持(API level 18)。
2、判断是否支持蓝牙,并打开蓝牙
获取到BluetoothAdapter之后,还需要判断是否支持蓝牙,以及蓝牙是否打开。
如果没打开,需要让用户打开蓝牙:
private BluetoothAdapter mBluetoothAdapter;
// Ensures Bluetooth is available on the device and it is enabled If not,
// displays a dialog requesting user permission to enable Bluetooth
if (mBluetoothAdapter == null || !mBluetoothAdapterisEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapterACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
五、搜索BLE设备:
通过调用BluetoothAdapter的startLeScan()搜索BLE设备。调用此方法时需要传入 BluetoothAdapterLeScanCallback参数。
因此你需要实现 BluetoothAdapterLeScanCallback接口,BLE设备的搜索结果将通过这个callback返回。
由于搜索需要尽量减少功耗,因此在实际使用时需要注意:
1、当找到对应的设备后,立即停止扫描;
2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。
搜索的示例代码如下:
/
Activity for scanning and displaying available BLE devices
/
public class DeviceScanActivity extends ListActivity {
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
// Stops scanning after 10 seconds
private static final long SCAN_PERIOD = 10000;
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period
mHandlerpostDelayed(new Runnable() {
@Override
public void run() {
mScanning = false;
mBluetoothAdapterstopLeScan(mLeScanCallback);
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapterstartLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapterstopLeScan(mLeScanCallback);
}
}
}
如果你只需要搜索指定UUID的外设,你可以调用 startLeScan(UUID[], BluetoothAdapterLeScanCallback)方法。
其中UUID数组指定你的应用程序所支持的GATT Services的UUID。
BluetoothAdapterLeScanCallback的实现示例如下:
private LeDeviceListAdapter mLeDeviceListAdapter;
// Device scan callback
private BluetoothAdapterLeScanCallback mLeScanCallback =
new BluetoothAdapterLeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mLeDeviceListAdapteraddDevice(device);
mLeDeviceListAdapternotifyDataSetChanged();
}
});
}
};
注意:搜索时,你只能搜索传统蓝牙设备或者BLE设备,两者完全独立,不可同时被搜索。
六、连接GATT Server:
两个设备通过BLE通信,首先需要建立GATT连接。这里我们讲的是Android设备作为client端,连接GATT Server。
连接GATT Server,你需要调用BluetoothDevice的connectGatt()方法。此函数带三个参数:Context、autoConnect(boolean)和BluetoothGattCallback对象。调用示例:
mBluetoothGatt = deviceconnectGatt(this, false, mGattCallback);
函数成功,返回BluetoothGatt对象,它是GATT profile的封装。通过这个对象,我们就能进行GATT Client端的相关 *** 作。BluetoothGattCallback用于传递一些连接状态及结果。
BluetoothGatt常规用到的几个 *** 作示例:
connect() :连接远程设备。
discoverServices() : 搜索连接设备所支持的service。
disconnect():断开与远程设备的GATT连接。
close():关闭GATT Client端。
readCharacteristic(characteristic) :读取指定的characteristic。
setCharacteristicNotification(characteristic, enabled) :设置当指定characteristic值变化时,发出通知。
getServices() :获取远程设备所支持的services。
等等。
注:
1、某些函数调用之间存在先后关系。例如首先需要connect上才能discoverServices。
2、 一些函数调用是异步的,需要得到的值不会立即返回,而会在BluetoothGattCallback的回调函数中返回。例如 discoverServices与onServicesDiscovered回调,readCharacteristic与 onCharacteristicRead回调,setCharacteristicNotification与 onCharacteristicChanged回调等。
以上就是关于linux下管理蓝牙设备 – 编程哪些事全部的内容,包括:linux下管理蓝牙设备 – 编程哪些事、android ble4.0 怎么获取 dbm、android ble搜到一个蓝牙怎么跟特征值通信的等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)