App móvil (React Native + Expo SDK 54) para monitorear sensores y operar actuadores (relés) de los hubs LibreAgro (ESP32). Se comunica directamente con el hub vía HTTP/REST y, donde aplica, con backends externos.
- Modo Directo: Wi-Fi directo al hub (AP), IP fija
192.168.4.1. - Modo Online: a través de internet (hub en modo STA), contra el backend.
El modo de conexión se elige con el switch del header. La IP del hub no se descubre: en Directo es fija (
192.168.4.1); en Online el acceso va contra el backend identificado por elhashdel hub.
- Node 20+
- JDK 17 (para compilar Android)
- Android SDK (para builds locales) — el CI ya lo trae preinstalado
- No hace falta commitear
android/niios/: se generan conexpo prebuild.
npm cinpm start # expo start (Metro)
npm run android # abre en AndroidEn desarrollo la app usa datos mock por defecto (no necesita un hub real). Los servicios reales se activan solo en builds de release (ver más abajo).
Para notificaciones nativas/background (con la app abierta o cerrada), LibreAgro utiliza UnifiedPush integrado con la app oficial de ntfy (io.heckel.ntfy) como distribuidor.
El flujo de registro es invertido y dinámico:
- La app LibreAgro genera un Endpoint único de notificaciones a través de
ntfy(ej.https://ntfy.sh/upqWunC0oivigx?up=1). - Al conectarse en Modo Directo, la app envía automáticamente su endpoint al ESP32 vía
POST http://192.168.4.1/api/notify/subscribe. - El ESP32 almacena la lista de suscriptores (consultables en
GET /api/notify/subscribers). - Al dispararse una alarma, el ESP32 emite la notificación realizando un HTTP POST directamente al endpoint del celular registrado.
- El módulo nativo Kotlin
NtfyPushPayloadRenderer.kten LibreAgro procesa el mensaje en background y muestra la notificación nativa de Android.
Ver la guía técnica completa en docs/ntfy-android-mvp.md.
npm test # jest
npx tsc --noEmit # chequeo de tiposTodas usan el prefijo EXPO_PUBLIC_ (se inyectan en build time). Los valores
por defecto en el código son mock, por eso en desarrollo la app funciona
sin backend.
| Variable | Valores | Default | Qué controla |
|---|---|---|---|
EXPO_PUBLIC_HUB_DATA_BACKEND |
mock | http |
mock |
/config, /actual, /api/relays, toggle, alarmas de /actual.errors, ping |
EXPO_PUBLIC_NOTIFY_BACKEND |
mock | http |
mock |
Push de alarmas vía ntfy.sh |
EXPO_PUBLIC_NOTIFY_BASE_URL |
URL | https://ntfy.sh |
Broker de ntfy |
EXPO_PUBLIC_RECOMMENDATIONS_BACKEND |
mock | http |
mock |
Recomendaciones (/messages) |
EXPO_PUBLIC_RECOMMENDATIONS_BASE_URL |
URL | — | Base URL del backend de recomendaciones (cuando exista) |
expo start(desarrollo) → no carga.env.production→ la app usa mocks.- Builds de release (
--variant release/assembleRelease) → Expo carga.env.production, que ya trae los valores sin mocks.
Por eso un APK compilado en debug sale con mocks y no se asocia al chip. Para probar con el hub real hay que usar un APK release (o descargar el del CI).
El APK release queda firmado con la debug keystore del template de Expo, así que es instalable por sideload (no apto para Play Store, sí para probar).
No requiere compilar localmente:
- GitHub → pestaña Actions → última corrida de CI en
main. - Sección Artifacts → descargar
libreagro-directo-apk. - Descomprimir →
libreagro-directo.apk→ instalar en el teléfono.
En releases por tag (v*) el APK también queda adjunto en la página de
Releases.
npm ci
npx expo prebuild --platform android --no-install
cd android
./gradlew assembleReleaseAPK resultante:
android/app/build/outputs/apk/release/app-release.apk
Atajo equivalente (compila e instala en un dispositivo conectado):
npx expo run:android --variant releaseImportante: usá siempre release. Un
expo run:androidsin--variant releasecompila en debug → mocks → no conecta con el chip.
Workflow: .github/workflows/ci.yml
| Job | Cuándo | Qué hace |
|---|---|---|
test |
push y PR | npm ci, tsc --noEmit, npm test |
build-android |
push a main, tags v*, manual |
expo prebuild + gradlew assembleRelease (env de release sin mocks) → sube APK como artifact; en tags adjunta el APK al Release |
git tag v1.0.0
git push origin v1.0.0El CI compila el APK y lo adjunta automáticamente al GitHub Release del tag.
src/
components/ UI (incluye ZoneAssignSheet, AlarmCard, ...)
screens/ pantallas (HubList, HubHome, SensorDetail, ActuatorDetail, Alarms, Crops, Recommendations)
services/
hubApi/ cliente del hub (mock | http) + adapters + parser de alarmas
notifyApi/ cliente ntfy.sh (mock | http)
recommendationsApi/ cliente de recomendaciones (mock | http)
connectivity.ts resuelve el target del hub según modo (Directo/Online)
hubDataService.ts fachada que usan los stores
stores/ estado (zustand): hubs, datos del hub, cultivos, zonas
features/sensors/ catálogo y rangos de medición
types/ modelos de dominio
Los clientes mock | http se seleccionan por variable de entorno, sin tocar las
pantallas. Cuando lleguen las URLs de los backends pendientes, solo cambia la
configuración (no el código de UI).