]> git.basschouten.com Git - openhab-addons.git/blob
36a8dad8c63e5d58210600a62efff78892a0623a
[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.hdpowerview.internal.handler;
14
15 import static org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants.*;
16
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.hdpowerview.internal.HDPowerViewWebTargets;
23 import org.openhab.binding.hdpowerview.internal.api.Firmware;
24 import org.openhab.binding.hdpowerview.internal.api.responses.RepeaterData;
25 import org.openhab.binding.hdpowerview.internal.config.HDPowerViewRepeaterConfiguration;
26 import org.openhab.binding.hdpowerview.internal.exceptions.HubException;
27 import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException;
28 import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
29 import org.openhab.core.library.types.OnOffType;
30 import org.openhab.core.library.types.StringType;
31 import org.openhab.core.thing.Bridge;
32 import org.openhab.core.thing.ChannelUID;
33 import org.openhab.core.thing.Thing;
34 import org.openhab.core.thing.ThingStatus;
35 import org.openhab.core.thing.ThingStatusDetail;
36 import org.openhab.core.types.Command;
37 import org.openhab.core.types.UnDefType;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * Handles commands for an HD PowerView Repeater
43  *
44  * @author Jacob Laursen - Initial contribution
45  */
46 @NonNullByDefault
47 public class HDPowerViewRepeaterHandler extends AbstractHubbedThingHandler {
48
49     private final Logger logger = LoggerFactory.getLogger(HDPowerViewRepeaterHandler.class);
50
51     private static final int REFRESH_INTERVAL_MINUTES = 5;
52     private static final int IDENTITY_PERIOD_SECONDS = 3;
53     private static final String COMMAND_IDENTIFY = "IDENTIFY";
54
55     private @Nullable ScheduledFuture<?> refreshStatusFuture = null;
56     private @Nullable ScheduledFuture<?> resetIdentifyStateFuture = null;
57     private int repeaterId;
58
59     public HDPowerViewRepeaterHandler(Thing thing) {
60         super(thing);
61     }
62
63     @Override
64     public void initialize() {
65         repeaterId = getConfigAs(HDPowerViewRepeaterConfiguration.class).id;
66         logger.debug("Initializing repeater handler for repeater {}", repeaterId);
67         if (repeaterId <= 0) {
68             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
69                     "@text/offline.conf-error.invalid-id");
70             return;
71         }
72         Bridge bridge = getBridge();
73         if (bridge == null) {
74             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED);
75             return;
76         }
77         if (!(bridge.getHandler() instanceof HDPowerViewHubHandler)) {
78             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED,
79                     "@text/offline.conf-error.invalid-bridge-handler");
80             return;
81         }
82         updateStatus(ThingStatus.UNKNOWN);
83         scheduleRefreshJob();
84     }
85
86     @Override
87     public void dispose() {
88         logger.debug("Disposing repeater handler for repeater {}", repeaterId);
89         cancelRefreshJob();
90         cancelResetIdentifyStateJob();
91     }
92
93     @Override
94     public void handleCommand(ChannelUID channelUID, Command command) {
95         HDPowerViewHubHandler bridge = getBridgeHandler();
96         if (bridge == null) {
97             logger.warn("Missing bridge handler");
98             return;
99         }
100         HDPowerViewWebTargets webTargets = bridge.getWebTargets();
101         if (webTargets == null) {
102             logger.warn("Web targets not initialized");
103             return;
104         }
105
106         try {
107             RepeaterData repeaterData;
108
109             switch (channelUID.getId()) {
110                 case CHANNEL_REPEATER_IDENTIFY:
111                     if (command instanceof StringType) {
112                         if (COMMAND_IDENTIFY.equals(((StringType) command).toString())) {
113                             repeaterData = webTargets.identifyRepeater(repeaterId);
114                             scheduler.submit(() -> updatePropertyAndState(repeaterData));
115                             cancelResetIdentifyStateJob();
116                             resetIdentifyStateFuture = scheduler.schedule(() -> {
117                                 updateState(CHANNEL_REPEATER_IDENTIFY, UnDefType.UNDEF);
118                             }, IDENTITY_PERIOD_SECONDS, TimeUnit.SECONDS);
119                         } else {
120                             logger.warn("Unsupported command: {}. Supported commands are: " + COMMAND_IDENTIFY,
121                                     command);
122                         }
123                     }
124                     break;
125                 case CHANNEL_REPEATER_BLINKING_ENABLED:
126                     repeaterData = webTargets.enableRepeaterBlinking(repeaterId, OnOffType.ON == command);
127                     scheduler.submit(() -> updatePropertyAndState(repeaterData));
128                     break;
129             }
130         } catch (HubInvalidResponseException e) {
131             Throwable cause = e.getCause();
132             if (cause == null) {
133                 logger.warn("Bridge returned a bad JSON response: {}", e.getMessage());
134             } else {
135                 logger.warn("Bridge returned a bad JSON response: {} -> {}", e.getMessage(), cause.getMessage());
136             }
137         } catch (HubMaintenanceException e) {
138             // exceptions are logged in HDPowerViewWebTargets
139         } catch (HubException e) {
140             logger.warn("Unexpected error: {}", e.getMessage());
141         }
142     }
143
144     private void cancelResetIdentifyStateJob() {
145         ScheduledFuture<?> scheduledJob = resetIdentifyStateFuture;
146         if (scheduledJob != null) {
147             scheduledJob.cancel(true);
148         }
149         resetIdentifyStateFuture = null;
150     }
151
152     private void scheduleRefreshJob() {
153         cancelRefreshJob();
154         logger.debug("Scheduling poll for repeater {} now, then every {} minutes", repeaterId,
155                 REFRESH_INTERVAL_MINUTES);
156         this.refreshStatusFuture = scheduler.scheduleWithFixedDelay(this::poll, 0, REFRESH_INTERVAL_MINUTES,
157                 TimeUnit.MINUTES);
158     }
159
160     private void cancelRefreshJob() {
161         ScheduledFuture<?> future = this.refreshStatusFuture;
162         if (future != null) {
163             future.cancel(false);
164         }
165         this.refreshStatusFuture = null;
166     }
167
168     private synchronized void poll() {
169         HDPowerViewHubHandler bridge = getBridgeHandler();
170         if (bridge == null) {
171             logger.warn("Missing bridge handler");
172             return;
173         }
174         HDPowerViewWebTargets webTargets = bridge.getWebTargets();
175         if (webTargets == null) {
176             logger.warn("Web targets not initialized");
177             return;
178         }
179         try {
180             logger.debug("Polling for status information");
181
182             RepeaterData repeaterData = webTargets.getRepeater(repeaterId);
183             updatePropertyAndState(repeaterData);
184
185         } catch (HubInvalidResponseException e) {
186             Throwable cause = e.getCause();
187             if (cause == null) {
188                 logger.warn("Bridge returned a bad JSON response: {}", e.getMessage());
189             } else {
190                 logger.warn("Bridge returned a bad JSON response: {} -> {}", e.getMessage(), cause.getMessage());
191             }
192         } catch (HubMaintenanceException e) {
193             // exceptions are logged in HDPowerViewWebTargets
194         } catch (HubException e) {
195             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, e.getMessage());
196         }
197     }
198
199     private void updatePropertyAndState(RepeaterData repeaterData) {
200         updateStatus(ThingStatus.ONLINE);
201
202         Firmware firmware = repeaterData.firmware;
203         if (firmware != null) {
204             logger.debug("Repeater firmware version received: {}", firmware.toString());
205             updateProperty(Thing.PROPERTY_FIRMWARE_VERSION, firmware.toString());
206         } else {
207             logger.warn("Repeater firmware version missing in response");
208         }
209
210         updateState(CHANNEL_REPEATER_BLINKING_ENABLED, repeaterData.blinkEnabled ? OnOffType.ON : OnOffType.OFF);
211     }
212 }