]> git.basschouten.com Git - openhab-addons.git/blob
c6ea44352b6bdef312b9467d71e434e6646048e3
[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.bsblan.internal.api;
14
15 import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.API_TIMEOUT;
16
17 import java.io.ByteArrayInputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.nio.charset.Charset;
21 import java.util.Set;
22 import java.util.stream.Collectors;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiContentDTO;
27 import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterQueryResponseDTO;
28 import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetRequestDTO;
29 import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetResponseDTO;
30 import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetResultDTO;
31 import org.openhab.binding.bsblan.internal.configuration.BsbLanBridgeConfiguration;
32 import org.openhab.core.io.net.http.HttpUtil;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * Utility class to call the BSB-LAN REST API.
38  *
39  * @author Peter Schraffl - Initial contribution
40  */
41 @NonNullByDefault
42 public class BsbLanApiCaller {
43
44     private final Logger logger = LoggerFactory.getLogger(BsbLanApiCaller.class);
45     private final BsbLanBridgeConfiguration bridgeConfig;
46
47     public BsbLanApiCaller(BsbLanBridgeConfiguration config) {
48         bridgeConfig = config;
49     }
50
51     public @Nullable BsbLanApiParameterQueryResponseDTO queryParameter(Integer parameterId) {
52         return queryParameters(Set.of(parameterId));
53     }
54
55     public @Nullable BsbLanApiParameterQueryResponseDTO queryParameters(Set<Integer> parameterIds) {
56         // note: make the request even if parameterIds is empty as
57         // thing OFFLINE/ONLINE detection relies on a response
58         String apiPath = String.format("/JQ=%s",
59                 parameterIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
60         return makeRestCall(BsbLanApiParameterQueryResponseDTO.class, "GET", apiPath, null);
61     }
62
63     public boolean setParameter(Integer parameterId, String value, BsbLanApiParameterSetRequestDTO.Type type) {
64         // prepare request content
65         BsbLanApiParameterSetRequestDTO request = new BsbLanApiParameterSetRequestDTO();
66         request.parameter = parameterId.toString();
67         request.value = value;
68         request.type = type;
69
70         // make REST call and process response
71         BsbLanApiParameterSetResponseDTO setResponse = makeRestCall(BsbLanApiParameterSetResponseDTO.class, "POST",
72                 "/JS", request);
73         if (setResponse == null) {
74             logger.debug("Failed to set parameter {} to '{}': no response received", parameterId, value);
75             return false;
76         }
77
78         BsbLanApiParameterSetResultDTO result = setResponse.getOrDefault(parameterId, null);
79         if (result == null) {
80             logger.debug("Failed to set parameter {} to '{}'': result is null", parameterId, value);
81             return false;
82         }
83         if (result.status == null) {
84             logger.debug("Failed to set parameter {} to '{}': status is null", parameterId, value);
85             return false;
86         }
87         if (result.status != BsbLanApiParameterSetResultDTO.Status.SUCCESS) {
88             logger.debug("Failed to set parameter {} to '{}': status = {}", parameterId, value, result.status);
89             return false;
90         }
91         return true;
92     }
93
94     private String createApiBaseUrl() {
95         final String host = bridgeConfig.host == null ? "" : bridgeConfig.host.trim();
96         final String username = bridgeConfig.username == null ? "" : bridgeConfig.username.trim();
97         final String password = bridgeConfig.password == null ? "" : bridgeConfig.password.trim();
98         final String passkey = bridgeConfig.passkey == null ? "" : bridgeConfig.passkey.trim();
99
100         StringBuilder url = new StringBuilder();
101         url.append("http://");
102         if (!username.isBlank() && !password.isBlank()) {
103             url.append(username).append(":").append(password).append("@");
104         }
105         url.append(host);
106         if (bridgeConfig.port != 80) {
107             url.append(":").append(bridgeConfig.port);
108         }
109         if (!passkey.isBlank()) {
110             url.append("/").append(passkey);
111         }
112         return url.toString();
113     }
114
115     /**
116      * @param responseType response class type
117      * @param httpMethod to execute
118      * @param apiPath to request
119      * @param content to add to request
120      * @return the object representation of the json response
121      */
122     private <T> @Nullable T makeRestCall(Class<T> responseType, String httpMethod, String apiPath,
123             @Nullable BsbLanApiContentDTO request) {
124         try {
125             String url = createApiBaseUrl() + apiPath;
126             logger.trace("api request url = '{}'", url);
127
128             InputStream contentStream = null;
129             String contentType = null;
130             if (request != null) {
131                 String content = BsbLanApiContentConverter.toJson(request);
132                 logger.trace("api request content: '{}'", content);
133                 if (!content.isBlank()) {
134                     contentStream = new ByteArrayInputStream(content.getBytes(Charset.forName("UTF-8")));
135                     contentType = "application/json";
136                 }
137             }
138
139             String response = HttpUtil.executeUrl(httpMethod, url, contentStream, contentType, API_TIMEOUT);
140             if (response == null) {
141                 logger.debug("no response returned");
142                 return null;
143             }
144
145             logger.trace("api response content: '{}'", response);
146             return BsbLanApiContentConverter.fromJson(response, responseType);
147         } catch (IOException | IllegalStateException e) {
148             logger.debug("Error executing bsb-lan api request: {}", e.getMessage());
149             return null;
150         }
151     }
152 }