]> git.basschouten.com Git - openhab-addons.git/blob
a6bea2b114ee613cc186fa443f78214d8c790b5f
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.haywardomnilogic.internal.discovery;
14
15 import static org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants.THING_TYPES_UIDS;
16
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.function.BiConsumer;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants;
27 import org.openhab.binding.haywardomnilogic.internal.HaywardException;
28 import org.openhab.binding.haywardomnilogic.internal.HaywardTypeToRequest;
29 import org.openhab.binding.haywardomnilogic.internal.handler.HaywardBridgeHandler;
30 import org.openhab.core.config.discovery.AbstractDiscoveryService;
31 import org.openhab.core.config.discovery.DiscoveryResult;
32 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
33 import org.openhab.core.config.discovery.DiscoveryService;
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  * Sets up the discovery results and details
43  *
44  * @author Matt Myers - Initial contribution
45  */
46
47 @NonNullByDefault
48 public class HaywardDiscoveryService extends AbstractDiscoveryService implements DiscoveryService, ThingHandlerService {
49     private final Logger logger = LoggerFactory.getLogger(HaywardDiscoveryService.class);
50     private @Nullable HaywardBridgeHandler discoveryBridgehandler;
51
52     public HaywardDiscoveryService() {
53         super(THING_TYPES_UIDS, 0, false);
54     }
55
56     @Override
57     public void activate() {
58         super.activate(null);
59     }
60
61     @Override
62     public void deactivate() {
63         super.deactivate();
64     }
65
66     @Override
67     protected void startScan() {
68         HaywardBridgeHandler bridgehandler = discoveryBridgehandler;
69         try {
70             if (bridgehandler != null) {
71                 String xmlResults = bridgehandler.getMspConfig();
72                 mspConfigDiscovery(xmlResults);
73             }
74         } catch (HaywardException e) {
75             logger.warn("Exception during discovery scan: {}", e.getMessage());
76         } catch (InterruptedException e) {
77             return;
78         }
79     }
80
81     public synchronized void mspConfigDiscovery(String xmlResponse) {
82         List<String> systemIDs = new ArrayList<>();
83         List<String> names = new ArrayList<>();
84         Map<String, Object> backyardProperties = new HashMap<>();
85         Map<String, Object> bowProperties = new HashMap<>();
86         HaywardBridgeHandler bridgehandler = discoveryBridgehandler;
87
88         if (bridgehandler == null) {
89             return;
90         }
91
92         // Find Backyard
93         names = bridgehandler.evaluateXPath("//Backyard/Name/text()", xmlResponse);
94
95         for (int i = 0; i < names.size(); i++) {
96             backyardProperties.put(HaywardBindingConstants.PROPERTY_TYPE, HaywardTypeToRequest.BACKYARD);
97             backyardProperties.put(HaywardBindingConstants.PROPERTY_SYSTEM_ID, bridgehandler.account.mspSystemID);
98
99             onDeviceDiscovered(HaywardBindingConstants.THING_TYPE_BACKYARD, names.get(i), backyardProperties);
100         }
101
102         // Find Bodies of Water
103         systemIDs = bridgehandler.evaluateXPath("//Body-of-water/System-Id/text()", xmlResponse);
104         names = bridgehandler.evaluateXPath("//Body-of-water/Name/text()", xmlResponse);
105
106         for (int i = 0; i < systemIDs.size(); i++) {
107             bowProperties.put(HaywardBindingConstants.PROPERTY_TYPE, HaywardTypeToRequest.BOW);
108             bowProperties.put(HaywardBindingConstants.PROPERTY_SYSTEM_ID, systemIDs.get(i));
109
110             onDeviceDiscovered(HaywardBindingConstants.THING_TYPE_BOW, names.get(i), bowProperties);
111         }
112
113         // Find Chlorinators
114         discoverDevices(bridgehandler, xmlResponse, "Chlorinator", HaywardTypeToRequest.CHLORINATOR,
115                 HaywardBindingConstants.THING_TYPE_CHLORINATOR, null);
116
117         // Find ColorLogic Lights
118         discoverDevices(bridgehandler, xmlResponse, "ColorLogic-Light", HaywardTypeToRequest.COLORLOGIC,
119                 HaywardBindingConstants.THING_TYPE_COLORLOGIC, null);
120
121         // Find Filters
122         final List<String> filterProperty1 = bridgehandler.evaluateXPath("//Filter/Min-Pump-Speed/text()", xmlResponse);
123         final List<String> filterProperty2 = bridgehandler.evaluateXPath("//Filter/Max-Pump-Speed/text()", xmlResponse);
124         final List<String> filterProperty3 = bridgehandler.evaluateXPath("//Filter/Min-Pump-RPM/text()", xmlResponse);
125         final List<String> filterProperty4 = bridgehandler.evaluateXPath("//Filter/Max-Pump-RPM/text()", xmlResponse);
126
127         discoverDevices(bridgehandler, xmlResponse, "Filter", HaywardTypeToRequest.FILTER,
128                 HaywardBindingConstants.THING_TYPE_FILTER, (props, i) -> {
129                     props.put(HaywardBindingConstants.PROPERTY_FILTER_MINPUMPSPEED, filterProperty1.get(i));
130                     props.put(HaywardBindingConstants.PROPERTY_FILTER_MAXPUMPSPEED, filterProperty2.get(i));
131                     props.put(HaywardBindingConstants.PROPERTY_FILTER_MINPUMPRPM, filterProperty3.get(i));
132                     props.put(HaywardBindingConstants.PROPERTY_FILTER_MAXPUMPRPM, filterProperty4.get(i));
133                 });
134
135         // Find Heaters
136         discoverDevices(bridgehandler, xmlResponse, "Heater-Equipment", HaywardTypeToRequest.HEATER,
137                 HaywardBindingConstants.THING_TYPE_HEATER, null);
138
139         // Find Pumps
140         final List<String> pumpProperty1 = bridgehandler.evaluateXPath("//Pump/Min-Pump-Speed/text()", xmlResponse);
141         final List<String> pumpProperty2 = bridgehandler.evaluateXPath("//Pump/Max-Pump-Speed/text()", xmlResponse);
142         final List<String> pumpProperty3 = bridgehandler.evaluateXPath("//Pump/Min-Pump-RPM/text()", xmlResponse);
143         final List<String> pumpProperty4 = bridgehandler.evaluateXPath("//Pump/Max-Pump-RPM/text()", xmlResponse);
144
145         discoverDevices(bridgehandler, xmlResponse, "Pump", HaywardTypeToRequest.PUMP,
146                 HaywardBindingConstants.THING_TYPE_FILTER, (props, i) -> {
147                     props.put(HaywardBindingConstants.PROPERTY_FILTER_MINPUMPSPEED, pumpProperty1.get(i));
148                     props.put(HaywardBindingConstants.PROPERTY_FILTER_MAXPUMPSPEED, pumpProperty2.get(i));
149                     props.put(HaywardBindingConstants.PROPERTY_FILTER_MINPUMPRPM, pumpProperty3.get(i));
150                     props.put(HaywardBindingConstants.PROPERTY_FILTER_MAXPUMPRPM, pumpProperty4.get(i));
151                 });
152
153         // Find Relays
154         discoverDevices(bridgehandler, xmlResponse, "Relay", HaywardTypeToRequest.RELAY,
155                 HaywardBindingConstants.THING_TYPE_RELAY, null);
156
157         // Find Virtual Heaters
158         discoverDevices(bridgehandler, xmlResponse, "Heater", HaywardTypeToRequest.VIRTUALHEATER,
159                 HaywardBindingConstants.THING_TYPE_VIRTUALHEATER, null);
160
161         // Find Sensors
162         discoverDevices(bridgehandler, xmlResponse, "Sensor", HaywardTypeToRequest.SENSOR,
163                 HaywardBindingConstants.THING_TYPE_SENSOR, null);
164     }
165
166     private void discoverDevices(HaywardBridgeHandler bridgehandler, String xmlResponse, String xmlSearchTerm,
167             HaywardTypeToRequest type, ThingTypeUID thingType,
168             @Nullable BiConsumer<Map<String, Object>, Integer> additionalPropertyConsumer) {
169         List<String> systemIDs = bridgehandler.evaluateXPath("//" + xmlSearchTerm + "/System-Id/text()", xmlResponse);
170         List<String> names;
171
172         // Set Virtual Heater Name
173         if (HaywardBindingConstants.THING_TYPE_VIRTUALHEATER.equals(thingType)) {
174             names = new ArrayList<>(systemIDs);
175             Collections.fill(names, "Heater");
176         } else {
177             names = bridgehandler.evaluateXPath("//" + xmlSearchTerm + "/Name/text()", xmlResponse);
178         }
179
180         for (int i = 0; i < systemIDs.size(); i++) {
181             // get Body of Water for each item
182             List<String> bowID = bridgehandler.evaluateXPath(
183                     "//*[System-Id=" + systemIDs.get(i) + "]/ancestor::Body-of-water/System-Id/text()", xmlResponse);
184             List<String> bowName = bridgehandler.evaluateXPath(
185                     "//*[System-Id=" + systemIDs.get(i) + "]/ancestor::Body-of-water/Name/text()", xmlResponse);
186
187             // skip system sensors with no BOW
188             if (bowID.isEmpty()) {
189                 continue;
190             }
191
192             Map<String, Object> properties = new HashMap<>();
193             properties.put(HaywardBindingConstants.PROPERTY_TYPE, type);
194             properties.put(HaywardBindingConstants.PROPERTY_SYSTEM_ID, systemIDs.get(i));
195             properties.put(HaywardBindingConstants.PROPERTY_BOWID, bowID.get(0));
196             properties.put(HaywardBindingConstants.PROPERTY_BOWNAME, bowName.get(0));
197             if (additionalPropertyConsumer != null) {
198                 additionalPropertyConsumer.accept(properties, i);
199             }
200             onDeviceDiscovered(thingType, names.get(i), properties);
201         }
202     }
203
204     public void onDeviceDiscovered(ThingTypeUID thingType, String label, Map<String, Object> properties) {
205         HaywardBridgeHandler bridgehandler = discoveryBridgehandler;
206         String systemID = (String) properties.get(HaywardBindingConstants.PROPERTY_SYSTEM_ID);
207         if (bridgehandler != null) {
208             if (systemID != null) {
209                 ThingUID thingUID = new ThingUID(thingType, bridgehandler.getThing().getUID(), systemID);
210                 DiscoveryResult result = DiscoveryResultBuilder.create(thingUID)
211                         .withBridge(bridgehandler.getThing().getUID())
212                         .withRepresentationProperty(HaywardBindingConstants.PROPERTY_SYSTEM_ID)
213                         .withLabel("Hayward " + label).withProperties(properties).build();
214                 thingDiscovered(result);
215             }
216         }
217     }
218
219     @Override
220     public void setThingHandler(@Nullable ThingHandler handler) {
221         if (handler instanceof HaywardBridgeHandler) {
222             this.discoveryBridgehandler = (HaywardBridgeHandler) handler;
223         }
224     }
225
226     @Override
227     public @Nullable ThingHandler getThingHandler() {
228         return discoveryBridgehandler;
229     }
230 }