react-native-move-sdk 2.12.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle.kts +42 -0
- package/android/gradle.properties +16 -6
- package/android/settings.gradle.kts +35 -0
- package/android/src/{main/java/in/dolph/move/sdk → legacy}/MoveSdkModule.kt +30 -195
- package/android/src/main/AndroidManifest.xml +1 -11
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/DeviceScanner.kt +19 -21
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/Mapper.kt +3 -2
- package/android/src/main/java/com/movesdk/MoveExtensions.kt +188 -0
- package/android/src/main/java/{in/dolph/move/sdk/MoveSdkRepository.kt → com/movesdk/MoveSdkConfigRepository.kt} +3 -1
- package/android/src/main/java/com/movesdk/MoveSdkPackage.kt +32 -0
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/NativeMoveSdkWrapper.kt +201 -61
- package/android/src/main/java/com/movesdk/extentions/ConnectionExt.kt +52 -0
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/extentions/PermissionUtils.kt +1 -1
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/extentions/SharedPreferencesExt.kt +1 -1
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/metadata/MetadataStorage.kt +1 -1
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/metadata/MetadataStorageImpl.kt +2 -2
- package/android/src/main/java/com/movesdk/shared/Constants.kt +39 -0
- package/android/src/turbo/MoveSdkModule.kt +422 -0
- package/ios/MoveSdk.h +13 -0
- package/ios/MoveSdk.mm +717 -0
- package/ios/MoveSdk.swift +1022 -0
- package/ios/{NativeModule/MoveSdkDeviceScanner.swift → MoveSdkDeviceScanner.swift} +1 -1
- package/lib/commonjs/NativeMoveSdk.js +21 -0
- package/lib/commonjs/NativeMoveSdk.js.map +1 -0
- package/lib/commonjs/components/LazyMoveSdk.js +22 -41
- package/lib/commonjs/components/LazyMoveSdk.js.map +1 -1
- package/lib/commonjs/index.js +331 -25
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/package.json +1 -0
- package/lib/module/NativeMoveSdk.js +17 -0
- package/lib/module/NativeMoveSdk.js.map +1 -0
- package/lib/module/components/LazyMoveSdk.js +15 -20
- package/lib/module/components/LazyMoveSdk.js.map +1 -1
- package/lib/module/index.js +337 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/package.json +1 -0
- package/lib/typescript/commonjs/example/src/App.d.ts +2 -0
- package/lib/typescript/commonjs/example/src/App.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/NativeMoveSdk.d.ts +138 -0
- package/lib/typescript/commonjs/src/NativeMoveSdk.d.ts.map +1 -0
- package/lib/typescript/{components → commonjs/src/components}/LazyMoveSdk.d.ts +2 -1
- package/lib/typescript/commonjs/src/components/LazyMoveSdk.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +84 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/module/example/src/App.d.ts +2 -0
- package/lib/typescript/module/example/src/App.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/NativeMoveSdk.d.ts +138 -0
- package/lib/typescript/module/src/NativeMoveSdk.d.ts.map +1 -0
- package/lib/typescript/module/src/components/LazyMoveSdk.d.ts +8 -0
- package/lib/typescript/module/src/components/LazyMoveSdk.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +84 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/package.json +197 -138
- package/react-native-move-sdk.podspec +30 -9
- package/src/NativeMoveSdk.ts +191 -0
- package/src/components/LazyMoveSdk.tsx +2 -2
- package/src/{MoveSdk.ts → index.tsx} +131 -199
- package/android/.project +0 -17
- package/android/build.gradle +0 -153
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +0 -8
- package/android/gradlew +0 -183
- package/android/gradlew.bat +0 -100
- package/android/src/main/java/in/dolph/move/sdk/MoveExtensions.kt +0 -72
- package/android/src/main/java/in/dolph/move/sdk/MoveSdkPackage.kt +0 -19
- package/android/src/main/java/in/dolph/move/sdk/WrapperBtConnectionsReceiver.kt +0 -96
- package/android/src/main/res/drawable-anydpi-v24/ic_notification.xml +0 -13
- package/android/src/main/res/drawable-hdpi/ic_notification.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_notification.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_notification.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_notification.png +0 -0
- package/android/src/main/res/values/strings.xml +0 -9
- package/android/src/main/strings.xml +0 -0
- package/android/src/test/java/io/dolphin/move/MoveWrapperTest.kt +0 -190
- package/ios/MoveSdk-Bridging-Header.h +0 -3
- package/ios/MoveSdk.xcodeproj/project.pbxproj +0 -287
- package/ios/MoveSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -4
- package/ios/MoveSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/ios/NativeModule/MoveSdk.h +0 -144
- package/ios/NativeModule/MoveSdk.swift +0 -1359
- package/lib/commonjs/MoveSdk.js +0 -443
- package/lib/commonjs/MoveSdk.js.map +0 -1
- package/lib/module/MoveSdk.js +0 -432
- package/lib/module/MoveSdk.js.map +0 -1
- package/lib/typescript/MoveSdk.d.ts +0 -158
- package/lib/typescript/index.d.ts +0 -3
- package/src/index.ts +0 -3
|
@@ -0,0 +1,1022 @@
|
|
|
1
|
+
import CoreMotion
|
|
2
|
+
import DolphinMoveSDK
|
|
3
|
+
import HealthKit
|
|
4
|
+
|
|
5
|
+
/// Move SDK instance singleton delegate.
|
|
6
|
+
@objc public protocol MoveSDKDelegate {
|
|
7
|
+
/// Send event to observer.
|
|
8
|
+
/// - Parameters:
|
|
9
|
+
/// - event: Event key.
|
|
10
|
+
/// - data: Event object.
|
|
11
|
+
@objc func send(event: String, data: Any)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/// Wrapper `MoveOptions` key.
|
|
15
|
+
@objc public enum MoveSdkOptionKey: Int {
|
|
16
|
+
public typealias RawValue = Int
|
|
17
|
+
case startDelay
|
|
18
|
+
case interval
|
|
19
|
+
case duration
|
|
20
|
+
case stopScanOnFirstDiscovered
|
|
21
|
+
case motionPermissionMandatory
|
|
22
|
+
case backgroundLocationPermissionMandatory
|
|
23
|
+
case useBackendConfig
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// Wrapper `MoveOptions` key value pair.
|
|
27
|
+
@objc public class MoveSdkOption: NSObject {
|
|
28
|
+
@objc let key: MoveSdkOptionKey
|
|
29
|
+
@objc let value: NSNumber
|
|
30
|
+
|
|
31
|
+
@objc public init(key: MoveSdkOptionKey, value: NSNumber) {
|
|
32
|
+
self.key = key
|
|
33
|
+
self.value = value
|
|
34
|
+
super.init()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
override public init() {
|
|
38
|
+
fatalError()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// Wrapper error object.
|
|
43
|
+
@objc public class MoveSdkError: NSObject {
|
|
44
|
+
@objc public let title: String
|
|
45
|
+
@objc public let text: String
|
|
46
|
+
|
|
47
|
+
init(_ title: String, text: String? = nil) {
|
|
48
|
+
self.title = title
|
|
49
|
+
self.text = text ?? title
|
|
50
|
+
super.init()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// Address resolution failed.
|
|
54
|
+
static var resolveFailed = MoveSdkError("RESOLVE_FAILED")
|
|
55
|
+
/// Service unavailable.
|
|
56
|
+
static var serviceUnavailable = MoveSdkError("SERVICE_UNAVAILABLE")
|
|
57
|
+
/// Thershold reached.
|
|
58
|
+
static var thresholdReached = MoveSdkError("THRESHOLD_REACHED")
|
|
59
|
+
/// Geolookup error.
|
|
60
|
+
static var geocodeError = MoveSdkError("GEOCODE_ERROR")
|
|
61
|
+
/// SDK Authentication invalid.
|
|
62
|
+
static var authInvalid = MoveSdkError("AUTH_INVALID")
|
|
63
|
+
/// Initialization error.
|
|
64
|
+
static var initializationError = MoveSdkError("INITIALIZATION_ERROR")
|
|
65
|
+
/// Location error.
|
|
66
|
+
static var locationError = MoveSdkError("LOCATION_ERROR")
|
|
67
|
+
/// Network error.
|
|
68
|
+
static var networkError = MoveSdkError("NETWORK_ERROR")
|
|
69
|
+
/// Assistance call failed.
|
|
70
|
+
static var assistanceCallError = MoveSdkError("ASSISTANCE_CALL_ERROR")
|
|
71
|
+
/// Configuration error.
|
|
72
|
+
static var configurationError = MoveSdkError("CONFIGURATION_ERROR")
|
|
73
|
+
/// SDK uninitialized.
|
|
74
|
+
static var uninitialized = MoveSdkError("UNINITIALIZED")
|
|
75
|
+
|
|
76
|
+
/// Other error.
|
|
77
|
+
static func otherError(title: String, text: String) -> MoveSdkError {
|
|
78
|
+
MoveSdkError(title, text: text)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// SDK setup error.
|
|
82
|
+
static func setupError(text: String) -> MoveSdkError {
|
|
83
|
+
MoveSdkError("SETUP_ERROR", text: text)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// Singleton Move SDK instance wrapper.
|
|
88
|
+
@objc public class MoveSDKInstance: NSObject {
|
|
89
|
+
public typealias ErrorListItem = [String: Any]
|
|
90
|
+
|
|
91
|
+
/// Sent event identifiers to React Native.
|
|
92
|
+
internal enum Event: String, CaseIterable {
|
|
93
|
+
/// App event.
|
|
94
|
+
case appEvent = "MOVE_SDK_APP_EVENT"
|
|
95
|
+
/// SDK state change event.
|
|
96
|
+
case sdkState = "MOVE_SDK_STATE"
|
|
97
|
+
/// SDK trip state change event.
|
|
98
|
+
case tripState = "MOVE_SDK_TRIP_STATE"
|
|
99
|
+
/// SDK auth state change event.
|
|
100
|
+
case authState = "MOVE_SDK_AUTH_STATE"
|
|
101
|
+
/// SDK warning listener event.
|
|
102
|
+
case warning = "MOVE_SDK_WARNINGS"
|
|
103
|
+
/// SDK failure listener event.
|
|
104
|
+
case failure = "MOVE_SDK_ERRORS"
|
|
105
|
+
/// SDK detected devices event.
|
|
106
|
+
case devices = "MOVE_SDK_DEVICES"
|
|
107
|
+
/// Device scanning event.
|
|
108
|
+
case scanResult = "MOVE_SDK_SCAN_RESULT"
|
|
109
|
+
/// Device state event.
|
|
110
|
+
case deviceState = "MOVE_SDK_DEVICE_STATE"
|
|
111
|
+
/// SDK configuration update event.
|
|
112
|
+
case configUpdate = "MOVE_SDK_CONFIG_UPDATE"
|
|
113
|
+
/// SDK trip start event.
|
|
114
|
+
case tripStart = "MOVE_SDK_TRIP_START"
|
|
115
|
+
/// Log event.
|
|
116
|
+
case logEvent = "MOVE_SDK_LOG"
|
|
117
|
+
/// SDK health listener event.
|
|
118
|
+
case health = "MOVE_SDK_HEALTH"
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// Move SDK service identifiers.
|
|
122
|
+
private enum ServiceName: String {
|
|
123
|
+
/// Driving detection service.
|
|
124
|
+
case driving = "DRIVING"
|
|
125
|
+
/// Driving behavior subservice.
|
|
126
|
+
case drivingBehavior = "DRIVING_BEHAVIOUR"
|
|
127
|
+
/// Distraction free driving subservice.
|
|
128
|
+
case distractionFreeDriving = "DISTRACTION_FREE_DRIVING"
|
|
129
|
+
/// Device discovery subservice.
|
|
130
|
+
case deviceDiscovery = "DEVICE_DISCOVERY"
|
|
131
|
+
/// Walking detection service.
|
|
132
|
+
case walking = "WALKING"
|
|
133
|
+
/// Walking location subservice.
|
|
134
|
+
case walkingLocation = "WALKING_LOCATION"
|
|
135
|
+
/// Cycling detection service.
|
|
136
|
+
case cycling = "CYCLING"
|
|
137
|
+
/// Public transport service.
|
|
138
|
+
case publicTransport = "PUBLIC_TRANSPORT"
|
|
139
|
+
/// Places service.
|
|
140
|
+
case places = "PLACES"
|
|
141
|
+
/// Assistance call service.
|
|
142
|
+
case assistanceCall = "ASSISTANCE_CALL"
|
|
143
|
+
/// Points of interest service.
|
|
144
|
+
case pointsOfInterest = "POINTS_OF_INTEREST"
|
|
145
|
+
/// Automatic impact detection.
|
|
146
|
+
case automaticImpactDetection = "AUTOMATIC_IMPACT_DETECTION"
|
|
147
|
+
/// Health steps service.
|
|
148
|
+
case health = "HEALTH"
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/// User defaults kets.
|
|
152
|
+
private enum DefaultsKey: String {
|
|
153
|
+
/// Persisted auth object.
|
|
154
|
+
case auth = "MOVE.WRAPPER.AUTH"
|
|
155
|
+
/// Persisted config object.
|
|
156
|
+
case config = "MOVE.WRAPPER.CONFIG"
|
|
157
|
+
/// Persisted trip metadata.
|
|
158
|
+
case metaData = "MOVE.WRAPPER.TRIP.METADATA"
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/// Shared wrapper instance.
|
|
162
|
+
@objc public static let shared = MoveSDKInstance()
|
|
163
|
+
|
|
164
|
+
/// Device Scanner.
|
|
165
|
+
private lazy var scanner = MoveSdkDeviceScanner()
|
|
166
|
+
|
|
167
|
+
/// Motion mananger for motion permission.
|
|
168
|
+
private lazy var motionManager = CMMotionActivityManager()
|
|
169
|
+
|
|
170
|
+
/// Bluetooth manager for permission.
|
|
171
|
+
private lazy var bluetoothManager = MoveSdkBluetoothManager()
|
|
172
|
+
|
|
173
|
+
/// Move SDK Singleton.
|
|
174
|
+
private let sdk: MoveSDK
|
|
175
|
+
|
|
176
|
+
/// Pending events triggered before event observer registered.
|
|
177
|
+
private var pendingEvents: [Event: Any]
|
|
178
|
+
|
|
179
|
+
/// Healthstore to get permissions from.
|
|
180
|
+
lazy var healthStore = HKHealthStore()
|
|
181
|
+
|
|
182
|
+
/// Persisted trip metadata.
|
|
183
|
+
private var tripMetaData: [String: String] {
|
|
184
|
+
didSet {
|
|
185
|
+
MoveSDKInstance.encode(tripMetaData, forKey: .metaData)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/// Objc delegate.
|
|
190
|
+
@objc public weak var delegate: MoveSDKDelegate? {
|
|
191
|
+
didSet {
|
|
192
|
+
for (key, value) in pendingEvents {
|
|
193
|
+
delegate?.send(event: key.rawValue, data: value)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/// NSObject init function.
|
|
199
|
+
public override init() {
|
|
200
|
+
sdk = MoveSDK.shared
|
|
201
|
+
pendingEvents = [:]
|
|
202
|
+
delegate = nil
|
|
203
|
+
tripMetaData = MoveSDKInstance.decode(.metaData) ?? [:]
|
|
204
|
+
|
|
205
|
+
super.init()
|
|
206
|
+
|
|
207
|
+
sdk.setSDKStateListener { state in
|
|
208
|
+
let value = "\(state)".uppercased()
|
|
209
|
+
self.send(event: .sdkState, data: ["state": "\(value)"])
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
sdk.setTripStateListener { state in
|
|
213
|
+
let value = "\(state)".uppercased()
|
|
214
|
+
self.send(event: .tripState, data: ["state": "\(value)"])
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
sdk.setTripStartListener { date in
|
|
218
|
+
self.send(event: .tripStart, data: Int64(date.timeIntervalSince1970 * 1000.0))
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
sdk.setAuthStateUpdateListener { state in
|
|
222
|
+
let value = "\(state)".uppercased()
|
|
223
|
+
self.send(event: .authState, data: ["state": "\(value)"])
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
sdk.setServiceFailureListener { failures in
|
|
227
|
+
let data: [String: Any] = ["errors": self.convert(failures: failures)]
|
|
228
|
+
self.send(event: .failure, data: data)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
sdk.setServiceWarningListener { warnings in
|
|
232
|
+
let data: [String: Any] = ["warnings": self.convert(warnings: warnings)]
|
|
233
|
+
self.send(event: .warning, data: data)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
sdk.setDeviceDiscoveryListener { scanResults in
|
|
237
|
+
let data = self.convert(scanResults: scanResults)
|
|
238
|
+
self.send(event: .scanResult, data: data)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
sdk.setDeviceStateListener { results in
|
|
242
|
+
let data = self.convert(devices: results)
|
|
243
|
+
self.send(event: .deviceState, data: data)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
sdk.setRemoteConfigChangeListener { config in
|
|
247
|
+
let services: [String] = config.services.reduce([]) { $0 + self.convert(service: $1, base: true) }
|
|
248
|
+
let data = ["services": services]
|
|
249
|
+
self.send(event: .configUpdate, data: data)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
sdk.setTripMetaDataListener { tripStart, tripEnd in
|
|
253
|
+
let metadata = self.tripMetaData
|
|
254
|
+
self.tripMetaData = [:]
|
|
255
|
+
return metadata
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
sdk.setLogListener { (event, value) in
|
|
259
|
+
DispatchQueue.main.async {
|
|
260
|
+
var data: [String: Any] = ["message": event]
|
|
261
|
+
|
|
262
|
+
if let value = value {
|
|
263
|
+
data["value"] = value
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
self.send(event: .logEvent, data: data)
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
sdk.setHealthScoreListener { items in
|
|
271
|
+
let data: [[String: String]] = items.map {
|
|
272
|
+
["reason": $0.reason.rawValue.snakeCased(), "description": $0.description]
|
|
273
|
+
}
|
|
274
|
+
self.send(event: .health, data: data)
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/// Convert service strings to config subroutine.
|
|
279
|
+
/// - Parameters:
|
|
280
|
+
/// - timelineDetectionServices: Timeline services strings.
|
|
281
|
+
/// - drivingServices: Driving services strings.
|
|
282
|
+
/// - walkingServices: Walking services strings
|
|
283
|
+
/// - Returns: `MoveConfig` for setup.
|
|
284
|
+
private func convert(timelineDetectionServices: Array<String>,
|
|
285
|
+
drivingServices: Array<String>,
|
|
286
|
+
walkingServices: Array<String>) -> MoveConfig {
|
|
287
|
+
|
|
288
|
+
let transformedServices: [MoveConfig.DrivingService] = drivingServices.compactMap {
|
|
289
|
+
switch $0 {
|
|
290
|
+
case ServiceName.distractionFreeDriving.rawValue:
|
|
291
|
+
return .distractionFreeDriving
|
|
292
|
+
case ServiceName.drivingBehavior.rawValue:
|
|
293
|
+
return .drivingBehavior
|
|
294
|
+
case ServiceName.deviceDiscovery.rawValue:
|
|
295
|
+
return .deviceDiscovery
|
|
296
|
+
default:
|
|
297
|
+
return nil
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
let transformedWalkingServices: [MoveConfig.WalkingService] = walkingServices.compactMap {
|
|
302
|
+
if $0 == ServiceName.walkingLocation.rawValue {
|
|
303
|
+
return .location
|
|
304
|
+
}
|
|
305
|
+
return nil
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
let transformedDetectionServices: [MoveConfig.DetectionService] = timelineDetectionServices.compactMap {
|
|
309
|
+
switch $0 {
|
|
310
|
+
case ServiceName.driving.rawValue:
|
|
311
|
+
return .driving(transformedServices)
|
|
312
|
+
case ServiceName.walking.rawValue:
|
|
313
|
+
return .walking(transformedWalkingServices)
|
|
314
|
+
case ServiceName.cycling.rawValue:
|
|
315
|
+
return .cycling
|
|
316
|
+
case ServiceName.publicTransport.rawValue:
|
|
317
|
+
return .publicTransport
|
|
318
|
+
case ServiceName.assistanceCall.rawValue:
|
|
319
|
+
return .assistanceCall
|
|
320
|
+
case ServiceName.pointsOfInterest.rawValue:
|
|
321
|
+
return .pointsOfInterest
|
|
322
|
+
case ServiceName.places.rawValue:
|
|
323
|
+
return .places
|
|
324
|
+
case ServiceName.automaticImpactDetection.rawValue:
|
|
325
|
+
return .automaticImpactDetection
|
|
326
|
+
case ServiceName.health.rawValue:
|
|
327
|
+
return .health
|
|
328
|
+
default:
|
|
329
|
+
return nil
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return MoveConfig(detectionService: transformedDetectionServices)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/// Convert options json dict to `MoveOptions` object.
|
|
337
|
+
/// - Returns: Converted options object.
|
|
338
|
+
private func convert(options: [MoveSdkOption]) -> MoveOptions {
|
|
339
|
+
let moveOptions = MoveOptions()
|
|
340
|
+
|
|
341
|
+
for option in options {
|
|
342
|
+
switch option.key {
|
|
343
|
+
case .startDelay:
|
|
344
|
+
moveOptions.deviceDiscovery.startDelay = option.value.doubleValue
|
|
345
|
+
case .interval:
|
|
346
|
+
moveOptions.deviceDiscovery.interval = option.value.doubleValue
|
|
347
|
+
case .duration:
|
|
348
|
+
moveOptions.deviceDiscovery.duration = option.value.doubleValue
|
|
349
|
+
case .stopScanOnFirstDiscovered:
|
|
350
|
+
moveOptions.deviceDiscovery.stopScanOnFirstDiscovered = option.value.boolValue
|
|
351
|
+
case .motionPermissionMandatory:
|
|
352
|
+
moveOptions.motionPermissionMandatory = option.value.boolValue
|
|
353
|
+
case .backgroundLocationPermissionMandatory:
|
|
354
|
+
moveOptions.backgroundLocationPermissionMandatory = option.value.boolValue
|
|
355
|
+
case .useBackendConfig:
|
|
356
|
+
moveOptions.useBackendConfig = option.value.boolValue
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return moveOptions
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
/// Serialize SDK service failures.
|
|
365
|
+
/// - Parameters:
|
|
366
|
+
/// - failures: Move service failures to be serialized.
|
|
367
|
+
///
|
|
368
|
+
/// - Returns: List of error list items.
|
|
369
|
+
///
|
|
370
|
+
/// Used in `MoveSDK.getServiceFailures()` and service failure listener.
|
|
371
|
+
fileprivate func convert(failures: [DolphinMoveSDK.MoveServiceFailure]) -> [ErrorListItem] {
|
|
372
|
+
var converted: [ErrorListItem] = []
|
|
373
|
+
|
|
374
|
+
for failure in failures {
|
|
375
|
+
var reasons: [String] = []
|
|
376
|
+
switch failure.reason {
|
|
377
|
+
case let .missingPermission(permissions):
|
|
378
|
+
let content: [String] = permissions.map { self.permissionString($0) }
|
|
379
|
+
reasons = content
|
|
380
|
+
case .unauthorized:
|
|
381
|
+
reasons = ["Unauthorized"]
|
|
382
|
+
}
|
|
383
|
+
let services = convert(service: failure.service)
|
|
384
|
+
for service in services {
|
|
385
|
+
converted.append(["service": service, "reasons": reasons])
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return converted
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/// Serialize detection service.
|
|
393
|
+
/// - Parameters:
|
|
394
|
+
/// - service: Move service to be serialized.
|
|
395
|
+
///
|
|
396
|
+
/// - Returns: List of one or more service strings for service and subservices.
|
|
397
|
+
fileprivate func convert(service: DolphinMoveSDK.MoveConfig.DetectionService, base: Bool = false) -> [String] {
|
|
398
|
+
switch service {
|
|
399
|
+
case let .driving(sub):
|
|
400
|
+
var services: [String] = base || sub.isEmpty ? [ServiceName.driving.rawValue] : []
|
|
401
|
+
for subservice in sub {
|
|
402
|
+
switch subservice {
|
|
403
|
+
case .drivingBehavior:
|
|
404
|
+
services.append(ServiceName.drivingBehavior.rawValue)
|
|
405
|
+
case .distractionFreeDriving:
|
|
406
|
+
services.append(ServiceName.distractionFreeDriving.rawValue)
|
|
407
|
+
case .deviceDiscovery:
|
|
408
|
+
services.append(ServiceName.deviceDiscovery.rawValue)
|
|
409
|
+
default: break
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return services
|
|
413
|
+
case .cycling:
|
|
414
|
+
return [ServiceName.cycling.rawValue]
|
|
415
|
+
case let .walking(sub):
|
|
416
|
+
var services: [String] = base || sub.isEmpty ? [ServiceName.walking.rawValue] : []
|
|
417
|
+
for subservice in sub {
|
|
418
|
+
switch subservice {
|
|
419
|
+
case .location:
|
|
420
|
+
services.append(ServiceName.walkingLocation.rawValue)
|
|
421
|
+
default: break
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return services
|
|
425
|
+
case .places:
|
|
426
|
+
return [ServiceName.places.rawValue]
|
|
427
|
+
case .publicTransport:
|
|
428
|
+
return [ServiceName.publicTransport.rawValue]
|
|
429
|
+
case .pointsOfInterest:
|
|
430
|
+
return [ServiceName.pointsOfInterest.rawValue]
|
|
431
|
+
case .automaticImpactDetection:
|
|
432
|
+
return [ServiceName.automaticImpactDetection.rawValue]
|
|
433
|
+
case .assistanceCall:
|
|
434
|
+
return [ServiceName.assistanceCall.rawValue]
|
|
435
|
+
case .health:
|
|
436
|
+
return [ServiceName.health.rawValue]
|
|
437
|
+
@unknown default:
|
|
438
|
+
return [service.debugDescription]
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/// Serialize SDK service warnings.
|
|
443
|
+
/// - Parameters:
|
|
444
|
+
/// - failures: Move service warnings to be serialized.
|
|
445
|
+
///
|
|
446
|
+
/// - Returns: List of error list items.
|
|
447
|
+
///
|
|
448
|
+
/// Used in `MoveSDK.getServiceWarnings()` and service warning listener.
|
|
449
|
+
fileprivate func convert(warnings: [DolphinMoveSDK.MoveServiceWarning]) -> [ErrorListItem] {
|
|
450
|
+
var converted: [ErrorListItem] = []
|
|
451
|
+
|
|
452
|
+
for warning in warnings {
|
|
453
|
+
var reasons: [String] = []
|
|
454
|
+
switch warning.reason {
|
|
455
|
+
case let .missingPermission(permissions):
|
|
456
|
+
let content: [String] = permissions.compactMap {
|
|
457
|
+
self.permissionString($0)
|
|
458
|
+
}
|
|
459
|
+
reasons = content
|
|
460
|
+
}
|
|
461
|
+
let services = convert(service: warning.service)
|
|
462
|
+
for service in services {
|
|
463
|
+
converted.append(["service": service, "reasons": reasons])
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return converted
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/// Serialize device objects for React Native events.
|
|
471
|
+
/// - Parameters:
|
|
472
|
+
/// - devices: `MoveDevice` list.
|
|
473
|
+
/// - Returns: List of serialized device objects.
|
|
474
|
+
///
|
|
475
|
+
/// Used from `getRegisteredDevices()` or from device scanner.
|
|
476
|
+
fileprivate func convert(devices: [MoveDevice]) -> [[String:String]] {
|
|
477
|
+
var deviceList: [[String: String]] = []
|
|
478
|
+
for device in devices {
|
|
479
|
+
let encoder = JSONEncoder()
|
|
480
|
+
do {
|
|
481
|
+
let data = try encoder.encode(device)
|
|
482
|
+
let str = String(data: data, encoding: .utf8) ?? ""
|
|
483
|
+
let info: [String: String] = ["name": device.name, "data": str, "id": device.id, "isConnected": "\(device.isConnected)"]
|
|
484
|
+
deviceList.append(info)
|
|
485
|
+
} catch {
|
|
486
|
+
print(error.localizedDescription)
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return deviceList
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/// Deserialize device objects from React Native function arguments.
|
|
494
|
+
/// - Parameters:
|
|
495
|
+
/// - devices: React Native function arguments list.
|
|
496
|
+
///
|
|
497
|
+
/// - Returns: List of deserialized `MoveDevice` objects.
|
|
498
|
+
///
|
|
499
|
+
/// Passed to `register(devices)` or `unregister(devices)`.
|
|
500
|
+
fileprivate func convert(devices: [Any]) -> [MoveDevice] {
|
|
501
|
+
return devices.compactMap { values in
|
|
502
|
+
guard let values = values as? [String: String] else { return nil }
|
|
503
|
+
let encoded: String = values["data"] ?? ""
|
|
504
|
+
|
|
505
|
+
let decoder = JSONDecoder()
|
|
506
|
+
guard let data = encoded.data(using: .utf8) else { return nil }
|
|
507
|
+
do {
|
|
508
|
+
let device = try decoder.decode(MoveDevice.self, from: data)
|
|
509
|
+
/* keep device name from info */
|
|
510
|
+
return device
|
|
511
|
+
} catch {
|
|
512
|
+
return nil
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/// Serialize device scan results for React Native events.
|
|
518
|
+
/// - Parameters:
|
|
519
|
+
/// - scanResults: `MoveScanResult` list.
|
|
520
|
+
///
|
|
521
|
+
/// - Returns: List of serialized device objects.
|
|
522
|
+
///
|
|
523
|
+
/// Used from device detection listener.
|
|
524
|
+
fileprivate func convert(scanResults: [MoveScanResult]) -> [[String: Any]] {
|
|
525
|
+
var deviceList: [[String: Any]] = []
|
|
526
|
+
for result in scanResults {
|
|
527
|
+
let encoder = JSONEncoder()
|
|
528
|
+
do {
|
|
529
|
+
let data = try encoder.encode(result.device)
|
|
530
|
+
let str = String(data: data, encoding: .utf8) ?? ""
|
|
531
|
+
let info: [String: Any] = ["name": result.device.name, "device": str, "id": result.device.id, "isDiscovered": result.isDiscovered]
|
|
532
|
+
deviceList.append(info)
|
|
533
|
+
} catch {
|
|
534
|
+
print(error.localizedDescription)
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return deviceList
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/// Decode from user defaults.
|
|
542
|
+
/// - Parameters:
|
|
543
|
+
/// - key: User defaults string key.
|
|
544
|
+
///
|
|
545
|
+
/// - Returns: Decoded object.
|
|
546
|
+
private static func decode<T>(_ key: DefaultsKey) -> T? where T: Decodable {
|
|
547
|
+
let decoder = PropertyListDecoder()
|
|
548
|
+
|
|
549
|
+
if let data = UserDefaults.standard.object(forKey: key.rawValue) as? Data {
|
|
550
|
+
return try? decoder.decode(T.self, from: data)
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
return nil
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/// Encode to user defaults.
|
|
557
|
+
/// - Parameters:
|
|
558
|
+
/// - key: User defaults string key.
|
|
559
|
+
private static func encode<T>(_ encodable: T?, forKey key: DefaultsKey) where T: Encodable {
|
|
560
|
+
if let encodable = encodable {
|
|
561
|
+
let encoder = PropertyListEncoder()
|
|
562
|
+
if let data = try? encoder.encode(encodable) {
|
|
563
|
+
UserDefaults.standard.set(data, forKey: key.rawValue)
|
|
564
|
+
}
|
|
565
|
+
} else {
|
|
566
|
+
UserDefaults.standard.removeObject(forKey: key.rawValue)
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/// Serialize move permission object into string.
|
|
571
|
+
/// - Parameters:
|
|
572
|
+
/// - permission: Permission object to serialize.
|
|
573
|
+
///
|
|
574
|
+
/// - Returns: Service permission string passed to React Native.
|
|
575
|
+
fileprivate func permissionString(_ permission: DolphinMoveSDK.MovePermission) -> String {
|
|
576
|
+
switch permission {
|
|
577
|
+
case .location:
|
|
578
|
+
return "LOCATION_PERMISSION_MISSING"
|
|
579
|
+
case .backgroundLocation:
|
|
580
|
+
return "BACKGROUND_LOCATION_PERMISSION_MISSING"
|
|
581
|
+
case .preciseLocation:
|
|
582
|
+
return "PRECISE_LOCATION_PERMISSION_MISSING"
|
|
583
|
+
case .motionActivity:
|
|
584
|
+
return "MOTION_PERMISSION_MISSING"
|
|
585
|
+
case .gyroscope:
|
|
586
|
+
return "GYROSCOPE_MISSING"
|
|
587
|
+
case .accelerometer:
|
|
588
|
+
return "ACCELEROMETER_MISSING"
|
|
589
|
+
case .bluetooth:
|
|
590
|
+
return "BLUETOOTH_TURNED_OFF"
|
|
591
|
+
case .bluetoothScan:
|
|
592
|
+
return "BLUETOOTH_PERMISSION_MISSING"
|
|
593
|
+
case .steps:
|
|
594
|
+
return "HEALTH_CONNECT_READ_STEPS_PERMISSION_MISSING"
|
|
595
|
+
@unknown default:
|
|
596
|
+
return "UNKNOWN"
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/// Send event to observer.
|
|
601
|
+
/// - Parameters:
|
|
602
|
+
/// - event: Event key.
|
|
603
|
+
/// - data: Event object.
|
|
604
|
+
///
|
|
605
|
+
/// Events are buffered when there is no observer.
|
|
606
|
+
private func send(event: Event, data: Any) {
|
|
607
|
+
if let delegate {
|
|
608
|
+
delegate.send(event: event.rawValue, data: data)
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
pendingEvents[event] = data
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
extension MoveSDKInstance: MoveSdkDeviceScannerDelegate {
|
|
616
|
+
func didDiscover(devices: [DolphinMoveSDK.MoveDevice]) {
|
|
617
|
+
send(event: .devices, data: convert(devices: devices))
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/// Wrapper extensions for ObjC interface.
|
|
622
|
+
@objc public extension MoveSDKInstance {
|
|
623
|
+
/// Event emitter supported events.
|
|
624
|
+
static var supportedEvents: [String] {
|
|
625
|
+
Event.allCases.map { $0.rawValue }
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/// Global initialization function.
|
|
629
|
+
func initialize() {
|
|
630
|
+
sdk.initialize(launchOptions: nil)
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/// Module wrapper.
|
|
634
|
+
var sdkState: String {
|
|
635
|
+
"\(sdk.getSDKState())".uppercased()
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/// Module wrapper.
|
|
639
|
+
var tripState: String {
|
|
640
|
+
"\(sdk.getTripState())".uppercased()
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/// Module wrapper.
|
|
644
|
+
var authState: String {
|
|
645
|
+
return "\(sdk.getAuthState())".uppercased()
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/// Module wrapper.
|
|
649
|
+
var warnings: [ErrorListItem] {
|
|
650
|
+
convert(warnings: sdk.getServiceWarnings())
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/// Module wrapper.
|
|
654
|
+
var failures: [ErrorListItem] {
|
|
655
|
+
convert(failures: sdk.getServiceFailures())
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/// Wrapper for `MoveSDK.setup(auth:config:options)`.
|
|
659
|
+
/// - Parameters:
|
|
660
|
+
/// - contractId: Authentication user ID.
|
|
661
|
+
/// - accessToken: Authentication user token.
|
|
662
|
+
/// - refreshToken: Authentication refresh token.
|
|
663
|
+
/// - productId: Authentication project ID.
|
|
664
|
+
/// - timelineDetectionServices: List of timeline detection services.
|
|
665
|
+
/// - drivingServices: List of driving services.
|
|
666
|
+
/// - walkingServices: List of walking services.
|
|
667
|
+
/// - options: Options dictionary object.
|
|
668
|
+
func setup(_ contractId: String,
|
|
669
|
+
accessToken: String,
|
|
670
|
+
refreshToken: String,
|
|
671
|
+
productId: Int64,
|
|
672
|
+
timelineDetectionServices: [String],
|
|
673
|
+
drivingServices: [String],
|
|
674
|
+
walkingServices: [String],
|
|
675
|
+
options: [MoveSdkOption]) {
|
|
676
|
+
|
|
677
|
+
let sdkConfig = convert(timelineDetectionServices: timelineDetectionServices, drivingServices: drivingServices, walkingServices: walkingServices)
|
|
678
|
+
let moveOptions = convert(options: options)
|
|
679
|
+
|
|
680
|
+
let auth = MoveAuth(userToken: accessToken, refreshToken: refreshToken, userID: contractId, projectID: productId)
|
|
681
|
+
|
|
682
|
+
sdk.setup(auth: auth, config: sdkConfig, options: moveOptions)
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/// Wrapper for `MoveSDK.setup(authCode:config:options:callback)`.
|
|
686
|
+
/// - Parameters:
|
|
687
|
+
/// - authCode: Authentication code.
|
|
688
|
+
/// - timelineDetectionServices: List of timeline detection services.
|
|
689
|
+
/// - drivingServices: List of driving services.
|
|
690
|
+
/// - walkingServices: List of walking services.
|
|
691
|
+
/// - options: Options dictionary object.
|
|
692
|
+
/// - callback: Error callback.
|
|
693
|
+
func setup(_ authCode: String,
|
|
694
|
+
timelineDetectionServices: [String],
|
|
695
|
+
drivingServices: [String],
|
|
696
|
+
walkingServices: [String],
|
|
697
|
+
options: [MoveSdkOption],
|
|
698
|
+
callback: @escaping(MoveSdkError?)->Void) {
|
|
699
|
+
|
|
700
|
+
let sdkConfig = convert(timelineDetectionServices: timelineDetectionServices, drivingServices: drivingServices, walkingServices: walkingServices)
|
|
701
|
+
let moveOptions = convert(options: options)
|
|
702
|
+
|
|
703
|
+
sdk.setup(authCode: authCode, config: sdkConfig, options: moveOptions) { result in
|
|
704
|
+
switch result {
|
|
705
|
+
case .success:
|
|
706
|
+
callback(nil)
|
|
707
|
+
case .networkError:
|
|
708
|
+
callback(.networkError)
|
|
709
|
+
case let .invalidCode(error):
|
|
710
|
+
callback(.setupError(text: "\(error)"))
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/// Wrapper for `MoveSDK.update(config:)`.
|
|
716
|
+
/// - Parameters:
|
|
717
|
+
/// - timelineDetectionServices: Timeline detection services strings.
|
|
718
|
+
/// - drivingServices: Driving services strings.
|
|
719
|
+
/// - walkingServices: Walking services strings.
|
|
720
|
+
func updateConfig(_ timelineDetectionServices: Array<String>,
|
|
721
|
+
drivingServices: Array<String>,
|
|
722
|
+
walkingServices: Array<String>,
|
|
723
|
+
options: [MoveSdkOption]) {
|
|
724
|
+
|
|
725
|
+
let sdkConfig = convert(timelineDetectionServices: timelineDetectionServices, drivingServices: drivingServices, walkingServices: walkingServices)
|
|
726
|
+
let moveOptions = convert(options: options)
|
|
727
|
+
sdk.update(config: sdkConfig, options: moveOptions)
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/// Wrapper for `MoveSDK.shutDown()`.
|
|
731
|
+
/// - Parameters:
|
|
732
|
+
/// - force: Force shutdown with possible data loss.
|
|
733
|
+
/// - callback: Error callback.
|
|
734
|
+
func shutdown(_ force: Bool, callback: @escaping(MoveSdkError?)->Void) {
|
|
735
|
+
sdk.shutDown() { status in
|
|
736
|
+
switch status {
|
|
737
|
+
case .success:
|
|
738
|
+
callback(nil)
|
|
739
|
+
case .uninitialized:
|
|
740
|
+
callback(.uninitialized)
|
|
741
|
+
case .networkError:
|
|
742
|
+
callback(.networkError)
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/// Wrapper for `MoveSDK.updateAuth(auth)`.
|
|
748
|
+
/// - Parameters:
|
|
749
|
+
/// - contractId: Authentication user ID.
|
|
750
|
+
/// - accessToken: Authentication user token.
|
|
751
|
+
/// - refreshToken: Authentication refresh token.
|
|
752
|
+
/// - productId: Authentication project ID.
|
|
753
|
+
/// - callback: Error callback.
|
|
754
|
+
func updateAuth(
|
|
755
|
+
_ contractId: String,
|
|
756
|
+
accessToken: String,
|
|
757
|
+
refreshToken: String,
|
|
758
|
+
productId: Int64,
|
|
759
|
+
callback: @escaping(MoveSdkError?)->Void
|
|
760
|
+
) {
|
|
761
|
+
let auth = MoveAuth(userToken: accessToken, refreshToken: refreshToken, userID: contractId, projectID: productId)
|
|
762
|
+
|
|
763
|
+
sdk.update(auth: auth) { configurationError in
|
|
764
|
+
if let configurationError = configurationError {
|
|
765
|
+
switch configurationError {
|
|
766
|
+
case .authInvalid:
|
|
767
|
+
callback(.authInvalid)
|
|
768
|
+
default:
|
|
769
|
+
callback(.configurationError)
|
|
770
|
+
}
|
|
771
|
+
} else {
|
|
772
|
+
callback(nil)
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/// Wrapper for `MoveSDK.geocode(latitude:longitude)`.
|
|
778
|
+
/// - Parameters:
|
|
779
|
+
/// - latitude: Geocoord degrees latitude.
|
|
780
|
+
/// - longitude: Geocoord degrees longitude.
|
|
781
|
+
/// - callback: Error callback.
|
|
782
|
+
func geocode(latitude: Double, longitude: Double, callback: @escaping(String?, MoveSdkError?)->Void) {
|
|
783
|
+
sdk.geocode(latitude: latitude, longitude: longitude) { result in
|
|
784
|
+
switch result {
|
|
785
|
+
case let .success(value):
|
|
786
|
+
callback(value, nil)
|
|
787
|
+
case let .failure(err):
|
|
788
|
+
switch err {
|
|
789
|
+
case .resolveFailed:
|
|
790
|
+
callback(nil, .resolveFailed)
|
|
791
|
+
case .serviceUnreachable:
|
|
792
|
+
callback(nil, .serviceUnavailable)
|
|
793
|
+
case .thresholdReached:
|
|
794
|
+
callback(nil, .thresholdReached)
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/// Wrapper for `MoveSDK.initiateAssistanceCall()`.
|
|
801
|
+
/// - callback: Error callback.
|
|
802
|
+
func initiateAssistanceCall(callback: @escaping(MoveSdkError?)->Void) {
|
|
803
|
+
sdk.initiateAssistanceCall { status in
|
|
804
|
+
switch status {
|
|
805
|
+
case .success:
|
|
806
|
+
callback(nil)
|
|
807
|
+
case .initializationError:
|
|
808
|
+
callback(.initializationError)
|
|
809
|
+
case .networkError:
|
|
810
|
+
callback(.networkError)
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/// Wrapper for `MoveSDK.isAuthValid()`.
|
|
816
|
+
/// - Returns: Is authentication valid.
|
|
817
|
+
///
|
|
818
|
+
/// Authentication is invalid incase of `.invalid` and `.expired`.
|
|
819
|
+
func isAuthValid() -> Bool {
|
|
820
|
+
switch sdk.getAuthState() {
|
|
821
|
+
case .invalid, .expired:
|
|
822
|
+
return false
|
|
823
|
+
default:
|
|
824
|
+
return true
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
/// Wrapper for `MoveSDK.setLiveLocationTag(:)`.
|
|
829
|
+
/// - Parameter tag: Tag. `NULL` = clear.
|
|
830
|
+
/// - Returns: Success.
|
|
831
|
+
func setLiveLocationTag(_ tag: String?) -> Bool {
|
|
832
|
+
sdk.setLiveLocationTag(tag)
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
/// Wrapper for `MoveSDK.startAutomaticDetection()`.
|
|
836
|
+
/// - Returns: Success.
|
|
837
|
+
func startAutomaticDetection() -> Bool {
|
|
838
|
+
sdk.startAutomaticDetection()
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/// Wrapper for `MoveSDK.stopAutomaticDetection()`
|
|
842
|
+
/// - Returns: Success.
|
|
843
|
+
func stopAutomaticDetection() -> Bool {
|
|
844
|
+
sdk.stopAutomaticDetection()
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
/// Wrapper for `MoveSDK.startTrip(metadata:)`.
|
|
848
|
+
/// - Parameter metadata: Trip metadata.
|
|
849
|
+
/// - Returns: Success.
|
|
850
|
+
func startTrip(_ metadata: [String: String]?) -> Bool {
|
|
851
|
+
sdk.startTrip(metadata: metadata ?? [:])
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
/// Wrapper for `MoveSDK.synchronizeUserData()`.
|
|
855
|
+
/// - Parameters:
|
|
856
|
+
/// - callback: Error callback.
|
|
857
|
+
func synchronizeUserData(_ callback: @escaping(Bool) -> Void) {
|
|
858
|
+
sdk.synchronizeUserData() { success in
|
|
859
|
+
callback(success)
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/// Start device scanner.
|
|
864
|
+
/// - Parameters:
|
|
865
|
+
/// - filter: Device type filter.
|
|
866
|
+
/// - uuid: iBeacon UUID.
|
|
867
|
+
func startScanningDevices(_ filter: [String], uuid: String?) {
|
|
868
|
+
DispatchQueue.main.async {
|
|
869
|
+
self.scanner.delegate = self
|
|
870
|
+
self.scanner.startScanning(filter: filter, uuid: uuid)
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
/// Stop device scanner.
|
|
875
|
+
func stopScanningDevices() {
|
|
876
|
+
DispatchQueue.main.async {
|
|
877
|
+
self.scanner.stopScanning()
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
func requestHealthPermissions(_ callback: @escaping(Bool, MoveSdkError?)->Void) {
|
|
882
|
+
let stepCountSampleType = HKObjectType.quantityType(forIdentifier: .stepCount)!
|
|
883
|
+
|
|
884
|
+
healthStore.requestAuthorization(toShare: [], read: [stepCountSampleType]) { (success, error) in
|
|
885
|
+
if let error {
|
|
886
|
+
callback(false, .otherError(title: "PERMISSION_ERROR", text: error.localizedDescription))
|
|
887
|
+
} else if success {
|
|
888
|
+
callback(success, nil)
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
/// Request bluetooth permission.
|
|
894
|
+
func requestBluetoothAlwaysUsagePermission() {
|
|
895
|
+
bluetoothManager.getBluetoothState() { _ in }
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
/// Request motion permission.
|
|
899
|
+
func requestMotionPermission() {
|
|
900
|
+
motionManager.queryActivityStarting(from: Date(), to: Date(), to: OperationQueue.main) { _, error in
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
/// Get bluetooth permission.
|
|
905
|
+
/// - Parameter resolve: Is bluetooth permitted.
|
|
906
|
+
func getBluetoothPermission(_ resolve: @escaping (Bool)->Void) {
|
|
907
|
+
bluetoothManager.getBluetoothState() { state in
|
|
908
|
+
switch state {
|
|
909
|
+
case .unknown:
|
|
910
|
+
resolve(false)
|
|
911
|
+
case .resetting:
|
|
912
|
+
resolve(false)
|
|
913
|
+
case .unsupported:
|
|
914
|
+
resolve(false)
|
|
915
|
+
case .unauthorized:
|
|
916
|
+
resolve(false)
|
|
917
|
+
case .poweredOff:
|
|
918
|
+
resolve(true)
|
|
919
|
+
case .poweredOn:
|
|
920
|
+
resolve(true)
|
|
921
|
+
@unknown default:
|
|
922
|
+
resolve(false)
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/// Get bluetooth state.
|
|
928
|
+
/// - Parameter resolve: Is bluetooth on.
|
|
929
|
+
///
|
|
930
|
+
/// Undefined without permission.
|
|
931
|
+
func getBluetoothState(_ resolve: @escaping (Bool)->Void) {
|
|
932
|
+
bluetoothManager.getBluetoothState() { state in
|
|
933
|
+
switch state {
|
|
934
|
+
case .unknown:
|
|
935
|
+
resolve(false)
|
|
936
|
+
case .resetting:
|
|
937
|
+
resolve(false)
|
|
938
|
+
case .unsupported:
|
|
939
|
+
resolve(false)
|
|
940
|
+
case .unauthorized:
|
|
941
|
+
resolve(false)
|
|
942
|
+
case .poweredOff:
|
|
943
|
+
resolve(false)
|
|
944
|
+
case .poweredOn:
|
|
945
|
+
resolve(true)
|
|
946
|
+
@unknown default:
|
|
947
|
+
resolve(false)
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
/// Wrapper for `MoveSDK.ignoreCurrentTrip()`.
|
|
953
|
+
func ignoreCurrentTrip() {
|
|
954
|
+
sdk.ignoreCurrentTrip()
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
/// Wrapper for `MoveSDK.finishCurrentTrip()`.
|
|
958
|
+
func finishCurrentTrip() {
|
|
959
|
+
sdk.finishCurrentTrip()
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/// Wrapper for `MoveSDK.resolveSDKStateError()`.
|
|
963
|
+
func resolveError() {
|
|
964
|
+
sdk.resolveSDKStateError()
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
/// Wrapper for `MoveSDK.setAssistanceMetaData(_)`
|
|
968
|
+
func setAssistanceMetaData(_ metadata: String) {
|
|
969
|
+
sdk.setAssistanceMetaData(metadata)
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/// Wrapper for `MoveSDK.getDeviceQualifier()`.
|
|
973
|
+
/// Identifier uniquely identifying device, for when device data is transferred to a new phone.
|
|
974
|
+
func getDeviceQualifier() -> String {
|
|
975
|
+
sdk.getDeviceQualifier()
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
/// Wrapper for `MoveSDK.getRegisteredDevices()`.
|
|
979
|
+
func getRegisteredDevices() -> [[String:String]] {
|
|
980
|
+
return convert(devices: sdk.getRegisteredDevices())
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
/// Wrapper for `MoveSDK.register(devices)`.
|
|
984
|
+
func registerDevices(_ devices: [Any]) {
|
|
985
|
+
let devices = convert(devices: devices)
|
|
986
|
+
sdk.register(devices: devices)
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
/// Wrapper for `MoveSDK.unregister(devices)`.
|
|
990
|
+
func unregisterDevices(_ devices: [Any]) {
|
|
991
|
+
let devices = convert(devices: devices)
|
|
992
|
+
sdk.unregister(devices: devices)
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/// Add trip metadata.
|
|
996
|
+
/// - Parameter metadata: Meta data strings dictionary.
|
|
997
|
+
func setTrip(metadata: [String: String]) {
|
|
998
|
+
var data = self.tripMetaData
|
|
999
|
+
for (key, value) in metadata {
|
|
1000
|
+
data[key] = value
|
|
1001
|
+
}
|
|
1002
|
+
self.tripMetaData = data
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
/// Wrapper for `MoveSDK.forceTripRecognition()`.
|
|
1006
|
+
func forceTripRecognition() {
|
|
1007
|
+
sdk.forceTripRecognition()
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
extension String {
|
|
1012
|
+
func snakeCased() -> String {
|
|
1013
|
+
let pattern = "([a-z0-9])([A-Z])"
|
|
1014
|
+
|
|
1015
|
+
if let regex = try? NSRegularExpression(pattern: pattern, options: []) {
|
|
1016
|
+
let range = NSRange(location: 0, length: count)
|
|
1017
|
+
return regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: "$1_$2").uppercased()
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
return uppercased()
|
|
1021
|
+
}
|
|
1022
|
+
}
|