2 * Copyright (c) 2010-2024 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.electroluxair.internal.handler;
15 import static org.openhab.binding.electroluxair.internal.ElectroluxAirBindingConstants.*;
17 import java.util.Collection;
20 import java.util.concurrent.ConcurrentHashMap;
21 import java.util.concurrent.ScheduledFuture;
22 import java.util.concurrent.TimeUnit;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.eclipse.jetty.client.HttpClient;
27 import org.openhab.binding.electroluxair.internal.ElectroluxAirBridgeConfiguration;
28 import org.openhab.binding.electroluxair.internal.api.ElectroluxDeltaAPI;
29 import org.openhab.binding.electroluxair.internal.discovery.ElectroluxAirDiscoveryService;
30 import org.openhab.binding.electroluxair.internal.dto.ElectroluxPureA9DTO;
31 import org.openhab.core.thing.Bridge;
32 import org.openhab.core.thing.ChannelUID;
33 import org.openhab.core.thing.ThingStatus;
34 import org.openhab.core.thing.ThingStatusDetail;
35 import org.openhab.core.thing.ThingTypeUID;
36 import org.openhab.core.thing.binding.BaseBridgeHandler;
37 import org.openhab.core.thing.binding.ThingHandlerService;
38 import org.openhab.core.types.Command;
39 import org.openhab.core.types.RefreshType;
41 import com.google.gson.Gson;
44 * The {@link ElectroluxAirBridgeHandler} is responsible for handling commands, which are
45 * sent to one of the channels.
47 * @author Jan Gustafsson - Initial contribution
50 public class ElectroluxAirBridgeHandler extends BaseBridgeHandler {
52 public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_BRIDGE);
54 private int refreshTimeInSeconds = 300;
56 private final Gson gson;
57 private final HttpClient httpClient;
58 private final Map<String, ElectroluxPureA9DTO> electroluxAirThings = new ConcurrentHashMap<>();
60 private @Nullable ElectroluxDeltaAPI api;
61 private @Nullable ScheduledFuture<?> refreshJob;
63 public ElectroluxAirBridgeHandler(Bridge bridge, HttpClient httpClient, Gson gson) {
65 this.httpClient = httpClient;
70 public void initialize() {
71 ElectroluxAirBridgeConfiguration config = getConfigAs(ElectroluxAirBridgeConfiguration.class);
73 ElectroluxDeltaAPI electroluxDeltaAPI = new ElectroluxDeltaAPI(config, gson, httpClient);
74 refreshTimeInSeconds = config.refresh;
76 if (config.username == null || config.password == null) {
77 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
78 "Configuration of username, password is mandatory");
79 } else if (refreshTimeInSeconds < 0) {
80 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
81 "Refresh time cannot be negative!");
84 this.api = electroluxDeltaAPI;
85 scheduler.execute(() -> {
86 updateStatus(ThingStatus.UNKNOWN);
87 startAutomaticRefresh();
90 } catch (RuntimeException e) {
91 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
96 public Map<String, ElectroluxPureA9DTO> getElectroluxAirThings() {
97 return electroluxAirThings;
101 public Collection<Class<? extends ThingHandlerService>> getServices() {
102 return Set.of(ElectroluxAirDiscoveryService.class);
106 public void dispose() {
107 stopAutomaticRefresh();
110 public @Nullable ElectroluxDeltaAPI getElectroluxDeltaAPI() {
114 private boolean refreshAndUpdateStatus() {
116 if (api.refresh(electroluxAirThings)) {
117 getThing().getThings().stream().forEach(thing -> {
118 ElectroluxAirHandler handler = (ElectroluxAirHandler) thing.getHandler();
119 if (handler != null) {
123 updateStatus(ThingStatus.ONLINE);
126 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
132 private void startAutomaticRefresh() {
133 ScheduledFuture<?> refreshJob = this.refreshJob;
134 if (refreshJob == null || refreshJob.isCancelled()) {
135 this.refreshJob = scheduler.scheduleWithFixedDelay(this::refreshAndUpdateStatus, 0, refreshTimeInSeconds,
140 private void stopAutomaticRefresh() {
141 ScheduledFuture<?> refreshJob = this.refreshJob;
142 if (refreshJob != null) {
143 refreshJob.cancel(true);
144 this.refreshJob = null;
149 public void handleCommand(ChannelUID channelUID, Command command) {
150 if (CHANNEL_STATUS.equals(channelUID.getId()) && command instanceof RefreshType) {
151 scheduler.schedule(this::refreshAndUpdateStatus, 1, TimeUnit.SECONDS);