Commit e36c37af authored by Lisa (AI Assistant)'s avatar Lisa (AI Assistant)

Fix: Send pairing request when WebSocket closes due to device auth error

parent 4ba8722f
...@@ -34,10 +34,29 @@ ...@@ -34,10 +34,29 @@
2. **Client ID**: Changed to "cli" (the only working client ID) 2. **Client ID**: Changed to "cli" (the only working client ID)
### Current Status (2026-03-11 16:45) ### Current Status (2026-03-11 17:15)
- Build: Working ✅ - Build: Working ✅
- Install: Working ✅ - Install: Working ✅
- Pairing: STILL FAILING - need to rebuild APK with "cli" client ID ❌ - Device Identity: PERSISTENT - uses RSA key pair stored in SharedPreferences ✅
- Device ID: `6a19599727bd964992898ac4251a9e08c52ae4740d2b0c927c11dc5d424a92bf`
- Client ID: "cli" ✅
- Pairing: STILL FAILING - gateway rejects device signature (device not registered) ❌
### Analysis
- Device identity persistence is working correctly (RSA key pair stored in SharedPreferences)
- Gateway requires device registration - no UI to approve nodes
- Cannot register device from here (no gateway API access)
- Current device ID: `6a19599727bd964992898ac4251a9e08c52ae4740d2b0c927c11dc5d424a92bf`
- Token: `415fa3c21b7ef06f22aff571697d88c59c2dc67737681267`
### Next Steps
1. Either register this device manually via gateway UI (not possible from here)
2. Or use a pre-registered device identity from the project
3. Or modify gateway to accept this device signature
### Files Modified
- `app/src/main/java/com/nexlab/openclaw/node/data/remote/NodeClient.kt` - Added device identity persistence
- `app/src/main/java/com/nexlab/openclaw/node/service/NodeService.kt` - Added `nodeClient.setContext(this)`
### Next Steps ### Next Steps
1. **BLOCKED**: Rebuild APK with "cli" client ID 1. **BLOCKED**: Rebuild APK with "cli" client ID
......
...@@ -246,10 +246,14 @@ class NodeClient() { ...@@ -246,10 +246,14 @@ class NodeClient() {
isPairingMode = false isPairingMode = false
_connectionStatus.trySend(ConnectionStatus(true, nodeId)) _connectionStatus.trySend(ConnectionStatus(true, nodeId))
} else { } else {
// Check if it's a device-required error // Check if it's a device-required or device signature error
val error = json.optJSONObject("error")?.optString("message", "Connection failed") val error = json.optJSONObject("error")?.optString("message", "Connection failed")
if (error?.contains("device-required") == true && isPairingMode) { Log.d(TAG, "Connection failed with error: $error")
if ((error?.contains("device-required") == true ||
error?.contains("device signature") == true ||
error?.contains("invalid") == true) && isPairingMode) {
// Now send pairing request after connect failed // Now send pairing request after connect failed
Log.d(TAG, "Sending pairing request after connection rejection")
sendPairingRequest(currentNodeId, currentToken, capabilities) sendPairingRequest(currentNodeId, currentToken, capabilities)
} else { } else {
_connectionStatus.trySend(ConnectionStatus(false, nodeId)) _connectionStatus.trySend(ConnectionStatus(false, nodeId))
...@@ -271,12 +275,32 @@ class NodeClient() { ...@@ -271,12 +275,32 @@ class NodeClient() {
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) { override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
Log.d(TAG, "WebSocket closing: code=$code reason=$reason") Log.d(TAG, "WebSocket closing: code=$code reason=$reason")
// Check if it's a device signature error and we should send pairing request
if (isPairingMode && (reason.contains("device signature") ||
reason.contains("invalid") ||
reason.contains("device-required"))) {
Log.d(TAG, "Connection rejected due to device auth, sending pairing request")
// Send pairing request after connection rejection
sendPairingRequest(currentNodeId, currentToken, capabilities)
}
webSocket.close(1000, null) webSocket.close(1000, null)
} }
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
Log.d(TAG, "WebSocket closed: code=$code reason=$reason") Log.d(TAG, "WebSocket closed: code=$code reason=$reason")
isConnected = false isConnected = false
// Also check here in case onClosing didn't handle it
if (isPairingMode && (reason.contains("device signature") ||
reason.contains("invalid") ||
reason.contains("device-required"))) {
Log.d(TAG, "Connection rejected due to device auth, sending pairing request")
sendPairingRequest(currentNodeId, currentToken, capabilities)
return
}
_connectionStatus.trySend(ConnectionStatus(false, nodeId)) _connectionStatus.trySend(ConnectionStatus(false, nodeId))
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment