RSS-Feed

David Hadizadeh

E-Mail

Xing-Profil

LinkedIn

Impressum

 




Bluetooth LE Proximity Technology (by UUIDs)

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 |


Impressum