View Javadoc
1   /*
2    * Copyright (C) 2018 Alberto Irurueta Carro (alberto@irurueta.com)
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.irurueta.navigation.indoor;
17  
18  import java.io.Serializable;
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.List;
22  
23  /**
24   * The <code>Beacon</code> class represents a single hardware Beacon detected by
25   * an Android device.
26   *
27   * <pre>A Beacon is identified by a unique multi-part identifier, with the first of the ordered
28   * identifiers being more significant for the purposes of grouping beacons.
29   *
30   * A Beacon sends a Bluetooth Low Energy (BLE) advertisement that contains these
31   * three identifiers, along with the calibrated tx power (in RSSI) of the Beacon's
32   * Bluetooth transmitter.
33   * </pre>
34   * <p>
35   * Based on:
36   * <a href="https://github.com/AltBeacon/android-beacon-library/blob/master/src/main/java/org/altbeacon/beacon/Beacon.java">
37   *   https://github.com/AltBeacon/android-beacon-library/blob/master/src/main/java/org/altbeacon/beacon/Beacon.java
38   * </a>
39   */
40  public class Beacon implements Serializable, RadioSource {
41  
42      /**
43       * Default frequency used by a Beacon when none is specified (expressed in Hz).
44       */
45      public static final double DEFAULT_FREQUENCY = 2.4e9;
46  
47      /**
48       * The list of the multipart identifiers of the beacon. Together, these identifiers signify
49       * a unique beacon. The identifiers are ordered by significance for the purpose of grouping
50       * beacons.
51       */
52      private ArrayList<BeaconIdentifier> identifiers;
53  
54      /**
55       * The calibrated measured Tx power of the Beacon in RSSI (expressed in dBm's).
56       * This value is baked into a Beacon when it is manufactured, and it is
57       * transmitted with each packet to aid in the distance estimate.
58       */
59      private double transmittedPower;
60  
61      /**
62       * The Bluetooth mac address.
63       */
64      private String bluetoothAddress;
65  
66      /**
67       * The two byte value indicating the type of beacon that this is, which is used for figuring
68       * out the byte layout of the beacon advertisement.
69       */
70      private int beaconTypeCode;
71  
72      /**
73       * A two byte code indicating the beacon manufacturer. A list of registered manufacturer codes
74       * may be found here:
75       * <a href="https://www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers">
76       *   https://www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers
77       * </a>
78       * <p>
79       * If the beacon is a GATT-based beacon, this field will be set to -1.
80       */
81      private int manufacturer;
82  
83      /**
84       * A 32 bit service uuid for the beacon.
85       * This is valid only for GATT-based beacons. If the beacon is a manufacturer data-based
86       * beacon, this field will be -1
87       */
88      private int serviceUuid = -1;
89  
90      /**
91       * The Bluetooth device name.  This is a field transmitted by the remote beacon device separate
92       * from the advertisement data
93       */
94      private String bluetoothName;
95  
96      /**
97       * Frequency used by this Beacon(expressed in Hz).
98       */
99      private double frequency = DEFAULT_FREQUENCY;
100 
101     /**
102      * Constructor.
103      *
104      * @param identifiers      list of the multipart identifiers of the beacon.
105      * @param transmittedPower calibrated measured Tx power of the Beacon in RSSI (expressed in dBm's).
106      * @throws IllegalArgumentException if identifiers is null.
107      */
108     public Beacon(final List<BeaconIdentifier> identifiers, final double transmittedPower) {
109         if (identifiers == null) {
110             throw new IllegalArgumentException();
111         }
112 
113         this.identifiers = new ArrayList<>(identifiers);
114         this.transmittedPower = transmittedPower;
115     }
116 
117     /**
118      * Constructor.
119      *
120      * @param identifiers      list of the multipart identifiers of the beacon.
121      * @param transmittedPower calibrated measured Tx power of the Beacon in RSSI (expressed in dBm's).
122      * @param bluetoothAddress the bluetooth mac address.
123      * @param beaconTypeCode   the two byte value indicating the type of beacon.
124      * @param manufacturer     a two byte code indicating the beacon manufacturer.
125      * @param serviceUuid      a 32 bit service uuid for the beacon.
126      * @param bluetoothName    the bluetooth device name.
127      * @throws IllegalArgumentException if identifiers is null.
128      */
129     public Beacon(final List<BeaconIdentifier> identifiers, final double transmittedPower,
130                   final String bluetoothAddress, final int beaconTypeCode, final int manufacturer,
131                   final int serviceUuid, final String bluetoothName) {
132         this(identifiers, transmittedPower);
133 
134         this.bluetoothAddress = bluetoothAddress;
135         this.beaconTypeCode = beaconTypeCode;
136         this.manufacturer = manufacturer;
137         this.serviceUuid = serviceUuid;
138         this.bluetoothName = bluetoothName;
139     }
140 
141     /**
142      * Constructor.
143      *
144      * @param identifiers      list of the multipart identifiers of the beacon.
145      * @param transmittedPower calibrated measured Tx power of the Beacon in RSSI (expressed in dBm's).
146      * @param frequency        frequency used by this Beacon.
147      * @throws IllegalArgumentException if identifiers is null or frequency is negative.
148      */
149     public Beacon(final List<BeaconIdentifier> identifiers, final double transmittedPower, final double frequency) {
150         this(identifiers, transmittedPower);
151 
152         if (frequency < 0.0) {
153             throw new IllegalArgumentException();
154         }
155 
156         this.frequency = frequency;
157     }
158 
159     /**
160      * Constructor.
161      *
162      * @param identifiers      list of the multipart identifiers of the beacon.
163      * @param transmittedPower calibrated measured Tx power of the Beacon in RSSI (expressed in dBm's).
164      * @param frequency        frequency used by this Beacon.
165      * @param bluetoothAddress the bluetooth mac address.
166      * @param beaconTypeCode   the two byte value indicating the type of beacon.
167      * @param manufacturer     a two byte code indicating the beacon manufacturer.
168      * @param serviceUuid      a 32 bit service uuid for the beacon.
169      * @param bluetoothName    the bluetooth device name.
170      * @throws IllegalArgumentException if identifiers is null.
171      */
172     public Beacon(final List<BeaconIdentifier> identifiers, final double transmittedPower, final double frequency,
173                   final String bluetoothAddress, final int beaconTypeCode, final int manufacturer,
174                   final int serviceUuid, final String bluetoothName) {
175         this(identifiers, transmittedPower, bluetoothAddress, beaconTypeCode, manufacturer, serviceUuid, bluetoothName);
176 
177         if (frequency < 0.0) {
178             throw new IllegalArgumentException();
179         }
180 
181         this.frequency = frequency;
182     }
183 
184     /**
185      * Empty constructor.
186      */
187     protected Beacon() {
188     }
189 
190     /**
191      * Returns the specified identifier - 0 indexed.
192      * Note: to read id1, call getIdentifier(0);
193      *
194      * @param i index identifier.
195      * @return identifier or null if not available.
196      */
197     public BeaconIdentifier getIdentifier(final int i) {
198         if (i < 0 || identifiers == null || identifiers.size() <= i) {
199             return null;
200         }
201         return identifiers.get(i);
202     }
203 
204     /**
205      * Convenience method to get the first identifier.
206      *
207      * @return first identifier or null if not available.
208      */
209     public BeaconIdentifier getId1() {
210         if (identifiers == null || identifiers.isEmpty()) {
211             return null;
212         }
213         return identifiers.get(0);
214     }
215 
216     /**
217      * Convenience method to get the second identifier.
218      *
219      * @return second identifier or null if not available.
220      */
221     public BeaconIdentifier getId2() {
222         if (identifiers == null || identifiers.size() < 2) {
223             return null;
224         }
225         return identifiers.get(1);
226     }
227 
228     /**
229      * Convenience method to get the third identifier.
230      *
231      * @return third identifier or null if not available.
232      */
233     public BeaconIdentifier getId3() {
234         if (identifiers == null || identifiers.size() < 3) {
235             return null;
236         }
237         return identifiers.get(2);
238     }
239 
240     /**
241      * Gets the list of the multipart identifiers of the beacon. Together, these identifiers signify
242      * a unique beacon. The identifiers are ordered by significance for the purpose of grouping
243      * beacons.
244      *
245      * @return list of identifiers of the beacon or null if not available.
246      */
247     public List<BeaconIdentifier> getIdentifiers() {
248         return identifiers != null ? Collections.unmodifiableList(identifiers) : null;
249     }
250 
251     /**
252      * Returns the calibrated measured Tx power of the Beacon in RSSI (expressed in dBm's).
253      * This value is baked into a Beacon when it is manufactured, and it is
254      * transmitted with each packet to aid in the distance estimate.
255      *
256      * @return the calibrated measured Tx power.
257      */
258     public double getTransmittedPower() {
259         return transmittedPower;
260     }
261 
262     /**
263      * Gets the bluetooth mac address.
264      *
265      * @return bluetooth mac address.
266      */
267     public String getBluetoothAddress() {
268         return bluetoothAddress;
269     }
270 
271     /**
272      * Gets the two byte value indicating the type of beacon that this is, which is used for figuring
273      * out the byte layout of the beacon advertisement.
274      *
275      * @return two byte value indicating the type of beacon.
276      */
277     public int getBeaconTypeCode() {
278         return beaconTypeCode;
279     }
280 
281 
282     /**
283      * Gets the Bluetooth device name. This is a field transmitted by the remote beacon device separate
284      * from the advertisement data.
285      *
286      * @return bluetooth device name.
287      */
288     public String getBluetoothName() {
289         return bluetoothName;
290     }
291 
292     /**
293      * Gets a two byte code indicating the beacon manufacturer. A list of registered manufacturer codes
294      * may be found here:
295      * <a href="https://www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers">
296      *   https://www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers
297      * </a>
298      * <p>
299      * If the beacon is a GATT-based beacon, this field will be set to -1.
300      *
301      * @return a two byte code indicating the beacon manufacturer.
302      */
303     public int getManufacturer() {
304         return manufacturer;
305     }
306 
307     /**
308      * Gets a 32 bit service uuid for the beacon.
309      * This is valid only for GATT-based beacons. If the beacon is a manufacturer data-based
310      * beacon, this field will be -1
311      *
312      * @return service uuid.
313      */
314     public int getServiceUuid() {
315         return serviceUuid;
316     }
317 
318     /**
319      * Gets frequency used by this radio source (expressed in Hz).
320      *
321      * @return frequency used by this radio source (expressed in Hz).
322      */
323     @Override
324     public double getFrequency() {
325         return frequency;
326     }
327 
328     /**
329      * Checks whether two beacons are considered equal if they share the same identifiers.
330      *
331      * @param that beacon to be compared.
332      * @return true if both beacons are considered equal, false otherwise.
333      */
334     @Override
335     public boolean equals(final Object that) {
336         if (!(that instanceof Beacon thatBeacon)) {
337             return false;
338         }
339 
340         return identifiers != null && identifiers.equals(thatBeacon.identifiers);
341     }
342 
343     /**
344      * Computes hash code for this instance.
345      *
346      * @return this instance hash code.
347      */
348     @Override
349     public int hashCode() {
350         return identifiers.hashCode();
351     }
352 
353     /**
354      * Gets radio source type, which can be either a Wi-Fi Access point or a bluetooth Beacon.
355      *
356      * @return radio source type.
357      */
358     @Override
359     public RadioSourceType getType() {
360         return RadioSourceType.BEACON;
361     }
362 }