2014-07-06 69 views
0

我有能夠掃描BLE devies的源代碼,它們是溫度傳感器,但掃描時不會顯示任何其他BLE decies。我想修改附帶的代碼,以便我可以掃描並查看所有BLE設備,無論它是否爲溫度傳感器。有人可以解釋我或告訴我我可以做到這一點。這裏是代碼片段來獲取BLE溫度傳感器數據。BLE temp傳感器服務檢測

package no.nordicsemi.android.nrftemp.ble; 

    import java.util.ArrayList; 
    import java.util.Calendar; 
    import java.util.List; 

import no.nordicsemi.android.nrftemp.ble.parser.TemperatureData; 
    import no.nordicsemi.android.nrftemp.ble.parser.TemperatureDataParser; 
    import no.nordicsemi.android.nrftemp.database.DatabaseHelper; 
import android.bluetooth.BluetoothAdapter; 
    import android.bluetooth.BluetoothDevice; 
    import android.bluetooth.BluetoothManager; 
import android.content.Context; 
    import android.os.Handler; 

public class TemperatureManager implements BluetoothAdapter.LeScanCallback { 
/** An minimal interval between each data row in the database for a single device */ 
private static final long DATA_INTERVAL = 60 * 5 * 1000L; // ms 

private BluetoothAdapter mBluetoothAdapter; 
private DatabaseHelper mDatabaseHelper; 

private List<TemperatureManagerCallback> mListeners; 

public TemperatureManager(final Context context, final DatabaseHelper databaseHelper) { 
    final BluetoothManager bluetoothManager = (BluetoothManager)  context.getSystemService(Context.BLUETOOTH_SERVICE); 
    mBluetoothAdapter = bluetoothManager.getAdapter(); 
    mDatabaseHelper = databaseHelper; 

    mListeners = new ArrayList<TemperatureManagerCallback>(2); 
} 

public void addCallback(final TemperatureManagerCallback callback) { 
    mListeners.add(callback); 
} 

public void removeCallback(final TemperatureManagerCallback callback) { 
    mListeners.remove(callback); 
} 

private void fireOnDevicesScanned() { 
    for (TemperatureManagerCallback callback : mListeners) 
     callback.onDevicesScaned(); 
} 

private void fireOnRssiUpdate(final long sensorId, final int rssi) { 
    for (TemperatureManagerCallback callback : mListeners) 
     callback.onRssiUpdate(sensorId, rssi); 
} 

/** 
    * Starts scanning for temperature data. Call {@link #stopScan()} when done to save the power. 
*/ 
    public void startScan() { 
    mBluetoothAdapter.startLeScan(this); 
} 

/** 
* Starts scanning for temperature data. Call {@link #stopScan()} when done to save the power. 
*/ 
    public void startScan(final long period) { 
    mBluetoothAdapter.startLeScan(this); 

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

/** 
* Stops scanning for temperature data from BLE sensors. 
*/ 
public void stopScan() { 
    mBluetoothAdapter.stopLeScan(this); 
} 

@Override 
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[]  scanRecord) { 
    final TemperatureData td = TemperatureDataParser.parse(device, scanRecord); 
    if (!td.isValid()) 
     return; 

    final long now = Calendar.getInstance().getTimeInMillis(); 
    final long then = mDatabaseHelper.getLastTimestamp(td.getAddress()); 

    if (now - then > DATA_INTERVAL) { 
     mDatabaseHelper.addNewSensorData(device.getAddress(), device.getName(), now,     
    td.getTemp(), td.getBattery()); 
     fireOnDevicesScanned(); 
    } 
    final long sensorId = mDatabaseHelper.findSensor(device.getAddress()); 
    final int rssiPercent = (int) (100.0f * (127.0f + rssi)/127.0f + 20.0f); 
    mDatabaseHelper.updateSensorRssi(sensorId, rssiPercent); 
    fireOnRssiUpdate(sensorId, rssiPercent); 
} 

/** 
* Return <code>true</code> if Bluetooth is currently enabled and ready for use. 
* 
* @return <code>true</code> if the local adapter is turned on 
*/ 
public boolean isEnabled() { 
    return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled(); 
} 
    } 


package no.nordicsemi.android.nrftemp.ble.parser; 

import android.bluetooth.BluetoothDevice; 

/** 
    * Domain class contains data obtained from a single advertising package from a  temperature sensor. 
    */ 
    public class TemperatureData { 
    /** The device address */ 
    private final String address; 

/** The device name */ 
private String name; 

/** The temperature value */ 
private double temp; 

/** Battery status (number 0-100 in percent) */ 
private int battery = 0xFF; // unknown value 

/** 
* The flag whether the data are valid (holds real temperature measurement or not) 
*/ 
private boolean valid; 

public TemperatureData(BluetoothDevice device) { 
    address = device.getAddress(); 
    name = device.getName(); 
} 

public String getAddress() { 
    return address; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public double getTemp() { 
    return temp; 
} 

public void setTemp(double temp) { 
    this.temp = temp; 
    this.valid = true; 
} 

public int getBattery() { 
    return battery; 
} 

public void setBattery(int battery) { 
    this.battery = battery; 
} 

public boolean isValid() { 
    return valid; 
} 
} 


package no.nordicsemi.android.nrftemp.ble.parser; 

    import java.io.UnsupportedEncodingException; 
    import java.text.ParseException; 

    import android.bluetooth.BluetoothDevice; 
    import android.util.Log; 

    public class TemperatureDataParser { 
private static final String TAG = "TemperatureDataParser"; 

private static final int FLAGS = 0x02; // "Flags" Data Type (See section 18.1 of Core_V4.0.pdf) 
private static final int LOCAL_NAME = 0x09; // "Complete Local Name" Data Type (See section 18.3 of Core_V4.0.pdf) 
private static final int SERVICE_DATA = 0x16; // "Service Data" Data Type (See section 18.10 of Core_V4.0.pdf) 

private static final short TEMPERATURE_SERVICE_UUID = 0x1809; 
private static final short BATTERY_SERVICE_UUID = 0x180F; 
private static final short DEVICE_INFORMATION_SERVICE_UUID = 0x180A; 

/** 
* Parses the advertising package obtained by BLE device 
* 
* @param data 
*   the data obtained (EIR data). Read Bluetooth Core Specification v4.0 (Core_V4.0.pdf -&gt; Vol.3 -&gt; Part C -&gt; Section 8) for details 
* @return the parsed temperature data 
* @throws ParseException 
*    thrown when the given data does not fit the expected format 
*/ 
public static TemperatureData parse(final BluetoothDevice device, final byte[] data) { 
    final TemperatureData td = new TemperatureData(device); 

    /* 
    * First byte of each EIR Data Structure has it's length (1 octet). 
    * There comes the EIR Data Type (n bytes) and (length - n bytes) of data. 
    * See Core_V4.0.pdf -> Vol.3 -> Part C -> Section 8 for details 
    */ 
    for (int i = 0; i < data.length;) { 
     final int eirLength = data[i]; 

     // check whether there is no more to read 
     if (eirLength == 0) 
      break; 

     final int eirDataType = data[++i]; 
     switch (eirDataType) { 
     case FLAGS: 
      // do nothing 
      break; 
     case LOCAL_NAME: 
      /* 
      * Local name data structure contains length - 1 bytes of the device name (1 byte for the data type) 
      */ 
      final String name = decodeLocalName(data, i + 1, eirLength - 1); 
      td.setName(name); 
      break; 
     case SERVICE_DATA: 
      /* 
      * First 2 bytes of service data are the 16-bit Service UUID in reverse order. The rest is service specific data. 
      */ 
      final short serviceUUID = decodeServiceUUID(data, i + 1); 

      switch (serviceUUID) { 
      case BATTERY_SERVICE_UUID: 
       final int battery = decodeBatteryLevel(data, i + 3); 
       td.setBattery(battery); 
       break; 
      case TEMPERATURE_SERVICE_UUID: 
       final double temp = decodeTempLevel(data, i + 3); 
       td.setTemp(temp); 
       break; 
      case DEVICE_INFORMATION_SERVICE_UUID: 
       // do nothing 
       break; 
      } 
      break; 
     default: 
      break; 
     } 
     i += eirLength; 
    } 
    return td; 
} 

private static String decodeLocalName(final byte[] data, final int start, final int length) { 
    try { 
     return new String(data, start, length, "UTF-8"); 
    } catch (UnsupportedEncodingException e) { 
     Log.e(TAG, "Unable to convert the local name to UTF-8", e); 
     return null; 
    } 
} 

private static short decodeServiceUUID(final byte[] data, final int start) { 
    return (short) ((data[start + 1] << 8) | data[start]); 
} 

private static int decodeBatteryLevel(final byte[] data, final int start) { 
    /* 
    * Battery level is a 1 byte number 0-100 (0x64). Value 255 (0xFF) is used for illegal measurement values 
    */ 
    return data[start]; 
} 

private static float decodeTempLevel(final byte[] data, final int start) { 
    return bytesToFloat(data[start], data[start + 1], data[start + 2], data[start + 3]); 
} 

/** 
* Convert signed bytes to a 32-bit short float value. 
*/ 
private static float bytesToFloat(byte b0, byte b1, byte b2, byte b3) { 
    int mantissa = unsignedToSigned(unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8) + (unsignedByteToInt(b2) << 16), 24); 
    return (float) (mantissa * Math.pow(10, b3)); 
} 

/** 
* Convert a signed byte to an unsigned int. 
*/ 
private static int unsignedByteToInt(byte b) { 
    return b & 0xFF; 
} 

/** 
* Convert an unsigned integer value to a two's-complement encoded signed value. 
*/ 
private static int unsignedToSigned(int unsigned, int size) { 
    if ((unsigned & (1 << size - 1)) != 0) { 
     unsigned = -1 * ((1 << size - 1) - (unsigned & ((1 << size - 1) - 1))); 
    } 
    return unsigned; 
} 

}

回答

0

據我所看到的,該代碼是用於掃描每一BLE設備已經有在掃描mBluetoothAdapter.startLeScan(本)無服務UUID限制;

這個代碼的問題(與許多例子一樣)是它假定每個設備都是它們自己的類型(在這種情況下是溫度傳感器)。

的假設是在這裏:

public void onLeScan(final BluetoothDevice device, final int rssi, final byte[]  scanRecord) { 
final TemperatureData td = TemperatureDataParser.parse(device, scanRecord); 

知道什麼服務設備支持的唯一方法是通過連接到它,做服務的發現,爲支持的服務的檢查。

Regards,Rob。