2 * Copyright (c) 2010-2021 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.bsblan.internal.api;
15 import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*;
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.HashSet;
24 import org.apache.commons.lang.StringUtils;
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiContentDTO;
28 import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterQueryResponseDTO;
29 import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetRequestDTO;
30 import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetResponseDTO;
31 import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetResultDTO;
32 import org.openhab.binding.bsblan.internal.configuration.BsbLanBridgeConfiguration;
33 import org.openhab.core.io.net.http.HttpUtil;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * Utility class to call the BSB-LAN REST API.
40 * @author Peter Schraffl - Initial contribution
43 public class BsbLanApiCaller {
45 private final Logger logger = LoggerFactory.getLogger(BsbLanApiCaller.class);
46 private final BsbLanBridgeConfiguration bridgeConfig;
48 public BsbLanApiCaller(BsbLanBridgeConfiguration config) {
49 bridgeConfig = config;
52 public @Nullable BsbLanApiParameterQueryResponseDTO queryParameter(Integer parameterId) {
53 Set<Integer> parameters = new HashSet<>();
55 parameters.add(parameterId);
56 return queryParameters(parameters);
59 public @Nullable BsbLanApiParameterQueryResponseDTO queryParameters(Set<Integer> parameterIds) {
60 // note: make the request even if parameterIds is empty as
61 // thing OFFLINE/ONLINE detection relies on a response
63 String apiPath = String.format("/JQ=%s", StringUtils.join(parameterIds, ","));
64 return makeRestCall(BsbLanApiParameterQueryResponseDTO.class, "GET", apiPath, null);
67 public boolean setParameter(Integer parameterId, String value, BsbLanApiParameterSetRequestDTO.Type type) {
68 // prepare request content
69 BsbLanApiParameterSetRequestDTO request = new BsbLanApiParameterSetRequestDTO();
70 request.parameter = parameterId.toString();
71 request.value = value;
74 // make REST call and process response
75 BsbLanApiParameterSetResponseDTO setResponse = makeRestCall(BsbLanApiParameterSetResponseDTO.class, "POST",
77 if (setResponse == null) {
78 logger.debug("Failed to set parameter {} to '{}': no response received", parameterId, value);
82 BsbLanApiParameterSetResultDTO result = setResponse.getOrDefault(parameterId, null);
84 logger.debug("Failed to set parameter {} to '{}'': result is null", parameterId, value);
87 if (result.status == null) {
88 logger.debug("Failed to set parameter {} to '{}': status is null", parameterId, value);
91 if (result.status != BsbLanApiParameterSetResultDTO.Status.SUCCESS) {
92 logger.debug("Failed to set parameter {} to '{}': status = {}", parameterId, value, result.status);
98 private String createApiBaseUrl() {
99 final String host = StringUtils.trimToEmpty(bridgeConfig.host);
100 final String username = StringUtils.trimToEmpty(bridgeConfig.username);
101 final String password = StringUtils.trimToEmpty(bridgeConfig.password);
102 final String passkey = StringUtils.trimToEmpty(bridgeConfig.passkey);
104 StringBuilder url = new StringBuilder();
105 url.append("http://");
106 if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
107 url.append(username).append(":").append(password).append("@");
110 if (bridgeConfig.port != 80) {
111 url.append(":").append(bridgeConfig.port);
113 if (StringUtils.isNotBlank(passkey)) {
114 url.append("/").append(passkey);
116 return url.toString();
120 * @param responseType response class type
121 * @param httpMethod to execute
122 * @param apiPath to request
123 * @param content to add to request
124 * @return the object representation of the json response
126 private <T> @Nullable T makeRestCall(Class<T> responseType, String httpMethod, String apiPath,
127 @Nullable BsbLanApiContentDTO request) {
129 String url = createApiBaseUrl() + apiPath;
130 logger.trace("api request url = '{}'", url);
132 InputStream contentStream = null;
133 String contentType = null;
134 if (request != null) {
135 String content = BsbLanApiContentConverter.toJson(request);
136 logger.trace("api request content: '{}'", content);
137 if (StringUtils.isNotBlank(content)) {
138 contentStream = new ByteArrayInputStream(content.getBytes(Charset.forName("UTF-8")));
139 contentType = "application/json";
143 String response = HttpUtil.executeUrl(httpMethod, url, contentStream, contentType, API_TIMEOUT);
144 if (response == null) {
145 logger.debug("no response returned");
149 logger.trace("api response content: '{}'", response);
150 return BsbLanApiContentConverter.fromJson(response, responseType);
151 } catch (IOException | IllegalStateException e) {
152 logger.debug("Error executing bsb-lan api request: {}", e.getMessage());