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