]> git.basschouten.com Git - openhab-addons.git/blob
89e6ec1a277e67b8041ae6e2c221fe5752f09524
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.surepetcare.internal.discovery;
14
15 import static org.openhab.binding.surepetcare.internal.SurePetcareConstants.*;
16
17 import java.util.HashMap;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.concurrent.ScheduledFuture;
21 import java.util.concurrent.TimeUnit;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.surepetcare.internal.dto.SurePetcareDevice;
26 import org.openhab.binding.surepetcare.internal.dto.SurePetcareDevice.ProductType;
27 import org.openhab.binding.surepetcare.internal.dto.SurePetcareHousehold;
28 import org.openhab.binding.surepetcare.internal.dto.SurePetcarePet;
29 import org.openhab.binding.surepetcare.internal.handler.SurePetcareBridgeHandler;
30 import org.openhab.core.config.discovery.AbstractDiscoveryService;
31 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
32 import org.openhab.core.config.discovery.DiscoveryService;
33 import org.openhab.core.thing.ThingStatus;
34 import org.openhab.core.thing.ThingTypeUID;
35 import org.openhab.core.thing.ThingUID;
36 import org.openhab.core.thing.binding.ThingHandler;
37 import org.openhab.core.thing.binding.ThingHandlerService;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * The {@link SurePetcareDiscoveryService} is an implementation of a discovery service for Sure Petcare pets and
43  * devices.
44  *
45  * @author Rene Scherer - Initial contribution
46  */
47 @NonNullByDefault
48 public class SurePetcareDiscoveryService extends AbstractDiscoveryService
49         implements DiscoveryService, ThingHandlerService {
50
51     private final Logger logger = LoggerFactory.getLogger(SurePetcareDiscoveryService.class);
52
53     private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_BRIDGE);
54
55     private static final int DISCOVER_TIMEOUT_SECONDS = 5;
56     private static final int DISCOVERY_SCAN_DELAY_MINUTES = 1;
57     private static final int DISCOVERY_REFRESH_INTERVAL_HOURS = 12;
58
59     private @Nullable ScheduledFuture<?> discoveryJob;
60
61     private @NonNullByDefault({}) SurePetcareBridgeHandler bridgeHandler;
62     private @NonNullByDefault({}) ThingUID bridgeUID;
63
64     /**
65      * Creates a SurePetcareDiscoveryService with enabled autostart.
66      */
67     public SurePetcareDiscoveryService() {
68         super(SUPPORTED_THING_TYPES, DISCOVER_TIMEOUT_SECONDS);
69     }
70
71     @Override
72     public Set<ThingTypeUID> getSupportedThingTypes() {
73         return SUPPORTED_THING_TYPES;
74     }
75
76     @Override
77     public void activate() {
78         Map<String, Object> properties = new HashMap<>();
79         properties.put(DiscoveryService.CONFIG_PROPERTY_BACKGROUND_DISCOVERY, Boolean.TRUE);
80         super.activate(properties);
81     }
82
83     /* We override this method to allow a call from the thing handler factory */
84     @Override
85     public void deactivate() {
86         super.deactivate();
87     }
88
89     @Override
90     public void setThingHandler(@Nullable ThingHandler handler) {
91         if (handler instanceof SurePetcareBridgeHandler bridgeHandler) {
92             bridgeUID = bridgeHandler.getUID();
93         }
94     }
95
96     @Override
97     public @Nullable ThingHandler getThingHandler() {
98         return bridgeHandler;
99     }
100
101     @Override
102     protected void startBackgroundDiscovery() {
103         logger.debug("Starting Sure Petcare household discovery");
104         stopBackgroundDiscovery();
105         discoveryJob = scheduler.scheduleWithFixedDelay(this::startScan, DISCOVERY_SCAN_DELAY_MINUTES,
106                 DISCOVERY_REFRESH_INTERVAL_HOURS * 60, TimeUnit.MINUTES);
107         logger.debug("Scheduled topology-changed job every {} hours", DISCOVERY_REFRESH_INTERVAL_HOURS);
108     }
109
110     @Override
111     protected void stopBackgroundDiscovery() {
112         ScheduledFuture<?> job = discoveryJob;
113         if (job != null) {
114             job.cancel(true);
115             discoveryJob = null;
116             logger.debug("Stopped Sure Petcare device background discovery");
117         }
118     }
119
120     @Override
121     protected void startScan() {
122         logger.debug("Starting Sure Petcare discovery scan");
123         // If the bridge is not online no other thing devices can be found, so no reason to scan at this moment.
124         removeOlderResults(getTimestampOfLastScan());
125         if (bridgeHandler.getThing().getStatus() == ThingStatus.ONLINE) {
126             logger.debug("Starting device discovery for bridge {}", bridgeUID);
127             bridgeHandler.listHouseholds().forEach(this::householdDiscovered);
128             bridgeHandler.listPets().forEach(this::petDiscovered);
129             bridgeHandler.listDevices().forEach(this::deviceDiscovered);
130         }
131     }
132
133     private void householdDiscovered(SurePetcareHousehold household) {
134         logger.debug("Discovered household: {}", household.name);
135         ThingUID thingsUID = new ThingUID(THING_TYPE_HOUSEHOLD, bridgeUID, household.id.toString());
136         Map<String, Object> properties = new HashMap<>(household.getThingProperties());
137         thingDiscovered(DiscoveryResultBuilder.create(thingsUID).withLabel(household.name).withProperties(properties)
138                 .withRepresentationProperty(PROPERTY_NAME_ID).withBridge(bridgeUID).build());
139     }
140
141     private void petDiscovered(SurePetcarePet pet) {
142         logger.debug("Discovered pet: {}", pet.name);
143         ThingUID thingsUID = new ThingUID(THING_TYPE_PET, bridgeUID, pet.id.toString());
144         Map<String, Object> properties = new HashMap<>(pet.getThingProperties());
145         thingDiscovered(DiscoveryResultBuilder.create(thingsUID).withLabel(pet.name).withProperties(properties)
146                 .withRepresentationProperty(PROPERTY_NAME_ID).withBridge(bridgeUID).build());
147     }
148
149     private void deviceDiscovered(SurePetcareDevice device) {
150         logger.debug("Discovered device: {}", device.name);
151         ThingTypeUID typeUID = null;
152         switch (ProductType.findByTypeId(device.productId)) {
153             case HUB:
154                 typeUID = THING_TYPE_HUB_DEVICE;
155                 break;
156             case CAT_FLAP:
157                 typeUID = THING_TYPE_FLAP_DEVICE;
158                 break;
159             case PET_FLAP:
160                 typeUID = THING_TYPE_FLAP_DEVICE;
161                 break;
162             case PET_FEEDER:
163                 typeUID = THING_TYPE_FEEDER_DEVICE;
164                 break;
165             case UNKNOWN:
166             default:
167                 return;
168         }
169         ThingUID thingsUID = new ThingUID(typeUID, bridgeUID, device.id.toString());
170         Map<String, Object> properties = new HashMap<>(device.getThingProperties());
171         thingDiscovered(DiscoveryResultBuilder.create(thingsUID).withLabel(device.name).withProperties(properties)
172                 .withRepresentationProperty(PROPERTY_NAME_ID).withBridge(bridgeUID).build());
173     }
174 }