03.06.2015
Here is an implementation for Bluetooth LE on Android which filters them by UUID. This can be used for devices which switch their MAC address like the Gimbal beacons. You can add this technology to the positioning manager with a single line of code:
1 | positionManager.addTechnology(new BluetoothLeTechnology("BLUETOOTH_LE")); |
The technology will take the strongest signal of an iBeacon or another Bluetooth LE device.
Add the following classes to your technology package:
Model for the technology:
BluetoothLeDevice.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | import android.bluetooth.BluetoothDevice; public class BluetoothLeDevice implements Comparable<BluetoothLeDevice> { private String name; private String address; private String companyId; private String uuid; private int rssi; private int major; private int minor; private int txPower; private long timeStamp; public BluetoothLeDevice(String name, String address, String companyId, String uuid, int rssi, int major, int minor, int txPower, long timeStamp) { initialize(name, address, companyId, uuid, rssi, major, minor, txPower, timeStamp); } public BluetoothLeDevice(String name, String address, String companyId, String uuid, int rssi, String major, String minor, String txPower, long timeStamp) { initialize(name, address, companyId, uuid, rssi, Integer.parseInt(major, 16), Integer.parseInt(minor, 16), Integer.valueOf(txPower, 16).shortValue(), timeStamp); } public BluetoothLeDevice(BluetoothDevice device, byte[] scanRecord, int rssi) { String uuid = ""; String companyId = String.format("%02x", scanRecord[5]) + String.format("%02x", scanRecord[6]); String major = String.format("%02x", scanRecord[25]) + String.format("%02x", scanRecord[26]); String minor = String.format("%02x", scanRecord[27]) + String.format("%02x", scanRecord[28]); String txPower = String.format("%02x", scanRecord[29]); for (int i = 0; i < scanRecord.length; i++) { if (i >= 9 && i <= 24) { uuid += String.format("%02x", scanRecord[i]); } } initialize(device.getName(), device.getAddress(), companyId, uuid, rssi, Integer.parseInt(major, 16), Integer.parseInt(minor, 16), Integer.valueOf(txPower, 16).shortValue(), System.currentTimeMillis()); } private void initialize(String name, String address, String companyId, String uuid, int rssi, int major, int minor, int txPower, long timeStamp) { this.name = name; this.address = address; this.companyId = companyId; this.uuid = uuid; this.rssi = rssi; this.major = major; this.minor = minor; this.txPower = txPower; this.timeStamp = timeStamp; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getCompanyId() { return companyId; } public void setCompanyId(String companyId) { this.companyId = companyId; } public int getRssi() { return rssi; } public void setRssi(int rssi) { this.rssi = rssi; } public long getTimeStamp() { return timeStamp; } public void setTimeStamp(long timeStamp) { this.timeStamp = timeStamp; } public int getMajor() { return major; } public void setMajor(int major) { this.major = major; } public int getMinor() { return minor; } public void setMinor(int minor) { this.minor = minor; } public String getIdentificator() { return major+"|"+minor; } public String getUuid() { return uuid; } public void setUuid(String uuid) { this.uuid = uuid; } public int getTxPower() { return txPower; } public void setTxPower(int txPower) { this.txPower = txPower; } @Override public int compareTo(BluetoothLeDevice another) { if(rssi > another.rssi) { return 1; } else if(rssi < another.rssi) { return -1; } return 0; } @Override public String toString() { return "BluetoothLeDevice{" + "name='" + name + '\'' + ", address='" + address + '\'' + ", companyId='" + companyId + '\'' + ", uuid='" + uuid + '\'' + ", rssi=" + rssi + ", major=" + major + ", minor=" + minor + ", txPower=" + txPower + ", timeStamp=" + timeStamp + '}'; } } |
The technology:
BluetoothLeTechnology.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.util.Log; import de.hadizadeh.positioning.controller.Technology; import de.hadizadeh.positioning.model.SignalInformation; import java.util.*; public class BluetoothLeTechnology extends Technology { private Map<String, SignalInformation> signalData; private BluetoothAdapter bluetoothAdapter; private int cacheSize = 10; private LinkedList<BluetoothLeDevice> btLeDevices; private boolean scanning; private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { BluetoothLeDevice btDevice = new BluetoothLeDevice(device, scanRecord, rssi); // Adapt the RSSI value to your hardware so you can filter devices. // 4c00 is the iBeacon type. if (rssi > -75 && "4c00".equals(btDevice.getCompanyId())) { btLeDevices.add(btDevice); } while (btLeDevices.size() > cacheSize) { btLeDevices.removeFirst(); } } }; public BluetoothLeTechnology(String name) { super(name, null); btLeDevices = new LinkedList<BluetoothLeDevice>(); providesExactlyPosition(); this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); this.signalData = new HashMap<String, SignalInformation>(); signalData = new HashMap<String, SignalInformation>(); bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); bluetoothAdapter.startLeScan(leScanCallback); scanning = true; new Thread() { @Override public void run() { while (scanning) { try { if (btLeDevices.size() > 0) { btLeDevices.removeFirst(); } Thread.sleep(1000); } catch (Exception ex) { ex.printStackTrace(); } } } }.start(); } @Override public Map<String, SignalInformation> getSignalData() { if (btLeDevices.size() > 0) { signalData.clear(); BluetoothLeDevice bestDevice = Collections.max(btLeDevices); signalData.put(bestDevice.getAddress(), new SignalInformation(1.0)); return signalData; } return null; } @Override public void stopScanning() { super.stopScanning(); scanning = false; bluetoothAdapter.stopLeScan(leScanCallback); } } |
Kategorie: Indoor-Positioning Addons |