docs: CSV 포맷 업데이트 (threshold/dps/sg_filter 컬럼) + Endian 안정화

- CSV: threshold, dps, sg_filter 컬럼 추가 설명
- Python 예시: 설정값 기반 필터링 추가
- BLE 로그 대조 방법 설명 (scan_id 기반)
- Endian 자동 감지: VBT=BE 기본, forceBigEndian fallback 설명
- 향후 과제: Endian 안정화 완료 항목 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-27 12:24:11 +09:00
parent fb8204994f
commit b750b22406
+45 -16
View File
@@ -1204,20 +1204,25 @@ Downloads/VesiScan_ADC/YYYY-MM-DD.csv
### CSV 포맷
```csv
scan_id,timestamp,volume_ml,lr_ratio,channel,s0,s1,s2,...,s99
1,14:30:12.345,305.2,1.20,CH0,1823,1801,1788,...,1245
1,14:30:12.345,305.2,1.20,CH1,1756,1734,1721,...,1198
1,14:30:12.345,305.2,1.20,CH2,1802,1788,1775,...,1234
1,14:30:12.345,305.2,1.20,CH3,1834,1812,1799,...,1267
1,14:30:12.345,305.2,1.20,CH4,1645,1623,1610,...,1123
1,14:30:12.345,305.2,1.20,CH5,1721,1698,1685,...,1178
2,14:30:22.678,,1.00,CH0,1234,...
scan_id,timestamp,volume_ml,lr_ratio,threshold,dps,sg_filter,channel,s0,s1,...,s99
1,14:30:12,305.2,1.20,1150,1.771,ON,CH0,1823,1801,...,1245
1,14:30:12,305.2,1.20,1150,1.771,ON,CH1,1756,1734,...,1198
1,14:30:12,305.2,1.20,1150,1.771,ON,CH2,1802,1788,...,1234
1,14:30:12,305.2,1.20,1150,1.771,ON,CH3,1834,1812,...,1267
1,14:30:12,305.2,1.20,1150,1.771,ON,CH4,1645,1623,...,1123
1,14:30:12,305.2,1.20,1150,1.771,ON,CH5,1721,1698,...,1178
2,14:30:22,419.0,1.20,1221,1.968,ON,CH0,1830,...
3,14:30:32,,1.00,1150,1.771,OFF,CH0,1234,...
```
- `scan_id`: 측정 회차 (같은 ID = 같은 측정의 6채널)
- `scan_id`: 측정 회차 (같은 ID = 같은 측정의 6채널). BLE 로그에도 동일 ID 기록
- `volume_ml`: BV 추정 결과 (빈칸이면 측정 실패)
- `lr_ratio`: lr_ratio 계산값
- `threshold`: Low Echo Threshold (측정 시점의 설정값)
- `dps`: Distance Per Sample mm (측정 시점의 설정값)
- `sg_filter`: SG 필터 적용 여부 (ON/OFF)
- `channel`: CH0~CH5
- `s0~s99`: ADC 100개 샘플
- `s0~s99`: Raw ADC 100개 샘플 (SG 적용 전 원본, 항상 raw)
### Python에서 읽기
@@ -1230,17 +1235,40 @@ df = pd.read_csv("2026-04-27.csv")
scan1 = df[df.scan_id == 1]
# CH0 ADC 100개
ch0_adc = scan1[scan1.channel == "CH0"].iloc[0, 5:].values
ch0_adc = scan1[scan1.channel == "CH0"].iloc[0, 8:].values
# 전체 측정 용적 추이
volumes = df[df.channel == "CH0"][["scan_id", "timestamp", "volume_ml"]].drop_duplicates()
volumes = df[df.channel == "CH0"][["scan_id", "timestamp", "volume_ml", "threshold", "dps"]].drop_duplicates()
# threshold 1221로 측정한 것만
df_1221 = df[df.threshold == 1221]
# SG OFF로 측정한 것만
df_nosg = df[df.sg_filter == "OFF"]
```
### BLE 로그와 대조
```
BLE 로그: INFO MEASUREMENT scan=3 vol=305.2ml lr=1.20 valid=4/6
CSV: 3,14:30:12,305.2,1.20,1150,1.771,ON,CH0,...
→ scan=3으로 동일 측정의 ADC + 설정값 + 로그를 대조 가능
```
### 저장 시점
- BV 추정 성공 시: volume_ml + lr_ratio + 6채널 ADC
- BV 추정 실패 시 (center 부족): volume_ml 빈칸 + 6채널 ADC
- 0채널 감지 시: volume_ml 빈칸 + 6채널 ADC (raw 데이터 보존)
- BV 추정 성공 시: volume_ml + lr_ratio + 설정값 + 6채널 ADC
- BV 추정 실패 시 (center 부족): volume_ml 빈칸 + 설정값 + 6채널 ADC
- 0채널 감지 시: volume_ml 빈칸 + 설정값 + 6채널 ADC (raw 보존)
### Endian 자동 감지
ADC 파싱 시 Big/Little Endian을 자동 감지:
- VBT* 기기: 기본 Big Endian (forceBigEndian=true)
- 2025MEDIP: 기본 Little Endian
- CH0 첫 샘플로 확인, 애매하면 기기 기본값 사용
- CSV에는 항상 정상 파싱된 0~4095 범위의 raw ADC 저장
---
@@ -1261,7 +1289,8 @@ volumes = df[df.channel == "CH0"][["scan_id", "timestamp", "volume_ml"]].drop_du
| 자동측정 (IMU 1s + 측정 10s) | ✅ 완료 | |
| 런타임 캘리브레이션 | ✅ 완료 | Threshold 슬라이더 + DPS 직접입력 + SG 토글 |
| 도넛차트 실시간 ml | ✅ 완료 | lastVolumeMl 직접 표시 |
| ADC CSV 저장 | ✅ 완료 | Downloads/VesiScan_ADC/일별.csv |
| ADC CSV 저장 | ✅ 완료 | Downloads/VesiScan_ADC/일별.csv + 설정값 포함 |
| Endian 감지 안정화 | ✅ 완료 | VBT=BE 기본, 애매한 경우 기기 기반 fallback |
| Python ↔ Android 1:1 검증 | ✅ 완료 | 전수 상수 비교 |
| 금요일 APK 배포 | 🔜 예정 | Gitea 릴리즈 |
| mbb 전체측정 전환 | 🔜 예정 | rbb: 헤더 파싱 검증 후 |