У меня проблемы с подключением и чтением с устройства BLE - PullRequest
1 голос
/ 09 января 2020

Привет. У меня возникли проблемы с подключением и чтением устройств BLE. Я думаю, что я подключился, так как код ниже печатает сообщение для подключения, однако считывание значений с устройства BLE, похоже, не работает. Служба uuid возвращает нулевое значение.

package com.example.asp_sqllite;
import android.Manifest;
import android.app.Dialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelUuid;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.UUID;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class PlayActivity extends AppCompatActivity {
    private static final int REQUEST_ENABLE_BT =1 ;
    private Button btnPlay;
    private Button btnConnect;
    private ListView btList;
    SQLiteDatabase db;

    private Handler handler;

    private ArrayList<String> deviceList = new ArrayList<>();
    private ArrayAdapter<String> testAdapter;
    private ArrayAdapter<String> deviceAdapter;

    private BluetoothAdapter bluetoothAdapter;
    private BluetoothLeScanner bleScanner;
    private BluetoothGatt bleGatt;
    private ArrayList<ScanResult> results = new ArrayList<>();
    private ScanSettings settings;

    private Intent intent;


    private ListView bluetoothList;

    private boolean completed = false;

    static final UUID HR_SERVICE_UUID = UUID.fromString("0000110a-0000-1000-8000-00805f9b34fb");
    private static final UUID HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A37-0000-1000-8000-00805f9b34fb");
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


        setContentView(R.layout.activity_play);

        this.handler= new Handler();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
            checkPermission();
        }
            BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            bluetoothAdapter = bluetoothManager.getAdapter();
            this.btList = (ListView) findViewById(R.id.btlist);
            deviceAdapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, android.R.id.text1);
            testAdapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, android.R.id.text1);
            intent = getIntent();

            db = openOrCreateDatabase("myDB.db", MODE_PRIVATE, null);
            checkBluetooth();


            this.btnPlay = (Button) findViewById(R.id.btnPlay);

            this.btnPlay.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if(bleGatt!=null) {
                        final String username = intent.getStringExtra("username");
                        System.out.println(username+"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                        String sqlStatement = "insert into records (Name) values( '" + username + "')";
                        String result = updateTable(sqlStatement);

                        /*
                         * Run query to get recid to be passed over to the next activity
                         *
                         * */

                        final Cursor cursor = db.rawQuery("SELECT recID From records", null);
                        int num = 0;
                        if (cursor != null) {
                            cursor.moveToLast();
                            num = cursor.getInt(0);
                            cursor.close();
                            db.close();
                        }
                        Intent intent = new Intent(PlayActivity.this, testPlayActivity.class);
                        intent.putExtra("ID", Integer.toString(num));
                        startActivity(intent);
                    }
                    else
                        Toast.makeText(getApplicationContext(),"Connect to BLE device", Toast.LENGTH_LONG).show();
                    //finish();
                }
            });

            this.btnConnect = (Button) findViewById(R.id.connect);
            this.btnConnect.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    startScan();
                    Dialog d = new Dialog(PlayActivity.this); //open up dialog box with listview
                    d.setContentView(R.layout.bluetooth_device);
                    d.setTitle("Devices");
                    d.show();

                    //stopScan();

                    Button scanBtn = d.findViewById(R.id.scanBluetooth);
                    bluetoothList = d.findViewById(R.id.bluetoothDeviceList);
                    bluetoothList.setAdapter(deviceAdapter);
                    bluetoothList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                            ScanResult device = results.get(i);
                            Toast.makeText(getApplicationContext(), device.getDevice().getName(), Toast.LENGTH_LONG).show();
                            bleGatt = device.getDevice().connectGatt(getApplicationContext(), false, bleGattCallback);

                            System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@testing 123");
                            //finish();
                            try {
                                BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
                                Method getUuidsMethod = BluetoothAdapter.class.getDeclaredMethod("getUuids", null);
                                ParcelUuid[] uuids = (ParcelUuid[]) getUuidsMethod.invoke(adapter, null);

                                if(uuids != null) {
                                    for (ParcelUuid uuid : uuids) {
                                        System.out.println(uuid.getUuid().toString()+"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
                                    }
                                }else{
                                    System.out.println("fail");
                                }

                            } catch (NoSuchMethodException e) {
                                e.printStackTrace();
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            }
                        }
                    });

                    scanBtn.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) { //clear all list and adapters before scanning again

                            deviceList.clear();
                            deviceAdapter.clear();
                            results.clear();
                            startScan();
                            //stopScan();

                            handler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    stopScan();
                                }
                            },5000);
                        }
                    });
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            stopScan();
                        }
                    },5000);
                }
            });

    }

    public void checkPermission(){
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
        ){//Can add more as per requirement

            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION},
                    123);
        }
    }



    private void checkBluetooth()
    {
        if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }
    }

    private String updateTable(String sql) {

        try {

            db.beginTransaction();
            db.execSQL(sql);
            db.setTransactionSuccessful();
            db.endTransaction();

        } catch (Exception e) {

            System.out.println(e.toString());
            return ("Error");
        }


        Toast.makeText(this, "DB updated", Toast.LENGTH_LONG).show();
        return ("Welcome");

    }
    private void stopScan(){
        bleScanner = bluetoothAdapter.getBluetoothLeScanner();
        bleScanner.stopScan(scanCallback);
    }
    private void startScan() {
        bleScanner = bluetoothAdapter.getBluetoothLeScanner();
        if (bleScanner != null) { //setting up of scanner
            final ScanFilter scanFilter =new ScanFilter.Builder().build();
            settings =new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
            bleScanner.startScan(Arrays.asList(scanFilter), settings, scanCallback);
            //stopScan();
        }
        else
            checkBluetooth();
    }

    private ScanCallback scanCallback = new ScanCallback() { //scan and return device results
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            System.out.println("@@@@@@@@@ "+callbackType + result);
            if (bleScanner != null && !deviceList.contains(result.getDevice().getName())) {
                deviceList.add(result.getDevice().getName());
                String device = result.getDevice().getName() + "\n" + result.getDevice().getAddress();
                deviceAdapter.add(device); //Store device name and address
                results.add(result); //records found devices as ScanResult
            }

        }
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            Log.e("TAG","onScanFailed");
        }

    };

    private BluetoothGattCallback bleGattCallback = new BluetoothGattCallback()
    {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            if (newState== BluetoothProfile.STATE_CONNECTED){
                System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Connected");


            }
            else if (newState == BluetoothProfile.STATE_DISCONNECTED)
            {
                System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Not Connected");

            }
            gatt.discoverServices();
            super.onConnectionStateChange(gatt, status, newState);
        }
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            BluetoothGattService service = gatt.getService(HR_SERVICE_UUID);
            System.out.println(service+"!!!!!!!!!!!!!!!!!!!!!!");
            BluetoothGattCharacteristic temperatureCharacteristic = service.getCharacteristic(HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID);
            gatt.readCharacteristic(temperatureCharacteristic);
            super.onServicesDiscovered(gatt, status);
        }
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, int status) {
            final String value = characteristic.getStringValue(0);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID.equals(characteristic.getUuid())) {
                        //Toast.makeText(getApplicationContext(), "Correct Bluetooth: " + value, Toast.LENGTH_LONG).show();
                          System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@correct");

                    } else {
                        //Toast.makeText(getApplicationContext(), "Wrong Bluetooth", Toast.LENGTH_LONG).show();
                        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@wrong");
                    }
                }
            });
            BluetoothGattService service = gatt.getService(HR_SERVICE_UUID);
            //readNextCharacteristic(gatt, characteristic);
            super.onCharacteristicRead(gatt, characteristic, status);
        }
    };
}

Код является примером в библиотеке Arduino (BLE_Example / BLE_HRM)

/*
 * Copyright (c) 2016 RedBear
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/**
 * @note This demo is Nordic HRM example.
 *       You could use nRF toolbox tool to test it.
 */
#include <nRF5x_BLE_API.h>

#define DEVICE_NAME       "Nordic_HRM"

BLE                       ble;
Ticker                    ticker_task1;

static uint8_t hrmCounter     = 100;
static uint8_t bpm[2]         = {0x00, hrmCounter};
static const uint8_t location = 0x03;

static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE};

// Create characteristic and service
GattCharacteristic   hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, bpm, sizeof(bpm), sizeof(bpm), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic   hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR,(uint8_t *)&location, sizeof(location), sizeof(location),GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
GattCharacteristic   *hrmChars[] = {&hrmRate, &hrmLocation, };
GattService          hrmService(GattService::UUID_HEART_RATE_SERVICE, hrmChars, sizeof(hrmChars) / sizeof(GattCharacteristic *));


void disconnectionCallBack(const Gap::DisconnectionCallbackParams_t *params) {
  Serial.println("Disconnected!");
  Serial.println("Restarting the advertising process");
  ble.startAdvertising();
}

void periodicCallback() {
  if (ble.getGapState().connected) {
    // Update the HRM measurement
    // First byte = 8-bit values, no extra info, Second byte = uint8_t HRM value
    // See --> https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
    hrmCounter++;
    if (hrmCounter == 175)
        hrmCounter = 100;

    bpm[1] = hrmCounter;
    ble.updateCharacteristicValue(hrmRate.getValueAttribute().getHandle(), bpm, sizeof(bpm));
  }
}

void setup() {
  // put your setup code here, to run once
  Serial.begin(9600);
  Serial.println("Nordic_HRM Demo ");
  // Init timer task
  ticker_task1.attach(periodicCallback, 1);
  // Init ble
  ble.init();
  ble.onDisconnection(disconnectionCallBack);

  // setup adv_data and srp_data
  ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
  ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list));
  ble.accumulateAdvertisingPayload(GapAdvertisingData::HEART_RATE_SENSOR_HEART_RATE_BELT);
  ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
  // set adv_type
  ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    // add service
  ble.addService(hrmService);
  // set device name
  ble.setDeviceName((const uint8_t *)DEVICE_NAME);
  // set tx power,valid values are -40, -20, -16, -12, -8, -4, 0, 4
  ble.setTxPower(4);
  // set adv_interval, 100ms in multiples of 0.625ms.
  ble.setAdvertisingInterval(160);
  // set adv_timeout, in seconds
  ble.setAdvertisingTimeout(0);
  // start advertising
  ble.startAdvertising();
}

void loop() {
  // put your main code here, to run repeatedly:
  ble.waitForEvent();
}
...