@mentra/bluetooth-sdk 0.1.4 → 0.1.6
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/README.md +61 -42
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +20 -12
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +38 -12
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +2 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +45 -51
- package/android/src/main/java/com/mentra/bluetoothsdk/audio/AudioModels.kt +125 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/camera/CameraModels.kt +187 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/connection/ConnectionModels.kt +78 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/events/BluetoothEvents.kt +60 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/internal/MapParsing.kt +132 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/requests/DisplayRequests.kt +39 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/status/DeviceStatus.kt +605 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/status/RuntimeState.kt +199 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/status/WifiHotspotStatus.kt +173 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/streaming/StreamModels.kt +348 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/types/DeviceModels.kt +75 -0
- package/build/BluetoothSdk.types.d.ts +24 -7
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_internal.d.ts +1 -1
- package/build/_internal.js +1 -1
- package/build/_internal.js.map +1 -1
- package/build/_private/BluetoothSdkModule.d.ts +5 -4
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
- package/build/_private/BluetoothSdkModule.js +4 -1
- package/build/_private/BluetoothSdkModule.js.map +1 -1
- package/build/index.d.ts +4 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +81 -2
- package/build/index.js.map +1 -1
- package/build/react/index.d.ts +2 -2
- package/build/react/index.d.ts.map +1 -1
- package/build/react/index.js +1 -2
- package/build/react/index.js.map +1 -1
- package/build/react/useBluetoothStatus.js +1 -1
- package/build/react/useBluetoothStatus.js.map +1 -1
- package/build/react/useGlassesConnection.d.ts.map +1 -1
- package/build/react/useGlassesConnection.js +13 -0
- package/build/react/useGlassesConnection.js.map +1 -1
- package/build/react/useMentraBluetooth.d.ts +98 -0
- package/build/react/useMentraBluetooth.d.ts.map +1 -0
- package/build/react/useMentraBluetooth.js +156 -0
- package/build/react/useMentraBluetooth.js.map +1 -0
- package/ios/BluetoothSdkModule.swift +9 -9
- package/ios/Source/Audio/AudioModels.swift +159 -0
- package/ios/Source/Bridge.swift +42 -8
- package/ios/Source/Camera/CameraModels.swift +246 -0
- package/ios/Source/Connection/ScanSession.swift +27 -0
- package/ios/Source/DeviceManager.swift +0 -1
- package/ios/Source/DeviceStore.swift +2 -1
- package/ios/Source/Errors/BluetoothError.swift +19 -0
- package/ios/Source/Events/BluetoothEvents.swift +115 -0
- package/ios/Source/Internal/BluetoothAvailability.swift +58 -0
- package/ios/Source/Internal/ValueParsing.swift +90 -0
- package/ios/Source/MentraBluetoothSDK.swift +32 -2040
- package/ios/Source/Requests/DisplayRequests.swift +58 -0
- package/ios/Source/Status/DeviceStatus.swift +463 -0
- package/ios/Source/Status/RuntimeState.swift +350 -0
- package/ios/Source/Status/WifiHotspotStatus.swift +326 -0
- package/ios/Source/Streaming/StreamModels.swift +436 -0
- package/ios/Source/Types/DeviceModels.swift +134 -0
- package/ios/Source/sgcs/G2.swift +97 -36
- package/package.json +1 -1
- package/src/BluetoothSdk.types.ts +24 -7
- package/src/_internal.ts +1 -1
- package/src/_private/BluetoothSdkModule.ts +10 -5
- package/src/index.ts +93 -4
- package/src/react/index.ts +13 -11
- package/src/react/useBluetoothStatus.ts +1 -1
- package/src/react/useGlassesConnection.ts +15 -0
- package/src/react/useMentraBluetooth.ts +307 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothModels.kt +0 -1725
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk
|
|
2
|
+
|
|
3
|
+
enum class GalleryMode {
|
|
4
|
+
AUTO,
|
|
5
|
+
MANUAL,
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
enum class PhotoSize(val value: String) {
|
|
9
|
+
SMALL("small"),
|
|
10
|
+
MEDIUM("medium"),
|
|
11
|
+
LARGE("large"),
|
|
12
|
+
FULL("full");
|
|
13
|
+
|
|
14
|
+
companion object {
|
|
15
|
+
@JvmStatic
|
|
16
|
+
fun fromValue(value: String?): PhotoSize =
|
|
17
|
+
values().firstOrNull { it.value == value } ?: MEDIUM
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
enum class ButtonPhotoSize(val value: String) {
|
|
22
|
+
SMALL("small"),
|
|
23
|
+
MEDIUM("medium"),
|
|
24
|
+
LARGE("large");
|
|
25
|
+
|
|
26
|
+
companion object {
|
|
27
|
+
@JvmStatic
|
|
28
|
+
fun fromValue(value: String?): ButtonPhotoSize =
|
|
29
|
+
values().firstOrNull { it.value == value } ?: MEDIUM
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
enum class PhotoCompression(val value: String) {
|
|
34
|
+
NONE("none"),
|
|
35
|
+
MEDIUM("medium"),
|
|
36
|
+
HEAVY("heavy");
|
|
37
|
+
|
|
38
|
+
companion object {
|
|
39
|
+
@JvmStatic
|
|
40
|
+
fun fromValue(value: String?): PhotoCompression =
|
|
41
|
+
values().firstOrNull { it.value == value } ?: NONE
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
data class ButtonPhotoSettings(
|
|
46
|
+
val size: ButtonPhotoSize,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
data class ButtonVideoRecordingSettings(
|
|
50
|
+
val width: Int,
|
|
51
|
+
val height: Int,
|
|
52
|
+
val frameRate: Int,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
enum class CameraFov(val fov: Int, val roiPosition: Int) {
|
|
56
|
+
STANDARD(118, 0),
|
|
57
|
+
WIDE(118, 0),
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
data class PhotoRequest @JvmOverloads constructor(
|
|
61
|
+
val requestId: String,
|
|
62
|
+
val appId: String,
|
|
63
|
+
val size: PhotoSize,
|
|
64
|
+
val webhookUrl: String,
|
|
65
|
+
val authToken: String? = null,
|
|
66
|
+
val compress: PhotoCompression = PhotoCompression.MEDIUM,
|
|
67
|
+
val sound: Boolean = true,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
enum class RgbLedAction(val value: String) {
|
|
71
|
+
ON("on"),
|
|
72
|
+
OFF("off");
|
|
73
|
+
|
|
74
|
+
companion object {
|
|
75
|
+
@JvmStatic
|
|
76
|
+
fun fromValue(value: String?): RgbLedAction =
|
|
77
|
+
values().firstOrNull { it.value == value } ?: OFF
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
enum class RgbLedColor(val value: String) {
|
|
82
|
+
RED("red"),
|
|
83
|
+
GREEN("green"),
|
|
84
|
+
BLUE("blue"),
|
|
85
|
+
ORANGE("orange"),
|
|
86
|
+
WHITE("white");
|
|
87
|
+
|
|
88
|
+
companion object {
|
|
89
|
+
@JvmStatic
|
|
90
|
+
fun fromValue(value: String?): RgbLedColor? =
|
|
91
|
+
values().firstOrNull { it.value == value }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
data class RgbLedRequest @JvmOverloads constructor(
|
|
96
|
+
val requestId: String,
|
|
97
|
+
val packageName: String?,
|
|
98
|
+
val action: RgbLedAction,
|
|
99
|
+
val color: RgbLedColor?,
|
|
100
|
+
val onDurationMs: Int,
|
|
101
|
+
val offDurationMs: Int,
|
|
102
|
+
val count: Int,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
data class VideoRecordingRequest(
|
|
106
|
+
val requestId: String,
|
|
107
|
+
val save: Boolean,
|
|
108
|
+
val sound: Boolean,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
data class GalleryStatusEvent(
|
|
112
|
+
val values: Map<String, Any>,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
sealed interface PhotoResponse {
|
|
116
|
+
val state: String
|
|
117
|
+
val requestId: String
|
|
118
|
+
val timestamp: Long
|
|
119
|
+
|
|
120
|
+
fun toMap(): Map<String, Any> =
|
|
121
|
+
when (this) {
|
|
122
|
+
is Success -> mapOf(
|
|
123
|
+
"state" to state,
|
|
124
|
+
"requestId" to requestId,
|
|
125
|
+
"uploadUrl" to uploadUrl,
|
|
126
|
+
"timestamp" to timestamp,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
is Error -> mutableMapOf<String, Any>(
|
|
130
|
+
"state" to state,
|
|
131
|
+
"requestId" to requestId,
|
|
132
|
+
"timestamp" to timestamp,
|
|
133
|
+
"errorMessage" to errorMessage,
|
|
134
|
+
).apply {
|
|
135
|
+
if (!errorCode.isNullOrBlank()) {
|
|
136
|
+
this["errorCode"] = errorCode
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
fun toEventMap(): Map<String, Any> = toMap() + mapOf("type" to "photo_response")
|
|
142
|
+
|
|
143
|
+
data class Success(
|
|
144
|
+
override val requestId: String,
|
|
145
|
+
val uploadUrl: String,
|
|
146
|
+
override val timestamp: Long,
|
|
147
|
+
) : PhotoResponse {
|
|
148
|
+
override val state: String = "success"
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
data class Error(
|
|
152
|
+
override val requestId: String,
|
|
153
|
+
val errorCode: String?,
|
|
154
|
+
val errorMessage: String,
|
|
155
|
+
override val timestamp: Long,
|
|
156
|
+
) : PhotoResponse {
|
|
157
|
+
override val state: String = "error"
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
companion object {
|
|
161
|
+
fun fromMap(values: Map<String, Any>): PhotoResponse {
|
|
162
|
+
val requestId = stringValue(values, "requestId").orEmpty()
|
|
163
|
+
val timestamp = longValue(values, "timestamp") ?: System.currentTimeMillis()
|
|
164
|
+
val state = stringValue(values, "state")?.lowercase()
|
|
165
|
+
return if (state == "success") {
|
|
166
|
+
val uploadUrl = stringValue(values, "uploadUrl").orEmpty()
|
|
167
|
+
Success(requestId = requestId, uploadUrl = uploadUrl, timestamp = timestamp)
|
|
168
|
+
} else {
|
|
169
|
+
Error(
|
|
170
|
+
requestId = requestId,
|
|
171
|
+
errorCode = stringValue(values, "errorCode"),
|
|
172
|
+
errorMessage = stringValue(values, "errorMessage") ?: "Unknown photo error",
|
|
173
|
+
timestamp = timestamp,
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
data class PhotoResponseEvent(
|
|
181
|
+
val response: PhotoResponse,
|
|
182
|
+
) {
|
|
183
|
+
constructor(values: Map<String, Any>) : this(PhotoResponse.fromMap(values))
|
|
184
|
+
|
|
185
|
+
val requestId: String get() = response.requestId
|
|
186
|
+
val values: Map<String, Any> get() = response.toEventMap()
|
|
187
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk
|
|
2
|
+
|
|
3
|
+
import com.mentra.bluetoothsdk.utils.ConnTypes
|
|
4
|
+
import java.util.concurrent.atomic.AtomicBoolean
|
|
5
|
+
|
|
6
|
+
enum class GlassesConnectionState(val value: String) {
|
|
7
|
+
DISCONNECTED(ConnTypes.DISCONNECTED),
|
|
8
|
+
SCANNING(ConnTypes.SCANNING),
|
|
9
|
+
CONNECTING(ConnTypes.CONNECTING),
|
|
10
|
+
BONDING(ConnTypes.BONDING),
|
|
11
|
+
CONNECTED(ConnTypes.CONNECTED);
|
|
12
|
+
|
|
13
|
+
val isConnected: Boolean
|
|
14
|
+
get() = this == CONNECTED
|
|
15
|
+
|
|
16
|
+
val isBusy: Boolean
|
|
17
|
+
get() = this == SCANNING || this == CONNECTING || this == BONDING
|
|
18
|
+
|
|
19
|
+
internal fun toStatusMap(
|
|
20
|
+
connected: Boolean,
|
|
21
|
+
fullyBooted: Boolean,
|
|
22
|
+
): Map<String, Any> =
|
|
23
|
+
when {
|
|
24
|
+
this == CONNECTED || connected || fullyBooted ->
|
|
25
|
+
mapOf("state" to "connected", "fullyBooted" to fullyBooted)
|
|
26
|
+
this == SCANNING -> mapOf("state" to "scanning")
|
|
27
|
+
this == CONNECTING -> mapOf("state" to "connecting")
|
|
28
|
+
this == BONDING -> mapOf("state" to "bonding")
|
|
29
|
+
else -> mapOf("state" to "disconnected")
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
companion object {
|
|
33
|
+
@JvmStatic
|
|
34
|
+
fun fromValue(value: String?): GlassesConnectionState =
|
|
35
|
+
optionalFromValue(value) ?: DISCONNECTED
|
|
36
|
+
|
|
37
|
+
internal fun optionalFromValue(value: String?): GlassesConnectionState? {
|
|
38
|
+
val normalized = value?.trim()?.takeIf { it.isNotEmpty() } ?: return null
|
|
39
|
+
return values().firstOrNull { it.value.equals(normalized, ignoreCase = true) }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
data class BluetoothError(
|
|
45
|
+
val code: String,
|
|
46
|
+
val message: String,
|
|
47
|
+
val cause: Throwable? = null,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
enum class ScanStopReason {
|
|
51
|
+
COMPLETED,
|
|
52
|
+
CANCELLED,
|
|
53
|
+
ERROR,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface ScanCallback {
|
|
57
|
+
fun onResults(devices: List<Device>) {}
|
|
58
|
+
fun onComplete(devices: List<Device>) {}
|
|
59
|
+
fun onError(error: BluetoothError) {}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
abstract class MentraBluetoothScanCallback : ScanCallback
|
|
63
|
+
|
|
64
|
+
class ScanSession internal constructor(
|
|
65
|
+
private val stopAction: () -> Unit,
|
|
66
|
+
) {
|
|
67
|
+
private val stopped = AtomicBoolean(false)
|
|
68
|
+
|
|
69
|
+
fun stop() {
|
|
70
|
+
if (stopped.compareAndSet(false, true)) {
|
|
71
|
+
stopAction()
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
internal fun markStopped() {
|
|
76
|
+
stopped.set(true)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk
|
|
2
|
+
|
|
3
|
+
data class ButtonPressEvent(
|
|
4
|
+
val buttonId: String,
|
|
5
|
+
val pressType: String,
|
|
6
|
+
val timestamp: Long? = null,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
data class TouchEvent(
|
|
10
|
+
val values: Map<String, Any>,
|
|
11
|
+
) {
|
|
12
|
+
val deviceModel: String? get() = stringValue(values, "deviceModel")
|
|
13
|
+
val gestureName: String? get() = stringValue(values, "gestureName")
|
|
14
|
+
val timestamp: Long? get() = longValue(values, "timestamp")
|
|
15
|
+
val isSwipe: Boolean get() = gestureName?.contains("swipe", ignoreCase = true) == true
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
data class SwipeEvent(
|
|
19
|
+
val values: Map<String, Any>,
|
|
20
|
+
) {
|
|
21
|
+
val deviceModel: String? get() = stringValue(values, "deviceModel")
|
|
22
|
+
val gestureName: String? get() = stringValue(values, "gestureName")
|
|
23
|
+
val timestamp: Long? get() = longValue(values, "timestamp")
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
data class BatteryStatusEvent(
|
|
27
|
+
val level: Int?,
|
|
28
|
+
val charging: Boolean?,
|
|
29
|
+
val values: Map<String, Any>,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
interface MentraBluetoothSdkListener {
|
|
33
|
+
fun onStateChanged(state: MentraBluetoothState) {}
|
|
34
|
+
fun onGlassesChanged(glasses: GlassesRuntimeState) {}
|
|
35
|
+
fun onSdkStateChanged(sdk: PhoneSdkRuntimeState) {}
|
|
36
|
+
fun onScanChanged(scan: BluetoothScanState) {}
|
|
37
|
+
fun onDeviceDiscovered(device: Device) {}
|
|
38
|
+
fun onScanStopped(reason: ScanStopReason) {}
|
|
39
|
+
fun onButtonPress(event: ButtonPressEvent) {}
|
|
40
|
+
fun onTouch(event: TouchEvent) {}
|
|
41
|
+
fun onSwipe(event: SwipeEvent) {}
|
|
42
|
+
fun onHeadUpChanged(headUp: Boolean) {}
|
|
43
|
+
fun onBatteryStatus(event: BatteryStatusEvent) {}
|
|
44
|
+
fun onWifiStatusChanged(event: WifiStatusEvent) {}
|
|
45
|
+
fun onHotspotStatusChanged(event: HotspotStatusEvent) {}
|
|
46
|
+
fun onHotspotError(event: HotspotErrorEvent) {}
|
|
47
|
+
fun onGalleryStatus(event: GalleryStatusEvent) {}
|
|
48
|
+
fun onPhotoResponse(event: PhotoResponseEvent) {}
|
|
49
|
+
fun onStreamStatus(event: StreamStatusEvent) {}
|
|
50
|
+
fun onKeepAliveAck(event: KeepAliveAckEvent) {}
|
|
51
|
+
fun onMicPcm(event: MicPcmEvent) {}
|
|
52
|
+
fun onMicLc3(event: MicLc3Event) {}
|
|
53
|
+
fun onLocalTranscription(event: LocalTranscriptionEvent) {}
|
|
54
|
+
fun onDefaultDeviceChanged(device: Device?) {}
|
|
55
|
+
fun onLog(message: String) {}
|
|
56
|
+
fun onError(error: BluetoothError) {}
|
|
57
|
+
fun onRawEvent(eventName: String, values: Map<String, Any>) {}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
abstract class MentraBluetoothSdkCallback : MentraBluetoothSdkListener
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk
|
|
2
|
+
|
|
3
|
+
internal fun numberValue(
|
|
4
|
+
values: Map<String, Any>,
|
|
5
|
+
vararg keys: String,
|
|
6
|
+
): Int? =
|
|
7
|
+
keys.firstNotNullOfOrNull { key ->
|
|
8
|
+
(values[key] as? Number)?.toInt()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
internal fun stringValue(
|
|
12
|
+
values: Map<String, Any>,
|
|
13
|
+
vararg keys: String,
|
|
14
|
+
): String? =
|
|
15
|
+
keys.firstNotNullOfOrNull { key ->
|
|
16
|
+
values[key]?.let { it as? String }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
internal fun boolValue(
|
|
20
|
+
values: Map<String, Any>,
|
|
21
|
+
vararg keys: String,
|
|
22
|
+
): Boolean? =
|
|
23
|
+
keys.firstNotNullOfOrNull { key ->
|
|
24
|
+
values[key] as? Boolean
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
internal fun longValue(
|
|
28
|
+
values: Map<String, Any>,
|
|
29
|
+
vararg keys: String,
|
|
30
|
+
): Long? =
|
|
31
|
+
keys.firstNotNullOfOrNull { key ->
|
|
32
|
+
(values[key] as? Number)?.toLong()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
internal fun hasAnyKey(
|
|
36
|
+
values: Map<String, Any>,
|
|
37
|
+
vararg keys: String,
|
|
38
|
+
): Boolean = keys.any(values::containsKey)
|
|
39
|
+
|
|
40
|
+
internal fun Map<*, *>.stringKeyedMap(): Map<String, Any> =
|
|
41
|
+
entries.mapNotNull { (key, value) ->
|
|
42
|
+
val stringKey = key as? String ?: return@mapNotNull null
|
|
43
|
+
val anyValue = value ?: return@mapNotNull null
|
|
44
|
+
stringKey to anyValue
|
|
45
|
+
}.toMap()
|
|
46
|
+
|
|
47
|
+
internal fun optionalNumberValue(
|
|
48
|
+
values: Map<String, Any>,
|
|
49
|
+
vararg keys: String,
|
|
50
|
+
): Int? =
|
|
51
|
+
if (hasAnyKey(values, *keys)) {
|
|
52
|
+
numberValue(values, *keys)
|
|
53
|
+
} else {
|
|
54
|
+
null
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
internal fun optionalLongValue(
|
|
58
|
+
values: Map<String, Any>,
|
|
59
|
+
vararg keys: String,
|
|
60
|
+
): Long? =
|
|
61
|
+
if (hasAnyKey(values, *keys)) {
|
|
62
|
+
longValue(values, *keys)
|
|
63
|
+
} else {
|
|
64
|
+
null
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
internal fun optionalStringValue(
|
|
68
|
+
values: Map<String, Any>,
|
|
69
|
+
vararg keys: String,
|
|
70
|
+
): String? =
|
|
71
|
+
if (hasAnyKey(values, *keys)) {
|
|
72
|
+
stringValue(values, *keys)
|
|
73
|
+
} else {
|
|
74
|
+
null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
internal fun optionalBoolValue(
|
|
78
|
+
values: Map<String, Any>,
|
|
79
|
+
vararg keys: String,
|
|
80
|
+
): Boolean? =
|
|
81
|
+
if (hasAnyKey(values, *keys)) {
|
|
82
|
+
boolValue(values, *keys)
|
|
83
|
+
} else {
|
|
84
|
+
null
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
internal fun stringListValue(
|
|
88
|
+
values: Map<String, Any>,
|
|
89
|
+
key: String,
|
|
90
|
+
): List<String> = (values[key] as? List<*>)?.mapNotNull { it as? String } ?: emptyList()
|
|
91
|
+
|
|
92
|
+
internal fun optionalStringListValue(
|
|
93
|
+
values: Map<String, Any>,
|
|
94
|
+
key: String,
|
|
95
|
+
): List<String>? =
|
|
96
|
+
if (values.containsKey(key)) {
|
|
97
|
+
stringListValue(values, key)
|
|
98
|
+
} else {
|
|
99
|
+
null
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
internal fun mapListValue(
|
|
103
|
+
values: Map<String, Any>,
|
|
104
|
+
key: String,
|
|
105
|
+
): List<Map<String, Any>> =
|
|
106
|
+
(values[key] as? List<*>)?.mapNotNull(::stringMapValue) ?: emptyList()
|
|
107
|
+
|
|
108
|
+
internal fun optionalMapListValue(
|
|
109
|
+
values: Map<String, Any>,
|
|
110
|
+
key: String,
|
|
111
|
+
): List<Map<String, Any>>? =
|
|
112
|
+
if (values.containsKey(key)) {
|
|
113
|
+
mapListValue(values, key)
|
|
114
|
+
} else {
|
|
115
|
+
null
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
internal fun stringMapValue(value: Any?): Map<String, Any>? =
|
|
119
|
+
(value as? Map<*, *>)?.entries?.mapNotNull { (key, mapValue) ->
|
|
120
|
+
val stringKey = key as? String ?: return@mapNotNull null
|
|
121
|
+
val nonNullValue = mapValue ?: return@mapNotNull null
|
|
122
|
+
stringKey to nonNullValue
|
|
123
|
+
}?.toMap()
|
|
124
|
+
|
|
125
|
+
internal fun MutableMap<String, Any>.putIfNotNull(
|
|
126
|
+
key: String,
|
|
127
|
+
value: Any?,
|
|
128
|
+
) {
|
|
129
|
+
if (value != null) {
|
|
130
|
+
put(key, value)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk
|
|
2
|
+
|
|
3
|
+
data class DisplayTextRequest(
|
|
4
|
+
val text: String,
|
|
5
|
+
val x: Int = 0,
|
|
6
|
+
val y: Int = 0,
|
|
7
|
+
val size: Int = 24,
|
|
8
|
+
) {
|
|
9
|
+
fun toMap(): Map<String, Any> =
|
|
10
|
+
mapOf(
|
|
11
|
+
"text" to text,
|
|
12
|
+
"x" to x,
|
|
13
|
+
"y" to y,
|
|
14
|
+
"size" to size,
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
internal data class DisplayEventRequest(
|
|
19
|
+
val values: Map<String, Any>,
|
|
20
|
+
) {
|
|
21
|
+
fun toMap(): Map<String, Any> = values
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
data class DashboardPositionRequest(
|
|
25
|
+
val height: Int,
|
|
26
|
+
val depth: Int,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
internal data class DashboardMenuItem(
|
|
30
|
+
val title: String,
|
|
31
|
+
val packageName: String,
|
|
32
|
+
val values: Map<String, Any> = emptyMap(),
|
|
33
|
+
) {
|
|
34
|
+
fun toMap(): Map<String, Any> =
|
|
35
|
+
values + mapOf(
|
|
36
|
+
"title" to title,
|
|
37
|
+
"packageName" to packageName,
|
|
38
|
+
)
|
|
39
|
+
}
|