@mentra/bluetooth-sdk 0.1.21-beta.3 → 0.1.21-beta.5
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/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +11 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/BesOtaHeartbeatGuard.kt +49 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/BesOtaProgressMapper.kt +27 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.kt +207 -93
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/BesOtaHeartbeatGuardTest.kt +73 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/sgcs/BesOtaProgressMapperTest.kt +67 -0
- package/build/BluetoothSdk.types.d.ts +2 -0
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- package/ios/Source/BluetoothSdkDefaults.swift +1 -1
- package/ios/Source/DeviceManager.swift +11 -6
- package/ios/Source/sgcs/MentraLive.swift +59 -47
- package/package.json +1 -1
- package/src/BluetoothSdk.types.ts +2 -0
|
@@ -948,15 +948,20 @@ class DeviceManager {
|
|
|
948
948
|
|
|
949
949
|
when (currentViewState.layoutType) {
|
|
950
950
|
"text_wall" -> {
|
|
951
|
-
sgc?.sendTextWall(currentViewState.text)
|
|
951
|
+
sgc?.sendTextWall(parsePlaceholders(currentViewState.text))
|
|
952
952
|
}
|
|
953
953
|
|
|
954
954
|
"double_text_wall" -> {
|
|
955
|
-
sgc?.sendDoubleTextWall(
|
|
955
|
+
sgc?.sendDoubleTextWall(
|
|
956
|
+
parsePlaceholders(currentViewState.topText),
|
|
957
|
+
parsePlaceholders(currentViewState.bottomText)
|
|
958
|
+
)
|
|
956
959
|
}
|
|
957
960
|
|
|
958
961
|
"reference_card" -> {
|
|
959
|
-
|
|
962
|
+
val title = parsePlaceholders(currentViewState.title)
|
|
963
|
+
val text = parsePlaceholders(currentViewState.text)
|
|
964
|
+
sgc?.sendTextWall("$title\n\n$text")
|
|
960
965
|
}
|
|
961
966
|
|
|
962
967
|
"bitmap_view" -> {
|
|
@@ -973,7 +978,7 @@ class DeviceManager {
|
|
|
973
978
|
|
|
974
979
|
"positioned_text" -> {
|
|
975
980
|
sgc?.sendPositionedText(
|
|
976
|
-
currentViewState.text,
|
|
981
|
+
parsePlaceholders(currentViewState.text),
|
|
977
982
|
currentViewState.bmpX ?: 0,
|
|
978
983
|
currentViewState.bmpY ?: 0,
|
|
979
984
|
currentViewState.bmpWidth ?: 576,
|
|
@@ -994,6 +999,8 @@ class DeviceManager {
|
|
|
994
999
|
}
|
|
995
1000
|
|
|
996
1001
|
private fun parsePlaceholders(text: String): String {
|
|
1002
|
+
if (!text.contains('$')) return text
|
|
1003
|
+
|
|
997
1004
|
val dateFormatter = SimpleDateFormat("M/dd, h:mm", Locale.getDefault())
|
|
998
1005
|
val formattedDate = dateFormatter.format(Date())
|
|
999
1006
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk.sgcs
|
|
2
|
+
|
|
3
|
+
import java.util.Locale
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Temporarily suppresses phone heartbeats while BES OTA owns the ASG-to-BES UART.
|
|
7
|
+
*
|
|
8
|
+
* The lease is renewable so a lost terminal status cannot disable heartbeats permanently. It is
|
|
9
|
+
* deliberately longer than ASG's 30-second BES response watchdog: after the lease expires, the
|
|
10
|
+
* raw transfer has already completed or failed and ordinary UART liveness traffic is safe again.
|
|
11
|
+
*/
|
|
12
|
+
internal class BesOtaHeartbeatGuard(
|
|
13
|
+
private val leaseDurationMs: Long = DEFAULT_LEASE_DURATION_MS,
|
|
14
|
+
) {
|
|
15
|
+
@Volatile private var suppressionDeadlineMs = 0L
|
|
16
|
+
|
|
17
|
+
init {
|
|
18
|
+
require(leaseDurationMs > 0) { "leaseDurationMs must be positive" }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
fun refresh(nowMs: Long) {
|
|
22
|
+
suppressionDeadlineMs =
|
|
23
|
+
if (nowMs > Long.MAX_VALUE - leaseDurationMs) Long.MAX_VALUE
|
|
24
|
+
else nowMs + leaseDurationMs
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
fun clear() {
|
|
28
|
+
suppressionDeadlineMs = 0L
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
fun observeOtaStatus(stepType: String, phase: String, status: String, nowMs: Long) {
|
|
32
|
+
if (!stepType.equals("bes", ignoreCase = true) ||
|
|
33
|
+
!phase.equals("install", ignoreCase = true)
|
|
34
|
+
) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
when (status.lowercase(Locale.US)) {
|
|
39
|
+
"failed", "complete", "step_complete", "finished", "success" -> clear()
|
|
40
|
+
else -> refresh(nowMs)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
fun shouldSuppress(nowMs: Long): Boolean = nowMs < suppressionDeadlineMs
|
|
45
|
+
|
|
46
|
+
companion object {
|
|
47
|
+
internal const val DEFAULT_LEASE_DURATION_MS = 120_000L
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk.sgcs
|
|
2
|
+
|
|
3
|
+
internal data class BesOtaProgressMapping(
|
|
4
|
+
val status: String,
|
|
5
|
+
val progress: Int,
|
|
6
|
+
val errorMessage: String? = null,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
/** Map the BES sr_adota protocol without inferring terminal state from transfer progress. */
|
|
10
|
+
internal fun mapBesOtaProgress(
|
|
11
|
+
type: String,
|
|
12
|
+
rawProgress: Int,
|
|
13
|
+
message: String?,
|
|
14
|
+
): BesOtaProgressMapping {
|
|
15
|
+
val roundedProgress = (((rawProgress.coerceIn(0, 100) + 2) / 5) * 5).coerceAtMost(100)
|
|
16
|
+
return when {
|
|
17
|
+
type == "success" -> BesOtaProgressMapping("FINISHED", 100)
|
|
18
|
+
type == "error" || type == "fail" ->
|
|
19
|
+
BesOtaProgressMapping(
|
|
20
|
+
"FAILED",
|
|
21
|
+
roundedProgress,
|
|
22
|
+
message?.takeIf { it.isNotBlank() } ?: "BES update failed",
|
|
23
|
+
)
|
|
24
|
+
// A raw update:100 is emitted before whole-image CRC/apply and is not terminal.
|
|
25
|
+
else -> BesOtaProgressMapping("PROGRESS", minOf(roundedProgress, 95))
|
|
26
|
+
}
|
|
27
|
+
}
|