如何连接到 arduino 并在 android 应用程序中查看服务?
How to connect to arduino and view services within android app?
我目前正在使用 Arduino Nano 33 BLE 计算来自 IMU 的角度测量值,并将这些值添加到服务中的蓝牙特征中。我使用 ArduinoBLE 库创建服务和特征:
BLEService angleService("1826");
BLEFloatCharacteristic rollBLE("2A57", BLERead | BLENotify);
在我的设置中,我设置了设备的名称、服务和特征。我最初将值 0 写入特征:
BLE.setLocalName("acsAssist");
BLE.setAdvertisedService(angleService);
angleService.addCharacteristic(rollBLE);
BLE.addService(angleService);
rollBLE.writeValue(0);
BLE.advertise();
在我的循环中,在执行计算后,我相应地更改了特征值:
rollBLE.writeValue(posiRoll); // posiRoll is my calculation
当我在 Android 设备上使用 nrfConnect 等第三方应用程序时,我能够找到我的设备并连接到它。我定义的服务和特征存在并且值按预期变化:
Here is the output from the nrfConnect app
现在,我正尝试在我正在构建的 Android 应用程序中手动连接到此设备,以便我可以在屏幕上显示此变化的值以供用户查看。我在清单中包含以下所有权限:
<uses-feature android:name="android.hardware.bluetooth" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
我首先检查用户使用的设备是否有蓝牙适配器,并且它已打开:
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) { // Bluetooth not supported
Toast.makeText(getActivity(), "This device does not support Bluetooth! Use a Bluetooth enabled device.", Toast.LENGTH_LONG).show();
}
if (!bluetoothAdapter.isEnabled()) { // If adapter is not enabled, request to enable it from within the app
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
因为我知道 arduino 的 MAC 地址,所以我尝试使用该 MAC 地址获取设备。当我这样做时,我能够查看设备名称和地址等属性。但是,当我尝试查看 arduino 的 UUID 时,我收到 'null'。以下代码:
BluetoothDevice arduino = bluetoothAdapter.getRemoteDevice("E5:A5:53:32:BD:7C");
Log.i("DEVICES", String.valueOf(arduino.getName()));
Log.i("DEVICES", String.valueOf(arduino.getAddress()));
Log.i("DEVICES", String.valueOf(arduino.getUuids()));
在 logcat 中生成结果输出:
02-11 12:09:02.862 29503-29503/com.seniorproject.acsAssistApp I/DEVICES: acsAssist
02-11 12:09:02.862 29503-29503/com.seniorproject.acsAssistApp I/DEVICES: E5:A5:53:32:BD:7C
02-11 12:09:02.868 29503-29503/com.seniorproject.acsAssistApp I/DEVICES: null
我一直在尝试弄清楚如何将我的应用程序连接到 arduino 并查看我创建的服务,但我不知道该怎么做。我试图找到的所有与此相关的指南、问答和文档都让我感到绝望和困惑。任何有关如何执行此操作的指导将不胜感激。
PS:如果我提交的格式不正确,我深表歉意。这是我第一次在 Stack Overflow 上提交问题。我也是 Arduino 和 Android 开发的 完全新手 。
我找到了解决困难的方法。我使情况过于复杂了;相反,我决定利用我的实现的 GATT 属性。首先,我通过 MAC 地址获取适配器和 arduino。
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice arduino = bluetoothAdapter.getRemoteDevice("E5:A5:53:32:BD:7C");
准备好后,我连接到 arduino:
arduino.connectGatt(this.getActivity(), true, gattCallback);
我实施我的 GATT 回调:
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
final TextView instructionText = getView().findViewById(R.id.instructionText);
Log.i("DEVICES", "Status: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
Log.i("DEVICES", "STATE_CONNECTED");
instructionText.setText("Connected. Select Exercise");
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.i("DEVICES", "STATE_DISCONNECTED");
instructionText.setText("acsAssist Disconnected");
break;
case BluetoothProfile.STATE_CONNECTING:
Log.i("DEVICES", "CONNECTING");
instructionText.setText("Connecting to acsAssist...");
break;
default:
Log.i("DEVICES", "STATE_OTHER");
instructionText.setText("acsAssist Disconnected");
}
}
我执行我想要的服务发现操作:
@Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.i("DEVICES", "Services Found");
for (BluetoothGattService service: gatt.getServices()) {
Log.i("DEVICES", service.getUuid().toString());
}
for (BluetoothGattCharacteristic characteristic: gatt.getService(UUID.fromString("00001826-0000-1000-8000-00805f9b34fb")).getCharacteristics()) {
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
// descriptor.setValue(true ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : new byte[]{0x00, 0x00});
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
}
我实现了对特征的读取,特别是当它通过 onCharacteristicChanged
更改时,我可以监控它
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
//super.onCharacteristicRead(gatt, characteristic, status);
//gatt.setCharacteristicNotification(characteristic, true);
Float tester = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT,1);
Log.i("UUID", String.valueOf(tester));
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
TextView instructionText = getView().findViewById(R.id.instructionText);
instructionText.setText(String.valueOf(characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT,1)));
}
我目前正在使用 Arduino Nano 33 BLE 计算来自 IMU 的角度测量值,并将这些值添加到服务中的蓝牙特征中。我使用 ArduinoBLE 库创建服务和特征:
BLEService angleService("1826");
BLEFloatCharacteristic rollBLE("2A57", BLERead | BLENotify);
在我的设置中,我设置了设备的名称、服务和特征。我最初将值 0 写入特征:
BLE.setLocalName("acsAssist");
BLE.setAdvertisedService(angleService);
angleService.addCharacteristic(rollBLE);
BLE.addService(angleService);
rollBLE.writeValue(0);
BLE.advertise();
在我的循环中,在执行计算后,我相应地更改了特征值:
rollBLE.writeValue(posiRoll); // posiRoll is my calculation
当我在 Android 设备上使用 nrfConnect 等第三方应用程序时,我能够找到我的设备并连接到它。我定义的服务和特征存在并且值按预期变化:
Here is the output from the nrfConnect app
现在,我正尝试在我正在构建的 Android 应用程序中手动连接到此设备,以便我可以在屏幕上显示此变化的值以供用户查看。我在清单中包含以下所有权限:
<uses-feature android:name="android.hardware.bluetooth" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
我首先检查用户使用的设备是否有蓝牙适配器,并且它已打开:
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) { // Bluetooth not supported
Toast.makeText(getActivity(), "This device does not support Bluetooth! Use a Bluetooth enabled device.", Toast.LENGTH_LONG).show();
}
if (!bluetoothAdapter.isEnabled()) { // If adapter is not enabled, request to enable it from within the app
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
因为我知道 arduino 的 MAC 地址,所以我尝试使用该 MAC 地址获取设备。当我这样做时,我能够查看设备名称和地址等属性。但是,当我尝试查看 arduino 的 UUID 时,我收到 'null'。以下代码:
BluetoothDevice arduino = bluetoothAdapter.getRemoteDevice("E5:A5:53:32:BD:7C");
Log.i("DEVICES", String.valueOf(arduino.getName()));
Log.i("DEVICES", String.valueOf(arduino.getAddress()));
Log.i("DEVICES", String.valueOf(arduino.getUuids()));
在 logcat 中生成结果输出:
02-11 12:09:02.862 29503-29503/com.seniorproject.acsAssistApp I/DEVICES: acsAssist
02-11 12:09:02.862 29503-29503/com.seniorproject.acsAssistApp I/DEVICES: E5:A5:53:32:BD:7C
02-11 12:09:02.868 29503-29503/com.seniorproject.acsAssistApp I/DEVICES: null
我一直在尝试弄清楚如何将我的应用程序连接到 arduino 并查看我创建的服务,但我不知道该怎么做。我试图找到的所有与此相关的指南、问答和文档都让我感到绝望和困惑。任何有关如何执行此操作的指导将不胜感激。
PS:如果我提交的格式不正确,我深表歉意。这是我第一次在 Stack Overflow 上提交问题。我也是 Arduino 和 Android 开发的 完全新手 。
我找到了解决困难的方法。我使情况过于复杂了;相反,我决定利用我的实现的 GATT 属性。首先,我通过 MAC 地址获取适配器和 arduino。
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice arduino = bluetoothAdapter.getRemoteDevice("E5:A5:53:32:BD:7C");
准备好后,我连接到 arduino:
arduino.connectGatt(this.getActivity(), true, gattCallback);
我实施我的 GATT 回调:
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
final TextView instructionText = getView().findViewById(R.id.instructionText);
Log.i("DEVICES", "Status: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
Log.i("DEVICES", "STATE_CONNECTED");
instructionText.setText("Connected. Select Exercise");
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.i("DEVICES", "STATE_DISCONNECTED");
instructionText.setText("acsAssist Disconnected");
break;
case BluetoothProfile.STATE_CONNECTING:
Log.i("DEVICES", "CONNECTING");
instructionText.setText("Connecting to acsAssist...");
break;
default:
Log.i("DEVICES", "STATE_OTHER");
instructionText.setText("acsAssist Disconnected");
}
}
我执行我想要的服务发现操作:
@Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.i("DEVICES", "Services Found");
for (BluetoothGattService service: gatt.getServices()) {
Log.i("DEVICES", service.getUuid().toString());
}
for (BluetoothGattCharacteristic characteristic: gatt.getService(UUID.fromString("00001826-0000-1000-8000-00805f9b34fb")).getCharacteristics()) {
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
// descriptor.setValue(true ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : new byte[]{0x00, 0x00});
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
}
我实现了对特征的读取,特别是当它通过 onCharacteristicChanged
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
//super.onCharacteristicRead(gatt, characteristic, status);
//gatt.setCharacteristicNotification(characteristic, true);
Float tester = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT,1);
Log.i("UUID", String.valueOf(tester));
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
TextView instructionText = getView().findViewById(R.id.instructionText);
instructionText.setText(String.valueOf(characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_SFLOAT,1)));
}