Skip to content

Commit 2837b20

Browse files
committed
KlapProtocol immediate relogin if protocol invalid v1.1
In case of HTTP403 response to a request, the binding now executes repeat login and then retries the request, avoiding unnecessary device-offline report. This situation typically occurs if a Tapo Hub or Tapo-App is also polling the Tapo device. (Copilot issues addressed 1.1) Closes #20316 Signed-off-by: David Henshaw <david@henshaws.me>
1 parent 6219f2a commit 2837b20

2 files changed

Lines changed: 7 additions & 5 deletions

File tree

bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/protocol/klap/KlapCipher.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public byte[] encrypt(String str) throws TapoErrorHandler {
102102
Cipher encodeCipher = getCipher(Cipher.ENCRYPT_MODE, ivSeq);
103103
byte[] msg = str.getBytes(CIPHER_CHARSET);
104104
byte[] cipherText = encodeCipher.doFinal(msg);
105-
byte[] signature = sha256Encode(concatBytes(sig, BigInteger.valueOf(ivSeq).toByteArray(), cipherText));
105+
byte[] signature = sha256Encode(concatBytes(sig, getIv(ivSeq), cipherText));
106106
return concatBytes(signature, cipherText);
107107
} catch (Exception e) {
108108
throw new TapoErrorHandler(ERR_DATA_ENCRYPTING, e.getMessage());
@@ -129,13 +129,13 @@ public String decrypt(byte[] byteArr, int ivSeq) throws TapoErrorHandler {
129129
* @param ivSeq ivSequence-Number
130130
*/
131131
private byte[] getIv(int ivSeq) throws TapoErrorHandler {
132-
/* seq must be 4 bytes long */
132+
/* return Iv, must be 4 bytes long */
133133
byte[] seq = new byte[4];
134134
seq[0] = (byte) (ivSeq >>> 24);
135135
seq[1] = (byte) (ivSeq >>> 16);
136136
seq[2] = (byte) (ivSeq >>> 8);
137137
seq[3] = (byte) ivSeq;
138-
return concatBytes(iv, seq);
138+
return seq;
139139
}
140140

141141
/************************
@@ -202,4 +202,5 @@ private Cipher getCipher(int opMode, int ivSeq) throws TapoErrorHandler {
202202
throw new TapoErrorHandler(e);
203203
}
204204
}
205+
205206
}

bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/protocol/klap/KlapProtocol.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public class KlapProtocol implements org.openhab.binding.tapocontrol.internal.ap
5151
protected final TapoConnectorInterface httpDelegator;
5252
private KlapSession session;
5353
private String uid;
54-
private ExecutorService executor = Executors.newSingleThreadExecutor();
54+
private ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
5555

5656
/***********************
5757
* Init Class
@@ -137,7 +137,7 @@ public void sendAsyncRequest(TapoBaseRequestInterface tapoRequest) throws TapoEr
137137
* pushes (decrypted) TapoResponse to [httpDelegator.handleResponse()]-function
138138
* retries login+command if Http 403 response indicates klap protocol no longer valid
139139
*/
140-
private void sendRequestRetryable(TapoBaseRequestInterface tapoRequest) throws TapoErrorHandler {
140+
private synchronized void sendRequestRetryable(TapoBaseRequestInterface tapoRequest) throws TapoErrorHandler {
141141
/*
142142
* send request, and retry with re-login if protocol rejected
143143
* (Protocol can be rejected due to polling from another device e.g. Tapo App, or Tapo H100 Hub)
@@ -231,6 +231,7 @@ private void sendRequestRetryable(TapoBaseRequestInterface tapoRequest) throws T
231231
httpDelegator.handleError(new TapoErrorHandler(ERR_BINDING_CONNECT_TIMEOUT, errorMessage));
232232
return;
233233
} catch (InterruptedException e) {
234+
Thread.currentThread().interrupt();
234235
throw new TapoErrorHandler(e, "error sending content");
235236
} catch (Exception e) {
236237
String errorMessage = e.getMessage();

0 commit comments

Comments
 (0)