SensorKit

RSS for tag

Retrieve data and derived metrics from iPhone sensors or from a paired Apple Watch.

Posts under SensorKit tag

18 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Sensorkit Fetch does not deliver Accelerometer data
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") }
0
0
32
8h
Walking speed
I´m working within the health felid with a few apps. Accordingly to science one of the most important parts to keep healthy is every day walking. But it is not to walk slow. You need to come to a little speed (not running or even jogging). But to rais your puls. This is when you get the "real health effect". In general it is around 6km/h. It would be great if apple could make this info available for us developers. I think lots of developers will be happa and use this to make better apps and get more people in a healtheyer life. Looking forward to get some feedback on this. Thank you! Cheers Peter
1
0
67
6d
SensorKit Visit Data Inconsistencies Across Devices
Hello, I am currently developing an application using SensorKit to retrieve visit data. While the data retrieval works smoothly on one iPhone (iPhone 14, iOS 18.0.1), it fails on other devices, including: iPhone 15 Pro Max with iOS 18.1 Beta Another iPhone 14 with iOS 18.0 I’ve verified that the entitlements are configured properly, and the app has the necessary SensorKit visit permissions across all devices. Despite these steps, only one of the phones is able to retrieve the visit data correctly. Is there any minimum hardware requirement or compatibility issue with certain models or configurations that I should be aware of for using SensorKit visits? Any guidance or insight would be greatly appreciated! Thank you.
0
0
90
2w
Problems with SensorKit data calls
The Deligate 'didFetchResult' method of fetching data past 24 hours from SensorKit is not being called. It is confirmed that you have already granted full access to the SensorKit and that data on the Ambient value in the device's personal information -> research sensor & usage data are recorded. It is possible to export to an lz4 file. I want to have the data after 24 hours called to the app, but other Deligate methods are called, but only Deligate that gets the illumination value is not called. Is it understood that only data past 24 hours can be imported after startRecoding() is called? If so, in order to receive data past 24 hours, do I have to continue to receive the illumination data value in the background for more than 24 hours to receive the Ambient value afterwards? import Foundation import SensorKit import UIKit final class SensorKitManager: NSObject, ObservableObject, SRSensorReaderDelegate { static let shared = SensorKitManager() private let ambientReader = SRSensorReader(sensor: .ambientLightSensor) var availableDevices: [SRDevice] = [] @Published var ambientLightData: [AmbientLightDataPoint] = [] var isFetching = false var isRecordingAmbientLight = false private override init() { super.init() setupReaders() checkAndRequestAuthorization() } private func setupReaders() { ambientReader.delegate = self } // MARK: - Permission Request func requestAuthorization() { SRSensorReader.requestAuthorization(sensors: [.ambientLightSensor]) { [weak self] error in DispatchQueue.main.async { guard let self = self else { print("Permission request aborted") return } if let error = error { print("Permission request failed: \(error.localizedDescription)") } else { print("Permission request succeeded") self.startRecordingAmbientLightData() } } } } func checkAndRequestAuthorization() { let status = ambientReader.authorizationStatus switch status { case .authorized: print("Ambient light sensor access granted") startRecordingAmbientLightData() case .notDetermined: print("Ambient light sensor access undetermined, requesting permission") requestAuthorization() case .denied: print("Ambient light sensor access denied or restricted") @unknown default: print("Unknown authorization status") } } // MARK: - Ambient Light Data Logic func startRecordingAmbientLightData() { guard !isRecordingAmbientLight else { print("Already recording ambient light data.") return } print("Starting ambient light data recording") isRecordingAmbientLight = true ambientReader.startRecording() fetchAmbientLightData() fetchAmbientDeviceData() } func fetchAmbientLightData() { print("Fetching ambient light data") let request = SRFetchRequest() let now = Date() let fromTime = now.addingTimeInterval(-72 * 60 * 60) let toTime = now.addingTimeInterval(-25 * 60 * 60) request.from = SRAbsoluteTime(fromTime.timeIntervalSinceReferenceDate) request.to = SRAbsoluteTime(toTime.timeIntervalSinceReferenceDate) print("Fetch request: \(fromTime) ~ \(toTime)") ambientReader.fetch(request) } private func displayAmbientLightData(sample: SRAmbientLightSample) { print("Ambient light: \(sample.lux.value) lux") print("Current ambientLightData content:") for data in ambientLightData { print("Timestamp: \(data.timestamp), Lux: \(data.lux)") } } // MARK: - Device Data Logic private func fetchAmbientDeviceData() { print("Fetching device information") let request = SRFetchRequest() let now = Date() let fromDate = now.addingTimeInterval(-72 * 60 * 60) let toDate = now.addingTimeInterval(-24 * 60 * 60) request.from = SRAbsoluteTime(fromDate.timeIntervalSinceReferenceDate) request.to = SRAbsoluteTime(toDate.timeIntervalSinceReferenceDate) if availableDevices.isEmpty { print("No devices available") ambientReader.fetchDevices() } else { for device in availableDevices { print("Starting data fetch (Device: \(device))") request.device = device ambientReader.fetch(request) print("Fetch request sent (Device: \(device))") } } } // MARK: - SRSensorReaderDelegate Methods func sensorReader(_ reader: SRSensorReader, didFetch devices: [SRDevice]) { availableDevices = devices for device in devices { print("Fetched device: \(device)") } if !devices.isEmpty { fetchAmbientDeviceData() } } func sensorReader(_ reader: SRSensorReader, fetching fetchRequest: SRFetchRequest, didFetchResult result: SRFetchResult<AnyObject>) -> Bool { print("sensorReader(_:fetching:didFetchResult:) method called") if let ambientSample = result.sample as? SRAmbientLightSample { let luxValue = ambientSample.lux.value let timestamp = Date(timeIntervalSinceReferenceDate: result.timestamp.rawValue) // Check for duplicate data and add it if !ambientLightData.contains(where: { $0.timestamp == timestamp }) { let dataPoint = AmbientLightDataPoint(timestamp: timestamp, lux: Float(luxValue)) ambientLightData.append(dataPoint) print("Added ambient light data: \(luxValue) lux, Timestamp: \(timestamp)") } else { print("Duplicate data, not adding: Timestamp: \(timestamp)") } // Output data self.displayAmbientLightData(sample: ambientSample) } return true } func sensorReader(_ reader: SRSensorReader, didCompleteFetch fetchRequest: SRFetchRequest) { print("Data fetch complete") if ambientLightData.isEmpty { print("No ambient light data within 24 hours.") } else { print("ambientLightData updated") for dataPoint in ambientLightData { print("Added ambient light data: \(dataPoint.lux) lux, Timestamp: \(dataPoint.timestamp)") } } } }
0
0
181
Sep ’24
Sensorkit - Troubleshooting SRErrorDataInaccessible in Background Fetch with SensorKit
Hello, I am currently developing an iOS application using SensorKit. I encountered an issue when attempting to fetch SensorKit data in the background using background tasks (appRefresh, processing). The following error occurs: In the delegate function func sensorReader(_ reader: SRSensorReader, fetching fetchRequest: SRFetchRequest, failedWithError error: any Error) {}, I receive the error: SRErrorDataInaccessible. In code specific manner: start and handle background fetch (appRefresh) func handleAppRefreshTask(task: BGAppRefreshTask) { logger.logWithServer(level: .default, message: "background fetch start", category: String(describing: BackgroundTaskManager.self)) scheduleBackgroundFetch() let queue = OperationQueue() queue.maxConcurrentOperationCount = 1 let fetchOperation = FetchOperation() queue.addOperation(fetchOperation) task.expirationHandler = { self.logger.logWithServer(level: .error, message: "background fetch expirated", category: String(describing: BackgroundTaskManager.self)) queue.cancelAllOperations() } fetchOperation.completionBlock = { task.setTaskCompleted(success: !fetchOperation.isCancelled) } } Background fetch operation class class FetchOperation: Operation { override func main() { guard !isCancelled else { return } Task { // this function will execute fetch request for all user allowed sensorReader, 'func fetch(_ request: SRFetchRequest)' await SensorkitManager.shared.startFetchAndUpload() } } } I have the following questions: Is it possible to fetch SensorKit data in the background? If it is possible, why does the above error occur? If it is possible, could you provide the solution code and the correct workflow to avoid this error? Thank you.
2
0
462
Aug ’24
Battery Consumption
We are developed app based on driver behaviour using location and sensor data. It's working in both background and foreground using region monitoring. Its consume more battery comparing other apps like. Its reduce 5% for every 5 to 10 mins of duration. We are using for our app functionality Location (Always) - every 1sec Sensor - Accelerometer - every 20data for 1sec Background - Region monitoring Time Action - 1sec for 20time Any possible way to reduce battery consuming? If any please suggest your points. Thanks in advance for your comments.
0
0
490
May ’24
collision detecting is not working in my Watch app
Wanted to reach out for some assistance with troublshooting my watch app not detecting collision, I have set up a few breakpoints and determined that it is not running the game over struct even if it had detected the collision, I have also tried to generate a log file when a collision is detected and that does not work either. I have considered that the objects may not be on the same layer so they are now in the same zstack.
1
0
647
Apr ’24
How to invoke an Apple Iphone to take screen shot
I am working on an application design where I would like to have the Iphone running an app such as Apple Map, and while I might be driving in the car I would like to have my apple Watch invoke a screen shot of the current view of I map showing my location without having to use the iphone. So the Iphone would be active and in a car holder displaying my location on the map. Once I made my route point, such as a waypoint. I would like to press a button on my watch app to do a screen print. Second though is, could I press a button on my Apple Watch app to fire an request to my own IOS Application using WatchConnectivity to capture my Location to a data file. Third thought is could a press a button on my Apple Watch app to interact with an active app, which is an app like a reminder app and create a new Reminder Note in the active app in focus on my Iphone, but is not a component of my IPhone App. Thanks for any insight how I could make a Apple Watch app send Button Presses reliably to my Iphone Application active, so that I. could avoid having to touch my iPhone? Thanks in advance for any guidance.
0
0
587
Mar ’24
Iphone 13 Pro Max unknown Display
Hello, I'm currently locked out of an old iphone 13 pro max purchased at Apple Store, i've forgotten the icloud account on the device so i can not locate the serial or imei number of the device and i've lost my proof of purchase, the store employee can not access the proof of purchase, the iphone 13 Pro Max is in great condition's. as i turn on the phone it's an Unknown Display. how could i bypass the unknown display or recycle the phone also the phone is running a ios almost 2 year's ago i've payed full price for the device.
1
0
687
Jan ’24
Getting accelerometer data in the app's inactive state in the WatchOS
Hi folks! We are developing a WatchOS companion app which records Accelerometer data. We call CMSensorRecorder.recordAccelerometer(forDuration: _) and retrieve the data by calling CMSensorRecorder.accelerometerData(from: _, to: _). So far so good. But the issue arises when we have a data for say 2 hours. We get the accelerometer data in the SwiftUI Task or using GCD's background queue. The data we get is in the loop, enumerating the CMSensorDataList. The loop goes on when the app is active. But as soon as the Watch app goes to inactive state, say applicationWillResignActive is called, the loop is suspended. I know this is the default behaviour of the OS. But this makes our data parsing so slow that sometimes it takes an hour or so to get 2 hours data. This is making our app not user friendly. Is there a way we can keep our app alive as soon as the data is being processed? Or is there another way for faster data processing that we can send the raw data to phone using WCSession so that the data gets there as soon as recording stops? Thanks
0
0
691
Dec ’23
Get device height with centimeter precision
Is it possible to get the height (Z location) of an iOS device based on sensor data? I've continuously added the accelerometer data up to infer the location but it results in a cascading error, and the inferred location of the phone "drifts" when the phone is placed still. I want to build an app where users measure the height of something by first zeroing the phone on the floor and then raising the phone to the height of the object, like placing it on the table.
3
0
1.1k
Jun ’24