@glassly/bluetooth-sdk 0.1.0-dev.26

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 (548) hide show
  1. package/README.md +563 -0
  2. package/android/build.gradle +450 -0
  3. package/android/gradle.properties.example +9 -0
  4. package/android/lc3Lib/CMakeLists.txt +6 -0
  5. package/android/lc3Lib/build.gradle +212 -0
  6. package/android/lc3Lib/proguard-rules.pro +33 -0
  7. package/android/lc3Lib/src/main/AndroidManifest.xml +2 -0
  8. package/android/lc3Lib/src/main/cpp/CMakeLists.txt +8 -0
  9. package/android/lc3Lib/src/main/cpp/google_opus_stuff/CMakeLists.txt +30 -0
  10. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/CMakeLists.txt +7 -0
  11. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.cc +96 -0
  12. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.h +53 -0
  13. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/Makefile.am +6 -0
  14. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h +26 -0
  15. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h.in +26 -0
  16. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/ogg.h +209 -0
  17. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/os_types.h +158 -0
  18. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus.h +981 -0
  19. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_custom.h +342 -0
  20. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_defines.h +799 -0
  21. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_multistream.h +660 -0
  22. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_projection.h +568 -0
  23. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_types.h +166 -0
  24. package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.cc +268 -0
  25. package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.h +115 -0
  26. package/android/lc3Lib/src/main/cpp/google_opus_stuff/opus_tools/opus_header.h +59 -0
  27. package/android/lc3Lib/src/main/cpp/liblc3/CMakeLists.txt +38 -0
  28. package/android/lc3Lib/src/main/cpp/liblc3/include/lc3.h +309 -0
  29. package/android/lc3Lib/src/main/cpp/liblc3/include/lc3_private.h +162 -0
  30. package/android/lc3Lib/src/main/cpp/liblc3/include/rnnoise.h +114 -0
  31. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/CMakeLists.txt +19 -0
  32. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.c +92 -0
  33. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.h +44 -0
  34. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.c +375 -0
  35. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.h +315 -0
  36. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.c +129 -0
  37. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.h +69 -0
  38. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/common.h +148 -0
  39. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.c +70 -0
  40. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.h +43 -0
  41. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/fastmath.h +158 -0
  42. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/lc3.c +702 -0
  43. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.c +893 -0
  44. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.h +111 -0
  45. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_arm.h +506 -0
  46. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_neon.h +281 -0
  47. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/makefile.mk +35 -0
  48. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.c +452 -0
  49. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.h +57 -0
  50. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct_neon.h +296 -0
  51. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/meson.build +46 -0
  52. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.c +61 -0
  53. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.h +57 -0
  54. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.c +880 -0
  55. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.h +103 -0
  56. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.c +904 -0
  57. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.h +119 -0
  58. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.c +3457 -0
  59. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.h +94 -0
  60. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.c +457 -0
  61. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.h +99 -0
  62. package/android/lc3Lib/src/main/cpp/liblc3/liblc3.cpp +159 -0
  63. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/_kiss_fft_guts.h +182 -0
  64. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/arch.h +261 -0
  65. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.c +279 -0
  66. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.h +59 -0
  67. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/common.h +48 -0
  68. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/compile.sh +3 -0
  69. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/denoise.c +646 -0
  70. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.c +601 -0
  71. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.h +203 -0
  72. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/opus_types.h +159 -0
  73. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.c +526 -0
  74. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.h +149 -0
  75. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.c +178 -0
  76. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.h +69 -0
  77. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.c +11051 -0
  78. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.h +34 -0
  79. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_reader.c +168 -0
  80. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_train.py +66 -0
  81. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/tansig_table.h +45 -0
  82. package/android/lc3Lib/src/main/java/com/glassly/lc3Lib/Lc3Cpp.java +38 -0
  83. package/android/lc3Lib/third_party/CMakeLists.txt +23 -0
  84. package/android/lc3Lib/third_party/CMakeLists_libogg.txt +18 -0
  85. package/android/lc3Lib/third_party/CMakeLists_libopus.txt +18 -0
  86. package/android/lc3Lib/third_party/CMakeLists_opus-tools.txt +23 -0
  87. package/android/lc3Lib/third_party/opus_tools/src/AUTHORS +5 -0
  88. package/android/lc3Lib/third_party/opus_tools/src/CMakeLists.txt +4 -0
  89. package/android/lc3Lib/third_party/opus_tools/src/COPYING +371 -0
  90. package/android/lc3Lib/third_party/opus_tools/src/ChangeLog +3 -0
  91. package/android/lc3Lib/third_party/opus_tools/src/Makefile.am +42 -0
  92. package/android/lc3Lib/third_party/opus_tools/src/Makefile.unix +23 -0
  93. package/android/lc3Lib/third_party/opus_tools/src/NEWS +0 -0
  94. package/android/lc3Lib/third_party/opus_tools/src/README +0 -0
  95. package/android/lc3Lib/third_party/opus_tools/src/autogen.sh +115 -0
  96. package/android/lc3Lib/third_party/opus_tools/src/configure.ac +293 -0
  97. package/android/lc3Lib/third_party/opus_tools/src/src/arch.h +239 -0
  98. package/android/lc3Lib/third_party/opus_tools/src/src/audio-in.c +1046 -0
  99. package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.c +245 -0
  100. package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.h +28 -0
  101. package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.c +320 -0
  102. package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.h +51 -0
  103. package/android/lc3Lib/third_party/opus_tools/src/src/lpc.c +157 -0
  104. package/android/lc3Lib/third_party/opus_tools/src/src/lpc.h +27 -0
  105. package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.c +286 -0
  106. package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.h +59 -0
  107. package/android/lc3Lib/third_party/opus_tools/src/src/opusdec.c +884 -0
  108. package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.c +1021 -0
  109. package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.h +101 -0
  110. package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.c +639 -0
  111. package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.h +51 -0
  112. package/android/lc3Lib/third_party/opus_tools/src/src/os_support.h +167 -0
  113. package/android/lc3Lib/third_party/opus_tools/src/src/resample.c +1137 -0
  114. package/android/lc3Lib/third_party/opus_tools/src/src/speex_resampler.h +344 -0
  115. package/android/lc3Lib/third_party/opus_tools/src/src/stack_alloc.h +115 -0
  116. package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.c +125 -0
  117. package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.h +62 -0
  118. package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.c +223 -0
  119. package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.h +60 -0
  120. package/android/settings.gradle +4 -0
  121. package/android/silero/LICENSE.md +17 -0
  122. package/android/silero/build.gradle +50 -0
  123. package/android/silero/proguard-rules.pro +24 -0
  124. package/android/silero/src/androidTest/assets/hello.wav +0 -0
  125. package/android/silero/src/androidTest/java/com/konovalov/vad/silero/VadSileroTest.kt +79 -0
  126. package/android/silero/src/main/assets/LICENSE +21 -0
  127. package/android/silero/src/main/assets/silero_vad.onnx +0 -0
  128. package/android/silero/src/main/java/com/konovalov/vad/silero/Vad.kt +160 -0
  129. package/android/silero/src/main/java/com/konovalov/vad/silero/VadSilero.kt +449 -0
  130. package/android/silero/src/main/java/com/konovalov/vad/silero/config/FrameSize.kt +15 -0
  131. package/android/silero/src/main/java/com/konovalov/vad/silero/config/Mode.kt +14 -0
  132. package/android/silero/src/main/java/com/konovalov/vad/silero/config/SampleRate.kt +12 -0
  133. package/android/silero/src/main/java/com/konovalov/vad/silero/utils/AudioUtils.kt +47 -0
  134. package/android/silero/src/main/java/com/konovalov/vad/silero/utils/TensorMap.kt +41 -0
  135. package/android/silero/src/test/java/com/konovalov/vad/silero/utils/AudioUtilsTest.kt +44 -0
  136. package/android/src/main/AndroidManifest.xml +42 -0
  137. package/android/src/main/assets/G2Firmware/README.md +11 -0
  138. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdk.kt +2325 -0
  139. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkAnalytics.kt +216 -0
  140. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDebug.kt +14 -0
  141. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDefaults.kt +7 -0
  142. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkModule.kt +1088 -0
  143. package/android/src/main/java/com/glassly/bluetoothsdk/Bridge.kt +953 -0
  144. package/android/src/main/java/com/glassly/bluetoothsdk/DeviceManager.kt +2528 -0
  145. package/android/src/main/java/com/glassly/bluetoothsdk/DeviceStore.kt +360 -0
  146. package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedChangelogCatalog.kt +8 -0
  147. package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedReleaseMetadata.kt +11 -0
  148. package/android/src/main/java/com/glassly/bluetoothsdk/LocalNetworkModule.kt +414 -0
  149. package/android/src/main/java/com/glassly/bluetoothsdk/ObservableStore.kt +88 -0
  150. package/android/src/main/java/com/glassly/bluetoothsdk/OtaManifest.kt +191 -0
  151. package/android/src/main/java/com/glassly/bluetoothsdk/ReleaseChangelog.kt +61 -0
  152. package/android/src/main/java/com/glassly/bluetoothsdk/ScopedNetworkReadiness.kt +17 -0
  153. package/android/src/main/java/com/glassly/bluetoothsdk/audio/AudioModels.kt +144 -0
  154. package/android/src/main/java/com/glassly/bluetoothsdk/camera/CameraModels.kt +486 -0
  155. package/android/src/main/java/com/glassly/bluetoothsdk/connection/ConnectionModels.kt +78 -0
  156. package/android/src/main/java/com/glassly/bluetoothsdk/controllers/ControllerManager.kt +158 -0
  157. package/android/src/main/java/com/glassly/bluetoothsdk/controllers/R1.kt +937 -0
  158. package/android/src/main/java/com/glassly/bluetoothsdk/debug/BleTraceLogger.kt +165 -0
  159. package/android/src/main/java/com/glassly/bluetoothsdk/events/BluetoothEvents.kt +178 -0
  160. package/android/src/main/java/com/glassly/bluetoothsdk/internal/MapParsing.kt +140 -0
  161. package/android/src/main/java/com/glassly/bluetoothsdk/net/LocalIpv4.kt +57 -0
  162. package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServer.kt +304 -0
  163. package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/OtaServerModule.kt +120 -0
  164. package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistry.java +108 -0
  165. package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoUploadServer.kt +622 -0
  166. package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/PhotoReceiverModule.kt +156 -0
  167. package/android/src/main/java/com/glassly/bluetoothsdk/requests/DisplayRequests.kt +56 -0
  168. package/android/src/main/java/com/glassly/bluetoothsdk/services/Foreground.kt +272 -0
  169. package/android/src/main/java/com/glassly/bluetoothsdk/services/PhoneMic.kt +1195 -0
  170. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Ar99.java +2653 -0
  171. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuard.kt +49 -0
  172. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapper.kt +27 -0
  173. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1.kt +3878 -0
  174. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizer.kt +38 -0
  175. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2.kt +6428 -0
  176. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassification.kt +49 -0
  177. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwRenderer.kt +1241 -0
  178. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCache.kt +270 -0
  179. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocol.kt +291 -0
  180. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2Flasher.kt +411 -0
  181. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/GlasslyBle.java +43189 -0
  182. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Mach1.kt +1280 -0
  183. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLive.kt +10817 -0
  184. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLiveL2capChannel.kt +274 -0
  185. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisement.kt +54 -0
  186. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraNex.kt +2011 -0
  187. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Nimo.kt +2532 -0
  188. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/SGCManager.kt +470 -0
  189. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Simulated.kt +228 -0
  190. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/Ar99OtaManager.java +566 -0
  191. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaByteUtils.java +18 -0
  192. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCommandConstants.java +35 -0
  193. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCrc32Util.java +13 -0
  194. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaGattTransport.java +11 -0
  195. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaProtocol.java +92 -0
  196. package/android/src/main/java/com/glassly/bluetoothsdk/speakerid/SpeakerIdEngine.kt +525 -0
  197. package/android/src/main/java/com/glassly/bluetoothsdk/status/DeviceStatus.kt +669 -0
  198. package/android/src/main/java/com/glassly/bluetoothsdk/status/RuntimeState.kt +201 -0
  199. package/android/src/main/java/com/glassly/bluetoothsdk/status/WifiHotspotStatus.kt +189 -0
  200. package/android/src/main/java/com/glassly/bluetoothsdk/streaming/StreamModels.kt +518 -0
  201. package/android/src/main/java/com/glassly/bluetoothsdk/stt/STTTools.kt +391 -0
  202. package/android/src/main/java/com/glassly/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +518 -0
  203. package/android/src/main/java/com/glassly/bluetoothsdk/stt/VadGateSpeechPolicy.kt +229 -0
  204. package/android/src/main/java/com/glassly/bluetoothsdk/tts/TTSTools.kt +248 -0
  205. package/android/src/main/java/com/glassly/bluetoothsdk/types/DeviceModels.kt +96 -0
  206. package/android/src/main/java/com/glassly/bluetoothsdk/utils/AES.java +106 -0
  207. package/android/src/main/java/com/glassly/bluetoothsdk/utils/AudioSessionMonitor.kt +189 -0
  208. package/android/src/main/java/com/glassly/bluetoothsdk/utils/AvifExifStripper.java +573 -0
  209. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BitmapJavaUtils.java +169 -0
  210. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleJsonCompact.java +496 -0
  211. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadService.java +677 -0
  212. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleWireProtocol.java +108 -0
  213. package/android/src/main/java/com/glassly/bluetoothsdk/utils/Constants.kt +46 -0
  214. package/android/src/main/java/com/glassly/bluetoothsdk/utils/G1Text.kt +436 -0
  215. package/android/src/main/java/com/glassly/bluetoothsdk/utils/HeifExifTagReader.java +199 -0
  216. package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleRelayNaming.java +29 -0
  217. package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleUploadService.java +77 -0
  218. package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900LengthCodec.java +115 -0
  219. package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtils.java +827 -0
  220. package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunkReassembler.java +228 -0
  221. package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunker.java +325 -0
  222. package/android/src/main/java/com/glassly/bluetoothsdk/utils/NexSGCUtils.kt +698 -0
  223. package/android/src/main/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitor.kt +348 -0
  224. package/android/src/main/java/com/glassly/bluetoothsdk/utils/SmartGlassesConnectionState.java +9 -0
  225. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Ar99OpusPcmDecoder.java +398 -0
  226. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/ByteUtilAudioPlayer.java +655 -0
  227. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Lc3Player.java +441 -0
  228. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PCMAudioPlayer.java +431 -0
  229. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PcmStreamPlayer.kt +328 -0
  230. package/android/src/main/res/values/strings.xml +4 -0
  231. package/android/src/test/java/com/glassly/bluetoothsdk/BluetoothSdkExceptionTest.kt +18 -0
  232. package/android/src/test/java/com/glassly/bluetoothsdk/OtaManifestDowngradeTest.kt +86 -0
  233. package/android/src/test/java/com/glassly/bluetoothsdk/OtaStartResponsePolicyTest.kt +30 -0
  234. package/android/src/test/java/com/glassly/bluetoothsdk/ReleaseChangelogTest.kt +13 -0
  235. package/android/src/test/java/com/glassly/bluetoothsdk/ScopedNetworkReadinessTest.kt +39 -0
  236. package/android/src/test/java/com/glassly/bluetoothsdk/StreamStatusEventTest.kt +29 -0
  237. package/android/src/test/java/com/glassly/bluetoothsdk/camera/PhotoRequestTest.kt +141 -0
  238. package/android/src/test/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServerTest.kt +82 -0
  239. package/android/src/test/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistryTest.java +75 -0
  240. package/android/src/test/java/com/glassly/bluetoothsdk/services/ForegroundServiceTypeTest.kt +69 -0
  241. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/Ar99AdvertisementMatcherTest.java +22 -0
  242. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuardTest.kt +73 -0
  243. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapperTest.kt +67 -0
  244. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/EvenRleTest.kt +63 -0
  245. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizerTest.kt +31 -0
  246. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassificationTest.kt +89 -0
  247. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwRendererTest.kt +344 -0
  248. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCacheTest.kt +200 -0
  249. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocolTest.kt +131 -0
  250. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLiveGattCharacteristicsTest.kt +39 -0
  251. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisementParserTest.kt +133 -0
  252. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/NimoProtocolTest.kt +333 -0
  253. package/android/src/test/java/com/glassly/bluetoothsdk/utils/AvifExifStripperTest.java +46 -0
  254. package/android/src/test/java/com/glassly/bluetoothsdk/utils/BinaryMessageChunkerTest.java +84 -0
  255. package/android/src/test/java/com/glassly/bluetoothsdk/utils/BleJsonCompactTest.java +319 -0
  256. package/android/src/test/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadServiceTest.java +107 -0
  257. package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsEndiannessTest.java +172 -0
  258. package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsTest.java +24 -0
  259. package/android/src/test/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitorTest.kt +45 -0
  260. package/android/src/test/resources/avif_with_exif.avif +0 -0
  261. package/app.plugin.js +3 -0
  262. package/build/BluetoothSdk.types.d.ts +1354 -0
  263. package/build/BluetoothSdk.types.d.ts.map +1 -0
  264. package/build/BluetoothSdk.types.js +41 -0
  265. package/build/BluetoothSdk.types.js.map +1 -0
  266. package/build/_internal.d.ts +17 -0
  267. package/build/_internal.d.ts.map +1 -0
  268. package/build/_internal.js +16 -0
  269. package/build/_internal.js.map +1 -0
  270. package/build/_private/BluetoothSdkModule.d.ts +172 -0
  271. package/build/_private/BluetoothSdkModule.d.ts.map +1 -0
  272. package/build/_private/BluetoothSdkModule.js +300 -0
  273. package/build/_private/BluetoothSdkModule.js.map +1 -0
  274. package/build/_private/LocalNetworkModule.d.ts +38 -0
  275. package/build/_private/LocalNetworkModule.d.ts.map +1 -0
  276. package/build/_private/LocalNetworkModule.js +3 -0
  277. package/build/_private/LocalNetworkModule.js.map +1 -0
  278. package/build/_private/cameraRequestPayload.d.ts +4 -0
  279. package/build/_private/cameraRequestPayload.d.ts.map +1 -0
  280. package/build/_private/cameraRequestPayload.js +32 -0
  281. package/build/_private/cameraRequestPayload.js.map +1 -0
  282. package/build/_private/photoRequestPayload.d.ts +6 -0
  283. package/build/_private/photoRequestPayload.d.ts.map +1 -0
  284. package/build/_private/photoRequestPayload.js +86 -0
  285. package/build/_private/photoRequestPayload.js.map +1 -0
  286. package/build/_private/sdkOtaManifest.d.ts +11 -0
  287. package/build/_private/sdkOtaManifest.d.ts.map +1 -0
  288. package/build/_private/sdkOtaManifest.js +15 -0
  289. package/build/_private/sdkOtaManifest.js.map +1 -0
  290. package/build/changelogs.d.ts +7 -0
  291. package/build/changelogs.d.ts.map +1 -0
  292. package/build/changelogs.js +46 -0
  293. package/build/changelogs.js.map +1 -0
  294. package/build/debug.d.ts +3 -0
  295. package/build/debug.d.ts.map +1 -0
  296. package/build/debug.js +8 -0
  297. package/build/debug.js.map +1 -0
  298. package/build/generated/changelogCatalog.d.ts +9 -0
  299. package/build/generated/changelogCatalog.d.ts.map +1 -0
  300. package/build/generated/changelogCatalog.js +12 -0
  301. package/build/generated/changelogCatalog.js.map +1 -0
  302. package/build/generated/releaseMetadata.d.ts +12 -0
  303. package/build/generated/releaseMetadata.d.ts.map +1 -0
  304. package/build/generated/releaseMetadata.js +10 -0
  305. package/build/generated/releaseMetadata.js.map +1 -0
  306. package/build/index.d.ts +6 -0
  307. package/build/index.d.ts.map +1 -0
  308. package/build/index.js +171 -0
  309. package/build/index.js.map +1 -0
  310. package/build/ota-server/OtaServer.types.d.ts +14 -0
  311. package/build/ota-server/OtaServer.types.d.ts.map +1 -0
  312. package/build/ota-server/OtaServer.types.js +2 -0
  313. package/build/ota-server/OtaServer.types.js.map +1 -0
  314. package/build/ota-server/OtaServerModule.d.ts +21 -0
  315. package/build/ota-server/OtaServerModule.d.ts.map +1 -0
  316. package/build/ota-server/OtaServerModule.js +3 -0
  317. package/build/ota-server/OtaServerModule.js.map +1 -0
  318. package/build/ota-server/OtaServerModule.web.d.ts +10 -0
  319. package/build/ota-server/OtaServerModule.web.d.ts.map +1 -0
  320. package/build/ota-server/OtaServerModule.web.js +12 -0
  321. package/build/ota-server/OtaServerModule.web.js.map +1 -0
  322. package/build/ota-server/index.d.ts +3 -0
  323. package/build/ota-server/index.d.ts.map +1 -0
  324. package/build/ota-server/index.js +3 -0
  325. package/build/ota-server/index.js.map +1 -0
  326. package/build/ota-transport/index.d.ts +67 -0
  327. package/build/ota-transport/index.d.ts.map +1 -0
  328. package/build/ota-transport/index.js +58 -0
  329. package/build/ota-transport/index.js.map +1 -0
  330. package/build/photo-receiver/PhotoReceiver.types.d.ts +18 -0
  331. package/build/photo-receiver/PhotoReceiver.types.d.ts.map +1 -0
  332. package/build/photo-receiver/PhotoReceiver.types.js +2 -0
  333. package/build/photo-receiver/PhotoReceiver.types.js.map +1 -0
  334. package/build/photo-receiver/PhotoReceiverModule.d.ts +10 -0
  335. package/build/photo-receiver/PhotoReceiverModule.d.ts.map +1 -0
  336. package/build/photo-receiver/PhotoReceiverModule.js +3 -0
  337. package/build/photo-receiver/PhotoReceiverModule.js.map +1 -0
  338. package/build/photo-receiver/PhotoReceiverModule.web.d.ts +10 -0
  339. package/build/photo-receiver/PhotoReceiverModule.web.d.ts.map +1 -0
  340. package/build/photo-receiver/PhotoReceiverModule.web.js +12 -0
  341. package/build/photo-receiver/PhotoReceiverModule.web.js.map +1 -0
  342. package/build/photo-receiver/index.d.ts +3 -0
  343. package/build/photo-receiver/index.d.ts.map +1 -0
  344. package/build/photo-receiver/index.js +3 -0
  345. package/build/photo-receiver/index.js.map +1 -0
  346. package/build/react/index.d.ts +5 -0
  347. package/build/react/index.d.ts.map +1 -0
  348. package/build/react/index.js +4 -0
  349. package/build/react/index.js.map +1 -0
  350. package/build/react/useBluetooth.d.ts +100 -0
  351. package/build/react/useBluetooth.d.ts.map +1 -0
  352. package/build/react/useBluetooth.js +167 -0
  353. package/build/react/useBluetooth.js.map +1 -0
  354. package/build/react/useBluetoothEvent.d.ts +6 -0
  355. package/build/react/useBluetoothEvent.d.ts.map +1 -0
  356. package/build/react/useBluetoothEvent.js +21 -0
  357. package/build/react/useBluetoothEvent.js.map +1 -0
  358. package/build/react/useBluetoothScan.d.ts +22 -0
  359. package/build/react/useBluetoothScan.d.ts.map +1 -0
  360. package/build/react/useBluetoothScan.js +135 -0
  361. package/build/react/useBluetoothScan.js.map +1 -0
  362. package/build/react/useBluetoothStatus.d.ts +16 -0
  363. package/build/react/useBluetoothStatus.d.ts.map +1 -0
  364. package/build/react/useBluetoothStatus.js +137 -0
  365. package/build/react/useBluetoothStatus.js.map +1 -0
  366. package/build/react/useGlassesConnection.d.ts +29 -0
  367. package/build/react/useGlassesConnection.d.ts.map +1 -0
  368. package/build/react/useGlassesConnection.js +153 -0
  369. package/build/react/useGlassesConnection.js.map +1 -0
  370. package/build/types/index.d.ts +3 -0
  371. package/build/types/index.d.ts.map +1 -0
  372. package/build/types/index.js +2 -0
  373. package/build/types/index.js.map +1 -0
  374. package/expo-module.config.json +14 -0
  375. package/ios/BackgroundOtaArtifactDownloader.swift +125 -0
  376. package/ios/BluetoothSdkModule.swift +1034 -0
  377. package/ios/GlasslyBluetoothSDK.podspec +106 -0
  378. package/ios/LocalIPv4.swift +150 -0
  379. package/ios/LocalOtaServer.swift +309 -0
  380. package/ios/LocalPhotoUploadServer.swift +754 -0
  381. package/ios/OtaServerModule.swift +147 -0
  382. package/ios/Packages/CoreObjC/CoreObjC.xcodeproj/project.pbxproj +213 -0
  383. package/ios/Packages/CoreObjC/PcmConverter.h +22 -0
  384. package/ios/Packages/CoreObjC/PcmConverter.m +266 -0
  385. package/ios/Packages/CoreObjC/attdet.c +92 -0
  386. package/ios/Packages/CoreObjC/attdet.h +44 -0
  387. package/ios/Packages/CoreObjC/bits.c +375 -0
  388. package/ios/Packages/CoreObjC/bits.h +315 -0
  389. package/ios/Packages/CoreObjC/bwdet.c +129 -0
  390. package/ios/Packages/CoreObjC/bwdet.h +69 -0
  391. package/ios/Packages/CoreObjC/common.h +151 -0
  392. package/ios/Packages/CoreObjC/energy.c +70 -0
  393. package/ios/Packages/CoreObjC/energy.h +43 -0
  394. package/ios/Packages/CoreObjC/fastmath.h +158 -0
  395. package/ios/Packages/CoreObjC/include/PcmConverter.h +22 -0
  396. package/ios/Packages/CoreObjC/lc3.c +704 -0
  397. package/ios/Packages/CoreObjC/lc3.h +313 -0
  398. package/ios/Packages/CoreObjC/lc3_cpp.h +283 -0
  399. package/ios/Packages/CoreObjC/lc3_private.h +163 -0
  400. package/ios/Packages/CoreObjC/ltpf.c +905 -0
  401. package/ios/Packages/CoreObjC/ltpf.h +111 -0
  402. package/ios/Packages/CoreObjC/ltpf_arm.h +506 -0
  403. package/ios/Packages/CoreObjC/ltpf_neon.h +281 -0
  404. package/ios/Packages/CoreObjC/makefile.mk +35 -0
  405. package/ios/Packages/CoreObjC/mdct.c +469 -0
  406. package/ios/Packages/CoreObjC/mdct.h +57 -0
  407. package/ios/Packages/CoreObjC/mdct_neon.h +296 -0
  408. package/ios/Packages/CoreObjC/meson.build +61 -0
  409. package/ios/Packages/CoreObjC/plc.c +61 -0
  410. package/ios/Packages/CoreObjC/plc.h +57 -0
  411. package/ios/Packages/CoreObjC/rnnoise.h +114 -0
  412. package/ios/Packages/CoreObjC/sns.c +880 -0
  413. package/ios/Packages/CoreObjC/sns.h +103 -0
  414. package/ios/Packages/CoreObjC/spec.c +907 -0
  415. package/ios/Packages/CoreObjC/spec.h +119 -0
  416. package/ios/Packages/CoreObjC/tables.c +3457 -0
  417. package/ios/Packages/CoreObjC/tables.h +94 -0
  418. package/ios/Packages/CoreObjC/tns.c +457 -0
  419. package/ios/Packages/CoreObjC/tns.h +99 -0
  420. package/ios/Packages/SherpaOnnx/Model/joiner.onnx +0 -0
  421. package/ios/Packages/SherpaOnnx/Model/tokens.txt +502 -0
  422. package/ios/Packages/SherpaOnnx/SherpaOnnx.swift +2383 -0
  423. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Info.plist +48 -0
  424. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
  425. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
  426. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/libsherpa-onnx.a +0 -0
  427. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
  428. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
  429. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/libsherpa-onnx.a +0 -0
  430. package/ios/Packages/libbz2/module.modulemap +5 -0
  431. package/ios/Packages/libbz2/shim.h +1 -0
  432. package/ios/PhotoReceiverModule.swift +129 -0
  433. package/ios/Source/BluetoothSDK.swift +2303 -0
  434. package/ios/Source/BluetoothSDKDebug.swift +12 -0
  435. package/ios/Source/BluetoothSdkDefaults.swift +29 -0
  436. package/ios/Source/Bridge.swift +708 -0
  437. package/ios/Source/Bridging-Header.h +16 -0
  438. package/ios/Source/DeviceManager.swift +2109 -0
  439. package/ios/Source/DeviceStore.swift +336 -0
  440. package/ios/Source/GeneratedChangelogCatalog.swift +7 -0
  441. package/ios/Source/GeneratedReleaseMetadata.swift +11 -0
  442. package/ios/Source/ObservableStore.swift +118 -0
  443. package/ios/Source/OtaManifest.swift +211 -0
  444. package/ios/Source/PrivacyInfo.xcprivacy +23 -0
  445. package/ios/Source/ReleaseChangelog.swift +65 -0
  446. package/ios/Source/Resources/G2Firmware/README.md +10 -0
  447. package/ios/Source/audio/AudioModels.swift +178 -0
  448. package/ios/Source/audio/PcmStreamPlayer.swift +410 -0
  449. package/ios/Source/camera/CameraModels.swift +866 -0
  450. package/ios/Source/connection/ScanSession.swift +27 -0
  451. package/ios/Source/controllers/ControllerManager.swift +184 -0
  452. package/ios/Source/controllers/R1.swift +829 -0
  453. package/ios/Source/errors/BluetoothSdkError.swift +19 -0
  454. package/ios/Source/events/BluetoothEvents.swift +342 -0
  455. package/ios/Source/internal/BleTraceLogger.swift +192 -0
  456. package/ios/Source/internal/BluetoothAvailability.swift +78 -0
  457. package/ios/Source/internal/BluetoothSdkAnalytics.swift +199 -0
  458. package/ios/Source/internal/ValueParsing.swift +99 -0
  459. package/ios/Source/requests/DisplayRequests.swift +82 -0
  460. package/ios/Source/services/PhoneMic.swift +662 -0
  461. package/ios/Source/sgcs/Ar99.swift +2451 -0
  462. package/ios/Source/sgcs/Frame.swift +649 -0
  463. package/ios/Source/sgcs/G1.swift +2554 -0
  464. package/ios/Source/sgcs/G2.swift +6887 -0
  465. package/ios/Source/sgcs/G2CfwClassification.swift +43 -0
  466. package/ios/Source/sgcs/G2CfwRenderer.swift +1279 -0
  467. package/ios/Source/sgcs/G2CfwTextureCache.swift +233 -0
  468. package/ios/Source/sgcs/G2FlashProtocol.swift +312 -0
  469. package/ios/Source/sgcs/G2Flasher.swift +773 -0
  470. package/ios/Source/sgcs/Mach1.swift +541 -0
  471. package/ios/Source/sgcs/MentraLive.swift +7011 -0
  472. package/ios/Source/sgcs/MentraLiveL2capChannel.swift +183 -0
  473. package/ios/Source/sgcs/MentraLivePairingAdvertisement.swift +64 -0
  474. package/ios/Source/sgcs/MentraNex.swift +3221 -0
  475. package/ios/Source/sgcs/Nimo.swift +1886 -0
  476. package/ios/Source/sgcs/SGCManager.swift +608 -0
  477. package/ios/Source/sgcs/Simulated.swift +274 -0
  478. package/ios/Source/sgcs/ar99/ota/Ar99OtaManager.swift +637 -0
  479. package/ios/Source/sgcs/glassly_ble.pb.swift +4354 -0
  480. package/ios/Source/speakerid/SpeakerIdEngine.swift +573 -0
  481. package/ios/Source/status/DeviceStatus.swift +981 -0
  482. package/ios/Source/status/RuntimeState.swift +359 -0
  483. package/ios/Source/status/WifiHotspotStatus.swift +345 -0
  484. package/ios/Source/streaming/StreamModels.swift +693 -0
  485. package/ios/Source/stt/STTTools.swift +191 -0
  486. package/ios/Source/stt/SherpaOnnxTranscriber.swift +466 -0
  487. package/ios/Source/tts/TTSTools.swift +171 -0
  488. package/ios/Source/types/DeviceModels.swift +177 -0
  489. package/ios/Source/utils/AudioSessionMonitor.swift +283 -0
  490. package/ios/Source/utils/BinaryCodec.swift +61 -0
  491. package/ios/Source/utils/BleJsonCompact.swift +405 -0
  492. package/ios/Source/utils/BleWireProtocol.swift +92 -0
  493. package/ios/Source/utils/Constants.swift +78 -0
  494. package/ios/Source/utils/Enums.swift +95 -0
  495. package/ios/Source/utils/G1Text.swift +2096 -0
  496. package/ios/Source/utils/JSCExperiment.swift +241 -0
  497. package/ios/Source/utils/MemoryMonitor.swift +44 -0
  498. package/ios/Source/utils/MessageChunkReassembler.swift +190 -0
  499. package/ios/Source/utils/MessageChunker.swift +294 -0
  500. package/ios/Source/utils/Models.swift +135 -0
  501. package/ios/Source/utils/PhoneAudioMonitor.swift +230 -0
  502. package/ios/Source/utils/TarBz2Extractor.swift +257 -0
  503. package/ios/Tests/BluetoothSDKTests/G2CfwClassificationTests.swift +78 -0
  504. package/ios/Tests/BluetoothSDKTests/G2CfwRendererTests.swift +372 -0
  505. package/ios/Tests/BluetoothSDKTests/G2CfwTextureCacheTests.swift +162 -0
  506. package/ios/Tests/BluetoothSDKTests/G2FlashProtocolTests.swift +182 -0
  507. package/ios/Tests/MentraLivePairingAdvertisementTests.swift +160 -0
  508. package/ios/Tests/ReleaseChangelogTests.swift +13 -0
  509. package/package.json +129 -0
  510. package/plugin/build/index.d.ts +10 -0
  511. package/plugin/build/index.js +12 -0
  512. package/plugin/build/withAndroid.d.ts +3 -0
  513. package/plugin/build/withAndroid.js +190 -0
  514. package/plugin/build/withIos.d.ts +5 -0
  515. package/plugin/build/withIos.js +108 -0
  516. package/scripts/inject-ios-sdk-version.mjs +65 -0
  517. package/scripts/public-ota-api.test.mjs +37 -0
  518. package/scripts/verify-release-package.mjs +45 -0
  519. package/scripts/write-release-metadata.mjs +152 -0
  520. package/scripts/write-release-metadata.test.mjs +37 -0
  521. package/src/BluetoothSdk.types.ts +1623 -0
  522. package/src/_internal.ts +16 -0
  523. package/src/_private/BluetoothSdkModule.ts +684 -0
  524. package/src/_private/LocalNetworkModule.ts +50 -0
  525. package/src/_private/cameraRequestPayload.ts +34 -0
  526. package/src/_private/photoRequestPayload.ts +90 -0
  527. package/src/_private/sdkOtaManifest.ts +18 -0
  528. package/src/changelogs.ts +46 -0
  529. package/src/debug.ts +9 -0
  530. package/src/generated/changelogCatalog.ts +13 -0
  531. package/src/generated/releaseMetadata.ts +20 -0
  532. package/src/index.ts +321 -0
  533. package/src/ota-server/OtaServer.types.ts +10 -0
  534. package/src/ota-server/OtaServerModule.ts +23 -0
  535. package/src/ota-server/OtaServerModule.web.ts +17 -0
  536. package/src/ota-server/index.ts +2 -0
  537. package/src/ota-transport/index.ts +116 -0
  538. package/src/photo-receiver/PhotoReceiver.types.ts +20 -0
  539. package/src/photo-receiver/PhotoReceiverModule.ts +11 -0
  540. package/src/photo-receiver/PhotoReceiverModule.web.ts +17 -0
  541. package/src/photo-receiver/index.ts +2 -0
  542. package/src/react/index.ts +21 -0
  543. package/src/react/useBluetooth.ts +309 -0
  544. package/src/react/useBluetoothEvent.ts +35 -0
  545. package/src/react/useBluetoothScan.ts +173 -0
  546. package/src/react/useBluetoothStatus.ts +180 -0
  547. package/src/react/useGlassesConnection.ts +202 -0
  548. package/src/types/index.ts +12 -0
@@ -0,0 +1,698 @@
1
+ package com.glassly.bluetoothsdk.utils
2
+
3
+ import java.nio.ByteBuffer
4
+ import java.io.IOException
5
+ import java.util.UUID
6
+
7
+ import android.content.Context
8
+ import android.util.Log
9
+
10
+ import com.glassly.bluetoothsdk.Bridge
11
+ import com.glassly.bluetoothsdk.DeviceStore
12
+
13
+ import glassly.ble.GlasslyBle.DisplayText
14
+ import glassly.ble.GlasslyBle.ClearDisplay
15
+ import glassly.ble.GlasslyBle.DisconnectRequest
16
+ import glassly.ble.GlasslyBle.PhoneToGlasses
17
+ import glassly.ble.GlasslyBle.DisplayImage
18
+ import glassly.ble.GlasslyBle.CanvasCreateComponent
19
+ import glassly.ble.GlasslyBle.CanvasUpdateImage
20
+ import glassly.ble.GlasslyBle.CanvasUpdateText
21
+ import glassly.ble.GlasslyBle.CanvasDeleteComponent
22
+ import glassly.ble.GlasslyBle.CanvasClear
23
+ import glassly.ble.GlasslyBle.CanvasComponentType
24
+ import glassly.ble.GlasslyBle.BatteryStateRequest
25
+ import glassly.ble.GlasslyBle.MicStateConfig
26
+ import glassly.ble.GlasslyBle.BrightnessConfig
27
+ import glassly.ble.GlasslyBle.AutoBrightnessConfig
28
+ import glassly.ble.GlasslyBle.HeadUpAngleConfig
29
+ import glassly.ble.GlasslyBle.DisplayDistanceConfig
30
+ import glassly.ble.GlasslyBle.DisplayHeightConfig
31
+ import glassly.ble.GlasslyBle.VadEnabledConfig
32
+
33
+ import org.json.JSONArray
34
+ import org.json.JSONException
35
+ import org.json.JSONObject
36
+
37
+
38
+ object NexBluetoothConstants {
39
+ val MAIN_SERVICE_UUID: UUID = UUID.fromString("00004860-0000-1000-8000-00805f9b34fb")
40
+ val WRITE_CHAR_UUID: UUID = UUID.fromString("000071FF-0000-1000-8000-00805f9b34fb")
41
+ val NOTIFY_CHAR_UUID: UUID = UUID.fromString("000070FF-0000-1000-8000-00805f9b34fb")
42
+ val CLIENT_CHARACTERISTIC_CONFIG_UUID: UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
43
+ }
44
+
45
+ object NexDisplayConstants {
46
+ const val DISPLAY_WIDTH: Int = 488
47
+ const val DISPLAY_USE_WIDTH: Int = 488 // How much of the display to use
48
+ const val FONT_MULTIPLIER: Float = 1.0f / 50.0f
49
+ const val OLD_FONT_SIZE: Int = 21 // Font size
50
+ const val FONT_DIVIDER: Float = 2.0f
51
+ const val LINES_PER_SCREEN: Int = 5 // Lines per screen
52
+
53
+ /** Matches dashboard depth slider in app settings (1-4); values outside range clamp. */
54
+ const val DASHBOARD_DEPTH_MIN: Int = 1
55
+ const val DASHBOARD_DEPTH_MAX: Int = 4
56
+ }
57
+
58
+ object NexBluetoothPacketTypes {
59
+ const val PACKET_TYPE_JSON: Byte = 0x01.toByte()
60
+ const val PACKET_TYPE_PROTOBUF: Byte = 0x02.toByte()
61
+ const val PACKET_TYPE_AUDIO: Byte = 0xA0.toByte()
62
+ const val PACKET_TYPE_IMAGE: Byte = 0xB0.toByte()
63
+ }
64
+
65
+ object NexProtobufUtils {
66
+ private const val TAG = "NexProtobufUtils"
67
+
68
+ private const val WHITELIST_CMD: Int = 0x04
69
+
70
+ // Characters the Nex font can render: letters, digits, whitespace, and a small
71
+ // punctuation set. Everything else (CJK, emoji, smart quotes, …) is stripped when
72
+ // Chinese captions are off. Compiled once — sanitizeDisplayText runs on every
73
+ // caption update (high frequency), so we don't rebuild it per call.
74
+ private val UNSUPPORTED_GLYPH_REGEX = Regex("""[^A-Za-z0-9 \r\n.,!?;:\-\[\]\(\)\{\}'"+=/]""")
75
+
76
+ /**
77
+ * Sanitize text bound for the glasses. When Chinese captions are disabled (the
78
+ * default) the Nex font can't render CJK/emoji/etc., so em-dashes are normalised
79
+ * to hyphens and any unsupported glyph is dropped. When enabled, text passes
80
+ * through untouched. Every text path that reaches the display funnels through
81
+ * here so the filter behaves identically for captions, text walls, and layouts.
82
+ */
83
+ private fun sanitizeDisplayText(text: String): String {
84
+ val chineseCaptionsEnabled = DeviceStore.get("bluetooth", "nex_chinese_captions") as? Boolean ?: false
85
+ if (chineseCaptionsEnabled) return text
86
+ return text.replace("—", "-").replace(UNSUPPORTED_GLYPH_REGEX, "")
87
+ }
88
+
89
+ /**
90
+ * Maps dashboard depth to the value Nex firmware expects in [DisplayDistanceConfig.distance_cm].
91
+ * The protobuf field is still named `distance_cm`, but Nex treats it as a **tier** 1–4, not centimeters.
92
+ * Keep in sync with iOS `NexDashboardDisplayWire.depthToWireTier`.
93
+ */
94
+ fun dashboardDepthToDistanceCm(depth: Int): Int {
95
+ return depth.coerceIn(
96
+ NexDisplayConstants.DASHBOARD_DEPTH_MIN,
97
+ NexDisplayConstants.DASHBOARD_DEPTH_MAX
98
+ )
99
+ }
100
+
101
+ data class AppInfo(
102
+ val id: String,
103
+ val name: String
104
+ )
105
+
106
+ fun getWhitelistChunks(maxChunkSize: Int): List<ByteArray> {
107
+ // Define the hardcoded whitelist
108
+ val apps = listOf(AppInfo("com.augment.os", "AugmentOS"))
109
+ val whitelistJson = createWhitelistJson(apps)
110
+
111
+ Bridge.log("Creating chunks for hardcoded whitelist: $whitelistJson")
112
+
113
+ // Convert JSON to bytes and split into chunks
114
+ return createWhitelistChunks(whitelistJson, maxChunkSize)
115
+ }
116
+
117
+ fun createBmpChunksForNexGlasses(streamId: String, bmpData: ByteArray, totalChunks: Int, bmpChunkSize: Int): List<ByteArray> {
118
+ val chunks = mutableListOf<ByteArray>()
119
+ Bridge.log("Creating $totalChunks chunks from ${bmpData.size} bytes")
120
+
121
+ // Parse hex stream ID to bytes (e.g., "002A" -> 0x00, 0x2A)
122
+ val streamIdInt = streamId.toInt(16)
123
+
124
+ repeat(totalChunks) { i ->
125
+ val start = i * bmpChunkSize
126
+ val end = minOf(start + bmpChunkSize, bmpData.size)
127
+ val chunk = bmpData.copyOfRange(start, end)
128
+
129
+ val header = ByteArray(4 + chunk.size).apply {
130
+ this[0] = NexBluetoothPacketTypes.PACKET_TYPE_IMAGE // 0xB0
131
+ this[1] = (streamIdInt shr 8).toByte() // Stream ID high byte
132
+ this[2] = streamIdInt.toByte() // Stream ID low byte
133
+ this[3] = i.toByte() // Chunk index
134
+ System.arraycopy(chunk, 0, this, 4, chunk.size)
135
+ }
136
+ chunks.add(header)
137
+ }
138
+ return chunks
139
+ }
140
+
141
+ /**
142
+ * Gets the current protobuf schema version from the compiled protobuf descriptor
143
+ */
144
+ fun getProtobufSchemaVersion(context: Context): Int {
145
+ return try {
146
+ // Get the protobuf descriptor and extract the schema version
147
+ val fileDescriptor = glassly.ble.GlasslyBle.getDescriptor().file
148
+
149
+ Log.d(TAG, "Proto file descriptor: ${fileDescriptor.name}")
150
+
151
+ // Method 1: Try to access the custom glassly_schema_version option
152
+ try {
153
+ // Get the file options from the descriptor
154
+ val options = fileDescriptor.options
155
+ Log.d(TAG, "Got file options: $options")
156
+
157
+ // Try to access the custom option using the extension registry
158
+ try {
159
+ // Look for the generated extension in the GlasslyBle class
160
+ glassly.ble.GlasslyBle::class.java.declaredFields.forEach { field ->
161
+ if (field.name.contains("schema", ignoreCase = true) ||
162
+ field.name.contains("version", ignoreCase = true)) {
163
+ Log.d(TAG, "Found potential version field: ${field.name}")
164
+ field.isAccessible = true
165
+ try {
166
+ val value = field.get(null)
167
+ if (value is com.google.protobuf.Extension<*, *>) {
168
+ @Suppress("UNCHECKED_CAST")
169
+ val ext = value as com.google.protobuf.Extension<com.google.protobuf.DescriptorProtos.FileOptions, Int>
170
+ if (options.hasExtension(ext)) {
171
+ val version = options.getExtension(ext)
172
+ Log.d(TAG, "Found schema version via extension: $version")
173
+ return version
174
+ }
175
+ }
176
+ } catch (fieldException: Exception) {
177
+ Log.d(TAG, "Field access failed for ${field.name}: ${fieldException.message}")
178
+ }
179
+ }
180
+ }
181
+ } catch (extensionException: Exception) {
182
+ Log.d(TAG, "Extension search failed: ${extensionException.message}")
183
+ }
184
+
185
+ } catch (optionsException: Exception) {
186
+ Log.d(TAG, "Options access failed: ${optionsException.message}")
187
+ }
188
+
189
+ // Method 2: Try to read from the actual proto file content
190
+ try {
191
+ val protoVersion = readProtoVersionFromProject(context)
192
+ if (protoVersion != null) {
193
+ Log.d(TAG, "Read proto version from project: $protoVersion")
194
+ return protoVersion.toInt()
195
+ }
196
+ } catch (projectException: Exception) {
197
+ Log.d(TAG, "Project file reading failed: ${projectException.message}")
198
+ }
199
+
200
+ Log.w(TAG, "Could not extract protobuf schema version dynamically, using fallback")
201
+ 1 // Fallback to version 1
202
+
203
+ } catch (e: Exception) {
204
+ Log.e(TAG, "Error getting protobuf schema version: ${e.message}", e)
205
+ 1 // Fallback to version 1
206
+ }
207
+ }
208
+
209
+ fun generateClearDisplayRequestCommandBytes(): ByteArray {
210
+ // Create the clear display protobuf message
211
+ val clearDisplay = ClearDisplay.newBuilder()
212
+ .build()
213
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
214
+ // .setMsgId("clear_disp_001")
215
+ .setClearDisplay(clearDisplay)
216
+ .build();
217
+ return generateProtobufCommandBytes(phoneToGlasses);
218
+ }
219
+
220
+ fun generateVersionRequestCommandBytes(): ByteArray {
221
+ // VersionRequest/VersionResponse removed from the BLE schema; fw_version now comes via DeviceInfo.
222
+ Bridge.log("Nex: generateVersionRequestCommandBytes is a no-op after schema removal")
223
+ return ByteArray(0)
224
+ }
225
+
226
+ fun generateDisconnectRequestCommandBytes(): ByteArray {
227
+ val disconnectRequest = DisconnectRequest.newBuilder().build()
228
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
229
+ .setDisconnect(disconnectRequest)
230
+ .build()
231
+ return generateProtobufCommandBytes(phoneToGlasses)
232
+ }
233
+
234
+ fun generateBatteryStateRequestCommandBytes(): ByteArray {
235
+ Bridge.log("Nex: === SENDING BATTERY STATUS QUERY TO GLASSES ===")
236
+ val batteryStateRequest = BatteryStateRequest.newBuilder().build()
237
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
238
+ .setBatteryState(batteryStateRequest)
239
+ .build()
240
+ return generateProtobufCommandBytes(phoneToGlasses)
241
+ }
242
+
243
+ fun generateDisplayImageCommandBytes(streamId: String, totalChunks: Int, width: Int, height: Int): ByteArray {
244
+ Bridge.log("=== SENDING IMAGE DISPLAY COMMAND TO GLASSES ===")
245
+ Bridge.log("Image Stream ID: $streamId")
246
+ Bridge.log("Total Chunks: $totalChunks")
247
+ Bridge.log("Image Position: X=0, Y=0")
248
+ Bridge.log("Image Dimensions: ${width}x$height")
249
+ Bridge.log("Image Encoding: raw")
250
+
251
+ val displayImage = DisplayImage.newBuilder()
252
+ .setStreamId(streamId)
253
+ .setTotalChunks(totalChunks)
254
+ .setX(0)
255
+ .setY(0)
256
+ .setWidth(width)
257
+ .setHeight(height)
258
+ .setEncoding("raw")
259
+ .build()
260
+
261
+ // Create the PhoneToGlasses using its builder and set the DisplayImage with msg_id
262
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
263
+ .setMsgId("img_start_1")
264
+ .setDisplayImage(displayImage)
265
+ .build()
266
+ return generateProtobufCommandBytes(phoneToGlasses)
267
+ }
268
+
269
+ /**
270
+ * Canvas: create (or replace) a full-screen bitmap component. The firmware infers the bitmap
271
+ * pool from the id (10..13); we use a single fixed id for the full-screen image. Pixels follow
272
+ * via [generateCanvasUpdateImageCommandBytes] + the 0xB0 chunk stream.
273
+ */
274
+ fun generateCanvasCreateBitmapCommandBytes(id: Int, x: Int, y: Int, width: Int, height: Int): ByteArray {
275
+ // Negative geometry would serialize as a huge unsigned varint on the
276
+ // wire — clamp to the drawable range before it reaches the firmware.
277
+ val create = CanvasCreateComponent.newBuilder()
278
+ .setId(id)
279
+ .setType(CanvasComponentType.CANVAS_BITMAP)
280
+ .setX(x.coerceAtLeast(0))
281
+ .setY(y.coerceAtLeast(0))
282
+ .setWidth(width.coerceAtLeast(1))
283
+ .setHeight(height.coerceAtLeast(1))
284
+ .build()
285
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
286
+ .setCanvasCreateComponent(create)
287
+ .build()
288
+ return generateProtobufCommandBytes(phoneToGlasses)
289
+ }
290
+
291
+ /** Canvas: create (or replace) a text component (TEXTBOX). Content follows via CanvasUpdateText. */
292
+ fun generateCanvasCreateTextboxCommandBytes(
293
+ id: Int, x: Int, y: Int, width: Int, height: Int, borderWidth: Int, borderRadius: Int
294
+ ): ByteArray {
295
+ val create = CanvasCreateComponent.newBuilder()
296
+ .setId(id)
297
+ .setType(CanvasComponentType.CANVAS_TEXTBOX)
298
+ .setX(x)
299
+ .setY(y)
300
+ .setWidth(width)
301
+ .setHeight(height)
302
+ .setBorderWidth(borderWidth)
303
+ .setBorderRadius(borderRadius)
304
+ .build()
305
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
306
+ .setCanvasCreateComponent(create)
307
+ .build()
308
+ return generateProtobufCommandBytes(phoneToGlasses)
309
+ }
310
+
311
+ /** Canvas: set the text of a TEXTBOX / SCROLL_TEXTBOX component. */
312
+ fun generateCanvasUpdateTextCommandBytes(id: Int, text: String, scrollOffset: Int = 0): ByteArray {
313
+ val update = CanvasUpdateText.newBuilder()
314
+ .setId(id)
315
+ .setText(sanitizeDisplayText(text))
316
+ .setScrollOffset(scrollOffset)
317
+ .build()
318
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
319
+ .setCanvasUpdateText(update)
320
+ .build()
321
+ return generateProtobufCommandBytes(phoneToGlasses)
322
+ }
323
+
324
+ /** Canvas: delete a single component by id. */
325
+ fun generateCanvasDeleteComponentCommandBytes(id: Int): ByteArray {
326
+ val del = CanvasDeleteComponent.newBuilder().setId(id).build()
327
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
328
+ .setCanvasDeleteComponent(del)
329
+ .build()
330
+ return generateProtobufCommandBytes(phoneToGlasses)
331
+ }
332
+
333
+ /** Canvas: delete all components and exit the canvas view. */
334
+ fun generateCanvasClearCommandBytes(): ByteArray {
335
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
336
+ .setCanvasClear(CanvasClear.newBuilder().build())
337
+ .build()
338
+ return generateProtobufCommandBytes(phoneToGlasses)
339
+ }
340
+
341
+ /** Canvas: begin streaming a 1-bit BMP into an existing bitmap component. */
342
+ fun generateCanvasUpdateImageCommandBytes(id: Int, streamId: String, totalChunks: Int): ByteArray {
343
+ val update = CanvasUpdateImage.newBuilder()
344
+ .setId(id)
345
+ .setStreamId(streamId)
346
+ .setTotalChunks(totalChunks)
347
+ .build()
348
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
349
+ .setCanvasUpdateImage(update)
350
+ .build()
351
+ return generateProtobufCommandBytes(phoneToGlasses)
352
+ }
353
+
354
+ fun generateDisplayTextCommandBytes(text: String): ByteArray {
355
+ Bridge.log("Nex: === SENDING TEXT TO GLASSES ===")
356
+ Bridge.log("Nex: Text: \"$text\"")
357
+ Bridge.log("Nex: Text Length: ${text.length} characters")
358
+
359
+ val displayText = sanitizeDisplayText(text)
360
+
361
+ val textNewBuilder = DisplayText.newBuilder()
362
+ .setColor(10000)
363
+ .setText(displayText)
364
+ .setSize(48)
365
+ .setX(20)
366
+ .setY(260)
367
+ .build()
368
+
369
+ // Create the PhoneToGlasses using its builder and set the DisplayText
370
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
371
+ .setDisplayText(textNewBuilder)
372
+ .build()
373
+
374
+ return generateProtobufCommandBytes(phoneToGlasses)
375
+ }
376
+
377
+ fun generateHeadUpAngleConfigCommandBytes(angle: Int): ByteArray {
378
+ val headUpAngleConfig = HeadUpAngleConfig.newBuilder().setAngle(angle).build()
379
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
380
+ .setHeadUpAngle(headUpAngleConfig)
381
+ .build()
382
+ Bridge.log("Nex: Sent headUp angle command => Angle: $angle")
383
+ return generateProtobufCommandBytes(phoneToGlasses)
384
+ }
385
+
386
+ fun generateDisplayHeightCommandBytes(height: Int): ByteArray {
387
+ val clampedHeight = height.coerceIn(0, 8)
388
+
389
+ Bridge.log("Nex: === SENDING DISPLAY HEIGHT COMMAND TO GLASSES ===")
390
+ Bridge.log("Nex: Display height: $clampedHeight (0-8)")
391
+ val displayHeightConfig = DisplayHeightConfig.newBuilder()
392
+ .setHeight(clampedHeight)
393
+ .build()
394
+
395
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
396
+ .setDisplayHeight(displayHeightConfig)
397
+ .build()
398
+
399
+ Bridge.log("Nex: Sent display height command => Height: $clampedHeight")
400
+
401
+ return generateProtobufCommandBytes(phoneToGlasses)
402
+ }
403
+
404
+ fun generateDisplayDistanceCommandBytes(distanceCm: Int): ByteArray {
405
+ val tier = distanceCm.coerceIn(
406
+ NexDisplayConstants.DASHBOARD_DEPTH_MIN,
407
+ NexDisplayConstants.DASHBOARD_DEPTH_MAX
408
+ )
409
+ Bridge.log("Nex: === SENDING DISPLAY DISTANCE COMMAND TO GLASSES ===")
410
+ Bridge.log("Nex: Display distance tier (distance_cm field): $tier")
411
+
412
+ val displayDistanceConfig = DisplayDistanceConfig.newBuilder()
413
+ .setDistanceCm(tier)
414
+ .build()
415
+
416
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
417
+ .setDisplayDistance(displayDistanceConfig)
418
+ .build()
419
+
420
+ Bridge.log("Nex: Sent display distance command => distance_cm (tier): $tier")
421
+
422
+ return generateProtobufCommandBytes(phoneToGlasses)
423
+ }
424
+
425
+ fun generateBrightnessConfigCommandBytes(brightness: Int): ByteArray {
426
+ // Validate brightness range
427
+ val validBrightness = if (brightness != -1) {
428
+ (brightness * 63) / 100
429
+ } else {
430
+ (30 * 63) / 100 // Default to 30% if brightness is -1
431
+ }
432
+
433
+ Bridge.log("Nex: === SENDING BRIGHTNESS COMMAND TO GLASSES ===")
434
+ Bridge.log("Nex: Brightness Value: $brightness (validated: $validBrightness)")
435
+
436
+ val brightnessConfig = BrightnessConfig.newBuilder()
437
+ .setValue(validBrightness)
438
+ .build()
439
+
440
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
441
+ .setBrightness(brightnessConfig)
442
+ .build()
443
+
444
+ Bridge.log("Nex: Sent auto light brightness command => Brightness: $validBrightness")
445
+
446
+ return generateProtobufCommandBytes(phoneToGlasses)
447
+ }
448
+
449
+ fun generateMicStateConfigCommandBytes(enable: Boolean): ByteArray {
450
+ Bridge.log("Nex: Microphone Enabled: $enable")
451
+ val micStateConfig = MicStateConfig.newBuilder()
452
+ .setEnabled(enable)
453
+ .build()
454
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
455
+ .setMicState(micStateConfig)
456
+ .build()
457
+
458
+ return generateProtobufCommandBytes(phoneToGlasses)
459
+ }
460
+
461
+ fun generateVadEnabledRequestCommandBytes(enable: Boolean): ByteArray {
462
+ Bridge.log("Nex: VAD Enabled: $enable")
463
+ val vadEnabledConfig = VadEnabledConfig.newBuilder()
464
+ .setEnabled(enable)
465
+ .build()
466
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
467
+ .setVadEnabled(vadEnabledConfig)
468
+ .build()
469
+
470
+ return generateProtobufCommandBytes(phoneToGlasses)
471
+ }
472
+
473
+ fun generateAutoBrightnessConfigCommandBytes(autoLight: Boolean): ByteArray {
474
+ Bridge.log("Nex: === SENDING AUTO BRIGHTNESS COMMAND TO GLASSES ===")
475
+ Bridge.log("Nex: Auto Brightness Enabled: $autoLight")
476
+
477
+ val autoBrightnessConfig = AutoBrightnessConfig.newBuilder()
478
+ .setEnabled(autoLight)
479
+ .build()
480
+
481
+ val phoneToGlasses = PhoneToGlasses.newBuilder()
482
+ .setAutoBrightness(autoBrightnessConfig)
483
+ .build()
484
+
485
+ Bridge.log("Nex: Sent auto light sendAutoBrightnessCommand => $autoLight")
486
+
487
+ return generateProtobufCommandBytes(phoneToGlasses)
488
+ }
489
+
490
+ private fun createWhitelistJson(apps: List<AppInfo>): String {
491
+ return try {
492
+ val appList = JSONArray().apply {
493
+ apps.forEach { app ->
494
+ put(JSONObject().apply {
495
+ put("id", app.id)
496
+ put("name", app.name)
497
+ })
498
+ }
499
+ }
500
+
501
+ JSONObject().apply {
502
+ put("calendar_enable", false)
503
+ put("call_enable", false)
504
+ put("msg_enable", false)
505
+ put("ios_mail_enable", false)
506
+ put("app", JSONObject().apply {
507
+ put("list", appList)
508
+ put("enable", true)
509
+ })
510
+ }.toString()
511
+ } catch (e: JSONException) {
512
+ Log.e(TAG, "Error creating whitelist JSON: ${e.message}", e)
513
+ "{}"
514
+ }
515
+ }
516
+
517
+ private fun createWhitelistChunks(json: String, maxChunkSize: Int): List<ByteArray> {
518
+ val jsonBytes = json.toByteArray(Charsets.UTF_8)
519
+ val totalChunks = (jsonBytes.size + maxChunkSize - 1) / maxChunkSize
520
+
521
+ return List(totalChunks) { chunkIndex ->
522
+ val start = chunkIndex * maxChunkSize
523
+ val end = (start + maxChunkSize).coerceAtMost(jsonBytes.size)
524
+ val payloadChunk = jsonBytes.copyOfRange(start, end)
525
+
526
+ // Create the header: [WHITELIST_CMD, total_chunks, chunk_index]
527
+ val header = byteArrayOf(
528
+ WHITELIST_CMD.toByte(),
529
+ totalChunks.toByte(),
530
+ chunkIndex.toByte()
531
+ )
532
+
533
+ header + payloadChunk
534
+ }
535
+ }
536
+
537
+ /**
538
+ * Returns the raw serialized PhoneToGlasses protobuf bytes.
539
+ *
540
+ * Transport framing (the 0x02 packet type and the [seq][totalChunks][chunkIndex]
541
+ * fragmentation header) is applied at send time by MentraNexSGC.sendProtobuf(),
542
+ * which owns the negotiated MTU / chunk size. Keeping framing out of here lets a
543
+ * single chunker handle every control command uniformly.
544
+ */
545
+ private fun generateProtobufCommandBytes(phoneToGlasses: PhoneToGlasses): ByteArray {
546
+ val contentBytes = phoneToGlasses.toByteArray()
547
+ logProtobufMessage(phoneToGlasses, contentBytes)
548
+ return contentBytes
549
+ }
550
+
551
+ private fun logProtobufMessage(phoneToGlasses: PhoneToGlasses, fullMessage: ByteArray) {
552
+ val logMessage = buildString {
553
+ appendLine("=== PROTOBUF MESSAGE TO GLASSES ===")
554
+ appendLine("Message Type: ${phoneToGlasses.payloadCase}")
555
+
556
+ // Extract and log text content if present
557
+ when {
558
+ phoneToGlasses.hasDisplayText() -> {
559
+ val text = phoneToGlasses.displayText.text
560
+ appendLine("Text Content: \"$text\"")
561
+ appendLine("Text Length: ${text.length} characters")
562
+ }
563
+ phoneToGlasses.hasDisplayScrollingText() -> {
564
+ val text = phoneToGlasses.displayScrollingText.text
565
+ appendLine("Scrolling Text Content: \"$text\"")
566
+ appendLine("Text Length: ${text.length} characters")
567
+ }
568
+ }
569
+
570
+ // Log message size information
571
+ appendLine("Protobuf Payload Size: ${phoneToGlasses.toByteArray().size} bytes")
572
+ appendLine("Total Message Size: ${fullMessage.size} bytes")
573
+ appendLine("Packet Type: 0x${NexBluetoothPacketTypes.PACKET_TYPE_PROTOBUF.toString(16).padStart(2, '0').uppercase()}")
574
+ append("=====================================")
575
+ }
576
+
577
+ Bridge.log("Nex: $logMessage")
578
+ }
579
+
580
+ private fun readProtoVersionFromAssets(context: Context): String? {
581
+ return try {
582
+ context.assets.open("glassly_ble.proto").use { inputStream ->
583
+ val content = inputStream.bufferedReader().use { it.readText() }
584
+ extractVersionFromProtoContent(content)
585
+ }
586
+ } catch (e: IOException) {
587
+ Bridge.log("Could not read proto from assets: ${e.message}")
588
+ null
589
+ }
590
+ }
591
+
592
+ private fun readProtoVersionFromResources(context: Context): String? {
593
+ return try {
594
+ val resId = context.resources.getIdentifier("glassly_ble", "raw", context.packageName)
595
+ if (resId != 0) {
596
+ context.resources.openRawResource(resId).use { inputStream ->
597
+ val content = inputStream.bufferedReader().use { it.readText() }
598
+ extractVersionFromProtoContent(content)
599
+ }
600
+ } else {
601
+ null
602
+ }
603
+ } catch (e: Exception) {
604
+ Bridge.log("Could not read proto from resources: ${e.message}")
605
+ null
606
+ }
607
+ }
608
+
609
+ private fun readProtoVersionFromProject(context: Context): String? {
610
+ val projectPaths = arrayOf(
611
+ "../../mcu_client/glassly_ble.proto",
612
+ "../../../mcu_client/glassly_ble.proto",
613
+ "../../../../mcu_client/glassly_ble.proto",
614
+ "/data/data/${context.packageName}/../../mcu_client/glassly_ble.proto",
615
+ "${android.os.Environment.getExternalStorageDirectory()}/Glassly/mcu_client/glassly_ble.proto"
616
+ )
617
+
618
+ return projectPaths.firstNotNullOfOrNull { path ->
619
+ try {
620
+ val protoFile = java.io.File(path)
621
+ if (protoFile.exists() && protoFile.canRead()) {
622
+ val content = protoFile.readText(Charsets.UTF_8)
623
+ extractVersionFromProtoContent(content)
624
+ } else {
625
+ null
626
+ }
627
+ } catch (e: Exception) {
628
+ null
629
+ }
630
+ }
631
+ }
632
+
633
+ private fun extractVersionFromProtoContent(content: String): String? {
634
+ return try {
635
+ val pattern = Regex("""option\s*\(\s*glassly_schema_version\s*\)\s*=\s*(\d+)\s*;""")
636
+ pattern.find(content)?.groupValues?.get(1)
637
+ } catch (e: Exception) {
638
+ Log.e(TAG, "Error extracting version from proto content: ${e.message}", e)
639
+ null
640
+ }
641
+ }
642
+ }
643
+
644
+ object NexEventUtils {
645
+ private const val TAG = "NexEventUtils"
646
+
647
+ fun sendHeartbeatSentEvent(timestamp: Long) {
648
+ try {
649
+ val data = HashMap<String, Any>()
650
+ data["timestamp"] = timestamp
651
+
652
+ Bridge.sendTypedMessage("heartbeat_sent", data as Map<String, Any>)
653
+ Bridge.log("NOTIF: Successfully queued heartbeat sent event")
654
+ } catch (e: Exception) {
655
+ Log.e(TAG, "NOTIF: Error sending heartbeat sent event", e)
656
+ }
657
+ }
658
+
659
+ fun sendHeartbeatReceivedEvent(timestamp: Long) {
660
+ try {
661
+ val data = HashMap<String, Any>()
662
+ data["timestamp"] = timestamp
663
+
664
+ Bridge.sendTypedMessage("heartbeat_received", data as Map<String, Any>)
665
+ Bridge.log("NOTIF: Successfully queued heartbeat received event")
666
+ } catch (e: Exception) {
667
+ Log.e(TAG, "NOTIF: Error sending heartbeat received event", e)
668
+ }
669
+ }
670
+
671
+ fun sendBleCommandSentEvent(payloadCase: String, packetHex: String, timestamp: Long) {
672
+ try {
673
+ val data = HashMap<String, Any>()
674
+ data["command"] = payloadCase
675
+ data["commandText"] = packetHex
676
+ data["timestamp"] = timestamp
677
+
678
+ Bridge.sendTypedMessage("send_command_to_ble", data as Map<String, Any>)
679
+ Bridge.log("NOTIF: Successfully queued ble command sent event")
680
+ } catch (e: Exception) {
681
+ Log.e(TAG, "NOTIF: Error sending ble command sent event", e)
682
+ }
683
+ }
684
+
685
+ fun sendBleCommandReceivedEvent(payloadCase: String, packetHex: String, timestamp: Long) {
686
+ try {
687
+ val data = HashMap<String, Any>()
688
+ data["command"] = payloadCase
689
+ data["commandText"] = packetHex
690
+ data["timestamp"] = timestamp
691
+
692
+ Bridge.sendTypedMessage("receive_command_from_ble", data as Map<String, Any>)
693
+ Bridge.log("NOTIF: Successfully queued ble command received event")
694
+ } catch (e: Exception) {
695
+ Log.e(TAG, "NOTIF: Error sending ble command received event", e)
696
+ }
697
+ }
698
+ }