通过蓝牙LE从Arduino Mega发送数据到Android应用

时间:2017-05-11 12:23:32

标签: android arduino bluetooth-lowenergy

我正在尝试通过蓝牙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"

所以程序在发送的第一个值之后就会卡住。

任何解决方案,我做错了什么以及如何让它发挥作用?

0 个答案:

没有答案