]> git.basschouten.com Git - openhab-addons.git/blob
7deba06274ccb0ca142d534682b6bcec5ebf28fb
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.tado.internal.handler;
14
15 import java.io.IOException;
16 import java.util.List;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.tado.internal.TadoBindingConstants;
23 import org.openhab.binding.tado.internal.TadoBindingConstants.TemperatureUnit;
24 import org.openhab.binding.tado.internal.api.ApiException;
25 import org.openhab.binding.tado.internal.api.HomeApiFactory;
26 import org.openhab.binding.tado.internal.api.client.HomeApi;
27 import org.openhab.binding.tado.internal.api.model.HomeInfo;
28 import org.openhab.binding.tado.internal.api.model.HomePresence;
29 import org.openhab.binding.tado.internal.api.model.HomeState;
30 import org.openhab.binding.tado.internal.api.model.PresenceState;
31 import org.openhab.binding.tado.internal.api.model.User;
32 import org.openhab.binding.tado.internal.api.model.UserHomes;
33 import org.openhab.binding.tado.internal.config.TadoHomeConfig;
34 import org.openhab.core.library.types.OnOffType;
35 import org.openhab.core.thing.Bridge;
36 import org.openhab.core.thing.ChannelUID;
37 import org.openhab.core.thing.Thing;
38 import org.openhab.core.thing.ThingStatus;
39 import org.openhab.core.thing.ThingStatusDetail;
40 import org.openhab.core.thing.binding.BaseBridgeHandler;
41 import org.openhab.core.thing.binding.ThingHandler;
42 import org.openhab.core.types.Command;
43 import org.openhab.core.types.RefreshType;
44 import org.openhab.core.types.State;
45 import org.openhab.core.types.UnDefType;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 /**
50  * The {@link TadoHomeHandler} is the bridge of all home-based things.
51  *
52  * @author Dennis Frommknecht - Initial contribution
53  */
54 @NonNullByDefault
55 public class TadoHomeHandler extends BaseBridgeHandler {
56
57     private Logger logger = LoggerFactory.getLogger(TadoHomeHandler.class);
58
59     private TadoHomeConfig configuration;
60     private final HomeApi api;
61
62     private @Nullable Long homeId;
63     private @Nullable TadoBatteryChecker batteryChecker;
64     private @Nullable ScheduledFuture<?> initializationFuture;
65
66     public TadoHomeHandler(Bridge bridge) {
67         super(bridge);
68         batteryChecker = new TadoBatteryChecker(this);
69         configuration = getConfigAs(TadoHomeConfig.class);
70         api = new HomeApiFactory().create(configuration.username, configuration.password);
71     }
72
73     public TemperatureUnit getTemperatureUnit() {
74         String temperatureUnitStr = this.thing.getProperties()
75                 .getOrDefault(TadoBindingConstants.PROPERTY_HOME_TEMPERATURE_UNIT, "CELSIUS");
76         return TemperatureUnit.valueOf(temperatureUnitStr);
77     }
78
79     @Override
80     public void initialize() {
81         configuration = getConfigAs(TadoHomeConfig.class);
82         ScheduledFuture<?> initializationFuture = this.initializationFuture;
83         if (initializationFuture == null || initializationFuture.isDone()) {
84             this.initializationFuture = scheduler.scheduleWithFixedDelay(
85                     this::initializeBridgeStatusAndPropertiesIfOffline, 0, 300, TimeUnit.SECONDS);
86         }
87     }
88
89     private void initializeBridgeStatusAndPropertiesIfOffline() {
90         if (getThing().getStatus() == ThingStatus.ONLINE) {
91             for (Thing thing : getThing().getThings()) {
92                 ThingHandler handler = thing.getHandler();
93                 if ((handler instanceof BaseHomeThingHandler) && (thing.getStatus() == ThingStatus.OFFLINE)
94                         && (thing.getStatusInfo().getStatusDetail() == ThingStatusDetail.COMMUNICATION_ERROR)) {
95                     scheduler.submit(() -> handler.bridgeStatusChanged(getThing().getStatusInfo()));
96                 }
97             }
98         }
99
100         try {
101             // if we are already online, don't make unnecessary calls on the server
102             if (getThing().getStatus() != ThingStatus.ONLINE) {
103                 // Get user info to verify successful authentication and connection to server
104                 User user = api.showUser();
105                 if (user == null) {
106                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
107                             "Cannot connect to server. Username and/or password might be invalid");
108                     return;
109                 }
110
111                 List<UserHomes> homes = user.getHomes();
112                 if (homes == null || homes.isEmpty()) {
113                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
114                             "User does not have access to any home");
115                     return;
116                 }
117
118                 Integer firstHomeId = homes.get(0).getId();
119                 if (firstHomeId == null) {
120                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Missing Home Id");
121                     return;
122                 }
123
124                 homeId = firstHomeId.longValue();
125             }
126
127             // but always make one server call as a 'ping' to confirm we are really still online
128             HomeInfo homeInfo = api.showHome(homeId);
129             TemperatureUnit temperatureUnit = org.openhab.binding.tado.internal.api.model.TemperatureUnit.FAHRENHEIT == homeInfo
130                     .getTemperatureUnit() ? TemperatureUnit.FAHRENHEIT : TemperatureUnit.CELSIUS;
131             updateProperty(TadoBindingConstants.PROPERTY_HOME_TEMPERATURE_UNIT, temperatureUnit.name());
132         } catch (IOException | ApiException e) {
133             logger.debug("Error accessing tado server: {}", e.getMessage(), e);
134             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
135                     "Could not connect to server due to " + e.getMessage());
136             return;
137         }
138
139         updateStatus(ThingStatus.ONLINE);
140     }
141
142     @Override
143     public void dispose() {
144         super.dispose();
145         ScheduledFuture<?> initializationFuture = this.initializationFuture;
146         if (initializationFuture != null && !initializationFuture.isCancelled()) {
147             initializationFuture.cancel(true);
148         }
149     }
150
151     public HomeApi getApi() {
152         return api;
153     }
154
155     public @Nullable Long getHomeId() {
156         return homeId;
157     }
158
159     public HomeState getHomeState() throws IOException, ApiException {
160         return api.homeState(getHomeId());
161     }
162
163     public void updateHomeState() {
164         try {
165             updateState(TadoBindingConstants.CHANNEL_HOME_PRESENCE_MODE,
166                     getHomeState().getPresence() == PresenceState.HOME ? OnOffType.ON : OnOffType.OFF);
167         } catch (IOException | ApiException e) {
168             logger.debug("Error accessing tado server: {}", e.getMessage(), e);
169         }
170     }
171
172     @Override
173     public void handleCommand(ChannelUID channelUID, Command command) {
174         String id = channelUID.getId();
175
176         if (command == RefreshType.REFRESH) {
177             updateHomeState();
178             return;
179         }
180
181         switch (id) {
182             case TadoBindingConstants.CHANNEL_HOME_PRESENCE_MODE:
183                 HomePresence presence = new HomePresence();
184                 presence.setHomePresence(command.toFullString().toUpperCase().equals("ON")
185                         || command.toFullString().toUpperCase().equals("HOME") ? PresenceState.HOME
186                                 : PresenceState.AWAY);
187                 try {
188                     api.updatePresenceLock(homeId, presence);
189                 } catch (IOException | ApiException e) {
190                     logger.warn("Error setting home presence: {}", e.getMessage(), e);
191                 }
192
193                 break;
194
195         }
196     }
197
198     public State getBatteryLowAlarm(long zoneId) {
199         TadoBatteryChecker batteryChecker = this.batteryChecker;
200         return batteryChecker != null ? batteryChecker.getBatteryLowAlarm(zoneId) : UnDefType.UNDEF;
201     }
202 }