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