2 * Copyright (c) 2010-2023 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.pulseaudio.internal.discovery;
15 import java.util.HashMap;
16 import java.util.HashSet;
19 import java.util.regex.PatternSyntaxException;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.binding.pulseaudio.internal.PulseaudioBindingConstants;
23 import org.openhab.binding.pulseaudio.internal.handler.DeviceIdentifier;
24 import org.openhab.binding.pulseaudio.internal.handler.DeviceStatusListener;
25 import org.openhab.binding.pulseaudio.internal.handler.PulseaudioBridgeHandler;
26 import org.openhab.binding.pulseaudio.internal.handler.PulseaudioHandler;
27 import org.openhab.binding.pulseaudio.internal.items.AbstractAudioDeviceConfig;
28 import org.openhab.binding.pulseaudio.internal.items.Sink;
29 import org.openhab.binding.pulseaudio.internal.items.SinkInput;
30 import org.openhab.binding.pulseaudio.internal.items.Source;
31 import org.openhab.binding.pulseaudio.internal.items.SourceOutput;
32 import org.openhab.core.config.core.Configuration;
33 import org.openhab.core.config.discovery.AbstractDiscoveryService;
34 import org.openhab.core.config.discovery.DiscoveryResult;
35 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
36 import org.openhab.core.thing.Thing;
37 import org.openhab.core.thing.ThingTypeUID;
38 import org.openhab.core.thing.ThingUID;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 * The {@link PulseaudioDeviceDiscoveryService} class is used to discover Pulseaudio
44 * devices on a Pulseaudio server.
46 * @author Tobias Bräutigam - Initial contribution
49 public class PulseaudioDeviceDiscoveryService extends AbstractDiscoveryService implements DeviceStatusListener {
51 private final Logger logger = LoggerFactory.getLogger(PulseaudioDeviceDiscoveryService.class);
53 private PulseaudioBridgeHandler pulseaudioBridgeHandler;
55 public PulseaudioDeviceDiscoveryService(PulseaudioBridgeHandler pulseaudioBridgeHandler) {
56 super(PulseaudioHandler.SUPPORTED_THING_TYPES_UIDS, 10, true);
57 this.pulseaudioBridgeHandler = pulseaudioBridgeHandler;
60 public void activate() {
61 pulseaudioBridgeHandler.registerDeviceStatusListener(this);
65 public void deactivate() {
66 pulseaudioBridgeHandler.unregisterDeviceStatusListener(this);
70 public Set<ThingTypeUID> getSupportedThingTypes() {
71 return PulseaudioHandler.SUPPORTED_THING_TYPES_UIDS;
75 public void onDeviceAdded(Thing bridge, AbstractAudioDeviceConfig device) {
76 if (getAlreadyConfiguredThings().stream().anyMatch(deviceIdentifier -> device.matches(deviceIdentifier))) {
80 String uidName = device.getPaName();
81 logger.debug("device {} found", device);
82 ThingTypeUID thingType = null;
83 Map<String, Object> properties = new HashMap<>();
84 // All devices need this parameter
85 properties.put(PulseaudioBindingConstants.DEVICE_PARAMETER_NAME_OR_DESCRIPTION, uidName);
86 if (device instanceof Sink sink) {
87 if (sink.isCombinedSink()) {
88 thingType = PulseaudioBindingConstants.COMBINED_SINK_THING_TYPE;
90 thingType = PulseaudioBindingConstants.SINK_THING_TYPE;
92 } else if (device instanceof SinkInput) {
93 thingType = PulseaudioBindingConstants.SINK_INPUT_THING_TYPE;
94 } else if (device instanceof Source) {
95 thingType = PulseaudioBindingConstants.SOURCE_THING_TYPE;
96 } else if (device instanceof SourceOutput) {
97 thingType = PulseaudioBindingConstants.SOURCE_OUTPUT_THING_TYPE;
100 if (thingType != null) {
101 logger.trace("Adding new pulseaudio {} with name '{}' to inbox", device.getClass().getSimpleName(),
103 ThingUID thingUID = new ThingUID(thingType, bridge.getUID(), device.getUIDName());
104 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
105 .withBridge(bridge.getUID()).withLabel(device.getUIDName()).build();
106 thingDiscovered(discoveryResult);
110 public Set<DeviceIdentifier> getAlreadyConfiguredThings() {
111 Set<DeviceIdentifier> alreadyConfiguredThings = new HashSet<>();
112 for (Thing thing : pulseaudioBridgeHandler.getThing().getThings()) {
113 Configuration configuration = thing.getConfiguration();
115 alreadyConfiguredThings.add(new DeviceIdentifier(
116 (String) configuration.get(PulseaudioBindingConstants.DEVICE_PARAMETER_NAME_OR_DESCRIPTION),
117 (String) configuration.get(PulseaudioBindingConstants.DEVICE_PARAMETER_ADDITIONAL_FILTERS)));
118 } catch (PatternSyntaxException p) {
120 "There is an error with an already configured things. Cannot compare with discovery, skipping it");
123 return alreadyConfiguredThings;
127 protected void startScan() {
128 pulseaudioBridgeHandler.resetKnownActiveDevices();