]> git.basschouten.com Git - openhab-addons.git/blob
446931de7257efa2e71c0a86c0a901b12a9b2c6f
[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.ojelectronics.internal.services;
14
15 import java.util.concurrent.ScheduledExecutorService;
16 import java.util.concurrent.ScheduledFuture;
17 import java.util.concurrent.TimeUnit;
18 import java.util.function.BiConsumer;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.eclipse.jetty.client.HttpClient;
23 import org.eclipse.jetty.client.api.Request;
24 import org.eclipse.jetty.client.api.Result;
25 import org.eclipse.jetty.client.util.BufferingResponseListener;
26 import org.eclipse.jetty.http.HttpMethod;
27 import org.eclipse.jetty.http.HttpStatus;
28 import org.openhab.binding.ojelectronics.internal.common.OJGSonBuilder;
29 import org.openhab.binding.ojelectronics.internal.config.OJElectronicsBridgeConfiguration;
30 import org.openhab.binding.ojelectronics.internal.models.groups.GroupContentResponseModel;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 import com.google.gson.Gson;
35 import com.google.gson.JsonSyntaxException;
36
37 /**
38  * Handles the refreshing of the devices of a session
39  *
40  * @author Christian Kittel - Initial Contribution
41  */
42 @NonNullByDefault
43 public final class RefreshService implements AutoCloseable {
44
45     private final OJElectronicsBridgeConfiguration config;
46     private final Logger logger = LoggerFactory.getLogger(RefreshService.class);
47     private final HttpClient httpClient;
48     private final Gson gson = OJGSonBuilder.getGSon();
49
50     private final ScheduledExecutorService schedulerService;
51
52     private @Nullable Runnable connectionLost;
53     private @Nullable BiConsumer<@Nullable GroupContentResponseModel, @Nullable String> refreshDone;
54     private @Nullable ScheduledFuture<?> scheduler;
55     private @Nullable Runnable unauthorized;
56     private @Nullable String sessionId;
57     private static boolean destroyed = false;
58
59     /**
60      * Creates a new instance of {@link RefreshService}
61      *
62      * @param config Configuration of the bridge
63      * @param httpClient HTTP client
64      * @param updateService Service to update the thermostat in the cloud
65      */
66     public RefreshService(OJElectronicsBridgeConfiguration config, HttpClient httpClient,
67             ScheduledExecutorService schedulerService) {
68         this.config = config;
69         this.httpClient = httpClient;
70         this.schedulerService = schedulerService;
71     }
72
73     /**
74      * Starts refreshing all thing values
75      *
76      * @param sessionId Session-Id
77      * @param refreshDone This method is called if refreshing is done.
78      * @param connectionLosed This method is called if no connection could established.
79      * @param unauthorized This method is called if the result is unauthorized.
80      */
81     public void start(String sessionId, BiConsumer<@Nullable GroupContentResponseModel, @Nullable String> refreshDone,
82             Runnable connectionLost, Runnable unauthorized) {
83         logger.trace("RefreshService.startService({})", sessionId);
84         this.connectionLost = connectionLost;
85         this.refreshDone = refreshDone;
86         this.unauthorized = unauthorized;
87         this.sessionId = sessionId;
88         long refreshTime = config.refreshDelayInSeconds;
89         scheduler = schedulerService.scheduleWithFixedDelay(this::refresh, refreshTime, refreshTime, TimeUnit.SECONDS);
90         refresh();
91         destroyed = false;
92     }
93
94     /**
95      * Stops refreshing.
96      */
97     public void stop() {
98         destroyed = true;
99         final ScheduledFuture<?> scheduler = this.scheduler;
100         if (scheduler != null) {
101             scheduler.cancel(false);
102         }
103         this.scheduler = null;
104     }
105
106     private void refresh() {
107         final String sessionId = this.sessionId;
108         if (sessionId == null) {
109             handleConnectionLost();
110         }
111         final Runnable unauthorized = this.unauthorized;
112         createRequest().send(new BufferingResponseListener() {
113             @Override
114             public void onComplete(@Nullable Result result) {
115                 if (!destroyed) {
116                     if (result == null || result.isFailed()) {
117                         handleConnectionLost();
118                     } else {
119                         int status = result.getResponse().getStatus();
120                         logger.trace("HTTP-Status {}", status);
121                         if (status == HttpStatus.FORBIDDEN_403) {
122                             if (unauthorized != null) {
123                                 unauthorized.run();
124                             } else {
125                                 handleConnectionLost();
126                             }
127                         } else if (status == HttpStatus.OK_200) {
128                             handleRefreshDone(getContentAsString());
129                         } else {
130                             logger.warn("unsupported HTTP-Status {}", status);
131                             handleConnectionLost();
132                         }
133                     }
134                 }
135             }
136         });
137     }
138
139     private Request createRequest() {
140         Request request = httpClient.newRequest(config.apiUrl + "/Group/GroupContents").param("sessionid", sessionId)
141                 .param("apiKey", config.apiKey).method(HttpMethod.GET);
142         return request;
143     }
144
145     private void handleRefreshDone(String responseBody) {
146         BiConsumer<@Nullable GroupContentResponseModel, @Nullable String> refreshDone = this.refreshDone;
147         if (refreshDone != null) {
148             logger.trace("refresh {}", responseBody);
149             try {
150                 GroupContentResponseModel content = gson.fromJson(responseBody, GroupContentResponseModel.class);
151                 refreshDone.accept(content, null);
152             } catch (JsonSyntaxException exception) {
153                 logger.debug("Error mapping Result to model", exception);
154                 refreshDone.accept(null, exception.getMessage());
155             }
156         }
157     }
158
159     private void handleConnectionLost() {
160         final Runnable connectionLost = this.connectionLost;
161         if (connectionLost != null) {
162             connectionLost.run();
163         }
164     }
165
166     @Override
167     public void close() throws Exception {
168         stop();
169     }
170 }