Skip to content

Commit b51ebab

Browse files
Sn0w3ysfeilmeier
andauthored
[Edge] Bosch.BPTS5Hybrid: refactor to HttpBridge (#3650)
- overhauls the Bosch BPT-S 5 Hybrid integration for improved stability and maintainability - deletes the BoschBpts5HybridReadWorker.java file from the Bosch BPTS5 Hybrid project --------- Co-authored-by: Stefan Feilmeier <stefan.feilmeier@fenecon.de>
1 parent 0148cdb commit b51ebab

File tree

9 files changed

+448
-202
lines changed

9 files changed

+448
-202
lines changed

io.openems.edge.bosch.bpts5hybrid/bnd.bnd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Bundle-Version: 1.0.0.${tstamp}
66
-buildpath: \
77
${buildpath},\
88
io.openems.common,\
9+
io.openems.common.bridge.http,\
10+
io.openems.edge.bridge.http,\
911
io.openems.edge.common,\
1012
io.openems.edge.ess.api,\
1113
io.openems.edge.meter.api,\

io.openems.edge.bosch.bpts5hybrid/src/io/openems/edge/bosch/bpts5hybrid/core/BoschBpts5HybridApiClient.java

Lines changed: 70 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,18 @@
11
package io.openems.edge.bosch.bpts5hybrid.core;
22

3-
import java.io.IOException;
4-
import java.net.URI;
5-
import java.net.http.HttpClient;
6-
import java.net.http.HttpRequest;
7-
import java.net.http.HttpRequest.BodyPublishers;
8-
import java.net.http.HttpResponse;
9-
import java.time.Duration;
10-
113
import org.jsoup.Jsoup;
124

135
import io.openems.common.exceptions.OpenemsError.OpenemsNamedException;
146
import io.openems.common.exceptions.OpenemsException;
157

168
public class BoschBpts5HybridApiClient {
179

10+
protected static final String GET_VALUES_URL_PART = "/cgi-bin/ipcclient.fcgi?";
11+
1812
private static final String POST_REQUEST_DATA = "action=get.hyb.overview&flow=1";
1913
private static final String REQUEST_LOG_BOOK_VIEW = "&action=get.logbookview&page=0&id=&type=BATTERY&dtype=";
20-
private static final String GET_VALUES_URL_PART = "/cgi-bin/ipcclient.fcgi?";
21-
22-
private final String baseUrl;
23-
private final HttpClient httpClient;
2414

25-
private String wuiSid;
15+
private String wuiSid = "";
2616
private Integer pvLeistungWatt = Integer.valueOf(0);
2717
private Integer soc = Integer.valueOf(0);
2818
private Integer einspeisung = Integer.valueOf(0);
@@ -31,43 +21,52 @@ public class BoschBpts5HybridApiClient {
3121
private Integer verbrauchVonBatterie = Integer.valueOf(0);
3222
private Integer strombezugAusNetz = Integer.valueOf(0);
3323

34-
public BoschBpts5HybridApiClient(String ipaddress) {
35-
this.baseUrl = "http://" + ipaddress;
36-
this.httpClient = HttpClient.newBuilder() //
37-
.connectTimeout(Duration.ofSeconds(5)) //
38-
.followRedirects(HttpClient.Redirect.NORMAL) //
39-
.build();
40-
this.connect();
41-
}
42-
43-
protected void connect() {
44-
try {
45-
this.wuiSid = this.getWuiSidRequest();
46-
} catch (OpenemsNamedException e) {
47-
this.wuiSid = "";
48-
e.printStackTrace();
49-
}
24+
/**
25+
* Extract WUI_SID from initial page response.
26+
*
27+
* @param body the HTML body
28+
* @throws OpenemsException on error
29+
*/
30+
public void processConnectResponse(String body) throws OpenemsException {
31+
this.wuiSid = this.extractWuiSidFromBody(body);
5032
}
5133

52-
private String getWuiSidRequest() throws OpenemsNamedException {
53-
try {
54-
var request = HttpRequest.newBuilder() //
55-
.uri(URI.create(this.baseUrl)) //
56-
.timeout(Duration.ofSeconds(5)) //
57-
.GET() //
58-
.build();
59-
var response = this.httpClient.send(request, HttpResponse.BodyHandlers.ofString());
60-
61-
var status = response.statusCode();
62-
if (status < 300) {
63-
return this.extractWuiSidFromBody(response.body());
64-
}
65-
throw new OpenemsException("Error while reading from Bosch BPT-S 5. Response code: " + status);
66-
67-
} catch (IOException | InterruptedException e) {
68-
throw new OpenemsException(
69-
"Unable to read from Bosch BPT-S 5. " + e.getClass().getSimpleName() + ": " + e.getMessage());
70-
}
34+
/**
35+
* Gets the URL for value retrieval (POST).
36+
*
37+
* @param baseUrl the base URL
38+
* @return the full URL
39+
*/
40+
public String getValuesUrl(String baseUrl) {
41+
return baseUrl + GET_VALUES_URL_PART + this.wuiSid;
42+
}
43+
44+
/**
45+
* Gets the URL for battery status retrieval (GET).
46+
*
47+
* @param baseUrl the base URL
48+
* @return the full URL
49+
*/
50+
public String getBatteryStatusUrl(String baseUrl) {
51+
return baseUrl + GET_VALUES_URL_PART + this.wuiSid + REQUEST_LOG_BOOK_VIEW;
52+
}
53+
54+
/**
55+
* Gets the POST data for value retrieval.
56+
*
57+
* @return the POST data string
58+
*/
59+
public static String getPostRequestData() {
60+
return POST_REQUEST_DATA;
61+
}
62+
63+
/**
64+
* Returns true if WUI_SID has been obtained.
65+
*
66+
* @return true if connected
67+
*/
68+
public boolean isConnected() {
69+
return this.wuiSid != null && !this.wuiSid.isEmpty();
7170
}
7271

7372
private String extractWuiSidFromBody(String body) throws OpenemsException {
@@ -80,76 +79,46 @@ private String extractWuiSidFromBody(String body) throws OpenemsException {
8079
return body.substring(index + 9, index + 9 + 15);
8180
}
8281

83-
protected void retreiveValues() throws OpenemsException {
84-
var request = HttpRequest.newBuilder() //
85-
.uri(URI.create(this.baseUrl + GET_VALUES_URL_PART + this.wuiSid)) //
86-
.timeout(Duration.ofSeconds(5)) //
87-
.header("Content-Type", "text/plain") //
88-
.POST(BodyPublishers.ofString(POST_REQUEST_DATA)) //
89-
.build();
90-
91-
try {
92-
var response = this.httpClient.send(request, HttpResponse.BodyHandlers.ofString());
93-
var status = response.statusCode();
94-
if (status >= 300) {
95-
throw new OpenemsException("Error while reading from Bosch BPT-S 5. Response code: " + status);
96-
}
97-
this.extractValuesFromAnswer(response.body());
98-
99-
} catch (IOException | InterruptedException | OpenemsNamedException e) {
100-
throw new OpenemsException(
101-
"Unable to read from Bosch BPT-S 5. " + e.getClass().getSimpleName() + ": " + e.getMessage());
102-
}
82+
/**
83+
* Process the values response body.
84+
*
85+
* @param body the response body
86+
* @throws OpenemsNamedException on error
87+
*/
88+
public void processValuesResponse(String body) throws OpenemsNamedException {
89+
this.extractValuesFromAnswer(body);
10390
}
10491

105-
protected int retreiveBatterieStatus() throws OpenemsException {
106-
try {
107-
var request = HttpRequest.newBuilder() //
108-
.uri(URI.create(this.baseUrl + GET_VALUES_URL_PART + this.wuiSid + REQUEST_LOG_BOOK_VIEW)) //
109-
.timeout(Duration.ofSeconds(5)) //
110-
.GET() //
111-
.build();
112-
var response = this.httpClient.send(request, HttpResponse.BodyHandlers.ofString());
113-
114-
var status = response.statusCode();
115-
if (status >= 300) {
116-
throw new OpenemsException("Error while reading from Bosch BPT-S 5. Response code: " + status);
117-
}
118-
var content = response.body();
119-
var document = Jsoup.parse(content);
120-
var tableNode = document.select("table").get(0);
121-
var firstRow = tableNode.select("tr").get(0);
122-
var firstRowText = firstRow.text();
123-
if (firstRowText.contains("Störung") && !firstRowText.contains("Keine")) {
124-
return 1;
125-
} else {
126-
return 0;
127-
}
128-
129-
} catch (IOException | InterruptedException e) {
130-
throw new OpenemsException(
131-
"Unable to read from Bosch BPT-S 5. " + e.getClass().getSimpleName() + ": " + e.getMessage());
92+
/**
93+
* Process the battery status response body.
94+
*
95+
* @param body the response body
96+
* @return 0 = OK, 1 = error
97+
*/
98+
public int processBatteryStatusResponse(String body) {
99+
var document = Jsoup.parse(body);
100+
var tableNode = document.select("table").get(0);
101+
var firstRow = tableNode.select("tr").get(0);
102+
var firstRowText = firstRow.text();
103+
if (firstRowText.contains("Störung") && !firstRowText.contains("Keine")) {
104+
return 1;
132105
}
106+
return 0;
133107
}
134108

135109
private void extractValuesFromAnswer(String body) throws OpenemsNamedException {
136110
if (body.contains("session invalid")) {
137-
this.getWuiSidRequest();
111+
this.wuiSid = ""; // force reconnect
138112
return;
139113
}
140114

141115
var values = body.split("\\|");
142116

143117
this.pvLeistungWatt = this.parseWattValue(values[2]);
144-
145118
this.soc = Integer.valueOf(values[3]);
146-
147119
this.batterieLadeStrom = this.parseWattValue(values[10]);
148-
149120
this.einspeisung = this.parseWattValue(values[11]);
150-
151121
this.verbrauchVonPv = this.parseWattValue(values[12]);
152-
153122
this.verbrauchVonBatterie = this.parseWattValue(values[13]);
154123

155124
if (values.length < 15) {
@@ -163,7 +132,6 @@ private Integer parseWattValue(String inputString) {
163132
if (inputString.trim().length() == 0 || inputString.contains("nbsp;")) {
164133
return Integer.valueOf(0);
165134
}
166-
167135
var wattString = inputString.replace("kW", " ").replace("von", " ").trim();
168136
return Integer.valueOf((int) (Float.parseFloat(wattString) * 1000.0f));
169137
}

0 commit comments

Comments
 (0)