App React Native que transforma qualquer celular Android num node completo do OpenClaw, com acesso a todos os recursos de hardware do dispositivo.
Ter controle total sobre o código do node mobile, sem depender de apps de terceiros. O app implementa o protocolo WebSocket do OpenClaw Gateway e expõe todos os recursos do celular para o agente.
| Recurso | Comandos | Biblioteca |
|---|---|---|
| 📸 Câmera | camera.snap, camera.clip |
react-native-camera-kit |
| 📍 GPS | location.get |
react-native-geolocation |
| 🎤 Microfone | audio.record |
react-native-audio-api |
| 🔊 Alto-falante | audio.play, audio.tts |
react-native-tts + expo-av |
| 🔵 Bluetooth | bluetooth.scan, bluetooth.connect, bluetooth.send |
react-native-ble-plx |
| 📡 NFC | nfc.read, nfc.write |
react-native-nfc-manager |
| 🧭 Sensores | sensors.read, sensors.subscribe |
react-native-sensors |
| 📱 SMS | sms.send |
Native bridge |
| 📂 Filesystem | fs.read, fs.write, fs.list |
react-native-fs |
| 💻 Sistema | system.run, system.info |
Native bridge |
┌─────────────────────────────────────┐
│ OpenClaw Gateway │
│ (DeskFelipeDell :18789) │
└──────────────┬──────────────────────┘
│ WebSocket (JSON frames)
│
┌──────────────▼──────────────────────┐
│ App React Native (Android) │
│ │
│ ┌───────────────────────────────┐ │
│ │ Protocol Layer (TS) │ │
│ │ - WebSocket client │ │
│ │ - Handshake + auth + pairing │ │
│ │ - Request/Response/Event │ │
│ │ - Reconnect automático │ │
│ └──────────────┬────────────────┘ │
│ │ │
│ ┌──────────────▼────────────────┐ │
│ │ Command Router (TS) │ │
│ │ - Recebe node.invoke │ │
│ │ - Despacha pro handler certo │ │
│ └──────────────┬────────────────┘ │
│ │ │
│ ┌──────────────▼────────────────┐ │
│ │ Hardware Handlers │ │
│ │ camera.* → CameraKit │ │
│ │ location.* → Geolocation │ │
│ │ bluetooth.* → BLE-PLX │ │
│ │ audio.* → Audio API │ │
│ │ sensors.* → RN Sensors │ │
│ │ nfc.* → NFC Manager │ │
│ │ sms.* → Native bridge │ │
│ │ fs.* → RN-FS │ │
│ │ system.* → Shell/Info │ │
│ └───────────────────────────────┘ │
│ │
│ ┌───────────────────────────────┐ │
│ │ Foreground Service (Kotlin) │ │
│ │ - Mantém app vivo │ │
│ │ - Notificação persistente │ │
│ │ - Wake lock parcial │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘
-
Protocol Layer — Implementa o protocolo OpenClaw (connect challenge, handshake com
role: "node", framing req/res/event, auth com device token, reconnect com backoff exponencial) -
Command Router — Quando o Gateway envia
node.invoke, o router despacha pro handler correspondente -
Hardware Handlers — Cada módulo encapsula uma lib RN e traduz entre o formato OpenClaw e a API nativa
- App conecta no WebSocket
ws://<gateway>:18789 - Recebe
connect.challengecomnonce+ts - Responde com
connect:
{
"type": "req",
"id": "...",
"method": "connect",
"params": {
"minProtocol": 3,
"maxProtocol": 3,
"client": {
"id": "quasar-node-android",
"version": "0.1.0",
"platform": "android",
"mode": "node"
},
"role": "node",
"caps": [
"camera", "location", "audio", "bluetooth",
"nfc", "sensors", "sms", "filesystem", "system"
],
"commands": [
"camera.snap", "camera.clip",
"location.get",
"audio.record", "audio.play", "audio.tts",
"bluetooth.scan", "bluetooth.connect", "bluetooth.send",
"nfc.read", "nfc.write",
"sensors.read", "sensors.subscribe",
"sms.send",
"fs.read", "fs.write", "fs.list",
"system.run", "system.info"
],
"device": {
"id": "<fingerprint>",
"publicKey": "...",
"signature": "<nonce assinado>",
"signedAt": 1737264000000,
"nonce": "..."
}
}
}- Recebe
hello-okcomdeviceToken(persiste em AsyncStorage) - Nas reconexões seguintes, usa o
deviceTokensalvo
- Backoff exponencial: 1s → 2s → 4s → 8s → max 30s
- Detecta rede via NetInfo, reconecta ao voltar online
- Heartbeat/ping a cada 15s (conforme
tickIntervalMsdo Gateway)
Gateway → App: { type: "req", id: "abc", method: "node.invoke",
params: { command: "camera.snap", ... } }
App → Gateway: { type: "res", id: "abc", ok: true,
payload: { format: "jpg", base64: "..." } }
Em caso de erro:
{ "type": "res", "id": "abc", "ok": false,
"error": { "code": "CAMERA_UNAVAILABLE", "message": "..." } }Tira foto (front/back/both), retorna { format: "jpg", base64 }
Grava vídeo curto (até 60s), retorna { format: "mp4", base64 }
Retorna { lat, lon, accuracy, timestamp }, aceita accuracy: "coarse"|"balanced"|"precise"
Grava áudio do microfone por X segundos, retorna { format: "mp3", base64 }
Recebe base64 de áudio e toca no alto-falante
Recebe texto, sintetiza com TTS do Android e toca
Escaneia dispositivos BLE, retorna [{ name, mac, rssi }]
Conecta num device por MAC
Envia dados pra um device conectado
Lê/escreve tags NFC
Leitura instantânea de { accelerometer, gyroscope, magnetometer, barometer, light, proximity }
Stream de dados por X segundos com intervalo configurável
Envia SMS para { to, message }
Acesso ao sistema de arquivos (scoped ao storage do app)
Executa comando shell (limitado no Android)
Retorna { model, brand, os, battery, network, storage }
- Foreground Service com notificação persistente ("Quasar Node • Conectado ao Gateway")
- Tipo:
FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE - Wake Lock parcial para manter CPU ativa
- Boot Receiver para auto-start após reiniciar o celular
- Network Callback para reconectar automaticamente ao mudar de rede
- Solicita desativação de otimização de bateria na primeira execução
Boot → BroadcastReceiver → Foreground Service → WebSocket → Gateway
quasar-node/
├── android/ # Código nativo Android
│ └── app/src/main/java/.../
│ ├── NodeForegroundService.kt # Foreground service
│ ├── BootReceiver.kt # Auto-start no boot
│ └── NativeBridgeModule.kt # Bridges extras
│
├── src/
│ ├── protocol/
│ │ ├── client.ts # WebSocket client + reconnect
│ │ ├── handshake.ts # Challenge, connect, auth
│ │ ├── framing.ts # Req/Res/Event types
│ │ ├── crypto.ts # Keypair, assinatura de nonce
│ │ └── storage.ts # Persistência do deviceToken
│ │
│ ├── router/
│ │ └── commandRouter.ts # Despacha node.invoke → handler
│ │
│ ├── handlers/
│ │ ├── camera.ts # camera.snap, camera.clip
│ │ ├── location.ts # location.get
│ │ ├── audio.ts # audio.record, audio.play, audio.tts
│ │ ├── bluetooth.ts # bluetooth.scan, connect, send
│ │ ├── nfc.ts # nfc.read, nfc.write
│ │ ├── sensors.ts # sensors.read, sensors.subscribe
│ │ ├── sms.ts # sms.send
│ │ ├── filesystem.ts # fs.read, fs.write, fs.list
│ │ └── system.ts # system.run, system.info
│ │
│ ├── services/
│ │ ├── foreground.ts # Interface JS pro foreground service
│ │ └── network.ts # Monitoramento de conectividade
│ │
│ ├── ui/
│ │ ├── App.tsx # Tela principal
│ │ ├── StatusScreen.tsx # Status da conexão + logs
│ │ └── SetupScreen.tsx # Config inicial (host:port)
│ │
│ └── config/
│ └── constants.ts # Versão, defaults, timeouts
│
├── package.json
├── tsconfig.json
├── babel.config.js
└── README.md
- Criar projeto React Native + TypeScript
- Foreground Service nativo (Kotlin)
- Boot receiver
- UI mínima: setup + status
- WebSocket client com reconnect + backoff
- Handshake completo: challenge → connect → hello-ok
- Keypair + assinatura de nonce
- Persistência do deviceToken
- Command router
camera.snapecamera.cliplocation.get
audio.record,audio.play,audio.tts
bluetooth.scan,bluetooth.connect,bluetooth.send
sensors.read,sensors.subscribesystem.info,system.run
nfc.read,nfc.writesms.sendfs.read,fs.write,fs.list
- Testes de longa duração (24h+)
- Edge cases e tratamento de erros
- Otimização de bateria por OEM
- Documentação completa
Total estimado: 12-17 dias
| # | Decisão | Alternativas | Motivo |
|---|---|---|---|
| 1 | React Native (não Flutter, não nativo) | Flutter, Kotlin puro, C/C++ | Preferência do dev, ecossistema JS/TS, velocidade |
| 2 | Compatível com protocolo OpenClaw | API própria independente | Integração nativa com Gateway, node real |
| 3 | RN + libs existentes | Expo, tudo nativo, C++ | Equilíbrio esforço/controle, 90% coberto |
| 4 | Permissões tudo-ou-nada | Granular, granular com atalho | Simplicidade, público confiável |
| 5 | Background obrigatório (foreground service) | Foreground only, fase 2 | Node always-on é requisito core |
| 6 | Foco Android | Android + iOS | Reduz escopo, dispositivos disponíveis |
| 7 | UI mínima (2 telas) | UI elaborada, zero UI | Setup + status, nada mais |
- iOS (pode vir depois)
- UI elaborada
- Compatibilidade com o app oficial do OpenClaw
- Alguns recursos em background (câmera, microfone) têm restrições no Android 12+ — pode ter limitações
- Bluetooth e NFC em background dependem do tipo de foreground service declarado
MIT