@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.
- package/README.md +563 -0
- package/android/build.gradle +450 -0
- package/android/gradle.properties.example +9 -0
- package/android/lc3Lib/CMakeLists.txt +6 -0
- package/android/lc3Lib/build.gradle +212 -0
- package/android/lc3Lib/proguard-rules.pro +33 -0
- package/android/lc3Lib/src/main/AndroidManifest.xml +2 -0
- package/android/lc3Lib/src/main/cpp/CMakeLists.txt +8 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/CMakeLists.txt +30 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/CMakeLists.txt +7 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.cc +96 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.h +53 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/Makefile.am +6 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h +26 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h.in +26 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/ogg.h +209 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/os_types.h +158 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus.h +981 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_custom.h +342 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_defines.h +799 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_multistream.h +660 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_projection.h +568 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_types.h +166 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.cc +268 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.h +115 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/opus_tools/opus_header.h +59 -0
- package/android/lc3Lib/src/main/cpp/liblc3/CMakeLists.txt +38 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/lc3.h +309 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/lc3_private.h +162 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/rnnoise.h +114 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/CMakeLists.txt +19 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.c +92 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.h +44 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.c +375 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.h +315 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.c +129 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.h +69 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/common.h +148 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.c +70 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.h +43 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/fastmath.h +158 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/lc3.c +702 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.c +893 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.h +111 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_arm.h +506 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_neon.h +281 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/makefile.mk +35 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.c +452 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.h +57 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct_neon.h +296 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/meson.build +46 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.c +61 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.h +57 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.c +880 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.h +103 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.c +904 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.h +119 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.c +3457 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.h +94 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.c +457 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.h +99 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3.cpp +159 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/_kiss_fft_guts.h +182 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/arch.h +261 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.c +279 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.h +59 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/common.h +48 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/compile.sh +3 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/denoise.c +646 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.c +601 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.h +203 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/opus_types.h +159 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.c +526 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.h +149 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.c +178 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.h +69 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.c +11051 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.h +34 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_reader.c +168 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_train.py +66 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/tansig_table.h +45 -0
- package/android/lc3Lib/src/main/java/com/glassly/lc3Lib/Lc3Cpp.java +38 -0
- package/android/lc3Lib/third_party/CMakeLists.txt +23 -0
- package/android/lc3Lib/third_party/CMakeLists_libogg.txt +18 -0
- package/android/lc3Lib/third_party/CMakeLists_libopus.txt +18 -0
- package/android/lc3Lib/third_party/CMakeLists_opus-tools.txt +23 -0
- package/android/lc3Lib/third_party/opus_tools/src/AUTHORS +5 -0
- package/android/lc3Lib/third_party/opus_tools/src/CMakeLists.txt +4 -0
- package/android/lc3Lib/third_party/opus_tools/src/COPYING +371 -0
- package/android/lc3Lib/third_party/opus_tools/src/ChangeLog +3 -0
- package/android/lc3Lib/third_party/opus_tools/src/Makefile.am +42 -0
- package/android/lc3Lib/third_party/opus_tools/src/Makefile.unix +23 -0
- package/android/lc3Lib/third_party/opus_tools/src/NEWS +0 -0
- package/android/lc3Lib/third_party/opus_tools/src/README +0 -0
- package/android/lc3Lib/third_party/opus_tools/src/autogen.sh +115 -0
- package/android/lc3Lib/third_party/opus_tools/src/configure.ac +293 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/arch.h +239 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/audio-in.c +1046 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.c +245 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.h +28 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.c +320 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.h +51 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/lpc.c +157 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/lpc.h +27 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.c +286 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.h +59 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusdec.c +884 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.c +1021 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.h +101 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.c +639 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.h +51 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/os_support.h +167 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/resample.c +1137 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/speex_resampler.h +344 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/stack_alloc.h +115 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.c +125 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.h +62 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.c +223 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.h +60 -0
- package/android/settings.gradle +4 -0
- package/android/silero/LICENSE.md +17 -0
- package/android/silero/build.gradle +50 -0
- package/android/silero/proguard-rules.pro +24 -0
- package/android/silero/src/androidTest/assets/hello.wav +0 -0
- package/android/silero/src/androidTest/java/com/konovalov/vad/silero/VadSileroTest.kt +79 -0
- package/android/silero/src/main/assets/LICENSE +21 -0
- package/android/silero/src/main/assets/silero_vad.onnx +0 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/Vad.kt +160 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/VadSilero.kt +449 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/FrameSize.kt +15 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/Mode.kt +14 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/SampleRate.kt +12 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/utils/AudioUtils.kt +47 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/utils/TensorMap.kt +41 -0
- package/android/silero/src/test/java/com/konovalov/vad/silero/utils/AudioUtilsTest.kt +44 -0
- package/android/src/main/AndroidManifest.xml +42 -0
- package/android/src/main/assets/G2Firmware/README.md +11 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdk.kt +2325 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkAnalytics.kt +216 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDebug.kt +14 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDefaults.kt +7 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkModule.kt +1088 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/Bridge.kt +953 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/DeviceManager.kt +2528 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/DeviceStore.kt +360 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedChangelogCatalog.kt +8 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedReleaseMetadata.kt +11 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/LocalNetworkModule.kt +414 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/ObservableStore.kt +88 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/OtaManifest.kt +191 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/ReleaseChangelog.kt +61 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/ScopedNetworkReadiness.kt +17 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/audio/AudioModels.kt +144 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/camera/CameraModels.kt +486 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/connection/ConnectionModels.kt +78 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/controllers/ControllerManager.kt +158 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/controllers/R1.kt +937 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/debug/BleTraceLogger.kt +165 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/events/BluetoothEvents.kt +178 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/internal/MapParsing.kt +140 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/net/LocalIpv4.kt +57 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServer.kt +304 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/OtaServerModule.kt +120 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistry.java +108 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoUploadServer.kt +622 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/PhotoReceiverModule.kt +156 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/requests/DisplayRequests.kt +56 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/services/Foreground.kt +272 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/services/PhoneMic.kt +1195 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Ar99.java +2653 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuard.kt +49 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapper.kt +27 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1.kt +3878 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizer.kt +38 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2.kt +6428 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassification.kt +49 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwRenderer.kt +1241 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCache.kt +270 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocol.kt +291 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2Flasher.kt +411 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/GlasslyBle.java +43189 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Mach1.kt +1280 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLive.kt +10817 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLiveL2capChannel.kt +274 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisement.kt +54 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraNex.kt +2011 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Nimo.kt +2532 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/SGCManager.kt +470 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Simulated.kt +228 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/Ar99OtaManager.java +566 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaByteUtils.java +18 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCommandConstants.java +35 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCrc32Util.java +13 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaGattTransport.java +11 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaProtocol.java +92 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/speakerid/SpeakerIdEngine.kt +525 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/status/DeviceStatus.kt +669 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/status/RuntimeState.kt +201 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/status/WifiHotspotStatus.kt +189 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/streaming/StreamModels.kt +518 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/stt/STTTools.kt +391 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +518 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/stt/VadGateSpeechPolicy.kt +229 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/tts/TTSTools.kt +248 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/types/DeviceModels.kt +96 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/AES.java +106 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/AudioSessionMonitor.kt +189 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/AvifExifStripper.java +573 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BitmapJavaUtils.java +169 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleJsonCompact.java +496 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadService.java +677 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleWireProtocol.java +108 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/Constants.kt +46 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/G1Text.kt +436 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/HeifExifTagReader.java +199 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleRelayNaming.java +29 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleUploadService.java +77 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900LengthCodec.java +115 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtils.java +827 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunkReassembler.java +228 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunker.java +325 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/NexSGCUtils.kt +698 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitor.kt +348 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/SmartGlassesConnectionState.java +9 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Ar99OpusPcmDecoder.java +398 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/ByteUtilAudioPlayer.java +655 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Lc3Player.java +441 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PCMAudioPlayer.java +431 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PcmStreamPlayer.kt +328 -0
- package/android/src/main/res/values/strings.xml +4 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/BluetoothSdkExceptionTest.kt +18 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/OtaManifestDowngradeTest.kt +86 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/OtaStartResponsePolicyTest.kt +30 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/ReleaseChangelogTest.kt +13 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/ScopedNetworkReadinessTest.kt +39 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/StreamStatusEventTest.kt +29 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/camera/PhotoRequestTest.kt +141 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServerTest.kt +82 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistryTest.java +75 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/services/ForegroundServiceTypeTest.kt +69 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/Ar99AdvertisementMatcherTest.java +22 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuardTest.kt +73 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapperTest.kt +67 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/EvenRleTest.kt +63 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizerTest.kt +31 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassificationTest.kt +89 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwRendererTest.kt +344 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCacheTest.kt +200 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocolTest.kt +131 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLiveGattCharacteristicsTest.kt +39 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisementParserTest.kt +133 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/NimoProtocolTest.kt +333 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/AvifExifStripperTest.java +46 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/BinaryMessageChunkerTest.java +84 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/BleJsonCompactTest.java +319 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadServiceTest.java +107 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsEndiannessTest.java +172 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsTest.java +24 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitorTest.kt +45 -0
- package/android/src/test/resources/avif_with_exif.avif +0 -0
- package/app.plugin.js +3 -0
- package/build/BluetoothSdk.types.d.ts +1354 -0
- package/build/BluetoothSdk.types.d.ts.map +1 -0
- package/build/BluetoothSdk.types.js +41 -0
- package/build/BluetoothSdk.types.js.map +1 -0
- package/build/_internal.d.ts +17 -0
- package/build/_internal.d.ts.map +1 -0
- package/build/_internal.js +16 -0
- package/build/_internal.js.map +1 -0
- package/build/_private/BluetoothSdkModule.d.ts +172 -0
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -0
- package/build/_private/BluetoothSdkModule.js +300 -0
- package/build/_private/BluetoothSdkModule.js.map +1 -0
- package/build/_private/LocalNetworkModule.d.ts +38 -0
- package/build/_private/LocalNetworkModule.d.ts.map +1 -0
- package/build/_private/LocalNetworkModule.js +3 -0
- package/build/_private/LocalNetworkModule.js.map +1 -0
- package/build/_private/cameraRequestPayload.d.ts +4 -0
- package/build/_private/cameraRequestPayload.d.ts.map +1 -0
- package/build/_private/cameraRequestPayload.js +32 -0
- package/build/_private/cameraRequestPayload.js.map +1 -0
- package/build/_private/photoRequestPayload.d.ts +6 -0
- package/build/_private/photoRequestPayload.d.ts.map +1 -0
- package/build/_private/photoRequestPayload.js +86 -0
- package/build/_private/photoRequestPayload.js.map +1 -0
- package/build/_private/sdkOtaManifest.d.ts +11 -0
- package/build/_private/sdkOtaManifest.d.ts.map +1 -0
- package/build/_private/sdkOtaManifest.js +15 -0
- package/build/_private/sdkOtaManifest.js.map +1 -0
- package/build/changelogs.d.ts +7 -0
- package/build/changelogs.d.ts.map +1 -0
- package/build/changelogs.js +46 -0
- package/build/changelogs.js.map +1 -0
- package/build/debug.d.ts +3 -0
- package/build/debug.d.ts.map +1 -0
- package/build/debug.js +8 -0
- package/build/debug.js.map +1 -0
- package/build/generated/changelogCatalog.d.ts +9 -0
- package/build/generated/changelogCatalog.d.ts.map +1 -0
- package/build/generated/changelogCatalog.js +12 -0
- package/build/generated/changelogCatalog.js.map +1 -0
- package/build/generated/releaseMetadata.d.ts +12 -0
- package/build/generated/releaseMetadata.d.ts.map +1 -0
- package/build/generated/releaseMetadata.js +10 -0
- package/build/generated/releaseMetadata.js.map +1 -0
- package/build/index.d.ts +6 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +171 -0
- package/build/index.js.map +1 -0
- package/build/ota-server/OtaServer.types.d.ts +14 -0
- package/build/ota-server/OtaServer.types.d.ts.map +1 -0
- package/build/ota-server/OtaServer.types.js +2 -0
- package/build/ota-server/OtaServer.types.js.map +1 -0
- package/build/ota-server/OtaServerModule.d.ts +21 -0
- package/build/ota-server/OtaServerModule.d.ts.map +1 -0
- package/build/ota-server/OtaServerModule.js +3 -0
- package/build/ota-server/OtaServerModule.js.map +1 -0
- package/build/ota-server/OtaServerModule.web.d.ts +10 -0
- package/build/ota-server/OtaServerModule.web.d.ts.map +1 -0
- package/build/ota-server/OtaServerModule.web.js +12 -0
- package/build/ota-server/OtaServerModule.web.js.map +1 -0
- package/build/ota-server/index.d.ts +3 -0
- package/build/ota-server/index.d.ts.map +1 -0
- package/build/ota-server/index.js +3 -0
- package/build/ota-server/index.js.map +1 -0
- package/build/ota-transport/index.d.ts +67 -0
- package/build/ota-transport/index.d.ts.map +1 -0
- package/build/ota-transport/index.js +58 -0
- package/build/ota-transport/index.js.map +1 -0
- package/build/photo-receiver/PhotoReceiver.types.d.ts +18 -0
- package/build/photo-receiver/PhotoReceiver.types.d.ts.map +1 -0
- package/build/photo-receiver/PhotoReceiver.types.js +2 -0
- package/build/photo-receiver/PhotoReceiver.types.js.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.d.ts +10 -0
- package/build/photo-receiver/PhotoReceiverModule.d.ts.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.js +3 -0
- package/build/photo-receiver/PhotoReceiverModule.js.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.web.d.ts +10 -0
- package/build/photo-receiver/PhotoReceiverModule.web.d.ts.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.web.js +12 -0
- package/build/photo-receiver/PhotoReceiverModule.web.js.map +1 -0
- package/build/photo-receiver/index.d.ts +3 -0
- package/build/photo-receiver/index.d.ts.map +1 -0
- package/build/photo-receiver/index.js +3 -0
- package/build/photo-receiver/index.js.map +1 -0
- package/build/react/index.d.ts +5 -0
- package/build/react/index.d.ts.map +1 -0
- package/build/react/index.js +4 -0
- package/build/react/index.js.map +1 -0
- package/build/react/useBluetooth.d.ts +100 -0
- package/build/react/useBluetooth.d.ts.map +1 -0
- package/build/react/useBluetooth.js +167 -0
- package/build/react/useBluetooth.js.map +1 -0
- package/build/react/useBluetoothEvent.d.ts +6 -0
- package/build/react/useBluetoothEvent.d.ts.map +1 -0
- package/build/react/useBluetoothEvent.js +21 -0
- package/build/react/useBluetoothEvent.js.map +1 -0
- package/build/react/useBluetoothScan.d.ts +22 -0
- package/build/react/useBluetoothScan.d.ts.map +1 -0
- package/build/react/useBluetoothScan.js +135 -0
- package/build/react/useBluetoothScan.js.map +1 -0
- package/build/react/useBluetoothStatus.d.ts +16 -0
- package/build/react/useBluetoothStatus.d.ts.map +1 -0
- package/build/react/useBluetoothStatus.js +137 -0
- package/build/react/useBluetoothStatus.js.map +1 -0
- package/build/react/useGlassesConnection.d.ts +29 -0
- package/build/react/useGlassesConnection.d.ts.map +1 -0
- package/build/react/useGlassesConnection.js +153 -0
- package/build/react/useGlassesConnection.js.map +1 -0
- package/build/types/index.d.ts +3 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/index.js +2 -0
- package/build/types/index.js.map +1 -0
- package/expo-module.config.json +14 -0
- package/ios/BackgroundOtaArtifactDownloader.swift +125 -0
- package/ios/BluetoothSdkModule.swift +1034 -0
- package/ios/GlasslyBluetoothSDK.podspec +106 -0
- package/ios/LocalIPv4.swift +150 -0
- package/ios/LocalOtaServer.swift +309 -0
- package/ios/LocalPhotoUploadServer.swift +754 -0
- package/ios/OtaServerModule.swift +147 -0
- package/ios/Packages/CoreObjC/CoreObjC.xcodeproj/project.pbxproj +213 -0
- package/ios/Packages/CoreObjC/PcmConverter.h +22 -0
- package/ios/Packages/CoreObjC/PcmConverter.m +266 -0
- package/ios/Packages/CoreObjC/attdet.c +92 -0
- package/ios/Packages/CoreObjC/attdet.h +44 -0
- package/ios/Packages/CoreObjC/bits.c +375 -0
- package/ios/Packages/CoreObjC/bits.h +315 -0
- package/ios/Packages/CoreObjC/bwdet.c +129 -0
- package/ios/Packages/CoreObjC/bwdet.h +69 -0
- package/ios/Packages/CoreObjC/common.h +151 -0
- package/ios/Packages/CoreObjC/energy.c +70 -0
- package/ios/Packages/CoreObjC/energy.h +43 -0
- package/ios/Packages/CoreObjC/fastmath.h +158 -0
- package/ios/Packages/CoreObjC/include/PcmConverter.h +22 -0
- package/ios/Packages/CoreObjC/lc3.c +704 -0
- package/ios/Packages/CoreObjC/lc3.h +313 -0
- package/ios/Packages/CoreObjC/lc3_cpp.h +283 -0
- package/ios/Packages/CoreObjC/lc3_private.h +163 -0
- package/ios/Packages/CoreObjC/ltpf.c +905 -0
- package/ios/Packages/CoreObjC/ltpf.h +111 -0
- package/ios/Packages/CoreObjC/ltpf_arm.h +506 -0
- package/ios/Packages/CoreObjC/ltpf_neon.h +281 -0
- package/ios/Packages/CoreObjC/makefile.mk +35 -0
- package/ios/Packages/CoreObjC/mdct.c +469 -0
- package/ios/Packages/CoreObjC/mdct.h +57 -0
- package/ios/Packages/CoreObjC/mdct_neon.h +296 -0
- package/ios/Packages/CoreObjC/meson.build +61 -0
- package/ios/Packages/CoreObjC/plc.c +61 -0
- package/ios/Packages/CoreObjC/plc.h +57 -0
- package/ios/Packages/CoreObjC/rnnoise.h +114 -0
- package/ios/Packages/CoreObjC/sns.c +880 -0
- package/ios/Packages/CoreObjC/sns.h +103 -0
- package/ios/Packages/CoreObjC/spec.c +907 -0
- package/ios/Packages/CoreObjC/spec.h +119 -0
- package/ios/Packages/CoreObjC/tables.c +3457 -0
- package/ios/Packages/CoreObjC/tables.h +94 -0
- package/ios/Packages/CoreObjC/tns.c +457 -0
- package/ios/Packages/CoreObjC/tns.h +99 -0
- package/ios/Packages/SherpaOnnx/Model/joiner.onnx +0 -0
- package/ios/Packages/SherpaOnnx/Model/tokens.txt +502 -0
- package/ios/Packages/SherpaOnnx/SherpaOnnx.swift +2383 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Info.plist +48 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/libsherpa-onnx.a +0 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/libsherpa-onnx.a +0 -0
- package/ios/Packages/libbz2/module.modulemap +5 -0
- package/ios/Packages/libbz2/shim.h +1 -0
- package/ios/PhotoReceiverModule.swift +129 -0
- package/ios/Source/BluetoothSDK.swift +2303 -0
- package/ios/Source/BluetoothSDKDebug.swift +12 -0
- package/ios/Source/BluetoothSdkDefaults.swift +29 -0
- package/ios/Source/Bridge.swift +708 -0
- package/ios/Source/Bridging-Header.h +16 -0
- package/ios/Source/DeviceManager.swift +2109 -0
- package/ios/Source/DeviceStore.swift +336 -0
- package/ios/Source/GeneratedChangelogCatalog.swift +7 -0
- package/ios/Source/GeneratedReleaseMetadata.swift +11 -0
- package/ios/Source/ObservableStore.swift +118 -0
- package/ios/Source/OtaManifest.swift +211 -0
- package/ios/Source/PrivacyInfo.xcprivacy +23 -0
- package/ios/Source/ReleaseChangelog.swift +65 -0
- package/ios/Source/Resources/G2Firmware/README.md +10 -0
- package/ios/Source/audio/AudioModels.swift +178 -0
- package/ios/Source/audio/PcmStreamPlayer.swift +410 -0
- package/ios/Source/camera/CameraModels.swift +866 -0
- package/ios/Source/connection/ScanSession.swift +27 -0
- package/ios/Source/controllers/ControllerManager.swift +184 -0
- package/ios/Source/controllers/R1.swift +829 -0
- package/ios/Source/errors/BluetoothSdkError.swift +19 -0
- package/ios/Source/events/BluetoothEvents.swift +342 -0
- package/ios/Source/internal/BleTraceLogger.swift +192 -0
- package/ios/Source/internal/BluetoothAvailability.swift +78 -0
- package/ios/Source/internal/BluetoothSdkAnalytics.swift +199 -0
- package/ios/Source/internal/ValueParsing.swift +99 -0
- package/ios/Source/requests/DisplayRequests.swift +82 -0
- package/ios/Source/services/PhoneMic.swift +662 -0
- package/ios/Source/sgcs/Ar99.swift +2451 -0
- package/ios/Source/sgcs/Frame.swift +649 -0
- package/ios/Source/sgcs/G1.swift +2554 -0
- package/ios/Source/sgcs/G2.swift +6887 -0
- package/ios/Source/sgcs/G2CfwClassification.swift +43 -0
- package/ios/Source/sgcs/G2CfwRenderer.swift +1279 -0
- package/ios/Source/sgcs/G2CfwTextureCache.swift +233 -0
- package/ios/Source/sgcs/G2FlashProtocol.swift +312 -0
- package/ios/Source/sgcs/G2Flasher.swift +773 -0
- package/ios/Source/sgcs/Mach1.swift +541 -0
- package/ios/Source/sgcs/MentraLive.swift +7011 -0
- package/ios/Source/sgcs/MentraLiveL2capChannel.swift +183 -0
- package/ios/Source/sgcs/MentraLivePairingAdvertisement.swift +64 -0
- package/ios/Source/sgcs/MentraNex.swift +3221 -0
- package/ios/Source/sgcs/Nimo.swift +1886 -0
- package/ios/Source/sgcs/SGCManager.swift +608 -0
- package/ios/Source/sgcs/Simulated.swift +274 -0
- package/ios/Source/sgcs/ar99/ota/Ar99OtaManager.swift +637 -0
- package/ios/Source/sgcs/glassly_ble.pb.swift +4354 -0
- package/ios/Source/speakerid/SpeakerIdEngine.swift +573 -0
- package/ios/Source/status/DeviceStatus.swift +981 -0
- package/ios/Source/status/RuntimeState.swift +359 -0
- package/ios/Source/status/WifiHotspotStatus.swift +345 -0
- package/ios/Source/streaming/StreamModels.swift +693 -0
- package/ios/Source/stt/STTTools.swift +191 -0
- package/ios/Source/stt/SherpaOnnxTranscriber.swift +466 -0
- package/ios/Source/tts/TTSTools.swift +171 -0
- package/ios/Source/types/DeviceModels.swift +177 -0
- package/ios/Source/utils/AudioSessionMonitor.swift +283 -0
- package/ios/Source/utils/BinaryCodec.swift +61 -0
- package/ios/Source/utils/BleJsonCompact.swift +405 -0
- package/ios/Source/utils/BleWireProtocol.swift +92 -0
- package/ios/Source/utils/Constants.swift +78 -0
- package/ios/Source/utils/Enums.swift +95 -0
- package/ios/Source/utils/G1Text.swift +2096 -0
- package/ios/Source/utils/JSCExperiment.swift +241 -0
- package/ios/Source/utils/MemoryMonitor.swift +44 -0
- package/ios/Source/utils/MessageChunkReassembler.swift +190 -0
- package/ios/Source/utils/MessageChunker.swift +294 -0
- package/ios/Source/utils/Models.swift +135 -0
- package/ios/Source/utils/PhoneAudioMonitor.swift +230 -0
- package/ios/Source/utils/TarBz2Extractor.swift +257 -0
- package/ios/Tests/BluetoothSDKTests/G2CfwClassificationTests.swift +78 -0
- package/ios/Tests/BluetoothSDKTests/G2CfwRendererTests.swift +372 -0
- package/ios/Tests/BluetoothSDKTests/G2CfwTextureCacheTests.swift +162 -0
- package/ios/Tests/BluetoothSDKTests/G2FlashProtocolTests.swift +182 -0
- package/ios/Tests/MentraLivePairingAdvertisementTests.swift +160 -0
- package/ios/Tests/ReleaseChangelogTests.swift +13 -0
- package/package.json +129 -0
- package/plugin/build/index.d.ts +10 -0
- package/plugin/build/index.js +12 -0
- package/plugin/build/withAndroid.d.ts +3 -0
- package/plugin/build/withAndroid.js +190 -0
- package/plugin/build/withIos.d.ts +5 -0
- package/plugin/build/withIos.js +108 -0
- package/scripts/inject-ios-sdk-version.mjs +65 -0
- package/scripts/public-ota-api.test.mjs +37 -0
- package/scripts/verify-release-package.mjs +45 -0
- package/scripts/write-release-metadata.mjs +152 -0
- package/scripts/write-release-metadata.test.mjs +37 -0
- package/src/BluetoothSdk.types.ts +1623 -0
- package/src/_internal.ts +16 -0
- package/src/_private/BluetoothSdkModule.ts +684 -0
- package/src/_private/LocalNetworkModule.ts +50 -0
- package/src/_private/cameraRequestPayload.ts +34 -0
- package/src/_private/photoRequestPayload.ts +90 -0
- package/src/_private/sdkOtaManifest.ts +18 -0
- package/src/changelogs.ts +46 -0
- package/src/debug.ts +9 -0
- package/src/generated/changelogCatalog.ts +13 -0
- package/src/generated/releaseMetadata.ts +20 -0
- package/src/index.ts +321 -0
- package/src/ota-server/OtaServer.types.ts +10 -0
- package/src/ota-server/OtaServerModule.ts +23 -0
- package/src/ota-server/OtaServerModule.web.ts +17 -0
- package/src/ota-server/index.ts +2 -0
- package/src/ota-transport/index.ts +116 -0
- package/src/photo-receiver/PhotoReceiver.types.ts +20 -0
- package/src/photo-receiver/PhotoReceiverModule.ts +11 -0
- package/src/photo-receiver/PhotoReceiverModule.web.ts +17 -0
- package/src/photo-receiver/index.ts +2 -0
- package/src/react/index.ts +21 -0
- package/src/react/useBluetooth.ts +309 -0
- package/src/react/useBluetoothEvent.ts +35 -0
- package/src/react/useBluetoothScan.ts +173 -0
- package/src/react/useBluetoothStatus.ts +180 -0
- package/src/react/useGlassesConnection.ts +202 -0
- package/src/types/index.ts +12 -0
package/README.md
ADDED
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
# @glassly/bluetooth-sdk
|
|
2
|
+
|
|
3
|
+
React Native and Expo SDK for connecting mobile apps directly to supported Glassly smart glasses over Bluetooth.
|
|
4
|
+
|
|
5
|
+
The package includes:
|
|
6
|
+
|
|
7
|
+
- A React Native / Expo module API exposed as `BluetoothSdk`.
|
|
8
|
+
- React hooks under `@glassly/bluetooth-sdk/react` for common scan,
|
|
9
|
+
connection, status, and event lifecycles.
|
|
10
|
+
- Native Android code published as `com.glassly:bluetooth-sdk`.
|
|
11
|
+
- Native iOS code available as the `BluetoothSDK` Swift package.
|
|
12
|
+
- An Expo config plugin that wires the native dependencies into generated Android and iOS projects.
|
|
13
|
+
|
|
14
|
+
Use a development build or production native build. Expo Go cannot load this package because the SDK contains native code.
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
- React Native `0.72+`.
|
|
19
|
+
- Expo `49+` when using Expo.
|
|
20
|
+
- Android min SDK `28+`.
|
|
21
|
+
- iOS deployment target `15.1+`.
|
|
22
|
+
- A physical phone for real Bluetooth testing.
|
|
23
|
+
- Bluetooth permissions, plus Android location permission where BLE scanning requires it.
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
bun add @glassly/bluetooth-sdk
|
|
29
|
+
bunx expo install expo-build-properties
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
For Expo apps, add the plugin to `app.json` or `app.config.ts`:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"expo": {
|
|
37
|
+
"plugins": [
|
|
38
|
+
[
|
|
39
|
+
"@glassly/bluetooth-sdk",
|
|
40
|
+
{
|
|
41
|
+
"node": true
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
[
|
|
45
|
+
"expo-build-properties",
|
|
46
|
+
{
|
|
47
|
+
"android": {
|
|
48
|
+
"minSdkVersion": 28,
|
|
49
|
+
"packagingOptions": {
|
|
50
|
+
"pickFirst": [
|
|
51
|
+
"**/libc++_shared.so",
|
|
52
|
+
"**/libonnxruntime.so",
|
|
53
|
+
"**/libonnxruntime4j_jni.so"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then regenerate native projects and run a development build:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
bunx expo prebuild
|
|
68
|
+
bunx expo run:ios
|
|
69
|
+
# or
|
|
70
|
+
bunx expo run:android
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Permissions
|
|
74
|
+
|
|
75
|
+
Android apps should request the permissions required by the features they use:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"android": {
|
|
80
|
+
"permissions": [
|
|
81
|
+
"android.permission.BLUETOOTH",
|
|
82
|
+
"android.permission.BLUETOOTH_ADMIN",
|
|
83
|
+
"android.permission.BLUETOOTH_SCAN",
|
|
84
|
+
"android.permission.BLUETOOTH_CONNECT",
|
|
85
|
+
"android.permission.ACCESS_FINE_LOCATION",
|
|
86
|
+
"android.permission.RECORD_AUDIO",
|
|
87
|
+
"android.permission.INTERNET",
|
|
88
|
+
"android.permission.POST_NOTIFICATIONS"
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Some Android 12+ devices require Location permission and Location services before BLE scan callbacks are delivered.
|
|
95
|
+
|
|
96
|
+
iOS apps should include usage descriptions:
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"ios": {
|
|
101
|
+
"infoPlist": {
|
|
102
|
+
"NSBluetoothAlwaysUsageDescription": "This app connects to your smart glasses over Bluetooth.",
|
|
103
|
+
"NSMicrophoneUsageDescription": "This app uses the microphone when you enable audio features.",
|
|
104
|
+
"NSLocalNetworkUsageDescription": "This app connects to local photo and streaming helpers during development."
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Minimal Usage
|
|
111
|
+
|
|
112
|
+
Use `scan()` when your app needs to show a picker. It calls `onResults` every time the discovered list changes, then resolves with the final list after the timeout.
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import BluetoothSdk, {
|
|
116
|
+
DeviceModels,
|
|
117
|
+
} from '@glassly/bluetooth-sdk'
|
|
118
|
+
|
|
119
|
+
const devices = await BluetoothSdk.scan(DeviceModels.MentraLive, {
|
|
120
|
+
timeoutMs: 10_000,
|
|
121
|
+
onResults: (nextDevices) => {
|
|
122
|
+
console.log('Nearby glasses:', nextDevices)
|
|
123
|
+
},
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
const device = await chooseDevice(devices)
|
|
127
|
+
if (!device) {
|
|
128
|
+
throw new Error('No Mentra Live glasses selected')
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
await BluetoothSdk.connect(device)
|
|
132
|
+
const versionInfo = await BluetoothSdk.requestVersionInfo()
|
|
133
|
+
console.log(versionInfo.buildNumber)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
In multi-device environments, present an explicit picker instead of
|
|
137
|
+
auto-connecting to the first nearby device.
|
|
138
|
+
|
|
139
|
+
Mentra Live does not have a display. Use display commands only after gating by
|
|
140
|
+
model capability.
|
|
141
|
+
|
|
142
|
+
Use `Device.id` as the stable app-facing key for scan rows, selected devices,
|
|
143
|
+
and persisted default devices. Do not parse it for model, name, or address
|
|
144
|
+
information; use the typed `model`, `name`, `address`, and `rssi` fields
|
|
145
|
+
instead. Android commonly uses a Bluetooth address when available, iOS commonly
|
|
146
|
+
uses a CoreBluetooth identifier when available, and the SDK falls back to
|
|
147
|
+
`model:name` when no platform identifier is available.
|
|
148
|
+
|
|
149
|
+
`Device.rssi` is optional. A device can appear in scan results before the
|
|
150
|
+
platform reports RSSI, so picker UI should handle `undefined` and avoid
|
|
151
|
+
reordering rows just because RSSI metadata arrives later.
|
|
152
|
+
|
|
153
|
+
## Glassly SDK Usage Analytics
|
|
154
|
+
|
|
155
|
+
The SDK sends three usage events to Glassly's PostHog project by default so
|
|
156
|
+
Glassly can understand SDK adoption, successful glasses connections, and
|
|
157
|
+
enterprise device deployments:
|
|
158
|
+
|
|
159
|
+
- `bluetooth_sdk_started`: sent once per app runtime after the native SDK starts.
|
|
160
|
+
- `bluetooth_sdk_glasses_connected`: sent when SDK status transitions from not connected to connected.
|
|
161
|
+
- `bluetooth_sdk_glasses_identified`: sent once per connection after the SDK receives a valid manufacturing serial from the glasses. This fires for every supported model that reports a serial. G1 and Ar99 decode the serial from the glasses' BLE advertisement. Mentra Live reports the product serial provisioned by its Android firmware through `asg_client`.
|
|
162
|
+
|
|
163
|
+
Analytics delivery is fire-and-forget: events are submitted asynchronously, do
|
|
164
|
+
not block Bluetooth SDK behavior, and are not retried if delivery fails.
|
|
165
|
+
|
|
166
|
+
React Native / Expo apps can disable these events before SDK startup through
|
|
167
|
+
the config plugin:
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"expo": {
|
|
172
|
+
"plugins": [
|
|
173
|
+
[
|
|
174
|
+
"@glassly/bluetooth-sdk",
|
|
175
|
+
{
|
|
176
|
+
"analytics": false
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Native Android apps can pass `BluetoothSdkAnalyticsConfig.disabled()` in
|
|
185
|
+
`BluetoothSdkConfig` or add
|
|
186
|
+
`com.glassly.bluetoothsdk.analytics.disabled=true` as application metadata.
|
|
187
|
+
Native iOS apps can pass `.disabled` in `BluetoothSDKConfiguration` or set
|
|
188
|
+
`BluetoothSdkAnalyticsDisabled` to `true` in `Info.plist`.
|
|
189
|
+
|
|
190
|
+
Glassly's PostHog project API key is embedded in the SDK as a public analytics
|
|
191
|
+
write token, not a private PostHog personal API key. Apps do not configure the
|
|
192
|
+
analytics destination; these SDK usage events are always sent to Glassly's
|
|
193
|
+
PostHog project unless analytics are disabled.
|
|
194
|
+
|
|
195
|
+
Captured properties include `event_source`, `sdk_platform`, `sdk_surface`,
|
|
196
|
+
`sdk_version`, `app_identifier` (the Android package or iOS bundle identifier),
|
|
197
|
+
the platform-specific `app_package` or `app_bundle_identifier`, OS
|
|
198
|
+
platform/version, and `event_kind`. Connection events also include
|
|
199
|
+
`fully_booted` and a glasses model value when known. The identification event
|
|
200
|
+
intentionally includes the glasses manufacturing serial as `glasses_device_id`,
|
|
201
|
+
with `glasses_device_id_type=manufacturing_serial`, so Glassly can correlate
|
|
202
|
+
fleet deployments across supported models. This serial identifies the glasses
|
|
203
|
+
hardware, not the user or the host phone. Its source depends on the model:
|
|
204
|
+
Mentra Live reports the serial provisioned in BES NV storage, while G1 and Ar99
|
|
205
|
+
decode it from the glasses' BLE advertisement / manufacturer data.
|
|
206
|
+
|
|
207
|
+
Apart from that glasses serial, the SDK does not upload BLE MAC addresses,
|
|
208
|
+
CoreBluetooth identifiers, the host phone's Android device serial, Bluetooth
|
|
209
|
+
device names, user ids, tokens, Wi-Fi credentials, microphone data, photos, or
|
|
210
|
+
transcripts. PostHog receives a locally generated anonymous SDK install id as
|
|
211
|
+
`distinct_id`, and events include `$process_person_profile: false`.
|
|
212
|
+
|
|
213
|
+
## React Hooks
|
|
214
|
+
|
|
215
|
+
React Native apps can import optional lifecycle helpers from the `react`
|
|
216
|
+
subpath for common lifecycle plumbing. Use the root `BluetoothSdk` object for
|
|
217
|
+
commands such as `requestPhoto()`, `startStream()`, and `setMicState()`.
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import {Button, Text, View} from 'react-native'
|
|
221
|
+
import {DeviceModels} from '@glassly/bluetooth-sdk'
|
|
222
|
+
import {useBluetoothEvent, useBluetooth} from '@glassly/bluetooth-sdk/react'
|
|
223
|
+
|
|
224
|
+
export function DeviceScreen() {
|
|
225
|
+
const glassly = useBluetooth({
|
|
226
|
+
defaultModel: DeviceModels.MentraLive,
|
|
227
|
+
scanTimeoutMs: 10_000,
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
useBluetoothEvent('button_press', (event) => {
|
|
231
|
+
console.log('Glasses button:', event.buttonId, event.pressType)
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<View>
|
|
236
|
+
<Text>{glassly.glasses.connected ? 'Connected' : 'Disconnected'}</Text>
|
|
237
|
+
<Button disabled={glassly.busy} title="Scan" onPress={() => glassly.scan.start()} />
|
|
238
|
+
{glassly.scan.devices.map((device) => (
|
|
239
|
+
<Button key={device.id} title={device.name} onPress={() => glassly.connect(device)} />
|
|
240
|
+
))}
|
|
241
|
+
<Button disabled={!glassly.glasses.connected} title="Disconnect" onPress={glassly.disconnect} />
|
|
242
|
+
</View>
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The hooks do not request Android permissions or choose a persistence package for
|
|
248
|
+
you. Ask for permissions in your app before calling scan/connect actions, and
|
|
249
|
+
pass a `defaultDeviceStorage` adapter to `useBluetooth` if you want a
|
|
250
|
+
default device to survive app restarts.
|
|
251
|
+
|
|
252
|
+
Use `useBluetooth()` as the React status API for connection, battery,
|
|
253
|
+
Wi-Fi, hotspot, scan, and SDK runtime state.
|
|
254
|
+
|
|
255
|
+
The React hook exposes `glasses.connection` as a discriminated union:
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
type GlassesConnectionStatus =
|
|
259
|
+
| {state: 'disconnected'}
|
|
260
|
+
| {state: 'scanning'}
|
|
261
|
+
| {state: 'connecting'}
|
|
262
|
+
| {state: 'bonding'}
|
|
263
|
+
| {state: 'connected'; fullyBooted: boolean}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Use `connection.state` for link progress. `fullyBooted` only exists when `state === 'connected'`. Android and iOS native APIs also keep `connectionState`, `connected`, and `fullyBooted` as native status properties for Kotlin and Swift callers.
|
|
267
|
+
|
|
268
|
+
## Default Device
|
|
269
|
+
|
|
270
|
+
`connectDefault()` connects to the default glasses target stored in SDK state. Apps that want this target to survive app restarts should persist the scanned `Device` in app storage and restore it with `setDefaultDevice()` before calling `connectDefault()`.
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
const savedDevice = await loadSavedDeviceFromYourAppStorage()
|
|
274
|
+
if (savedDevice) {
|
|
275
|
+
await BluetoothSdk.setDefaultDevice(savedDevice)
|
|
276
|
+
await BluetoothSdk.connectDefault()
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const discoveredDevice = await scanAndChooseDevice()
|
|
280
|
+
await BluetoothSdk.connect(discoveredDevice)
|
|
281
|
+
await saveDeviceToYourAppStorage(discoveredDevice)
|
|
282
|
+
|
|
283
|
+
await BluetoothSdk.clearDefaultDevice()
|
|
284
|
+
await saveDeviceToYourAppStorage(null)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Common Commands
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
await BluetoothSdk.clearDisplay()
|
|
291
|
+
await BluetoothSdk.showDashboard()
|
|
292
|
+
await BluetoothSdk.setDashboardPosition(4, 2)
|
|
293
|
+
|
|
294
|
+
const networks = await BluetoothSdk.requestWifiScan()
|
|
295
|
+
console.log(networks.map((network) => network.ssid))
|
|
296
|
+
|
|
297
|
+
const wifiStatus = await BluetoothSdk.sendWifiCredentials('Office WiFi', 'secret')
|
|
298
|
+
console.log(wifiStatus.state)
|
|
299
|
+
|
|
300
|
+
const forgetStatus = await BluetoothSdk.forgetWifiNetwork('Office WiFi')
|
|
301
|
+
console.log(forgetStatus.state)
|
|
302
|
+
|
|
303
|
+
const hotspotStatus = await BluetoothSdk.setHotspotState(true)
|
|
304
|
+
console.log(hotspotStatus.state)
|
|
305
|
+
|
|
306
|
+
await BluetoothSdk.setWifiAdbState(true) // Mentra Live Wi-Fi ADB (wireless debugging)
|
|
307
|
+
|
|
308
|
+
const galleryAck = await BluetoothSdk.setGalleryModeEnabled(true)
|
|
309
|
+
console.log(galleryAck.status)
|
|
310
|
+
await BluetoothSdk.setGalleryModeEnabled(false)
|
|
311
|
+
|
|
312
|
+
await BluetoothSdk.setPreferredMic('auto')
|
|
313
|
+
await BluetoothSdk.setMicState(true)
|
|
314
|
+
await BluetoothSdk.setOwnAppAudioPlaying(false)
|
|
315
|
+
|
|
316
|
+
const ledAck = await BluetoothSdk.rgbLedControl(
|
|
317
|
+
`led-${Date.now()}`,
|
|
318
|
+
'com.example.app',
|
|
319
|
+
'on',
|
|
320
|
+
'green',
|
|
321
|
+
500,
|
|
322
|
+
500,
|
|
323
|
+
3,
|
|
324
|
+
)
|
|
325
|
+
console.log(ledAck.state)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Settings commands that return `SettingsAckSuccessEvent` reject when the ASG reports an error ack. The SDK updates its local settings store only after that ASG ack resolves successfully, so observed SDK state reflects the acknowledged glasses state rather than a queued request. Raw `settings_ack` listener events still use `SettingsAckEvent` because they can include both success and failure statuses. `rgbLedControl(...)` resolves from a successful ASG `rgb_led_control_response` and rejects when the ASG reports `state: "error"`; raw `settings_ack` and `rgb_led_control_response` events remain available through listeners.
|
|
329
|
+
|
|
330
|
+
WiFi, hotspot, and version-info commands resolve from the ASG response path, not local dispatch:
|
|
331
|
+
`requestWifiScan()` resolves from the ASG `wifi_scan_result` completion response with the updated scan list, including `[]` when no networks are found. Intermediate `wifi_scan_result` events can arrive with `scanComplete: false` while the glasses stream discovered networks; the final event uses `scanComplete: true`. If older glasses stream non-empty scan results but never send the completion event, the request resolves with the accumulated scan list when the request times out. `sendWifiCredentials()` resolves when the requested SSID is connected, `forgetWifiNetwork()` resolves when that SSID is no longer connected, `setHotspotState()` resolves when the requested hotspot state is reported, and `requestVersionInfo()` resolves from the ASG `version_info` response instead of local store changes.
|
|
332
|
+
|
|
333
|
+
The SDK automatically sends the phone wall clock once shortly after a glasses connection becomes ready. It waits for the initial command burst to drain before timestamping the command so startup queue delay does not become clock skew. The once-per-connection guard resets after disconnect, so every successful reconnect synchronizes again. The SDK does not periodically verify or correct clock skew during a long-lived connection; apps that require periodic reconciliation can compare `requestVersionInfo().systemTimeMs` with the phone clock.
|
|
334
|
+
|
|
335
|
+
React Native narrows returned values to success shapes where the raw listener event can also report errors:
|
|
336
|
+
|
|
337
|
+
| API | Returned Value After `await` | Error Path |
|
|
338
|
+
| --- | --- | --- |
|
|
339
|
+
| `requestPhoto(...)` | Terminal `PhotoSuccessResponseEvent` with `state: "success"` after capture and delivery finish. `uploadUrl` is always present; webhook JSON metadata such as `photoUrl`, `statusUrl`, `contentType`, or `fileSizeBytes` is included when the receiver returns it. | Rejects when raw `photo_response.state === "error"`, the SDK cannot send the command, or the terminal photo response times out. |
|
|
340
|
+
| `startVideoRecording(...)` | `VideoRecordingStartedStatusEvent` with `success: true` and `status: "recording_started"`. | Rejects on `success: false` statuses such as `already_recording`, send failure, or timeout. |
|
|
341
|
+
| `stopVideoRecording(...)` | `VideoRecordingStoppedStatusEvent` with `success: true` and `status: "recording_stopped"`. When a webhook URL is supplied, resolves after the video upload succeeds. | Rejects on `success: false` statuses such as `not_recording`, webhook upload failure, send failure, or timeout. |
|
|
342
|
+
| `queryVideoRecordingStatus(requestId)` | `VideoRecordingStatusEvent` with the current `recording` state and elapsed `duration_ms` when available. | Rejects when disconnected, another video command uses the same request ID, or the response times out. |
|
|
343
|
+
| `rgbLedControl(...)` | `RgbLedControlSuccessResponseEvent` with `state: "success"`. | Rejects when raw `rgb_led_control_response.state === "error"` or the response times out. |
|
|
344
|
+
| `checkForOtaUpdate()` | `boolean`, true when the configured OTA manifest has an ASG APK, MTK, or BES update for the connected glasses; false only when the manifest was checked successfully and no update is available. | Rejects when the glasses are disconnected, version info is unavailable, the manifest cannot be fetched, or the manifest response is invalid/missing required ASG app version fields. |
|
|
345
|
+
|
|
346
|
+
Android and iOS async APIs use `BluetoothSdkException` / `BluetoothSdkError` for the same error paths. Their returned event structs are the successful response in normal `try`/`await` code, while raw listener/delegate events still include both success and error payloads.
|
|
347
|
+
|
|
348
|
+
`setMicState(true)` defaults to continuous microphone PCM from the glasses. The SDK does not apply phone-side Voice Activity Detection gating to microphone audio events. Glasses-side Voice Activity Detection is disabled by default for public SDK consumers; use `setVoiceActivityDetectionEnabled(true)` when you want supported glasses to gate microphone audio and emit live speaking status. `voice_activity_detection_status` reports whether glasses-side Voice Activity Detection is enabled, and `speaking_status` reports speaking/not-speaking when supported. Microphone events include the latest `voiceActivityDetectionEnabled` value.
|
|
349
|
+
|
|
350
|
+
## OTA Updates
|
|
351
|
+
|
|
352
|
+
React Native apps should use `MentraLiveOtaFlow` or `useMentraLiveOta` from
|
|
353
|
+
`@glassly/engine/ota`. They provide the same tested Wi-Fi/hotspot,
|
|
354
|
+
APK/MTK/BES, restart, retry, and verification flow as the Glassly App. See
|
|
355
|
+
[Update Mentra Live](https://docs.glassly.com/mentra-live/software-update).
|
|
356
|
+
|
|
357
|
+
The Bluetooth SDK exposes the lower-level commands and transport capabilities
|
|
358
|
+
that Glassly Engine and native apps build on. They are not a replacement for the
|
|
359
|
+
Engine coordinator:
|
|
360
|
+
|
|
361
|
+
- `setOtaVersionUrl(url)` selects the manifest used by subsequent checks and installs. Use this
|
|
362
|
+
for a customer-controlled internal update server.
|
|
363
|
+
- `getOtaVersionUrl()` returns the selected manifest, or the SDK-version-pinned Glassly manifest
|
|
364
|
+
when no override was supplied.
|
|
365
|
+
- `checkForOtaUpdate()` fetches the configured manifest and resolves with `true` when an ASG APK, MTK, or BES update is available.
|
|
366
|
+
- `startOtaUpdate()` sends `ota_start` with the same configured manifest URL and resolves with the ASG start ack after your app presents the update and the user accepts it.
|
|
367
|
+
- `queryOtaStatus()` returns the correlated status for the active session.
|
|
368
|
+
- `@glassly/bluetooth-sdk/ota-transport` exposes scoped hotspot networking and
|
|
369
|
+
the local OTA artifact server without exposing native module internals.
|
|
370
|
+
|
|
371
|
+
Release CI embeds an immutable manifest URL and checksum into every published
|
|
372
|
+
SDK distribution. The completed coordinated release record correlates the SDK
|
|
373
|
+
package with its exact manifest and OTA bundle. A completed release is available at
|
|
374
|
+
`https://github.com/Glassly-Community/GlasslyOS/releases/tag/glassly-v<releaseIdentity>`
|
|
375
|
+
and contains `glassly-release-<releaseIdentity>.json`, which records the exact
|
|
376
|
+
package coordinates, asset URLs, sizes, checksums, and build provenance.
|
|
377
|
+
|
|
378
|
+
Pre-wall-clock ASG builds that ignore `ota_start.ota_version_url` are checked
|
|
379
|
+
against the URL they advertise, or the production default if they do not
|
|
380
|
+
advertise one, so the app does not prompt for an update the glasses cannot
|
|
381
|
+
install.
|
|
382
|
+
|
|
383
|
+
Use these primitives directly only when implementing the documented native
|
|
384
|
+
Android/iOS OTA contract or infrastructure beneath a coordinator. React Native
|
|
385
|
+
application pages should render Glassly Engine's semantic controller state
|
|
386
|
+
instead of sequencing raw events.
|
|
387
|
+
|
|
388
|
+
Each coordinated prerelease publishes a portable OTA bundle. Stable releases
|
|
389
|
+
promote the exact beta-tested OTA bytes, so always resolve the bundle coordinate
|
|
390
|
+
and URL from `glassly-release-<releaseIdentity>.json` rather than constructing a
|
|
391
|
+
filename. The selected archive contains
|
|
392
|
+
`version.template.json`, every referenced ASG/MTK/BES artifact, `SHA256SUMS`,
|
|
393
|
+
and a dependency-free configuration script. After unpacking it, generate the
|
|
394
|
+
final manifest for its exact hosting URL:
|
|
395
|
+
|
|
396
|
+
```sh
|
|
397
|
+
node configure.mjs https://updates.example.internal/mentra-live/version.json
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Host the entire directory at that location, then pass the same URL to `setOtaVersionUrl(...)`.
|
|
401
|
+
The generated `version.json` contains absolute internal artifact URLs, so it works with Mentra Live
|
|
402
|
+
ASG build 39 and newer as well as future firmware. Re-run the command if the hosted directory moves.
|
|
403
|
+
|
|
404
|
+
Firmware before ASG build 39 ignores `ota_start.ota_version_url` and must first be updated through
|
|
405
|
+
its legacy or factory-supported path. OTA remains host-driven: the SDK does not check or install
|
|
406
|
+
automatically.
|
|
407
|
+
|
|
408
|
+
OTA requires Mentra Live glasses firmware that supports the ASG OTA protocol and network access from the glasses. During install, normal BLE traffic can be interrupted and the glasses may restart; keep the app connected and avoid sending unrelated commands until `ota_status.status` is `complete` or `failed`.
|
|
409
|
+
|
|
410
|
+
For release selection, bundle verification, analytics opt-out, internal server
|
|
411
|
+
requirements, and disconnected validation, see the
|
|
412
|
+
[air-gapped deployment guide](https://docs.glassly.com/mentra-live/air-gapped-deployment).
|
|
413
|
+
|
|
414
|
+
Mentra Live also rejects `ota_start` before acknowledgement when its known battery level is below 5%, emitting a failed `ota_status` with `error_message: "battery_low"`. Unknown battery state remains fail-open, so apps should keep their own (typically stricter) user-facing battery policy.
|
|
415
|
+
|
|
416
|
+
## Photo Upload
|
|
417
|
+
|
|
418
|
+
```ts
|
|
419
|
+
const photo = await BluetoothSdk.requestPhoto({
|
|
420
|
+
size: 'medium',
|
|
421
|
+
webhookUrl: 'https://api.example.com/glassly/photo',
|
|
422
|
+
authToken: 'optional-token',
|
|
423
|
+
compress: 'medium',
|
|
424
|
+
sound: true,
|
|
425
|
+
exposureTimeNs: null, // auto exposure; pass a positive nanosecond value for manual exposure
|
|
426
|
+
iso: null, // auto ISO; pass a positive ISO only with manual exposureTimeNs
|
|
427
|
+
})
|
|
428
|
+
console.log('photo delivered', photo.photoUrl ?? photo.uploadUrl, photo.fileSizeBytes)
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
`requestPhoto(...)` resolves only after the full photo action reaches terminal success: capture completed and the photo was delivered to the webhook, either directly from the glasses over Wi-Fi or through the phone's Bluetooth fallback relay. If you omit `requestId`, the SDK generates one and the terminal response includes it. It rejects if the ASG reports `state: "error"`, if phone-side fallback upload fails, if the SDK cannot send the command, or if no terminal `photo_response` arrives within 30 seconds. Photo requests use this longer operation-specific deadline because max-quality BLE fallback can legitimately exceed the 15-second deadline used by ordinary commands. Use `photo_status` for intermediate stages such as `accepted`, `configuring`, `capturing`, `captured`, `uploading`, `ble_fallback_compression`, `ready_for_transfer`, and `transferring`; `photo_status` is progress, while `photo_response` is terminal success/error. The raw `photo_response` event stream still includes both success and error events for subscribers. The webhook should accept multipart form data with a `photo` file and `requestId`. If `authToken` is provided, the uploader adds `Authorization: Bearer <token>`. The camera light is always enabled for photo capture.
|
|
432
|
+
|
|
433
|
+
For one-shot manual capture tuning, pass `exposureTimeNs` and `iso` together. `exposureTimeNs` is sensor exposure time in nanoseconds; `iso` is sensor ISO. If `exposureTimeNs` is omitted, `null`, invalid, or unsupported by the connected glasses, the camera uses auto exposure and ignores `iso`.
|
|
434
|
+
|
|
435
|
+
To own and explicitly release a warm camera, pass a request ID to `warmUpCamera({requestId, ...})`, then call `stopCameraWarmUp(requestId)` when the foreground UI closes. Warm holds default to 15 seconds and are capped at 60 seconds. Stopping while the camera is opening rejects the pending warm-up with `camera_warm_up_cancelled`; stopping after `ready` emits `stopped`. Compatible ready leases share the camera and expire independently.
|
|
436
|
+
|
|
437
|
+
Use `setCameraFov({fov, roiPosition})` to configure Mentra Live camera field of view and crop position. FOV is clamped to 62-118 degrees; ROI position is `"center"`, `"bottom"`, or `"top"`. You can also call `setCameraFov({preset: "narrow" | "standard" | "wide"})`; presets map to 82, 102, and 118 degrees with center ROI. The returned `CameraFovResult` resolves only after the ASG client reports that the setting was applied to camera hardware after the restart cooldown, and the promise rejects if the glasses report an error, persist the setting without hardware application, or time out. Raw `settings_ack` events remain available through `addListener("settings_ack", ...)` for diagnostic fields such as `hardwareApplied`. Treat FOV as a framing/ROI control; output resolution and effective detail can vary by capture path, firmware, and camera mode.
|
|
438
|
+
|
|
439
|
+
The missing/factory persistent FOV base is 102 degrees with centered ROI; existing saved values are not migrated. Use `setCameraFovOverride({leaseId, fov, roiPosition, ttlMs})` for a memory-only crop and `releaseCameraFovOverride(leaseId)` to restore the persistent base. A stale release is a safe no-op, and refreshing the same lease/config extends its TTL without another HAL restart.
|
|
440
|
+
|
|
441
|
+
`startVideoRecording(...)` resolves from the ASG `video_recording_status` event whose status is `recording_started`. `stopVideoRecording(...)` without a webhook resolves from `recording_stopped`; with a webhook it waits for `recording_stopped` plus a video `media_success`, and rejects on `media_error`. Use `queryVideoRecordingStatus(requestId)` after a timeout, reconnect, or app resume to fetch the glasses' current `recording` state and elapsed `duration_ms`. Raw `video_recording_status`, `media_success`, and `media_error` events remain available through listeners.
|
|
442
|
+
|
|
443
|
+
## Streaming
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
const streamId = `stream-${Date.now()}`
|
|
447
|
+
|
|
448
|
+
await BluetoothSdk.startStream({
|
|
449
|
+
type: 'start_stream',
|
|
450
|
+
streamUrl: 'http://192.168.1.42:8889/mentra-live/whip',
|
|
451
|
+
streamId,
|
|
452
|
+
video: {fps: 15},
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
await BluetoothSdk.stopStream()
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
Use `rtmp://` or `rtmps://` for RTMP, `srt://` for SRT, and `http://` or `https://` for WHIP/WebRTC ingest. `startStream()` resolves with the correlated `stream_status` event once the glasses report `status: "streaming"`; `stopStream()` resolves when the glasses report `status: "stopped"` or confirms the stream was already stopped / not streaming. `stopStream()` returns a normalized stopped event for that already-stopped case. Stream starts reject if the glasses report an error before streaming; stream stops reject for real stop errors, send failure, another stop in flight, or timeout. Stream video input fields are `width`, `height`, `bitrate`, and `fps`. The SDK sends stream keep-alives automatically while streaming and reports keep-alive failures through `stream_status`. The camera light is always enabled while streaming.
|
|
459
|
+
`stream_status` events may include `resolvedConfig`, which reports the effective transport, video, and audio settings after glasses defaults, clamps, and camera preflight. The resolved effective frame rate is reported as `resolvedConfig.video.fps`. While live, supported firmware emits periodic `streaming` events whose `stats` object contains `bitrate` (bits per second), `fps`, `droppedFrames`, `duration` (seconds), and `temperatureC` when the CPU sensor is available.
|
|
460
|
+
|
|
461
|
+
## Events
|
|
462
|
+
|
|
463
|
+
React Native components should use `useBluetoothEvent()` for hardware events:
|
|
464
|
+
|
|
465
|
+
```tsx
|
|
466
|
+
import {useBluetoothEvent} from '@glassly/bluetooth-sdk/react'
|
|
467
|
+
|
|
468
|
+
export function HardwareEventLogger() {
|
|
469
|
+
useBluetoothEvent('button_press', (event) => console.log(event))
|
|
470
|
+
useBluetoothEvent('touch_event', (event) => console.log(event))
|
|
471
|
+
useBluetoothEvent('photo_status', (event) => console.log(event.status, event.resolvedConfig, event.captureMetadata))
|
|
472
|
+
useBluetoothEvent('stream_status', (event) => console.log(event))
|
|
473
|
+
useBluetoothEvent('speaking_status', (event) => console.log(event.speaking))
|
|
474
|
+
useBluetoothEvent('mic_pcm', (event) => {
|
|
475
|
+
console.log(event.sampleRate, event.bitsPerSample, event.channels, event.encoding)
|
|
476
|
+
console.log(event.pcm)
|
|
477
|
+
})
|
|
478
|
+
useBluetoothEvent('mic_health', (event) => {
|
|
479
|
+
console.log(event.reason, event.sequenceGapEvents, event.decodeFailures)
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
return null
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
For non-React modules, `BluetoothSdk.addListener(...)` is the low-level subscription API. Keep the returned subscription and call `remove()` when the listener is no longer needed.
|
|
487
|
+
|
|
488
|
+
Common event names include `button_press`, `touch_event`, `head_up`, `battery_status`, `wifi_status_change`, `wifi_scan_result`, `hotspot_status_change`, `photo_status`, `photo_response`, `gallery_status`, `settings_ack`, `version_info`, `stream_status`, `ota_start_ack`, `ota_status`, `mic_pcm`, `mic_lc3`, `mic_health`, `local_transcription`, `rgb_led_control_response`, `audio_connected`, `audio_disconnected`, and `log`.
|
|
489
|
+
|
|
490
|
+
React Native event payload fields usually use camelCase. OTA events intentionally mirror the glasses firmware field names, such as `overall_percent` and `version_name`. For example, `touch_event` includes `gestureName`, `wifi_scan_result` includes `networks` and `scanComplete`, `version_info` matches the `requestVersionInfo()` result shape, `photo_response` success includes `uploadUrl` and may include webhook-returned `photoUrl`, `statusUrl`, `contentType`, and `fileSizeBytes`, and `gallery_status` includes `hasContent`, `cameraBusy`, and optional `cameraBusyReason`. `photo_status` reports intermediate photo states such as `accepted`, `queued`, `configuring`, `capturing`, `captured`, `compressing`, `ble_fallback_compression`, `uploading`, `ready_for_transfer`, `transferring`, and `failed`; the `configuring` event includes `resolvedConfig` with the effective JPEG dimensions, quality, requested size, transfer method, compression, and manual exposure fields when present. The `capturing` event may include `requestedCaptureConfig` and `meteredPreview`; the `captured` event may include `captureMetadata` with the HAL-applied exposure, ISO, frame duration, and AE state. `mic_pcm` includes `sampleRate`, `bitsPerSample`, `channels`, and `encoding`; `mic_lc3` includes `sampleRate`, `channels`, `encoding`, `frameDurationMs`, `frameSizeBytes`, `bitrate`, and `packetizedFromGlasses`.
|
|
491
|
+
|
|
492
|
+
`mic_health` emits a snapshot when native code detects a glasses LC3 `sequence_gap` or `decode_failure`. Each event includes cumulative `sequenceGapEvents` and `decodeFailures` counters for the current connection plus `lastLc3ReceivedAt`, `lastPcmProducedAt`, and `timestamp` in Unix milliseconds when available. These failures occur before React Native receives PCM and cannot be reconstructed from `mic_pcm` alone. The existing `mic_pcm` and `mic_lc3` streams remain unchanged.
|
|
493
|
+
|
|
494
|
+
Photo status metadata is tied to the capture stage where the glasses know it:
|
|
495
|
+
|
|
496
|
+
| Status | Optional metadata | Meaning |
|
|
497
|
+
| --- | --- | --- |
|
|
498
|
+
| `configuring` | `resolvedConfig` | Effective JPEG size, quality, requested size, source, transfer method, compression, and manual capture settings when present. |
|
|
499
|
+
| `capturing` | `requestedCaptureConfig`, `meteredPreview` | Camera2 still request about to be submitted, plus the latest auto-exposure preview estimate before capture. |
|
|
500
|
+
| `captured` | `captureMetadata` | HAL-applied still capture result, including actual exposure, ISO, frame duration, AE state, and related camera modes when available. |
|
|
501
|
+
|
|
502
|
+
Upload and transfer statuses such as `uploading`, `compressing`, `ble_fallback_compression`, `ready_for_transfer`, and `transferring` describe transport progress only and do not carry capture metadata. `ble_fallback_compression` means the direct Wi-Fi/webhook upload failed and the glasses are compressing the already-captured photo for Bluetooth fallback delivery. Local action-button photos emitted by the glasses use the same `photo_status` event shape when the phone SDK is connected; those events use `resolvedConfig.source: "button"` and `resolvedConfig.transferMethod: "local"`.
|
|
503
|
+
|
|
504
|
+
Only documented imports are supported for app developers. Undocumented package subpaths or symbols with a leading underscore can change without notice.
|
|
505
|
+
|
|
506
|
+
## Local SDK Development
|
|
507
|
+
|
|
508
|
+
For normal app development, install the JavaScript package from npm. For SDK source development or release testing, install a local checkout and point Metro/native resolution at the same path:
|
|
509
|
+
|
|
510
|
+
```sh
|
|
511
|
+
bun add --no-save /path/to/Glassly/mobile/modules/bluetooth-sdk
|
|
512
|
+
GLASSLY_BLUETOOTH_SDK_PACKAGE_PATH=/path/to/Glassly/mobile/modules/bluetooth-sdk bunx expo run:ios
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
Use `bunx expo run:android` for Android. Keep local paths in your shell or CI environment, not in committed app config.
|
|
516
|
+
|
|
517
|
+
For local Android source compile checks inside this monorepo, run from the
|
|
518
|
+
Glassly repo root:
|
|
519
|
+
|
|
520
|
+
```sh
|
|
521
|
+
./scripts/check-android-compile.sh bluetooth-sdk
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
The `android/` folder in this package is source for the generated Expo Android
|
|
525
|
+
project, not the local Gradle entrypoint. The check script prepares
|
|
526
|
+
`mobile/android` and uses its Gradle wrapper with `-PglasslyPublicSdk=true`,
|
|
527
|
+
matching the CI release workflow's public SDK dependency mode.
|
|
528
|
+
|
|
529
|
+
For bare native iOS apps, use the public SwiftPM repository:
|
|
530
|
+
|
|
531
|
+
```text
|
|
532
|
+
https://github.com/tetramo-labs/glassly-bluetooth-sdk-ios.git
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
Select version `0.1.20`, then add the `BluetoothSDK` product to your app target.
|
|
536
|
+
|
|
537
|
+
For local SDK development, add this package folder directly in Xcode:
|
|
538
|
+
|
|
539
|
+
```text
|
|
540
|
+
/path/to/Glassly/mobile/modules/bluetooth-sdk
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
The core Swift package intentionally excludes optional local STT, Nex/SwiftProtobuf, Vuzix/Ultralite, and tar.bz2 extraction code paths.
|
|
544
|
+
|
|
545
|
+
Maintainers publishing the public SwiftPM mirror should follow
|
|
546
|
+
[RELEASING_IOS_SPM.md](./RELEASING_IOS_SPM.md).
|
|
547
|
+
|
|
548
|
+
## Android Maven Publishing
|
|
549
|
+
|
|
550
|
+
Maintainers publishing the native Android artifacts to Maven Central should
|
|
551
|
+
follow [RELEASING_ANDROID_MAVEN.md](./RELEASING_ANDROID_MAVEN.md).
|
|
552
|
+
|
|
553
|
+
Public Maven publishing uses a public SDK mode that omits Glassly-only Android
|
|
554
|
+
integrations from the artifact metadata while normal Glassly app builds keep
|
|
555
|
+
those integrations enabled.
|
|
556
|
+
|
|
557
|
+
Use `android/gradle.properties.example` as the template for Sonatype Central and
|
|
558
|
+
GPG signing properties. Put real values in `~/.gradle/gradle.properties` or CI
|
|
559
|
+
secrets, not in the repository.
|
|
560
|
+
|
|
561
|
+
## Starter Example App
|
|
562
|
+
|
|
563
|
+
The [Glassly Bluetooth SDK Starter Kit](https://github.com/Glassly-Community/Glassly-Bluetooth-SDK-Starter-Kit) includes starter example apps for Android, iOS, and React Native / Expo. The React Native starter demonstrates scan/connect, display, camera photo upload, RTMP/SRT/WebRTC streaming, Wi-Fi/hotspot, microphone PCM, RGB LED, gallery mode, and console event inspection.
|