]> git.basschouten.com Git - openhab-addons.git/blob
62be5dad91605645435e7280e6f24e3e32336f5c
[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             this.bridgeHandler = bridgeHandler;
93             bridgeUID = bridgeHandler.getUID();
94         }
95     }
96
97     @Override
98     public @Nullable ThingHandler getThingHandler() {
99         return bridgeHandler;
100     }
101
102     @Override
103     protected void startBackgroundDiscovery() {
104         logger.debug("Starting Sure Petcare household discovery");
105         stopBackgroundDiscovery();
106         discoveryJob = scheduler.scheduleWithFixedDelay(this::startScan, DISCOVERY_SCAN_DELAY_MINUTES,
107                 DISCOVERY_REFRESH_INTERVAL_HOURS * 60, TimeUnit.MINUTES);
108         logger.debug("Scheduled topology-changed job every {} hours", DISCOVERY_REFRESH_INTERVAL_HOURS);
109     }
110
111     @Override
112     protected void stopBackgroundDiscovery() {
113         ScheduledFuture<?> job = discoveryJob;
114         if (job != null) {
115             job.cancel(true);
116             discoveryJob = null;
117             logger.debug("Stopped Sure Petcare device background discovery");
118         }
119     }
120
121     @Override
122     protected void startScan() {
123         logger.debug("Starting Sure Petcare discovery scan");
124         // If the bridge is not online no other thing devices can be found, so no reason to scan at this moment.
125         removeOlderResults(getTimestampOfLastScan());
126         if (bridgeHandler.getThing().getStatus() == ThingStatus.ONLINE) {
127             logger.debug("Starting device discovery for bridge {}", bridgeUID);
128             bridgeHandler.listHouseholds().forEach(this::householdDiscovered);
129             bridgeHandler.listPets().forEach(this::petDiscovered);
130             bridgeHandler.listDevices().forEach(this::deviceDiscovered);
131         }
132     }
133
134     private void householdDiscovered(SurePetcareHousehold household) {
135         logger.debug("Discovered household: {}", household.name);
136         ThingUID thingsUID = new ThingUID(THING_TYPE_HOUSEHOLD, bridgeUID, household.id.toString());
137         Map<String, Object> properties = new HashMap<>(household.getThingProperties());
138         thingDiscovered(DiscoveryResultBuilder.create(thingsUID).withLabel(household.name).withProperties(properties)
139                 .withRepresentationProperty(PROPERTY_NAME_ID).withBridge(bridgeUID).build());
140     }
141
142     private void petDiscovered(SurePetcarePet pet) {
143         logger.debug("Discovered pet: {}", pet.name);
144         ThingUID thingsUID = new ThingUID(THING_TYPE_PET, bridgeUID, pet.id.toString());
145         Map<String, Object> properties = new HashMap<>(pet.getThingProperties());
146         thingDiscovered(DiscoveryResultBuilder.create(thingsUID).withLabel(pet.name).withProperties(properties)
147                 .withRepresentationProperty(PROPERTY_NAME_ID).withBridge(bridgeUID).build());
148     }
149
150     private void deviceDiscovered(SurePetcareDevice device) {
151         logger.debug("Discovered device: {}", device.name);
152         ThingTypeUID typeUID = null;
153         switch (ProductType.findByTypeId(device.productId)) {
154             case HUB:
155                 typeUID = THING_TYPE_HUB_DEVICE;
156                 break;
157             case CAT_FLAP:
158                 typeUID = THING_TYPE_FLAP_DEVICE;
159                 break;
160             case PET_FLAP:
161                 typeUID = THING_TYPE_FLAP_DEVICE;
162                 break;
163             case PET_FEEDER:
164                 typeUID = THING_TYPE_FEEDER_DEVICE;
165                 break;
166             case UNKNOWN:
167             default:
168                 return;
169         }
170         ThingUID thingsUID = new ThingUID(typeUID, bridgeUID, device.id.toString());
171         Map<String, Object> properties = new HashMap<>(device.getThingProperties());
172         thingDiscovered(DiscoveryResultBuilder.create(thingsUID).withLabel(device.name).withProperties(properties)
173                 .withRepresentationProperty(PROPERTY_NAME_ID).withBridge(bridgeUID).build());
174     }
175 }