@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.
Files changed (69) hide show
  1. package/README.md +30 -11
  2. package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +47 -12
  3. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +75 -29
  4. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +1 -5
  5. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +208 -45
  6. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdkDebug.kt +14 -0
  7. package/android/src/main/java/com/mentra/bluetoothsdk/ObservableStore.kt +20 -0
  8. package/android/src/main/java/com/mentra/bluetoothsdk/OtaManifest.kt +153 -0
  9. package/android/src/main/java/com/mentra/bluetoothsdk/camera/CameraModels.kt +80 -14
  10. package/android/src/main/java/com/mentra/bluetoothsdk/controllers/ControllerManager.kt +4 -16
  11. package/android/src/main/java/com/mentra/bluetoothsdk/controllers/R1.kt +4 -8
  12. package/android/src/main/java/com/mentra/bluetoothsdk/services/PhoneMic.kt +90 -4
  13. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.kt +3831 -0
  14. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +20 -28
  15. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/{Mach1.java → Mach1.kt} +514 -561
  16. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.kt +8674 -0
  17. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +12 -3
  18. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +5 -17
  19. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Simulated.kt +9 -20
  20. package/android/src/main/java/com/mentra/bluetoothsdk/status/DeviceStatus.kt +0 -6
  21. package/android/src/main/java/com/mentra/bluetoothsdk/streaming/StreamModels.kt +16 -33
  22. package/build/BluetoothSdk.types.d.ts +48 -17
  23. package/build/BluetoothSdk.types.d.ts.map +1 -1
  24. package/build/BluetoothSdk.types.js.map +1 -1
  25. package/build/_private/BluetoothSdkModule.d.ts +9 -9
  26. package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
  27. package/build/_private/BluetoothSdkModule.js +0 -6
  28. package/build/_private/BluetoothSdkModule.js.map +1 -1
  29. package/build/_private/photoRequestPayload.d.ts +3 -1
  30. package/build/_private/photoRequestPayload.d.ts.map +1 -1
  31. package/build/_private/photoRequestPayload.js +46 -2
  32. package/build/_private/photoRequestPayload.js.map +1 -1
  33. package/build/debug.d.ts +3 -0
  34. package/build/debug.d.ts.map +1 -0
  35. package/build/debug.js +8 -0
  36. package/build/debug.js.map +1 -0
  37. package/build/index.d.ts +1 -1
  38. package/build/index.d.ts.map +1 -1
  39. package/build/index.js +8 -8
  40. package/build/index.js.map +1 -1
  41. package/ios/BluetoothSdkModule.swift +44 -68
  42. package/ios/Source/BluetoothSdkDefaults.swift +23 -3
  43. package/ios/Source/DeviceManager.swift +38 -33
  44. package/ios/Source/DeviceStore.swift +5 -5
  45. package/ios/Source/MentraBluetoothSDK.swift +217 -50
  46. package/ios/Source/MentraBluetoothSDKDebug.swift +12 -0
  47. package/ios/Source/ObservableStore.swift +11 -0
  48. package/ios/Source/OtaManifest.swift +170 -0
  49. package/ios/Source/camera/CameraModels.swift +219 -13
  50. package/ios/Source/controllers/ControllerManager.swift +3 -7
  51. package/ios/Source/controllers/R1.swift +3 -7
  52. package/ios/Source/sgcs/Frame.swift +0 -2
  53. package/ios/Source/sgcs/G1.swift +7 -8
  54. package/ios/Source/sgcs/G2.swift +21 -20
  55. package/ios/Source/sgcs/Mach1.swift +7 -8
  56. package/ios/Source/sgcs/MentraLive.swift +132 -63
  57. package/ios/Source/sgcs/MentraNex.swift +7 -8
  58. package/ios/Source/sgcs/SGCManager.swift +7 -10
  59. package/ios/Source/sgcs/Simulated.swift +8 -8
  60. package/ios/Source/status/DeviceStatus.swift +1 -9
  61. package/ios/Source/streaming/StreamModels.swift +7 -32
  62. package/package.json +6 -1
  63. package/src/BluetoothSdk.types.ts +49 -17
  64. package/src/_private/BluetoothSdkModule.ts +9 -17
  65. package/src/_private/photoRequestPayload.ts +48 -3
  66. package/src/debug.ts +9 -0
  67. package/src/index.ts +19 -10
  68. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.java +0 -3974
  69. 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.annotation.NonNull;
13
- import androidx.annotation.Nullable;
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.sgcs.SGCManager;
19
- import com.mentra.bluetoothsdk.DeviceManager;
20
- import com.mentra.bluetoothsdk.Bridge;
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
- public class Mach1 extends SGCManager {
61
- private static final String TAG = "WearableAi_UltraliteSGC";
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
- UltraliteSDK ultraliteSdk;
64
- UltraliteSDK.Canvas ultraliteCanvas;
65
- UltraliteListener ultraliteListener;
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
- private ArrayList rowTextsLiveNow;
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
- int ultraliteLeftSidePixelBuffer = 40;
113
+ var ultraliteLeftSidePixelBuffer = 40
75
114
 
76
115
  //handler to turn off screen
77
- Handler goHomeHandler;
78
- Runnable goHomeRunnable;
116
+ var goHomeHandler: Handler? = null
117
+ var goHomeRunnable: Runnable? = null
79
118
 
80
119
  //handler to turn off screen/toggle
81
- Handler screenOffHandler;
82
- Runnable screenOffRunnable;
120
+ var screenOffHandler: Handler? = null
121
+ var screenOffRunnable: Runnable? = null
83
122
 
84
123
  //handler to check battery life
85
- Handler batteryHandler;
86
- Runnable batteryRunnable;
124
+ var batteryHandler: Handler? = null
125
+ var batteryRunnable: Runnable? = null
87
126
 
88
127
  //handler to disconnect
89
- Handler killHandler;
128
+ var killHandler: Handler? = null
90
129
 
91
- boolean hasUltraliteControl;
92
- boolean screenIsClear;
93
- boolean isHeadUp = false; // Dashboard state toggled by taps
130
+ var hasUltraliteControl = false
131
+ var screenIsClear = false
132
+ var isHeadUp = false // Dashboard state toggled by taps
94
133
  // SmartGlassesDevice smartGlassesDevice;
95
- private static final long TAP_DEBOUNCE_TIME = 80; // milliseconds
96
- private long lastTapTime = 0;
97
- private int totalDashboardsIdk = 0;
134
+ private var lastTapTime = 0L
135
+ private var totalDashboardsIdk = 0
98
136
 
99
- private boolean hasBattery() {
100
- Object level = DeviceStore.INSTANCE.get("glasses", "batteryLevel");
101
- return level instanceof Number && ((Number) level).intValue() != -1;
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 void updateConnectionState(String state) {
105
- boolean isEqual = state.equals(getConnectionState());
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.INSTANCE.apply("glasses", "connectionState", state);
149
+ DeviceStore.apply("glasses", "connectionState", state)
112
150
 
113
- if (state.equals(ConnTypes.CONNECTED)) {
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.INSTANCE.apply("glasses", "connected", true);
117
- DeviceStore.INSTANCE.apply("glasses", "fullyBooted", true);
154
+ DeviceStore.apply("glasses", "connected", true)
155
+ DeviceStore.apply("glasses", "fullyBooted", true)
118
156
  }
119
- } else if (state.equals(ConnTypes.DISCONNECTED)) {
120
- DeviceStore.INSTANCE.apply("glasses", "fullyBooted", false);
121
- DeviceStore.INSTANCE.apply("glasses", "connected", false);
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
- @Override
126
- public void setMicEnabled(boolean enabled) {
163
+ override fun setMicEnabled(enabled: Boolean) {
127
164
  }
128
165
 
129
- @Override
130
- public List<String> sortMicRanking(List<String> list) {
131
- return list;
166
+ override fun sortMicRanking(list: MutableList<String>): MutableList<String> {
167
+ return list
132
168
  }
133
169
 
134
- @Override
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
- @Override
140
- public void startStream(@NonNull Map<String, Object> message) {
174
+ override fun startStream(message: MutableMap<String, Any>) {
141
175
 
142
176
  }
143
177
 
144
- @Override
145
- public void stopStream() {
178
+ override fun stopStream() {
146
179
 
147
180
  }
148
181
 
149
- @Override
150
- public void sendStreamKeepAlive(@NonNull Map<String, Object> message) {
182
+ override fun sendStreamKeepAlive(message: MutableMap<String, Any>) {
151
183
 
152
184
  }
153
185
 
154
- @Override
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
- @Override
160
- public void stopVideoRecording(@NonNull String requestId) {
190
+ override fun stopVideoRecording(requestId: String) {
161
191
 
162
192
  }
163
193
 
164
- @Override
165
- public void sendButtonPhotoSettings() {
194
+ override fun sendButtonPhotoSettings() {
166
195
 
167
196
  }
168
197
 
169
- @Override
170
- public void sendButtonVideoRecordingSettings() {
198
+ override fun sendButtonVideoRecordingSettings() {
171
199
 
172
200
  }
173
201
 
174
- @Override
175
- public void sendButtonMaxRecordingTime() {
202
+ override fun sendButtonMaxRecordingTime() {
176
203
 
177
204
  }
178
205
 
179
- @Override
180
- public void sendButtonCameraLedSetting() {
181
-
206
+ override fun sendCameraFovSetting() {
182
207
  }
183
208
 
184
- @Override
185
- public void sendCameraFovSetting() {
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
- @Override
189
- public void setBrightness(int level, boolean autoMode) {
190
- Bridge.log("Mach1: setBrightness() - level: " + level + "%, autoMode: " + autoMode);
191
- updateGlassesBrightness(level);
192
- updateGlassesAutoBrightness(autoMode);
215
+ override fun clearDisplay() {
216
+ Bridge.log("Mach1: clearDisplay()")
217
+ blankScreen()
193
218
  }
194
219
 
195
- @Override
196
- public void clearDisplay() {
197
- Bridge.log("Mach1: clearDisplay()");
198
- blankScreen();
220
+ override fun sendText(text: String) {
221
+ Bridge.log("Mach1: sendText() - text: " + text)
222
+ displayTextWall(text)
199
223
  }
200
224
 
201
- @Override
202
- public void sendTextWall(@NonNull String text) {
203
- Bridge.log("Mach1: sendTextWall()");
204
- displayTextWall(text);
225
+ override fun sendTextWall(text: String) {
226
+ Bridge.log("Mach1: sendTextWall()")
227
+ displayTextWall(text)
205
228
  }
206
229
 
207
- @Override
208
- public void sendDoubleTextWall(@NonNull String top, @NonNull String bottom) {
209
- Bridge.log("Mach1: sendDoubleTextWall()");
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
- @Override
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
- byte[] bmpData = android.util.Base64.decode(base64ImageData, android.util.Base64.DEFAULT);
239
+ val bmpData = android.util.Base64.decode(base64ImageData, android.util.Base64.DEFAULT)
219
240
 
220
- if (bmpData == null || bmpData.length == 0) {
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
- Bitmap bitmap = BitmapFactory.decodeByteArray(bmpData, 0, bmpData.length);
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 e) {
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
- @Override
243
- public void showDashboard() {
263
+ override fun showDashboard() {
244
264
 
245
265
  }
246
266
 
247
- @Override
248
- public void ping() {
267
+ override fun ping() {
249
268
  }
250
269
 
251
- @Override
252
- public void dbg1() {}
270
+ override fun dbg1() {}
253
271
 
254
- @Override
255
- public void dbg2() {}
272
+ override fun dbg2() {}
256
273
 
257
- @Override
258
- public void setDashboardPosition(int height, int depth) {
274
+ override fun setDashboardPosition(height: Int, depth: Int) {
259
275
 
260
276
  }
261
277
 
262
- @Override
263
- public void setHeadUpAngle(int angle) {
278
+ override fun setHeadUpAngle(angle: Int) {
264
279
 
265
280
  }
266
281
 
267
- @Override
268
- public void getBatteryStatus() {
282
+ override fun getBatteryStatus() {
269
283
 
270
284
  }
271
285
 
272
- @Override
273
- public void setSilentMode(boolean enabled) {
286
+ override fun setSilentMode(enabled: Boolean) {
274
287
 
275
288
  }
276
289
 
277
- @Override
278
- public void exit() {
290
+ override fun exit() {
279
291
 
280
292
  }
281
293
 
282
- @Override
283
- public void sendShutdown() {
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
- @Override
288
- public void sendReboot() {
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
- @Override
293
- public void sendRgbLedControl(String requestId, String packageName, String action, String color, int onDurationMs, int offDurationMs, int count) {
294
- Bridge.log("sendRgbLedControl - not supported on Mach1");
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
- @Override
299
- public void disconnect() {
300
- Bridge.log("Mach1: disconnect()");
307
+ override fun disconnect() {
308
+ Bridge.log("Mach1: disconnect()")
301
309
  if (ultraliteSdk != null) {
302
- ultraliteSdk.releaseControl();
303
- updateConnectionState(ConnTypes.DISCONNECTED);
310
+ ultraliteSdk!!.releaseControl()
311
+ updateConnectionState(ConnTypes.DISCONNECTED)
304
312
  }
305
313
  }
306
314
 
307
- @Override
308
- public void forget() {
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
- @Override
315
- public void findCompatibleDevices() {
316
- Bridge.log("Mach1: findCompatibleDevices()");
317
- findCompatibleDeviceNames();
321
+ override fun findCompatibleDevices() {
322
+ Bridge.log("Mach1: findCompatibleDevices()")
323
+ findCompatibleDeviceNames()
318
324
  }
319
325
 
320
- @Override
321
- public void stopScan() {
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
- @Override
326
- public void connectById(@NonNull String id) {
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
- @NonNull
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
- LiveData<Boolean> connected = ultraliteSdk.getConnected();
340
- if (connected != null && Boolean.TRUE.equals(connected.getValue())) {
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
- @Override
348
- public void cleanup() {
349
- destroy();
349
+ override fun cleanup() {
350
+ destroy()
350
351
  }
351
352
 
352
- @Override
353
- public void requestWifiScan() {
353
+ override fun requestWifiScan() {
354
354
 
355
355
  }
356
356
 
357
- @Override
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
- @Override
363
- public void forgetWifiNetwork(String ssid) {
361
+ override fun forgetWifiNetwork(ssid: String) {
364
362
  // Mach1 doesn't support WiFi
365
363
  }
366
364
 
367
- @Override
368
- public void sendHotspotState(boolean enabled) {
365
+ override fun sendHotspotState(enabled: Boolean) {
369
366
  // Mach1 doesn't support hotspot
370
367
  }
371
368
 
372
- @Override
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
- @Override
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
- @Override
383
- public void queryGalleryStatus() {
377
+ override fun queryGalleryStatus() {
384
378
 
385
379
  }
386
380
 
387
- @Override
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
- @Override
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
- public class UltraliteListener implements EventListener{
400
- @Override
401
- public void onTap(int tapCount) {
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.INSTANCE.apply("glasses", "headUp", isHeadUp);
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.postDelayed(() -> {
413
+ goHomeHandler!!.postDelayed({
423
414
  if (isHeadUp) {
424
- isHeadUp = false;
425
- DeviceStore.INSTANCE.apply("glasses", "headUp", false);
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
- }, 15000);
419
+ }, 15000L)
429
420
  }
430
421
  }
431
422
  }
432
423
 
433
- @Override
434
- public void onDisplayTimeout() {
435
- Log.d(TAG, "Ultralite display timeout.");
424
+ override fun onDisplayTimeout() {
425
+ Log.d(TAG, "Ultralite display timeout.")
436
426
  }
437
427
 
438
- @Override
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
- private LiveData<Boolean> ultraliteConnectedLive;
455
- private LiveData<Boolean> ultraliteControlled;
456
- private LiveData<BatteryStatus> batteryStatusObserver;
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> connectedObserver;
460
- private Observer<Boolean> controlledObserver;
461
- private Observer<BatteryStatus> batteryObserver;
449
+ private var connectedObserver: Observer<Boolean>? = null
450
+ private var controlledObserver: Observer<Boolean>? = null
451
+ private var batteryObserver: Observer<BatteryStatus?>? = null
462
452
 
463
- public Mach1() {
464
- super();
465
- this.type = DeviceTypes.MACH1;
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 = new Handler(Looper.getMainLooper());
476
- screenOffHandler = new Handler(Looper.getMainLooper());
477
- killHandler = new Handler(Looper.getMainLooper());
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 = new ArrayList<Integer>();
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 = new UltraliteListener();
488
- ultraliteSdk.addEventListener(ultraliteListener);
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.getConnected();
493
- ultraliteControlled = ultraliteSdk.getControlledByMe();
494
- batteryStatusObserver = ultraliteSdk.getBatteryStatus();
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
- new Handler(Looper.getMainLooper()).post(() -> {
500
+ Handler(Looper.getMainLooper()).post {
512
501
  try {
513
- ultraliteConnectedLive.observeForever(connectedObserver);
514
- Log.d(TAG, "Mach1: Connected observer registered");
502
+ ultraliteConnectedLive!!.observeForever(connectedObserver!!)
503
+ Log.d(TAG, "Mach1: Connected observer registered")
515
504
 
516
- ultraliteControlled.observeForever(controlledObserver);
517
- Log.d(TAG, "Mach1: Controlled observer registered");
505
+ ultraliteControlled!!.observeForever(controlledObserver!!)
506
+ Log.d(TAG, "Mach1: Controlled observer registered")
518
507
 
519
- batteryStatusObserver.observeForever(batteryObserver);
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 e) {
524
- Log.e(TAG, "Mach1: Failed to register observers: " + e.getMessage(), 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 e) {
530
- Log.e(TAG, "Mach1 constructor FAILED with exception: " + e.getMessage(), e);
531
- Bridge.log("Mach1 constructor FAILED: " + e.getMessage());
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
- public void updateGlassesBrightness(int brightness) {
524
+ fun updateGlassesBrightness(brightness: Int) {
536
525
  // TODO: Implement this method
537
526
  }
538
527
 
539
- public void updateGlassesAutoBrightness(boolean autoBrightness) {
528
+ fun updateGlassesAutoBrightness(autoBrightness: Boolean) {
540
529
  // TODO: Implement this method
541
530
  }
542
531
 
543
- private void onUltraliteConnectedChange(boolean isConnected) {
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
- boolean isControlled = ultraliteSdk.requestControl();
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 void onUltraliteControlChanged(boolean isControlledByMe) {
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 void onUltraliteBatteryChanged(BatteryStatus batteryStatus) {
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.getLevel());
584
- DeviceStore.INSTANCE.apply("glasses", "batteryLevel", batteryStatus.getLevel());
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 (getConnectionState().equals(ConnTypes.CONNECTED) && !getFullyBooted()) {
589
- DeviceStore.INSTANCE.apply("glasses", "connected", true);
590
- DeviceStore.INSTANCE.apply("glasses", "fullyBooted", true);
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 void setFontSizes(){
584
+ protected fun setFontSizes() {
596
585
  }
597
586
 
598
- public void findCompatibleDeviceNames() {
587
+ fun findCompatibleDeviceNames() {
599
588
  // EventBus.getDefault().post(new GlassesBluetoothSearchDiscoverEvent(smartGlassesDevice.deviceModelName, "NOTREQUIREDSKIP"));
600
- Bridge.sendDiscoveredDevice(this.type, "NOTREQUIREDSKIP"); // Use this.type to support both Mach1 and Z100
589
+ Bridge.sendDiscoveredDevice(this.type, "NOTREQUIREDSKIP") // Use this.type to support both Mach1 and Z100
601
590
  //this.destroy();
602
591
  }
603
592
 
604
- public void connectToSmartGlasses(){
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
- public void displayTextLine(String text){
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
- public void displayTextWall(String text) {
623
+ fun displayTextWall(text: String) {
635
624
  if (screenToggleOff) {
636
- return;
625
+ return
637
626
  }
638
627
 
639
- goHomeHandler.removeCallbacksAndMessages(null);
640
- goHomeHandler.removeCallbacksAndMessages(goHomeRunnable);
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.sendText(text);
632
+ changeUltraliteLayout(Layout.TEXT_BOTTOM_LEFT_ALIGN)
633
+ ultraliteSdk!!.sendText(text)
645
634
 
646
635
  if (ultraliteCanvas != null) {
647
- ultraliteCanvas.commit();
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
- public void displayDoubleTextWall(String textTop, String textBottom) {
651
+ fun displayDoubleTextWall(textTop: String, textBottom: String) {
663
652
  if (screenToggleOff) {
664
- return;
653
+ return
665
654
  }
666
655
 
667
- goHomeHandler.removeCallbacksAndMessages(null);
668
- goHomeHandler.removeCallbacksAndMessages(goHomeRunnable);
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
- String combinedText = textTop + "\n\n\n" + textBottom;
661
+ val combinedText = textTop + "\n\n\n" + textBottom
673
662
 
674
- changeUltraliteLayout(Layout.TEXT_BOTTOM_LEFT_ALIGN);
675
- ultraliteSdk.sendText(combinedText);
663
+ changeUltraliteLayout(Layout.TEXT_BOTTOM_LEFT_ALIGN)
664
+ ultraliteSdk!!.sendText(combinedText)
676
665
 
677
666
  if (ultraliteCanvas != null) {
678
- ultraliteCanvas.commit();
667
+ ultraliteCanvas!!.commit()
679
668
  }
680
- screenIsClear = false;
669
+ screenIsClear = false
681
670
  }
682
671
 
683
- public void displayCustomContent(String json) {
684
- displayReferenceCardSimple("CustomDisplayNotImplemented", json);
672
+ fun displayCustomContent(json: String) {
673
+ displayReferenceCardSimple("CustomDisplayNotImplemented", json)
685
674
  }
686
675
 
687
676
 
688
- public void showNaturalLanguageCommandScreen(String prompt, String naturalLanguageInput){
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
- public void updateNaturalLanguageCommandScreen(String naturalLanguageArgs){
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
- public void blankScreen(){
705
+ fun blankScreen() {
717
706
  // if (connectedGlasses != null){
718
707
  // connectedGlasses.clear();
719
708
  // }
720
709
  }
721
710
 
722
- public void destroy() {
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.removeObserver(connectedObserver);
715
+ ultraliteConnectedLive!!.removeObserver(connectedObserver!!)
727
716
  }
728
717
  if (ultraliteControlled != null && controlledObserver != null) {
729
- ultraliteControlled.removeObserver(controlledObserver);
718
+ ultraliteControlled!!.removeObserver(controlledObserver!!)
730
719
  }
731
720
  if (batteryStatusObserver != null && batteryObserver != null) {
732
- batteryStatusObserver.removeObserver(batteryObserver);
721
+ batteryStatusObserver!!.removeObserver(batteryObserver!!)
733
722
  }
734
723
 
735
724
  if (ultraliteSdk != null) {
736
725
  // Remove event listeners and release control
737
- ultraliteSdk.removeEventListener(ultraliteListener);
738
- ultraliteSdk.releaseControl();
739
- ultraliteSdk = null; // Nullify reference
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.removeCallbacksAndMessages(null);
733
+ goHomeHandler!!.removeCallbacksAndMessages(null)
745
734
  }
746
735
  if (screenOffHandler != null) {
747
- screenOffHandler.removeCallbacksAndMessages(null);
736
+ screenOffHandler!!.removeCallbacksAndMessages(null)
748
737
  }
749
738
  if (killHandler != null) {
750
- killHandler.removeCallbacksAndMessages(null);
739
+ killHandler!!.removeCallbacksAndMessages(null)
751
740
  }
752
741
 
753
742
  // Clear canvas and other resources
754
743
  if (ultraliteCanvas != null) {
755
- ultraliteCanvas.clear();
756
- ultraliteCanvas.commit();
757
- ultraliteCanvas = null;
744
+ ultraliteCanvas!!.clear()
745
+ ultraliteCanvas!!.commit()
746
+ ultraliteCanvas = null
758
747
  }
759
748
 
760
749
  // Reset state variables
761
- rowTextsLiveNow.clear();
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 e) {
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
- public void showHomeScreen() {
782
- Log.d(TAG, "SHOW HOME SCREEN");
783
- ultraliteSdk.screenOff();
784
- screenIsClear = true;
770
+ fun showHomeScreen() {
771
+ Log.d(TAG, "SHOW HOME SCREEN")
772
+ ultraliteSdk!!.screenOff()
773
+ screenIsClear = true
785
774
  }
786
775
 
787
- public void setupUltraliteCanvas(){
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.getCanvas();
779
+ ultraliteCanvas = ultraliteSdk!!.getCanvas()
791
780
  }
792
781
  }
793
782
 
794
- public void changeUltraliteLayout(Layout chosenLayout) {
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.screenOn();
789
+ ultraliteSdk!!.screenOn()
801
790
 
802
- currentUltraliteLayout = chosenLayout;
803
- ultraliteSdk.setLayout(chosenLayout, 0, true, false, 2);
791
+ currentUltraliteLayout = chosenLayout
792
+ ultraliteSdk!!.setLayout(chosenLayout, 0, true, false, 2)
804
793
 
805
- if (chosenLayout.equals(Layout.CANVAS)){
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
- public void drawTextOnUltralite(String text){
830
- UltraliteColor ultraliteColor = UltraliteColor.WHITE;
831
- Anchor ultraliteAnchor = Anchor.TOP_LEFT;
832
- TextAlignment ultraliteAlignment = TextAlignment.LEFT;
833
- changeUltraliteLayout(Layout.CANVAS);
834
- ultraliteCanvas.clear();
835
- ultraliteCanvas.clearBackground(UltraliteColor.DIM);
836
- ultraliteCanvas.createText(text, ultraliteAlignment, ultraliteColor, ultraliteAnchor, true);
837
- ultraliteCanvas.commit();
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
- public void displayReferenceCardSimple(String titleStr, String bodyStr){
900
- if (screenToggleOff){
901
- return;
888
+ fun displayReferenceCardSimple(titleStr: String, bodyStr: String) {
889
+ if (screenToggleOff) {
890
+ return
902
891
  }
903
892
 
904
- String title = maybeReverseRTLString(titleStr);
905
- String body = maybeReverseRTLString(bodyStr);
906
- if (!getConnectionState().equals(ConnTypes.CONNECTED)) {
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.clear();
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
- UltraliteColor ultraliteColor = UltraliteColor.WHITE;
933
- Anchor ultraliteAnchor = Anchor.TOP_CENTER;
934
- TextAlignment ultraliteAlignment = TextAlignment.LEFT;
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() && !title.equals("")){
937
- ultraliteCanvas.createText(title + ": " + body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_RIGHT, 0, 0, 640 / 2, -1, TextWrapMode.WRAP, true);
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.createText(body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_RIGHT, 0, 0, 640 / 2, -1, TextWrapMode.WRAP, true);
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.commit();
960
- screenIsClear = false;
948
+ ultraliteCanvas!!.commit()
949
+ screenIsClear = false
961
950
  }
962
951
 
963
952
 
964
- public void displayBulletList(String title, String [] bullets){
965
- displayBulletList(title, bullets, 14);
953
+ fun displayBulletList(title: String, bullets: Array<String>) {
954
+ displayBulletList(title, bullets, 14)
966
955
  }
967
956
 
968
- public void displayRowsCard(String[] rowStrings){
969
- displayRowsCard(rowStrings, cardLingerTime);
957
+ fun displayRowsCard(rowStrings: Array<String>) {
958
+ displayRowsCard(rowStrings, cardLingerTime)
970
959
  }
971
960
 
972
- public void displayRowsCard(String[] rowStringList, int lingerTime){
973
- if (screenToggleOff){
974
- return;
961
+ fun displayRowsCard(rowStringList: Array<String>, lingerTime: Int) {
962
+ if (screenToggleOff) {
963
+ return
975
964
  }
976
965
 
977
- String[] rowStrings = maybeReverseRTLStringList(rowStringList);
978
- if (!getConnectionState().equals(ConnTypes.CONNECTED)) {
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
- int line_thickness = 3;
988
- for (int y = 120; y < 480; y += 120) {
989
- ultraliteCanvas.clearBackgroundRect(0, y, 640, line_thickness, UltraliteColor.DIM);
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 (int i = 0; i < rowTextsLiveNow.size(); i++){
994
- ultraliteCanvas.removeText(i);
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
- UltraliteColor ultraliteColor = UltraliteColor.WHITE;
1006
- Anchor ultraliteAnchor = Anchor.TOP_LEFT;
1007
- TextAlignment ultraliteAlignment = TextAlignment.LEFT;
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.length == 0){
1011
- ultraliteCanvas.commit();
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
- int y_start_height = 55;
1008
+ val y_start_height = 55
1018
1009
  // Reverse rowStrings array
1019
- Collections.reverse(Arrays.asList(rowStrings));
1020
- int numRows = 4;
1021
- int actualRows = Math.min(rowStrings.length, numRows);
1022
- for (int i = 0; i < actualRows; i++) {
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
- int yOffset = (numRows - actualRows) * 112;
1025
- int 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);
1026
- rowTextsLiveNow.add(textId);
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.commit();
1030
- screenIsClear = false;
1020
+ ultraliteCanvas!!.commit()
1021
+ screenIsClear = false
1031
1022
  }
1032
1023
 
1033
- public void displayBulletList(String title, String [] bulletList, int lingerTime){
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
- String[] bullets = maybeReverseRTLStringList(bulletList);
1039
- if (!getConnectionState().equals(ConnTypes.CONNECTED)) {
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
- UltraliteColor ultraliteColor = UltraliteColor.WHITE;
1048
- Anchor ultraliteAnchor = Anchor.TOP_LEFT;
1049
- TextAlignment ultraliteAlignment = TextAlignment.LEFT;
1050
- changeUltraliteLayout(Layout.CANVAS);
1051
- ultraliteCanvas.clear();
1052
-
1053
- ultraliteCanvas.createText(title, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true);
1054
- int displaceY = 25;
1055
- int displaceX = 25;
1056
- for (String bullet : bullets){
1057
- ultraliteCanvas.createText("⬤ " + bullet, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_LEFT, displaceX, displaceY, 640 - displaceX, -1, TextWrapMode.WRAP, true);
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.commit();
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
- public void displayBitmap(Bitmap bmp) {
1082
- Bitmap resizedBmp = Bitmap.createScaledBitmap(bmp, 620, 460, true); // 640 x 480
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.drawBackground(resizedBmp, 50, 80);
1089
- ultraliteCanvas.commit();
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
- public void displayReferenceCardImage(String title, String body, String imgUrl){
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.clear();
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
- Anchor ultraliteImageAnchor = Anchor.CENTER;
1094
+ val ultraliteImageAnchor = Anchor.CENTER
1104
1095
  Picasso.get()
1105
1096
  .load(imgUrl)
1106
- .into(new Target() {
1107
- @Override
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.createText(title, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.TOP_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true);
1116
- ultraliteCanvas.createText(body, TextAlignment.AUTO, UltraliteColor.WHITE, Anchor.BOTTOM_LEFT, 0, 0, 640, -1, TextWrapMode.WRAP, true);
1117
- ultraliteCanvas.commit();
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.drawBackground(bitmap, 0, 0);
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
- @Override
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.printStackTrace();
1130
+ Log.d(TAG, "Bitmap failed")
1131
+ e!!.printStackTrace()
1143
1132
  }
1144
1133
 
1145
- @Override
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
- public void stopScrollingTextViewMode() {
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
- public void scrollingTextViewIntermediateText(String text){
1195
+ fun scrollingTextViewIntermediateText(text: String) {
1208
1196
  }
1209
1197
 
1210
- public void scrollingTextViewFinalText(String text){
1211
- if (!getConnectionState().equals(ConnTypes.CONNECTED)) {
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
- public static String maybeReverseRTLString(String text) {
1264
- StringBuilder result = new StringBuilder();
1265
- StringBuilder rtlBuffer = new StringBuilder();
1266
-
1267
- for (char c : text.toCharArray()) {
1268
- if (isRTLCharacter(c)) {
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
- public void displayPromptView(String prompt, String [] options){
1307
- if (!getConnectionState().equals(ConnTypes.CONNECTED)) {
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();