@mentra/bluetooth-sdk 0.1.17 → 0.1.19
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 +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +52 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +119 -16
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +0 -6
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +22 -21
- package/android/src/main/java/com/mentra/bluetoothsdk/OtaManifest.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +488 -15
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.kt +457 -31
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLiveL2capChannel.kt +274 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +361 -67
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraosBle.java +7501 -3704
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +134 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/status/DeviceStatus.kt +0 -6
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BleJsonCompact.java +493 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BlePhotoUploadService.java +4 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BleWireProtocol.java +108 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/IncidentLogBleUploadService.java +4 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/K900LengthCodec.java +115 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/K900ProtocolUtils.java +103 -68
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunkReassembler.java +106 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunker.java +93 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/NexSGCUtils.kt +111 -11
- package/android/src/test/java/com/mentra/bluetoothsdk/camera/PhotoRequestTest.kt +7 -9
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/AvifExifStripperTest.java +17 -1
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/BinaryMessageChunkerTest.java +84 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/BleJsonCompactTest.java +158 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/K900ProtocolUtilsEndiannessTest.java +172 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/K900ProtocolUtilsTest.java +24 -0
- package/build/BluetoothSdk.types.d.ts +12 -1
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- 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/ios/LocalPhotoUploadServer.swift +78 -0
- package/ios/MentraPhotoReceiverModule.swift +10 -0
- package/ios/Source/BluetoothSdkDefaults.swift +1 -1
- package/ios/Source/Bridge.swift +63 -0
- package/ios/Source/DeviceManager.swift +134 -29
- package/ios/Source/DeviceStore.swift +0 -5
- package/ios/Source/MentraBluetoothSDK.swift +26 -23
- package/ios/Source/OtaManifest.swift +1 -1
- package/ios/Source/internal/BleTraceLogger.swift +192 -0
- package/ios/Source/sgcs/G2.swift +518 -11
- package/ios/Source/sgcs/MentraLive.swift +607 -39
- package/ios/Source/sgcs/MentraNex.swift +416 -32
- package/ios/Source/sgcs/SGCManager.swift +155 -0
- package/ios/Source/sgcs/mentraos_ble.pb.swift +726 -122
- package/ios/Source/status/DeviceStatus.swift +0 -8
- package/ios/Source/utils/BleJsonCompact.swift +395 -0
- package/ios/Source/utils/BleWireProtocol.swift +92 -0
- package/ios/Source/utils/MessageChunkReassembler.swift +82 -0
- package/ios/Source/utils/MessageChunker.swift +73 -0
- package/package.json +14 -7
- package/src/BluetoothSdk.types.ts +13 -1
- package/src/types/index.ts +7 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import os.log
|
|
3
|
+
import UIKit
|
|
4
|
+
|
|
5
|
+
enum BleTraceLogger {
|
|
6
|
+
private static let log = OSLog(subsystem: "com.mentra.bluetoothsdk", category: "MentraBleTrace")
|
|
7
|
+
private static let maxPayloadChars = 3000
|
|
8
|
+
private static let k900Type = "k900"
|
|
9
|
+
private static let sensitiveKeyParts = ["password", "pass", "token", "secret", "authorization", "auth", "email"]
|
|
10
|
+
|
|
11
|
+
static func logJson(
|
|
12
|
+
direction: String,
|
|
13
|
+
layer: String,
|
|
14
|
+
payload: [String: Any]?,
|
|
15
|
+
bytes: Int? = nil,
|
|
16
|
+
sourceFile: String = #fileID,
|
|
17
|
+
sourceFunction: String = #function,
|
|
18
|
+
sourceLine: Int = #line
|
|
19
|
+
) {
|
|
20
|
+
guard let payload else {
|
|
21
|
+
emit(format(
|
|
22
|
+
direction: direction,
|
|
23
|
+
layer: layer,
|
|
24
|
+
source: source(file: sourceFile, function: sourceFunction, line: sourceLine),
|
|
25
|
+
type: "null",
|
|
26
|
+
bytes: bytes,
|
|
27
|
+
payload: "null"
|
|
28
|
+
))
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let sanitized = sanitizeDictionary(payload)
|
|
33
|
+
emit(format(
|
|
34
|
+
direction: direction,
|
|
35
|
+
layer: layer,
|
|
36
|
+
source: source(file: sourceFile, function: sourceFunction, line: sourceLine),
|
|
37
|
+
type: extractType(from: payload),
|
|
38
|
+
bytes: bytes,
|
|
39
|
+
payload: jsonString(sanitized)
|
|
40
|
+
))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static func logMap(
|
|
44
|
+
direction: String,
|
|
45
|
+
layer: String,
|
|
46
|
+
type: String?,
|
|
47
|
+
payload: [String: Any],
|
|
48
|
+
bytes: Int? = nil,
|
|
49
|
+
sourceFile: String = #fileID,
|
|
50
|
+
sourceFunction: String = #function,
|
|
51
|
+
sourceLine: Int = #line
|
|
52
|
+
) {
|
|
53
|
+
let sanitized = sanitizeDictionary(payload)
|
|
54
|
+
emit(format(
|
|
55
|
+
direction: direction,
|
|
56
|
+
layer: layer,
|
|
57
|
+
source: source(file: sourceFile, function: sourceFunction, line: sourceLine),
|
|
58
|
+
type: type ?? extractType(from: sanitized),
|
|
59
|
+
bytes: bytes,
|
|
60
|
+
payload: jsonString(sanitized)
|
|
61
|
+
))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static func logLifecycle(component: String, event: String, extra: [String: Any] = [:]) {
|
|
65
|
+
var payload: [String: Any] = [
|
|
66
|
+
"event": event,
|
|
67
|
+
"component": component,
|
|
68
|
+
"pid": ProcessInfo.processInfo.processIdentifier,
|
|
69
|
+
"model": UIDevice.current.model,
|
|
70
|
+
"systemVersion": UIDevice.current.systemVersion,
|
|
71
|
+
]
|
|
72
|
+
for (key, value) in extra {
|
|
73
|
+
payload[key] = value
|
|
74
|
+
}
|
|
75
|
+
logMap(direction: "phone_app", layer: "app_lifecycle", type: event, payload: payload)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private static func emit(_ line: String) {
|
|
79
|
+
os_log("%{public}@", log: log, type: .info, line)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private static func format(
|
|
83
|
+
direction: String,
|
|
84
|
+
layer: String,
|
|
85
|
+
source: String,
|
|
86
|
+
type: String,
|
|
87
|
+
bytes: Int?,
|
|
88
|
+
payload: String
|
|
89
|
+
) -> String {
|
|
90
|
+
let bytesText = bytes.map { " bytes=\($0)" } ?? ""
|
|
91
|
+
return "BLE_TRACE direction=\(direction) layer=\(layer) source=\(source) type=\(type)\(bytesText) payload=\(truncate(payload))"
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private static func extractType(from payload: [String: Any]) -> String {
|
|
95
|
+
if let type = payload["type"] as? String, !type.isEmpty {
|
|
96
|
+
return type
|
|
97
|
+
}
|
|
98
|
+
if let cValue = payload["C"] as? String, !cValue.isEmpty {
|
|
99
|
+
if let data = cValue.data(using: .utf8),
|
|
100
|
+
let inner = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
101
|
+
let type = inner["type"] as? String,
|
|
102
|
+
!type.isEmpty
|
|
103
|
+
{
|
|
104
|
+
return type
|
|
105
|
+
}
|
|
106
|
+
return extractK900Type(cValue)
|
|
107
|
+
}
|
|
108
|
+
return "unknown"
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private static func extractK900Type(_ value: String) -> String {
|
|
112
|
+
value == "sr_log" ? "\(k900Type):sr_log" : k900Type
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private static func sanitizeDictionary(_ value: [String: Any]) -> [String: Any] {
|
|
116
|
+
var output: [String: Any] = [:]
|
|
117
|
+
for (key, child) in value {
|
|
118
|
+
output[key] = sanitizeValue(key: key, value: child)
|
|
119
|
+
}
|
|
120
|
+
return output
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private static func sanitizeArray(_ value: [Any]) -> [Any] {
|
|
124
|
+
value.map { sanitizeValue(key: nil, value: $0) }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private static func sanitizeValue(key: String?, value: Any) -> Any {
|
|
128
|
+
if let key, sensitiveKeyParts.contains(where: { key.localizedCaseInsensitiveContains($0) }) {
|
|
129
|
+
return "<redacted>"
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if key == "C", let stringValue = value as? String {
|
|
133
|
+
if let data = stringValue.data(using: .utf8),
|
|
134
|
+
let parsed = try? JSONSerialization.jsonObject(with: data)
|
|
135
|
+
{
|
|
136
|
+
return jsonString(sanitizeJsonValue(parsed))
|
|
137
|
+
}
|
|
138
|
+
return sanitizeK900Command(stringValue)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return sanitizeJsonValue(value)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private static func sanitizeJsonValue(_ value: Any) -> Any {
|
|
145
|
+
switch value {
|
|
146
|
+
case let dictionary as [String: Any]:
|
|
147
|
+
return sanitizeDictionary(dictionary)
|
|
148
|
+
case let array as [Any]:
|
|
149
|
+
return sanitizeArray(array)
|
|
150
|
+
case let data as Data:
|
|
151
|
+
return "<data \(data.count) bytes>"
|
|
152
|
+
case let url as URL:
|
|
153
|
+
return url.absoluteString
|
|
154
|
+
case let bool as Bool:
|
|
155
|
+
return bool
|
|
156
|
+
case let number as NSNumber:
|
|
157
|
+
return number
|
|
158
|
+
case let string as String:
|
|
159
|
+
return string
|
|
160
|
+
case _ as NSNull:
|
|
161
|
+
return NSNull()
|
|
162
|
+
default:
|
|
163
|
+
return String(describing: value)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private static func sanitizeK900Command(_ value: String) -> String {
|
|
168
|
+
value == "sr_log" ? value : "<non-json C payload>"
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private static func jsonString(_ value: Any) -> String {
|
|
172
|
+
guard JSONSerialization.isValidJSONObject(value),
|
|
173
|
+
let data = try? JSONSerialization.data(withJSONObject: value),
|
|
174
|
+
let string = String(data: data, encoding: .utf8)
|
|
175
|
+
else {
|
|
176
|
+
return String(describing: value)
|
|
177
|
+
}
|
|
178
|
+
return string
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private static func source(file: String, function: String, line: Int) -> String {
|
|
182
|
+
"\(function)(\(file):\(line))"
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private static func truncate(_ value: String) -> String {
|
|
186
|
+
guard value.count > maxPayloadChars else {
|
|
187
|
+
return value
|
|
188
|
+
}
|
|
189
|
+
let endIndex = value.index(value.startIndex, offsetBy: maxPayloadChars)
|
|
190
|
+
return "\(value[..<endIndex])...(truncated \(value.count - maxPayloadChars) chars)"
|
|
191
|
+
}
|
|
192
|
+
}
|