我正在尝试通过蓝牙LE从连接到nRF8001的Arduino Mefa 2560发送数据到我的Android应用程序。我已经设法在Android sid上找到了特性,但我没有得到通知。
对于Arduino方面,我使用了一个我发现多次的代码片段并稍微改了一下,所以它正在计算并发送每五个数字:
#include <SPI.h>
#include "Adafruit_BLE_UART.h"
#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RDY 2
#define ADAFRUITBLE_RST 9
Adafruit_BLE_UART BTLEserial = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
int value = 0;
void setup(void)
{
Serial.begin(9600);
while(!Serial);
BTLEserial.setDeviceName("MEGA1"); /* 7 characters max! */
BTLEserial.begin();
}
aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;
void loop()
{
BTLEserial.pollACI();
aci_evt_opcode_t status = BTLEserial.getState();
if (status != laststatus) {
if (status == ACI_EVT_DEVICE_STARTED) {
Serial.println(F("* Advertising started"));
}
if (status == ACI_EVT_CONNECTED) {
Serial.println(F("* Connected!"));
}
if (status == ACI_EVT_DISCONNECTED) {
Serial.println(F("* Disconnected or advertising timed out"));
}
laststatus = status;
}
if (status == ACI_EVT_CONNECTED) {
value = value+1;
String s = String(value);
uint8_t sendbuffer[20];
s.getBytes(sendbuffer, 20);
char sendbuffersize = min(20, s.length());
Serial.print(F("\n* Sending -> \"")); Serial.print((char *)sendbuffer); Serial.println("\"");
if (value %5 == 0) {
BTLEserial.write(sendbuffer, sendbuffersize);
Serial.println(F("* wrote"));
} else {
Serial.println(F("* filtered"));
}
delay(1000);
}
}
我也没有问题,用像BluefruitLE这样的应用程序阅读预期的数字。
对于Android方面,我使用了this教程并稍微改了一下,所以我的代码如下所示:
public class MainActivity extends Activity{
private static final String TAG = "MyBLEApplication";
private BluetoothAdapter mBluetoothAdapter;
private int REQUEST_ENABLE_BT = 1;
private Handler mHandler;
private static final long SCAN_PERIOD = 10000;
private BluetoothLeScanner mLEScanner;
private BluetoothGatt mGatt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler();
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();
}
@Override
protected void onResume() {
super.onResume();
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
scanLeDevice(true);
}
}
@Override
protected void onPause() {
super.onPause();
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
scanLeDevice(false);
}
}
@Override
protected void onDestroy() {
if (mGatt == null) {
return;
}
mGatt.close();
mGatt = null;
super.onDestroy();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == Activity.RESULT_CANCELED) {
//Bluetooth not enabled.
finish();
return;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mLEScanner.stopScan(mScanCallback);
}
}, SCAN_PERIOD);
mLEScanner.startScan(mScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i(TAG, "callbackType: " + String.valueOf(callbackType));
Log.i(TAG, "result: " + result.toString());
BluetoothDevice btDevice = result.getDevice();
connectToDevice(btDevice);
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
Log.i(TAG, "ScanResult - Results: " + sr.toString());
}
}
@Override
public void onScanFailed(int errorCode) {
Log.e(TAG, "San failed, Error Code: " + errorCode);
}
};
public void connectToDevice(BluetoothDevice device) {
if (mGatt == null && device.getName() != null && device.getName().equals("MEGA1")) {
mGatt = device.connectGatt(this, false, gattCallback);
scanLeDevice(false);// will stop after first device detection
}
}
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i(TAG, "ConnectionState: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
Log.i(TAG, "STATE_CONNECTED");
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.e(TAG, "STATE_DISCONNECTED");
break;
default:
Log.e(TAG, "STATE_OTHER");
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
List<BluetoothGattService> services = gatt.getServices();
Log.i(TAG, "Services discovered: " + services.toString());
for (BluetoothGattService service : services){
if (service.getUuid().equals(UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E"))){
for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()){
if (characteristic.getUuid().equals(UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"))){
Log.i(TAG, "set notification for characteristic");
gatt.setCharacteristicNotification(characteristic, true);
}
}
}
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic){
Log.i(TAG, "got notified");
}
};
}
我现在的问题是,我找到了设备,UART服务和特性,但是onCharacteristicChanged没有被调用,所以我的Android Monitor看起来像这样:
I/MyBLEApplication: callbackType: 1
I/MyBLEApplication: result: ScanResult{mDevice=XX:XX:XX:XX:XX:XX, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[6e400001-b5a3-f393-e0a9-e50e24dcca9e], mManufacturerSpecificData={}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=MEGA1], mRssi=-26, mTimestampNanos=1262117579287571}
I/MyBLEApplication: callbackType: 1
I/MyBLEApplication: result: ScanResult{mDevice=XX:XX:XX:XX:XX:XX, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[6e400001-b5a3-f393-e0a9-e50e24dcca9e], mManufacturerSpecificData={}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=MEGA1], mRssi=-26, mTimestampNanos=1262117665316624}
I/MyBLEApplication: ConnectionState: 0
I/MyBLEApplication: STATE_CONNECTED
I/MyBLEApplication: Services discovered: [android.bluetooth.BluetoothGattService@340653e, android.bluetooth.BluetoothGattService@d382f9f, android.bluetooth.BluetoothGattService@3368e8ec, android.bluetooth.BluetoothGattService@2d2b44b5]
I/MyBLEApplication: set notification for characteristic
Arduino的串行监视器也会显示:
* Advertising started
* Connected!
* Sending -> "1"
* filtered
* Sending -> "2"
* filtered
* Sending -> "3"
* filtered
* Sending -> "4"
* filtered
* Sending -> "5"
所以程序在发送的第一个值之后就会卡住。
任何解决方案,我做错了什么以及如何让它发挥作用?