@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,866 @@
1
+ import Foundation
2
+
3
+ func generatedCameraRequestId(_ prefix: String) -> String {
4
+ "\(prefix)-\(Int(Date().timeIntervalSince1970 * 1000))-\(UUID().uuidString.prefix(8))"
5
+ }
6
+
7
+ func nonBlankRequestId(_ requestId: String?) -> String? {
8
+ guard let requestId else { return nil }
9
+ let trimmed = requestId.trimmingCharacters(in: .whitespacesAndNewlines)
10
+ return trimmed.isEmpty ? nil : trimmed
11
+ }
12
+
13
+ public enum PhotoSize: String {
14
+ case low
15
+ case medium
16
+ case high
17
+ case max
18
+
19
+ public static func normalizeLegacy(_ value: String?) -> String {
20
+ switch value {
21
+ case "small":
22
+ return PhotoSize.low.rawValue
23
+ case "large":
24
+ return PhotoSize.high.rawValue
25
+ case "full":
26
+ return PhotoSize.max.rawValue
27
+ default:
28
+ return value ?? PhotoSize.medium.rawValue
29
+ }
30
+ }
31
+
32
+ public init(normalizedRawValue value: String?) {
33
+ let normalized = PhotoSize.normalizeLegacy(value)
34
+ self = PhotoSize(rawValue: normalized) ?? .medium
35
+ }
36
+ }
37
+
38
+ public enum PhotoMode: String {
39
+ case photo
40
+ case text
41
+
42
+ public init(normalizedRawValue value: String?) {
43
+ self = PhotoMode(rawValue: value ?? "") ?? .photo
44
+ }
45
+ }
46
+
47
+ public enum ButtonPhotoSize: String {
48
+ case low
49
+ case medium
50
+ case high
51
+ case max
52
+
53
+ public static func normalizeLegacy(_ value: String?) -> String {
54
+ PhotoSize.normalizeLegacy(value)
55
+ }
56
+
57
+ public init(normalizedRawValue value: String?) {
58
+ let normalized = ButtonPhotoSize.normalizeLegacy(value)
59
+ self = ButtonPhotoSize(rawValue: normalized) ?? .medium
60
+ }
61
+ }
62
+
63
+ public enum PhotoCompression: String {
64
+ case none
65
+ case medium
66
+ case heavy
67
+ }
68
+
69
+ public struct PhotoCaptureDefaults {
70
+ public let size: PhotoSize?
71
+ public let mfnr: Bool?
72
+ public let zsl: Bool?
73
+ public let noiseReduction: Bool?
74
+ public let edgeEnhancement: Bool?
75
+ public let ispDigitalGain: Int?
76
+ public let ispAnalogGain: String?
77
+ public let aeExposureDivisor: Int?
78
+ public let isoCap: Int?
79
+ public let compress: String?
80
+ public let sound: Bool?
81
+ public let resetCaptureTuning: Bool?
82
+
83
+ public init(
84
+ size: PhotoSize? = nil,
85
+ mfnr: Bool? = nil,
86
+ zsl: Bool? = nil,
87
+ noiseReduction: Bool? = nil,
88
+ edgeEnhancement: Bool? = nil,
89
+ ispDigitalGain: Int? = nil,
90
+ ispAnalogGain: String? = nil,
91
+ aeExposureDivisor: Int? = nil,
92
+ isoCap: Int? = nil,
93
+ compress: String? = nil,
94
+ sound: Bool? = nil,
95
+ resetCaptureTuning: Bool? = nil
96
+ ) {
97
+ self.size = size
98
+ self.mfnr = mfnr
99
+ self.zsl = zsl
100
+ self.noiseReduction = noiseReduction
101
+ self.edgeEnhancement = edgeEnhancement
102
+ self.ispDigitalGain = ispDigitalGain
103
+ self.ispAnalogGain = ispAnalogGain
104
+ self.aeExposureDivisor = aeExposureDivisor
105
+ self.isoCap = isoCap
106
+ self.compress = compress
107
+ self.sound = sound
108
+ self.resetCaptureTuning = resetCaptureTuning
109
+ }
110
+
111
+ static func from(params: [String: Any]) -> PhotoCaptureDefaults {
112
+ let size = (params["size"] as? String).map { PhotoSize(normalizedRawValue: $0) }
113
+ let aeExposureDivisor =
114
+ optionalIntValue(params, "aeExposureDivisor").flatMap { $0 > 1 ? $0 : nil }
115
+ let isoCap = optionalIntValue(params, "isoCap").flatMap { $0 > 0 ? $0 : nil }
116
+ return PhotoCaptureDefaults(
117
+ size: size,
118
+ mfnr: optionalBoolValue(params, "mfnr"),
119
+ zsl: optionalBoolValue(params, "zsl"),
120
+ noiseReduction: optionalBoolValue(params, "noiseReduction"),
121
+ edgeEnhancement: optionalBoolValue(params, "edgeEnhancement"),
122
+ ispDigitalGain: optionalIntValue(params, "ispDigitalGain"),
123
+ ispAnalogGain: optionalStringValue(params, "ispAnalogGain"),
124
+ aeExposureDivisor: aeExposureDivisor,
125
+ isoCap: isoCap,
126
+ compress: optionalStringValue(params, "compress"),
127
+ sound: optionalBoolValue(params, "sound"),
128
+ resetCaptureTuning: optionalBoolValue(params, "resetCaptureTuning")
129
+ )
130
+ }
131
+ }
132
+
133
+ public struct VideoRecordingDefaults {
134
+ public let width: Int
135
+ public let height: Int
136
+ public let fps: Int
137
+
138
+ public init(width: Int, height: Int, fps: Int) {
139
+ self.width = width
140
+ self.height = height
141
+ self.fps = fps
142
+ }
143
+ }
144
+
145
+ public enum CameraRoiPosition: Int {
146
+ case center = 0
147
+ case bottom = 1
148
+ case top = 2
149
+
150
+ public var label: String {
151
+ switch self {
152
+ case .center:
153
+ return "center"
154
+ case .bottom:
155
+ return "bottom"
156
+ case .top:
157
+ return "top"
158
+ }
159
+ }
160
+
161
+ public static func from(rawValue: Int?) -> CameraRoiPosition {
162
+ guard let rawValue else {
163
+ return .center
164
+ }
165
+ return CameraRoiPosition(rawValue: rawValue) ?? .center
166
+ }
167
+ }
168
+
169
+ public struct CameraFov {
170
+ public static let minFov = 62
171
+ public static let maxFov = 118
172
+ public static let defaultFov = 118
173
+ public static let narrowFov = 82
174
+ public static let standardFov = 102
175
+ public static let defaultRoiPosition = CameraRoiPosition.center
176
+ public static let narrow = CameraFov(
177
+ fov: CameraFov.narrowFov,
178
+ roiPosition: CameraFov.defaultRoiPosition
179
+ )
180
+ public static let standard = CameraFov(
181
+ fov: CameraFov.standardFov,
182
+ roiPosition: CameraFov.defaultRoiPosition
183
+ )
184
+ public static let wide = CameraFov(
185
+ fov: CameraFov.maxFov,
186
+ roiPosition: CameraFov.defaultRoiPosition
187
+ )
188
+
189
+ public let fov: Int
190
+ public let roiPosition: CameraRoiPosition
191
+
192
+ public init(fov: Int = CameraFov.defaultFov, roiPosition: CameraRoiPosition = CameraFov.defaultRoiPosition) {
193
+ self.fov = min(max(fov, CameraFov.minFov), CameraFov.maxFov)
194
+ self.roiPosition = roiPosition
195
+ }
196
+
197
+ var value: [String: Int] {
198
+ ["fov": fov, "roi_position": roiPosition.rawValue]
199
+ }
200
+ }
201
+
202
+ public struct CameraFovResult: CustomStringConvertible {
203
+ public let requestId: String
204
+ public let fov: Int
205
+ public let roiPosition: CameraRoiPosition
206
+ public let timestamp: Int
207
+
208
+ public var values: [String: Any] {
209
+ [
210
+ "requestId": requestId,
211
+ "fov": fov,
212
+ "roiPosition": roiPosition.label,
213
+ "timestamp": timestamp,
214
+ ]
215
+ }
216
+
217
+ public var description: String {
218
+ "CameraFovResult(fov: \(fov), roiPosition: \(roiPosition.label))"
219
+ }
220
+
221
+ static func from(ack: SettingsAckEvent, fallback: CameraFov) throws -> CameraFovResult {
222
+ if ack.status == "error" {
223
+ throw BluetoothSdkError(
224
+ code: ack.errorCode ?? "camera_fov_failed",
225
+ message: ack.errorMessage ?? "Camera FOV request failed."
226
+ )
227
+ }
228
+ if !ack.hardwareApplied {
229
+ throw BluetoothSdkError(
230
+ code: "camera_fov_not_applied",
231
+ message: "Camera FOV was saved but not applied to hardware."
232
+ )
233
+ }
234
+
235
+ return CameraFovResult(
236
+ requestId: ack.requestId,
237
+ fov: ack.fov ?? fallback.fov,
238
+ roiPosition: CameraRoiPosition.from(rawValue: ack.roiPosition ?? fallback.roiPosition.rawValue),
239
+ timestamp: ack.timestamp
240
+ )
241
+ }
242
+ }
243
+
244
+ public struct PhotoRequest {
245
+ public let requestId: String
246
+ public let size: PhotoSize
247
+ public let mode: PhotoMode
248
+ public let transferMethod: String
249
+ public let webhookUrl: String?
250
+ public let authToken: String?
251
+ public let compress: PhotoCompression?
252
+ public let save: Bool
253
+ public let sound: Bool
254
+ /// Sensor exposure time for this capture only (ns), or nil for auto exposure
255
+ public let exposureTimeNs: Double?
256
+ /// Sensor ISO for this capture only. Only used when exposureTimeNs enables manual exposure.
257
+ public let iso: Int?
258
+ public let aeExposureDivisor: Int?
259
+ public let isoCap: Int?
260
+ public let noiseReduction: Bool?
261
+ public let edgeEnhancement: Bool?
262
+ public let mfnr: Bool?
263
+ public let zsl: Bool?
264
+ public let ispDigitalGain: Int?
265
+ public let ispAnalogGain: String?
266
+
267
+ public init(
268
+ requestId: String? = nil,
269
+ size: PhotoSize,
270
+ webhookUrl: String? = nil,
271
+ authToken: String? = nil,
272
+ compress: PhotoCompression? = nil,
273
+ save: Bool = false,
274
+ sound: Bool,
275
+ exposureTimeNs: Double? = nil,
276
+ iso: Int? = nil,
277
+ aeExposureDivisor: Int? = nil,
278
+ isoCap: Int? = nil,
279
+ noiseReduction: Bool? = nil,
280
+ edgeEnhancement: Bool? = nil,
281
+ mfnr: Bool? = nil,
282
+ zsl: Bool? = nil,
283
+ ispDigitalGain: Int? = nil,
284
+ ispAnalogGain: String? = nil,
285
+ mode: PhotoMode = .photo,
286
+ transferMethod: String = "auto"
287
+ ) {
288
+ self.requestId = nonBlankRequestId(requestId) ?? generatedCameraRequestId("photo")
289
+ self.size = size
290
+ self.webhookUrl = webhookUrl
291
+ self.authToken = authToken
292
+ self.compress = compress
293
+ self.save = save
294
+ self.sound = sound
295
+ self.exposureTimeNs = exposureTimeNs
296
+ self.iso = iso
297
+ self.aeExposureDivisor = aeExposureDivisor
298
+ self.isoCap = isoCap
299
+ self.noiseReduction = noiseReduction
300
+ self.edgeEnhancement = edgeEnhancement
301
+ self.mfnr = mfnr
302
+ self.zsl = zsl
303
+ self.ispDigitalGain = ispDigitalGain
304
+ self.ispAnalogGain = ispAnalogGain
305
+ self.mode = mode
306
+ self.transferMethod = transferMethod
307
+ }
308
+
309
+ public static func from(params: [String: Any]) throws -> PhotoRequest {
310
+ let sizeRaw = params["size"] as? String ?? "medium"
311
+ let compressRaw = params["compress"] as? String ?? "none"
312
+ let transferMethod: String
313
+ if let rawValue = params["transferMethod"] {
314
+ guard let rawString = rawValue as? String,
315
+ rawString == "auto" || rawString == "direct" || rawString == "ble"
316
+ else {
317
+ throw BluetoothSdkError(
318
+ code: "invalid_photo_transfer_method",
319
+ message: "Invalid transferMethod \(String(describing: rawValue)). Expected auto, direct, or ble."
320
+ )
321
+ }
322
+ transferMethod = rawString
323
+ } else {
324
+ transferMethod = "auto"
325
+ }
326
+ let exposureTimeNs: Double?
327
+ switch params["exposureTimeNs"] {
328
+ case let value as Double:
329
+ exposureTimeNs = value.isFinite && value > 0 ? value : nil
330
+ case let value as Int:
331
+ exposureTimeNs = value > 0 ? Double(value) : nil
332
+ case let value as NSNumber:
333
+ let d = value.doubleValue
334
+ exposureTimeNs = d.isFinite && d > 0 ? d : nil
335
+ default:
336
+ exposureTimeNs = nil
337
+ }
338
+ let iso: Int?
339
+ switch params["iso"] {
340
+ case let value as Int:
341
+ iso = value > 0 ? value : nil
342
+ case let value as Double:
343
+ iso = value.isFinite && value > 0 && value < Double(Int.max) ? Int(value) : nil
344
+ case let value as NSNumber:
345
+ let intValue = value.intValue
346
+ iso = intValue > 0 ? intValue : nil
347
+ default:
348
+ iso = nil
349
+ }
350
+ func optionalInt(_ key: String, min: Int = Int.min, filter: (Int) -> Bool = { _ in true }) -> Int? {
351
+ guard params.keys.contains(key) else { return nil }
352
+ switch params[key] {
353
+ case let value as Int:
354
+ return filter(value) ? value : nil
355
+ case let value as Double:
356
+ guard value.isFinite, value >= Double(min) else { return nil }
357
+ return filter(Int(value)) ? Int(value) : nil
358
+ case let value as NSNumber:
359
+ let intValue = value.intValue
360
+ return filter(intValue) ? intValue : nil
361
+ default:
362
+ return nil
363
+ }
364
+ }
365
+ func optionalBool(_ key: String) -> Bool? {
366
+ guard params.keys.contains(key) else { return nil }
367
+ return params[key] as? Bool
368
+ }
369
+
370
+ return PhotoRequest(
371
+ requestId: params["requestId"] as? String,
372
+ size: PhotoSize(normalizedRawValue: sizeRaw),
373
+ webhookUrl: params["webhookUrl"] as? String,
374
+ authToken: (params["authToken"] as? String)?.nilIfBlank,
375
+ compress: PhotoCompression(rawValue: compressRaw),
376
+ save: (params["save"] as? Bool) ?? (params["saveToGallery"] as? Bool) ?? false,
377
+ sound: params["sound"] as? Bool ?? true,
378
+ exposureTimeNs: exposureTimeNs,
379
+ iso: iso,
380
+ aeExposureDivisor: optionalInt("aeExposureDivisor", min: 2) { $0 > 1 },
381
+ isoCap: optionalInt("isoCap", min: 1) { $0 > 0 },
382
+ noiseReduction: optionalBool("noiseReduction"),
383
+ edgeEnhancement: optionalBool("edgeEnhancement"),
384
+ mfnr: optionalBool("mfnr"),
385
+ zsl: optionalBool("zsl"),
386
+ ispDigitalGain: optionalInt("ispDigitalGain"),
387
+ ispAnalogGain: params["ispAnalogGain"] as? String,
388
+ mode: PhotoMode(normalizedRawValue: params["mode"] as? String),
389
+ transferMethod: transferMethod
390
+ )
391
+ }
392
+
393
+ func appendScanFields(to json: inout [String: Any]) {
394
+ if let aeExposureDivisor {
395
+ json["aeExposureDivisor"] = aeExposureDivisor
396
+ }
397
+ if let isoCap {
398
+ json["isoCap"] = isoCap
399
+ }
400
+ if let noiseReduction {
401
+ json["noiseReduction"] = noiseReduction
402
+ }
403
+ if let edgeEnhancement {
404
+ json["edgeEnhancement"] = edgeEnhancement
405
+ }
406
+ if let mfnr {
407
+ json["mfnr"] = mfnr
408
+ }
409
+ if let zsl {
410
+ json["zsl"] = zsl
411
+ }
412
+ if let ispDigitalGain {
413
+ json["ispDigitalGain"] = ispDigitalGain
414
+ }
415
+ if let ispAnalogGain {
416
+ json["ispAnalogGain"] = ispAnalogGain
417
+ }
418
+ }
419
+
420
+ func withRequestId(_ requestId: String) -> PhotoRequest {
421
+ PhotoRequest(
422
+ requestId: requestId,
423
+ size: size,
424
+ webhookUrl: webhookUrl,
425
+ authToken: authToken,
426
+ compress: compress,
427
+ save: save,
428
+ sound: sound,
429
+ exposureTimeNs: exposureTimeNs,
430
+ iso: iso,
431
+ aeExposureDivisor: aeExposureDivisor,
432
+ isoCap: isoCap,
433
+ noiseReduction: noiseReduction,
434
+ edgeEnhancement: edgeEnhancement,
435
+ mfnr: mfnr,
436
+ zsl: zsl,
437
+ ispDigitalGain: ispDigitalGain,
438
+ ispAnalogGain: ispAnalogGain,
439
+ mode: mode,
440
+ transferMethod: transferMethod
441
+ )
442
+ }
443
+ }
444
+
445
+ private extension String {
446
+ var nilIfBlank: String? {
447
+ isEmpty ? nil : self
448
+ }
449
+ }
450
+
451
+ public enum RgbLedAction: String {
452
+ case on
453
+ case off
454
+ }
455
+
456
+ public enum RgbLedColor: String {
457
+ case red
458
+ case green
459
+ case blue
460
+ case orange
461
+ case white
462
+ }
463
+
464
+ public struct RgbLedRequest {
465
+ public let requestId: String
466
+ public let packageName: String?
467
+ public let action: RgbLedAction
468
+ public let color: RgbLedColor?
469
+ public let onDurationMs: Int
470
+ public let offDurationMs: Int
471
+ public let count: Int
472
+
473
+ public init(
474
+ requestId: String,
475
+ packageName: String?,
476
+ action: RgbLedAction,
477
+ color: RgbLedColor?,
478
+ onDurationMs: Int,
479
+ offDurationMs: Int,
480
+ count: Int
481
+ ) {
482
+ self.requestId = requestId
483
+ self.packageName = packageName
484
+ self.action = action
485
+ self.color = color
486
+ self.onDurationMs = onDurationMs
487
+ self.offDurationMs = offDurationMs
488
+ self.count = count
489
+ }
490
+ }
491
+
492
+ public struct VideoRecordingRequest {
493
+ public let requestId: String
494
+ public let save: Bool
495
+ public let sound: Bool
496
+ // Optional per-recording overrides; 0 means "use the saved button-video default".
497
+ public let width: Int
498
+ public let height: Int
499
+ public let fps: Int
500
+ // Optional auto-stop timer in minutes; 0 = record until stopped/interrupted.
501
+ public let maxRecordingTimeMinutes: Int
502
+
503
+ public init(
504
+ requestId: String, save: Bool, sound: Bool, width: Int = 0, height: Int = 0, fps: Int = 0,
505
+ maxRecordingTimeMinutes: Int = 0
506
+ ) {
507
+ self.requestId = requestId
508
+ self.save = save
509
+ self.sound = sound
510
+ self.width = width
511
+ self.height = height
512
+ self.fps = fps
513
+ self.maxRecordingTimeMinutes = maxRecordingTimeMinutes
514
+ }
515
+ }
516
+
517
+ public struct VideoRecordingStatusEvent: CustomStringConvertible {
518
+ public let values: [String: Any]
519
+
520
+ public init(values: [String: Any]) {
521
+ var values = values
522
+ values["type"] = "video_recording_status"
523
+ self.values = values
524
+ }
525
+
526
+ public var requestId: String {
527
+ stringValue(values, "requestId") ?? ""
528
+ }
529
+
530
+ public var success: Bool {
531
+ boolValue(values, "success") ?? false
532
+ }
533
+
534
+ public var status: String {
535
+ stringValue(values, "status") ?? ""
536
+ }
537
+
538
+ public var details: String? {
539
+ stringValue(values, "details")
540
+ }
541
+
542
+ public var timestamp: Int {
543
+ intValue(values["timestamp"]) ?? Int(Date().timeIntervalSince1970 * 1000)
544
+ }
545
+
546
+ public var data: [String: Any]? {
547
+ values["data"] as? [String: Any]
548
+ }
549
+
550
+ public var description: String {
551
+ "VideoRecordingStatusEvent(requestId: \(requestId), status: \(status), success: \(success))"
552
+ }
553
+ }
554
+
555
+ public struct MediaUploadEvent: CustomStringConvertible {
556
+ public let values: [String: Any]
557
+
558
+ public init(values: [String: Any]) {
559
+ self.values = values
560
+ }
561
+
562
+ public var type: String {
563
+ stringValue(values, "type") ?? ""
564
+ }
565
+
566
+ public var requestId: String {
567
+ stringValue(values, "requestId") ?? ""
568
+ }
569
+
570
+ public var mediaUrl: String? {
571
+ stringValue(values, "mediaUrl")
572
+ }
573
+
574
+ public var errorMessage: String? {
575
+ stringValue(values, "errorMessage")
576
+ }
577
+
578
+ public var mediaType: Int? {
579
+ intValue(values["mediaType"])
580
+ }
581
+
582
+ public var timestamp: Int {
583
+ intValue(values["timestamp"]) ?? Int(Date().timeIntervalSince1970 * 1000)
584
+ }
585
+
586
+ public var isSuccess: Bool {
587
+ type == "media_success"
588
+ }
589
+
590
+ public var isVideo: Bool {
591
+ mediaType == 2
592
+ }
593
+
594
+ public var description: String {
595
+ "MediaUploadEvent(requestId: \(requestId), type: \(type), mediaType: \(mediaType ?? -1))"
596
+ }
597
+ }
598
+
599
+ public enum PhotoResponse: CustomStringConvertible, Equatable {
600
+ public enum State: String {
601
+ case success
602
+ case error
603
+ }
604
+
605
+ case success(
606
+ requestId: String,
607
+ uploadUrl: String,
608
+ photoUrl: String?,
609
+ statusUrl: String?,
610
+ contentType: String?,
611
+ fileSizeBytes: Int?,
612
+ timestamp: Int
613
+ )
614
+ case error(requestId: String, errorCode: String?, errorMessage: String, timestamp: Int)
615
+
616
+ public init(values: [String: Any]) {
617
+ let requestId = stringValue(values, "requestId") ?? ""
618
+ let timestamp = intValue(values["timestamp"]) ?? Int(Date().timeIntervalSince1970 * 1000)
619
+ let state = stringValue(values, "state")?.lowercased()
620
+ let success = state == State.success.rawValue || boolValue(values, "success") == true
621
+ if success {
622
+ self = .success(
623
+ requestId: requestId,
624
+ uploadUrl: stringValue(values, "uploadUrl") ?? "",
625
+ photoUrl: stringValue(values, "photoUrl"),
626
+ statusUrl: stringValue(values, "statusUrl"),
627
+ contentType: stringValue(values, "contentType") ?? stringValue(values, "mimeType"),
628
+ fileSizeBytes: intValue(values["fileSizeBytes"]) ?? intValue(values["bytes"])
629
+ ?? intValue(values["size"]),
630
+ timestamp: timestamp
631
+ )
632
+ } else {
633
+ self = .error(
634
+ requestId: requestId,
635
+ errorCode: stringValue(values, "errorCode"),
636
+ errorMessage: stringValue(values, "errorMessage") ?? stringValue(values, "error")
637
+ ?? "Unknown photo error",
638
+ timestamp: timestamp
639
+ )
640
+ }
641
+ }
642
+
643
+ public var state: State {
644
+ switch self {
645
+ case .success:
646
+ .success
647
+ case .error:
648
+ .error
649
+ }
650
+ }
651
+
652
+ public var requestId: String {
653
+ switch self {
654
+ case let .success(requestId, _, _, _, _, _, _), let .error(requestId, _, _, _):
655
+ requestId
656
+ }
657
+ }
658
+
659
+ public var timestamp: Int {
660
+ switch self {
661
+ case let .success(_, _, _, _, _, _, timestamp), let .error(_, _, _, timestamp):
662
+ timestamp
663
+ }
664
+ }
665
+
666
+ public var values: [String: Any] {
667
+ switch self {
668
+ case let .success(requestId, uploadUrl, photoUrl, statusUrl, contentType, fileSizeBytes, timestamp):
669
+ var values: [String: Any] = [
670
+ "state": State.success.rawValue,
671
+ "requestId": requestId,
672
+ "uploadUrl": uploadUrl,
673
+ "timestamp": timestamp,
674
+ ]
675
+ if let photoUrl, !photoUrl.isEmpty {
676
+ values["photoUrl"] = photoUrl
677
+ }
678
+ if let statusUrl, !statusUrl.isEmpty {
679
+ values["statusUrl"] = statusUrl
680
+ }
681
+ if let contentType, !contentType.isEmpty {
682
+ values["contentType"] = contentType
683
+ }
684
+ if let fileSizeBytes {
685
+ values["fileSizeBytes"] = fileSizeBytes
686
+ }
687
+ return values
688
+ case let .error(requestId, errorCode, errorMessage, timestamp):
689
+ var values: [String: Any] = [
690
+ "state": State.error.rawValue,
691
+ "requestId": requestId,
692
+ "errorMessage": errorMessage,
693
+ "timestamp": timestamp,
694
+ ]
695
+ if let errorCode, !errorCode.isEmpty {
696
+ values["errorCode"] = errorCode
697
+ }
698
+ return values
699
+ }
700
+ }
701
+
702
+ public var description: String {
703
+ "PhotoResponse(requestId: \(requestId), state: \(state.rawValue))"
704
+ }
705
+ }
706
+
707
+ public struct PhotoResponseEvent: CustomStringConvertible {
708
+ public let response: PhotoResponse
709
+
710
+ public init(response: PhotoResponse) {
711
+ self.response = response
712
+ }
713
+
714
+ public init(values: [String: Any]) {
715
+ response = PhotoResponse(values: values)
716
+ }
717
+
718
+ public var requestId: String {
719
+ response.requestId
720
+ }
721
+
722
+ public var values: [String: Any] {
723
+ var values = response.values
724
+ values["type"] = "photo_response"
725
+ return values
726
+ }
727
+
728
+ public var description: String {
729
+ "PhotoResponseEvent(requestId: \(requestId), state: \(response.state.rawValue))"
730
+ }
731
+ }
732
+
733
+ public struct PhotoStatusEvent: CustomStringConvertible {
734
+ public let values: [String: Any]
735
+
736
+ public init(values: [String: Any]) {
737
+ var values = values
738
+ values["type"] = "photo_status"
739
+ self.values = values
740
+ }
741
+
742
+ public var requestId: String {
743
+ stringValue(values, "requestId") ?? ""
744
+ }
745
+
746
+ public var status: String {
747
+ stringValue(values, "status") ?? ""
748
+ }
749
+
750
+ public var timestamp: Int64 {
751
+ if let value = values["timestamp"] as? Int64 { return value }
752
+ if let value = values["timestamp"] as? Int { return Int64(value) }
753
+ if let value = values["timestamp"] as? Double { return Int64(value) }
754
+ if let value = values["timestamp"] as? NSNumber { return value.int64Value }
755
+ return Int64(Date().timeIntervalSince1970 * 1000)
756
+ }
757
+
758
+ public var resolvedConfig: [String: Any]? {
759
+ values["resolvedConfig"] as? [String: Any]
760
+ }
761
+
762
+ public var requestedCaptureConfig: [String: Any]? {
763
+ values["requestedCaptureConfig"] as? [String: Any]
764
+ }
765
+
766
+ public var meteredPreview: [String: Any]? {
767
+ values["meteredPreview"] as? [String: Any]
768
+ }
769
+
770
+ public var captureMetadata: [String: Any]? {
771
+ values["captureMetadata"] as? [String: Any]
772
+ }
773
+
774
+ public var errorCode: String? {
775
+ stringValue(values, "errorCode")
776
+ }
777
+
778
+ public var errorMessage: String? {
779
+ stringValue(values, "errorMessage")
780
+ }
781
+
782
+ public var description: String {
783
+ "PhotoStatusEvent(requestId: \(requestId), status: \(status))"
784
+ }
785
+ }
786
+
787
+ public struct CameraStatusEvent: CustomStringConvertible {
788
+ public let values: [String: Any]
789
+
790
+ public init(values: [String: Any]) {
791
+ var values = values
792
+ values["type"] = "camera_status"
793
+ self.values = values
794
+ }
795
+
796
+ public var requestId: String {
797
+ stringValue(values, "requestId") ?? ""
798
+ }
799
+
800
+ public var state: String {
801
+ stringValue(values, "state") ?? ""
802
+ }
803
+
804
+ public var timestamp: Int64 {
805
+ if let value = values["timestamp"] as? Int64 { return value }
806
+ if let value = values["timestamp"] as? Int { return Int64(value) }
807
+ if let value = values["timestamp"] as? Double { return Int64(value) }
808
+ if let value = values["timestamp"] as? NSNumber { return value.int64Value }
809
+ return Int64(Date().timeIntervalSince1970 * 1000)
810
+ }
811
+
812
+ public var errorCode: String? {
813
+ stringValue(values, "errorCode")
814
+ }
815
+
816
+ public var errorMessage: String? {
817
+ stringValue(values, "errorMessage")
818
+ }
819
+
820
+ public var description: String {
821
+ "CameraStatusEvent(requestId: \(requestId), state: \(state))"
822
+ }
823
+ }
824
+
825
+ public struct GalleryStatusEvent: CustomStringConvertible {
826
+ public let values: [String: Any]
827
+
828
+ public init(values: [String: Any]) {
829
+ var values = values
830
+ values["type"] = "gallery_status"
831
+ self.values = values
832
+ }
833
+
834
+ public var photos: Int {
835
+ intValue(values["photos"]) ?? 0
836
+ }
837
+
838
+ public var videos: Int {
839
+ intValue(values["videos"]) ?? 0
840
+ }
841
+
842
+ public var total: Int {
843
+ intValue(values["total"]) ?? 0
844
+ }
845
+
846
+ public var totalSize: Int? {
847
+ intValue(values["totalSize"]) ?? intValue(values["total_size"])
848
+ }
849
+
850
+ public var hasContent: Bool {
851
+ boolValue(values, "hasContent", "has_content") ?? false
852
+ }
853
+
854
+ public var cameraBusy: Bool {
855
+ boolValue(values, "cameraBusy", "camera_busy") ?? false
856
+ }
857
+
858
+ public var cameraBusyReason: String? {
859
+ stringValue(values, "cameraBusyReason", "camera_busy")
860
+ }
861
+
862
+ public var description: String {
863
+ "GalleryStatusEvent(total: \(total), photos: \(photos), videos: \(videos))"
864
+ }
865
+ }
866
+