Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
BTDeviceRegistry.java
Go to the documentation of this file.
1 /**
2  * Author: Sven Gothel <sgothel@jausoft.com>
3  * Copyright (c) 2020 Gothel Software e.K.
4  * Copyright (c) 2020 ZAFENA AB
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 package org.direct_bt;
27 
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.List;
35 
36 /**
37  * Application toolkit providing BT device registration of processed and awaited devices.
38  * The latter on a pattern matching basis, i.e. EUI48Sub or name-sub.
39  */
40 public class BTDeviceRegistry {
41  /**
42  * Specifies devices queries to act upon.
43  */
44  public static class DeviceQuery {
45  /**
46  * {@link DeviceQuery} type, i.e. {@link EUI48Sub} or a {@link String} name.
47  */
48  public static enum Type {
49  /** {@link DeviceQuery} type, using a sensor device {@link EUI48Sub}. */
51  /** {@link DeviceQuery} type, using a sensor device {@link String} name. */
52  NAME
53  }
54 
55  public final Type type;
56  public final EUI48Sub addressSub;
57  public final String nameSub;
58 
59  public DeviceQuery(final EUI48Sub as) {
60  type = Type.EUI48SUB;
61  addressSub = as;
62  nameSub = new String();
63  }
64  public DeviceQuery(final String ns) {
65  type = Type.NAME;
67  nameSub = ns;
68  }
69 
70  public final boolean isEUI48Sub() { return Type.EUI48SUB == type; }
71 
72  @Override
73  public String toString() {
74  if( Type.EUI48SUB == type ) {
75  return "[a: "+addressSub.toString()+"]";
76  } else {
77  return "[n: '"+nameSub+"']";
78  }
79  }
80  };
81  private static List<DeviceQuery> waitForDevices = new ArrayList<DeviceQuery>();
82 
83  /**
84  * Specifies unique device identities,
85  * using {@link BDAddressAndType} as key.
86  */
87  public static class DeviceID {
89  public final String name;
90  public DeviceID(final BDAddressAndType a, final String n) {
91  addressAndType = a;
92  name = n;
93  }
94 
95  /**
96  * {@inheritDoc}
97  * <p>
98  * Implementation simply tests the {@link BDAddressAndType} fields for equality,
99  * `name` is ignored.
100  * </p>
101  */
102  @Override
103  public final boolean equals(final Object obj) {
104  if(this == obj) {
105  return true;
106  }
107  if (obj == null || !(obj instanceof DeviceID)) {
108  return false;
109  }
111  }
112 
113  /**
114  * {@inheritDoc}
115  * <p>
116  * Implementation simply returns the {@link BDAddressAndType} hash code,
117  * `name` is ignored.
118  * </p>
119  */
120  @Override
121  public final int hashCode() {
122  return addressAndType.hashCode();
123  }
124 
125  @Override
126  public String toString() {
127  return "["+addressAndType+", "+name+"]";
128  }
129  };
130  private static Collection<DeviceID> devicesInProcessing = Collections.synchronizedCollection(new HashSet<DeviceID>());
131  private static Collection<DeviceID> devicesProcessed = Collections.synchronizedCollection(new HashSet<DeviceID>());
132 
133  public static void addToWaitForDevices(final String addrOrNameSub) {
134  final EUI48Sub addr1 = new EUI48Sub();
135  final StringBuilder errmsg = new StringBuilder();
136  if( EUI48Sub.scanEUI48Sub(addrOrNameSub, addr1, errmsg) ) {
137  waitForDevices.add( new DeviceQuery( addr1 ) );
138  } else {
139  addr1.clear();
140  waitForDevices.add( new DeviceQuery( addrOrNameSub ) );
141  }
142  }
143  public static boolean isWaitingForAnyDevice() {
144  return waitForDevices.size()>0;
145  }
146  public static int getWaitForDevicesCount() {
147  return waitForDevices.size();
148  }
149  public static String getWaitForDevicesString() {
150  return Arrays.toString(waitForDevices.toArray());
151  }
152  /**
153  * Returns the reference of the current list of {@link DeviceQuery}, not a copy.
154  */
155  public static List<DeviceQuery> getWaitForDevices() {
156  return waitForDevices;
157  }
158  /**
159  * Clears internal list
160  */
161  public static void clearWaitForDevices() {
162  waitForDevices.clear();
163  }
164 
165  public static void addToProcessedDevices(final BDAddressAndType a, final String n) {
166  devicesProcessed.add( new DeviceID(a, n) );
167  }
168  public static boolean isDeviceProcessed(final BDAddressAndType a) {
169  return devicesProcessed.contains( new DeviceID(a, null) );
170  }
171  public static int getProcessedDeviceCount() {
172  return devicesProcessed.size();
173  }
174  public static String getProcessedDevicesString() {
175  return Arrays.toString(devicesProcessed.toArray());
176  }
177  /**
178  * Returns a copy of the current collection of processed {@link DeviceID}.
179  */
180  public static List<DeviceID> getProcessedDevices() {
181  return new ArrayList<DeviceID>(devicesProcessed);
182  }
183  /**
184  * Clears internal list
185  */
186  public static void clearProcessedDevices() {
187  devicesProcessed.clear();
188  }
189 
190  /**
191  * Interface for user defined {@link DeviceQuery} matching criteria and algorithm.
192  */
193  public static interface DeviceQueryMatch {
194  /**
195  * Return {@code true} if the given {@code address} and/or {@code name} matches
196  * with the {@link DeviceQuery}'s {@link DeviceQuery#addressSub addressSub} and/or
197  * {@link DeviceQuery#nameSub nameSub}.
198  * <p>
199  * Example (lambda):
200  * <pre>
201  * (final EUI48 a, final String n, final DeviceQuery q) -> {
202  * return q.isEUI48Sub() ? a.contains(q.addressSub) : n.indexOf(q.nameSub) >= 0;
203  * }
204  * </pre>
205  * </p>
206  */
207  public boolean match(final EUI48 address, final String name, final DeviceQuery q);
208  }
209 
210  /**
211  * Returns {@code true} if the given {@code address} and/or {@code name}
212  * {@link DeviceQueryMatch#match(EUI48, String, DeviceQuery) matches}
213  * any of the {@link #addToWaitForDevices(String) awaited devices}.
214  * <p>
215  * Matching criteria and algorithm is defined by the given {@link DeviceQueryMatch}.
216  * </p>
217  * @see #isWaitingForDevice(EUI48, String)
218  */
219  public static boolean isWaitingForDevice(final EUI48 address, final String name,
220  final DeviceQueryMatch m) {
221  for(final Iterator<DeviceQuery> it=waitForDevices.iterator(); it.hasNext(); ) {
222  final DeviceQuery q = it.next();
223  if( m.match(address, name, q) ) {
224  return true;
225  }
226  }
227  return false;
228  }
229  /**
230  * Returns {@code true} if the given {@code address} and/or {@code name}
231  * {@link DeviceQueryMatch#match(EUI48, String, DeviceQuery) matches}
232  * any of the {@link #addToWaitForDevices(String) awaited devices}.
233  * <p>
234  * Matching criteria is either the awaited device's {@link DeviceQuery#addressSub}
235  * or {@link DeviceQuery#nameSub}, whichever is set.
236  * </p>
237  * <p>
238  * Matching algorithm is a simple {@code contains} pattern match,
239  * i.e. the given {@code address} or {@code name} contains the corresponding {@link DeviceQuery} element.
240  * </p>
241  * @see #isWaitingForDevice(EUI48, String, DeviceQueryMatch)
242  */
243  public static boolean isWaitingForDevice(final EUI48 address, final String name) {
244  return isWaitingForDevice( address, name,
245  (final EUI48 a, final String n, final DeviceQuery q) -> {
246  return q.isEUI48Sub() ? a.contains(q.addressSub) : n.indexOf(q.nameSub) >= 0;
247  });
248  }
249 
250  /**
251  * Returns {@code true} if all {@link #addToWaitForDevices(String) awaited devices}
252  * have been {@link #addToProcessedDevices(BDAddressAndType, String) processed}.
253  * <p>
254  * Matching criteria and algorithm is defined by the given {@link DeviceQueryMatch}.
255  * </p>
256  * @see #areAllDevicesProcessed()
257  */
258  public static boolean areAllDevicesProcessed(final DeviceQueryMatch m) {
259  for(final Iterator<DeviceQuery> it1=waitForDevices.iterator(); it1.hasNext(); ) {
260  final DeviceQuery q = it1.next();
261  final Iterator<DeviceID> it2=devicesProcessed.iterator();
262  while( it2.hasNext() ) {
263  final DeviceID id = it2.next();
264  if( m.match(id.addressAndType.address, id.name, q) ) {
265  break;
266  }
267  }
268  if( !it2.hasNext() ) {
269  return false;
270  }
271  }
272  return true;
273  }
274  /**
275  * Returns {@code true} if all {@link #addToWaitForDevices(String) awaited devices}
276  * have been {@link #addToProcessedDevices(BDAddressAndType, String) processed}.
277  * <p>
278  * Matching criteria is either the awaited device's {@link DeviceQuery#addressSub}
279  * or {@link DeviceQuery#nameSub}, whichever is set.
280  * </p>
281  * <p>
282  * Matching algorithm is a simple {@code contains} pattern match,
283  * i.e. the processed {@link DeviceID} contains one element of {@link DeviceQuery}.
284  * </p>
285  * @see #areAllDevicesProcessed(DeviceQueryMatch)
286  */
287  public static boolean areAllDevicesProcessed() {
288  return areAllDevicesProcessed( (final EUI48 a, final String n, final DeviceQuery q) -> {
289  return q.isEUI48Sub() ? a.contains(q.addressSub) : n.indexOf(q.nameSub) >= 0;
290  });
291  }
292 
293 
294  public static void addToProcessingDevices(final BDAddressAndType a, final String n) {
295  devicesInProcessing.add( new DeviceID(a, n) );
296  }
297  public static boolean removeFromProcessingDevices(final BDAddressAndType a) {
298  return devicesInProcessing.remove( new DeviceID(a, null) );
299  }
300  public static boolean isDeviceProcessing(final BDAddressAndType a) {
301  return devicesInProcessing.contains( new DeviceID(a, null) );
302  }
303  public static int getProcessingDeviceCount() {
304  return devicesInProcessing.size();
305  }
306  /**
307  * Returns a copy of the current collection of processing {@link DeviceID}.
308  */
309  public static List<DeviceID> getProcessingDevices() {
310  return new ArrayList<DeviceID>(devicesInProcessing);
311  }
312  /**
313  * Clears internal list
314  */
315  public static void clearProcessingDevices() {
316  devicesInProcessing.clear();
317  }
318 }
org.direct_bt.BTDeviceRegistry.clearProcessingDevices
static void clearProcessingDevices()
Clears internal list.
Definition: BTDeviceRegistry.java:315
org.direct_bt.BDAddressAndType.equals
final boolean equals(final Object obj)
Definition: BDAddressAndType.java:107
org.direct_bt.EUI48.contains
boolean contains(final EUI48Sub needle)
Returns true, if given EUI48Sub is contained in here.
Definition: EUI48.java:265
org.direct_bt.BTDeviceRegistry.getProcessingDeviceCount
static int getProcessingDeviceCount()
Definition: BTDeviceRegistry.java:303
org.direct_bt.BTDeviceRegistry.isWaitingForAnyDevice
static boolean isWaitingForAnyDevice()
Definition: BTDeviceRegistry.java:143
org.direct_bt.BTDeviceRegistry
Application toolkit providing BT device registration of processed and awaited devices.
Definition: BTDeviceRegistry.java:40
org.direct_bt.BTDeviceRegistry.getWaitForDevicesString
static String getWaitForDevicesString()
Definition: BTDeviceRegistry.java:149
org.direct_bt.BTDeviceRegistry.DeviceID.toString
String toString()
Definition: BTDeviceRegistry.java:126
org.direct_bt.BTDeviceRegistry.DeviceQuery.type
final Type type
Definition: BTDeviceRegistry.java:55
org.direct_bt.BTDeviceRegistry.DeviceQueryMatch.match
boolean match(final EUI48 address, final String name, final DeviceQuery q)
Return.
org.direct_bt.BTDeviceRegistry.clearWaitForDevices
static void clearWaitForDevices()
Clears internal list.
Definition: BTDeviceRegistry.java:161
org.direct_bt.BTDeviceRegistry.DeviceQuery.Type
DeviceQuery type, i.e.
Definition: BTDeviceRegistry.java:48
org.direct_bt.EUI48Sub
A 48 bit EUI-48 sub-identifier, see EUI48.
Definition: EUI48Sub.java:31
org.direct_bt.EUI48
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Definition: EUI48.java:37
org.direct_bt.EUI48Sub.ANY_DEVICE
static final EUI48Sub ANY_DEVICE
EUI48Sub MAC address matching any device, i.e.
Definition: EUI48Sub.java:33
org.direct_bt.BTDeviceRegistry.DeviceQuery.isEUI48Sub
final boolean isEUI48Sub()
Definition: BTDeviceRegistry.java:70
org.direct_bt.BTDeviceRegistry.areAllDevicesProcessed
static boolean areAllDevicesProcessed()
Returns.
Definition: BTDeviceRegistry.java:287
org.direct_bt.BTDeviceRegistry.removeFromProcessingDevices
static boolean removeFromProcessingDevices(final BDAddressAndType a)
Definition: BTDeviceRegistry.java:297
org.direct_bt.BTDeviceRegistry.DeviceQuery
Specifies devices queries to act upon.
Definition: BTDeviceRegistry.java:44
org.direct_bt.BTDeviceRegistry.DeviceQuery.DeviceQuery
DeviceQuery(final EUI48Sub as)
Definition: BTDeviceRegistry.java:59
org.direct_bt.BTDeviceRegistry.DeviceQuery.Type.NAME
NAME
DeviceQuery type, using a sensor device String name.
Definition: BTDeviceRegistry.java:52
org.direct_bt.BTDeviceRegistry.isWaitingForDevice
static boolean isWaitingForDevice(final EUI48 address, final String name)
Returns.
Definition: BTDeviceRegistry.java:243
org.direct_bt.BTDeviceRegistry.getProcessingDevices
static List< DeviceID > getProcessingDevices()
Returns a copy of the current collection of processing DeviceID.
Definition: BTDeviceRegistry.java:309
org.direct_bt.EUI48Sub.clear
void clear()
Method clears the underlying byte array b and sets length to zero.
Definition: EUI48Sub.java:184
org.direct_bt.BTDeviceRegistry.DeviceQueryMatch
Interface for user defined DeviceQuery matching criteria and algorithm.
Definition: BTDeviceRegistry.java:193
org.direct_bt.BTDeviceRegistry.isDeviceProcessing
static boolean isDeviceProcessing(final BDAddressAndType a)
Definition: BTDeviceRegistry.java:300
org.direct_bt.BTDeviceRegistry.getWaitForDevices
static List< DeviceQuery > getWaitForDevices()
Returns the reference of the current list of DeviceQuery, not a copy.
Definition: BTDeviceRegistry.java:155
org.direct_bt.BTDeviceRegistry.addToWaitForDevices
static void addToWaitForDevices(final String addrOrNameSub)
Definition: BTDeviceRegistry.java:133
org.direct_bt.BTDeviceRegistry.DeviceQuery.addressSub
final EUI48Sub addressSub
Definition: BTDeviceRegistry.java:56
org.direct_bt.BTDeviceRegistry.DeviceID.addressAndType
final BDAddressAndType addressAndType
Definition: BTDeviceRegistry.java:88
org.direct_bt.BTDeviceRegistry.DeviceQuery.DeviceQuery
DeviceQuery(final String ns)
Definition: BTDeviceRegistry.java:64
org.direct_bt.BDAddressAndType
Unique Bluetooth EUI48 address and BDAddressType tuple.
Definition: BDAddressAndType.java:36
org.direct_bt.BTDeviceRegistry.DeviceID
Specifies unique device identities, using BDAddressAndType as key.
Definition: BTDeviceRegistry.java:87
org.direct_bt.BTDeviceRegistry.areAllDevicesProcessed
static boolean areAllDevicesProcessed(final DeviceQueryMatch m)
Returns.
Definition: BTDeviceRegistry.java:258
org.direct_bt.BTDeviceRegistry.addToProcessedDevices
static void addToProcessedDevices(final BDAddressAndType a, final String n)
Definition: BTDeviceRegistry.java:165
org.direct_bt.BTDeviceRegistry.DeviceID.equals
final boolean equals(final Object obj)
Definition: BTDeviceRegistry.java:103
org.direct_bt.BTDeviceRegistry.DeviceQuery.toString
String toString()
Definition: BTDeviceRegistry.java:73
org.direct_bt.BTDeviceRegistry.getProcessedDevicesString
static String getProcessedDevicesString()
Definition: BTDeviceRegistry.java:174
org.direct_bt.BTDeviceRegistry.clearProcessedDevices
static void clearProcessedDevices()
Clears internal list.
Definition: BTDeviceRegistry.java:186
org.direct_bt.BTDeviceRegistry.getWaitForDevicesCount
static int getWaitForDevicesCount()
Definition: BTDeviceRegistry.java:146
org.direct_bt.EUI48Sub.scanEUI48Sub
static boolean scanEUI48Sub(final String str, final EUI48Sub dest, final StringBuilder errmsg)
Fills given EUI48Sub instance via given string representation.
Definition: EUI48Sub.java:64
org.direct_bt.BTDeviceRegistry.isDeviceProcessed
static boolean isDeviceProcessed(final BDAddressAndType a)
Definition: BTDeviceRegistry.java:168
org.direct_bt.BTDeviceRegistry.addToProcessingDevices
static void addToProcessingDevices(final BDAddressAndType a, final String n)
Definition: BTDeviceRegistry.java:294
org.direct_bt.BDAddressAndType.hashCode
final int hashCode()
Definition: BDAddressAndType.java:126
org.direct_bt.BTDeviceRegistry.getProcessedDeviceCount
static int getProcessedDeviceCount()
Definition: BTDeviceRegistry.java:171
org.direct_bt.BTDeviceRegistry.DeviceID.hashCode
final int hashCode()
Definition: BTDeviceRegistry.java:121
org.direct_bt.BTDeviceRegistry.isWaitingForDevice
static boolean isWaitingForDevice(final EUI48 address, final String name, final DeviceQueryMatch m)
Returns.
Definition: BTDeviceRegistry.java:219
org.direct_bt.EUI48Sub.toString
final String toString()
Definition: EUI48Sub.java:259
org.direct_bt.BTDeviceRegistry.DeviceQuery.Type.EUI48SUB
EUI48SUB
DeviceQuery type, using a sensor device EUI48Sub.
Definition: BTDeviceRegistry.java:50
org.direct_bt.BTDeviceRegistry.DeviceID.name
final String name
Definition: BTDeviceRegistry.java:89
org.direct_bt.BTDeviceRegistry.DeviceQuery.nameSub
final String nameSub
Definition: BTDeviceRegistry.java:57
org.direct_bt.BTDeviceRegistry.DeviceID.DeviceID
DeviceID(final BDAddressAndType a, final String n)
Definition: BTDeviceRegistry.java:90
org.direct_bt.BTDeviceRegistry.getProcessedDevices
static List< DeviceID > getProcessedDevices()
Returns a copy of the current collection of processed DeviceID.
Definition: BTDeviceRegistry.java:180