feat: 자동측정 IMU 1초 + 전체측정(mbb) 10초 루프

자동측정 변경 (기존: 30초 maa → 신규: 1초 msp + 10초 mbb):
- 1~9초: msp(IMU query) → rsp(accel+gyro) 1초 간격
- 10초째: mbb(전체측정) → rbb(헤더) + reb×6 + raa
- 기존 maa → mbb(sendFullMeasurement)로 전환
- mbb 응답은 rbb: 헤더 후 reb:/raa: 동일 파이프라인

BLE 명령어 추가:
- sendImuQuery(): msp 전송
- sendFullMeasurement(): mbb 전송 (piezoCollector 연동)
- sendLedMode(state): mls 전송

응답 파싱 추가:
- rxs: → "cmd_not_supported" (mid? 미지원 기기 대응)
- rbb: → full measurement header
- rsp: → IMU data

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-24 11:31:03 +09:00
parent e6e339379b
commit eb5affc6b8
2 changed files with 50 additions and 9 deletions
@@ -85,6 +85,8 @@ class BleManager private constructor(private val context: Context) {
var onPiezoDataReceived: ((ByteArray) -> Unit)? = null
var onUnexpectedDisconnect: (() -> Unit)? = null
var onReconnectionFailed: (() -> Unit)? = null
var onImuReceived: ((ByteArray) -> Unit)? = null
var onMbbHeaderReceived: ((ByteArray) -> Unit)? = null
val isBluetoothReady: Boolean get() = bluetoothAdapter?.isEnabled == true
@@ -282,6 +284,8 @@ class BleManager private constructor(private val context: Context) {
"mcj" -> "NIRS MCJ query"
"mid" -> "device info query"
"mls" -> "LED mode ${if (data.size > 4) data[4].toInt() and 0xFF else "?"}"
"msp" -> "IMU query"
"mbb" -> "full measurement (battery+IMU+temp+6ch)"
else -> ""
}
logd { "sendRaw: $cmdPreview (${data.size} bytes)" }
@@ -353,6 +357,16 @@ class BleManager private constructor(private val context: Context) {
sendRaw(CRC16.buildCommand("mls", intArrayOf(state)))
}
fun sendImuQuery() {
sendRaw(CRC16.buildCommand("msp"))
}
/** 전체 측정: 배터리+IMU+온도+6ch piezo (rbb→reb×6→raa) */
fun sendFullMeasurement() {
piezoCollector.startMultiChannel(6)
sendRaw(CRC16.buildCommand("mbb"))
}
fun startBatteryPolling() {
batteryTimer?.let { handler.removeCallbacks(it) }
sendBatteryQuery()
@@ -789,6 +803,20 @@ class BleManager private constructor(private val context: Context) {
val state = if (data.size >= 5) data[4].toInt() and 0xFF else -1
debugLogger.rx("rls", data.size, "led_state=$state")
}
"rxs:" -> {
val echoCmd = if (data.size > 4) String(data, 4, minOf(data.size - 4, 10), Charsets.US_ASCII).trim() else "?"
debugLogger.rx("rxs", data.size, "cmd_not_supported: $echoCmd")
}
"rbb:" -> {
debugLogger.rx("rbb", data.size, "full measurement header (battery+IMU+temp)")
onMbbHeaderReceived?.invoke(data)
}
"rsp:" -> {
if (data.size >= 16) {
debugLogger.rx("rsp", data.size, "IMU data")
}
onImuReceived?.invoke(data)
}
else -> {
val hex = data.take(8).joinToString(" ") { "%02X".format(it) }
debugLogger.rx("???", data.size, "unknown prefix='$prefix' hex=$hex")