]> git.basschouten.com Git - openhab-addons.git/blob
774de7dab6912cf20c85cee91142604d4616665e
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.bluetooth;
14
15 import java.time.ZonedDateTime;
16 import java.util.Collection;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.UUID;
20 import java.util.concurrent.ConcurrentHashMap;
21 import java.util.concurrent.CopyOnWriteArraySet;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * The {@link BaseBluetoothDevice} implements parts of the BluetoothDevice functionality that is
30  * shared to all concrete BluetoothDevice implementations.
31  *
32  * @author Connor Petty - Initial Contribution
33  */
34 @NonNullByDefault
35 public abstract class BaseBluetoothDevice extends BluetoothDevice {
36
37     private final Logger logger = LoggerFactory.getLogger(BaseBluetoothDevice.class);
38
39     /**
40      * Current connection state
41      */
42     protected ConnectionState connectionState = ConnectionState.DISCOVERING;
43
44     /**
45      * Manufacturer id
46      */
47     protected @Nullable Integer manufacturer = null;
48
49     /**
50      * Device name.
51      * <p>
52      * Uses the devices long name if known, otherwise the short name if known
53      */
54     protected @Nullable String name;
55
56     /**
57      * List of supported services
58      */
59     protected final Map<UUID, BluetoothService> supportedServices = new ConcurrentHashMap<>();
60
61     /**
62      * Last known RSSI
63      */
64     protected @Nullable Integer rssi = null;
65
66     /**
67      * Last reported transmitter power
68      */
69     protected @Nullable Integer txPower = null;
70
71     protected final transient ZonedDateTime createTime = ZonedDateTime.now();
72
73     /**
74      * Last time when activity occurred on this device.
75      */
76     protected @Nullable ZonedDateTime lastSeenTime = null;
77
78     /**
79      * The event listeners will be notified of device updates
80      */
81     private final Set<BluetoothDeviceListener> eventListeners = new CopyOnWriteArraySet<>();
82
83     /**
84      * Construct a Bluetooth device taking the Bluetooth address
85      *
86      * @param adapter
87      * @param sender
88      */
89     public BaseBluetoothDevice(BluetoothAdapter adapter, BluetoothAddress address) {
90         super(adapter, address);
91     }
92
93     /**
94      * Returns the last time this device was active
95      *
96      * @return The last time this device was active
97      */
98     public @Nullable ZonedDateTime getLastSeenTime() {
99         return lastSeenTime;
100     }
101
102     /**
103      * Updates the last activity timestamp for this device.
104      * Should be called whenever activity occurs on this device.
105      *
106      */
107     public void updateLastSeenTime() {
108         lastSeenTime = ZonedDateTime.now();
109     }
110
111     /**
112      * Returns the name of the Bluetooth device.
113      *
114      * @return The devices name
115      */
116     @Override
117     public @Nullable String getName() {
118         return name;
119     }
120
121     /**
122      * Sets the manufacturer id for the device
123      *
124      * @param manufacturer the manufacturer id
125      */
126     public void setManufacturerId(int manufacturer) {
127         this.manufacturer = manufacturer;
128     }
129
130     /**
131      * Returns the manufacturer ID of the device
132      *
133      * @return an integer with manufacturer ID of the device, or null if not known
134      */
135     @Override
136     public @Nullable Integer getManufacturerId() {
137         return manufacturer;
138     }
139
140     /**
141      * Returns a {@link BluetoothService} if the requested service is supported
142      *
143      * @return the {@link BluetoothService} or null if the service is not supported.
144      */
145     @Override
146     public @Nullable BluetoothService getServices(UUID uuid) {
147         return supportedServices.get(uuid);
148     }
149
150     /**
151      * Returns a list of supported service UUIDs
152      *
153      * @return list of supported {@link BluetoothService}s.
154      */
155     @Override
156     public Collection<BluetoothService> getServices() {
157         return supportedServices.values();
158     }
159
160     /**
161      * Sets the device transmit power
162      *
163      * @param power the current transmitter power in dBm
164      */
165     public void setTxPower(int txPower) {
166         this.txPower = txPower;
167     }
168
169     /**
170      * Returns the last Transmit Power value or null if no transmit power has been received
171      *
172      * @return the last reported transmitter power value in dBm
173      */
174     @Override
175     public @Nullable Integer getTxPower() {
176         return txPower;
177     }
178
179     /**
180      * Sets the current Receive Signal Strength Indicator (RSSI) value
181      *
182      * @param rssi the current RSSI value in dBm
183      * @return true if the RSSI has changed, false if it was the same as previous
184      */
185     public boolean setRssi(int rssi) {
186         boolean changed = (this.rssi == null || this.rssi != rssi);
187         this.rssi = rssi;
188
189         return changed;
190     }
191
192     /**
193      * Returns the last Receive Signal Strength Indicator (RSSI) value or null if no RSSI has been received
194      *
195      * @return the last RSSI value in dBm
196      */
197     @Override
198     public @Nullable Integer getRssi() {
199         return rssi;
200     }
201
202     /**
203      * Set the name of the device
204      *
205      * @param name a {@link String} defining the device name
206      */
207     public void setName(String name) {
208         this.name = name;
209     }
210
211     /**
212      * Check if the device supports the specified service
213      *
214      * @param uuid the service {@link UUID}
215      * @return true if the service is supported
216      */
217     @Override
218     public boolean supportsService(UUID uuid) {
219         return supportedServices.containsKey(uuid);
220     }
221
222     /**
223      * Get the current connection state for this device
224      *
225      * @return the current {@link ConnectionState}
226      */
227     @Override
228     public ConnectionState getConnectionState() {
229         return connectionState;
230     }
231
232     /**
233      * Adds a service to the device.
234      *
235      * @param service the new {@link BluetoothService} to add
236      * @return true if the service was added or false if the service was already supported
237      */
238     @Override
239     protected boolean addService(BluetoothService service) {
240         BluetoothService oldValue = supportedServices.putIfAbsent(service.getUuid(), service);
241         if (oldValue == null) {
242             logger.trace("Adding new service to device {}: {}", address, service);
243             return true;
244         }
245         return false;
246     }
247
248     @Override
249     protected Collection<BluetoothDeviceListener> getListeners() {
250         return eventListeners;
251     }
252
253     /**
254      * Releases resources that this device is using.
255      *
256      */
257     @Override
258     protected void dispose() {
259     }
260
261     @Override
262     protected void notifyListeners(BluetoothEventType event, Object... args) {
263         switch (event) {
264             case SCAN_RECORD:
265             case CHARACTERISTIC_UPDATED:
266             case DESCRIPTOR_UPDATED:
267             case SERVICES_DISCOVERED:
268                 updateLastSeenTime();
269                 break;
270             default:
271                 break;
272         }
273         super.notifyListeners(event, args);
274     }
275
276     @Override
277     public String toString() {
278         StringBuilder builder = new StringBuilder();
279         builder.append("BluetoothDevice [address=");
280         builder.append(address);
281         builder.append(", manufacturer=");
282         builder.append(manufacturer);
283         if (BluetoothCompanyIdentifiers.get(manufacturer) != null) {
284             builder.append(" (");
285             builder.append(BluetoothCompanyIdentifiers.get(manufacturer));
286             builder.append(')');
287         }
288         builder.append(", name=");
289         builder.append(name);
290         builder.append(", rssi=");
291         builder.append(rssi);
292         builder.append(']');
293         return builder.toString();
294     }
295 }