View Javadoc
1   package fr.ifremer.tutti.ichtyometer;
2   
3   /*
4    * #%L
5    * Tutti :: Ichtyometer API
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2012 - 2015 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU General Public License as
13   * published by the Free Software Foundation, either version 3 of the
14   * License, or (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public
22   * License along with this program.  If not, see
23   * <http://www.gnu.org/licenses/gpl-3.0.html>.
24   * #L%
25   */
26  
27  import com.google.common.collect.Maps;
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  
31  import javax.bluetooth.BluetoothStateException;
32  import javax.bluetooth.DeviceClass;
33  import javax.bluetooth.DiscoveryAgent;
34  import javax.bluetooth.DiscoveryListener;
35  import javax.bluetooth.LocalDevice;
36  import javax.bluetooth.RemoteDevice;
37  import javax.bluetooth.ServiceRecord;
38  import java.io.IOException;
39  import java.util.Map;
40  
41  /**
42   * Created on 4/4/15.
43   *
44   * @author Tony Chemit - chemit@codelutin.com
45   * @since 3.14.4
46   */
47  public class RemoteDevicesFinder {
48  
49      /** Logger. */
50      private static final Log log = LogFactory.getLog(RemoteDevicesFinder.class);
51  
52      private final Map<String, RemoteDevice> devices;
53  
54      private final int maximumNumberOfTryToConnect;
55  
56      private final Object lock;
57  
58      public RemoteDevicesFinder(int maximumNumberOfTryToConnect, Object lock) {
59          this.maximumNumberOfTryToConnect = maximumNumberOfTryToConnect;
60          this.lock = lock;
61          this.devices = Maps.newTreeMap();
62      }
63  
64      public Map<String, RemoteDevice> findDevices(LocalDevice localDevice) throws BluetoothStateException, InterruptedException {
65  
66          DevicesDiscoveryListener listener = new DevicesDiscoveryListener();
67  
68  
69          synchronized (lock) {
70  
71              int tryRound = 0;
72  
73              while (tryRound < maximumNumberOfTryToConnect && devices.isEmpty()) {
74  
75                  boolean started = localDevice.getDiscoveryAgent().startInquiry(DiscoveryAgent.LIAC, listener);
76                  if (started) {
77                      if (log.isInfoEnabled()) {
78                          log.info("Wait for device inquiry to complete... (try " + tryRound + ")");
79                      }
80                      lock.wait();
81                      if (log.isInfoEnabled()) {
82                          log.info(devices.size() + " device(s) found");
83                      }
84                  }
85                  tryRound++;
86              }
87  
88          }
89  
90          return devices;
91  
92      }
93  
94      protected class DevicesDiscoveryListener implements DiscoveryListener {
95  
96          @Override
97          public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
98              if (log.isInfoEnabled()) {
99                  log.info("Device " + btDevice.getBluetoothAddress() + " found");
100             }
101 
102             String friendlyName = null;
103 
104             int tryRound = 0;
105 
106             while (tryRound < maximumNumberOfTryToConnect && friendlyName == null) {
107 
108                 if (log.isInfoEnabled()) {
109                     log.info("Try to get device friendlyName (try " + tryRound + ")");
110                 }
111                 friendlyName = getName(btDevice);
112 
113                 tryRound++;
114             }
115 
116             if (friendlyName == null) {
117                 throw new RemoteDeviceCantGetNameException(btDevice.getBluetoothAddress());
118             }
119 
120             devices.put(friendlyName, btDevice);
121         }
122 
123         protected String getName(RemoteDevice btDevice) {
124             String friendlyName = null;
125             try {
126                 friendlyName = btDevice.getFriendlyName(false);
127                 if (log.isInfoEnabled()) {
128                     log.info("Name: " + friendlyName);
129                 }
130             } catch (IOException e) {
131                 if (log.isDebugEnabled()) {
132                     log.debug("Can't get name of remote", e);
133                 }
134 
135             }
136             return friendlyName;
137         }
138 
139         @Override
140         public void inquiryCompleted(int discType) {
141             if (log.isDebugEnabled()) {
142                 log.debug("Device Inquiry completed!");
143             }
144             synchronized (lock) {
145                 lock.notifyAll();
146             }
147         }
148 
149         @Override
150         public void serviceSearchCompleted(int transID, int respCode) {
151         }
152 
153         @Override
154         public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
155         }
156 
157     }
158 
159 }