@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,637 @@
1
+ import Foundation
2
+
3
+ @MainActor
4
+ protocol Ar99OtaGattTransport: AnyObject {
5
+ func enableOtaNotification() -> Bool
6
+ func sendOtaData(_ data: Data)
7
+ func requestMtu(_ mtu: Int)
8
+ func isBleConnected() -> Bool
9
+ }
10
+
11
+ @MainActor
12
+ struct Ar99OtaCallbacks {
13
+ var onProgress: (_ offset: Int, _ total: Int, _ progress: Int) -> Void
14
+ var onCompleted: (_ needReboot: Bool) -> Void
15
+ var onError: (_ errorCode: Int, _ message: String) -> Void
16
+ var onCancelled: () -> Void
17
+ var onPausedWaitingReconnect: () -> Void = {}
18
+ }
19
+
20
+ private enum Ar99OtaCommand {
21
+ static let serviceId: UInt8 = 0x09
22
+ static let requestUpgrade: UInt8 = 0x01
23
+ static let connectNegotiation: UInt8 = 0x02
24
+ static let requireImageData: UInt8 = 0x03
25
+ static let validateImage: UInt8 = 0x06
26
+ static let negotiationResult: UInt8 = 0x09
27
+ static let sendImageData: UInt8 = 0x0B
28
+ }
29
+
30
+ private enum Ar99OtaErrorCode {
31
+ static let protocolError = 0x04
32
+ static let packageSizeError = 0x06
33
+ static let firmwareValidationFailed = 0x0A
34
+ static let unknownError = 0xFF
35
+ }
36
+
37
+ private enum Ar99OtaState {
38
+ static let idle = 0
39
+ static let requesting = 1
40
+ static let negotiating = 2
41
+ static let waitingReady = 3
42
+ static let transferring = 4
43
+ static let completed = 6
44
+ static let failed = 7
45
+ static let pausedDisconnected = 8
46
+ }
47
+
48
+ private struct Ar99OtaFrameHeader {
49
+ let serviceId: UInt8
50
+ let command: UInt8
51
+ let parameterLength: Int
52
+ let payloadOffset: Int
53
+ }
54
+
55
+ private enum Ar99OtaByteUtils {
56
+ static func readUInt16LE(_ data: Data, offset: Int) -> Int {
57
+ guard offset >= 0, offset + 1 < data.count else { return 0 }
58
+ let bytes = Array(data)
59
+ return Int(bytes[offset]) | (Int(bytes[offset + 1]) << 8)
60
+ }
61
+
62
+ static func readInt32LE(_ data: Data, offset: Int) -> Int {
63
+ guard offset >= 0, offset + 3 < data.count else { return 0 }
64
+ let bytes = Array(data)
65
+ let value = UInt32(bytes[offset])
66
+ | (UInt32(bytes[offset + 1]) << 8)
67
+ | (UInt32(bytes[offset + 2]) << 16)
68
+ | (UInt32(bytes[offset + 3]) << 24)
69
+ return Int(Int32(bitPattern: value))
70
+ }
71
+ }
72
+
73
+ private enum Ar99OtaCrc32 {
74
+ private static let table: [UInt32] = {
75
+ (0 ..< 256).map { index in
76
+ var crc = UInt32(index)
77
+ for _ in 0 ..< 8 {
78
+ crc = (crc & 1) == 1 ? (0xEDB88320 ^ (crc >> 1)) : (crc >> 1)
79
+ }
80
+ return crc
81
+ }
82
+ }()
83
+
84
+ static func calculate(_ data: Data?) -> UInt32 {
85
+ var crc: UInt32 = 0xFFFF_FFFF
86
+ for byte in data ?? Data() {
87
+ let index = Int((crc ^ UInt32(byte)) & 0xFF)
88
+ crc = table[index] ^ (crc >> 8)
89
+ }
90
+ return crc ^ 0xFFFF_FFFF
91
+ }
92
+ }
93
+
94
+ private enum Ar99OtaProtocol {
95
+ static func buildFrame(command: UInt8, parameterType: UInt8, payload: Data?) -> Data {
96
+ var frame = Data()
97
+ frame.append(Ar99OtaCommand.serviceId)
98
+ frame.append(command)
99
+ frame.append(parameterType)
100
+ let length = payload?.count ?? 0
101
+ frame.append(UInt8(length & 0xFF))
102
+ frame.append(UInt8((length >> 8) & 0xFF))
103
+ if let payload, !payload.isEmpty {
104
+ frame.append(payload)
105
+ }
106
+ return frame
107
+ }
108
+
109
+ static func buildRequestUpgrade(packageSize: Int, blockSize _: Int, crc32 _: UInt32) -> Data {
110
+ // Wire layout matches the vendor bring-up frame: type marker, then TLV
111
+ // 0x0A/len4 = package size (LE). CRC is validated per-block in sendImageData;
112
+ // blockSize is negotiated separately in connectNegotiation.
113
+ var payload = Data([0x09, 0x01, 0x00, 0x01, 0x0A, 0x04])
114
+ payload.append(UInt8(packageSize & 0xFF))
115
+ payload.append(UInt8((packageSize >> 8) & 0xFF))
116
+ payload.append(UInt8((packageSize >> 16) & 0xFF))
117
+ payload.append(UInt8((packageSize >> 24) & 0xFF))
118
+ payload.append(0x00)
119
+ return buildFrame(command: Ar99OtaCommand.requestUpgrade, parameterType: 0x80, payload: payload)
120
+ }
121
+
122
+ static func buildConnectNegotiation(blockSize _: Int) -> Data {
123
+ buildFrame(command: Ar99OtaCommand.connectNegotiation, parameterType: 0x80, payload: nil)
124
+ }
125
+
126
+ static func buildNegotiationResult() -> Data {
127
+ buildFrame(command: Ar99OtaCommand.negotiationResult, parameterType: 0x80, payload: Data([0x01, 0x01, 0x00, 0x01]))
128
+ }
129
+
130
+ static func buildSendImageData(packetSequenceNumber: Int, block: Data) -> Data {
131
+ var payload = Data()
132
+ payload.append(UInt8(packetSequenceNumber & 0xFF))
133
+ let crc32 = Ar99OtaCrc32.calculate(block)
134
+ payload.append(UInt8(crc32 & 0xFF))
135
+ payload.append(UInt8((crc32 >> 8) & 0xFF))
136
+ payload.append(UInt8((crc32 >> 16) & 0xFF))
137
+ payload.append(UInt8((crc32 >> 24) & 0xFF))
138
+ payload.append(block)
139
+ return buildFrame(command: Ar99OtaCommand.sendImageData, parameterType: 0x80, payload: payload)
140
+ }
141
+
142
+ static func parseFrameHeader(_ frame: Data) -> Ar99OtaFrameHeader? {
143
+ guard frame.count >= 5 else { return nil }
144
+ let bytes = Array(frame)
145
+ return Ar99OtaFrameHeader(
146
+ serviceId: bytes[0],
147
+ command: bytes[1],
148
+ parameterLength: Ar99OtaByteUtils.readUInt16LE(frame, offset: 3),
149
+ payloadOffset: 5
150
+ )
151
+ }
152
+ }
153
+
154
+ @MainActor
155
+ final class Ar99OtaManager {
156
+ static let shared = Ar99OtaManager()
157
+
158
+ private static let defaultBlockSize = 200
159
+ private static let timeoutMs = 5_000
160
+ private static let reconnectTimeoutMs = 90_000
161
+
162
+ private weak var transport: Ar99OtaGattTransport?
163
+ private var callbacks: Ar99OtaCallbacks?
164
+ private var timeoutItem: DispatchWorkItem?
165
+ private var reconnectTimeoutItem: DispatchWorkItem?
166
+
167
+ private var state = Ar99OtaState.idle
168
+ private var firmwareData: Data?
169
+ private var firmwareSize = 0
170
+ private var firmwareCrc32: UInt32 = 0
171
+ private var blockSize = defaultBlockSize
172
+ private var currentOffset = 0
173
+ private var otaNotifyEnabled = false
174
+
175
+ private init() {}
176
+
177
+ func setTransport(_ transport: Ar99OtaGattTransport?) {
178
+ self.transport = transport
179
+ }
180
+
181
+ func setCallback(_ callbacks: Ar99OtaCallbacks?) {
182
+ self.callbacks = callbacks
183
+ }
184
+
185
+ func isOTAInProgress() -> Bool {
186
+ state != Ar99OtaState.idle && state != Ar99OtaState.completed && state != Ar99OtaState.failed
187
+ }
188
+
189
+ func isPausedWaitingReconnect() -> Bool {
190
+ state == Ar99OtaState.pausedDisconnected
191
+ }
192
+
193
+ func getProgress() -> Int {
194
+ guard firmwareSize > 0 else { return 0 }
195
+ return (currentOffset * 100) / firmwareSize
196
+ }
197
+
198
+ func startOTA(filePath: String) -> Bool {
199
+ let trimmed = filePath.trimmingCharacters(in: .whitespacesAndNewlines)
200
+ guard !trimmed.isEmpty else {
201
+ notifyError(Ar99OtaErrorCode.unknownError, "Firmware file path is empty")
202
+ return false
203
+ }
204
+
205
+ let url: URL
206
+ if trimmed.hasPrefix("file://"), let fileUrl = URL(string: trimmed) {
207
+ url = fileUrl
208
+ } else {
209
+ url = URL(fileURLWithPath: trimmed)
210
+ }
211
+
212
+ do {
213
+ return startOTA(data: try Data(contentsOf: url))
214
+ } catch {
215
+ notifyError(Ar99OtaErrorCode.unknownError, "Failed to read firmware file")
216
+ return false
217
+ }
218
+ }
219
+
220
+ func startOTA(data: Data) -> Bool {
221
+ if isOTAInProgress() {
222
+ Bridge.log("Ar99OtaManager: OTA is already in progress")
223
+ return false
224
+ }
225
+ guard !data.isEmpty else {
226
+ notifyError(Ar99OtaErrorCode.packageSizeError, "Firmware data is empty")
227
+ return false
228
+ }
229
+
230
+ state = Ar99OtaState.idle
231
+ otaNotifyEnabled = false
232
+ cancelTimeout()
233
+ cancelReconnectTimeout()
234
+ firmwareData = data
235
+ firmwareSize = data.count
236
+ firmwareCrc32 = Ar99OtaCrc32.calculate(data)
237
+ blockSize = Self.defaultBlockSize
238
+ currentOffset = 0
239
+
240
+ guard let transport else {
241
+ notifyError(Ar99OtaErrorCode.unknownError, "OTA transport is not initialized")
242
+ return false
243
+ }
244
+ guard transport.enableOtaNotification() else {
245
+ notifyError(Ar99OtaErrorCode.unknownError, "OTA service was not found")
246
+ return false
247
+ }
248
+ return true
249
+ }
250
+
251
+ func cancelOTA() {
252
+ state = Ar99OtaState.idle
253
+ otaNotifyEnabled = false
254
+ firmwareData = nil
255
+ firmwareSize = 0
256
+ currentOffset = 0
257
+ cancelTimeout()
258
+ cancelReconnectTimeout()
259
+ callbacks?.onCancelled()
260
+ cleanupFirmware()
261
+ }
262
+
263
+ func onBleDisconnected() {
264
+ guard isOTAInProgress(), firmwareData != nil, firmwareSize > 0 else { return }
265
+ guard state != Ar99OtaState.pausedDisconnected else { return }
266
+ state = Ar99OtaState.pausedDisconnected
267
+ otaNotifyEnabled = false
268
+ cancelTimeout()
269
+ startReconnectTimeout()
270
+ callbacks?.onPausedWaitingReconnect()
271
+ }
272
+
273
+ func tryResumeOtaAfterGattReady() {
274
+ let shouldResume = state == Ar99OtaState.pausedDisconnected && firmwareData != nil && firmwareSize > 0
275
+ if shouldResume {
276
+ _ = transport?.enableOtaNotification()
277
+ }
278
+ }
279
+
280
+ func onOtaNotifyEnabled() {
281
+ otaNotifyEnabled = true
282
+ guard firmwareData != nil, firmwareSize > 0 else { return }
283
+ guard state == Ar99OtaState.idle || state == Ar99OtaState.pausedDisconnected else { return }
284
+
285
+ DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1_000)) { [weak self] in
286
+ Task { @MainActor in
287
+ guard let self else { return }
288
+ guard self.state == Ar99OtaState.idle || self.state == Ar99OtaState.pausedDisconnected else { return }
289
+ _ = self.sendUpgradeRequest()
290
+ }
291
+ }
292
+ }
293
+
294
+ func handleMtuNegotiatedForOta(success: Bool) -> Bool {
295
+ guard state == Ar99OtaState.requesting else { return false }
296
+ guard success else {
297
+ handleOTAFailure(Ar99OtaErrorCode.unknownError, "MTU negotiation failed")
298
+ return true
299
+ }
300
+ onMtuNegotiated()
301
+ return true
302
+ }
303
+
304
+ func handleOTAResponse(_ data: Data) {
305
+ guard data.count >= 5 else { return }
306
+ guard let header = Ar99OtaProtocol.parseFrameHeader(data),
307
+ header.serviceId == Ar99OtaCommand.serviceId
308
+ else {
309
+ return
310
+ }
311
+ cancelTimeout()
312
+
313
+ let payload: Data?
314
+ if header.parameterLength > 0, data.count >= header.payloadOffset + header.parameterLength {
315
+ payload = data.subdata(in: header.payloadOffset ..< header.payloadOffset + header.parameterLength)
316
+ } else {
317
+ payload = nil
318
+ }
319
+
320
+ switch header.command {
321
+ case Ar99OtaCommand.requestUpgrade:
322
+ handleUpgradeRequestResponse(payload)
323
+ case Ar99OtaCommand.connectNegotiation:
324
+ handleNegotiationResponse(payload)
325
+ case Ar99OtaCommand.negotiationResult:
326
+ handleNegotiationResultResponse()
327
+ case Ar99OtaCommand.requireImageData:
328
+ handleRequireImageData(payload)
329
+ case Ar99OtaCommand.sendImageData:
330
+ handleImageDataResponse(payload)
331
+ case Ar99OtaCommand.validateImage:
332
+ handleValidateImageResponse(payload)
333
+ default:
334
+ startTimeout()
335
+ break
336
+ }
337
+ }
338
+
339
+ private func sendUpgradeRequest() -> Bool {
340
+ guard isBluetoothConnected() else {
341
+ notifyError(Ar99OtaErrorCode.unknownError, "Bluetooth is not connected")
342
+ return false
343
+ }
344
+ guard firmwareData != nil, firmwareSize > 0 else {
345
+ state = Ar99OtaState.idle
346
+ return false
347
+ }
348
+ cancelReconnectTimeout()
349
+ state = Ar99OtaState.requesting
350
+ guard let transport else {
351
+ notifyError(Ar99OtaErrorCode.unknownError, "OTA transport is not initialized")
352
+ return false
353
+ }
354
+ transport.requestMtu(247)
355
+ startTimeout()
356
+ return true
357
+ }
358
+
359
+ private func onMtuNegotiated() {
360
+ DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) { [weak self] in
361
+ Task { @MainActor in
362
+ guard let self, self.state == Ar99OtaState.requesting else { return }
363
+ self.sendOtaData(
364
+ Ar99OtaProtocol.buildRequestUpgrade(
365
+ packageSize: self.firmwareSize,
366
+ blockSize: self.blockSize,
367
+ crc32: self.firmwareCrc32
368
+ )
369
+ )
370
+ }
371
+ }
372
+ }
373
+
374
+ private func handleUpgradeRequestResponse(_ payload: Data?) {
375
+ guard let payload, payload.count >= 3 else {
376
+ handleOTAFailure(Ar99OtaErrorCode.protocolError, "Invalid upgrade response")
377
+ return
378
+ }
379
+
380
+ var offset = 0
381
+ var success = false
382
+ while offset + 3 <= payload.count {
383
+ let bytes = Array(payload)
384
+ let type = bytes[offset]
385
+ offset += 1
386
+ let length = Ar99OtaByteUtils.readUInt16LE(payload, offset: offset)
387
+ offset += 2
388
+ guard offset + length <= payload.count else {
389
+ handleOTAFailure(Ar99OtaErrorCode.protocolError, "Invalid upgrade TLV")
390
+ return
391
+ }
392
+ if type == 0x7F, length >= 4 {
393
+ let errorCode = Ar99OtaByteUtils.readInt32LE(payload, offset: offset)
394
+ if errorCode == 100_000 {
395
+ success = true
396
+ } else {
397
+ handleOTAFailure(Ar99OtaErrorCode.protocolError, "Upgrade request failed: \(errorCode)")
398
+ return
399
+ }
400
+ }
401
+ offset += length
402
+ }
403
+
404
+ guard success else {
405
+ handleOTAFailure(Ar99OtaErrorCode.protocolError, "Upgrade request was rejected")
406
+ return
407
+ }
408
+ state = Ar99OtaState.negotiating
409
+ sendOtaData(Ar99OtaProtocol.buildConnectNegotiation(blockSize: blockSize))
410
+ startTimeout()
411
+ }
412
+
413
+ private func handleNegotiationResponse(_ payload: Data?) {
414
+ guard let payload, payload.count >= 3 else {
415
+ handleOTAFailure(Ar99OtaErrorCode.protocolError, "Invalid negotiation response")
416
+ return
417
+ }
418
+
419
+ var offset = 0
420
+ while offset + 3 <= payload.count {
421
+ let bytes = Array(payload)
422
+ let type = bytes[offset]
423
+ offset += 1
424
+ let length = Ar99OtaByteUtils.readUInt16LE(payload, offset: offset)
425
+ offset += 2
426
+ guard offset + length <= payload.count else {
427
+ handleOTAFailure(Ar99OtaErrorCode.protocolError, "Invalid negotiation TLV")
428
+ return
429
+ }
430
+ if type == 0x03, length >= 2 {
431
+ let suggestedBlockSize = Ar99OtaByteUtils.readUInt16LE(payload, offset: offset)
432
+ if suggestedBlockSize > 0 {
433
+ blockSize = suggestedBlockSize
434
+ }
435
+ }
436
+ offset += length
437
+ }
438
+
439
+ state = Ar99OtaState.waitingReady
440
+ sendOtaData(Ar99OtaProtocol.buildNegotiationResult())
441
+ startTimeout()
442
+ }
443
+
444
+ private func handleNegotiationResultResponse() {
445
+ state = Ar99OtaState.transferring
446
+ startTimeout()
447
+ }
448
+
449
+ private func handleRequireImageData(_ payload: Data?) {
450
+ guard let payload, payload.count >= 3 else {
451
+ handleOTAFailure(Ar99OtaErrorCode.protocolError, "Invalid image data request")
452
+ return
453
+ }
454
+
455
+ var offset = 0
456
+ var fileOffset = 0
457
+ var fileLength = 0
458
+ while offset + 3 <= payload.count {
459
+ let bytes = Array(payload)
460
+ let type = bytes[offset]
461
+ offset += 1
462
+ let length = Ar99OtaByteUtils.readUInt16LE(payload, offset: offset)
463
+ offset += 2
464
+ guard offset + length <= payload.count else {
465
+ handleOTAFailure(Ar99OtaErrorCode.protocolError, "Invalid image data TLV")
466
+ return
467
+ }
468
+ if type == 0x01, length >= 4 {
469
+ fileOffset = Ar99OtaByteUtils.readInt32LE(payload, offset: offset)
470
+ } else if type == 0x02, length >= 4 {
471
+ fileLength = Ar99OtaByteUtils.readInt32LE(payload, offset: offset)
472
+ }
473
+ offset += length
474
+ }
475
+
476
+ guard let image = firmwareData,
477
+ firmwareSize > 0,
478
+ fileOffset >= 0,
479
+ fileOffset <= firmwareSize
480
+ else {
481
+ handleOTAFailure(Ar99OtaErrorCode.protocolError, "Invalid firmware offset")
482
+ return
483
+ }
484
+ guard fileOffset < firmwareSize else {
485
+ startTimeout()
486
+ return
487
+ }
488
+
489
+ let remaining = firmwareSize - fileOffset
490
+ let totalSendLength = fileLength > 0 ? min(remaining, fileLength) : remaining
491
+ var sentLength = 0
492
+ var packetSequenceNumber = 0
493
+ while sentLength < totalSendLength {
494
+ let size = min(totalSendLength - sentLength, blockSize)
495
+ let current = fileOffset + sentLength
496
+ let block = image.subdata(in: current ..< current + size)
497
+ sendOtaData(Ar99OtaProtocol.buildSendImageData(packetSequenceNumber: packetSequenceNumber, block: block))
498
+ sentLength += size
499
+ packetSequenceNumber += 1
500
+ }
501
+
502
+ currentOffset = fileOffset + sentLength
503
+ notifyProgress(offset: currentOffset, progress: getProgress())
504
+ startTimeout()
505
+ }
506
+
507
+ private func handleValidateImageResponse(_ payload: Data?) {
508
+ var validFlag: Int?
509
+ if let payload, payload.count >= 4 {
510
+ var offset = 0
511
+ while offset + 3 <= payload.count {
512
+ let bytes = Array(payload)
513
+ let type = bytes[offset]
514
+ offset += 1
515
+ let length = Ar99OtaByteUtils.readUInt16LE(payload, offset: offset)
516
+ offset += 2
517
+ guard offset + length <= payload.count else { break }
518
+ if type == 0x01, length >= 1 {
519
+ validFlag = Int(bytes[offset])
520
+ break
521
+ }
522
+ offset += length
523
+ }
524
+ }
525
+ if validFlag == nil, let payload, let first = payload.first {
526
+ validFlag = Int(first)
527
+ }
528
+
529
+ if validFlag == 1 {
530
+ handleOTASuccess()
531
+ } else {
532
+ handleOTAFailure(Ar99OtaErrorCode.firmwareValidationFailed, "Firmware validation failed")
533
+ }
534
+ }
535
+
536
+ private func handleImageDataResponse(_ payload: Data?) {
537
+ guard let payload, payload.count >= 5 else {
538
+ handleOTAFailure(Ar99OtaErrorCode.protocolError, "Invalid image data response")
539
+ return
540
+ }
541
+ let receivedOffset = Ar99OtaByteUtils.readInt32LE(payload, offset: 0)
542
+ let status = Int(Array(payload)[4])
543
+ guard status == 0 else {
544
+ handleOTAFailure(status, "Firmware data write failed")
545
+ return
546
+ }
547
+ if receivedOffset != currentOffset {
548
+ currentOffset = receivedOffset
549
+ }
550
+ startTimeout()
551
+ }
552
+
553
+ private func sendOtaData(_ frame: Data) {
554
+ guard let transport else {
555
+ handleOTAFailure(Ar99OtaErrorCode.unknownError, "OTA transport is not initialized")
556
+ return
557
+ }
558
+ transport.sendOtaData(frame)
559
+ }
560
+
561
+ private func isBluetoothConnected() -> Bool {
562
+ transport?.isBleConnected() == true && otaNotifyEnabled
563
+ }
564
+
565
+ private func handleOTASuccess() {
566
+ state = Ar99OtaState.completed
567
+ currentOffset = firmwareSize
568
+ cancelTimeout()
569
+ cancelReconnectTimeout()
570
+ notifyProgress(offset: firmwareSize, progress: 100)
571
+ callbacks?.onCompleted(false)
572
+ cleanupFirmware()
573
+ }
574
+
575
+ private func handleOTAFailure(_ code: Int, _ message: String) {
576
+ state = Ar99OtaState.failed
577
+ cancelTimeout()
578
+ cancelReconnectTimeout()
579
+ notifyError(code, message)
580
+ cleanupFirmware()
581
+ }
582
+
583
+ private func startTimeout() {
584
+ cancelTimeout()
585
+ let item = DispatchWorkItem { [weak self] in
586
+ Task { @MainActor in
587
+ self?.handleOTAFailure(Ar99OtaErrorCode.unknownError, "OTA timed out")
588
+ }
589
+ }
590
+ timeoutItem = item
591
+ DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(Self.timeoutMs), execute: item)
592
+ }
593
+
594
+ private func cancelTimeout() {
595
+ timeoutItem?.cancel()
596
+ timeoutItem = nil
597
+ }
598
+
599
+ private func startReconnectTimeout() {
600
+ cancelReconnectTimeout()
601
+ let item = DispatchWorkItem { [weak self] in
602
+ Task { @MainActor in
603
+ guard let self, self.state == Ar99OtaState.pausedDisconnected else { return }
604
+ self.handleOTAFailure(
605
+ Ar99OtaErrorCode.unknownError,
606
+ "Bluetooth disconnected during AR99 OTA. Reconnect timed out; please try the update again."
607
+ )
608
+ }
609
+ }
610
+ reconnectTimeoutItem = item
611
+ DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(Self.reconnectTimeoutMs), execute: item)
612
+ }
613
+
614
+ private func cancelReconnectTimeout() {
615
+ reconnectTimeoutItem?.cancel()
616
+ reconnectTimeoutItem = nil
617
+ }
618
+
619
+ private func notifyProgress(offset: Int, progress: Int) {
620
+ callbacks?.onProgress(offset, firmwareSize, progress)
621
+ }
622
+
623
+ private func notifyError(_ errorCode: Int, _ message: String) {
624
+ callbacks?.onError(errorCode, message)
625
+ }
626
+
627
+ private func cleanupFirmware() {
628
+ firmwareData = nil
629
+ firmwareSize = 0
630
+ firmwareCrc32 = 0
631
+ currentOffset = 0
632
+ blockSize = Self.defaultBlockSize
633
+ otaNotifyEnabled = false
634
+ cancelTimeout()
635
+ cancelReconnectTimeout()
636
+ }
637
+ }