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.util.Log
import androidx.annotation.RequiresApi
import com.ejada.hmg.penguin.PenguinView
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import com.ejada.hmg.PermissionManager.HostNotificationPermissionManager
import com.ejada.hmg.PermissionManager.HostBgLocationManager
import com.ejada.hmg.PermissionManager.HostGpsStateManager
import com.ejada.hmg.samsung_watch.model.Vitals
import com.samsung.android.sdk.health.data.HealthDataService
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.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.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.response.DataResponse
import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import java.time.Duration
import java.time.LocalDateTime
import java.time.LocalTime
@ -37,6 +41,9 @@ class SamsungWatch(
private lateinit var dataStore: HealthDataStore
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private val TAG = "SamsungWatch"
private lateinit var vitals: MutableMap<String, List<Vitals>>
companion object {
private const val CHANNEL = "samsung_watch"
@ -55,6 +62,7 @@ class SamsungWatch(
"init" -> {
Log.d(TAG, "onMethodCall: init called")
dataStore = HealthDataService.getStore(mainActivity)
vitals = mutableMapOf()
result.success("initialized")
}
@ -75,13 +83,17 @@ class SamsungWatch(
try {
var granted = dataStore.getGrantedPermissions(permSet)
if(granted.containsAll(granted))
result.success("Permission Granted") // adapt result as needed
if (granted.containsAll(permSet)) {
result.success("Permission Granted")
return@launch
}
granted = dataStore.requestPermissions(permSet, mainActivity)
if(granted.containsAll(granted))
if (granted.containsAll(permSet)) {
result.success("Permission Granted") // adapt result as needed
return@launch
}
result.error("PermissionError", "Permission Not Granted", null) // adapt result as needed
} catch (e: Exception) {
Log.e(TAG, "create: getPermission failed", e)
@ -91,8 +103,8 @@ class SamsungWatch(
}
"getHeartRate"->{
val dateTime = LocalDateTime.now().with(LocalTime.MIDNIGHT)
val localTimeFilter = LocalTimeFilter.of(dateTime, dateTime.minusDays(365))
val dateTime = LocalDateTime.now().with(LocalTime.MIDNIGHT).minusDays(365)
val localTimeFilter = LocalTimeFilter.of(dateTime, LocalDateTime.now())
val readRequest = DataTypes.HEART_RATE.readDataRequestBuilder
.setLocalTimeFilter(localTimeFilter)
.setOrdering(Ordering.DESC)
@ -100,8 +112,46 @@ class SamsungWatch(
scope.launch {
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() {
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) {
error = 'Error initializing device: ${result.asError}';
} else {
getHeartRate();
getIt.get<NavigationService>().pushPage(page: SmartWatchActivity());
print('Device initialized successfully');
}

@ -185,6 +185,13 @@ class HealthService {
print('No watch helper found');
return;
}
await watchHelper!.getHeartRate();
try {
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);
}
}
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
FutureOr<void> getHeartRate() async {
await platformChannel.getHeartRate();
try {
await platformChannel.getHeartRate();
}catch(e){
print('Error getting heart rate: $e');
}
}
@override
@ -22,4 +29,24 @@ class SamsungHealth extends WatchHelper {
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 {
Future<Result<bool>> initDevice();
FutureOr<void> getHeartRate();
FutureOr<void> getSleep();
FutureOr<void> getSteps();
}
Loading…
Cancel
Save