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.bluez.internal.discovery;
15 import java.util.Collections;
17 import org.openhab.binding.bluetooth.bluez.BlueZAdapterConstants;
18 import org.openhab.core.config.discovery.AbstractDiscoveryService;
19 import org.openhab.core.config.discovery.DiscoveryResult;
20 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
21 import org.openhab.core.config.discovery.DiscoveryService;
22 import org.openhab.core.thing.ThingUID;
23 import org.osgi.service.component.annotations.Component;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 import tinyb.BluetoothAdapter;
28 import tinyb.BluetoothManager;
31 * This is a discovery service, which checks whether we are running on a Linux with a BlueZ stack.
32 * If this is the case, we create a bridge handler that provides Bluetooth access through BlueZ.
34 * @author Kai Kreuzer - Initial Contribution and API
35 * @author Hilbrand Bouwkamp - Moved background scan to actual background method
38 @Component(immediate = true, service = DiscoveryService.class, configurationPid = "discovery.bluetooth.bluez")
39 public class BlueZDiscoveryService extends AbstractDiscoveryService {
41 private final Logger logger = LoggerFactory.getLogger(BlueZDiscoveryService.class);
43 private BluetoothManager manager;
45 public BlueZDiscoveryService() {
46 super(Collections.singleton(BlueZAdapterConstants.THING_TYPE_BLUEZ), 1, true);
50 protected void startBackgroundDiscovery() {
55 protected void startScan() {
57 manager = BluetoothManager.getBluetoothManager();
58 manager.getAdapters().stream().map(this::createDiscoveryResult).forEach(this::thingDiscovered);
59 } catch (UnsatisfiedLinkError e) {
60 logger.debug("Not possible to initialize the BlueZ stack. ", e);
62 } catch (RuntimeException e) {
63 // we do not get anything more specific from TinyB here
64 if (e.getMessage() != null && e.getMessage().contains("AccessDenied")) {
66 "Cannot access BlueZ stack due to permission problems. Make sure that your OS user is part of the 'bluetooth' group of BlueZ.");
68 logger.warn("Failed to scan for Bluetooth devices", e);
73 private DiscoveryResult createDiscoveryResult(BluetoothAdapter adapter) {
74 return DiscoveryResultBuilder.create(new ThingUID(BlueZAdapterConstants.THING_TYPE_BLUEZ, getId(adapter)))
75 .withLabel("Bluetooth Interface " + adapter.getName())
76 .withProperty(BlueZAdapterConstants.PROPERTY_ADDRESS, adapter.getAddress())
77 .withRepresentationProperty(BlueZAdapterConstants.PROPERTY_ADDRESS).build();
80 private String getId(BluetoothAdapter adapter) {
81 return adapter.getInterfaceName().replaceAll("[^a-zA-Z0-9_]", "");