11package 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-
113import org .jsoup .Jsoup ;
124
135import io .openems .common .exceptions .OpenemsError .OpenemsNamedException ;
146import io .openems .common .exceptions .OpenemsException ;
157
168public 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