Hi there.
We are trying to implement SensorKit into our App to explore the data quality of accelerometer data recorded even when the App is terminated. So far we managed everything to work, even the fetch, except the SRSensorReaderDelegate never seems to reach
func sensorReader(_ reader: SRSensorReader, fetching fetchRequest: SRFetchRequest, didFetchResult result: SRFetchResult) -> Bool { ... }
Any clue as to what we need to adjust in our code to get the FetchResult?
import Foundation
import SensorKit
import CoreMotion
import os.log
class SensorKitDataManager: NSObject, SRSensorReaderDelegate {
static let shared = SensorKitDataManager()
// Sensor Readers
let accelerometerReader = SRSensorReader(sensor: .accelerometer)
let rotationRateReader = SRSensorReader(sensor: .rotationRate)
let deviceUsageReader = SRSensorReader(sensor: .deviceUsageReport)
let phoneUsageReader = SRSensorReader(sensor: .phoneUsageReport)
let wristUsageReader = SRSensorReader(sensor: .onWristState)
var startTime: CFTimeInterval = CFTimeInterval(Date().timeIntervalSince1970)
var endTime: CFTimeInterval = CFTimeInterval(Date().timeIntervalSince1970)
override init() {
super.init()
configureSensorReaders()
}
// Configure sensor readers and set delegate
private func configureSensorReaders() {
if SRSensorReader(sensor: .accelerometer).authorizationStatus == .authorized {
accelerometerReader.delegate = self
}
...
}
func sensorReaderWillStartRecording(_ reader: SRSensorReader) {
print("\(reader.description) Delegate starts recording")
}
func sensorReader(_ reader: SRSensorReader, startRecordingFailedWithError error: Error)
{
print("\(reader.description) Delegate failed recording")
}
func sensorReader(_ reader: SRSensorReader, didChange authorizationStatus: SRAuthorizationStatus) {
if reader.sensor == .accelerometer {
if authorizationStatus == SRAuthorizationStatus.authorized {
accelerometerReader.startRecording()
}
else if authorizationStatus == SRAuthorizationStatus.denied {
accelerometerReader.stopRecording()
}
}
...
}
// Request SensorKit Authorization
func requestAuthorization() {
}
if UserDefaults.standard.bool(forKey: "JTrack_accelerometerEnabled") && accelerometerReader.authorizationStatus == .notDetermined {
SRSensorReader.requestAuthorization(sensors: [.accelerometer]) { error in
if let error = error {
os_log("Authorization denied: %@", log: OSLog.default, type: .error, error.localizedDescription)
} else {
os_log("Authorization granted for accelerometer sensor", log: OSLog.default, type: .info)
}
}
}
...
self.startRecordingIfAuthorized()
}
// Start recording for each authorized sensor
private func startRecordingIfAuthorized() {
if accelerometerReader.authorizationStatus == .authorized {
accelerometerReader.startRecording()
}
...
}
func fetchAllDataSinceJoined(from startTime: CFTimeInterval, to endTime: CFTimeInterval) {
self.startTime = startTime
self.endTime = endTime
if accelerometerReader.authorizationStatus == .authorized {
accelerometerReader.fetchDevices()
}
....
}
func stopAllRecordings() {
if accelerometerReader.authorizationStatus == .authorized {
accelerometerReader.stopRecording()
}
...
}
func sensorReader(_ reader: SRSensorReader, didFetch devices: [SRDevice]) {
let now = CFTimeInterval(Date().timeIntervalSince1970)
// Ensure the data is at least 24 hours old
let holdingPeriod: CFTimeInterval = 24 * 60 * 60 // 24 hours in seconds
let earliestFetchTime = now - holdingPeriod
// Adjust the start time if it's within the holding period
let adjustedStartTime = min(startTime, earliestFetchTime)
// If adjustedStartTime is after endTime, no data is available for fetching
guard adjustedStartTime < endTime else {
print("No data available to fetch as it falls within the 24-hour holding period.")
return
}
let fetchRequest = SRFetchRequest()
fetchRequest.from = SRAbsoluteTime(adjustedStartTime)
fetchRequest.to = SRAbsoluteTime(endTime)
// Log information about the devices that contributed data
for device in devices {
print("Device model: \(device.model), OS version: \(device.systemVersion), Identifier: \(device.description)")
if device.model == "iPhone" {
fetchRequest.device = device
}
}
if accelerometerReader.authorizationStatus == .authorized {
accelerometerReader.fetch(fetchRequest)
}
...
}
// SensorKit Delegate Methods
func sensorReader(_ reader: SRSensorReader, didCompleteFetch fetchRequest: SRFetchRequest) {
os_log("Fetch completed for sensor: %@", log: OSLog.default, type: .info, reader.sensor.rawValue)
}
func sensorReader(_ reader: SRSensorReader, fetching fetchRequest: SRFetchRequest, didFetchResult result: SRFetchResult<AnyObject>) -> Bool {
if reader.sensor == .accelerometer {
....
}
....
}
func sensorReaderDidStopRecording(_ reader: SRSensorReader) {
print("\(reader.description) Delegate stops recording")
}
func sensorReader(_ reader: SRSensorReader, stopRecordingFailedWithError error: Error) {
print("\(reader.description) Delegate failed stopping")
}