Kinetic WOL es una app Android nativa para guardar equipos de red, despertarlos con Wake-on-LAN y apagarlos de forma remota cuando el dispositivo tiene una ruta de apagado configurada.
El apagado remoto puede hacerse por dos vías:
- SSH directo al equipo remoto
- agente Linux HTTP, disponible en Neikon/kinetic_sol
La descarga rápida del APK está en las releases del repositorio:
El control por voz con Assistant/Gemini todavía está pendiente. El proyecto incluye base técnica para App Actions y fulfillment headless, pero la invocación real desde voz aún no está cerrada ni validada como funcional para usuarios finales.
- App Android nativa funcional
- UI principal en Jetpack Compose
- Persistencia local real con Room
- Envío WOL manual funcional
- Apagado remoto manual funcional por agente Linux HTTP
- Apagado remoto manual funcional por SSH con clave privada, fingerprint de host y comando configurable
- Quick tile de Android con selector para despertar y apagar dispositivos compatibles
- Fulfillment headless funcional mediante
WakeDeviceActivity - Shortcuts dinámicos publicados para equipos guardados
- Recursos bilingües en español e inglés
- Pipeline de GitHub Actions que compila APK debug y publica una prerelease en cada push relevante a
main
Validaciones ya hechas sobre la app:
- creación, edición y borrado de dispositivos
- envío de magic packets contra un listener UDP local
- apagado remoto contra el agente Linux HTTP
- apagado remoto por SSH en un PC Linux con
sudoerspreparado - apagado remoto por SSH en TrueNAS SCALE
- invocación headless por
adbresolviendo dispositivos por nombre - aparición de shortcuts dinámicos al mantener pulsado el icono de la app
Pendiente importante:
- el control por voz real con Assistant/Gemini todavía está por hacer
- falta generar y validar una
internal testing releasepara cerrar el flujo real de App Actions
- Kotlin
- Jetpack Compose
- Material 3
- Room
- sshj
- Android SDK 36
minSdk = 36- Java 17
app/src/main/java/dev/neikon/kineticwol/
├── actions/ # fulfillment headless y shortcuts dinámicos
├── data/ # Room y repositorio
├── domain/ # modelo y lógica WOL/apagado remoto
├── ui/ # Compose, estado y tema
└── util/ # utilidades compartidas
Piezas clave:
- MainActivity.kt: entrada principal de la app
- KineticWolApp.kt: dashboard, formulario y navegación principal
- HomeViewModel.kt: estado, validación y acciones de la pantalla
- WakeOnLanSender.kt: normalización MAC y envío del magic packet
- AgentShutdownSender.kt: apagado remoto por agente Linux HTTP
- SshShutdownSender.kt: apagado remoto por SSH
- SshKeyMaterialGenerator.kt: generación de claves SSH dentro de la app
- WakeDeviceActivity.kt: ejecución headless por intent
- WakeQuickTileService.kt: tile rápida de Android
- DeviceShortcutPublisher.kt: shortcuts dinámicos por dispositivo
- shortcuts.xml: capability y query patterns de App Actions
Para abrir y compilar el proyecto:
- Android Studio reciente
- Android SDK 36
- JDK 17 o el
Embedded JDKde Android Studio
Notas:
- el proyecto usa
minSdk 36, así que solo apunta a Android 16+ - en este repo no se está usando
gradlew; la compilación se ha validado desde Android Studio
El workflow de GitHub Actions publica una prerelease por cada push relevante a main.
Para descargar el APK:
- Abre GitHub Releases.
- Entra en la release más reciente
main-.... - Descarga el archivo
kinetic-wol-main-....apk.
- Abre el repo en Android Studio.
- Asegúrate de que el
Gradle JDKapunta al JDK embebido o a Java 17+. - Sincroniza el proyecto.
- Ejecuta
:appsobre un emulador o dispositivo Android 16+.
El repo incluye un listener Python para verificar que llegan magic packets:
Ejemplo recomendado:
python3 scripts/listen_wol.py --port 4009 --onceLuego crea un dispositivo en la app apuntando a tu host:
Nombre: el que prefierasMAC: una MAC válida de pruebaHost: IP de tu equipo o10.0.2.2si disparas desde emulador AndroidPuerto:4009
Una vez guardado un dispositivo en la app, puedes disparar el fulfillment sin tocar la UI:
adb -s emulator-5554 shell am start -W \
-a dev.neikon.kineticwol.action.WAKE_DEVICE \
-n dev.neikon.kineticwol/.actions.WakeDeviceActivity \
--es deviceName "bazzite"Eso debería resolver el dispositivo guardado por nombre y enviar el magic packet.
Kinetic WOL permite apagar un dispositivo guardado si se activa la sección de apagado remoto en el formulario del dispositivo.
Métodos soportados:
Agente: agente Linux HTTP autenticado por Bearer tokenSSH: conexión SSH por clave privada, fingerprint de host y comando remoto configurable
El agente Linux compatible con esta ruta está en:
La app espera este contrato:
GET /api/v1/statusPOST /api/v1/poweroffAuthorization: Bearer <token>
En el editor del dispositivo configura:
- URL base del agente
- token
- método
Agente
Usa Probar conexión antes de guardar como ruta de apagado habitual.
En el editor del dispositivo configura:
- host SSH
- puerto, normalmente
22 - usuario
- clave privada
- fingerprint del host
- comando remoto
La app puede generar un par de claves SSH. Copia la clave pública que muestra la app al authorized_keys del usuario remoto.
El comando por defecto es:
sudo -n systemctl poweroffPara TrueNAS SCALE se ha validado usando:
sudo -n /usr/sbin/shutdown -h nowEl usuario remoto debe poder ejecutar el comando configurado sin prompt interactivo. En Linux normalmente hay que preparar una regla específica de sudoers o, en TrueNAS SCALE, añadir el ejecutable permitido en los comandos sudo sin contraseña del usuario.
Guía detallada para Linux:
Guía detallada para TrueNAS SCALE desde la Web UI:
Estado: pendiente de cerrar y validar como experiencia real de usuario.
El proyecto incluye base técnica:
shortcuts.xmlmeta-datade shortcuts en el manifest- activity headless exportada
- shortcuts dinámicos por equipo
Pero el control por voz todavía no está terminado:
- no se ha encontrado un built-in intent oficial específico para Wake-on-LAN
- la solución actual usa un
custom intent - la documentación oficial sigue mencionando un
App Actions test tool, pero en el entorno del proyecto ese plugin no aparece disponible en Android Studio - la validación real de Assistant/Gemini probablemente requerirá una
internal testing release
La guía preparada para eso está en:
Tests unitarios incluidos:
- WakeOnLanSenderTest.kt
- DeviceNameNormalizerTest.kt
- AgentShutdownSenderTest.kt
- SshShutdownSenderTest.kt
- AGENTS.md: índice y reglas operativas
- docs/agent_memory.md: memoria persistente del proyecto
- docs/app_spec.md: especificación funcional y técnica
- docs/roadmap.md: histórico, estado y próximos pasos
- docs/release_internal_testing.md: guía para testing interno en Play Console
- CRUD de dispositivos
- Persistencia con Room
- Envío WOL manual
- Apagado remoto por agente Linux HTTP
- Apagado remoto por SSH
- Fulfillment headless
- Shortcuts dinámicos
- Quick tile de Android
- Publicación automática de APK en GitHub Releases
- Limpieza inicial de build con AGP 9
- Mejoras de UX en formulario y navegación
- Implementar/cerrar la invocación real desde Assistant/Gemini fuera de
adb - Endurecer la estrategia final de App Actions y validar una
internal testing release - Decidir si se añade historial persistente de eventos