]> git.basschouten.com Git - openhab-addons.git/blob
84b40f44cd607fc9930b90d3a679d12cf74a7265
[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.mystrom.internal;
14
15 import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.CHANNEL_POWER;
16 import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.CHANNEL_SWITCH;
17 import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.CHANNEL_TEMPERATURE;
18 import static org.openhab.core.library.unit.SIUnits.CELSIUS;
19 import static org.openhab.core.library.unit.SmartHomeUnits.WATT;
20
21 import java.time.Duration;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.ScheduledFuture;
24 import java.util.concurrent.TimeUnit;
25 import java.util.concurrent.TimeoutException;
26
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.eclipse.jdt.annotation.Nullable;
29 import org.eclipse.jetty.client.HttpClient;
30 import org.eclipse.jetty.client.api.ContentResponse;
31 import org.eclipse.jetty.http.HttpMethod;
32 import org.openhab.core.cache.ExpiringCache;
33 import org.openhab.core.library.types.OnOffType;
34 import org.openhab.core.library.types.QuantityType;
35 import org.openhab.core.thing.ChannelUID;
36 import org.openhab.core.thing.Thing;
37 import org.openhab.core.thing.ThingStatus;
38 import org.openhab.core.thing.ThingStatusDetail;
39 import org.openhab.core.thing.binding.BaseThingHandler;
40 import org.openhab.core.types.Command;
41 import org.openhab.core.types.RefreshType;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 import com.google.gson.Gson;
46
47 /**
48  * The {@link MyStromHandler} is responsible for handling commands, which are
49  * sent to one of the channels.
50  *
51  * @author Paul Frank - Initial contribution
52  */
53 @NonNullByDefault
54 public class MyStromHandler extends BaseThingHandler {
55
56     private static class MyStromReport {
57
58         public float power;
59         public boolean relay;
60         public float temperature;
61     }
62
63     private static final int HTTP_OK_CODE = 200;
64     private static final String COMMUNICATION_ERROR = "Error while communicating to the myStrom plug: ";
65     private static final String HTTP_REQUEST_URL_PREFIX = "http://";
66
67     private final Logger logger = LoggerFactory.getLogger(MyStromHandler.class);
68
69     private HttpClient httpClient;
70     private String hostname = "";
71
72     private @Nullable ScheduledFuture<?> pollingJob;
73     private ExpiringCache<MyStromReport> cache = new ExpiringCache<>(Duration.ofSeconds(3), this::getReport);
74     private final Gson gson = new Gson();
75
76     public MyStromHandler(Thing thing, HttpClient httpClient) {
77         super(thing);
78         this.httpClient = httpClient;
79     }
80
81     @Override
82     public void handleCommand(ChannelUID channelUID, Command command) {
83         try {
84             if (command instanceof RefreshType) {
85                 pollDevice();
86             } else {
87                 if (command instanceof OnOffType && CHANNEL_SWITCH.equals(channelUID.getId())) {
88                     sendHttpGet("relay?state=" + (command == OnOffType.ON ? "1" : "0"));
89                     scheduler.schedule(this::pollDevice, 500, TimeUnit.MILLISECONDS);
90                 }
91             }
92         } catch (MyStromException e) {
93             logger.warn("Error while handling command {}", e.getMessage());
94         }
95     }
96
97     private @Nullable MyStromReport getReport() {
98         try {
99             String returnContent = sendHttpGet("report");
100             MyStromReport report = gson.fromJson(returnContent, MyStromReport.class);
101             updateStatus(ThingStatus.ONLINE);
102             return report;
103         } catch (MyStromException e) {
104             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
105             return null;
106         }
107     }
108
109     private void pollDevice() {
110         MyStromReport report = cache.getValue();
111         if (report != null) {
112             updateState(CHANNEL_SWITCH, report.relay ? OnOffType.ON : OnOffType.OFF);
113             updateState(CHANNEL_POWER, QuantityType.valueOf(report.power, WATT));
114             updateState(CHANNEL_TEMPERATURE, QuantityType.valueOf(report.temperature, CELSIUS));
115         }
116     }
117
118     @Override
119     public void initialize() {
120         MyStromConfiguration config = getConfigAs(MyStromConfiguration.class);
121         this.hostname = HTTP_REQUEST_URL_PREFIX + config.hostname;
122
123         updateStatus(ThingStatus.UNKNOWN);
124         pollingJob = scheduler.scheduleWithFixedDelay(this::pollDevice, 0, config.refresh, TimeUnit.SECONDS);
125     }
126
127     @Override
128     public void dispose() {
129         if (pollingJob != null) {
130             pollingJob.cancel(true);
131             pollingJob = null;
132         }
133         super.dispose();
134     }
135
136     /**
137      * Given a URL and a set parameters, send a HTTP GET request to the URL location
138      * created by the URL and parameters.
139      *
140      * @param url The URL to send a GET request to.
141      * @return String contents of the response for the GET request.
142      * @throws Exception
143      */
144     public String sendHttpGet(String action) throws MyStromException {
145         String url = hostname + "/" + action;
146         ContentResponse response = null;
147         try {
148             response = httpClient.newRequest(url).timeout(10, TimeUnit.SECONDS).method(HttpMethod.GET).send();
149         } catch (InterruptedException | TimeoutException | ExecutionException e) {
150             throw new MyStromException(COMMUNICATION_ERROR + e.getMessage());
151         }
152
153         if (response.getStatus() != HTTP_OK_CODE) {
154             throw new MyStromException(
155                     "Error sending HTTP GET request to " + url + ". Got response code: " + response.getStatus());
156         }
157         return response.getContentAsString();
158     }
159 }