Skip to content

Commit 355ec55

Browse files
committed
mais ajustes
1 parent 3cb9bc1 commit 355ec55

2 files changed

Lines changed: 68 additions & 75 deletions

File tree

android/app/src/main/kotlin/com/beforbike/app/BleServerService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ class BleServerService : Service() {
255255
val dataCharacteristic = BluetoothGattCharacteristic(
256256
GattProfile.UUID_CHAR_DATA,
257257
BluetoothGattCharacteristic.PROPERTY_WRITE or BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE or BluetoothGattCharacteristic.PROPERTY_NOTIFY,
258-
0 // No permissions required - allow writes from any device
258+
BluetoothGattCharacteristic.PERMISSION_WRITE // No permissions required - allow writes from any device
259259
)
260260
// Add CCCD descriptor for notifications
261261
val cccd = BluetoothGattDescriptor(

android/app/src/main/kotlin/com/beforbike/app/database/RideDbHelper.kt

Lines changed: 67 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class RideDbHelper(context: Context) :
1616

1717
companion object {
1818
// Incrementado para v11 para adicionar as novas colunas
19-
const val DATABASE_VERSION = 15
19+
const val DATABASE_VERSION = 19
2020
const val DATABASE_NAME = "BikeRides.db"
2121
private const val TAG = "RideDbHelper"
2222

@@ -185,27 +185,27 @@ class RideDbHelper(context: Context) :
185185
val values = ContentValues().apply {
186186
put(TelemetryEntry.COLUMN_RIDE_ID, rideId)
187187

188-
// DADOS CRUCIAIS: Data vinda do Info
189-
put(TelemetryEntry.COLUMN_PACKET_DATE, infoMap["date"] as? String) // "yyyy-MM-dd HH:mm:ss"
188+
put(TelemetryEntry.COLUMN_PACKET_DATE, infoMap["date"] as? String)
190189
put(TelemetryEntry.COLUMN_PACKET_TIME, infoMap["time"] as? String)
191190

192191
put(TelemetryEntry.COLUMN_GPS_TIMESTAMP, gpsMap["timestamp"] as? String)
193-
put(TelemetryEntry.COLUMN_LATITUDE, gpsMap["latitude"] as? Double)
194-
put(TelemetryEntry.COLUMN_LONGITUDE, gpsMap["longitude"] as? Double)
195-
put(TelemetryEntry.COLUMN_ALTITUDE, gpsMap["altitude"] as? Double)
196-
put(TelemetryEntry.COLUMN_GPS_SPEED, gpsMap["speed"] as? Double)
197-
put(TelemetryEntry.COLUMN_DIRECTION, gpsMap["direction"] as? Double)
192+
put(TelemetryEntry.COLUMN_LATITUDE, (gpsMap["latitude"] as? Number)?.toDouble())
193+
put(TelemetryEntry.COLUMN_LONGITUDE, (gpsMap["longitude"] as? Number)?.toDouble())
194+
put(TelemetryEntry.COLUMN_ALTITUDE, (gpsMap["altitude"] as? Number)?.toDouble())
195+
put(TelemetryEntry.COLUMN_GPS_SPEED, (gpsMap["speed"] as? Number)?.toDouble())
196+
put(TelemetryEntry.COLUMN_DIRECTION, (gpsMap["direction"] as? Number)?.toDouble())
198197
put(TelemetryEntry.COLUMN_FIX_SATELLITES, gpsMap["fix_satellites"] as? Int)
199198
put(TelemetryEntry.COLUMN_FIX_QUALITY, gpsMap["fix_quality"] as? Int)
200199

201200
crankMap?.let {
202-
put(TelemetryEntry.COLUMN_POWER, it["power"] as? Double)
203-
put(TelemetryEntry.COLUMN_CADENCE, it["cadence"] as? Double)
204-
put(TelemetryEntry.COLUMN_JOULES, it["joules"] as? Double)
205-
put(TelemetryEntry.COLUMN_CRANK_CALORIES, it["calories"] as? Double)
206-
put(TelemetryEntry.COLUMN_CRANK_SPEED_MS, it["speed_ms"] as? Double)
207-
put(TelemetryEntry.COLUMN_CRANK_SPEED, it["speed"] as? Double)
208-
put(TelemetryEntry.COLUMN_CRANK_DISTANCE, it["distance"] as? Double)
201+
// AQUI ESTAVA O BUG: Usamos (Number)?.toDouble() para aceitar Zeros
202+
put(TelemetryEntry.COLUMN_POWER, (it["power"] as? Number)?.toDouble())
203+
put(TelemetryEntry.COLUMN_CADENCE, (it["cadence"] as? Number)?.toDouble())
204+
put(TelemetryEntry.COLUMN_JOULES, (it["joules"] as? Number)?.toDouble())
205+
put(TelemetryEntry.COLUMN_CRANK_CALORIES, (it["calories"] as? Number)?.toDouble())
206+
put(TelemetryEntry.COLUMN_CRANK_SPEED_MS, (it["speed_ms"] as? Number)?.toDouble())
207+
put(TelemetryEntry.COLUMN_CRANK_SPEED, (it["speed"] as? Number)?.toDouble())
208+
put(TelemetryEntry.COLUMN_CRANK_DISTANCE, (it["distance"] as? Number)?.toDouble())
209209
}
210210
}
211211
return db.insert(TelemetryEntry.TABLE_NAME, null, values) != -1L
@@ -279,17 +279,14 @@ class RideDbHelper(context: Context) :
279279
fun calculateRideStatistics(rideId: Long): Map<String, Any?>? {
280280
val db = this.readableDatabase
281281

282-
// 1. Adicionei COLUMN_CRANK_DISTANCE na projeção, pois estava faltando para cumprir o TODO da distância
283282
val cursor = db.query(
284283
TelemetryEntry.TABLE_NAME,
285284
arrayOf(
286285
TelemetryEntry.COLUMN_PACKET_DATE,
287-
TelemetryEntry.COLUMN_LATITUDE, // Mantido caso queira debug ou fallback, mas o cálculo principal mudou
288-
TelemetryEntry.COLUMN_LONGITUDE,
289286
TelemetryEntry.COLUMN_ALTITUDE,
290287
TelemetryEntry.COLUMN_GPS_SPEED,
291288
TelemetryEntry.COLUMN_CRANK_SPEED,
292-
TelemetryEntry.COLUMN_CRANK_DISTANCE, // <-- ADICIONADO
289+
TelemetryEntry.COLUMN_CRANK_DISTANCE,
293290
TelemetryEntry.COLUMN_POWER,
294291
TelemetryEntry.COLUMN_CADENCE,
295292
TelemetryEntry.COLUMN_CRANK_CALORIES
@@ -304,27 +301,28 @@ class RideDbHelper(context: Context) :
304301
return null
305302
}
306303

307-
// Variáveis de Estado
308304
var startTime: Long? = null
309305
var endTime: Long? = null
310306
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
311307

312-
// Acumuladores e Rastreadores de Máximas
308+
// Variáveis para Máximas
313309
var maxSpeed = 0.0
314310
var maxPower = 0.0
315311
var maxCadence = 0.0
316312
var maxAltitude = 0.0
317313

318-
// Listas para médias que NÃO são cumulativas
314+
// Listas para calcular as médias
315+
val speeds = mutableListOf<Double>()
319316
val powers = mutableListOf<Double>()
317+
val cadences = mutableListOf<Double>()
320318
val altitudes = mutableListOf<Double>()
321319

322-
// Variáveis para valores "Last Known" (já acumulados pelo sensor)
323-
var lastTotalDistanceKm = 0.0
320+
// Acumuladores finais
321+
var lastTotalDistanceMeters = 0.0
324322
var lastTotalCalories = 0.0
325-
var lastAvgCadence = 0.0
326323

327324
cursor.use {
325+
// Índices das colunas
328326
val dateIdx = it.getColumnIndexOrThrow(TelemetryEntry.COLUMN_PACKET_DATE)
329327
val altIdx = it.getColumnIndexOrThrow(TelemetryEntry.COLUMN_ALTITUDE)
330328
val gpsSpeedIdx = it.getColumnIndexOrThrow(TelemetryEntry.COLUMN_GPS_SPEED)
@@ -335,7 +333,7 @@ class RideDbHelper(context: Context) :
335333
val calIdx = it.getColumnIndexOrThrow(TelemetryEntry.COLUMN_CRANK_CALORIES)
336334

337335
do {
338-
// --- 1. Tempo (Start/End) ---
336+
// 1. Tempo
339337
val dateStr = it.getString(dateIdx)
340338
if (dateStr != null) {
341339
try {
@@ -345,77 +343,76 @@ class RideDbHelper(context: Context) :
345343
if (startTime == null) startTime = ts
346344
endTime = ts
347345
}
348-
} catch (e: Exception) {
349-
Log.e(TAG, "Erro parsing packet_date: $dateStr")
350-
}
346+
} catch (e: Exception) { Log.e(TAG, "Erro parse data: $dateStr") }
351347
}
352348

353-
// --- 2. Distância (#TODO: PEGAR ULTIMO VALOR) ---
349+
// 2. Distância (Acumulada em Metros)
354350
if (!it.isNull(crankDistIdx)) {
355351
val dist = it.getDouble(crankDistIdx)
356-
// Assume que o sensor envia valor cumulativo. Atualizamos sempre o "último visto".
357-
if (dist > lastTotalDistanceKm) {
358-
lastTotalDistanceKm = dist
359-
}
352+
if (dist > lastTotalDistanceMeters) lastTotalDistanceMeters = dist
360353
}
361354

362-
// --- 3. Altitude (Média e Máxima) ---
355+
// 3. Altitude (Sempre adicionamos, pois existe altitude mesmo parado)
363356
if (!it.isNull(altIdx)) {
364357
val alt = it.getDouble(altIdx)
358+
// Filtramos 0 absoluto pois geralmente é erro de GPS iniciando,
359+
// mas não filtramos "parado"
365360
if (alt != 0.0) {
366361
altitudes.add(alt)
367362
if (alt > maxAltitude) maxAltitude = alt
368363
}
369364
}
370365

371-
// --- 4. Velocidade Máxima (#TODO: PRIORIDADE CRANK) ---
366+
// 4. Velocidade
372367
val cSpeed = if (!it.isNull(crankSpeedIdx)) it.getDouble(crankSpeedIdx) else null
373368
val gSpeed = if (!it.isNull(gpsSpeedIdx)) it.getDouble(gpsSpeedIdx) else null
374-
375-
// Prioridade: Se tem CrankSpeed, usa ele. Se não, usa GPS. Se nenhum, 0.0
369+
// Prioriza sensor de roda, senão GPS, senão 0
376370
val currentSpeed = cSpeed ?: gSpeed ?: 0.0
371+
372+
speeds.add(currentSpeed) // Adiciona na lista para média
377373
if (currentSpeed > maxSpeed) maxSpeed = currentSpeed
378374

379-
// --- 5. Potência (#TODO: CALCULAR MAX E MEDIA) ---
380-
// Potência é instantânea, então acumulamos na lista para média e verificamos pico.
381-
if (!it.isNull(powerIdx)) {
382-
val p = it.getDouble(powerIdx)
383-
powers.add(p)
384-
if (p > maxPower) maxPower = p
385-
}
375+
// 5. Potência
376+
val p = if (!it.isNull(powerIdx)) it.getDouble(powerIdx) else 0.0
377+
powers.add(p)
378+
if (p > maxPower) maxPower = p
386379

387-
// --- 6. Cadência (#TODO: JA VEM SOMADO, PEGAR ULTIMA COLUNA) ---
388-
// Se "já vem somado" (ou é uma média cumulativa do sensor), guardamos o último valor para a média final.
389-
// Mas para Máxima, ainda precisamos varrer os valores instantâneos se o sensor oscilar.
390-
if (!it.isNull(cadIdx)) {
391-
val c = it.getDouble(cadIdx)
392-
lastAvgCadence = c // O último valor lido será a média/total final
393-
if (c > maxCadence) maxCadence = c
394-
}
380+
// 6. Cadência
381+
val c = if (!it.isNull(cadIdx)) it.getDouble(cadIdx) else 0.0
382+
cadences.add(c)
383+
if (c > maxCadence) maxCadence = c
395384

396-
// --- 7. Calorias (#TODO: JA VEM SOMADO) ---
385+
// 7. Calorias
397386
if (!it.isNull(calIdx)) {
398387
val cal = it.getDouble(calIdx)
399-
if (cal > lastTotalCalories) {
400-
lastTotalCalories = cal
401-
}
388+
if (cal > lastTotalCalories) lastTotalCalories = cal
402389
}
403390

404391
} while (it.moveToNext())
405392
}
406393

407-
// --- CÁLCULOS FINAIS ---
394+
// --- CÁLCULOS FINAIS COM LÓGICA DE "ATIVA" (IGNORANDO ZEROS) ---
408395

409-
val avgPower = if (powers.isNotEmpty()) powers.average() else 0.0
410-
val avgAltitude = if (altitudes.isNotEmpty()) altitudes.average() else 0.0
396+
// 1. Correção de Unidade: Metros para KM
397+
val totalDistanceKm = lastTotalDistanceMeters / 1000.0
398+
399+
// 2. Velocidade Média em Movimento (Average Moving Speed)
400+
// Filtramos velocidades muito baixas (< 1.0 km/h) que são ruído
401+
val activeSpeeds = speeds.filter { it > 1.0 }
402+
val avgSpeed = if (activeSpeeds.isNotEmpty()) activeSpeeds.average() else 0.0
411403

412-
// Velocidade Média calculada com base na Distância Final (do sensor) / Tempo Total
413-
val startTs = startTime ?: 0L
414-
val endTs = endTime ?: 0L
415-
val durationMillis = if (endTs >= startTs) endTs - startTs else 0L
416-
val durationHours = durationMillis / 1000.0 / 3600.0
404+
// 3. Potência Média Ativa (Average Active Power)
405+
// Filtramos potências < 1.0 Watt (ignora roda livre/parado)
406+
val activePowers = powers.filter { it > 1.0 }
407+
val avgPower = if (activePowers.isNotEmpty()) activePowers.average() else 0.0
417408

418-
val avgSpeed = if (durationHours > 0.002) lastTotalDistanceKm / durationHours else 0.0
409+
// 4. Cadência Média Ativa
410+
// Filtramos zeros (ignora quando parou de pedalar)
411+
val activeCadences = cadences.filter { it > 0 }
412+
val avgCadence = if (activeCadences.isNotEmpty()) activeCadences.average() else 0.0
413+
414+
// 5. Altitude Média (Geralmente se usa média total)
415+
val avgAltitude = if (altitudes.isNotEmpty()) altitudes.average() else 0.0
419416

420417
val outputDateFmt = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault())
421418

@@ -424,21 +421,17 @@ class RideDbHelper(context: Context) :
424421
"start_time" to if (startTime != null) outputDateFmt.format(Date(startTime!!)) else null,
425422
"end_time" to if (endTime != null) outputDateFmt.format(Date(endTime!!)) else null,
426423

427-
// Distância direta do sensor (último valor)
428-
"total_distance_km" to lastTotalDistanceKm,
429-
430-
// Calorias direta do sensor (último valor)
424+
"total_distance_km" to totalDistanceKm, // Agora corrigido para KM
431425
"calories" to lastTotalCalories,
432426

433427
"max_velocity_kmh" to maxSpeed,
434-
"avg_velocity_kmh" to avgSpeed,
428+
"avg_velocity_kmh" to avgSpeed, // Média apenas em movimento
435429

436430
"max_power" to maxPower,
437-
"avg_power" to avgPower,
431+
"avg_power" to avgPower, // Média apenas pedalando
438432

439433
"max_cadence" to maxCadence,
440-
// Cadência média baseada no último valor lido (conforme TODO "pegar ultima coluna")
441-
"avg_cadence" to lastAvgCadence,
434+
"avg_cadence" to avgCadence, // Média apenas pedalando
442435

443436
"max_altitude" to maxAltitude,
444437
"avg_altitude" to avgAltitude

0 commit comments

Comments
 (0)