2 * Copyright (c) 2010-2022 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.astro.internal.discovery;
15 import static org.openhab.binding.astro.internal.AstroBindingConstants.*;
16 import static org.openhab.binding.astro.internal.config.AstroThingConfig.*;
18 import java.util.Arrays;
19 import java.util.HashSet;
21 import java.util.Objects;
23 import java.util.concurrent.ScheduledFuture;
24 import java.util.concurrent.TimeUnit;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.openhab.core.config.discovery.AbstractDiscoveryService;
29 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
30 import org.openhab.core.config.discovery.DiscoveryService;
31 import org.openhab.core.i18n.LocaleProvider;
32 import org.openhab.core.i18n.LocationProvider;
33 import org.openhab.core.i18n.TranslationProvider;
34 import org.openhab.core.library.types.PointType;
35 import org.openhab.core.thing.ThingTypeUID;
36 import org.openhab.core.thing.ThingUID;
37 import org.osgi.service.component.annotations.Activate;
38 import org.osgi.service.component.annotations.Component;
39 import org.osgi.service.component.annotations.Reference;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 * The {@link AstroDiscoveryService} creates things based on the configured location.
46 * @author Gerhard Riegler - Initial Contribution
47 * @author Stefan Triller - Use configured location
50 @Component(service = DiscoveryService.class, configurationPid = "discovery.astro")
51 public class AstroDiscoveryService extends AbstractDiscoveryService {
52 private static final int DISCOVER_TIMEOUT_SECONDS = 2;
53 private static final int LOCATION_CHANGED_CHECK_INTERVAL = 60;
54 private static final Set<String> METEO_BASED_COUNTRIES = Set.of("NZ", "AU");
55 private static final ThingUID SUN_THING = new ThingUID(THING_TYPE_SUN, LOCAL);
56 private static final ThingUID MOON_THING = new ThingUID(THING_TYPE_MOON, LOCAL);
58 private final Logger logger = LoggerFactory.getLogger(AstroDiscoveryService.class);
60 private final LocationProvider locationProvider;
62 private @Nullable ScheduledFuture<?> astroDiscoveryJob;
63 private @Nullable PointType previousLocation;
66 public AstroDiscoveryService(final @Reference LocationProvider locationProvider,
67 final @Reference LocaleProvider localeProvider, final @Reference TranslationProvider i18nProvider,
68 @Nullable Map<String, Object> configProperties) {
69 super(new HashSet<>(Arrays.asList(new ThingTypeUID(BINDING_ID, "-"))), DISCOVER_TIMEOUT_SECONDS, true);
70 this.locationProvider = locationProvider;
71 this.localeProvider = localeProvider;
72 this.i18nProvider = i18nProvider;
73 activate(configProperties);
77 protected void startScan() {
78 logger.debug("Starting Astro discovery scan");
79 PointType location = locationProvider.getLocation();
80 if (location == null) {
81 logger.debug("LocationProvider.getLocation() is not set -> Will not provide any discovery results");
84 createResults(location);
88 protected void startBackgroundDiscovery() {
89 if (astroDiscoveryJob == null) {
90 astroDiscoveryJob = scheduler.scheduleWithFixedDelay(() -> {
91 PointType currentLocation = locationProvider.getLocation();
92 if (currentLocation != null && !Objects.equals(currentLocation, previousLocation)) {
93 logger.debug("Location has been changed from {} to {}: Creating new discovery results",
94 previousLocation, currentLocation);
95 createResults(currentLocation);
96 previousLocation = currentLocation;
98 }, 0, LOCATION_CHANGED_CHECK_INTERVAL, TimeUnit.SECONDS);
99 logger.debug("Scheduled astro location-changed job every {} seconds", LOCATION_CHANGED_CHECK_INTERVAL);
104 protected void stopBackgroundDiscovery() {
105 logger.debug("Stopping Astro device background discovery");
106 ScheduledFuture<?> discoveryJob = astroDiscoveryJob;
107 if (discoveryJob != null) {
108 discoveryJob.cancel(true);
110 astroDiscoveryJob = null;
113 public void createResults(PointType location) {
114 String propGeolocation = location.toString();
115 String country = localeProvider.getLocale().getCountry();
117 thingDiscovered(DiscoveryResultBuilder.create(SUN_THING).withLabel("Local Sun")
118 .withProperty(GEOLOCATION, propGeolocation)
119 .withProperty(USE_METEOROLOGICAL_SEASON, METEO_BASED_COUNTRIES.contains(country))
120 .withRepresentationProperty(GEOLOCATION).build());
122 thingDiscovered(DiscoveryResultBuilder.create(MOON_THING).withLabel("Local Moon")
123 .withProperty(GEOLOCATION, propGeolocation).withRepresentationProperty(GEOLOCATION).build());