feat: completar integracion M530 backend, telemetria y cierre SOS central
This commit is contained in:
parent
41b81c972a
commit
1b130a9ed8
5 changed files with 82 additions and 5 deletions
|
|
@ -1,5 +1,7 @@
|
|||
package com.bodycamera.twentyfoulabs.data.auth
|
||||
|
||||
import android.util.Log
|
||||
|
||||
import com.bodycamera.twentyfoulabs.data.backend.BackendConfig
|
||||
import com.bodycamera.twentyfoulabs.data.backend.DeviceIdentity
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -44,6 +46,18 @@ class AuthApiClient @Inject constructor(
|
|||
json.decodeFromString<LoginResponse>(response)
|
||||
}
|
||||
|
||||
suspend fun refresh(request: RefreshRequest): RefreshResponse =
|
||||
withContext(Dispatchers.IO) {
|
||||
val body = json.encodeToString(request)
|
||||
val response = request(
|
||||
"POST",
|
||||
"/mobile/v1/auth/refresh",
|
||||
body = body
|
||||
)
|
||||
Log.i("AuthApiClient", "AUTH REFRESH OK")
|
||||
json.decodeFromString<RefreshResponse>(response)
|
||||
}
|
||||
|
||||
suspend fun me(token: String): MeResponse =
|
||||
withContext(Dispatchers.IO) {
|
||||
val response = request(
|
||||
|
|
@ -173,3 +187,9 @@ class AuthApiException(
|
|||
val statusCode: Int,
|
||||
override val message: String
|
||||
) : Exception(message)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@ data class LoginRequest(
|
|||
@SerialName("device_model") val deviceModel: String? = null
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class RefreshRequest(
|
||||
@SerialName("refresh_token") val refreshToken: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class QrLoginRequest(
|
||||
@SerialName("qr_token") val qrToken: String,
|
||||
|
|
@ -63,6 +68,15 @@ data class LoginResponse(
|
|||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class RefreshResponse(
|
||||
@SerialName("access_token") val accessToken: String? = null,
|
||||
@SerialName("refresh_token") val refreshToken: String? = null,
|
||||
@SerialName("token_type") val tokenType: String? = null,
|
||||
@SerialName("expires_in") val expiresIn: Int? = null,
|
||||
@SerialName("server_time") val serverTime: String? = null
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MeResponse(
|
||||
val user: AuthUser,
|
||||
|
|
@ -88,3 +102,7 @@ data class AuthSession(
|
|||
val device: AuthDevice? = null,
|
||||
val refreshToken: String? = null
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -127,11 +127,21 @@ session
|
|||
|
||||
} catch (e: AuthApiException) {
|
||||
|
||||
if (e.statusCode == 401) {
|
||||
if (e.statusCode == 401 && !refreshToken.isNullOrBlank()) {
|
||||
android.util.Log.i("AuthRepository", "401 inicial detectado - intentando refresh")
|
||||
val refreshed = api.refresh(RefreshRequest(refreshToken))
|
||||
val newToken = refreshed.accessToken?.takeIf { it.isNotBlank() } ?: throw e
|
||||
val refreshedResponse = try { api.me(newToken) } catch (retryError: AuthApiException) { if (retryError.statusCode == 401) { store.clear(); android.util.Log.i("AuthRepository", "Segundo 401 - sesion eliminada"); throw retryError } else { throw retryError } }
|
||||
val newRefreshToken = refreshed.refreshToken?.takeIf { it.isNotBlank() } ?: refreshToken
|
||||
val refreshedSession = AuthSession(token = newToken, user = refreshedResponse.user, device = refreshedResponse.device ?: refreshedResponse.user.assignedDevice, refreshToken = newRefreshToken)
|
||||
store.save(refreshedSession)
|
||||
refreshedSession
|
||||
} else if (e.statusCode == 401) {
|
||||
store.clear()
|
||||
throw e
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,3 +163,20 @@ suspend fun logout() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.bodycamera.twentyfoulabs.data.device
|
||||
package com.bodycamera.twentyfoulabs.data.device
|
||||
|
||||
import android.Manifest
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
|
|
@ -82,8 +83,11 @@ class M530DeviceController @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private val powerReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == Intent.ACTION_POWER_CONNECTED || intent?.action == Intent.ACTION_POWER_DISCONNECTED) { Log.i(TAG, "Cambio de cargador detectado: ${intent.action}"); logTelemetry() } } }
|
||||
|
||||
init {
|
||||
startLocationUpdates()
|
||||
context.registerReceiver(powerReceiver, IntentFilter().apply { addAction(Intent.ACTION_POWER_CONNECTED); addAction(Intent.ACTION_POWER_DISCONNECTED) })
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -460,7 +464,7 @@ Result.success(file)
|
|||
}
|
||||
|
||||
if (location == null) {
|
||||
Log.w(TAG, "GPS: sin ubicación reciente; se omite el envÃÂÂo")
|
||||
Log.w(TAG, "GPS: sin ubicación reciente; se omite el envÃÂo")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -609,3 +613,6 @@ Result.success(file)
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -203,6 +203,10 @@ private fun vibrateRecordingStopped() {
|
|||
result.onSuccess { state ->
|
||||
val previous = centralSosCadenceActive
|
||||
centralSosCadenceActive = state.isSosCadenceActive
|
||||
if (previous && !centralSosCadenceActive && sosSessionActive.get()) {
|
||||
Log.i(TAG, "SOS cerrado desde central - finalizando sesion SOS local")
|
||||
stopVideoFromUi()
|
||||
}
|
||||
if (previous != centralSosCadenceActive) {
|
||||
Log.i(
|
||||
TAG,
|
||||
|
|
@ -668,3 +672,4 @@ data class DeviceStatus(
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue