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.lametrictime.internal.discovery;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.List;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.openhab.binding.lametrictime.internal.LaMetricTimeBindingConstants;
22 import org.openhab.binding.lametrictime.internal.LaMetricTimeUtil;
23 import org.openhab.binding.lametrictime.internal.api.dto.CoreApps;
24 import org.openhab.binding.lametrictime.internal.api.local.dto.Application;
25 import org.openhab.binding.lametrictime.internal.api.local.dto.Widget;
26 import org.openhab.binding.lametrictime.internal.config.LaMetricTimeAppConfiguration;
27 import org.openhab.binding.lametrictime.internal.handler.LaMetricTimeAppHandler;
28 import org.openhab.binding.lametrictime.internal.handler.LaMetricTimeHandler;
29 import org.openhab.core.config.discovery.AbstractDiscoveryService;
30 import org.openhab.core.config.discovery.DiscoveryResult;
31 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.thing.ThingTypeUID;
34 import org.openhab.core.thing.ThingUID;
35 import org.openhab.core.thing.binding.ThingHandler;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 import com.google.gson.JsonPrimitive;
42 * The {@link LaMetricTimeAppDiscoveryService} is responsible for processing the
43 * list of apps found on the LaMetric Time device.
45 * @author Gregory Moyer - Initial contribution
48 public class LaMetricTimeAppDiscoveryService extends AbstractDiscoveryService {
50 private static final Map<String, ThingTypeUID> CORE_APP_THING_TYPE_UIDS = new HashMap<>();
52 CORE_APP_THING_TYPE_UIDS.put(CoreApps.clock().getPackageName(),
53 LaMetricTimeBindingConstants.THING_TYPE_CLOCK_APP);
54 CORE_APP_THING_TYPE_UIDS.put(CoreApps.countdown().getPackageName(),
55 LaMetricTimeBindingConstants.THING_TYPE_COUNTDOWN_APP);
56 CORE_APP_THING_TYPE_UIDS.put(CoreApps.radio().getPackageName(),
57 LaMetricTimeBindingConstants.THING_TYPE_RADIO_APP);
58 CORE_APP_THING_TYPE_UIDS.put(CoreApps.stopwatch().getPackageName(),
59 LaMetricTimeBindingConstants.THING_TYPE_STOPWATCH_APP);
60 CORE_APP_THING_TYPE_UIDS.put(CoreApps.weather().getPackageName(),
61 LaMetricTimeBindingConstants.THING_TYPE_WEATHER_APP);
64 private static final int TIMEOUT = 60;
66 private final Logger logger = LoggerFactory.getLogger(LaMetricTimeAppDiscoveryService.class);
68 private final LaMetricTimeHandler deviceHandler;
71 * Discovers apps on the LaMetric Time device.
73 * @param deviceHandler the LaMetric Time device handler (bridge)
75 public LaMetricTimeAppDiscoveryService(final LaMetricTimeHandler deviceHandler) {
76 super(new HashSet<>(CORE_APP_THING_TYPE_UIDS.values()), TIMEOUT, false);
77 this.deviceHandler = deviceHandler;
81 protected void startScan() {
82 logger.debug("Starting scan for new apps");
84 ThingUID bridgeUID = deviceHandler.getThing().getUID();
85 List<Thing> existingThings = deviceHandler.getThing().getThings();
87 for (Application app : deviceHandler.getApps().values()) {
88 String packageName = app.getPackageName();
90 ThingTypeUID thingType = CORE_APP_THING_TYPE_UIDS.get(packageName);
91 if (thingType == null) {
96 for (Widget widget : app.getWidgets().values()) {
97 String widgetId = widget.getId();
98 ThingUID thingUID = new ThingUID(thingType, bridgeUID, widgetId);
100 // check if thing already exists
101 if (containsThing(existingThings, widgetId)) {
105 logger.debug("New app {} instance found with widget ID {}", packageName, widgetId);
107 Map<String, Object> properties = new HashMap<>();
108 properties.put(LaMetricTimeAppConfiguration.PACKAGE_NAME, app.getPackageName());
109 properties.put(LaMetricTimeAppConfiguration.WIDGET_ID, widgetId);
110 properties.put(Thing.PROPERTY_VENDOR, app.getVendor());
111 properties.put(Thing.PROPERTY_FIRMWARE_VERSION, app.getVersion());
113 Map<String, JsonPrimitive> settings = widget.getSettings();
114 if (settings != null) {
115 settings.entrySet().stream().forEach(entry -> properties.put(entry.getKey(), entry.getValue()));
118 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
119 .withBridge(bridgeUID).withLabel(LaMetricTimeUtil.getAppLabel(app, widget)).build();
120 thingDiscovered(discoveryResult);
125 private boolean containsThing(List<Thing> things, String widgetId) {
126 return things.stream().anyMatch(thing -> {
127 ThingHandler handler = thing.getHandler();
128 if (!(handler instanceof LaMetricTimeAppHandler)) {
132 Widget widget = ((LaMetricTimeAppHandler) handler).getWidget();
133 return widget.getId().equals(widgetId);