2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.bluetooth;
15 import java.time.ZonedDateTime;
16 import java.util.Collection;
19 import java.util.UUID;
20 import java.util.concurrent.ConcurrentHashMap;
21 import java.util.concurrent.CopyOnWriteArraySet;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
29 * The {@link BaseBluetoothDevice} implements parts of the BluetoothDevice functionality that is
30 * shared to all concrete BluetoothDevice implementations.
32 * @author Connor Petty - Initial Contribution
35 public abstract class BaseBluetoothDevice extends BluetoothDevice {
37 private final Logger logger = LoggerFactory.getLogger(BaseBluetoothDevice.class);
40 * Current connection state
42 protected ConnectionState connectionState = ConnectionState.DISCOVERING;
47 protected @Nullable Integer manufacturer = null;
52 * Uses the devices long name if known, otherwise the short name if known
54 protected @Nullable String name;
57 * List of supported services
59 protected final Map<UUID, BluetoothService> supportedServices = new ConcurrentHashMap<>();
64 protected @Nullable Integer rssi = null;
67 * Last reported transmitter power
69 protected @Nullable Integer txPower = null;
71 protected final transient ZonedDateTime createTime = ZonedDateTime.now();
74 * Last time when activity occurred on this device.
76 protected @Nullable ZonedDateTime lastSeenTime = null;
79 * The event listeners will be notified of device updates
81 private final Set<BluetoothDeviceListener> eventListeners = new CopyOnWriteArraySet<>();
84 * Construct a Bluetooth device taking the Bluetooth address
89 public BaseBluetoothDevice(BluetoothAdapter adapter, BluetoothAddress address) {
90 super(adapter, address);
94 * Returns the last time this device was active
96 * @return The last time this device was active
98 public @Nullable ZonedDateTime getLastSeenTime() {
103 * Updates the last activity timestamp for this device.
104 * Should be called whenever activity occurs on this device.
107 public void updateLastSeenTime() {
108 lastSeenTime = ZonedDateTime.now();
112 * Returns the name of the Bluetooth device.
114 * @return The devices name
117 public @Nullable String getName() {
122 * Sets the manufacturer id for the device
124 * @param manufacturer the manufacturer id
126 public void setManufacturerId(int manufacturer) {
127 this.manufacturer = manufacturer;
131 * Returns the manufacturer ID of the device
133 * @return an integer with manufacturer ID of the device, or null if not known
136 public @Nullable Integer getManufacturerId() {
141 * Returns a {@link BluetoothService} if the requested service is supported
143 * @return the {@link BluetoothService} or null if the service is not supported.
146 public @Nullable BluetoothService getServices(UUID uuid) {
147 return supportedServices.get(uuid);
151 * Returns a list of supported service UUIDs
153 * @return list of supported {@link BluetoothService}s.
156 public Collection<BluetoothService> getServices() {
157 return supportedServices.values();
161 * Sets the device transmit power
163 * @param power the current transmitter power in dBm
165 public void setTxPower(int txPower) {
166 this.txPower = txPower;
170 * Returns the last Transmit Power value or null if no transmit power has been received
172 * @return the last reported transmitter power value in dBm
175 public @Nullable Integer getTxPower() {
180 * Sets the current Receive Signal Strength Indicator (RSSI) value
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
185 public boolean setRssi(int rssi) {
186 boolean changed = (this.rssi == null || this.rssi != rssi);
193 * Returns the last Receive Signal Strength Indicator (RSSI) value or null if no RSSI has been received
195 * @return the last RSSI value in dBm
198 public @Nullable Integer getRssi() {
203 * Set the name of the device
205 * @param name a {@link String} defining the device name
207 public void setName(String name) {
212 * Check if the device supports the specified service
214 * @param uuid the service {@link UUID}
215 * @return true if the service is supported
218 public boolean supportsService(UUID uuid) {
219 return supportedServices.containsKey(uuid);
223 * Get the current connection state for this device
225 * @return the current {@link ConnectionState}
228 public ConnectionState getConnectionState() {
229 return connectionState;
233 * Adds a service to the device.
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
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);
249 protected Collection<BluetoothDeviceListener> getListeners() {
250 return eventListeners;
254 * Releases resources that this device is using.
258 protected void dispose() {
262 protected void notifyListeners(BluetoothEventType event, Object... args) {
265 case CHARACTERISTIC_UPDATED:
266 case DESCRIPTOR_UPDATED:
267 case SERVICES_DISCOVERED:
268 updateLastSeenTime();
273 super.notifyListeners(event, args);
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));
288 builder.append(", name=");
289 builder.append(name);
290 builder.append(", rssi=");
291 builder.append(rssi);
293 return builder.toString();