简体   繁体   English

如何从iOS中的Health Kit实时获取心率数据?

[英]How to get Heart Rate Data near by Real Time from Health Kit in iOS?

I have created a session in Watch and updating Heart Rate Data in Health Kit. 我在Watch中创建了一个会话并更新了Health Kit中的心率数据。 Now, I want to Display the current Heart Rate in my iPhone Screen. 现在,我想在iPhone屏幕上显示当前的心率。 Watch sensor update the Heart Rate Data in Health kit BUT iPhone Application in NOT able to Fetch Real-Time Data from the Health kit. 观察传感器更新健康套件中的心率数据,但iPhone应用程序无法从健康套件中获取实时数据。 I have tested out below TWO scenarios. 我已经测试了以下两种情况。 I have also recalled this method/function using timer BUT it is not getting real-time data. 我还使用计时器调用了这个方法/功能但它没有获得实时数据。

Note: When I open Health App and Re-open my application then It will automatically refresh the data. 注意:当我打开Health App并重新打开我的应用程序时,它会自动刷新数据。 If my application continuously in foreground then below code not refreshing latest data from the health kit 如果我的应用程序持续处于前台,则代码下方不会刷新健康工具包中的最新数据

1. Tried to get Real Time Heart Rate Data using HKSampleQuery 1.尝试使用HKSampleQuery获取实时心率数据

        let calendar = NSCalendar.current
        let components = calendar.dateComponents([.year, .month, .day], from: Date())
        let startDate : NSDate = calendar.date(from: components)! as NSDate
        let endDate : Date = calendar.date(byAdding: Calendar.Component.day, value: 1, to: startDate as Date)!

        let predicate = HKQuery.predicateForSamples(withStart: startDate as Date, end: endDate, options:[])

        //descriptor
        let sortDescriptors = [NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)]

        self.heartRateQuery = HKSampleQuery(sampleType: self.heartRateType, predicate: predicate, limit: 1, sortDescriptors: sortDescriptors, resultsHandler: { (query:HKSampleQuery,  results:[HKSample]?, error:Error?) in

            guard error == nil else { print("error in getting data"); return }

            self.collectCurrentHeartRateSample(currentSampleTyple: results)

        })

        self.healthStore.execute(self.heartRateQuery!)

2. Tried to get Real Time Heart Rate Data using HKAnchoredObjectQuery 2.尝试使用HKAnchoredObjectQuery获取实时心率数据

    let sampleType : HKSampleType =  HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
    let predicate : NSPredicate =  HKQuery.predicateForSamples(withStart: startDate as Date, end: endDate, options: [])
    let anchor: HKQueryAnchor = HKQueryAnchor(fromValue: 0)

    let anchoredQuery = HKAnchoredObjectQuery(type: sampleType, predicate: predicate, anchor: anchor, limit: HKObjectQueryNoLimit) { (query, samples, deletedObjects, anchor, error ) in

        self.collectCurrentHeartRateSample(currentSampleTyple: samples!, deleted: deletedObjects!)

    }

    anchoredQuery.updateHandler = { (query, samples, deletedObjects, anchor, error) -> Void in
        self.collectCurrentHeartRateSample(currentSampleTyple: samples!, deleted: deletedObjects!)
    }

    self.healthStore.execute(anchoredQuery)

============================================= =============================================

Parsed the Data 解析数据

func collectCurrentHeartRateSample(currentSampleTyple : [HKSample]?, deleted : 

    [HKDeletedObject]?){

    //    func collectCurrentHeartRateSample(currentSampleTyple : [HKSample]?){

            DispatchQueue.main.async {

                self.currentHeartRateSample = currentSampleTyple

                //Get Last Sample of Heart Rate
                self.currentHeartLastSample = self.currentHeartRateSample?.last
                print("lastSample : \(String(describing: self.currentHeartLastSample))")

                if self.currentHeartLastSample != nil {

                    let result = self.currentHeartLastSample as! HKQuantitySample

                    let heartRateBPM = result.quantity.doubleValue(for: HKUnit(from: "count/min"))
                    let heartRateBPMUnit = "count/min"

                    let deviceUUID = self.currentHeartLastSample?.uuid
                    let deviceIdentity = result.sourceRevision.source.name
                    let deviceProductName = self.currentHeartLastSample?.device?.name
                    let deviceProductType = result.sourceRevision.productType
                    let deviceOSVersion = result.sourceRevision.version

                    let startDate = self.currentHeartLastSample?.startDate
                    let endDate = self.currentHeartLastSample?.endDate

                    self.aCollectionView.reloadData()
                }


            }

        }

I think the best method is to simply send the heart rate data to the phone app using Watch Communication. 我认为最好的方法是使用Watch Communication将心率数据发送到手机应用程序。

In Watch code: 在Watch代码中:

func send(heartRate: Int) {
    guard WCSession.default.isReachable else {
        print("Phone is not reachable")
        return
    }

    WCSession.default.sendMessage(["Heart Rate" : heartRate], replyHandler: nil) { error in
        print("Error sending message to phone: \(error.localizedDescription)")
    }
 }

and on phone you receive the data with: 并在电话上收到数据:

func session(_ session: WCSession, didReceiveMessage message: [String: Any]) {
    if let heartRate = message["Heart Rate"] {
        print("Received heart rate: \(heartRate)")
    } else {
        print("Did not receive heart rate =[")
    }
}

This should happen in pretty much real time. 这应该在很多时候实现。 Alternatively there is another less reliable solution (imo) which is to just perform the heart rate query once every 5 seconds or so, but if I understand correctly you've already tried that and it didn't work. 另外还有另一个不太可靠的解决方案(imo),即每5秒钟左右执行一次心率查询,但如果我理解正确,你已经尝试了它并且它不起作用。

Here is my own analysis regarding get nearby real-time Heart Rate. 以下是关于获得附近实时心率的自己的分析。

1. If you are accessing Health Kit data using iPhone app, In this scenario, Health Kit DB NOT frequently updated/refreshed. 1.如果您使用iPhone应用程序访问Health Kit数据,在此方案中,Health Kit DB不会经常更新/刷新。 So, your app not able to get real-time latest updated data through iPhone app. 因此,您的应用无法通过iPhone应用获取实时最新更新数据。

2. Using a watch app, you can access near real-time data through Health Kit DB. 2.使用监视应用程序,您可以通过Health Kit DB访问近实时数据。 Watch app is able to get the real-time latest updated Health Kit Data. Watch应用程序能够获取实时最新的Health Kit数据。

3. You need to transfer data from watch to iPhone app. 3.您需要将数据从手表传输到iPhone应用程序。 Here is a code for your reference. 这是一个供您参考的代码。 You can write code as per your requirement. 您可以根据自己的要求编写代码。 You just need to access Heart Rate through HKQuery 您只需要通过HKQuery访问心率

let defaultSession = WCSession.default

let healthStore = HKHealthStore()

var currentHeartRateSample : [HKSample]?

var currentHeartLastSample : HKSample?

var currentHeartRateBPM = Double()


//Get Heart Rate from Health Kit

func getCurrentHeartRateData(){

    let calendar = Calendar.current
    let components = calendar.dateComponents([.year, .month, .day], from: Date())
    let startDate : Date = calendar.date(from: components)!
    let endDate : Date = calendar.date(byAdding: Calendar.Component.day, value: 1, to: startDate as Date)!

    let sampleType : HKSampleType =  HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
    let predicate : NSPredicate =  HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: [])
    let anchor: HKQueryAnchor = HKQueryAnchor(fromValue: 0)

    let anchoredQuery = HKAnchoredObjectQuery(type: sampleType, predicate: predicate, anchor: anchor, limit: HKObjectQueryNoLimit) { (query, samples, deletedObjects, anchor, error ) in

        if samples != nil {

            self.collectCurrentHeartRateSample(currentSampleTyple: samples!, deleted: deletedObjects!)

        }

    }

    anchoredQuery.updateHandler = { (query, samples, deletedObjects, anchor, error) -> Void in
        self.collectCurrentHeartRateSample(currentSampleTyple: samples!, deleted: deletedObjects!)
    }

    self.healthStore.execute(anchoredQuery)

}


//Retrived necessary parameter from HK Sample
func collectCurrentHeartRateSample(currentSampleTyple : [HKSample]?, deleted : [HKDeletedObject]?){

        self.currentHeartRateSample = currentSampleTyple

        //Get Last Sample of Heart Rate
        self.currentHeartLastSample = self.currentHeartRateSample?.last

        if self.currentHeartLastSample != nil {

            let lastHeartRateSample = self.currentHeartLastSample as! HKQuantitySample

            self.currentHeartRateBPM = lastHeartRateSample.quantity.doubleValue(for: HKUnit(from: "count/min"))
            let heartRateStartDate = lastHeartRateSample.startDate
            let heartRateEndDate = lastHeartRateSample.endDate

            //Send Heart Rate Data Using Send Messge

            DispatchQueue.main.async {

                let message = [
                    "HeartRateBPM" : "\(self.currentHeartRateBPM)",
                    "HeartRateStartDate" : "\(heartRateStartDate)",
                    "HeartRateEndDate" : "\(heartRateEndDate)"
                ]

//Transfer data from watch to iPhone
                self.defaultSession.sendMessage(message, replyHandler:nil, errorHandler: { (error) in
                    print("Error in send message : \(error)")
                })

            }

        }


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM