I'm making a Watch app that will record user acceleration. I've used CMSensorRecorder
from the CoreMotion
Framework to do this.
The flow of the program right now is that the user presses a button on the watch, which triggers acceleration to be recorded for 30 seconds. After this, there is a 6-minute delay (referring to answer here :watchOS2 - CMSensorRecorder, a delay is needed to read the data), and the acceleration and timestamp data is printed to the console.
Right now I'm getting a "response invalid" and "Error occurred" when running the app. I've added a motion usage description to the info.plist
file.
I'm fairly new to Swift and app development, and I fear something's wrong with the way I'm trying to access the data. I've attached the console logs and code below.
Can anybody provide some insight into the messages and how to resolve this? I've searched around but haven't found any cases of this issue before. Cheers.
func recordAcceleration(){
if CMSensorRecorder.isAccelerometerRecordingAvailable(){
print("recorder started")
recorder.recordAccelerometer(forDuration: 30) //forDuration controls how many seconds data is recorded for.
print("recording done")
}
}
func getData(){
if let list = recorder.accelerometerData(from: Date(timeIntervalSinceNow: -400), to: Date()){
print("listing data")
for data in list{
if let accData = data as? CMRecordedAccelerometerData{
let accX = accData.acceleration.x
let timestamp = accData.startDate
//Do something here.
print(accX)
print(timestamp)
}
}
}
}
//Send data to iphone after time period.
func sendData(dataBlock:CMSensorDataList){
WCSession.default.transferUserInfo(["Data" : dataBlock])
}
//UI Elements
@IBAction func recordButtonPressed() {
print("button pressed")
recordAcceleration()
//A delay is needed to read the data properly.
print("delaying 6 mins")
perform(#selector(callback), with: nil, afterDelay: 6*60)
}
@objc func callback(){
getData()
}
extension CMSensorDataList: Sequence {
public func makeIterator() -> NSFastEnumerationIterator {
return NSFastEnumerationIterator(self)
}
Console output:
button pressed
recorder started
2019-03-12 12:12:12.568962+1100 app_name WatchKit Extension[233:5614] [Motion] Warning - invoking recordDataType:forDuration: on main may lead to deadlock.
2019-03-12 12:12:13.102712+1100 app_name WatchKit Extension[233:5614] [SensorRecorder] Response invalid.
recording done
delaying 6 mins
2019-03-12 12:18:13.115955+1100 app_name WatchKit Extension[233:5614] [Motion] Warning - invoking sensorDataFromDate:toDate:forType: on main may lead to deadlock.
2019-03-12 12:18:13.162476+1100 app_name WatchKit Extension[233:5753] [SensorRecorder] Error occurred while trying to retrieve accelerometer records!
I ran your code and did not get the "Response invalid" or "Error occurred". I did get the main thread warnings. So I changed to a background thread and it works fine.
Also, I don't think you need to wait six minutes. I changed it to one minute.
I hope this helps.
let recorder = CMSensorRecorder()
@IBAction func recordAcceleration() {
if CMSensorRecorder.isAccelerometerRecordingAvailable() {
print("recorder started")
DispatchQueue.global(qos: .background).async {
self.recorder.recordAccelerometer(forDuration: 30)
}
perform(#selector(callback), with: nil, afterDelay: 1 * 60)
}
}
@objc func callback(){
DispatchQueue.global(qos: .background).async { self.getData() }
}
func getData(){
print("getData started")
if let list = recorder.accelerometerData(from: Date(timeIntervalSinceNow: -60), to: Date()) {
print("listing data")
for data in list{
if let accData = data as? CMRecordedAccelerometerData{
let accX = accData.acceleration.x
let timestamp = accData.startDate
//Do something here.
print(accX)
print(timestamp)
}
}
}
}