heart rate sleep data and steps count obtained

watch_integration
tahaalam 1 month ago
parent 4912f686f9
commit df0b926e59

@ -6,25 +6,29 @@ import com.ejada.hmg.MainActivity
import android.os.Build import android.os.Build
import android.util.Log import android.util.Log
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import com.ejada.hmg.penguin.PenguinView
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
import com.ejada.hmg.PermissionManager.HostNotificationPermissionManager import com.ejada.hmg.samsung_watch.model.Vitals
import com.ejada.hmg.PermissionManager.HostBgLocationManager
import com.ejada.hmg.PermissionManager.HostGpsStateManager
import com.samsung.android.sdk.health.data.HealthDataService import com.samsung.android.sdk.health.data.HealthDataService
import com.samsung.android.sdk.health.data.HealthDataStore import com.samsung.android.sdk.health.data.HealthDataStore
import com.samsung.android.sdk.health.data.data.AggregatedData
import com.samsung.android.sdk.health.data.data.HealthDataPoint
import com.samsung.android.sdk.health.data.permission.AccessType import com.samsung.android.sdk.health.data.permission.AccessType
import com.samsung.android.sdk.health.data.permission.Permission import com.samsung.android.sdk.health.data.permission.Permission
import com.samsung.android.sdk.health.data.request.DataType
import com.samsung.android.sdk.health.data.request.DataTypes import com.samsung.android.sdk.health.data.request.DataTypes
import com.samsung.android.sdk.health.data.request.LocalTimeFilter import com.samsung.android.sdk.health.data.request.LocalTimeFilter
import com.samsung.android.sdk.health.data.request.LocalTimeGroup
import com.samsung.android.sdk.health.data.request.LocalTimeGroupUnit
import com.samsung.android.sdk.health.data.request.Ordering import com.samsung.android.sdk.health.data.request.Ordering
import com.samsung.android.sdk.health.data.response.DataResponse
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.time.Duration
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.LocalTime import java.time.LocalTime
@ -37,6 +41,9 @@ class SamsungWatch(
private lateinit var dataStore: HealthDataStore private lateinit var dataStore: HealthDataStore
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private val TAG = "SamsungWatch" private val TAG = "SamsungWatch"
private lateinit var vitals: MutableMap<String, List<Vitals>>
companion object { companion object {
private const val CHANNEL = "samsung_watch" private const val CHANNEL = "samsung_watch"
@ -55,6 +62,7 @@ class SamsungWatch(
"init" -> { "init" -> {
Log.d(TAG, "onMethodCall: init called") Log.d(TAG, "onMethodCall: init called")
dataStore = HealthDataService.getStore(mainActivity) dataStore = HealthDataService.getStore(mainActivity)
vitals = mutableMapOf()
result.success("initialized") result.success("initialized")
} }
@ -75,13 +83,17 @@ class SamsungWatch(
try { try {
var granted = dataStore.getGrantedPermissions(permSet) var granted = dataStore.getGrantedPermissions(permSet)
if(granted.containsAll(granted)) if (granted.containsAll(permSet)) {
result.success("Permission Granted") // adapt result as needed result.success("Permission Granted")
return@launch
}
granted = dataStore.requestPermissions(permSet, mainActivity) granted = dataStore.requestPermissions(permSet, mainActivity)
if(granted.containsAll(granted)) if (granted.containsAll(permSet)) {
result.success("Permission Granted") // adapt result as needed result.success("Permission Granted") // adapt result as needed
return@launch
}
result.error("PermissionError", "Permission Not Granted", null) // adapt result as needed result.error("PermissionError", "Permission Not Granted", null) // adapt result as needed
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "create: getPermission failed", e) Log.e(TAG, "create: getPermission failed", e)
@ -91,8 +103,8 @@ class SamsungWatch(
} }
"getHeartRate"->{ "getHeartRate"->{
val dateTime = LocalDateTime.now().with(LocalTime.MIDNIGHT) val dateTime = LocalDateTime.now().with(LocalTime.MIDNIGHT).minusDays(365)
val localTimeFilter = LocalTimeFilter.of(dateTime, dateTime.minusDays(365)) val localTimeFilter = LocalTimeFilter.of(dateTime, LocalDateTime.now())
val readRequest = DataTypes.HEART_RATE.readDataRequestBuilder val readRequest = DataTypes.HEART_RATE.readDataRequestBuilder
.setLocalTimeFilter(localTimeFilter) .setLocalTimeFilter(localTimeFilter)
.setOrdering(Ordering.DESC) .setOrdering(Ordering.DESC)
@ -100,9 +112,47 @@ class SamsungWatch(
scope.launch { scope.launch {
val heartRateList = dataStore.readData(readRequest).dataList val heartRateList = dataStore.readData(readRequest).dataList
Log.d(TAG, "create: heart rate data count: ${heartRateList}") processHeartVital(heartRateList)
Log.d("TAG"," the data is ${vitals}")
print("the data is ${vitals}")
result.success("Permission Granted")
}
}
"getSleepData" -> {
val dateTime = LocalDateTime.now().with(LocalTime.MIDNIGHT).minusDays(365)
val localTimeFilter = LocalTimeFilter.of(dateTime, LocalDateTime.now())
val readRequest = DataTypes.SLEEP.readDataRequestBuilder
.setLocalTimeFilter(localTimeFilter)
.setOrdering(Ordering.ASC)
.build()
scope.launch {
val sleepData = dataStore.readData(readRequest).dataList
processSleepVital(sleepData)
print("the data is $vitals")
Log.d(TAG, "the data is $vitals")
result.success("Permission Granted")
}
} }
"steps"->{
val dateTime = LocalDateTime.now().with(LocalTime.MIDNIGHT).minusDays(365)
val localTimeFilter = LocalTimeFilter.of(dateTime, LocalDateTime.now())
val localTimeGroup = LocalTimeGroup.of(LocalTimeGroupUnit.HOURLY, 1)
val aggregateRequest = DataType.StepsType.TOTAL.requestBuilder
.setLocalTimeFilterWithGroup(localTimeFilter, localTimeGroup)
.setOrdering(Ordering.ASC)
.build()
scope.launch {
val steps = dataStore.aggregateData(aggregateRequest)
processStepsCount(steps)
print("the data is $vitals")
Log.d(TAG, "the data is $vitals")
result.success("Permission Granted")
}
} }
@ -118,6 +168,50 @@ class SamsungWatch(
} }
} }
private fun CoroutineScope.processStepsCount(result: DataResponse<AggregatedData<Long>>) {
val stepCount = ArrayList<AggregatedData<Long>>()
var totalSteps: Long = 0
vitals["steps"] = emptyList()
result.dataList.forEach { stepData ->
val vitalData = Vitals().apply {
value = (stepData.value as Long).toString()
timeStamp = stepData.startTime.toString()
}
(vitals["sleep"] as MutableList).add(vitalData)
}
}
private fun CoroutineScope.processSleepVital(sleepData: List<HealthDataPoint>) {
vitals["sleep"] = mutableListOf()
sleepData.forEach {
(vitals["sleep"] as MutableList).add(
Vitals().apply {
timeStamp = it.startTime.toString()
value = (it.getValue(DataType.SleepType.DURATION)?.toString().toString())
}
)
}
}
private suspend fun CoroutineScope.processHeartVital(
heartRateList: List<HealthDataPoint>,
) {
vitals["heartRate"] = mutableListOf()
heartRateList.forEach {
(vitals["heartRate"] as MutableList).add(processHeartRateData(it))
}
}
private fun processHeartRateData(heartRateData: HealthDataPoint) =
Vitals().apply {
heartRateData.getValue(DataType.HeartRateType.MAX_HEART_RATE)?.let {
value = it.toString()
}
timeStamp = heartRateData.startTime.toString()
}
fun destroy() { fun destroy() {
scope.cancel() scope.cancel()
} }

@ -0,0 +1,6 @@
package com.ejada.hmg.samsung_watch.model
data class Vitals(
var value : String = "",
var timeStamp : String = ""
)

@ -109,6 +109,7 @@ class HealthProvider with ChangeNotifier {
if (result.isError) { if (result.isError) {
error = 'Error initializing device: ${result.asError}'; error = 'Error initializing device: ${result.asError}';
} else { } else {
getHeartRate();
getIt.get<NavigationService>().pushPage(page: SmartWatchActivity()); getIt.get<NavigationService>().pushPage(page: SmartWatchActivity());
print('Device initialized successfully'); print('Device initialized successfully');
} }

@ -185,6 +185,13 @@ class HealthService {
print('No watch helper found'); print('No watch helper found');
return; return;
} }
try {
await watchHelper!.getHeartRate(); await watchHelper!.getHeartRate();
await watchHelper!.getSleep();
await watchHelper!.getSteps();
}catch(e){
print('Error getting heart rate: $e');
}
} }
} }

@ -28,4 +28,20 @@ class SamsungPlatformChannel {
return Result.error(e); return Result.error(e);
} }
} }
Future<Result<bool>> getSleep() async {
try{
await _channel.invokeMethod('getSleepData');
return Result.value(true);
}catch(e){
return Result.error(e);
}
}
Future<Result<bool>> getSteps() async {
try{
await _channel.invokeMethod('steps');
return Result.value(true);
}catch(e){
return Result.error(e);
}
}
} }

@ -10,7 +10,14 @@ class SamsungHealth extends WatchHelper {
@override @override
FutureOr<void> getHeartRate() async { FutureOr<void> getHeartRate() async {
try {
await platformChannel.getHeartRate(); await platformChannel.getHeartRate();
}catch(e){
print('Error getting heart rate: $e');
}
} }
@override @override
@ -22,4 +29,24 @@ class SamsungHealth extends WatchHelper {
return await platformChannel.getRequestedPermission(); return await platformChannel.getRequestedPermission();
} }
@override
FutureOr<void> getSleep() async {
try {
await platformChannel.getSleep();
}catch(e){
print('Error getting heart rate: $e');
}
}
@override
FutureOr<void> getSteps() async{
try {
await platformChannel.getSteps();
}catch(e){
print('Error getting heart rate: $e');
}
}
} }

@ -3,5 +3,7 @@ import 'package:async/async.dart';
abstract class WatchHelper { abstract class WatchHelper {
Future<Result<bool>> initDevice(); Future<Result<bool>> initDevice();
FutureOr<void> getHeartRate(); FutureOr<void> getHeartRate();
FutureOr<void> getSleep();
FutureOr<void> getSteps();
} }
Loading…
Cancel
Save