martedì 21 agosto 2018

Bluetooth LE cached name scan

Lavorando ad un progetto in cui un beacon BLE cambia spesso il proprio nome ho scoperto che la funzione ScanResult (vedi qui per esempio) non aggiorna i nomi dei beacon una volta scoperti (come se avesse una cache interna). Usando invece la funzioen ScanRecord, come nel codice sottostante, tutto funziona in modo corretto


-----------------------------
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.blescan.lucainnocenti.blescan">

    <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-feature        android:name="android.hardware.bluetooth_le"        android:required="true" />

    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:roundIcon="@mipmap/ic_launcher_round"        android:supportsRtl="true"        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
-----------------------------


-----------------------------
package com.blescan.lucainnocenti.blescan;

import android.Manifest;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    private BluetoothAdapter mBluetoothAdapter  = null;
    private BluetoothLeScanner mBluetoothLeScanner = null;

    public static final int REQUEST_BT_PERMISSIONS = 0;
    public static final int REQUEST_BT_ENABLE = 1;

    private boolean mScanning = false;
    private Handler mHandler = null;

    private Button btnScan = null;



    private ScanCallback mLeScanCallback =
            new ScanCallback() {

                @Override                public void onScanResult(int callbackType, final ScanResult result) {
                    super.onScanResult(callbackType, result);
                    final ScanRecord scanRecord = result.getScanRecord();


                    if (scanRecord.getDeviceName() != null) {
                        Log.d("BLE", scanRecord.getDeviceName());
                    }

                }

                @Override                public void onScanFailed(int errorCode) {
                    super.onScanFailed(errorCode);
                    Log.d("BLE", "error");
                }
            };






    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnScan = (Button) findViewById(R.id.btnScan);

        new Handler().postDelayed(new Runnable() {
            @Override            public void run() {
                if (mScanning){
                    mScanning = false;
                    scanLeDevice(false);
                    btnScan.setText("STOP");
                } else {
                    mScanning = true;
                    scanLeDevice(true);
                    btnScan.setText("SCAN");
                }
            }
        }, 30000);




        btnScan.setOnClickListener(new View.OnClickListener() {
            @Override            public void onClick(View view) {
                onBtnScan();
            }
        });
        this.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        this.mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
        this.mHandler = new Handler();

        checkBtPermissions();
        enableBt();
    }

    public void onBtnScan(){
        if (mScanning){
            mScanning = false;
            scanLeDevice(false);
            btnScan.setText("STOP");
        } else {
            mScanning = true;
            scanLeDevice(true);
            btnScan.setText("SCAN");
        }
    }

    public void checkBtPermissions() {
        this.requestPermissions(
                new String[]{
                        Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN                },
                REQUEST_BT_PERMISSIONS);
    }

    public void enableBt(){
        if (mBluetoothAdapter == null) {
            // Device does not support Bluetooth        }
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_BT_ENABLE);
        }
    }

    public void scanLeDevice(final boolean enable) {
        // ScanSettings mScanSettings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_BALANCED).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).build();
        if (enable) {
            mScanning = true;
            Log.i("Scanning", "start");
            mBluetoothLeScanner.startScan(mLeScanCallback);
        } else {
            Log.i("Scanning", "stop");
            mScanning = false;
            mBluetoothLeScanner.stopScan(mLeScanCallback);
        }
    }
-----------------------------

Nessun commento:

Posta un commento

Pandas su serie tempo

Problema: hai un csv che riporta una serie tempo datetime/valore di un sensore Effettuare calcoli, ordina le righe, ricampiona il passo temp...