@mentra/bluetooth-sdk 0.1.12 → 0.1.13
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 +16 -9
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +51 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +73 -21
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +190 -26
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdkDebug.kt +14 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/ObservableStore.kt +20 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/OtaManifest.kt +153 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/camera/CameraModels.kt +78 -10
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/ControllerManager.kt +3 -14
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/R1.kt +3 -6
- package/android/src/main/java/com/mentra/bluetoothsdk/services/PhoneMic.kt +90 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.kt +3835 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +20 -23
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/{Mach1.java → Mach1.kt} +517 -560
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.kt +8712 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +11 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +3 -13
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Simulated.kt +7 -14
- package/build/BluetoothSdk.types.d.ts +39 -9
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_private/BluetoothSdkModule.d.ts +8 -6
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
- package/build/_private/BluetoothSdkModule.js +0 -2
- package/build/_private/BluetoothSdkModule.js.map +1 -1
- package/build/_private/photoRequestPayload.d.ts +3 -1
- package/build/_private/photoRequestPayload.d.ts.map +1 -1
- package/build/_private/photoRequestPayload.js +43 -1
- package/build/_private/photoRequestPayload.js.map +1 -1
- package/build/debug.d.ts +3 -0
- package/build/debug.d.ts.map +1 -0
- package/build/debug.js +8 -0
- package/build/debug.js.map +1 -0
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +14 -5
- package/build/index.js.map +1 -1
- package/ios/BluetoothSdkModule.swift +38 -57
- package/ios/Source/BluetoothSdkDefaults.swift +23 -3
- package/ios/Source/DeviceManager.swift +37 -26
- package/ios/Source/DeviceStore.swift +5 -1
- package/ios/Source/MentraBluetoothSDK.swift +197 -26
- package/ios/Source/MentraBluetoothSDKDebug.swift +12 -0
- package/ios/Source/ObservableStore.swift +11 -0
- package/ios/Source/OtaManifest.swift +170 -0
- package/ios/Source/camera/CameraModels.swift +218 -8
- package/ios/Source/controllers/ControllerManager.swift +2 -5
- package/ios/Source/controllers/R1.swift +2 -5
- package/ios/Source/sgcs/G1.swift +6 -5
- package/ios/Source/sgcs/G2.swift +20 -18
- package/ios/Source/sgcs/Mach1.swift +6 -5
- package/ios/Source/sgcs/MentraLive.swift +129 -33
- package/ios/Source/sgcs/MentraNex.swift +6 -5
- package/ios/Source/sgcs/SGCManager.swift +3 -5
- package/ios/Source/sgcs/Simulated.swift +7 -3
- package/ios/Source/status/DeviceStatus.swift +1 -1
- package/package.json +6 -1
- package/src/BluetoothSdk.types.ts +40 -9
- package/src/_private/BluetoothSdkModule.ts +8 -9
- package/src/_private/photoRequestPayload.ts +45 -2
- package/src/debug.ts +9 -0
- package/src/index.ts +23 -6
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.java +0 -3974
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.java +0 -7434
|
@@ -1,608 +1,601 @@
|
|
|
1
|
-
package com.mentra.bluetoothsdk.sgcs
|
|
2
|
-
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import android.content.res.Resources
|
|
5
|
-
import android.graphics.Bitmap
|
|
6
|
-
import android.graphics.BitmapFactory
|
|
7
|
-
import android.graphics.drawable.Drawable
|
|
8
|
-
import android.os.Handler
|
|
9
|
-
import android.os.Looper
|
|
10
|
-
import android.util.Log
|
|
11
|
-
|
|
12
|
-
import androidx.
|
|
13
|
-
import androidx.
|
|
14
|
-
import androidx.lifecycle.LiveData;
|
|
15
|
-
import androidx.lifecycle.Observer;
|
|
1
|
+
package com.mentra.bluetoothsdk.sgcs
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.content.res.Resources
|
|
5
|
+
import android.graphics.Bitmap
|
|
6
|
+
import android.graphics.BitmapFactory
|
|
7
|
+
import android.graphics.drawable.Drawable
|
|
8
|
+
import android.os.Handler
|
|
9
|
+
import android.os.Looper
|
|
10
|
+
import android.util.Log
|
|
11
|
+
|
|
12
|
+
import androidx.lifecycle.LiveData
|
|
13
|
+
import androidx.lifecycle.Observer
|
|
16
14
|
|
|
17
15
|
// Mentra
|
|
18
|
-
import com.mentra.bluetoothsdk.
|
|
19
|
-
import com.mentra.bluetoothsdk.
|
|
20
|
-
import com.mentra.bluetoothsdk.
|
|
21
|
-
import com.mentra.bluetoothsdk.utils.DeviceTypes
|
|
22
|
-
import com.mentra.bluetoothsdk.utils.ConnTypes
|
|
23
|
-
import com.mentra.bluetoothsdk.utils.BitmapJavaUtils
|
|
24
|
-
import com.mentra.bluetoothsdk.utils.SmartGlassesConnectionState
|
|
25
|
-
import com.mentra.bluetoothsdk.utils.K900ProtocolUtils
|
|
26
|
-
import com.mentra.bluetoothsdk.utils.MessageChunker
|
|
27
|
-
import com.mentra.bluetoothsdk.utils.audio.Lc3Player
|
|
28
|
-
import com.mentra.bluetoothsdk.utils.BlePhotoUploadService
|
|
29
|
-
import com.mentra.bluetoothsdk.DeviceStore
|
|
16
|
+
import com.mentra.bluetoothsdk.DeviceManager
|
|
17
|
+
import com.mentra.bluetoothsdk.Bridge
|
|
18
|
+
import com.mentra.bluetoothsdk.PhotoRequest
|
|
19
|
+
import com.mentra.bluetoothsdk.utils.DeviceTypes
|
|
20
|
+
import com.mentra.bluetoothsdk.utils.ConnTypes
|
|
21
|
+
import com.mentra.bluetoothsdk.utils.BitmapJavaUtils
|
|
22
|
+
import com.mentra.bluetoothsdk.utils.SmartGlassesConnectionState
|
|
23
|
+
import com.mentra.bluetoothsdk.utils.K900ProtocolUtils
|
|
24
|
+
import com.mentra.bluetoothsdk.utils.MessageChunker
|
|
25
|
+
import com.mentra.bluetoothsdk.utils.audio.Lc3Player
|
|
26
|
+
import com.mentra.bluetoothsdk.utils.BlePhotoUploadService
|
|
27
|
+
import com.mentra.bluetoothsdk.DeviceStore
|
|
30
28
|
|
|
31
29
|
// import com.augmentos.augmentos_core.R;
|
|
32
30
|
// import com.augmentos.augmentos_core.smarterglassesmanager.smartglassescommunicators.SmartGlassesCommunicator;
|
|
33
31
|
// import com.augmentos.augmentos_core.smarterglassesmanager.smartglassescommunicators.SmartGlassesFontSize;
|
|
34
32
|
// import com.augmentos.augmentos_core.smarterglassesmanager.utils.SmartGlassesConnectionState;
|
|
35
|
-
import com.squareup.picasso.Picasso
|
|
36
|
-
import com.squareup.picasso.Target
|
|
33
|
+
import com.squareup.picasso.Picasso
|
|
34
|
+
import com.squareup.picasso.Target
|
|
37
35
|
// import com.augmentos.augmentos_core.smarterglassesmanager.eventbusmessages.BatteryLevelEvent;
|
|
38
36
|
// import com.augmentos.augmentos_core.smarterglassesmanager.eventbusmessages.GlassesBluetoothSearchDiscoverEvent;
|
|
39
37
|
// import com.augmentos.augmentos_core.smarterglassesmanager.eventbusmessages.GlassesDisplayPowerEvent;
|
|
40
38
|
// import com.augmentos.augmentos_core.smarterglassesmanager.supportedglasses.SmartGlassesDevice;
|
|
41
|
-
import com.vuzix.ultralite.Anchor
|
|
42
|
-
import com.vuzix.ultralite.BatteryStatus
|
|
43
|
-
import com.vuzix.ultralite.EventListener
|
|
44
|
-
import com.vuzix.ultralite.Layout
|
|
45
|
-
import com.vuzix.ultralite.TextAlignment
|
|
46
|
-
import com.vuzix.ultralite.TextWrapMode
|
|
47
|
-
import com.vuzix.ultralite.UltraliteColor
|
|
48
|
-
import com.vuzix.ultralite.UltraliteSDK
|
|
39
|
+
import com.vuzix.ultralite.Anchor
|
|
40
|
+
import com.vuzix.ultralite.BatteryStatus
|
|
41
|
+
import com.vuzix.ultralite.EventListener
|
|
42
|
+
import com.vuzix.ultralite.Layout
|
|
43
|
+
import com.vuzix.ultralite.TextAlignment
|
|
44
|
+
import com.vuzix.ultralite.TextWrapMode
|
|
45
|
+
import com.vuzix.ultralite.UltraliteColor
|
|
46
|
+
import com.vuzix.ultralite.UltraliteSDK
|
|
49
47
|
|
|
50
|
-
import org.greenrobot.eventbus.EventBus
|
|
48
|
+
import org.greenrobot.eventbus.EventBus
|
|
51
49
|
|
|
52
|
-
import java.util.ArrayList
|
|
53
|
-
import java.util.Arrays
|
|
54
|
-
import java.util.Collections
|
|
55
|
-
import java.util.List;
|
|
56
|
-
import java.util.Map;
|
|
50
|
+
import java.util.ArrayList
|
|
51
|
+
import java.util.Arrays
|
|
52
|
+
import java.util.Collections
|
|
57
53
|
|
|
58
54
|
|
|
59
55
|
//communicate with ActiveLook smart glasses
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
class Mach1 : SGCManager() {
|
|
57
|
+
|
|
58
|
+
companion object {
|
|
59
|
+
private const val TAG = "WearableAi_UltraliteSGC"
|
|
60
|
+
const val cardLingerTime = 15
|
|
61
|
+
|
|
62
|
+
private const val TAP_DEBOUNCE_TIME = 80L // milliseconds
|
|
63
|
+
|
|
64
|
+
@JvmStatic
|
|
65
|
+
fun maybeReverseRTLString(text: String): String {
|
|
66
|
+
val result = StringBuilder()
|
|
67
|
+
val rtlBuffer = StringBuilder()
|
|
68
|
+
|
|
69
|
+
for (c in text.toCharArray()) {
|
|
70
|
+
if (isRTLCharacter(c)) {
|
|
71
|
+
rtlBuffer.append(c) // Append RTL characters to a buffer
|
|
72
|
+
} else {
|
|
73
|
+
if (rtlBuffer.length > 0) {
|
|
74
|
+
result.append(rtlBuffer.reverse()) // Reverse and append RTL text when a non-RTL character is found
|
|
75
|
+
rtlBuffer.setLength(0) // Clear the buffer
|
|
76
|
+
}
|
|
77
|
+
result.append(c) // Append non-RTL characters directly to the result
|
|
78
|
+
}
|
|
79
|
+
}
|
|
62
80
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
Layout currentUltraliteLayout;
|
|
67
|
-
boolean screenToggleOff = false; //should we keep the screen off?
|
|
68
|
-
Context context;
|
|
69
|
-
public static final int cardLingerTime = 15;
|
|
81
|
+
if (rtlBuffer.length > 0) {
|
|
82
|
+
result.append(rtlBuffer.reverse()) // Append any remaining RTL text in reverse
|
|
83
|
+
}
|
|
70
84
|
|
|
71
|
-
|
|
85
|
+
return result.toString()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private fun isRTLCharacter(c: Char): Boolean {
|
|
89
|
+
val block = Character.UnicodeBlock.of(c)
|
|
90
|
+
return block == Character.UnicodeBlock.ARABIC ||
|
|
91
|
+
block == Character.UnicodeBlock.HEBREW ||
|
|
92
|
+
block == Character.UnicodeBlock.SYRIAC ||
|
|
93
|
+
block == Character.UnicodeBlock.ARABIC_SUPPLEMENT ||
|
|
94
|
+
block == Character.UnicodeBlock.THAANA ||
|
|
95
|
+
block == Character.UnicodeBlock.NKO ||
|
|
96
|
+
block == Character.UnicodeBlock.SAMARITAN ||
|
|
97
|
+
block == Character.UnicodeBlock.MANDAIC ||
|
|
98
|
+
block == Character.UnicodeBlock.ARABIC_EXTENDED_A
|
|
99
|
+
// Add other RTL blocks as needed
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
var ultraliteSdk: UltraliteSDK? = null
|
|
104
|
+
var ultraliteCanvas: UltraliteSDK.Canvas? = null
|
|
105
|
+
var ultraliteListener: UltraliteListener? = null
|
|
106
|
+
var currentUltraliteLayout: Layout? = null
|
|
107
|
+
var screenToggleOff = false //should we keep the screen off?
|
|
108
|
+
var context: Context? = null
|
|
109
|
+
|
|
110
|
+
private var rowTextsLiveNow: ArrayList<Int>? = null
|
|
72
111
|
|
|
73
112
|
//ultralite pixel buffer on left side of screen
|
|
74
|
-
|
|
113
|
+
var ultraliteLeftSidePixelBuffer = 40
|
|
75
114
|
|
|
76
115
|
//handler to turn off screen
|
|
77
|
-
Handler
|
|
78
|
-
Runnable
|
|
116
|
+
var goHomeHandler: Handler? = null
|
|
117
|
+
var goHomeRunnable: Runnable? = null
|
|
79
118
|
|
|
80
119
|
//handler to turn off screen/toggle
|
|
81
|
-
Handler
|
|
82
|
-
Runnable
|
|
120
|
+
var screenOffHandler: Handler? = null
|
|
121
|
+
var screenOffRunnable: Runnable? = null
|
|
83
122
|
|
|
84
123
|
//handler to check battery life
|
|
85
|
-
Handler
|
|
86
|
-
Runnable
|
|
124
|
+
var batteryHandler: Handler? = null
|
|
125
|
+
var batteryRunnable: Runnable? = null
|
|
87
126
|
|
|
88
127
|
//handler to disconnect
|
|
89
|
-
Handler
|
|
128
|
+
var killHandler: Handler? = null
|
|
90
129
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
130
|
+
var hasUltraliteControl = false
|
|
131
|
+
var screenIsClear = false
|
|
132
|
+
var isHeadUp = false // Dashboard state toggled by taps
|
|
94
133
|
// SmartGlassesDevice smartGlassesDevice;
|
|
95
|
-
private
|
|
96
|
-
private
|
|
97
|
-
private int totalDashboardsIdk = 0;
|
|
134
|
+
private var lastTapTime = 0L
|
|
135
|
+
private var totalDashboardsIdk = 0
|
|
98
136
|
|
|
99
|
-
private
|
|
100
|
-
|
|
101
|
-
return level
|
|
137
|
+
private fun hasBattery(): Boolean {
|
|
138
|
+
val level = DeviceStore.get("glasses", "batteryLevel")
|
|
139
|
+
return level is Number && level.toInt() != -1
|
|
102
140
|
}
|
|
103
141
|
|
|
104
|
-
private
|
|
105
|
-
|
|
142
|
+
private fun updateConnectionState(state: String) {
|
|
143
|
+
val isEqual = state == connectionState
|
|
106
144
|
if (isEqual) {
|
|
107
|
-
return
|
|
145
|
+
return
|
|
108
146
|
}
|
|
109
147
|
|
|
110
148
|
// Update the connection state
|
|
111
|
-
DeviceStore.
|
|
149
|
+
DeviceStore.apply("glasses", "connectionState", state)
|
|
112
150
|
|
|
113
|
-
if (state
|
|
151
|
+
if (state == ConnTypes.CONNECTED) {
|
|
114
152
|
// Match iOS: only declare fully booted once we have battery info too
|
|
115
153
|
if (hasBattery()) {
|
|
116
|
-
DeviceStore.
|
|
117
|
-
DeviceStore.
|
|
154
|
+
DeviceStore.apply("glasses", "connected", true)
|
|
155
|
+
DeviceStore.apply("glasses", "fullyBooted", true)
|
|
118
156
|
}
|
|
119
|
-
} else if (state
|
|
120
|
-
DeviceStore.
|
|
121
|
-
DeviceStore.
|
|
157
|
+
} else if (state == ConnTypes.DISCONNECTED) {
|
|
158
|
+
DeviceStore.apply("glasses", "fullyBooted", false)
|
|
159
|
+
DeviceStore.apply("glasses", "connected", false)
|
|
122
160
|
}
|
|
123
161
|
}
|
|
124
162
|
|
|
125
|
-
|
|
126
|
-
public void setMicEnabled(boolean enabled) {
|
|
163
|
+
override fun setMicEnabled(enabled: Boolean) {
|
|
127
164
|
}
|
|
128
165
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return list;
|
|
166
|
+
override fun sortMicRanking(list: MutableList<String>): MutableList<String> {
|
|
167
|
+
return list
|
|
132
168
|
}
|
|
133
169
|
|
|
134
|
-
|
|
135
|
-
public void requestPhoto(@NonNull String requestId, @NonNull String appId, @NonNull String size, @Nullable String webhookUrl, @Nullable String authToken, @Nullable String compress, boolean flash, boolean save, boolean sound, @Nullable Long exposureTimeNs, @Nullable Integer iso) {
|
|
170
|
+
override fun requestPhoto(request: PhotoRequest) {
|
|
136
171
|
|
|
137
172
|
}
|
|
138
173
|
|
|
139
|
-
|
|
140
|
-
public void startStream(@NonNull Map<String, Object> message) {
|
|
174
|
+
override fun startStream(message: MutableMap<String, Any>) {
|
|
141
175
|
|
|
142
176
|
}
|
|
143
177
|
|
|
144
|
-
|
|
145
|
-
public void stopStream() {
|
|
178
|
+
override fun stopStream() {
|
|
146
179
|
|
|
147
180
|
}
|
|
148
181
|
|
|
149
|
-
|
|
150
|
-
public void sendStreamKeepAlive(@NonNull Map<String, Object> message) {
|
|
182
|
+
override fun sendStreamKeepAlive(message: MutableMap<String, Any>) {
|
|
151
183
|
|
|
152
184
|
}
|
|
153
185
|
|
|
154
|
-
|
|
155
|
-
public void startVideoRecording(@NonNull String requestId, boolean save, boolean flash, boolean sound) {
|
|
186
|
+
override fun startVideoRecording(requestId: String, save: Boolean, flash: Boolean, sound: Boolean) {
|
|
156
187
|
|
|
157
188
|
}
|
|
158
189
|
|
|
159
|
-
|
|
160
|
-
public void stopVideoRecording(@NonNull String requestId) {
|
|
190
|
+
override fun stopVideoRecording(requestId: String) {
|
|
161
191
|
|
|
162
192
|
}
|
|
163
193
|
|
|
164
|
-
|
|
165
|
-
public void sendButtonPhotoSettings() {
|
|
194
|
+
override fun sendButtonPhotoSettings() {
|
|
166
195
|
|
|
167
196
|
}
|
|
168
197
|
|
|
169
|
-
|
|
170
|
-
public void sendButtonVideoRecordingSettings() {
|
|
198
|
+
override fun sendButtonVideoRecordingSettings() {
|
|
171
199
|
|
|
172
200
|
}
|
|
173
201
|
|
|
174
|
-
|
|
175
|
-
public void sendButtonMaxRecordingTime() {
|
|
202
|
+
override fun sendButtonMaxRecordingTime() {
|
|
176
203
|
|
|
177
204
|
}
|
|
178
205
|
|
|
179
|
-
|
|
180
|
-
|
|
206
|
+
override fun sendButtonCameraLedSetting() {
|
|
207
|
+
|
|
208
|
+
}
|
|
181
209
|
|
|
210
|
+
override fun sendCameraFovSetting() {
|
|
182
211
|
}
|
|
183
212
|
|
|
184
|
-
|
|
185
|
-
|
|
213
|
+
override fun setBrightness(level: Int, autoMode: Boolean) {
|
|
214
|
+
Bridge.log("Mach1: setBrightness() - level: " + level + "%, autoMode: " + autoMode)
|
|
215
|
+
updateGlassesBrightness(level)
|
|
216
|
+
updateGlassesAutoBrightness(autoMode)
|
|
186
217
|
}
|
|
187
218
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
updateGlassesBrightness(level);
|
|
192
|
-
updateGlassesAutoBrightness(autoMode);
|
|
219
|
+
override fun clearDisplay() {
|
|
220
|
+
Bridge.log("Mach1: clearDisplay()")
|
|
221
|
+
blankScreen()
|
|
193
222
|
}
|
|
194
223
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
blankScreen();
|
|
224
|
+
override fun sendText(text: String) {
|
|
225
|
+
Bridge.log("Mach1: sendText() - text: " + text)
|
|
226
|
+
displayTextWall(text)
|
|
199
227
|
}
|
|
200
228
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
displayTextWall(text);
|
|
229
|
+
override fun sendTextWall(text: String) {
|
|
230
|
+
Bridge.log("Mach1: sendTextWall()")
|
|
231
|
+
displayTextWall(text)
|
|
205
232
|
}
|
|
206
233
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
displayDoubleTextWall(top, bottom);
|
|
234
|
+
override fun sendDoubleTextWall(top: String, bottom: String) {
|
|
235
|
+
Bridge.log("Mach1: sendDoubleTextWall()")
|
|
236
|
+
displayDoubleTextWall(top, bottom)
|
|
211
237
|
}
|
|
212
238
|
|
|
213
|
-
|
|
214
|
-
public boolean displayBitmap(@NonNull String base64ImageData, Integer x, Integer y, Integer width, Integer height) {
|
|
239
|
+
override fun displayBitmap(base64ImageData: String, x: Int?, y: Int?, width: Int?, height: Int?): Boolean {
|
|
215
240
|
try {
|
|
216
|
-
Bridge.log("Mach1: displayBitmap() - decoding base64")
|
|
241
|
+
Bridge.log("Mach1: displayBitmap() - decoding base64")
|
|
217
242
|
// Decode base64 to byte array
|
|
218
|
-
|
|
243
|
+
val bmpData = android.util.Base64.decode(base64ImageData, android.util.Base64.DEFAULT)
|
|
219
244
|
|
|
220
|
-
if (bmpData == null || bmpData.
|
|
221
|
-
Log.e(TAG, "Failed to decode base64 image data")
|
|
222
|
-
return false
|
|
245
|
+
if (bmpData == null || bmpData.isEmpty()) {
|
|
246
|
+
Log.e(TAG, "Failed to decode base64 image data")
|
|
247
|
+
return false
|
|
223
248
|
}
|
|
224
249
|
|
|
225
250
|
// Convert byte array to Bitmap
|
|
226
|
-
|
|
251
|
+
val bitmap = BitmapFactory.decodeByteArray(bmpData, 0, bmpData.size)
|
|
227
252
|
|
|
228
253
|
if (bitmap == null) {
|
|
229
|
-
Log.e(TAG, "Failed to decode bitmap from byte array")
|
|
230
|
-
return false
|
|
254
|
+
Log.e(TAG, "Failed to decode bitmap from byte array")
|
|
255
|
+
return false
|
|
231
256
|
}
|
|
232
257
|
|
|
233
258
|
// Call internal implementation
|
|
234
|
-
displayBitmap(bitmap)
|
|
235
|
-
return true
|
|
236
|
-
} catch (Exception
|
|
237
|
-
Log.e(TAG, "Error displaying bitmap from base64", e)
|
|
238
|
-
return false
|
|
259
|
+
displayBitmap(bitmap)
|
|
260
|
+
return true
|
|
261
|
+
} catch (e: Exception) {
|
|
262
|
+
Log.e(TAG, "Error displaying bitmap from base64", e)
|
|
263
|
+
return false
|
|
239
264
|
}
|
|
240
265
|
}
|
|
241
266
|
|
|
242
|
-
|
|
243
|
-
public void showDashboard() {
|
|
267
|
+
override fun showDashboard() {
|
|
244
268
|
|
|
245
269
|
}
|
|
246
270
|
|
|
247
|
-
|
|
248
|
-
public void ping() {
|
|
271
|
+
override fun ping() {
|
|
249
272
|
}
|
|
250
273
|
|
|
251
|
-
|
|
252
|
-
public void dbg1() {}
|
|
274
|
+
override fun dbg1() {}
|
|
253
275
|
|
|
254
|
-
|
|
255
|
-
public void dbg2() {}
|
|
276
|
+
override fun dbg2() {}
|
|
256
277
|
|
|
257
|
-
|
|
258
|
-
public void setDashboardPosition(int height, int depth) {
|
|
278
|
+
override fun setDashboardPosition(height: Int, depth: Int) {
|
|
259
279
|
|
|
260
280
|
}
|
|
261
281
|
|
|
262
|
-
|
|
263
|
-
public void setHeadUpAngle(int angle) {
|
|
282
|
+
override fun setHeadUpAngle(angle: Int) {
|
|
264
283
|
|
|
265
284
|
}
|
|
266
285
|
|
|
267
|
-
|
|
268
|
-
public void getBatteryStatus() {
|
|
286
|
+
override fun getBatteryStatus() {
|
|
269
287
|
|
|
270
288
|
}
|
|
271
289
|
|
|
272
|
-
|
|
273
|
-
public void setSilentMode(boolean enabled) {
|
|
290
|
+
override fun setSilentMode(enabled: Boolean) {
|
|
274
291
|
|
|
275
292
|
}
|
|
276
293
|
|
|
277
|
-
|
|
278
|
-
public void exit() {
|
|
294
|
+
override fun exit() {
|
|
279
295
|
|
|
280
296
|
}
|
|
281
297
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
Bridge.log("sendShutdown - not supported on Mach1");
|
|
298
|
+
override fun sendShutdown() {
|
|
299
|
+
Bridge.log("sendShutdown - not supported on Mach1")
|
|
285
300
|
}
|
|
286
301
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
Bridge.log("sendReboot - not supported on Mach1");
|
|
302
|
+
override fun sendReboot() {
|
|
303
|
+
Bridge.log("sendReboot - not supported on Mach1")
|
|
290
304
|
}
|
|
291
305
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
Bridge.
|
|
295
|
-
Bridge.sendRgbLedControlResponse(requestId, false, "device_not_supported");
|
|
306
|
+
override fun sendRgbLedControl(requestId: String, packageName: String?, action: String, color: String?, onDurationMs: Int, offDurationMs: Int, count: Int) {
|
|
307
|
+
Bridge.log("sendRgbLedControl - not supported on Mach1")
|
|
308
|
+
Bridge.sendRgbLedControlResponse(requestId, false, "device_not_supported")
|
|
296
309
|
}
|
|
297
310
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
Bridge.log("Mach1: disconnect()");
|
|
311
|
+
override fun disconnect() {
|
|
312
|
+
Bridge.log("Mach1: disconnect()")
|
|
301
313
|
if (ultraliteSdk != null) {
|
|
302
|
-
ultraliteSdk
|
|
303
|
-
updateConnectionState(ConnTypes.DISCONNECTED)
|
|
314
|
+
ultraliteSdk!!.releaseControl()
|
|
315
|
+
updateConnectionState(ConnTypes.DISCONNECTED)
|
|
304
316
|
}
|
|
305
317
|
}
|
|
306
318
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
Bridge.log("Mach1: forget()");
|
|
319
|
+
override fun forget() {
|
|
320
|
+
Bridge.log("Mach1: forget()")
|
|
310
321
|
// Release control and clean up
|
|
311
|
-
destroy()
|
|
322
|
+
destroy()
|
|
312
323
|
}
|
|
313
324
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
findCompatibleDeviceNames();
|
|
325
|
+
override fun findCompatibleDevices() {
|
|
326
|
+
Bridge.log("Mach1: findCompatibleDevices()")
|
|
327
|
+
findCompatibleDeviceNames()
|
|
318
328
|
}
|
|
319
329
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
Bridge.log("Mach1: stopScan() - no active BLE scanner owned by Mach1");
|
|
330
|
+
override fun stopScan() {
|
|
331
|
+
Bridge.log("Mach1: stopScan() - no active BLE scanner owned by Mach1")
|
|
323
332
|
}
|
|
324
333
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
Bridge.log("Mach1: connectById() - id: " + id);
|
|
334
|
+
override fun connectById(id: String) {
|
|
335
|
+
Bridge.log("Mach1: connectById() - id: " + id)
|
|
328
336
|
// The Mach1 uses UltraliteSDK which handles connection internally
|
|
329
337
|
// We just need to trigger the connection process
|
|
330
|
-
connectToSmartGlasses()
|
|
338
|
+
connectToSmartGlasses()
|
|
331
339
|
}
|
|
332
340
|
|
|
333
|
-
|
|
334
|
-
@Override
|
|
335
|
-
public String getConnectedBluetoothName() {
|
|
341
|
+
override fun getConnectedBluetoothName(): String {
|
|
336
342
|
// Mach1/Ultralite SDK doesn't expose the peripheral name directly
|
|
337
343
|
// Return device type if connected
|
|
338
344
|
if (ultraliteSdk != null) {
|
|
339
|
-
|
|
340
|
-
if (connected != null && Boolean.TRUE
|
|
341
|
-
return "Vuzix Ultralite"
|
|
345
|
+
val connected = ultraliteSdk!!.getConnected()
|
|
346
|
+
if (connected != null && java.lang.Boolean.TRUE == connected.value) {
|
|
347
|
+
return "Vuzix Ultralite"
|
|
342
348
|
}
|
|
343
349
|
}
|
|
344
|
-
return ""
|
|
350
|
+
return ""
|
|
345
351
|
}
|
|
346
352
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
destroy();
|
|
353
|
+
override fun cleanup() {
|
|
354
|
+
destroy()
|
|
350
355
|
}
|
|
351
356
|
|
|
352
|
-
|
|
353
|
-
public void requestWifiScan() {
|
|
357
|
+
override fun requestWifiScan() {
|
|
354
358
|
|
|
355
359
|
}
|
|
356
360
|
|
|
357
|
-
|
|
358
|
-
public void sendWifiCredentials(@NonNull String ssid, @NonNull String password) {
|
|
361
|
+
override fun sendWifiCredentials(ssid: String, password: String) {
|
|
359
362
|
|
|
360
363
|
}
|
|
361
364
|
|
|
362
|
-
|
|
363
|
-
public void forgetWifiNetwork(String ssid) {
|
|
365
|
+
override fun forgetWifiNetwork(ssid: String) {
|
|
364
366
|
// Mach1 doesn't support WiFi
|
|
365
367
|
}
|
|
366
368
|
|
|
367
|
-
|
|
368
|
-
public void sendHotspotState(boolean enabled) {
|
|
369
|
+
override fun sendHotspotState(enabled: Boolean) {
|
|
369
370
|
// Mach1 doesn't support hotspot
|
|
370
371
|
}
|
|
371
372
|
|
|
372
|
-
|
|
373
|
-
public void sendUserEmailToGlasses(String email) {
|
|
373
|
+
override fun sendUserEmailToGlasses(email: String) {
|
|
374
374
|
// Mach1 doesn't support user email (no ASG client)
|
|
375
375
|
}
|
|
376
376
|
|
|
377
|
-
|
|
378
|
-
public void sendIncidentId(String incidentId, String apiBaseUrl) {
|
|
377
|
+
override fun sendIncidentId(incidentId: String, apiBaseUrl: String?) {
|
|
379
378
|
// Mach1 doesn't support incident reporting (no ASG client)
|
|
380
379
|
}
|
|
381
380
|
|
|
382
|
-
|
|
383
|
-
public void queryGalleryStatus() {
|
|
381
|
+
override fun queryGalleryStatus() {
|
|
384
382
|
|
|
385
383
|
}
|
|
386
384
|
|
|
387
|
-
|
|
388
|
-
public void sendGalleryMode() {
|
|
385
|
+
override fun sendGalleryMode() {
|
|
389
386
|
// Mach1 doesn't have a built-in camera/gallery system
|
|
390
|
-
Bridge.log("Mach1: sendGalleryModeActive - not supported on Mach1")
|
|
387
|
+
Bridge.log("Mach1: sendGalleryModeActive - not supported on Mach1")
|
|
391
388
|
}
|
|
392
389
|
|
|
393
|
-
|
|
394
|
-
public void requestVersionInfo() {
|
|
390
|
+
override fun requestVersionInfo() {
|
|
395
391
|
// Mach1 doesn't support version info requests
|
|
396
|
-
Bridge.log("Mach1: requestVersionInfo - not supported on Mach1")
|
|
392
|
+
Bridge.log("Mach1: requestVersionInfo - not supported on Mach1")
|
|
397
393
|
}
|
|
398
394
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
long currentTime = System.currentTimeMillis();
|
|
395
|
+
inner class UltraliteListener : EventListener {
|
|
396
|
+
override fun onTap(tapCount: Int) {
|
|
397
|
+
val currentTime = System.currentTimeMillis()
|
|
403
398
|
if (currentTime - lastTapTime < TAP_DEBOUNCE_TIME) {
|
|
404
|
-
Log.d(TAG, "Ignoring duplicate tap event")
|
|
405
|
-
return
|
|
399
|
+
Log.d(TAG, "Ignoring duplicate tap event")
|
|
400
|
+
return
|
|
406
401
|
}
|
|
407
|
-
totalDashboardsIdk
|
|
408
|
-
Log.d(TAG, "TOTAL NUMBER OF DASHBOARD TOGGLEZ: " + totalDashboardsIdk)
|
|
402
|
+
totalDashboardsIdk++
|
|
403
|
+
Log.d(TAG, "TOTAL NUMBER OF DASHBOARD TOGGLEZ: " + totalDashboardsIdk)
|
|
409
404
|
|
|
410
|
-
lastTapTime = currentTime
|
|
411
|
-
Log.d(TAG, "Ultralite go tap n times: " + tapCount)
|
|
405
|
+
lastTapTime = currentTime
|
|
406
|
+
Log.d(TAG, "Ultralite go tap n times: " + tapCount)
|
|
412
407
|
|
|
413
408
|
// Toggle dashboard on 2+ taps (same as iOS implementation)
|
|
414
409
|
if (tapCount >= 2) {
|
|
415
|
-
isHeadUp = !isHeadUp
|
|
410
|
+
isHeadUp = !isHeadUp
|
|
416
411
|
// Notify DeviceManager of head up state change (same as G1 does with IMU)
|
|
417
|
-
DeviceStore.
|
|
418
|
-
Log.d(TAG, "Mach1: Dashboard toggled via tap, isHeadUp: " + isHeadUp)
|
|
412
|
+
DeviceStore.apply("glasses", "headUp", isHeadUp)
|
|
413
|
+
Log.d(TAG, "Mach1: Dashboard toggled via tap, isHeadUp: " + isHeadUp)
|
|
419
414
|
|
|
420
415
|
// Auto turn off the dashboard after 15 seconds
|
|
421
416
|
if (isHeadUp) {
|
|
422
|
-
goHomeHandler
|
|
417
|
+
goHomeHandler!!.postDelayed({
|
|
423
418
|
if (isHeadUp) {
|
|
424
|
-
isHeadUp = false
|
|
425
|
-
DeviceStore.
|
|
426
|
-
Log.d(TAG, "Mach1: Auto-disabling dashboard after 15 seconds")
|
|
419
|
+
isHeadUp = false
|
|
420
|
+
DeviceStore.apply("glasses", "headUp", false)
|
|
421
|
+
Log.d(TAG, "Mach1: Auto-disabling dashboard after 15 seconds")
|
|
427
422
|
}
|
|
428
|
-
},
|
|
423
|
+
}, 15000L)
|
|
429
424
|
}
|
|
430
425
|
}
|
|
431
426
|
}
|
|
432
427
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
Log.d(TAG, "Ultralite display timeout.");
|
|
428
|
+
override fun onDisplayTimeout() {
|
|
429
|
+
Log.d(TAG, "Ultralite display timeout.")
|
|
436
430
|
}
|
|
437
431
|
|
|
438
|
-
|
|
439
|
-
public void onPowerButtonPress(boolean turningOn) {
|
|
432
|
+
override fun onPowerButtonPress(turningOn: Boolean) {
|
|
440
433
|
//since we implement our own state for the power turn on/off, we ignore what the ultralite thinks ('turningOn') and use our own state
|
|
441
|
-
Log.d(TAG, "Ultralites power button pressed: " + turningOn)
|
|
434
|
+
Log.d(TAG, "Ultralites power button pressed: " + turningOn)
|
|
442
435
|
|
|
443
436
|
//flip value of screen toggle
|
|
444
|
-
screenToggleOff = !screenToggleOff
|
|
437
|
+
screenToggleOff = !screenToggleOff
|
|
445
438
|
|
|
446
439
|
if (!screenToggleOff) {
|
|
447
|
-
Log.d(TAG, "screen toggle off NOT on, showing turn ON message")
|
|
440
|
+
Log.d(TAG, "screen toggle off NOT on, showing turn ON message")
|
|
448
441
|
// EventBus.getDefault().post(new GlassesDisplayPowerEvent(screenToggleOff));
|
|
449
442
|
} else {
|
|
450
|
-
Log.d(TAG, "screen toggle off IS on")
|
|
443
|
+
Log.d(TAG, "screen toggle off IS on")
|
|
451
444
|
}
|
|
452
445
|
}
|
|
453
446
|
}
|
|
454
|
-
|
|
455
|
-
private LiveData<Boolean
|
|
456
|
-
private LiveData<
|
|
447
|
+
|
|
448
|
+
private var ultraliteConnectedLive: LiveData<Boolean>? = null
|
|
449
|
+
private var ultraliteControlled: LiveData<Boolean>? = null
|
|
450
|
+
private var batteryStatusObserver: LiveData<BatteryStatus>? = null
|
|
457
451
|
|
|
458
452
|
// Observer references for cleanup
|
|
459
|
-
private Observer<Boolean
|
|
460
|
-
private Observer<Boolean
|
|
461
|
-
private Observer<BatteryStatus
|
|
453
|
+
private var connectedObserver: Observer<Boolean>? = null
|
|
454
|
+
private var controlledObserver: Observer<Boolean>? = null
|
|
455
|
+
private var batteryObserver: Observer<BatteryStatus?>? = null
|
|
462
456
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
Log.d(TAG, "Mach1 constructor started");
|
|
457
|
+
init {
|
|
458
|
+
this.type = DeviceTypes.MACH1
|
|
459
|
+
Log.d(TAG, "Mach1 constructor started")
|
|
467
460
|
|
|
468
461
|
try {
|
|
469
462
|
// Get context from Bridge (like G1 does)
|
|
470
|
-
this.context = Bridge.getContext()
|
|
471
|
-
Log.d(TAG, "Mach1: Got context from Bridge")
|
|
463
|
+
this.context = Bridge.getContext()
|
|
464
|
+
Log.d(TAG, "Mach1: Got context from Bridge")
|
|
472
465
|
|
|
473
|
-
hasUltraliteControl = false
|
|
474
|
-
screenIsClear = true
|
|
475
|
-
goHomeHandler =
|
|
476
|
-
screenOffHandler =
|
|
477
|
-
killHandler =
|
|
478
|
-
Log.d(TAG, "Mach1: Handlers created")
|
|
466
|
+
hasUltraliteControl = false
|
|
467
|
+
screenIsClear = true
|
|
468
|
+
goHomeHandler = Handler(Looper.getMainLooper())
|
|
469
|
+
screenOffHandler = Handler(Looper.getMainLooper())
|
|
470
|
+
killHandler = Handler(Looper.getMainLooper())
|
|
471
|
+
Log.d(TAG, "Mach1: Handlers created")
|
|
479
472
|
|
|
480
|
-
rowTextsLiveNow =
|
|
473
|
+
rowTextsLiveNow = ArrayList<Int>()
|
|
481
474
|
|
|
482
475
|
// Initialize UltraliteSDK with valid context
|
|
483
|
-
Log.d(TAG, "Mach1: About to initialize UltraliteSDK")
|
|
484
|
-
ultraliteSdk = UltraliteSDK.get(context)
|
|
485
|
-
Log.d(TAG, "Mach1: UltraliteSDK initialized")
|
|
476
|
+
Log.d(TAG, "Mach1: About to initialize UltraliteSDK")
|
|
477
|
+
ultraliteSdk = UltraliteSDK.get(context)
|
|
478
|
+
Log.d(TAG, "Mach1: UltraliteSDK initialized")
|
|
486
479
|
|
|
487
|
-
ultraliteListener =
|
|
488
|
-
ultraliteSdk
|
|
489
|
-
Log.d(TAG, "Mach1: Event listener added")
|
|
480
|
+
ultraliteListener = UltraliteListener()
|
|
481
|
+
ultraliteSdk!!.addEventListener(ultraliteListener)
|
|
482
|
+
Log.d(TAG, "Mach1: Event listener added")
|
|
490
483
|
|
|
491
484
|
// Set up LiveData observers using observeForever (no LifecycleOwner needed)
|
|
492
|
-
ultraliteConnectedLive = ultraliteSdk
|
|
493
|
-
ultraliteControlled = ultraliteSdk
|
|
494
|
-
batteryStatusObserver = ultraliteSdk
|
|
495
|
-
Log.d(TAG, "Mach1: LiveData references obtained")
|
|
485
|
+
ultraliteConnectedLive = ultraliteSdk!!.getConnected()
|
|
486
|
+
ultraliteControlled = ultraliteSdk!!.getControlledByMe()
|
|
487
|
+
batteryStatusObserver = ultraliteSdk!!.getBatteryStatus()
|
|
488
|
+
Log.d(TAG, "Mach1: LiveData references obtained")
|
|
496
489
|
|
|
497
490
|
// Create observers
|
|
498
|
-
connectedObserver = isConnected ->
|
|
499
|
-
onUltraliteConnectedChange(isConnected)
|
|
500
|
-
}
|
|
491
|
+
connectedObserver = Observer { isConnected ->
|
|
492
|
+
onUltraliteConnectedChange(isConnected)
|
|
493
|
+
}
|
|
501
494
|
|
|
502
|
-
controlledObserver = isControlled ->
|
|
503
|
-
onUltraliteControlChanged(isControlled)
|
|
504
|
-
}
|
|
495
|
+
controlledObserver = Observer { isControlled ->
|
|
496
|
+
onUltraliteControlChanged(isControlled)
|
|
497
|
+
}
|
|
505
498
|
|
|
506
|
-
batteryObserver = batteryStatus ->
|
|
507
|
-
onUltraliteBatteryChanged(batteryStatus)
|
|
508
|
-
}
|
|
499
|
+
batteryObserver = Observer { batteryStatus ->
|
|
500
|
+
onUltraliteBatteryChanged(batteryStatus)
|
|
501
|
+
}
|
|
509
502
|
|
|
510
503
|
// Register observers on main thread (observeForever requires main thread)
|
|
511
|
-
|
|
504
|
+
Handler(Looper.getMainLooper()).post {
|
|
512
505
|
try {
|
|
513
|
-
ultraliteConnectedLive
|
|
514
|
-
Log.d(TAG, "Mach1: Connected observer registered")
|
|
506
|
+
ultraliteConnectedLive!!.observeForever(connectedObserver!!)
|
|
507
|
+
Log.d(TAG, "Mach1: Connected observer registered")
|
|
515
508
|
|
|
516
|
-
ultraliteControlled
|
|
517
|
-
Log.d(TAG, "Mach1: Controlled observer registered")
|
|
509
|
+
ultraliteControlled!!.observeForever(controlledObserver!!)
|
|
510
|
+
Log.d(TAG, "Mach1: Controlled observer registered")
|
|
518
511
|
|
|
519
|
-
batteryStatusObserver
|
|
520
|
-
Log.d(TAG, "Mach1: Battery observer registered")
|
|
512
|
+
batteryStatusObserver!!.observeForever(batteryObserver!!)
|
|
513
|
+
Log.d(TAG, "Mach1: Battery observer registered")
|
|
521
514
|
|
|
522
|
-
Log.d(TAG, "Mach1: All observers registered on main thread")
|
|
523
|
-
} catch (Exception
|
|
524
|
-
Log.e(TAG, "Mach1: Failed to register observers: " + e.
|
|
515
|
+
Log.d(TAG, "Mach1: All observers registered on main thread")
|
|
516
|
+
} catch (e: Exception) {
|
|
517
|
+
Log.e(TAG, "Mach1: Failed to register observers: " + e.message, e)
|
|
525
518
|
}
|
|
526
|
-
}
|
|
519
|
+
}
|
|
527
520
|
|
|
528
|
-
Log.d(TAG, "Mach1 initialized with context and observers")
|
|
529
|
-
} catch (Exception
|
|
530
|
-
Log.e(TAG, "Mach1 constructor FAILED with exception: " + e.
|
|
531
|
-
Bridge.log("Mach1 constructor FAILED: " + e.
|
|
521
|
+
Log.d(TAG, "Mach1 initialized with context and observers")
|
|
522
|
+
} catch (e: Exception) {
|
|
523
|
+
Log.e(TAG, "Mach1 constructor FAILED with exception: " + e.message, e)
|
|
524
|
+
Bridge.log("Mach1 constructor FAILED: " + e.message)
|
|
532
525
|
}
|
|
533
526
|
}
|
|
534
527
|
|
|
535
|
-
|
|
528
|
+
fun updateGlassesBrightness(brightness: Int) {
|
|
536
529
|
// TODO: Implement this method
|
|
537
530
|
}
|
|
538
531
|
|
|
539
|
-
|
|
532
|
+
fun updateGlassesAutoBrightness(autoBrightness: Boolean) {
|
|
540
533
|
// TODO: Implement this method
|
|
541
534
|
}
|
|
542
535
|
|
|
543
|
-
private
|
|
544
|
-
Log.d(TAG, "Ultralite CONNECT changed to: " + isConnected)
|
|
536
|
+
private fun onUltraliteConnectedChange(isConnected: Boolean) {
|
|
537
|
+
Log.d(TAG, "Ultralite CONNECT changed to: " + isConnected)
|
|
545
538
|
if (isConnected) {
|
|
546
|
-
Log.d(TAG, "Ultralite requesting control...")
|
|
547
|
-
|
|
548
|
-
if (isControlled){
|
|
539
|
+
Log.d(TAG, "Ultralite requesting control...")
|
|
540
|
+
val isControlled = ultraliteSdk!!.requestControl()
|
|
541
|
+
if (isControlled) {
|
|
549
542
|
// setupUltraliteCanvas();
|
|
550
543
|
// changeUltraliteLayout(Layout.CANVAS);
|
|
551
|
-
showHomeScreen()
|
|
544
|
+
showHomeScreen()
|
|
552
545
|
} else {
|
|
553
|
-
return
|
|
546
|
+
return
|
|
554
547
|
}
|
|
555
|
-
Log.d(TAG, "Ultralite RESULT control request: " + isControlled)
|
|
556
|
-
updateConnectionState(ConnTypes.CONNECTED)
|
|
548
|
+
Log.d(TAG, "Ultralite RESULT control request: " + isControlled)
|
|
549
|
+
updateConnectionState(ConnTypes.CONNECTED)
|
|
557
550
|
// connectionEvent(SmartGlassesConnectionState.CONNECTED);
|
|
558
551
|
} else {
|
|
559
|
-
Log.d(TAG, "Ultralite not connected.")
|
|
560
|
-
updateConnectionState(ConnTypes.DISCONNECTED)
|
|
552
|
+
Log.d(TAG, "Ultralite not connected.")
|
|
553
|
+
updateConnectionState(ConnTypes.DISCONNECTED)
|
|
561
554
|
// connectionEvent(SmartGlassesConnectionState.DISCONNECTED);
|
|
562
555
|
}
|
|
563
556
|
}
|
|
564
557
|
|
|
565
|
-
private
|
|
566
|
-
Log.d(TAG, "Ultralite CONTROL changed to: " + isControlledByMe)
|
|
567
|
-
if(isControlledByMe) {
|
|
568
|
-
hasUltraliteControl = true
|
|
558
|
+
private fun onUltraliteControlChanged(isControlledByMe: Boolean) {
|
|
559
|
+
Log.d(TAG, "Ultralite CONTROL changed to: " + isControlledByMe)
|
|
560
|
+
if (isControlledByMe) {
|
|
561
|
+
hasUltraliteControl = true
|
|
569
562
|
// connectionEvent(SmartGlassesConnectionState.CONNECTED);
|
|
570
|
-
updateConnectionState(ConnTypes.CONNECTED)
|
|
563
|
+
updateConnectionState(ConnTypes.CONNECTED)
|
|
571
564
|
} else {
|
|
572
|
-
hasUltraliteControl = false
|
|
565
|
+
hasUltraliteControl = false
|
|
573
566
|
}
|
|
574
567
|
}
|
|
575
568
|
|
|
576
|
-
private
|
|
569
|
+
private fun onUltraliteBatteryChanged(batteryStatus: BatteryStatus?) {
|
|
577
570
|
// Guard against null batteryStatus which can occur during connection/disconnection
|
|
578
571
|
// See: MENTRA-OS-154
|
|
579
572
|
if (batteryStatus == null) {
|
|
580
|
-
Log.d(TAG, "Ultralite battery status is null, ignoring")
|
|
581
|
-
return
|
|
573
|
+
Log.d(TAG, "Ultralite battery status is null, ignoring")
|
|
574
|
+
return
|
|
582
575
|
}
|
|
583
|
-
Log.d(TAG, "Ultralite new battery status: " + batteryStatus.
|
|
584
|
-
DeviceStore.
|
|
576
|
+
Log.d(TAG, "Ultralite new battery status: " + batteryStatus.level)
|
|
577
|
+
DeviceStore.apply("glasses", "batteryLevel", batteryStatus.level)
|
|
585
578
|
|
|
586
579
|
// Match iOS: if we're already connected but weren't fully booted yet (waiting
|
|
587
580
|
// for battery), now that we have battery info we can declare fully booted.
|
|
588
|
-
if (
|
|
589
|
-
DeviceStore.
|
|
590
|
-
DeviceStore.
|
|
581
|
+
if (connectionState == ConnTypes.CONNECTED && !fullyBooted) {
|
|
582
|
+
DeviceStore.apply("glasses", "connected", true)
|
|
583
|
+
DeviceStore.apply("glasses", "fullyBooted", true)
|
|
591
584
|
}
|
|
592
585
|
}
|
|
593
586
|
|
|
594
587
|
|
|
595
|
-
protected
|
|
588
|
+
protected fun setFontSizes() {
|
|
596
589
|
}
|
|
597
590
|
|
|
598
|
-
|
|
591
|
+
fun findCompatibleDeviceNames() {
|
|
599
592
|
// EventBus.getDefault().post(new GlassesBluetoothSearchDiscoverEvent(smartGlassesDevice.deviceModelName, "NOTREQUIREDSKIP"));
|
|
600
|
-
Bridge.sendDiscoveredDevice(this.type, "NOTREQUIREDSKIP")
|
|
593
|
+
Bridge.sendDiscoveredDevice(this.type, "NOTREQUIREDSKIP") // Use this.type to support both Mach1 and Z100
|
|
601
594
|
//this.destroy();
|
|
602
595
|
}
|
|
603
596
|
|
|
604
|
-
|
|
605
|
-
Log.d(TAG, "connectToSmartGlasses running...")
|
|
597
|
+
fun connectToSmartGlasses() {
|
|
598
|
+
Log.d(TAG, "connectToSmartGlasses running...")
|
|
606
599
|
// int mCount = 10;
|
|
607
600
|
// while ((mConnectState != 2) && (!hasUltraliteControl) && (mCount > 0)){
|
|
608
601
|
// mCount--;
|
|
@@ -618,11 +611,11 @@ public class Mach1 extends SGCManager {
|
|
|
618
611
|
// Log.d(TAG, "mCOunt: " + mCount);
|
|
619
612
|
// displayReferenceCardSimple("Connected to AugmentOS", "");
|
|
620
613
|
// connectionEvent(mConnectState);
|
|
621
|
-
Log.d(TAG, "connectToSmartGlasses finished")
|
|
614
|
+
Log.d(TAG, "connectToSmartGlasses finished")
|
|
622
615
|
}
|
|
623
616
|
|
|
624
|
-
|
|
625
|
-
displayReferenceCardSimple("", text)
|
|
617
|
+
fun displayTextLine(text: String) {
|
|
618
|
+
displayReferenceCardSimple("", text)
|
|
626
619
|
}
|
|
627
620
|
|
|
628
621
|
/**
|
|
@@ -631,22 +624,22 @@ public class Mach1 extends SGCManager {
|
|
|
631
624
|
* Text wrapping and processing is handled by DisplayProcessor in React Native.
|
|
632
625
|
* This method is a "dumb pipe" - it just sends the text to the Vuzix SDK.
|
|
633
626
|
*/
|
|
634
|
-
|
|
627
|
+
fun displayTextWall(text: String) {
|
|
635
628
|
if (screenToggleOff) {
|
|
636
|
-
return
|
|
629
|
+
return
|
|
637
630
|
}
|
|
638
631
|
|
|
639
|
-
goHomeHandler
|
|
640
|
-
goHomeHandler
|
|
632
|
+
goHomeHandler!!.removeCallbacksAndMessages(null)
|
|
633
|
+
goHomeHandler!!.removeCallbacksAndMessages(goHomeRunnable)
|
|
641
634
|
|
|
642
635
|
// Text is already wrapped by DisplayProcessor - just send it
|
|
643
|
-
changeUltraliteLayout(Layout.TEXT_BOTTOM_LEFT_ALIGN)
|
|
644
|
-
ultraliteSdk
|
|
636
|
+
changeUltraliteLayout(Layout.TEXT_BOTTOM_LEFT_ALIGN)
|
|
637
|
+
ultraliteSdk!!.sendText(text)
|
|
645
638
|
|
|
646
639
|
if (ultraliteCanvas != null) {
|
|
647
|
-
ultraliteCanvas
|
|
640
|
+
ultraliteCanvas!!.commit()
|
|
648
641
|
}
|
|
649
|
-
screenIsClear = false
|
|
642
|
+
screenIsClear = false
|
|
650
643
|
}
|
|
651
644
|
|
|
652
645
|
/**
|
|
@@ -659,33 +652,33 @@ public class Mach1 extends SGCManager {
|
|
|
659
652
|
* Column composition is handled by DisplayProcessor in React Native.
|
|
660
653
|
* This method is a "dumb pipe" - it just sends the text to the Vuzix SDK.
|
|
661
654
|
*/
|
|
662
|
-
|
|
655
|
+
fun displayDoubleTextWall(textTop: String, textBottom: String) {
|
|
663
656
|
if (screenToggleOff) {
|
|
664
|
-
return
|
|
657
|
+
return
|
|
665
658
|
}
|
|
666
659
|
|
|
667
|
-
goHomeHandler
|
|
668
|
-
goHomeHandler
|
|
660
|
+
goHomeHandler!!.removeCallbacksAndMessages(null)
|
|
661
|
+
goHomeHandler!!.removeCallbacksAndMessages(goHomeRunnable)
|
|
669
662
|
|
|
670
663
|
// Text is already composed by DisplayProcessor's ColumnComposer
|
|
671
664
|
// Just combine and send - no custom logic needed
|
|
672
|
-
|
|
665
|
+
val combinedText = textTop + "\n\n\n" + textBottom
|
|
673
666
|
|
|
674
|
-
changeUltraliteLayout(Layout.TEXT_BOTTOM_LEFT_ALIGN)
|
|
675
|
-
ultraliteSdk
|
|
667
|
+
changeUltraliteLayout(Layout.TEXT_BOTTOM_LEFT_ALIGN)
|
|
668
|
+
ultraliteSdk!!.sendText(combinedText)
|
|
676
669
|
|
|
677
670
|
if (ultraliteCanvas != null) {
|
|
678
|
-
ultraliteCanvas
|
|
671
|
+
ultraliteCanvas!!.commit()
|
|
679
672
|
}
|
|
680
|
-
screenIsClear = false
|
|
673
|
+
screenIsClear = false
|
|
681
674
|
}
|
|
682
675
|
|
|
683
|
-
|
|
684
|
-
displayReferenceCardSimple("CustomDisplayNotImplemented", json)
|
|
676
|
+
fun displayCustomContent(json: String) {
|
|
677
|
+
displayReferenceCardSimple("CustomDisplayNotImplemented", json)
|
|
685
678
|
}
|
|
686
679
|
|
|
687
680
|
|
|
688
|
-
|
|
681
|
+
fun showNaturalLanguageCommandScreen(prompt: String, naturalLanguageInput: String) {
|
|
689
682
|
// int boxDelta = 3;
|
|
690
683
|
//
|
|
691
684
|
// if (connectedGlasses != null) {
|
|
@@ -708,103 +701,103 @@ public class Mach1 extends SGCManager {
|
|
|
708
701
|
// }
|
|
709
702
|
}
|
|
710
703
|
|
|
711
|
-
|
|
704
|
+
fun updateNaturalLanguageCommandScreen(naturalLanguageArgs: String) {
|
|
712
705
|
// Log.d(TAG, "Displaynig: " + naturalLanguageArgs);
|
|
713
706
|
// displayText(new TextLineSG(naturalLanguageArgs, SMALL_FONT), new Point(0, lastLocNaturalLanguageArgsTextView.y));
|
|
714
707
|
}
|
|
715
708
|
|
|
716
|
-
|
|
709
|
+
fun blankScreen() {
|
|
717
710
|
// if (connectedGlasses != null){
|
|
718
711
|
// connectedGlasses.clear();
|
|
719
712
|
// }
|
|
720
713
|
}
|
|
721
714
|
|
|
722
|
-
|
|
715
|
+
fun destroy() {
|
|
723
716
|
try {
|
|
724
717
|
// Remove LiveData observers (using observeForever, so use removeObserver)
|
|
725
718
|
if (ultraliteConnectedLive != null && connectedObserver != null) {
|
|
726
|
-
ultraliteConnectedLive
|
|
719
|
+
ultraliteConnectedLive!!.removeObserver(connectedObserver!!)
|
|
727
720
|
}
|
|
728
721
|
if (ultraliteControlled != null && controlledObserver != null) {
|
|
729
|
-
ultraliteControlled
|
|
722
|
+
ultraliteControlled!!.removeObserver(controlledObserver!!)
|
|
730
723
|
}
|
|
731
724
|
if (batteryStatusObserver != null && batteryObserver != null) {
|
|
732
|
-
batteryStatusObserver
|
|
725
|
+
batteryStatusObserver!!.removeObserver(batteryObserver!!)
|
|
733
726
|
}
|
|
734
727
|
|
|
735
728
|
if (ultraliteSdk != null) {
|
|
736
729
|
// Remove event listeners and release control
|
|
737
|
-
ultraliteSdk
|
|
738
|
-
ultraliteSdk
|
|
739
|
-
ultraliteSdk = null
|
|
730
|
+
ultraliteSdk!!.removeEventListener(ultraliteListener)
|
|
731
|
+
ultraliteSdk!!.releaseControl()
|
|
732
|
+
ultraliteSdk = null // Nullify reference
|
|
740
733
|
}
|
|
741
734
|
|
|
742
735
|
// Cancel all pending handlers and callbacks
|
|
743
736
|
if (goHomeHandler != null) {
|
|
744
|
-
goHomeHandler
|
|
737
|
+
goHomeHandler!!.removeCallbacksAndMessages(null)
|
|
745
738
|
}
|
|
746
739
|
if (screenOffHandler != null) {
|
|
747
|
-
screenOffHandler
|
|
740
|
+
screenOffHandler!!.removeCallbacksAndMessages(null)
|
|
748
741
|
}
|
|
749
742
|
if (killHandler != null) {
|
|
750
|
-
killHandler
|
|
743
|
+
killHandler!!.removeCallbacksAndMessages(null)
|
|
751
744
|
}
|
|
752
745
|
|
|
753
746
|
// Clear canvas and other resources
|
|
754
747
|
if (ultraliteCanvas != null) {
|
|
755
|
-
ultraliteCanvas
|
|
756
|
-
ultraliteCanvas
|
|
757
|
-
ultraliteCanvas = null
|
|
748
|
+
ultraliteCanvas!!.clear()
|
|
749
|
+
ultraliteCanvas!!.commit()
|
|
750
|
+
ultraliteCanvas = null
|
|
758
751
|
}
|
|
759
752
|
|
|
760
753
|
// Reset state variables
|
|
761
|
-
rowTextsLiveNow
|
|
762
|
-
screenToggleOff = false
|
|
763
|
-
screenIsClear = true
|
|
764
|
-
lastTapTime = 0
|
|
765
|
-
totalDashboardsIdk = 0
|
|
766
|
-
currentUltraliteLayout = null
|
|
754
|
+
rowTextsLiveNow!!.clear()
|
|
755
|
+
screenToggleOff = false
|
|
756
|
+
screenIsClear = true
|
|
757
|
+
lastTapTime = 0
|
|
758
|
+
totalDashboardsIdk = 0
|
|
759
|
+
currentUltraliteLayout = null
|
|
767
760
|
|
|
768
761
|
// Free up references
|
|
769
|
-
this.context = null
|
|
770
|
-
connectedObserver = null
|
|
771
|
-
controlledObserver = null
|
|
772
|
-
batteryObserver = null
|
|
773
|
-
|
|
774
|
-
Log.d(TAG, "UltraliteSGC destroyed successfully.")
|
|
775
|
-
} catch (Exception
|
|
776
|
-
Log.e(TAG, "Error during destroy: ", e)
|
|
762
|
+
this.context = null
|
|
763
|
+
connectedObserver = null
|
|
764
|
+
controlledObserver = null
|
|
765
|
+
batteryObserver = null
|
|
766
|
+
|
|
767
|
+
Log.d(TAG, "UltraliteSGC destroyed successfully.")
|
|
768
|
+
} catch (e: Exception) {
|
|
769
|
+
Log.e(TAG, "Error during destroy: ", e)
|
|
777
770
|
}
|
|
778
771
|
}
|
|
779
772
|
|
|
780
773
|
|
|
781
|
-
|
|
782
|
-
Log.d(TAG, "SHOW HOME SCREEN")
|
|
783
|
-
ultraliteSdk
|
|
784
|
-
screenIsClear = true
|
|
774
|
+
fun showHomeScreen() {
|
|
775
|
+
Log.d(TAG, "SHOW HOME SCREEN")
|
|
776
|
+
ultraliteSdk!!.screenOff()
|
|
777
|
+
screenIsClear = true
|
|
785
778
|
}
|
|
786
779
|
|
|
787
|
-
|
|
788
|
-
Log.d(TAG, "Setting up ultralite canvas")
|
|
780
|
+
fun setupUltraliteCanvas() {
|
|
781
|
+
Log.d(TAG, "Setting up ultralite canvas")
|
|
789
782
|
if (ultraliteSdk != null) {
|
|
790
|
-
ultraliteCanvas = ultraliteSdk
|
|
783
|
+
ultraliteCanvas = ultraliteSdk!!.getCanvas()
|
|
791
784
|
}
|
|
792
785
|
}
|
|
793
786
|
|
|
794
|
-
|
|
787
|
+
fun changeUltraliteLayout(chosenLayout: Layout) {
|
|
795
788
|
//don't update layout if it's already setup
|
|
796
|
-
if (currentUltraliteLayout != null && currentUltraliteLayout == chosenLayout){
|
|
797
|
-
return
|
|
789
|
+
if (currentUltraliteLayout != null && currentUltraliteLayout == chosenLayout) {
|
|
790
|
+
return
|
|
798
791
|
}
|
|
799
792
|
|
|
800
|
-
ultraliteSdk
|
|
793
|
+
ultraliteSdk!!.screenOn()
|
|
801
794
|
|
|
802
|
-
currentUltraliteLayout = chosenLayout
|
|
803
|
-
ultraliteSdk
|
|
795
|
+
currentUltraliteLayout = chosenLayout
|
|
796
|
+
ultraliteSdk!!.setLayout(chosenLayout, 0, true, false, 2)
|
|
804
797
|
|
|
805
|
-
if (chosenLayout
|
|
806
|
-
if (ultraliteCanvas == null){
|
|
807
|
-
setupUltraliteCanvas()
|
|
798
|
+
if (chosenLayout == Layout.CANVAS) {
|
|
799
|
+
if (ultraliteCanvas == null) {
|
|
800
|
+
setupUltraliteCanvas()
|
|
808
801
|
}
|
|
809
802
|
}
|
|
810
803
|
}
|
|
@@ -826,16 +819,16 @@ public class Mach1 extends SGCManager {
|
|
|
826
819
|
* Draw text on Ultralite canvas.
|
|
827
820
|
* Text is expected to be pre-wrapped by DisplayProcessor.
|
|
828
821
|
*/
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
changeUltraliteLayout(Layout.CANVAS)
|
|
834
|
-
ultraliteCanvas
|
|
835
|
-
ultraliteCanvas
|
|
836
|
-
ultraliteCanvas
|
|
837
|
-
ultraliteCanvas
|
|
838
|
-
screenIsClear = false
|
|
822
|
+
fun drawTextOnUltralite(text: String) {
|
|
823
|
+
val ultraliteColor = UltraliteColor.WHITE
|
|
824
|
+
val ultraliteAnchor = Anchor.TOP_LEFT
|
|
825
|
+
val ultraliteAlignment = TextAlignment.LEFT
|
|
826
|
+
changeUltraliteLayout(Layout.CANVAS)
|
|
827
|
+
ultraliteCanvas!!.clear()
|
|
828
|
+
ultraliteCanvas!!.clearBackground(UltraliteColor.DIM)
|
|
829
|
+
ultraliteCanvas!!.createText(text, ultraliteAlignment, ultraliteColor, ultraliteAnchor, true)
|
|
830
|
+
ultraliteCanvas!!.commit()
|
|
831
|
+
screenIsClear = false
|
|
839
832
|
}
|
|
840
833
|
|
|
841
834
|
// public Bitmap getBitmapFromDrawable(Resources res) {
|
|
@@ -896,25 +889,25 @@ public class Mach1 extends SGCManager {
|
|
|
896
889
|
// ultraliteSdk.setFont(null, 0, textSize);
|
|
897
890
|
// }
|
|
898
891
|
|
|
899
|
-
|
|
900
|
-
if (screenToggleOff){
|
|
901
|
-
return
|
|
892
|
+
fun displayReferenceCardSimple(titleStr: String, bodyStr: String) {
|
|
893
|
+
if (screenToggleOff) {
|
|
894
|
+
return
|
|
902
895
|
}
|
|
903
896
|
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
if (
|
|
907
|
-
Log.d(TAG, "Not showing reference card because not connected to Ultralites...")
|
|
908
|
-
return
|
|
897
|
+
val title = maybeReverseRTLString(titleStr)
|
|
898
|
+
val body = maybeReverseRTLString(bodyStr)
|
|
899
|
+
if (connectionState != ConnTypes.CONNECTED) {
|
|
900
|
+
Log.d(TAG, "Not showing reference card because not connected to Ultralites...")
|
|
901
|
+
return
|
|
909
902
|
}
|
|
910
903
|
|
|
911
|
-
changeUltraliteLayout(Layout.CANVAS)
|
|
912
|
-
ultraliteCanvas
|
|
904
|
+
changeUltraliteLayout(Layout.CANVAS)
|
|
905
|
+
ultraliteCanvas!!.clear()
|
|
913
906
|
|
|
914
907
|
// String [] bulletPoints = {"first one", "second one", "dogs and cats"};
|
|
915
908
|
// displayBulletList("Cool Bullets:", bulletPoints, 15);
|
|
916
909
|
|
|
917
|
-
Log.d(TAG, "Sending text to Ultralite SDK: \n" + body)
|
|
910
|
+
Log.d(TAG, "Sending text to Ultralite SDK: \n" + body)
|
|
918
911
|
// ultraliteSdk.sendText("hello world"); //this is BROKEN in Vuzix ultralite 0.4.2 SDK - crashes Vuzix OEM Platform android app
|
|
919
912
|
|
|
920
913
|
//edit the text to add new lines to it because ultralite wrapping doesn't work
|
|
@@ -929,14 +922,14 @@ public class Mach1 extends SGCManager {
|
|
|
929
922
|
// ultraliteCanvas.createText(body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.MIDDLE_LEFT, ultraliteLeftSidePixelBuffer, 0, 640 - ultraliteLeftSidePixelBuffer, -1, TextWrapMode.WRAP, true);
|
|
930
923
|
|
|
931
924
|
//concat body and title, put text on top right of screen (to not block main view)
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
925
|
+
val ultraliteColor = UltraliteColor.WHITE
|
|
926
|
+
val ultraliteAnchor = Anchor.TOP_CENTER
|
|
927
|
+
val ultraliteAlignment = TextAlignment.LEFT
|
|
935
928
|
//ultraliteCanvas.createText(body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_RIGHT, 0, 0, (640 / 2) - ultraliteLeftSidePixelBuffer, -1, TextWrapMode.WRAP, true);
|
|
936
|
-
if (!title.isEmpty() &&
|
|
937
|
-
ultraliteCanvas
|
|
929
|
+
if (!title.isEmpty() && title != "") {
|
|
930
|
+
ultraliteCanvas!!.createText(title + ": " + body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_RIGHT, 0, 0, 640 / 2, -1, TextWrapMode.WRAP, true)
|
|
938
931
|
} else {
|
|
939
|
-
ultraliteCanvas
|
|
932
|
+
ultraliteCanvas!!.createText(body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_RIGHT, 0, 0, 640 / 2, -1, TextWrapMode.WRAP, true)
|
|
940
933
|
}
|
|
941
934
|
|
|
942
935
|
//NOTE:
|
|
@@ -956,42 +949,44 @@ public class Mach1 extends SGCManager {
|
|
|
956
949
|
// TextWrapMode wrap,
|
|
957
950
|
// boolean visible)
|
|
958
951
|
|
|
959
|
-
ultraliteCanvas
|
|
960
|
-
screenIsClear = false
|
|
952
|
+
ultraliteCanvas!!.commit()
|
|
953
|
+
screenIsClear = false
|
|
961
954
|
}
|
|
962
955
|
|
|
963
956
|
|
|
964
|
-
|
|
965
|
-
displayBulletList(title, bullets, 14)
|
|
957
|
+
fun displayBulletList(title: String, bullets: Array<String>) {
|
|
958
|
+
displayBulletList(title, bullets, 14)
|
|
966
959
|
}
|
|
967
960
|
|
|
968
|
-
|
|
969
|
-
displayRowsCard(rowStrings, cardLingerTime)
|
|
961
|
+
fun displayRowsCard(rowStrings: Array<String>) {
|
|
962
|
+
displayRowsCard(rowStrings, cardLingerTime)
|
|
970
963
|
}
|
|
971
964
|
|
|
972
|
-
|
|
973
|
-
if (screenToggleOff){
|
|
974
|
-
return
|
|
965
|
+
fun displayRowsCard(rowStringList: Array<String>, lingerTime: Int) {
|
|
966
|
+
if (screenToggleOff) {
|
|
967
|
+
return
|
|
975
968
|
}
|
|
976
969
|
|
|
977
|
-
|
|
978
|
-
if (
|
|
979
|
-
Log.d(TAG, "Not showing rows card because not connected to Ultralites...")
|
|
980
|
-
return
|
|
970
|
+
val rowStrings = maybeReverseRTLStringList(rowStringList)
|
|
971
|
+
if (connectionState != ConnTypes.CONNECTED) {
|
|
972
|
+
Log.d(TAG, "Not showing rows card because not connected to Ultralites...")
|
|
973
|
+
return
|
|
981
974
|
}
|
|
982
975
|
|
|
983
976
|
// changeUltraliteLayout(Layout.CANVAS);
|
|
984
977
|
// ultraliteCanvas.clear();
|
|
985
978
|
|
|
986
979
|
//make lines to draw on screen to delineate rows
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
980
|
+
val line_thickness = 3
|
|
981
|
+
var y = 120
|
|
982
|
+
while (y < 480) {
|
|
983
|
+
ultraliteCanvas!!.clearBackgroundRect(0, y, 640, line_thickness, UltraliteColor.DIM)
|
|
984
|
+
y += 120
|
|
990
985
|
}
|
|
991
986
|
|
|
992
987
|
//clear old text
|
|
993
|
-
for (
|
|
994
|
-
ultraliteCanvas
|
|
988
|
+
for (i in 0 until rowTextsLiveNow!!.size) {
|
|
989
|
+
ultraliteCanvas!!.removeText(i)
|
|
995
990
|
}
|
|
996
991
|
//old way to clear old text - vuzix ultralite sdk bug that clear background doesn't clear text?
|
|
997
992
|
// for (int y = 0; y < 480; y += 120) {
|
|
@@ -1002,64 +997,64 @@ public class Mach1 extends SGCManager {
|
|
|
1002
997
|
// ultraliteCanvas.commit();
|
|
1003
998
|
|
|
1004
999
|
//display the title at the top of the screen
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1000
|
+
val ultraliteColor = UltraliteColor.WHITE
|
|
1001
|
+
val ultraliteAnchor = Anchor.TOP_LEFT
|
|
1002
|
+
val ultraliteAlignment = TextAlignment.LEFT
|
|
1008
1003
|
|
|
1009
1004
|
//if no input, just show the lines
|
|
1010
|
-
if (rowStrings.
|
|
1011
|
-
ultraliteCanvas
|
|
1012
|
-
screenIsClear = false
|
|
1013
|
-
return
|
|
1005
|
+
if (rowStrings.isEmpty()) {
|
|
1006
|
+
ultraliteCanvas!!.commit()
|
|
1007
|
+
screenIsClear = false
|
|
1008
|
+
return
|
|
1014
1009
|
}
|
|
1015
1010
|
|
|
1016
1011
|
//go throw rows, draw the text, don't do more than 4
|
|
1017
|
-
|
|
1012
|
+
val y_start_height = 55
|
|
1018
1013
|
// Reverse rowStrings array
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
for (
|
|
1014
|
+
rowStrings.reverse()
|
|
1015
|
+
val numRows = 4
|
|
1016
|
+
val actualRows = Math.min(rowStrings.size, numRows)
|
|
1017
|
+
for (i in 0 until actualRows) {
|
|
1023
1018
|
// Calculate the offset to start from the bottom for 1, 2, or 3 values
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
rowTextsLiveNow
|
|
1019
|
+
val yOffset = (numRows - actualRows) * 112
|
|
1020
|
+
val textId = ultraliteCanvas!!.createText(rowStrings[i], TextAlignment.CENTER, UltraliteColor.WHITE, Anchor.TOP_LEFT, ultraliteLeftSidePixelBuffer, y_start_height + yOffset + (i * 112), 640 - ultraliteLeftSidePixelBuffer, -1, TextWrapMode.WRAP, true)
|
|
1021
|
+
rowTextsLiveNow!!.add(textId)
|
|
1027
1022
|
}
|
|
1028
1023
|
|
|
1029
|
-
ultraliteCanvas
|
|
1030
|
-
screenIsClear = false
|
|
1024
|
+
ultraliteCanvas!!.commit()
|
|
1025
|
+
screenIsClear = false
|
|
1031
1026
|
}
|
|
1032
1027
|
|
|
1033
|
-
|
|
1034
|
-
if (screenToggleOff){
|
|
1035
|
-
return
|
|
1028
|
+
fun displayBulletList(title: String, bulletList: Array<String>, lingerTime: Int) {
|
|
1029
|
+
if (screenToggleOff) {
|
|
1030
|
+
return
|
|
1036
1031
|
}
|
|
1037
1032
|
|
|
1038
|
-
|
|
1039
|
-
if (
|
|
1040
|
-
Log.d(TAG, "Not showing bullet point list because not connected to Ultralites...")
|
|
1041
|
-
return
|
|
1033
|
+
val bullets = maybeReverseRTLStringList(bulletList)
|
|
1034
|
+
if (connectionState != ConnTypes.CONNECTED) {
|
|
1035
|
+
Log.d(TAG, "Not showing bullet point list because not connected to Ultralites...")
|
|
1036
|
+
return
|
|
1042
1037
|
}
|
|
1043
1038
|
|
|
1044
|
-
Log.d(TAG, "Sending bullets to Ultralite SDK: " + title)
|
|
1039
|
+
Log.d(TAG, "Sending bullets to Ultralite SDK: " + title)
|
|
1045
1040
|
|
|
1046
1041
|
//display the title at the top of the screen
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
changeUltraliteLayout(Layout.CANVAS)
|
|
1051
|
-
ultraliteCanvas
|
|
1052
|
-
|
|
1053
|
-
ultraliteCanvas
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
for (
|
|
1057
|
-
ultraliteCanvas
|
|
1058
|
-
displaceY += 125
|
|
1042
|
+
val ultraliteColor = UltraliteColor.WHITE
|
|
1043
|
+
val ultraliteAnchor = Anchor.TOP_LEFT
|
|
1044
|
+
val ultraliteAlignment = TextAlignment.LEFT
|
|
1045
|
+
changeUltraliteLayout(Layout.CANVAS)
|
|
1046
|
+
ultraliteCanvas!!.clear()
|
|
1047
|
+
|
|
1048
|
+
ultraliteCanvas!!.createText(title, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true)
|
|
1049
|
+
var displaceY = 25
|
|
1050
|
+
val displaceX = 25
|
|
1051
|
+
for (bullet in bullets) {
|
|
1052
|
+
ultraliteCanvas!!.createText("⬤ " + bullet, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_LEFT, displaceX, displaceY, 640 - displaceX, -1, TextWrapMode.WRAP, true)
|
|
1053
|
+
displaceY += 125
|
|
1059
1054
|
}
|
|
1060
1055
|
|
|
1061
|
-
ultraliteCanvas
|
|
1062
|
-
screenIsClear = false
|
|
1056
|
+
ultraliteCanvas!!.commit()
|
|
1057
|
+
screenIsClear = false
|
|
1063
1058
|
}
|
|
1064
1059
|
|
|
1065
1060
|
// public void homeScreenInNSeconds(int n){
|
|
@@ -1078,48 +1073,47 @@ public class Mach1 extends SGCManager {
|
|
|
1078
1073
|
// goHomeHandler.postDelayed(goHomeRunnable, n * 1000);
|
|
1079
1074
|
// }
|
|
1080
1075
|
|
|
1081
|
-
|
|
1082
|
-
|
|
1076
|
+
fun displayBitmap(bmp: Bitmap) {
|
|
1077
|
+
val resizedBmp = Bitmap.createScaledBitmap(bmp, 620, 460, true) // 640 x 480
|
|
1083
1078
|
|
|
1084
|
-
changeUltraliteLayout(Layout.CANVAS)
|
|
1085
|
-
screenIsClear = false
|
|
1079
|
+
changeUltraliteLayout(Layout.CANVAS)
|
|
1080
|
+
screenIsClear = false
|
|
1086
1081
|
|
|
1087
|
-
Log.d(TAG, "Sending bitmap to Ultralite")
|
|
1088
|
-
ultraliteCanvas
|
|
1089
|
-
ultraliteCanvas
|
|
1082
|
+
Log.d(TAG, "Sending bitmap to Ultralite")
|
|
1083
|
+
ultraliteCanvas!!.drawBackground(resizedBmp, 50, 80)
|
|
1084
|
+
ultraliteCanvas!!.commit()
|
|
1090
1085
|
}
|
|
1091
1086
|
|
|
1092
1087
|
//don't show images on activelook (screen is too low res)
|
|
1093
|
-
|
|
1094
|
-
if (screenToggleOff){
|
|
1095
|
-
return
|
|
1088
|
+
fun displayReferenceCardImage(title: String, body: String, imgUrl: String) {
|
|
1089
|
+
if (screenToggleOff) {
|
|
1090
|
+
return
|
|
1096
1091
|
}
|
|
1097
1092
|
|
|
1098
|
-
changeUltraliteLayout(Layout.CANVAS)
|
|
1099
|
-
ultraliteCanvas
|
|
1093
|
+
changeUltraliteLayout(Layout.CANVAS)
|
|
1094
|
+
ultraliteCanvas!!.clear()
|
|
1100
1095
|
|
|
1101
1096
|
//make image
|
|
1102
1097
|
//below works, but only for very, very low res/size images
|
|
1103
|
-
|
|
1098
|
+
val ultraliteImageAnchor = Anchor.CENTER
|
|
1104
1099
|
Picasso.get()
|
|
1105
1100
|
.load(imgUrl)
|
|
1106
|
-
.into(
|
|
1107
|
-
|
|
1108
|
-
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
|
|
1101
|
+
.into(object : Target {
|
|
1102
|
+
override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
|
|
1109
1103
|
// Use the bitmap
|
|
1110
1104
|
// LVGLImage ultraliteImage = LVGLImage.fromBitmap(getBitmapFromDrawable(context.getResources()), CF_INDEXED_2_BIT);
|
|
1111
1105
|
// LVGLImage ultraliteImage = LVGLImage.fromBitmap(bitmap, CF_INDEXED_2_BIT);
|
|
1112
|
-
changeUltraliteLayout(Layout.CANVAS)
|
|
1106
|
+
changeUltraliteLayout(Layout.CANVAS)
|
|
1113
1107
|
|
|
1114
1108
|
//send text first, cuz this is fast
|
|
1115
|
-
ultraliteCanvas
|
|
1116
|
-
ultraliteCanvas
|
|
1117
|
-
ultraliteCanvas
|
|
1118
|
-
screenIsClear = false
|
|
1109
|
+
ultraliteCanvas!!.createText(title, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true)
|
|
1110
|
+
ultraliteCanvas!!.createText(body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.BOTTOM_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true)
|
|
1111
|
+
ultraliteCanvas!!.commit()
|
|
1112
|
+
screenIsClear = false
|
|
1119
1113
|
|
|
1120
|
-
Log.d(TAG, "Sending image to Ultralite")
|
|
1114
|
+
Log.d(TAG, "Sending image to Ultralite")
|
|
1121
1115
|
// ultraliteCanvas.createImage(ultraliteImage, ultraliteImageAnchor, 0, 0, true);
|
|
1122
|
-
ultraliteCanvas
|
|
1116
|
+
ultraliteCanvas!!.drawBackground(bitmap!!, 0, 0)
|
|
1123
1117
|
|
|
1124
1118
|
//sending text again to ultralite in case image overwrote it
|
|
1125
1119
|
// ultraliteCanvas.createText(title + "2", TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.BOTTOM_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true);
|
|
@@ -1135,18 +1129,16 @@ public class Mach1 extends SGCManager {
|
|
|
1135
1129
|
// ultraliteCanvas.commit();
|
|
1136
1130
|
}
|
|
1137
1131
|
|
|
1138
|
-
|
|
1139
|
-
public void onBitmapFailed(Exception e, Drawable errorDrawable) {
|
|
1132
|
+
override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {
|
|
1140
1133
|
// Handle the error
|
|
1141
|
-
Log.d(TAG, "Bitmap failed")
|
|
1142
|
-
e
|
|
1134
|
+
Log.d(TAG, "Bitmap failed")
|
|
1135
|
+
e!!.printStackTrace()
|
|
1143
1136
|
}
|
|
1144
1137
|
|
|
1145
|
-
|
|
1146
|
-
public void onPrepareLoad(Drawable placeHolderDrawable) {
|
|
1138
|
+
override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
|
|
1147
1139
|
// Called before the image is loaded. You can set a placeholder if needed.
|
|
1148
1140
|
}
|
|
1149
|
-
})
|
|
1141
|
+
})
|
|
1150
1142
|
|
|
1151
1143
|
//edit the text to add new lines to it because ultralite wrapping doesn't work
|
|
1152
1144
|
// String titleWrapped = addNewlineEveryNWords(title, 6);
|
|
@@ -1195,7 +1187,7 @@ public class Mach1 extends SGCManager {
|
|
|
1195
1187
|
// return textPoint;
|
|
1196
1188
|
// }
|
|
1197
1189
|
|
|
1198
|
-
|
|
1190
|
+
fun stopScrollingTextViewMode() {
|
|
1199
1191
|
// if (connectedGlasses == null) {
|
|
1200
1192
|
// return;
|
|
1201
1193
|
// }
|
|
@@ -1204,12 +1196,12 @@ public class Mach1 extends SGCManager {
|
|
|
1204
1196
|
// connectedGlasses.clear();
|
|
1205
1197
|
}
|
|
1206
1198
|
|
|
1207
|
-
|
|
1199
|
+
fun scrollingTextViewIntermediateText(text: String) {
|
|
1208
1200
|
}
|
|
1209
1201
|
|
|
1210
|
-
|
|
1211
|
-
if (
|
|
1212
|
-
return
|
|
1202
|
+
fun scrollingTextViewFinalText(text: String) {
|
|
1203
|
+
if (connectionState != ConnTypes.CONNECTED) {
|
|
1204
|
+
return
|
|
1213
1205
|
}
|
|
1214
1206
|
|
|
1215
1207
|
// //save to our saved list of final scrolling text strings
|
|
@@ -1260,52 +1252,17 @@ public class Mach1 extends SGCManager {
|
|
|
1260
1252
|
|
|
1261
1253
|
}
|
|
1262
1254
|
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
rtlBuffer.append(c); // Append RTL characters to a buffer
|
|
1270
|
-
} else {
|
|
1271
|
-
if (rtlBuffer.length() > 0) {
|
|
1272
|
-
result.append(rtlBuffer.reverse()); // Reverse and append RTL text when a non-RTL character is found
|
|
1273
|
-
rtlBuffer.setLength(0); // Clear the buffer
|
|
1274
|
-
}
|
|
1275
|
-
result.append(c); // Append non-RTL characters directly to the result
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
if (rtlBuffer.length() > 0) {
|
|
1280
|
-
result.append(rtlBuffer.reverse()); // Append any remaining RTL text in reverse
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
|
-
return result.toString();
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
private static boolean isRTLCharacter(char c) {
|
|
1287
|
-
Character.UnicodeBlock block = Character.UnicodeBlock.of(c);
|
|
1288
|
-
return block == Character.UnicodeBlock.ARABIC ||
|
|
1289
|
-
block == Character.UnicodeBlock.HEBREW ||
|
|
1290
|
-
block == Character.UnicodeBlock.SYRIAC ||
|
|
1291
|
-
block == Character.UnicodeBlock.ARABIC_SUPPLEMENT ||
|
|
1292
|
-
block == Character.UnicodeBlock.THAANA ||
|
|
1293
|
-
block == Character.UnicodeBlock.NKO ||
|
|
1294
|
-
block == Character.UnicodeBlock.SAMARITAN ||
|
|
1295
|
-
block == Character.UnicodeBlock.MANDAIC ||
|
|
1296
|
-
block == Character.UnicodeBlock.ARABIC_EXTENDED_A;
|
|
1297
|
-
// Add other RTL blocks as needed
|
|
1298
|
-
}
|
|
1299
|
-
public String[] maybeReverseRTLStringList(String[] in){
|
|
1300
|
-
String[] out = new String[in.length];
|
|
1301
|
-
for(int i = 0; i < in.length; i++)
|
|
1302
|
-
out[i] = maybeReverseRTLString(in[i]);
|
|
1303
|
-
return out;
|
|
1255
|
+
fun maybeReverseRTLStringList(input: Array<String>): Array<String> {
|
|
1256
|
+
val out = arrayOfNulls<String>(input.size)
|
|
1257
|
+
for (i in 0 until input.size)
|
|
1258
|
+
out[i] = maybeReverseRTLString(input[i])
|
|
1259
|
+
@Suppress("UNCHECKED_CAST")
|
|
1260
|
+
return out as Array<String>
|
|
1304
1261
|
}
|
|
1305
1262
|
|
|
1306
|
-
|
|
1307
|
-
if (
|
|
1308
|
-
return
|
|
1263
|
+
fun displayPromptView(prompt: String, options: Array<String>?) {
|
|
1264
|
+
if (connectionState != ConnTypes.CONNECTED) {
|
|
1265
|
+
return
|
|
1309
1266
|
}
|
|
1310
1267
|
|
|
1311
1268
|
// ultraliteCanvas.clear();
|