Nano Hash - криптовалюты, майнинг, программирование

Как увеличить readCharacteristic устройства Ble?

Я создаю приложение, которое загружает все характеристики с устройства BLE. Это устройство хранит в вашей локальной памяти 10 различных двойных значений каждые 3 мс.

Таким образом, за 1 секунду устройство BLE хранит 333 строки (каждая строка имеет 10 значений).

Мое приложение для Android, загрузите эти значения, но я могу скачать одну строку за секунду или чуть меньше. В этом режиме я никогда не смогу загрузить всю информацию об этом BLE-устройстве.

Теперь есть способ увеличить частоту сканирования, чтобы прочитать эту характеристику?

это моя служба, которая загрузила характеристику устройства BLE:

public class BlePowerService extends Service {
    public DbLayer db;
    Setting settingApp;
    List<ScanFilter> filters;
    String[] stringSequence = new String[] {CHARACTERISTIC_FORZA_STRING, CHARACTERISTIC_TEMPERATURA_STRING};
    BluetoothAdapter mBluetoothAdapter;
    BluetoothGatt mGatt;
    BluetoothDevice currDevice;
    static final long SCAN_PERIOD = 500;
    static String SPLIT_CHAR =";";
    BluetoothLeScanner mLEScanner;
    Handler mHandler;
    int ReadQueueIndex;
    List<BluetoothGattCharacteristic> ReadQueue;
    BluetoothGattCharacteristic caratteristicaDaLeggere;
    ScanSettings settings;
    Integer ultimaForzaLetta,ultimaTemperaturaLetta;
    boolean continuaLetturaForza, continuaLetturaTemperatura;
    boolean isReading = true;
    String LOG_CODE = "NOTIFSRV";
    GattClientCallback gattClientCallback;
    private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;


    public BlePowerService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mHandler = new Handler();

        Context sharedContext = null;
        try {
            sharedContext = this.createPackageContext(
                    "com.care.devicesensor",
                    Context.CONTEXT_INCLUDE_CODE);
            if (sharedContext == null) {
                return;
            }
            db=new DbLayer(sharedContext);
            db.open();
        } catch (Exception e) {
            String error = e.getMessage();
          //  Log.d(LOG_CODE,"DB error : " + error);
            return;
        }
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {
            //RECUPERO LE IMPOSTAZIONI SETTATE DALL'UTENTE
            settingApp = db.fetchSetting();
            if (settingApp != null && settingApp.getAddressBleSX()!=null) {
                //POSSO FILTRARE DIRETTAMENTE PER L'UUID DEL DISPOSITIVO MEMORIZZATO
                //DALL'UTENTE
                ScanFilter.Builder scanFilterMac =
                        null;
                    scanFilterMac = new ScanFilter.Builder().setDeviceAddress(settingApp.getAddressBleSX());
                if(filters==null)
                    filters = new ArrayList<ScanFilter>();
                //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                filters.add(scanFilterMac.build());
                //}
                //FILTRO ANCHE PER LA CARATTERISTICA DI FORZA
                ScanFilter filter = null;
                    filter = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(CHARACTERISTIC_FORZA_STRING)).build();
                filters.add(filter);

                final BluetoothManager bluetoothManager =
                        (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
                    mBluetoothAdapter = bluetoothManager.getAdapter();
                //mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                    mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
                    settings = new ScanSettings.Builder()
                            .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
                            .build();
                scanLeDevice(true);
                mTimer = new Timer();
                //ogni 2 ore
                continuaLetturaForza = true;
                continuaLetturaTemperatura = true;

                int nSecondi = settingApp.getFrequenzaDownload()!= null ? settingApp.getFrequenzaDownload() : 1;
                mTimer.schedule(timerTask,5000);
                //mTimer.schedule(timerTask, 10000, 1000 * nSecondi);
                //mTimer.scheduleAtFixedRate (timerTask, 10000, 1000 * nSecondi);
            }
        } catch (Exception e) {
           // Log.e("POWER_SERVICE", e.getMessage());
        }
        return super.onStartCommand(intent, flags, startId);
    }

    private Timer mTimer;

    TimerTask timerTask = new TimerTask() {

        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void run() {
            //LEGGO TUTTI I DATI DAL SENSORE FINCHE CI SONO VALORI
             int counter = 0;
            while(continuaLetturaForza || continuaLetturaTemperatura){
                counter++;
                //Log.v("CICLO WHILE", counter+"");
                if (currDevice != null) {

                    if(ReadQueue!= null && ReadQueue.size()>0){
                        int index =0;
                        for(index=0; index < ReadQueue.size(); index++){
                            if(mGatt!=null){
                                isReading = mGatt.readCharacteristic(ReadQueue.get(index));
                                while(isReading){
                                    try {
                                        Thread.sleep(1);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }else{
                                continuaLetturaForza = false;
                                continuaLetturaTemperatura = false;
                            }
                        }
                    }

                }else{
                    //provo a ricollegarmi al dispositivo probabile, abbia perso la connessione con esso
                    scanLeDevice(true);
                    try {
                        Thread.sleep(2500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(currDevice == null && counter == 25){
                        //in questo caso non è riuscito a trovare il dispositivo BLE
                        //esco dal ciclo
                        continuaLetturaForza = false;
                        continuaLetturaTemperatura = false;
                        continue;
                    }
                }

            }

            if(gattClientCallback!=null && mGatt != null)
                gattClientCallback.disconnectGattServer();
            mTimer.cancel();
            stopSelf();
            EventBus.getDefault().post(new MessageEvent("stopService"));
        }

        public void stopTask() {

            if (timerTask != null) {

                Log.d("TIMER", "timer canceled");
                timerTask.cancel();
            }
        }
    };


    public void connectToDevice(BluetoothDevice device) {
        //VERIFICO SE IL DEVICE è QUELLO CHE VOGLIO IO
        if (mGatt == null && settingApp != null
                && device.getAddress().equals(settingApp.getAddressBleSX())) {
            currDevice = device;
            gattClientCallback = new GattClientCallback();
            mGatt = currDevice.connectGatt(getBaseContext(), false, gattClientCallback);
            scanLeDevice(false);// will stop after first device detection
        }
    }

    private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {
                @Override
                public void onLeScan(final BluetoothDevice device, int rssi,
                                     byte[] scanRecord) {
                    Handler h = new Handler(getApplicationContext().getMainLooper());
                    // Although you need to pass an appropriate context
                    h.post(new Runnable() {
                        @Override
                        public void run() {
                          //  Log.i("onLeScan", device.toString());
                                connectToDevice(device);

                        }
                    });
                }
            };

    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 = null;
               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 class GattClientCallback extends BluetoothGattCallback {

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            try{
                super.onConnectionStateChange(gatt, status, newState);
                //Log.i("tag", "onConnectionStateChange newState: " + newState);

                if (status == BluetoothGatt.GATT_FAILURE) {
                    Log.e("ERROR_SERVICE", "Connection Gatt failure status " + status);
                    if(mGatt == null){

                    }else{
                        try {
                            gatt.close();
                        } catch (Exception e) {
                            Log.d("", "close ignoring: " + e);
                        }
                        mGatt = null;
                    }
                    return;
                } else if (status != BluetoothGatt.GATT_SUCCESS) {
                    // handle anything not SUCCESS as failure
                    Log.e("ERROR_SERVICE", "Connection not GATT sucess status " + status);
                    if(mGatt == null){

                    }else{
                        try {
                            gatt.close();
                        } catch (Exception e) {
                            Log.d("", "close ignoring: " + e);
                        }
                        mGatt = null;
                    }
                    return;
                }

                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    //Log.i("INFO", "Connected to device " + gatt.getDevice().getAddress());
                    gatt.discoverServices();
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    Log.i("INFO", "Disconnected from device");
                    if(mGatt == null){

                    }else{
                        try {
                            mGatt.close();
                            mGatt = null;
                            currDevice = null;
                        } catch (Exception e) {
                            Log.d("", "close ignoring: " + e);
                        }
                        mGatt = null;
                    }

                }
            }catch(Exception e){
                Log.e("tag", e.getMessage());
                continuaLetturaForza = true;
                continuaLetturaTemperatura = true;
            }
        }

        public void disconnectGattServer() {

            continuaLetturaForza = true;
            continuaLetturaTemperatura = true;
            isReading = false;
            if (mGatt == null) {

            }
            else{
                try{
                    mGatt.disconnect();
                   // mGatt.close();
                }catch(Exception e){
                    mGatt = null;
                }

            }
            //mGatt = null;
            //currDevice = null;
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);

            if (status != BluetoothGatt.GATT_SUCCESS) {
             //   Log.i("INFO", "Device service discovery unsuccessful, status " + status);
                return;
            }

            List<BluetoothGattCharacteristic> matchingCharacteristics =
                    BluetoothUtils.findCharacteristics(gatt,stringSequence);
            if (matchingCharacteristics.isEmpty()) {
              //  Log.e("ERROR_SERVICE","Unable to find characteristics.");
                return;
            }else {

                ReadQueue = new ArrayList<>();
                for (BluetoothGattCharacteristic characterist : matchingCharacteristics) {
                    ReadQueue.add(characterist);
                }
                //ReadQueueIndex = 0;
                //ReadCharacteristics(ReadQueueIndex);
            }



        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {

                String valoreRestituito = characteristic.getStringValue(0);
                if(valoreRestituito==null){
                    int i = 0;
                    i = i + 1;
                    return;
                }
                //SPLITTO PER IL CARATTERE ;
                String[] arrayValori = valoreRestituito.split(SPLIT_CHAR);
                //1 valore è l ID
                try{
                    int id = new Integer(arrayValori[0]);
                    //VERIFICO SE STO LEGGENDO TEMPERATURA O FORZA
                    if(characteristic.getUuid().equals(CHARACTERISTIC_FORZA_UUID)){
                        /*Log.v("CARATTERISTICA", "*****************************************");
                        Log.v("FORZA", "*****************************************");*/
                        if(ultimaForzaLetta!= null && ultimaForzaLetta == id){
                            continuaLetturaForza = false;
                            isReading = false;
                            return;
                        }
                        ultimaForzaLetta = id;
                    }else if(characteristic.getUuid().equals( CHARACTERISTIC_TEMPERATURA_UUID)){
                        /*Log.v("CARATTERISTICA", "*****************************************");
                        Log.v("TEMPERATURA", "*****************************************");*/
                        if(ultimaTemperaturaLetta!= null && ultimaTemperaturaLetta == id){
                            continuaLetturaTemperatura = false;
                            isReading = false;
                            return;
                        }
                        ultimaTemperaturaLetta = id;
                    }

                    SensorData mSenData = new SensorData();
                    mSenData.setIdType(id);
                    mSenData.setValue1(arrayValori[1]);
                    mSenData.setValue2(arrayValori[2]);
                    mSenData.setValue3(arrayValori[3]);
                    mSenData.setValue4(arrayValori[4]);
                    mSenData.setValue5(arrayValori[5]);
                    mSenData.setValue6(arrayValori[6]);
                    mSenData.setValue7(arrayValori[7]);
                    mSenData.setValue8(arrayValori[8]);
                    //TO-DO HO COMMENTATO QUESTA RIGA DI CODICE
                    // mSenData.setIdType(st.getId());
                    mSenData.setCharacteristic(characteristic.getUuid().toString());
                    mSenData.setValueTimestamp(db.getDateTime(true));

                    db.insertSensorData(mSenData);

                    EventBus.getDefault().post(new MessageEvent("update"));

                }catch (Exception e){
                    Log.e("ERROR", e.getMessage());
                }
                isReading = false;

            } else {
                isReading = false;
                Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);

                disconnectGattServer();

                return;
            }
        }
    }

    public void onDestroy() {
        try {
            db.close();
            Log.d(LOG_CODE,"DB connection closed" );

            mTimer.cancel();
            timerTask.cancel();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

Сервис работает корректно, но тормозит.


Ответы:


1

Вы не можете сделать более одного запроса на чтение за интервал подключения. Поскольку 3 мс намного меньше минимально допустимого интервала соединения, то, что вы пытаетесь сделать, кажется невозможным. Вам придется сделать свой протокол более эффективным, например, разрешив периферийному устройству отправлять поток уведомлений. Таким образом, вы можете получить несколько пакетов на одно событие соединения.

16.05.2018
  • спасибо за Ваш ответ. Могу ли я узнать, каково минимальное время до интервала подключения? 16.05.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..