]> git.basschouten.com Git - openhab-addons.git/blob
19b8da9864f9310b7a72052bd85b5d6e199a2051
[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.windcentrale.internal.handler;
14
15 import static java.util.function.Predicate.not;
16
17 import java.util.Collection;
18 import java.util.List;
19 import java.util.Objects;
20 import java.util.concurrent.Future;
21 import java.util.stream.Collectors;
22 import java.util.stream.Stream;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.windcentrale.internal.WindcentraleDiscoveryService;
27 import org.openhab.binding.windcentrale.internal.api.RequestListener;
28 import org.openhab.binding.windcentrale.internal.api.TokenProvider;
29 import org.openhab.binding.windcentrale.internal.api.WindcentraleAPI;
30 import org.openhab.binding.windcentrale.internal.config.AccountConfiguration;
31 import org.openhab.binding.windcentrale.internal.exception.FailedGettingDataException;
32 import org.openhab.binding.windcentrale.internal.exception.InvalidAccessTokenException;
33 import org.openhab.core.io.net.http.HttpClientFactory;
34 import org.openhab.core.thing.Bridge;
35 import org.openhab.core.thing.ChannelUID;
36 import org.openhab.core.thing.ThingStatus;
37 import org.openhab.core.thing.ThingStatusDetail;
38 import org.openhab.core.thing.binding.BaseBridgeHandler;
39 import org.openhab.core.thing.binding.ThingHandlerService;
40 import org.openhab.core.types.Command;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 /**
45  * The {@link WindcentraleAccountHandler} provides the {@link WindcentraleAPI} instance used by the windmill handlers.
46  *
47  * @author Wouter Born - Initial contribution
48  */
49 @NonNullByDefault
50 public class WindcentraleAccountHandler extends BaseBridgeHandler {
51
52     private final Logger logger = LoggerFactory.getLogger(WindcentraleAccountHandler.class);
53
54     private final HttpClientFactory httpClientFactory;
55
56     private @Nullable WindcentraleAPI api;
57     private @Nullable Exception apiException;
58     private @Nullable Future<?> initializeFuture;
59
60     private final RequestListener requestListener = new RequestListener() {
61         @Override
62         public void onError(Exception exception) {
63             apiException = exception;
64             logger.debug("API exception occurred");
65             updateThingStatus();
66         }
67
68         @Override
69         public void onSuccess() {
70             if (apiException != null) {
71                 apiException = null;
72                 logger.debug("API exception cleared");
73                 updateThingStatus();
74             }
75         }
76     };
77
78     public WindcentraleAccountHandler(Bridge bridge, HttpClientFactory httpClientFactory) {
79         super(bridge);
80         this.httpClientFactory = httpClientFactory;
81     }
82
83     @Override
84     public void dispose() {
85         Future<?> localFuture = initializeFuture;
86         if (localFuture != null) {
87             localFuture.cancel(true);
88             initializeFuture = null;
89         }
90
91         WindcentraleAPI localAPI = api;
92         if (localAPI != null) {
93             localAPI.dispose();
94             api = null;
95         }
96     }
97
98     public @Nullable WindcentraleAPI getAPI() {
99         return api;
100     }
101
102     @Override
103     public void initialize() {
104         updateStatus(ThingStatus.UNKNOWN);
105
106         initializeFuture = scheduler.submit(() -> {
107             api = initializeAPI();
108             updateThingStatus();
109         });
110     }
111
112     private WindcentraleAPI initializeAPI() {
113         AccountConfiguration config = getConfigAs(AccountConfiguration.class);
114         TokenProvider tokenProvider = new TokenProvider(httpClientFactory, config.username, config.password);
115
116         WindcentraleAPI api = new WindcentraleAPI(httpClientFactory, tokenProvider);
117         api.addRequestListener(requestListener);
118         apiException = null;
119
120         try {
121             api.getProjects();
122             api.getLiveData();
123         } catch (FailedGettingDataException | InvalidAccessTokenException e) {
124             apiException = e;
125         }
126         return api;
127     }
128
129     @Override
130     public Collection<Class<? extends ThingHandlerService>> getServices() {
131         return List.of(WindcentraleDiscoveryService.class);
132     }
133
134     @Override
135     public void handleCommand(ChannelUID channelUID, Command command) {
136     }
137
138     private void updateThingStatus() {
139         Exception e = apiException;
140         if (e != null) {
141             if (e instanceof InvalidAccessTokenException) {
142                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
143             } else {
144                 Throwable cause = e.getCause();
145                 String description = Stream
146                         .of(Objects.requireNonNullElse(e.getMessage(), ""),
147                                 cause == null ? "" : Objects.requireNonNullElse(cause.getMessage(), ""))
148                         .filter(not(String::isBlank)) //
149                         .collect(Collectors.joining(": "));
150                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, description);
151             }
152         } else {
153             updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE);
154         }
155     }
156 }