2020import java .net .URI ;
2121import java .net .UnknownHostException ;
2222import java .nio .ByteBuffer ;
23+ import java .util .Objects ;
2324import java .util .concurrent .TimeUnit ;
2425import java .util .concurrent .TimeoutException ;
26+ import java .util .function .Consumer ;
27+ import java .util .function .Supplier ;
2528
2629import org .eclipse .jdt .annotation .NonNullByDefault ;
2730import org .eclipse .jdt .annotation .Nullable ;
3134import org .eclipse .jetty .client .util .BufferingResponseListener ;
3235import org .eclipse .jetty .http .HttpStatus ;
3336import org .eclipse .jetty .http .HttpStatus .Code ;
37+ import org .openhab .binding .solaredge .internal .config .PublicApiAuthentication ;
38+ import org .openhab .binding .solaredge .internal .config .PublicApiVersion ;
3439import org .openhab .binding .solaredge .internal .config .SolarEdgeConfiguration ;
3540import org .openhab .binding .solaredge .internal .connector .CommunicationStatus ;
3641import org .openhab .binding .solaredge .internal .connector .StatusUpdateListener ;
@@ -72,6 +77,10 @@ public abstract class AbstractCommand extends BufferingResponseListener implemen
7277 * listener to provide updates to the WebInterface class
7378 */
7479 private final StatusUpdateListener listener ;
80+ private final Supplier <String > publicApiV2CredentialSupplier ;
81+ private final Runnable publicApiV2CredentialInvalidator ;
82+ private final Runnable publicApiV2RequestRecorder ;
83+ private final Consumer <Response > publicApiV2RateLimitListener ;
7584
7685 /**
7786 * the constructor
@@ -81,9 +90,37 @@ public abstract class AbstractCommand extends BufferingResponseListener implemen
8190 *
8291 */
8392 public AbstractCommand (SolarEdgeConfiguration config , StatusUpdateListener listener ) {
93+ this (config , listener , config ::getTokenOrApiKey , () -> {
94+ }, () -> {
95+ }, response -> {
96+ });
97+ }
98+
99+ protected AbstractCommand (SolarEdgeConfiguration config , StatusUpdateListener listener ,
100+ Supplier <String > publicApiV2CredentialSupplier ) {
101+ this (config , listener , publicApiV2CredentialSupplier , () -> {
102+ }, () -> {
103+ }, response -> {
104+ });
105+ }
106+
107+ protected AbstractCommand (SolarEdgeConfiguration config , StatusUpdateListener listener ,
108+ Supplier <String > publicApiV2CredentialSupplier , Runnable publicApiV2CredentialInvalidator ) {
109+ this (config , listener , publicApiV2CredentialSupplier , publicApiV2CredentialInvalidator , () -> {
110+ }, response -> {
111+ });
112+ }
113+
114+ protected AbstractCommand (SolarEdgeConfiguration config , StatusUpdateListener listener ,
115+ Supplier <String > publicApiV2CredentialSupplier , Runnable publicApiV2CredentialInvalidator ,
116+ Runnable publicApiV2RequestRecorder , Consumer <Response > publicApiV2RateLimitListener ) {
84117 this .communicationStatus = new CommunicationStatus ();
85118 this .config = config ;
86119 this .listener = listener ;
120+ this .publicApiV2CredentialSupplier = publicApiV2CredentialSupplier ;
121+ this .publicApiV2CredentialInvalidator = publicApiV2CredentialInvalidator ;
122+ this .publicApiV2RequestRecorder = publicApiV2RequestRecorder ;
123+ this .publicApiV2RateLimitListener = publicApiV2RateLimitListener ;
87124 this .gson = new Gson ();
88125 }
89126
@@ -93,9 +130,14 @@ public AbstractCommand(SolarEdgeConfiguration config, StatusUpdateListener liste
93130 @ Override
94131 public final void onSuccess (Response response ) {
95132 super .onSuccess (response );
96- if (response != null ) {
97- communicationStatus .setHttpCode (HttpStatus .getCode (response .getStatus ()));
98- logger .debug ("HTTP response {}" , response .getStatus ());
133+ communicationStatus .setHttpCode (HttpStatus .getCode (response .getStatus ()));
134+ logger .debug ("HTTP response {}" , response .getStatus ());
135+ if (!config .isUsePrivateApi () && PublicApiVersion .V2 .equals (config .getPublicApiVersion ())) {
136+ publicApiV2RateLimitListener .accept (response );
137+ }
138+ if (response .getStatus () == HttpStatus .UNAUTHORIZED_401
139+ && PublicApiAuthentication .OAUTH .equals (config .getPublicApiAuthentication ())) {
140+ publicApiV2CredentialInvalidator .run ();
99141 }
100142 }
101143
@@ -109,7 +151,7 @@ public final void onFailure(@Nullable Response response, @Nullable Throwable fai
109151 }
110152 if (failure != null ) {
111153 logger .debug ("Request failed: {}" , failure .toString ());
112- communicationStatus .setError (( Exception ) failure );
154+ communicationStatus .setError (failure instanceof Exception exception ? exception : new Exception ( failure ) );
113155
114156 if (failure instanceof SocketTimeoutException || failure instanceof TimeoutException ) {
115157 communicationStatus .setHttpCode (Code .REQUEST_TIMEOUT );
@@ -126,7 +168,8 @@ public final void onFailure(@Nullable Response response, @Nullable Throwable fai
126168 @ Override
127169 public void onContent (Response response , ByteBuffer content ) {
128170 super .onContent (response , content );
129- logger .debug ("received content, length: {}" , getContentAsString ().length ());
171+ String receivedContent = getContentAsString ();
172+ logger .debug ("received content, length: {}" , receivedContent == null ? 0 : receivedContent .length ());
130173 }
131174
132175 @ Override
@@ -142,11 +185,20 @@ public void performAction(HttpClient asyncclient) {
142185 c .setDomain (PRIVATE_API_TOKEN_COOKIE_DOMAIN );
143186 c .setPath (PRIVATE_API_TOKEN_COOKIE_PATH );
144187 cookieStore .add (URI .create (getURL ()), c );
188+ } else if (PublicApiVersion .V2 .equals (config .getPublicApiVersion ())) {
189+ String credential = Objects .requireNonNull (publicApiV2CredentialSupplier .get ());
190+ if (PublicApiAuthentication .OAUTH .equals (config .getPublicApiAuthentication ())) {
191+ request .header ("Authorization" , "Bearer " + credential );
192+ } else {
193+ request .header (PUBLIC_DATA_API_V2_KEY_HEADER , credential );
194+ }
145195 } else {
146- // this is only relevant when using public API
147196 request .param (PUBLIC_DATA_API_KEY_FIELD , config .getTokenOrApiKey ());
148197 }
149198
199+ if (!config .isUsePrivateApi () && PublicApiVersion .V2 .equals (config .getPublicApiVersion ())) {
200+ publicApiV2RequestRecorder .run ();
201+ }
150202 prepareRequest (request ).send (this );
151203 }
152204
@@ -157,6 +209,14 @@ public CommunicationStatus getCommunicationStatus() {
157209 return communicationStatus ;
158210 }
159211
212+ /** Returns whether a failed request may succeed when retried shortly afterwards. */
213+ protected final boolean isRetryable () {
214+ return switch (communicationStatus .getHttpCode ()) {
215+ case REQUEST_TIMEOUT , INTERNAL_SERVER_ERROR , BAD_GATEWAY , SERVICE_UNAVAILABLE , GATEWAY_TIMEOUT -> true ;
216+ default -> false ;
217+ };
218+ }
219+
160220 /**
161221 * updates status of the registered listener.
162222 */
0 commit comments