From 33de6569310b77be68cf6932a4e168ce5f90d7d5 Mon Sep 17 00:00:00 2001 From: Johann Date: Fri, 3 Jul 2026 22:41:43 -0600 Subject: [PATCH] =?UTF-8?q?feat(battery):=20monitor=20de=20bater=C3=ADa=20?= =?UTF-8?q?por=20ACTION=5FBATTERY=5FCHANGED?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit callbackFlow sobre el sticky broadcast (sin polling, CLAUDE.md §8). Alimenta el chip DA-08 del dashboard y es la base del módulo 3. --- .../platform/battery/BatteryStatusMonitor.kt | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 app/app/src/main/java/mx/paputec/rachita/platform/battery/BatteryStatusMonitor.kt diff --git a/app/app/src/main/java/mx/paputec/rachita/platform/battery/BatteryStatusMonitor.kt b/app/app/src/main/java/mx/paputec/rachita/platform/battery/BatteryStatusMonitor.kt new file mode 100644 index 0000000..bb7f35c --- /dev/null +++ b/app/app/src/main/java/mx/paputec/rachita/platform/battery/BatteryStatusMonitor.kt @@ -0,0 +1,43 @@ +package mx.paputec.rachita.platform.battery + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.os.BatteryManager +import javax.inject.Inject +import javax.inject.Singleton +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import mx.paputec.rachita.domain.model.BatteryStatus + +/** + * Real battery level + charging state from ACTION_BATTERY_CHANGED (sticky + * broadcast — no polling, CLAUDE.md §8). Feeds the dashboard chip (DA-08) now + * and the low-battery/charging-lock flows of module 3 later. + */ +@Singleton +class BatteryStatusMonitor @Inject constructor( + private val context: Context, +) { + val status: Flow = callbackFlow { + val receiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + trySend(intent.toBatteryStatus()) + } + } + val sticky = context.registerReceiver(receiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + sticky?.let { trySend(it.toBatteryStatus()) } + awaitClose { context.unregisterReceiver(receiver) } + }.distinctUntilChanged() +} + +private fun Intent.toBatteryStatus(): BatteryStatus { + val level = getIntExtra(BatteryManager.EXTRA_LEVEL, -1) + val scale = getIntExtra(BatteryManager.EXTRA_SCALE, -1) + val percent = if (level >= 0 && scale > 0) (level * 100) / scale else 100 + val plugged = getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) + return BatteryStatus(percent = percent, isCharging = plugged != 0) +}