如何读取我的 BLE 设备的所有特征值?
How can read all characteristic's value of my BLE device?
我正在使用 Android Studio 构建一个可以从设备 BLE 读取值的应用程序。这个设备,有4个服务。第四个服务有3个特点。
我想阅读这第四个服务的所有特性。
这个设备,可以发送更多信息,所以我希望应用程序可以存储从设备 BLE 到达的所有信息。
所以这是我的代码:
@TargetApi(21)
public class BLEActivity extends BaseActivity {
private BluetoothAdapter mBluetoothAdapter;
private int REQUEST_ENABLE_BT = 1;
private Handler mHandler;
private static final long SCAN_PERIOD = 10000;
private BluetoothLeScanner mLEScanner;
private ScanSettings settings;
private List<ScanFilter> filters;
private BluetoothGatt mGatt;
String mCurrentService;
TextView tvBLE;
ImageButton ibDownload;
BluetoothDevice currDevice;
private int id = 1000;
public SensorDataAdapter adapter;
final BLEActivity classe = this;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ble);
mHandler = new Handler();
//mSensors = db.getAllSensorTypes();
//BLUETOOTH LOW ENERGY NON SUPPORTATO
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "BLE Not Supported",
Toast.LENGTH_SHORT).show();
finish();
}
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
//VERIFICO SE IL BLUETOOTH DEL DISPOSITIVO E' ABILITATO
//OPPURE NO. SE NON è ABILITATO DEVO CHIEDERE ALL'UTENTE DI ATTIVARLO
// Ensures Bluetooth is available on the device and it is enabled. If not,
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
ibDownload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(currDevice!=null){
mGatt = currDevice.connectGatt(getBaseContext(), false, gattCallback);
scanLeDevice(false);// will stop after first device detection
}
}
});
}
private void scanLeDevice(final boolean enable) {
if (enable) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}, SCAN_PERIOD);
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mLEScanner.startScan(filters, settings, mScanCallback);
}
} else {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i("callbackType", String.valueOf(callbackType));
Log.i("result", result.toString());
BluetoothDevice btDevice = result.getDevice();
connectToDevice(btDevice);
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
Log.i("ScanResult - Results", sr.toString());
}
}
@Override
public void onScanFailed(int errorCode) {
Log.e("Scan Failed", "Error Code: " + errorCode);
}
};
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("onLeScan", device.toString());
connectToDevice(device);
}
});
}
};
public void connectToDevice(BluetoothDevice device) {
if (mGatt == null) {
currDevice = device;
ibDownload.setEnabled(true);
ibDownload.setImageResource(R.drawable.download_ok);
}
}
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i("onConnectionStateChange", "Status: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
Log.i("gattCallback", "STATE_CONNECTED");
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.e("gattCallback", "STATE_DISCONNECTED");
break;
default:
Log.e("gattCallback", "STATE_OTHER");
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
List<BluetoothGattService> services = gatt.getServices();
Log.i("onServicesDiscovered", services.toString());
;
for(BluetoothGattService srv : services){
// if(srv.getUuid().toString().equals(mSensors.get(1).getServUid())){
mCurrentService = srv.getUuid().toString();
//RECUPERO SOLO IL SERVIZIO CON UID 1130
if(mCurrentService.contains("1130")){
List<BluetoothGattCharacteristic> mListCars = srv.getCharacteristics();
//leggo le caratteristiche del servizio che cerco
for(BluetoothGattCharacteristic bc : mListCars){
//recupero solo le caratteristiche 1131, 1132
if(bc.getUuid().toString().contains("1131") ||
bc.getUuid().toString().contains("1132")){
//LEGGO LE 2 CARATTERISTICHE NECESSARIE
gatt.readCharacteristic(srv.getCharacteristic(bc.getUuid()));
}
}
}else{
Log.i("SERVIZIO NON CORRETTO", "SERVIZIO NON CORRETTO");
}
// }
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic
characteristic, int status) {
Log.i("onCharacteristicRead", characteristic.toString());
SensorData mSenData = new SensorData();
mSenData.setValue(characteristic.getStringValue(0));
Log.i("LETTURA DATI ", mSenData.getValue());
mSenData.setIdType(++id);
mSenData.setCharacteristic(characteristic.getUuid().toString());
mSenData.setValueTimestamp(db.getDateTime());
db.insertSensorData(mSenData);
}
};
}
使用此代码,我可以读取服务的第一个特征,并且只能读取第一个特征的一个值。
我想自动读取我的 BLE 设备所有特性的所有值。
我怎样才能更改我的代码来执行此操作?
首先存储你的读取特征,以及 ghatt 对象。
如果您想从特征中读取值,请调用此方法:
private fun readDataFromCharacteristic(ghatt: BluetoothGhatt? , characteristic:BluetoothGhattCharacteristic) {
Log.d(TAG, " readDataFromCharacteristic")
ghatt?.readCharacteristic(characteristic)
}
如果您在 ghatt 上调用 readCharacteristic(characteristic),下面的方法将给出结果
override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {}
您可以通过以下代码实现多次读取:
首先创建一个列表
private int ReadQueueIndex;
private List<BluetoothGattCharacteristic> ReadQueue;
在onServicesDiscovered
ReadQueue中添加特性:
ReadQueue = new ArrayList<>();
ReadQueue.add(characteristicsList.get(2));
ReadQueue.add(characteristicsList.get(1));
ReadQueue.add(characteristicsList.get(0));
ReadQueueIndex = 2;
ReadCharacteristics(ReadQueueIndex);
创建ReadCharacteristics
方法
private void ReadCharacteristics(int index){
bluetoothGatt.readCharacteristic(ReadQueue.get(index));
}
然后在您的 onCharacteristicRead
回调中:
String value = Arrays.toString(characteristic.getValue());
if(characteristic.getUuid().equals(characteristicsList.get(0).getUuid())){
Log.i("Characteristic 0:", value);
} else if(characteristic.getUuid().equals(characteristicsList.get(1).getUuid())){
Log.i("Characteristic 1:", value);
} else if(characteristic.getUuid().equals(characteristicsList.get(2).getUuid())){
Log.i("Characteristic 2:", value);
}
ReadQueue.remove(ReadQueue.get(ReadQueueIndex));
if (ReadQueue.size() >= 0) {
ReadQueueIndex--;
if (ReadQueueIndex == -1) {
Log.i("Read Queue: ", "Complete");
}
else {
ReadCharacteristics(ReadQueueIndex);
}
}
希望对您有所帮助。
您不应该阅读 onServicesDiscovered 方法中的整个特征列表,因为设备可能没有时间执行来自 android 个客户端的所有请求。
我给你:
- 在 onServicesDiscovered 中保留所有特征
- 轮流尝试在 onCharacteristicRead 方法中读取特征(首先读取第一个特征,读取完特征后,尝试读取第二个特征,然后...)
我正在使用 Android Studio 构建一个可以从设备 BLE 读取值的应用程序。这个设备,有4个服务。第四个服务有3个特点。 我想阅读这第四个服务的所有特性。
这个设备,可以发送更多信息,所以我希望应用程序可以存储从设备 BLE 到达的所有信息。
所以这是我的代码:
@TargetApi(21)
public class BLEActivity extends BaseActivity {
private BluetoothAdapter mBluetoothAdapter;
private int REQUEST_ENABLE_BT = 1;
private Handler mHandler;
private static final long SCAN_PERIOD = 10000;
private BluetoothLeScanner mLEScanner;
private ScanSettings settings;
private List<ScanFilter> filters;
private BluetoothGatt mGatt;
String mCurrentService;
TextView tvBLE;
ImageButton ibDownload;
BluetoothDevice currDevice;
private int id = 1000;
public SensorDataAdapter adapter;
final BLEActivity classe = this;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ble);
mHandler = new Handler();
//mSensors = db.getAllSensorTypes();
//BLUETOOTH LOW ENERGY NON SUPPORTATO
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "BLE Not Supported",
Toast.LENGTH_SHORT).show();
finish();
}
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
//VERIFICO SE IL BLUETOOTH DEL DISPOSITIVO E' ABILITATO
//OPPURE NO. SE NON è ABILITATO DEVO CHIEDERE ALL'UTENTE DI ATTIVARLO
// Ensures Bluetooth is available on the device and it is enabled. If not,
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
ibDownload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(currDevice!=null){
mGatt = currDevice.connectGatt(getBaseContext(), false, gattCallback);
scanLeDevice(false);// will stop after first device detection
}
}
});
}
private void scanLeDevice(final boolean enable) {
if (enable) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}, SCAN_PERIOD);
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mLEScanner.startScan(filters, settings, mScanCallback);
}
} else {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i("callbackType", String.valueOf(callbackType));
Log.i("result", result.toString());
BluetoothDevice btDevice = result.getDevice();
connectToDevice(btDevice);
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
Log.i("ScanResult - Results", sr.toString());
}
}
@Override
public void onScanFailed(int errorCode) {
Log.e("Scan Failed", "Error Code: " + errorCode);
}
};
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("onLeScan", device.toString());
connectToDevice(device);
}
});
}
};
public void connectToDevice(BluetoothDevice device) {
if (mGatt == null) {
currDevice = device;
ibDownload.setEnabled(true);
ibDownload.setImageResource(R.drawable.download_ok);
}
}
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i("onConnectionStateChange", "Status: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
Log.i("gattCallback", "STATE_CONNECTED");
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.e("gattCallback", "STATE_DISCONNECTED");
break;
default:
Log.e("gattCallback", "STATE_OTHER");
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
List<BluetoothGattService> services = gatt.getServices();
Log.i("onServicesDiscovered", services.toString());
;
for(BluetoothGattService srv : services){
// if(srv.getUuid().toString().equals(mSensors.get(1).getServUid())){
mCurrentService = srv.getUuid().toString();
//RECUPERO SOLO IL SERVIZIO CON UID 1130
if(mCurrentService.contains("1130")){
List<BluetoothGattCharacteristic> mListCars = srv.getCharacteristics();
//leggo le caratteristiche del servizio che cerco
for(BluetoothGattCharacteristic bc : mListCars){
//recupero solo le caratteristiche 1131, 1132
if(bc.getUuid().toString().contains("1131") ||
bc.getUuid().toString().contains("1132")){
//LEGGO LE 2 CARATTERISTICHE NECESSARIE
gatt.readCharacteristic(srv.getCharacteristic(bc.getUuid()));
}
}
}else{
Log.i("SERVIZIO NON CORRETTO", "SERVIZIO NON CORRETTO");
}
// }
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic
characteristic, int status) {
Log.i("onCharacteristicRead", characteristic.toString());
SensorData mSenData = new SensorData();
mSenData.setValue(characteristic.getStringValue(0));
Log.i("LETTURA DATI ", mSenData.getValue());
mSenData.setIdType(++id);
mSenData.setCharacteristic(characteristic.getUuid().toString());
mSenData.setValueTimestamp(db.getDateTime());
db.insertSensorData(mSenData);
}
};
}
使用此代码,我可以读取服务的第一个特征,并且只能读取第一个特征的一个值。
我想自动读取我的 BLE 设备所有特性的所有值。 我怎样才能更改我的代码来执行此操作?
首先存储你的读取特征,以及 ghatt 对象。 如果您想从特征中读取值,请调用此方法:
private fun readDataFromCharacteristic(ghatt: BluetoothGhatt? , characteristic:BluetoothGhattCharacteristic) {
Log.d(TAG, " readDataFromCharacteristic")
ghatt?.readCharacteristic(characteristic)
}
如果您在 ghatt 上调用 readCharacteristic(characteristic),下面的方法将给出结果
override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {}
您可以通过以下代码实现多次读取: 首先创建一个列表
private int ReadQueueIndex;
private List<BluetoothGattCharacteristic> ReadQueue;
在onServicesDiscovered
ReadQueue中添加特性:
ReadQueue = new ArrayList<>();
ReadQueue.add(characteristicsList.get(2));
ReadQueue.add(characteristicsList.get(1));
ReadQueue.add(characteristicsList.get(0));
ReadQueueIndex = 2;
ReadCharacteristics(ReadQueueIndex);
创建ReadCharacteristics
方法
private void ReadCharacteristics(int index){
bluetoothGatt.readCharacteristic(ReadQueue.get(index));
}
然后在您的 onCharacteristicRead
回调中:
String value = Arrays.toString(characteristic.getValue());
if(characteristic.getUuid().equals(characteristicsList.get(0).getUuid())){
Log.i("Characteristic 0:", value);
} else if(characteristic.getUuid().equals(characteristicsList.get(1).getUuid())){
Log.i("Characteristic 1:", value);
} else if(characteristic.getUuid().equals(characteristicsList.get(2).getUuid())){
Log.i("Characteristic 2:", value);
}
ReadQueue.remove(ReadQueue.get(ReadQueueIndex));
if (ReadQueue.size() >= 0) {
ReadQueueIndex--;
if (ReadQueueIndex == -1) {
Log.i("Read Queue: ", "Complete");
}
else {
ReadCharacteristics(ReadQueueIndex);
}
}
希望对您有所帮助。
您不应该阅读 onServicesDiscovered 方法中的整个特征列表,因为设备可能没有时间执行来自 android 个客户端的所有请求。
我给你:
- 在 onServicesDiscovered 中保留所有特征
- 轮流尝试在 onCharacteristicRead 方法中读取特征(首先读取第一个特征,读取完特征后,尝试读取第二个特征,然后...)