2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.ojelectronics.internal;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.eclipse.jetty.client.HttpClient;
23 import org.openhab.binding.ojelectronics.internal.config.OJElectronicsBridgeConfiguration;
24 import org.openhab.binding.ojelectronics.internal.models.groups.GroupContentResponseModel;
25 import org.openhab.binding.ojelectronics.internal.services.OJDiscoveryService;
26 import org.openhab.binding.ojelectronics.internal.services.RefreshGroupContentService;
27 import org.openhab.binding.ojelectronics.internal.services.RefreshService;
28 import org.openhab.binding.ojelectronics.internal.services.SignInService;
29 import org.openhab.binding.ojelectronics.internal.services.UpdateService;
30 import org.openhab.core.thing.Bridge;
31 import org.openhab.core.thing.ChannelUID;
32 import org.openhab.core.thing.ThingStatus;
33 import org.openhab.core.thing.ThingStatusDetail;
34 import org.openhab.core.thing.binding.BaseBridgeHandler;
35 import org.openhab.core.thing.binding.BridgeHandler;
36 import org.openhab.core.thing.binding.ThingHandlerService;
37 import org.openhab.core.types.Command;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 * Handles all traffic with OJ Electronics cloud
44 * @author Christian Kittel - Initial Contribution
47 public class OJCloudHandler extends BaseBridgeHandler implements BridgeHandler {
49 private final Logger logger = LoggerFactory.getLogger(OJCloudHandler.class);
50 private final HttpClient httpClient;
52 private @Nullable RefreshService refreshService;
53 private @Nullable UpdateService updateService;
54 private @Nullable SignInService signInService;
55 private OJElectronicsBridgeConfiguration configuration;
56 private @Nullable ScheduledFuture<?> signTask;
57 private @Nullable OJDiscoveryService discoveryService;
60 * Creates a new instance of {@link OJCloudHandler}
62 * @param bridge {@link Bridge}
63 * @param httpClient HttpClient
65 public OJCloudHandler(Bridge bridge, HttpClient httpClient) {
67 this.httpClient = httpClient;
68 this.configuration = new OJElectronicsBridgeConfiguration();
72 * Initializes the binding.
75 public void initialize() {
76 configuration = getConfigAs(OJElectronicsBridgeConfiguration.class);
81 * Disposes the binding.
84 public void dispose() {
85 final RefreshService refreshService = this.refreshService;
86 if (refreshService != null) {
87 refreshService.stop();
89 final ScheduledFuture<?> signTask = this.signTask;
90 if (signTask != null) {
91 signTask.cancel(true);
93 this.refreshService = null;
99 public void handleCommand(ChannelUID channelUID, Command command) {
102 private void ensureSignIn() {
103 if (signInService == null) {
104 signInService = new SignInService(configuration, httpClient);
106 final SignInService signInService = this.signInService;
107 if (signInService != null) {
108 signInService.signIn(this::handleSignInDone, this::handleConnectionLost,
109 this::handleUnauthorizedWhileSignIn);
113 private void handleRefreshDone(@Nullable GroupContentResponseModel groupContentResponse,
114 @Nullable String errorMessage) {
115 logger.trace("OJElectronicsCloudHandler.handleRefreshDone({})", groupContentResponse);
116 if (groupContentResponse != null && groupContentResponse.errorCode == 0) {
117 internalRefreshDone(groupContentResponse);
119 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
120 (errorMessage == null) ? "Wrong or no result model; Refreshing stoppped" : errorMessage);
121 final RefreshService refreshService = this.refreshService;
122 if (refreshService != null) {
123 refreshService.stop();
128 private void internalRefreshDone(GroupContentResponseModel groupContentResponse) {
129 new RefreshGroupContentService(groupContentResponse.groupContents, getThing().getThings()).handle();
130 final OJDiscoveryService discoveryService = this.discoveryService;
131 if (discoveryService != null) {
132 discoveryService.setScanResultForDiscovery(groupContentResponse.groupContents);
134 final UpdateService updateService = this.updateService;
135 if (updateService != null) {
136 updateService.updateAllThermostats(getThing().getThings());
140 private void handleSignInDone(String sessionId) {
141 logger.trace("OJElectronicsCloudHandler.handleSignInDone({})", sessionId);
142 if (refreshService == null) {
143 refreshService = new RefreshService(configuration, httpClient, scheduler);
145 final RefreshService refreshService = this.refreshService;
146 if (refreshService != null) {
147 refreshService.start(sessionId, this::handleRefreshDone, this::handleConnectionLost,
148 this::handleUnauthorized);
150 updateStatus(ThingStatus.ONLINE);
152 this.updateService = new UpdateService(configuration, httpClient, sessionId);
155 private void handleUnauthorized() {
156 logger.trace("OJElectronicsCloudHandler.handleUnauthorized()");
157 final RefreshService refreshService = this.refreshService;
158 if (refreshService != null) {
159 refreshService.stop();
161 restartRefreshServiceAsync(1);
164 private void handleUnauthorizedWhileSignIn() {
165 logger.trace("OJElectronicsCloudHandler.handleUnauthorizedWhileSignIn()");
166 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
167 "Could not sign in. Check user name and password.");
168 final RefreshService refreshService = this.refreshService;
169 if (refreshService != null) {
170 refreshService.stop();
174 private void handleConnectionLost() {
175 logger.trace("OJElectronicsCloudHandler.handleConnectionLost()");
176 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
177 final RefreshService refreshService = this.refreshService;
178 if (refreshService != null) {
179 refreshService.stop();
181 restartRefreshServiceAsync(configuration.refreshDelayInSeconds);
184 private void restartRefreshServiceAsync(long delayInSeconds) {
185 signTask = scheduler.schedule(this::ensureSignIn, delayInSeconds, TimeUnit.SECONDS);
188 public void setDiscoveryService(OJDiscoveryService ojDiscoveryService) {
189 this.discoveryService = ojDiscoveryService;
193 public Collection<Class<? extends ThingHandlerService>> getServices() {
194 return Collections.singleton(OJDiscoveryService.class);