2 * Copyright (c) 2010-2023 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.kostalinverter.internal.secondgeneration;
15 import java.nio.charset.StandardCharsets;
16 import java.security.MessageDigest;
17 import java.security.NoSuchAlgorithmException;
18 import java.util.Base64;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.TimeoutException;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jetty.client.HttpClient;
24 import org.eclipse.jetty.client.api.ContentResponse;
25 import org.eclipse.jetty.client.api.Request;
26 import org.eclipse.jetty.client.util.StringContentProvider;
27 import org.eclipse.jetty.http.HttpHeader;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
31 import com.google.gson.JsonArray;
32 import com.google.gson.JsonIOException;
33 import com.google.gson.JsonObject;
34 import com.google.gson.JsonParser;
37 * The {@link SecondGenerationConfigurationHandler} is responsible for configuration changes,
38 * regarded to second generation part of the binding.
40 * @author Örjan Backsell - Initial contribution Piko1020, Piko New Generation
43 public class SecondGenerationConfigurationHandler {
45 public static void executeConfigurationChanges(HttpClient httpClient, String url, String username, String password,
46 String dxsId, String value)
47 throws InterruptedException, ExecutionException, TimeoutException, NoSuchAlgorithmException {
48 String urlLogin = url + "/api/login.json?";
50 String sessionId = "";
52 Logger logger = LoggerFactory.getLogger(SecondGenerationConfigurationHandler.class);
54 String getAuthenticateResponse = httpClient.GET(urlLogin).getContentAsString();
57 JsonObject getAuthenticateResponseJsonObject = (JsonObject) JsonParser
58 .parseString(transformJsonResponse(getAuthenticateResponse));
60 sessionId = extractSessionId(getAuthenticateResponseJsonObject);
62 JsonObject authenticateJsonObject = JsonParser.parseString(getAuthenticateResponse.toString())
64 salt = authenticateJsonObject.get("salt").getAsString();
66 String saltedPassword = new StringBuilder(password).append(salt).toString();
67 MessageDigest mDigest = MessageDigest.getInstance("SHA1");
69 byte[] mDigestedPassword = mDigest.digest(saltedPassword.getBytes(StandardCharsets.UTF_8));
70 StringBuilder loginPostStringBuilder = new StringBuilder();
71 for (int i = 0; i < mDigestedPassword.length; i++) {
72 loginPostStringBuilder.append(Integer.toString((mDigestedPassword[i] & 0xff) + 0x100, 16).substring(1));
74 String saltedmDigestedPwd = Base64.getEncoder().encodeToString(mDigest.digest(saltedPassword.getBytes()));
76 String loginPostJsonData = "{\"mode\":1,\"userId\":\"" + username + "\",\"pwh\":\"" + saltedmDigestedPwd
79 Request loginPostJsonResponse = httpClient.POST(urlLogin + "?sessionId=" + sessionId);
80 loginPostJsonResponse.header(HttpHeader.CONTENT_TYPE, "application/json");
81 loginPostJsonResponse.content(new StringContentProvider(loginPostJsonData));
82 ContentResponse loginPostJsonDataContentResponse = loginPostJsonResponse.send();
84 String loginPostResponse = new String(loginPostJsonDataContentResponse.getContent(),
85 StandardCharsets.UTF_8);
87 JsonObject loginPostJsonObject = (JsonObject) JsonParser
88 .parseString(transformJsonResponse(loginPostResponse));
90 sessionId = extractSessionId(loginPostJsonObject);
92 // Part for sending data to Inverter
93 String postJsonData = "{\"dxsEntries\":[{\"dxsId\":" + dxsId + ",\"value\":" + value + "}]}";
95 Request postJsonDataRequest = httpClient.POST(url + "/api/dxs.json?sessionId=" + sessionId);
96 postJsonDataRequest.header(HttpHeader.CONTENT_TYPE, "application/json");
97 postJsonDataRequest.content(new StringContentProvider(postJsonData));
98 postJsonDataRequest.send();
99 } catch (JsonIOException getAuthenticateResponseException) {
100 logger.debug("Could not read the response: {}", getAuthenticateResponseException.getMessage());
104 static String transformJsonResponse(String jsonResponse) {
105 // Method transformJsonResponse converts response,due to missing [] in ContentResponse
106 // postJsonDataContentResponse.
108 int sessionStartPosition = jsonResponse.indexOf("session");
109 int statusStartPosition = jsonResponse.indexOf("status");
111 StringBuilder transformStringBuilder = new StringBuilder();
113 transformStringBuilder.append(jsonResponse);
115 transformStringBuilder.insert(sessionStartPosition + 9, '[');
116 int roleIdStartPosition = jsonResponse.indexOf("roleId");
117 transformStringBuilder.insert(roleIdStartPosition + 11, ']');
119 transformStringBuilder.insert(statusStartPosition + 10, '[');
120 int codeStartPosition = jsonResponse.indexOf("code");
121 transformStringBuilder.insert(codeStartPosition + 11, ']');
123 String transformJsonObject = transformStringBuilder.toString();
125 return transformJsonObject;
128 // Method extractSessionId extracts sessionId from JsonObject
129 static String extractSessionId(JsonObject extractJsonObjectSessionId) {
130 Logger sessionIdLogger = LoggerFactory.getLogger(SecondGenerationConfigurationHandler.class);
131 String extractSessionId = "";
132 JsonArray extractJsonArraySessionId = extractJsonObjectSessionId.getAsJsonArray("session");
134 int size = extractJsonArraySessionId.size();
136 extractSessionId = extractJsonArraySessionId.get(size - 1).getAsJsonObject().get("sessionId").getAsString();
138 if ("0".equals(extractSessionId)) {
139 sessionIdLogger.debug(" Login Post Json Reponse not OK! , inverter answered with sessionId like: {}",
142 return extractSessionId;
145 // Method extractCode extracts code from JsonObject
146 static String extractCode(JsonObject extractJsonObjectCode) {
147 Logger codeLogger = LoggerFactory.getLogger(SecondGenerationConfigurationHandler.class);
148 String extractCode = "";
149 JsonArray extractJsonArrayCode = extractJsonObjectCode.getAsJsonArray("status");
151 int size = extractJsonArrayCode.size();
153 extractCode = extractJsonArrayCode.get(size - 1).getAsJsonObject().get("code").getAsString();
155 if (!"0".equals(extractCode)) {
156 codeLogger.debug(" Login Post Json Reponse not OK! , inverter answered with status code like: {}",