]> git.basschouten.com Git - openhab-addons.git/blob
fa489152a75b52fcfe9efa871842ecb65bd7beea
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.config.OJElectronicsBridgeConfiguration;
29 import org.openhab.binding.ojelectronics.internal.models.groups.GroupContentResponseModel;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import com.google.gson.FieldNamingPolicy;
34 import com.google.gson.Gson;
35 import com.google.gson.GsonBuilder;
36 import com.google.gson.JsonSyntaxException;
37
38 /**
39  * Handles the refreshing of the devices of a session
40  *
41  * @author Christian Kittel - Initial Contribution
42  */
43 @NonNullByDefault
44 public final class RefreshService implements AutoCloseable {
45
46     private final OJElectronicsBridgeConfiguration config;
47     private final Logger logger = LoggerFactory.getLogger(RefreshService.class);
48     private final HttpClient httpClient;
49     private final Gson gson = createGson();
50
51     private final ScheduledExecutorService schedulerService;
52
53     private @Nullable Runnable connectionLost;
54     private @Nullable BiConsumer<@Nullable GroupContentResponseModel, @Nullable String> refreshDone;
55     private @Nullable ScheduledFuture<?> scheduler;
56     private @Nullable Runnable unauthorized;
57     private @Nullable String sessionId;
58     private static boolean destroyed = false;
59
60     /**
61      * Creates a new instance of {@link RefreshService}
62      *
63      * @param config Configuration of the bridge
64      * @param httpClient HTTP client
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 Gson createGson() {
107         return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).setPrettyPrinting()
108                 .setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create();
109     }
110
111     private void refresh() {
112         final String sessionId = this.sessionId;
113         if (sessionId == null) {
114             handleConnectionLost();
115         }
116         final Runnable unauthorized = this.unauthorized;
117         createRequest().send(new BufferingResponseListener() {
118             @Override
119             public void onComplete(@Nullable Result result) {
120                 if (!destroyed) {
121                     if (result == null || result.isFailed()) {
122                         handleConnectionLost();
123                     } else if (result.getResponse().getStatus() == HttpStatus.FORBIDDEN_403) {
124                         if (unauthorized != null) {
125                             unauthorized.run();
126                         }
127                     } else {
128                         handleRefreshDone(getContentAsString());
129                     }
130                 }
131             }
132         });
133     }
134
135     private Request createRequest() {
136         Request request = httpClient.newRequest(config.apiUrl + "/Group/GroupContents").param("sessionid", sessionId)
137                 .param("apiKey", config.apiKey).method(HttpMethod.GET);
138         return request;
139     }
140
141     private void handleRefreshDone(String responseBody) {
142         BiConsumer<@Nullable GroupContentResponseModel, @Nullable String> refreshDone = this.refreshDone;
143         if (refreshDone != null) {
144             logger.trace("refresh {}", responseBody);
145             try {
146                 GroupContentResponseModel content = gson.fromJson(responseBody, GroupContentResponseModel.class);
147                 refreshDone.accept(content, null);
148             } catch (JsonSyntaxException exception) {
149                 logger.debug("Error mapping Result to model", exception);
150                 refreshDone.accept(null, exception.getMessage());
151             }
152         }
153     }
154
155     private void handleConnectionLost() {
156         final Runnable connectionLost = this.connectionLost;
157         if (connectionLost != null) {
158             connectionLost.run();
159         }
160     }
161
162     @Override
163     public void close() throws Exception {
164         stop();
165     }
166 }