]> git.basschouten.com Git - openhab-addons.git/blob
79b73c29f0b5948a3b9d3a7090886753dbb42eb7
[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.gardena.internal.handler;
14
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.concurrent.TimeUnit;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.gardena.internal.GardenaSmart;
22 import org.openhab.binding.gardena.internal.GardenaSmartEventListener;
23 import org.openhab.binding.gardena.internal.GardenaSmartImpl;
24 import org.openhab.binding.gardena.internal.config.GardenaConfig;
25 import org.openhab.binding.gardena.internal.discovery.GardenaDeviceDiscoveryService;
26 import org.openhab.binding.gardena.internal.exception.GardenaException;
27 import org.openhab.binding.gardena.internal.model.dto.Device;
28 import org.openhab.binding.gardena.internal.util.UidUtils;
29 import org.openhab.core.io.net.http.HttpClientFactory;
30 import org.openhab.core.io.net.http.WebSocketFactory;
31 import org.openhab.core.thing.*;
32 import org.openhab.core.thing.binding.BaseBridgeHandler;
33 import org.openhab.core.thing.binding.ThingHandlerService;
34 import org.openhab.core.types.Command;
35 import org.openhab.core.types.RefreshType;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * The {@link GardenaAccountHandler} is the handler for a Gardena smart system access and connects it to the framework.
41  *
42  * @author Gerhard Riegler - Initial contribution
43  */
44 @NonNullByDefault
45 public class GardenaAccountHandler extends BaseBridgeHandler implements GardenaSmartEventListener {
46     private final Logger logger = LoggerFactory.getLogger(GardenaAccountHandler.class);
47     private final long REINITIALIZE_DELAY_SECONDS = 10;
48
49     private @Nullable GardenaDeviceDiscoveryService discoveryService;
50
51     private @Nullable GardenaSmart gardenaSmart;
52     private HttpClientFactory httpClientFactory;
53     private WebSocketFactory webSocketFactory;
54
55     public GardenaAccountHandler(Bridge bridge, HttpClientFactory httpClientFactory,
56             WebSocketFactory webSocketFactory) {
57         super(bridge);
58         this.httpClientFactory = httpClientFactory;
59         this.webSocketFactory = webSocketFactory;
60     }
61
62     @Override
63     public void initialize() {
64         logger.debug("Initializing Gardena account '{}'", getThing().getUID().getId());
65         initializeGardena();
66     }
67
68     public void setDiscoveryService(GardenaDeviceDiscoveryService discoveryService) {
69         this.discoveryService = discoveryService;
70     }
71
72     /**
73      * Initializes the GardenaSmart account.
74      */
75     private void initializeGardena() {
76         final GardenaAccountHandler instance = this;
77         scheduler.execute(() -> {
78             try {
79                 GardenaConfig gardenaConfig = getThing().getConfiguration().as(GardenaConfig.class);
80                 logger.debug("{}", gardenaConfig);
81
82                 String id = getThing().getUID().getId();
83                 gardenaSmart = new GardenaSmartImpl(id, gardenaConfig, instance, scheduler, httpClientFactory,
84                         webSocketFactory);
85                 final GardenaDeviceDiscoveryService discoveryService = this.discoveryService;
86                 if (discoveryService != null) {
87                     discoveryService.startScan(null);
88                     discoveryService.waitForScanFinishing();
89                 }
90                 updateStatus(ThingStatus.ONLINE);
91             } catch (GardenaException ex) {
92                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, ex.getMessage());
93                 disposeGardena();
94                 scheduleReinitialize();
95                 logger.warn("{}", ex.getMessage());
96             }
97         });
98     }
99
100     /**
101      * Schedules a reinitialization, if Gardena smart system account is not reachable.
102      */
103     private void scheduleReinitialize() {
104         scheduler.schedule(() -> {
105             if (getThing().getStatus() != ThingStatus.UNINITIALIZED) {
106                 initializeGardena();
107             }
108         }, REINITIALIZE_DELAY_SECONDS, TimeUnit.SECONDS);
109     }
110
111     @Override
112     public void dispose() {
113         super.dispose();
114         disposeGardena();
115     }
116
117     /**
118      * Disposes the GardenaSmart account.
119      */
120     private void disposeGardena() {
121         logger.debug("Disposing Gardena account '{}'", getThing().getUID().getId());
122         final GardenaDeviceDiscoveryService discoveryService = this.discoveryService;
123         if (discoveryService != null) {
124             discoveryService.stopScan();
125         }
126         final GardenaSmart gardenaSmart = this.gardenaSmart;
127         if (gardenaSmart != null) {
128             gardenaSmart.dispose();
129         }
130     }
131
132     /**
133      * Returns the Gardena smart system implementation.
134      */
135     public @Nullable GardenaSmart getGardenaSmart() {
136         return gardenaSmart;
137     }
138
139     @Override
140     public Collection<Class<? extends ThingHandlerService>> getServices() {
141         return Collections.singleton(GardenaDeviceDiscoveryService.class);
142     }
143
144     @Override
145     public void handleCommand(ChannelUID channelUID, Command command) {
146         if (RefreshType.REFRESH == command) {
147             logger.debug("Refreshing Gardena account '{}'", getThing().getUID().getId());
148             disposeGardena();
149             initializeGardena();
150         }
151     }
152
153     @Override
154     public void onDeviceUpdated(Device device) {
155         for (ThingUID thingUID : UidUtils.getThingUIDs(device, getThing())) {
156             final Thing gardenaThing;
157             final GardenaThingHandler gardenaThingHandler;
158             if ((gardenaThing = getThing().getThing(thingUID)) != null
159                     && (gardenaThingHandler = (GardenaThingHandler) gardenaThing.getHandler()) != null) {
160                 try {
161                     gardenaThingHandler.updateProperties(device);
162                     for (Channel channel : gardenaThing.getChannels()) {
163                         gardenaThingHandler.updateChannel(channel.getUID());
164                     }
165                     gardenaThingHandler.updateStatus(device);
166                 } catch (GardenaException ex) {
167                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, ex.getMessage());
168                 } catch (AccountHandlerNotAvailableException ignore) {
169                 }
170             }
171         }
172     }
173
174     @Override
175     public void onNewDevice(Device device) {
176         final GardenaDeviceDiscoveryService discoveryService = this.discoveryService;
177         if (discoveryService != null) {
178             discoveryService.deviceDiscovered(device);
179         }
180         onDeviceUpdated(device);
181     }
182
183     @Override
184     public void onError() {
185         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Connection lost");
186         disposeGardena();
187         scheduleReinitialize();
188     }
189 }