]> git.basschouten.com Git - openhab-addons.git/blob
59e6c79a1dd506d650d294b8783e8317497d580f
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.seneye.internal;
14
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.ScheduledExecutorService;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
20
21 import org.eclipse.jetty.client.HttpClient;
22 import org.eclipse.jetty.client.api.ContentResponse;
23 import org.eclipse.jetty.client.api.Request;
24 import org.eclipse.jetty.http.HttpStatus;
25 import org.eclipse.jetty.util.ssl.SslContextFactory;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import com.google.gson.Gson;
30
31 /**
32  * The {@link SeneyeService} handles the connection to the Seneye API
33  *
34  * @author Niko Tanghe - Initial contribution
35  */
36
37 public class SeneyeService {
38
39     private final Logger logger = LoggerFactory.getLogger(SeneyeService.class);
40     private int retry;
41     private SeneyeConfigurationParameters config;
42     private String seneyeId;
43     public int seneyeType;
44     private boolean isInitialized;
45     private final Gson gson;
46     private HttpClient httpClient = new HttpClient(new SslContextFactory.Client());
47     private ScheduledFuture<?> scheduledJob;
48
49     public SeneyeService(SeneyeConfigurationParameters config) throws CommunicationException {
50         this.config = config;
51
52         this.retry = 1;
53
54         this.gson = new Gson();
55
56         this.isInitialized = false;
57
58         if (!httpClient.isStarted()) {
59             try {
60                 httpClient.setFollowRedirects(false);
61                 httpClient.start();
62             } catch (Exception e) {
63                 throw new CommunicationException("Cannot start HttpClient!", e);
64             }
65         }
66     }
67
68     @Override
69     public void finalize() {
70         try {
71             httpClient.stop();
72         } catch (Exception e) {
73             // swallow this
74         }
75         httpClient = null;
76     }
77
78     public void startAutomaticRefresh(ScheduledExecutorService scheduledExecutorService,
79             final ReadingsUpdate readingsUpdate) {
80         scheduledJob = scheduledExecutorService.scheduleWithFixedDelay(() -> {
81             readingsUpdate.newState(getDeviceReadings());
82         }, 0, config.poll_time, TimeUnit.MINUTES);
83     }
84
85     public void stopAutomaticRefresh() {
86         if (scheduledJob != null) {
87             scheduledJob.cancel(true);
88         }
89     }
90
91     public SeneyeDeviceReading getDeviceReadings() {
92         int currentTry = 0;
93         do {
94             try {
95                 String responseState = getData("/" + seneyeId + "/state?" + getCredentials());
96                 String responseReadings = getData("/" + seneyeId + "/exps?" + getCredentials());
97
98                 SeneyeDeviceReading readings = gson.fromJson(responseReadings, SeneyeDeviceReading.class);
99                 readings.status = gson.fromJson(responseState, SeneyeStatus.class);
100                 logger.debug("seneye '{}' read", this.seneyeId);
101
102                 return readings;
103             } catch (Exception se) {
104                 // ok, this readout failed, swallow this error, this is a scheduled task and this is in a retry loop,
105                 // so it will be retried.
106                 logger.debug("failed to read seneye '{}'", se.getMessage());
107             }
108         } while (currentTry++ < this.retry);
109
110         return null;
111     }
112
113     public void initialize() throws CommunicationException, InvalidConfigurationException {
114         String response = getData("?" + getCredentials());
115
116         Seneye[] seneyeDevices = gson.fromJson(response, Seneye[].class);
117
118         for (Seneye seneye : seneyeDevices) {
119             if (seneye.description.equals(config.aquarium_name)) {
120                 seneyeId = Integer.toString(seneye.id);
121                 seneyeType = (seneye.type);
122                 isInitialized = true;
123                 return;
124             }
125         }
126         throw new InvalidConfigurationException(
127                 "Could not find a seneye with aquarium name '" + config.aquarium_name + "'");
128     }
129
130     public boolean isInitialized() {
131         return isInitialized;
132     }
133
134     private String getData(String request) throws CommunicationException {
135         // get devices
136         // https://api.seneye.com/v1/devices?user=emailaddress&pwd=xxx
137
138         // get devicestatus
139         // https://api.seneye.com/v1/devices/23142/state?user=emailaddress&pwd=xxx
140
141         // get readings
142         // https://api.seneye.com/v1/devices/23142/exps?user=emailaddress&pwd=xxx
143
144         // get advices
145         // https://api.seneye.com/v1/devices/23142/advices/<id>?user=emailaddress&pwd=xxx
146
147         String url = "https://api.seneye.com/v1/devices" + request;
148
149         Request getMethod = httpClient.newRequest(url);
150         getMethod.accept("application/json");
151
152         try {
153             ContentResponse response = getMethod.send();
154             if (response.getStatus() != HttpStatus.OK_200) {
155                 logger.debug("Get readings method failed: {}", response.getReason());
156                 return "";
157             }
158
159             return response.getContentAsString();
160         } catch (InterruptedException e) {
161             throw new CommunicationException("Request aborted", e);
162         } catch (TimeoutException e) {
163             throw new CommunicationException("Timeout error", e);
164         } catch (ExecutionException e) {
165             throw new CommunicationException("Communication error", e.getCause());
166         }
167     }
168
169     private String getCredentials() {
170         return "user=" + config.username + "&pwd=" + config.password;
171     }
172 }