@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,169 @@
1
+ package com.glassly.bluetoothsdk.utils;
2
+
3
+ import java.io.File;
4
+ import android.graphics.Bitmap;
5
+ import android.graphics.BitmapFactory;
6
+ import android.util.Log;
7
+ import android.graphics.Bitmap;
8
+ import java.io.ByteArrayOutputStream;
9
+ import java.io.IOException;
10
+ import java.io.OutputStream;
11
+
12
+ public class BitmapJavaUtils {
13
+ private static final String TAG = "WearableAi_BitmapJavaUtils";
14
+
15
+ public static Bitmap loadImageFromStorage(String path){
16
+ File imgFile = new File(path);
17
+ if(imgFile.exists()){
18
+ Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
19
+ return myBitmap;
20
+ } else {
21
+ Log.d(TAG, "Image doesn't exist");
22
+ return null;
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Converts a standard Android ARGB Bitmap into a 1-bit-per-pixel (monochrome) BMP file in memory.
28
+ *
29
+ * <p>This method:
30
+ * <ul>
31
+ * <li>Thresholds each pixel to black or white (simple average-based threshold).
32
+ * <li>Packs the bits: leftmost pixel in the most significant bit.
33
+ * <li>Writes a BITMAPFILEHEADER + BITMAPINFOHEADER + 2-entry palette + raw 1-bpp data.
34
+ * </ul>
35
+ *
36
+ * @param bitmap the Android Bitmap to convert. Its alpha channel is ignored.
37
+ * @param invert if {@code false}, bits of 0 map to white, bits of 1 map to black;
38
+ * if {@code true}, the palette is reversed so 0 maps to black, 1 to white.
39
+ * @return A byte[] containing a valid 1-bpp BMP file.
40
+ * @throws IOException if an I/O error occurs writing to the buffer (unlikely in memory).
41
+ */
42
+ public static byte[] convertBitmapTo1BitBmpBytes(Bitmap bitmap, boolean invert) throws IOException {
43
+ int width = bitmap.getWidth();
44
+ int height = bitmap.getHeight();
45
+
46
+ // Each row is padded to a multiple of 4 bytes (32 bits).
47
+ int rowSizeBytes = ((width + 31) / 32) * 4;
48
+ int imageSize = rowSizeBytes * height;
49
+
50
+ // BMP header sizes for 1-bpp:
51
+ // - File header: 14 bytes
52
+ // - DIB header (BITMAPINFOHEADER): 40 bytes
53
+ // - Color table: 2 entries × 4 bytes each = 8 bytes
54
+ // => Pixel data offset = 14 + 40 + 8 = 62
55
+ int dataOffset = 62;
56
+ int fileSize = dataOffset + imageSize;
57
+
58
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(fileSize);
59
+
60
+ // ================== BMP FILE HEADER (14 bytes) ==================
61
+ // Signature: "BM"
62
+ baos.write('B');
63
+ baos.write('M');
64
+ // File size (4 bytes, LE)
65
+ writeIntLE(baos, fileSize);
66
+ // Reserved (4 bytes)
67
+ writeShortLE(baos, 0);
68
+ writeShortLE(baos, 0);
69
+ // Offset to pixel data
70
+ writeIntLE(baos, dataOffset);
71
+
72
+ // ================== DIB HEADER: BITMAPINFOHEADER (40 bytes) ==================
73
+ writeIntLE(baos, 40); // DIB header size
74
+ writeIntLE(baos, width); // Width
75
+ writeIntLE(baos, height); // Height (positive => bottom-to-top)
76
+ writeShortLE(baos, 1); // Planes = 1
77
+ writeShortLE(baos, 1); // Bits per pixel = 1
78
+ writeIntLE(baos, 0); // Compression = BI_RGB (uncompressed)
79
+ writeIntLE(baos, imageSize); // Image size
80
+ writeIntLE(baos, 2835); // X pixels per meter (72 DPI)
81
+ writeIntLE(baos, 2835); // Y pixels per meter (72 DPI)
82
+ writeIntLE(baos, 2); // # of colors in palette
83
+ writeIntLE(baos, 0); // # of important colors
84
+
85
+ // ================== COLOR TABLE (8 bytes: 2 entries × 4 bytes each) ==================
86
+ // Each color entry: (Blue, Green, Red, Reserved)
87
+ // If invert=false, then 0 => White, 1 => Black. Otherwise, 0 => Black, 1 => White.
88
+ if (!invert) {
89
+ // color index 0 => white
90
+ baos.write(0xFF); baos.write(0xFF); baos.write(0xFF); baos.write(0x00);
91
+ // color index 1 => black
92
+ baos.write(0x00); baos.write(0x00); baos.write(0x00); baos.write(0x00);
93
+ } else {
94
+ // color index 0 => black
95
+ baos.write(0x00); baos.write(0x00); baos.write(0x00); baos.write(0x00);
96
+ // color index 1 => white
97
+ baos.write(0xFF); baos.write(0xFF); baos.write(0xFF); baos.write(0x00);
98
+ }
99
+
100
+ // ================== PIXEL DATA (1-bpp, bottom-to-top) ==================
101
+ // We'll iterate from top row to bottom row in the Android sense,
102
+ // but actually output from bottom row to top row in BMP format.
103
+ int[] rowPixels = new int[width];
104
+
105
+ for (int y = 0; y < height; y++) {
106
+ int py = height - 1 - y; // "py" is the actual row index in the source
107
+ bitmap.getPixels(rowPixels, 0, width, 0, py, width, 1);
108
+
109
+ byte[] packedRow = new byte[rowSizeBytes];
110
+ int bitIndex = 0; // which bit within the current byte [0..7]
111
+ int byteIndex = 0; // which byte in packedRow
112
+
113
+ for (int x = 0; x < width; x++) {
114
+ int color = rowPixels[x];
115
+ int r = (color >> 16) & 0xFF;
116
+ int g = (color >> 8) & 0xFF;
117
+ int b = (color) & 0xFF;
118
+
119
+ // Simple threshold (tweak if you want better dithering)
120
+ int gray = (r + g + b) / 3;
121
+ // int pixelVal = (gray < 128) ? 1 : 0; // 0=white or 1=black depending on palette
122
+ int pixelVal = 0;
123
+ if (!invert) {
124
+ pixelVal = (gray < 128) ? 1 : 0; // Dark → 1 (black), Light → 0 (white)
125
+ } else {
126
+ pixelVal = (gray < 128) ? 0 : 1; // Dark → 0 (black), Light → 1 (white)
127
+ }
128
+
129
+ // The leftmost pixel goes in the MSB of the byte => bit position = 7 - bitIndex
130
+ packedRow[byteIndex] |= (pixelVal << (7 - bitIndex));
131
+
132
+ bitIndex++;
133
+ if (bitIndex == 8) {
134
+ bitIndex = 0;
135
+ byteIndex++;
136
+ }
137
+ }
138
+
139
+ baos.write(packedRow, 0, rowSizeBytes);
140
+ }
141
+
142
+ return baos.toByteArray();
143
+ }
144
+
145
+ /**
146
+ * Writes an integer as 4 little-endian bytes.
147
+ */
148
+ private static void writeIntLE(OutputStream out, int value) throws IOException {
149
+ out.write(value & 0xFF);
150
+ out.write((value >> 8) & 0xFF);
151
+ out.write((value >> 16) & 0xFF);
152
+ out.write((value >> 24) & 0xFF);
153
+ }
154
+
155
+ /**
156
+ * Writes a short as 2 little-endian bytes.
157
+ */
158
+ private static void writeShortLE(OutputStream out, int value) throws IOException {
159
+ out.write(value & 0xFF);
160
+ out.write((value >> 8) & 0xFF);
161
+ }
162
+
163
+ public static Bitmap bytesToBitmap(byte[] imageData) {
164
+ if (imageData == null || imageData.length == 0) {
165
+ return null;
166
+ }
167
+ return BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
168
+ }
169
+ }
@@ -0,0 +1,496 @@
1
+ package com.glassly.bluetoothsdk.utils;
2
+
3
+ import java.nio.charset.StandardCharsets;
4
+ import java.util.ArrayList;
5
+ import java.util.Arrays;
6
+ import java.util.Collections;
7
+ import java.util.HashMap;
8
+ import java.util.HashSet;
9
+ import java.util.Iterator;
10
+ import java.util.List;
11
+ import java.util.Map;
12
+ import java.util.Set;
13
+ import org.json.JSONArray;
14
+ import org.json.JSONException;
15
+ import org.json.JSONObject;
16
+
17
+ /** BLE Wire Protocol v2 JSON compaction with lossless fallback for ambiguous payloads. */
18
+ public final class BleJsonCompact {
19
+
20
+ private static final Map<String, String> LONG_TO_SHORT = new HashMap<>();
21
+ private static final Map<String, String> SHORT_TO_LONG = new HashMap<>();
22
+
23
+ private static final Map<String, Integer> PHOTO_STATUS_TO_INT = new HashMap<>();
24
+ private static final Map<Integer, String> PHOTO_STATUS_FROM_INT = new HashMap<>();
25
+ private static final Map<String, Integer> KIND_TO_INT = new HashMap<>();
26
+ private static final Map<Integer, String> KIND_FROM_INT = new HashMap<>();
27
+ private static final Map<String, Integer> SOURCE_TO_INT = new HashMap<>();
28
+ private static final Map<Integer, String> SOURCE_FROM_INT = new HashMap<>();
29
+ private static final Map<String, Integer> AE_STATE_TO_INT = new HashMap<>();
30
+ private static final Map<Integer, String> AE_STATE_FROM_INT = new HashMap<>();
31
+
32
+ public static final String KEY_RESOLVED_CONFIG_HASH = "rch";
33
+
34
+ /** ROI 8–10 message types: compact outbound and accept compact inbound. */
35
+ private static final Set<String> HIGH_ROI_MESSAGE_TYPES =
36
+ Collections.unmodifiableSet(
37
+ new HashSet<>(
38
+ Arrays.asList(
39
+ "photo_status",
40
+ "stream_status",
41
+ "wifi_scan_result",
42
+ "start_stream",
43
+ "photo_response")));
44
+
45
+ /** Structural chunk envelope (always compact on wire). */
46
+ private static final Set<String> CHUNK_MESSAGE_TYPES =
47
+ Collections.unmodifiableSet(new HashSet<>(Arrays.asList("ck", "chunked_msg")));
48
+
49
+ private static long sessionConnectEpochMs;
50
+ private static final Map<String, JSONObject> resolvedConfigByHash = new HashMap<>();
51
+
52
+ static {
53
+ putKey("type", "t");
54
+ putKey("requestId", "r");
55
+ putKey("timestamp", "ts");
56
+ putKey("status", "s");
57
+ putKey("kind", "k");
58
+ putKey("source", "src");
59
+ putKey("requestedCaptureConfig", "rcc");
60
+ putKey("meteredPreview", "mp");
61
+ putKey("exposureTimeNs", "etn");
62
+ putKey("captureMetadata", "cm");
63
+ putKey("aeStateName", "aes");
64
+ putKey("transferMethod", "tm");
65
+ putKey("manual", "m");
66
+ putKey("reconnecting", "rc");
67
+ putKey("stats", "st");
68
+ putKey("width", "w");
69
+ putKey("height", "h");
70
+ putKey("bitrate", "br");
71
+ putKey("fps", "f");
72
+ putKey("droppedFrames", "df");
73
+ putKey("duration", "du");
74
+ putKey("temperatureC", "tc");
75
+
76
+ putEnum(PHOTO_STATUS_TO_INT, PHOTO_STATUS_FROM_INT, "accepted", 0);
77
+ putEnum(PHOTO_STATUS_TO_INT, PHOTO_STATUS_FROM_INT, "queued", 1);
78
+ putEnum(PHOTO_STATUS_TO_INT, PHOTO_STATUS_FROM_INT, "configuring", 2);
79
+ putEnum(PHOTO_STATUS_TO_INT, PHOTO_STATUS_FROM_INT, "capturing", 3);
80
+ putEnum(PHOTO_STATUS_TO_INT, PHOTO_STATUS_FROM_INT, "captured", 4);
81
+ putEnum(PHOTO_STATUS_TO_INT, PHOTO_STATUS_FROM_INT, "uploading", 5);
82
+ putEnum(PHOTO_STATUS_TO_INT, PHOTO_STATUS_FROM_INT, "uploaded", 6);
83
+ putEnum(PHOTO_STATUS_TO_INT, PHOTO_STATUS_FROM_INT, "failed", 7);
84
+
85
+ putEnum(KIND_TO_INT, KIND_FROM_INT, "lifecycle", 0);
86
+ putEnum(KIND_TO_INT, KIND_FROM_INT, "snapshot", 1);
87
+
88
+ putEnum(SOURCE_TO_INT, SOURCE_FROM_INT, "sdk", 0);
89
+ putEnum(SOURCE_TO_INT, SOURCE_FROM_INT, "button", 1);
90
+
91
+ putEnum(AE_STATE_TO_INT, AE_STATE_FROM_INT, "CONVERGED", 0);
92
+ putEnum(AE_STATE_TO_INT, AE_STATE_FROM_INT, "SEARCHING", 1);
93
+ putEnum(AE_STATE_TO_INT, AE_STATE_FROM_INT, "INACTIVE", 2);
94
+ putEnum(AE_STATE_TO_INT, AE_STATE_FROM_INT, "LOCKED", 3);
95
+ putEnum(AE_STATE_TO_INT, AE_STATE_FROM_INT, "FLASH_REQUIRED", 4);
96
+ putEnum(AE_STATE_TO_INT, AE_STATE_FROM_INT, "PRECAPTURE", 5);
97
+ }
98
+
99
+ private BleJsonCompact() {}
100
+
101
+ public static void resetSession() {
102
+ sessionConnectEpochMs = 0L;
103
+ resolvedConfigByHash.clear();
104
+ }
105
+
106
+ public static void markSessionConnected(long epochMs) {
107
+ resetSession();
108
+ sessionConnectEpochMs = epochMs;
109
+ }
110
+
111
+ public static boolean isCameraCommandJson(String jsonData) {
112
+ if (jsonData == null || jsonData.isEmpty()) {
113
+ return false;
114
+ }
115
+ return jsonData.contains("cs_pho")
116
+ || jsonData.contains("cs_cpho")
117
+ || jsonData.contains("cs_vid")
118
+ || jsonData.contains("\"type\":\"take_photo\"");
119
+ }
120
+
121
+ public static boolean shouldCompactOutbound(String messageType) {
122
+ return messageType != null && HIGH_ROI_MESSAGE_TYPES.contains(messageType);
123
+ }
124
+
125
+ public static boolean supportsCompactInbound(String messageType) {
126
+ if (messageType == null || messageType.isEmpty()) {
127
+ return false;
128
+ }
129
+ return HIGH_ROI_MESSAGE_TYPES.contains(messageType)
130
+ || CHUNK_MESSAGE_TYPES.contains(messageType);
131
+ }
132
+
133
+ /** Compact wire form uses short `t` key without verbose `type`. */
134
+ public static boolean isCompactWireForm(JSONObject json) {
135
+ return json != null && json.has("t") && !json.has("type");
136
+ }
137
+
138
+ public static String extractMessageType(JSONObject json) {
139
+ if (json == null) {
140
+ return "";
141
+ }
142
+ if (json.has("type")) {
143
+ return json.optString("type", "");
144
+ }
145
+ if (json.has("t")) {
146
+ return json.optString("t", "");
147
+ }
148
+ return "";
149
+ }
150
+
151
+ public static JSONObject encode(JSONObject json) throws JSONException {
152
+ if (json == null) {
153
+ return null;
154
+ }
155
+ if (isCameraCommandJson(json.toString())) {
156
+ return json;
157
+ }
158
+ String messageType = extractMessageType(json);
159
+ if (!shouldCompactOutbound(messageType) || !canCompactLosslessly(json, true)) {
160
+ return json;
161
+ }
162
+ return compactObject(json, true);
163
+ }
164
+
165
+ public static JSONObject encode(String jsonData) throws JSONException {
166
+ if (jsonData == null || !jsonData.startsWith("{")) {
167
+ return null;
168
+ }
169
+ return encode(new JSONObject(jsonData));
170
+ }
171
+
172
+ public static JSONObject decode(JSONObject json) throws JSONException {
173
+ if (json == null) {
174
+ return null;
175
+ }
176
+ if (isCameraCommandJson(json.toString())) {
177
+ return json;
178
+ }
179
+ return expandObject(json, true);
180
+ }
181
+
182
+ /**
183
+ * Expand compact wire JSON only when the message type is on the ROI allowlist.
184
+ *
185
+ * @return expanded JSON, passthrough expanded JSON, or {@code null} if compact form is unsupported
186
+ */
187
+ public static JSONObject decodeIfSupported(JSONObject json) throws JSONException {
188
+ if (json == null) {
189
+ return null;
190
+ }
191
+ if (isCameraCommandJson(json.toString())) {
192
+ return json;
193
+ }
194
+ if (!isCompactWireForm(json)) {
195
+ return json;
196
+ }
197
+ String compactType = json.optString("t", "");
198
+ if (!supportsCompactInbound(compactType)) {
199
+ return null;
200
+ }
201
+ return expandObject(json, true);
202
+ }
203
+
204
+ public static JSONObject decode(String jsonData) throws JSONException {
205
+ if (jsonData == null || !jsonData.startsWith("{")) {
206
+ return null;
207
+ }
208
+ return decode(new JSONObject(jsonData));
209
+ }
210
+
211
+ private static void putKey(String longKey, String shortKey) {
212
+ LONG_TO_SHORT.put(longKey, shortKey);
213
+ SHORT_TO_LONG.put(shortKey, longKey);
214
+ }
215
+
216
+ private static void putEnum(
217
+ Map<String, Integer> toInt, Map<Integer, String> fromInt, String value, int code) {
218
+ toInt.put(value, code);
219
+ fromInt.put(code, value);
220
+ }
221
+
222
+ /**
223
+ * Compact JSON has reserved short keys and enum integers. If an otherwise valid future payload
224
+ * already uses one of those wire representations, sending verbose JSON is the only way an older
225
+ * decoder can distinguish the original value.
226
+ */
227
+ private static boolean canCompactLosslessly(JSONObject input, boolean topLevel)
228
+ throws JSONException {
229
+ String messageType = input.optString("type", input.optString("t", ""));
230
+ Iterator<String> keys = input.keys();
231
+ while (keys.hasNext()) {
232
+ String key = keys.next();
233
+ Object value = input.get(key);
234
+ if (SHORT_TO_LONG.containsKey(key)
235
+ || (topLevel && KEY_RESOLVED_CONFIG_HASH.equals(key))
236
+ || isAmbiguousEnumValue(key, value, messageType)) {
237
+ return false;
238
+ }
239
+ if (value instanceof JSONObject
240
+ && !canCompactLosslessly((JSONObject) value, false)) {
241
+ return false;
242
+ }
243
+ if (value instanceof JSONArray
244
+ && !canCompactArrayLosslessly((JSONArray) value)) {
245
+ return false;
246
+ }
247
+ }
248
+ return true;
249
+ }
250
+
251
+ private static boolean canCompactArrayLosslessly(JSONArray array) throws JSONException {
252
+ for (int i = 0; i < array.length(); i++) {
253
+ Object value = array.get(i);
254
+ if (value instanceof JSONObject
255
+ && !canCompactLosslessly((JSONObject) value, false)) {
256
+ return false;
257
+ }
258
+ if (value instanceof JSONArray
259
+ && !canCompactArrayLosslessly((JSONArray) value)) {
260
+ return false;
261
+ }
262
+ }
263
+ return true;
264
+ }
265
+
266
+ private static boolean isAmbiguousEnumValue(
267
+ String key, Object value, String messageType) {
268
+ if (!(value instanceof Number)) {
269
+ return false;
270
+ }
271
+ return "kind".equals(key)
272
+ || "source".equals(key)
273
+ || "aeStateName".equals(key)
274
+ || ("status".equals(key) && "photo_status".equals(messageType));
275
+ }
276
+
277
+ private static JSONObject compactObject(JSONObject input, boolean topLevel) throws JSONException {
278
+ JSONObject output = new JSONObject();
279
+ String messageType = input.optString("type", input.optString("t", ""));
280
+
281
+ Iterator<String> keys = input.keys();
282
+ while (keys.hasNext()) {
283
+ String key = keys.next();
284
+ Object value = input.get(key);
285
+ // Keep the absolute timestamp under its verbose key. Legacy peers recognize it and
286
+ // therefore do not mistake it for the old session-relative `ts` representation.
287
+ String shortKey =
288
+ topLevel && "timestamp".equals(key)
289
+ ? key
290
+ : LONG_TO_SHORT.getOrDefault(key, key);
291
+ Object compacted = compactValue(key, value, messageType);
292
+ output.put(shortKey, compacted);
293
+ }
294
+ return output;
295
+ }
296
+
297
+ private static Object compactValue(String longKey, Object value, String messageType)
298
+ throws JSONException {
299
+ if (value == JSONObject.NULL || value == null) {
300
+ return JSONObject.NULL;
301
+ }
302
+ if (value instanceof JSONObject) {
303
+ return compactObject((JSONObject) value, false);
304
+ }
305
+ if (value instanceof JSONArray) {
306
+ return compactArray((JSONArray) value);
307
+ }
308
+ if (value instanceof Boolean || value instanceof Number) {
309
+ return value;
310
+ }
311
+ String str = String.valueOf(value);
312
+ if ("status".equals(longKey) && "photo_status".equals(messageType)) {
313
+ Integer code = PHOTO_STATUS_TO_INT.get(str);
314
+ if (code != null) {
315
+ return code;
316
+ }
317
+ }
318
+ if ("kind".equals(longKey)) {
319
+ Integer code = KIND_TO_INT.get(str);
320
+ if (code != null) {
321
+ return code;
322
+ }
323
+ }
324
+ if ("source".equals(longKey)) {
325
+ Integer code = SOURCE_TO_INT.get(str);
326
+ if (code != null) {
327
+ return code;
328
+ }
329
+ }
330
+ if ("aeStateName".equals(longKey)) {
331
+ Integer code = AE_STATE_TO_INT.get(str);
332
+ if (code != null) {
333
+ return code;
334
+ }
335
+ }
336
+ return str;
337
+ }
338
+
339
+ private static JSONArray compactArray(JSONArray array) throws JSONException {
340
+ JSONArray out = new JSONArray();
341
+ for (int i = 0; i < array.length(); i++) {
342
+ Object value = array.get(i);
343
+ if (value instanceof JSONObject) {
344
+ out.put(compactObject((JSONObject) value, false));
345
+ } else {
346
+ out.put(value);
347
+ }
348
+ }
349
+ return out;
350
+ }
351
+
352
+ private static JSONObject expandObject(JSONObject input, boolean topLevel) throws JSONException {
353
+ JSONObject output = new JSONObject();
354
+ String messageType = input.optString("type", input.optString("t", ""));
355
+
356
+ Iterator<String> keys = input.keys();
357
+ while (keys.hasNext()) {
358
+ String key = keys.next();
359
+ Object value = input.get(key);
360
+ if (topLevel && "ts".equals(key)) {
361
+ output.put("ts", value);
362
+ continue;
363
+ }
364
+ String longKey = SHORT_TO_LONG.getOrDefault(key, key);
365
+ Object expanded = expandValue(longKey, value, messageType);
366
+ output.put(longKey, expanded);
367
+ }
368
+
369
+ if (topLevel) {
370
+ expandTimestamp(output);
371
+ expandResolvedConfigHash(output);
372
+ cacheResolvedConfigIfPresent(output);
373
+ }
374
+ return output;
375
+ }
376
+
377
+ private static void cacheResolvedConfigIfPresent(JSONObject output) throws JSONException {
378
+ if (!(output.opt("resolvedConfig") instanceof JSONObject)) {
379
+ return;
380
+ }
381
+ JSONObject resolvedConfig = output.getJSONObject("resolvedConfig");
382
+ String hash = hashConfig(resolvedConfig);
383
+ resolvedConfigByHash.put(hash, cloneObject(resolvedConfig));
384
+ }
385
+
386
+ private static void expandResolvedConfigHash(JSONObject output) throws JSONException {
387
+ if (output.has("resolvedConfig") || !output.has(KEY_RESOLVED_CONFIG_HASH)) {
388
+ return;
389
+ }
390
+ String hash = output.optString(KEY_RESOLVED_CONFIG_HASH, "");
391
+ JSONObject cached = resolvedConfigByHash.get(hash);
392
+ if (cached != null) {
393
+ output.put("resolvedConfig", cloneObject(cached));
394
+ output.remove(KEY_RESOLVED_CONFIG_HASH);
395
+ }
396
+ }
397
+
398
+ private static Object expandValue(String longKey, Object value, String messageType)
399
+ throws JSONException {
400
+ if (value == JSONObject.NULL || value == null) {
401
+ return JSONObject.NULL;
402
+ }
403
+ if (value instanceof JSONObject) {
404
+ return expandObject((JSONObject) value, false);
405
+ }
406
+ if (value instanceof JSONArray) {
407
+ JSONArray out = new JSONArray();
408
+ JSONArray array = (JSONArray) value;
409
+ for (int i = 0; i < array.length(); i++) {
410
+ Object item = array.get(i);
411
+ if (item instanceof JSONObject) {
412
+ out.put(expandObject((JSONObject) item, false));
413
+ } else {
414
+ out.put(item);
415
+ }
416
+ }
417
+ return out;
418
+ }
419
+ if ("status".equals(longKey) && value instanceof Number && "photo_status".equals(messageType)) {
420
+ String restored = PHOTO_STATUS_FROM_INT.get(((Number) value).intValue());
421
+ return restored != null ? restored : value;
422
+ }
423
+ if ("kind".equals(longKey) && value instanceof Number) {
424
+ String restored = KIND_FROM_INT.get(((Number) value).intValue());
425
+ return restored != null ? restored : value;
426
+ }
427
+ if ("source".equals(longKey) && value instanceof Number) {
428
+ String restored = SOURCE_FROM_INT.get(((Number) value).intValue());
429
+ return restored != null ? restored : value;
430
+ }
431
+ if ("aeStateName".equals(longKey) && value instanceof Number) {
432
+ String restored = AE_STATE_FROM_INT.get(((Number) value).intValue());
433
+ return restored != null ? restored : value;
434
+ }
435
+ return value;
436
+ }
437
+
438
+ private static void expandTimestamp(JSONObject output) throws JSONException {
439
+ if (!output.has("timestamp") && output.has("ts")) {
440
+ Object timestamp = output.opt("ts");
441
+ if (!(timestamp instanceof Number)) {
442
+ output.put("timestamp", timestamp);
443
+ output.remove("ts");
444
+ return;
445
+ }
446
+ long delta = ((Number) timestamp).longValue();
447
+ long absolute = sessionConnectEpochMs > 0 ? sessionConnectEpochMs + delta : delta;
448
+ output.put("timestamp", absolute);
449
+ output.remove("ts");
450
+ if (sessionConnectEpochMs <= 0) {
451
+ sessionConnectEpochMs = absolute - delta;
452
+ }
453
+ }
454
+ }
455
+
456
+ public static String hashConfig(JSONObject config) {
457
+ try {
458
+ return fnv1a32Hex(canonicalObject(config).toString());
459
+ } catch (JSONException e) {
460
+ return fnv1a32Hex(config.toString());
461
+ }
462
+ }
463
+
464
+ private static JSONObject canonicalObject(JSONObject input) throws JSONException {
465
+ List<String> keys = new ArrayList<>();
466
+ Iterator<String> it = input.keys();
467
+ while (it.hasNext()) {
468
+ keys.add(it.next());
469
+ }
470
+ Collections.sort(keys);
471
+ JSONObject out = new JSONObject();
472
+ for (String key : keys) {
473
+ Object value = input.get(key);
474
+ if (value instanceof JSONObject) {
475
+ out.put(key, canonicalObject((JSONObject) value));
476
+ } else {
477
+ out.put(key, value);
478
+ }
479
+ }
480
+ return out;
481
+ }
482
+
483
+ private static JSONObject cloneObject(JSONObject input) throws JSONException {
484
+ return new JSONObject(input.toString());
485
+ }
486
+
487
+ private static String fnv1a32Hex(String value) {
488
+ byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
489
+ int hash = 0x811c9dc5;
490
+ for (byte b : bytes) {
491
+ hash ^= (b & 0xff);
492
+ hash *= 0x01000193;
493
+ }
494
+ return String.format("%08x", hash);
495
+ }
496
+ }