Как получить данные о частоте сердечных сокращений в реальном времени с помощью Health Kit в iOS? - PullRequest
0 голосов
/ 14 декабря 2018

Я создал сеанс в Наблюдении и обновляю данные о частоте сердечных сокращений в Health Kit.Теперь я хочу отобразить текущий пульс на экране iPhone.Наблюдайте, как датчик обновляет данные о сердечном ритме в аптечке, НО приложение iPhone НЕ в состоянии получать данные в реальном времени из аптечки.Я проверил ниже ДВА сценария.Я также вспомнил этот метод / функцию, используя таймер, НО он не получает данные в реальном времени.

Примечание. При открытии приложения «Здоровье» и повторном открытии приложения оно автоматически обновляет данные.Если мое приложение постоянно на переднем плане, то ниже код не обновляет последние данные из аптечки

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.Пытался получить данные о частоте сердечных сокращений в реальном времени с помощью 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)

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

Анализ данных

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()
                }


            }

        }

Ответы [ 2 ]

0 голосов
/ 16 марта 2019

Вот мой собственный анализ, касающийся измерения пульса в реальном времени.

1. Если вы получаете доступ к данным Health Kit с помощью приложения iPhone, в этом случае DB Health Kit DB НЕ часто обновляется / обновляется.Таким образом, ваше приложение не может получать последние обновленные данные в режиме реального времени через приложение iPhone.

2. Используя приложение для часов, вы можете получить доступ к данным в режиме реального времени через базу данных Health Kit.Приложение Watch может в режиме реального времени получать последние обновленные данные Health Kit.

3. Вам необходимо перенести данные с часов в приложение для iPhone.Вот код для вашей справки.Вы можете написать код согласно вашему требованию.Вам просто нужно получить доступ к ЧСС через 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)")
                })

            }

        }


}
0 голосов
/ 18 декабря 2018

Я думаю, что лучший способ - просто отправить данные о частоте сердечных сокращений в приложение телефона с помощью Watch Communication.

В коде часов:

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)")
    }
 }

и по телефону вы получаете данные с:

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 =[")
    }
}

Это должно происходить в реальном времени.В качестве альтернативы есть еще одно менее надежное решение (imo), которое заключается в том, чтобы просто выполнять запрос сердечного ритма каждые 5 секунд или около того, но если я правильно понимаю, вы уже попробовали это, и оно не сработало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...