Download apps/ios/Sources/Motion/MotionService.swift from Darochin/openskynet: direct link, hf CLI and curl.
- Browser
- Download file 4.59 kB
-
https://huggingface.co/Darochin/openskynet/resolve/main/apps/ios/Sources/Motion/MotionService.swift
- Command line
-
hf download hf://Darochin/openskynet/apps/ios/Sources/Motion/MotionService.swift
-
curl -L -o MotionService.swift https://huggingface.co/Darochin/openskynet/resolve/main/apps/ios/Sources/Motion/MotionService.swift
4.59 kB
| import CoreMotion | |
| import Foundation | |
| import OpenClawKit | |
| final class MotionService: MotionServicing { | |
| func activities(params: OpenClawMotionActivityParams) async throws -> OpenClawMotionActivityPayload { | |
| guard CMMotionActivityManager.isActivityAvailable() else { | |
| throw NSError(domain: "Motion", code: 1, userInfo: [ | |
| NSLocalizedDescriptionKey: "MOTION_UNAVAILABLE: activity not supported on this device", | |
| ]) | |
| } | |
| let auth = CMMotionActivityManager.authorizationStatus() | |
| guard auth == .authorized else { | |
| throw NSError(domain: "Motion", code: 3, userInfo: [ | |
| NSLocalizedDescriptionKey: "MOTION_PERMISSION_REQUIRED: grant Motion & Fitness permission", | |
| ]) | |
| } | |
| let (start, end) = Self.resolveRange(startISO: params.startISO, endISO: params.endISO) | |
| let limit = max(1, min(params.limit ?? 200, 1000)) | |
| let manager = CMMotionActivityManager() | |
| let mapped: [OpenClawMotionActivityEntry] = try await withCheckedThrowingContinuation { cont in | |
| manager.queryActivityStarting(from: start, to: end, to: OperationQueue()) { activity, error in | |
| if let error { | |
| cont.resume(throwing: error) | |
| } else { | |
| let formatter = ISO8601DateFormatter() | |
| let sliced = Array((activity ?? []).suffix(limit)) | |
| let entries = sliced.map { entry in | |
| OpenClawMotionActivityEntry( | |
| startISO: formatter.string(from: entry.startDate), | |
| endISO: formatter.string(from: end), | |
| confidence: Self.confidenceString(entry.confidence), | |
| isWalking: entry.walking, | |
| isRunning: entry.running, | |
| isCycling: entry.cycling, | |
| isAutomotive: entry.automotive, | |
| isStationary: entry.stationary, | |
| isUnknown: entry.unknown) | |
| } | |
| cont.resume(returning: entries) | |
| } | |
| } | |
| } | |
| return OpenClawMotionActivityPayload(activities: mapped) | |
| } | |
| func pedometer(params: OpenClawPedometerParams) async throws -> OpenClawPedometerPayload { | |
| guard CMPedometer.isStepCountingAvailable() else { | |
| throw NSError(domain: "Motion", code: 2, userInfo: [ | |
| NSLocalizedDescriptionKey: "PEDOMETER_UNAVAILABLE: step counting not supported", | |
| ]) | |
| } | |
| let auth = CMPedometer.authorizationStatus() | |
| guard auth == .authorized else { | |
| throw NSError(domain: "Motion", code: 4, userInfo: [ | |
| NSLocalizedDescriptionKey: "MOTION_PERMISSION_REQUIRED: grant Motion & Fitness permission", | |
| ]) | |
| } | |
| let (start, end) = Self.resolveRange(startISO: params.startISO, endISO: params.endISO) | |
| let pedometer = CMPedometer() | |
| let payload: OpenClawPedometerPayload = try await withCheckedThrowingContinuation { cont in | |
| pedometer.queryPedometerData(from: start, to: end) { data, error in | |
| if let error { | |
| cont.resume(throwing: error) | |
| } else { | |
| let formatter = ISO8601DateFormatter() | |
| let payload = OpenClawPedometerPayload( | |
| startISO: formatter.string(from: start), | |
| endISO: formatter.string(from: end), | |
| steps: data?.numberOfSteps.intValue, | |
| distanceMeters: data?.distance?.doubleValue, | |
| floorsAscended: data?.floorsAscended?.intValue, | |
| floorsDescended: data?.floorsDescended?.intValue) | |
| cont.resume(returning: payload) | |
| } | |
| } | |
| } | |
| return payload | |
| } | |
| private static func resolveRange(startISO: String?, endISO: String?) -> (Date, Date) { | |
| let formatter = ISO8601DateFormatter() | |
| let start = startISO.flatMap { formatter.date(from: $0) } ?? Calendar.current.startOfDay(for: Date()) | |
| let end = endISO.flatMap { formatter.date(from: $0) } ?? Date() | |
| return (start, end) | |
| } | |
| private static func confidenceString(_ confidence: CMMotionActivityConfidence) -> String { | |
| switch confidence { | |
| case .low: "low" | |
| case .medium: "medium" | |
| case .high: "high" | |
| @unknown default: "unknown" | |
| } | |
| } | |
| } | |