refactor: 데모 브랜치 패키지 통일 com.example.medilightv2android → com.medithings.vesiscan

사용자앱 (feature/tab-navigation) 과 패키지 이름 일치. namespace + applicationId
둘 다 com.medithings.vesiscan 로 변경 (기존 데모 앱은 재설치 필요).

## 변경 범위
- Kotlin 148 파일: package + import 문 (714 occurrences)
- 디렉토리 이동: com/example/medilightv2android → com/medithings/vesiscan
  (main, test, androidTest 각각)
- app/build.gradle.kts: namespace, applicationId
- docs/FLAVOR_DEMO_STABLE.md: 참조 갱신
- V41DetectorCH4Test: BvDispatchResult.methodChosen → method (dto field name fix)

## 주의
- applicationId 가 바뀌므로 기존 데모 앱 (com.example.medilightv2android.demo) 은
  Android 관점에서 다른 앱으로 취급 — 재설치 시 PIN/설정 초기화됨.
- Fresh install 권장. 기존 앱 (com.example...) 은 별도로 uninstall 필요.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 14:30:43 +09:00
parent 55d55225ab
commit bcbc7b440c
159 changed files with 2865 additions and 717 deletions
+85
View File
@@ -0,0 +1,85 @@
# RawBleLogger session — started 15:50:20.665
# Format: HH:mm:ss.SSS dir=RX prefix=XXX len=N hex=AA BB ...
15:50:28.876 dir=RX prefix=reb: len=210 hex=72 65 62 3A 16 00 00 64 08 80 08 B6 08 F8 09 25 08 BC 08 76 07 F4 06 F7 06 BA 06 9C 06 94 06 6D 06 2C 05 EF 05 8C 05 41 05 0E 04 C1 04 9E 04 42 03 CE 03 8B 03 6E 03 5B 03 4A 03 55 03 45 03 4C 03 47 03 34 03 50 03 48 03 53 03 3D 03 36 03 44 03 2E 03 4A 03 4C 03 55 03 3D 03 30 03 25 03 4E 03 55 03 4A 03 36 03 3C 03 48 03 4A 03 47 03 44 03 4D 03 4B 03 4A 03 36 03 59 03 52 03 39 03 4B 03 4A 03 29 03 3F 03 4B 03 46 03 47 03 4A 03 3D 03 5D 03 50 03 47 03 38 03 4E 03 45 03 2C 03 3C 03 42 03 45 03 43 03 31 03 3A 03 28 03 4E 03 43 03 5B 03 55 03 45 03 47 03 2F 03 4A 03 42 03 4C 03 31 03 3F 03 3A 03 4A 03 3D 03 3C 03 32 03 44 6C 80
15:50:28.919 dir=RX prefix=reb: len=210 hex=72 65 62 3A 16 01 00 64 08 84 07 48 07 40 06 7B 06 47 06 59 05 CF 05 B0 04 DD 04 89 04 15 03 FC 03 A1 03 65 03 5B 03 54 03 52 03 53 03 55 03 3B 03 4A 03 42 03 24 03 35 03 50 03 36 03 50 03 36 03 46 03 49 03 3B 03 23 03 57 03 44 03 3D 03 4F 03 46 03 43 03 59 03 3C 03 37 03 38 03 46 03 47 03 61 03 44 03 33 03 55 03 2F 03 43 03 44 03 59 03 44 03 3A 03 4C 03 50 03 3D 03 32 03 3E 03 2C 03 49 03 4F 03 47 03 52 03 3F 03 48 03 4F 03 3F 03 36 03 35 03 51 03 44 03 32 03 39 03 37 03 53 03 43 03 41 03 4E 03 3D 03 33 03 55 03 51 03 34 03 48 03 44 03 51 03 62 03 41 03 34 03 3A 03 38 03 49 03 35 03 4E 03 3F 03 43 03 52 03 54 03 56 72 8C
15:50:28.942 dir=RX prefix=reb: len=210 hex=72 65 62 3A 16 02 00 64 08 D2 07 93 06 F0 06 C9 06 A9 05 90 05 E0 05 A3 06 13 05 0C 04 76 04 6D 04 1B 03 99 03 68 03 39 03 41 03 55 03 8F 03 75 03 83 03 81 03 6F 03 6F 03 71 03 80 03 7E 03 68 03 8A 03 7B 03 7A 03 6D 03 88 03 93 03 6F 03 84 03 8F 03 8E 03 75 03 89 03 7E 03 70 03 74 03 73 03 8A 03 75 03 74 03 81 03 8C 03 78 03 65 03 91 03 75 03 8A 03 87 03 7D 03 71 03 46 03 5B 03 3B 03 4B 03 4B 03 41 03 4B 03 3B 03 36 03 38 03 47 03 42 03 48 03 52 03 55 03 4E 03 4C 03 47 03 53 03 52 03 47 03 44 03 58 03 68 03 3E 03 41 03 2F 03 23 03 49 03 4E 03 47 03 49 03 50 03 4D 03 43 03 3A 03 56 03 44 03 46 03 44 03 47 03 61 03 3B 68 54
15:50:28.963 dir=RX prefix=reb: len=210 hex=72 65 62 3A 16 03 00 64 09 35 08 D9 07 C2 07 30 06 E4 06 2A 06 0A 06 20 05 E2 05 81 04 C4 03 F5 04 9E 03 B6 03 66 03 6E 03 7D 03 3E 03 41 03 46 03 3F 03 3E 03 47 03 41 03 4A 03 3D 03 4A 03 46 03 56 03 47 03 4C 03 4A 03 47 03 36 03 43 03 2C 03 52 03 4A 03 38 03 4A 03 3B 03 46 03 4D 03 47 03 53 03 44 03 41 03 4C 03 40 03 3D 03 42 03 55 03 38 03 42 03 32 03 41 03 49 03 48 03 41 03 42 03 36 03 38 03 2D 03 54 03 5F 03 32 03 4E 03 47 03 4F 03 46 03 48 03 3A 03 47 03 51 03 54 03 42 03 44 03 28 03 4D 03 42 03 51 03 3F 03 3F 03 4F 03 3E 03 3E 03 52 03 5E 03 44 03 39 03 40 03 44 03 3C 03 44 03 41 03 56 03 5F 03 55 03 49 03 2E B9 A7
15:50:28.995 dir=RX prefix=reb: len=210 hex=72 65 62 3A 16 04 00 64 07 1F 06 E9 06 9B 05 EE 05 D9 05 DD 05 79 05 48 05 47 04 85 04 0B 03 C0 03 6A 03 4C 03 42 03 5D 03 43 03 48 03 48 03 5A 03 47 03 42 03 3B 03 2D 03 45 03 50 03 42 03 48 03 40 03 40 03 51 03 3D 03 3B 03 59 03 44 03 33 03 41 03 40 03 49 03 38 03 47 03 51 03 41 03 42 03 49 03 47 03 5F 03 41 03 31 03 48 03 46 03 53 03 39 03 4B 03 55 03 61 03 47 03 43 03 52 03 4D 03 3E 03 3A 03 46 03 50 03 3F 03 41 03 46 03 47 03 5C 03 3E 03 4E 03 5E 03 3C 03 53 03 41 03 4A 03 54 03 47 03 63 03 34 03 49 03 49 03 41 03 44 03 49 03 3D 03 4C 03 66 03 44 03 95 03 A6 03 8E 03 9C 03 92 03 88 03 8B 03 99 03 99 03 8D 03 C9 36 DD
15:50:29.038 dir=RX prefix=reb: len=210 hex=72 65 62 3A 16 05 00 64 07 8E 06 90 06 CD 06 38 06 3C 05 D8 05 3B 05 24 05 17 04 D8 04 39 03 96 03 7D 03 59 03 63 03 50 03 4C 03 50 03 4D 03 67 03 55 03 4F 03 43 03 48 03 45 03 62 03 46 03 4F 03 44 03 4D 03 5D 03 5A 03 44 03 3F 03 49 03 37 03 3D 03 5D 03 57 03 66 03 45 03 38 03 3F 03 46 03 44 03 4B 03 60 03 4A 03 59 03 72 03 72 03 43 03 4E 03 4A 03 64 03 4E 03 56 03 4A 03 3F 03 4A 03 52 03 52 03 32 03 41 03 46 03 50 03 4F 03 56 03 59 03 54 03 42 03 46 03 44 03 54 03 53 03 3F 03 51 03 50 03 46 03 49 03 42 03 54 03 3B 03 55 03 43 03 41 03 39 03 45 03 59 03 36 03 47 03 54 03 51 03 62 03 54 03 63 03 48 03 58 03 55 03 49 2D 8F
15:50:29.066 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
15:50:29.145 dir=RX prefix=rim: len=188 hex=72 69 6D 3A 00 0F 07 71 02 8D 00 6C FD 46 DC 2C 04 C5 08 95 02 D7 FF D7 FB 71 DD 30 05 7A 09 93 03 01 FF 06 F9 8C DF 0F 05 E4 0A 68 02 D5 FE E5 F8 61 E2 9B 06 2D 0B 57 02 A6 FF BC F8 59 E6 CD 06 78 0C 76 02 0C 00 AF F9 93 EA D0 06 B0 0D A1 01 29 01 77 FB B8 ED E4 06 D2 0E 92 00 3F 01 84 FE 58 EF 30 06 AA 10 0C FE D3 FF F9 00 E8 F0 19 06 AD 11 FB FD 31 FE 0C 02 BB F0 49 05 C6 11 E0 FD 0D FC 0D 03 39 EF 8A 03 CC 0F 86 FE 6D FB 2B 02 46 EE 3A 02 26 0B 76 00 FA FD 9D 00 C0 EB 94 02 20 08 26 01 CB FF 99 00 97 E6 E4 03 DE 07 98 00 BE FE 48 03 08 E5 FB 06 59 1F 5A
15:50:38.878 dir=RX prefix=reb: len=210 hex=72 65 62 3A 17 00 00 64 08 78 08 AB 08 F8 09 27 08 BE 08 77 07 E2 06 E4 06 D6 06 AC 06 A9 06 73 06 31 05 EE 05 8E 05 42 05 09 04 D1 04 A2 04 57 03 D7 03 96 03 64 03 61 03 63 03 5D 03 5D 03 48 03 3E 03 50 03 44 03 44 03 3D 03 3E 03 3A 03 4E 03 3D 03 49 03 50 03 3A 03 51 03 3C 03 44 03 4B 03 3C 03 26 03 30 03 5E 03 45 03 39 03 4A 03 4C 03 2A 03 42 03 3C 03 3C 03 38 03 34 03 48 03 4A 03 43 03 38 03 42 03 39 03 37 03 44 03 4E 03 35 03 47 03 3A 03 48 03 45 03 65 03 47 03 58 03 4B 03 34 03 50 03 3F 03 59 03 52 03 43 03 45 03 3C 03 30 03 40 03 57 03 4B 03 48 03 40 03 44 03 45 03 4D 03 2F 03 44 03 48 03 4D 03 3B 03 3E 03 51 35 A5
15:50:38.894 dir=RX prefix=reb: len=210 hex=72 65 62 3A 17 01 00 64 08 86 07 56 07 3C 06 D0 06 92 06 A8 06 1A 05 BE 05 38 04 58 04 52 04 10 03 AA 03 67 03 49 03 5E 03 3B 03 49 03 63 03 49 03 50 03 4F 03 5C 03 43 03 44 03 3E 03 43 03 38 03 4F 03 48 03 44 03 46 03 53 03 3E 03 4E 03 46 03 47 03 59 03 4C 03 4B 03 37 03 4D 03 48 03 44 03 3C 03 2B 03 40 03 4D 03 36 03 49 03 33 03 36 03 4C 03 34 03 4E 03 44 03 48 03 4A 03 45 03 35 03 46 03 3B 03 4A 03 42 03 40 03 46 03 50 03 4C 03 5B 03 3B 03 31 03 55 03 2E 03 46 03 38 03 35 03 2B 03 53 03 50 03 58 03 3A 03 42 03 30 03 45 03 36 03 45 03 3A 03 47 03 45 03 3D 03 58 03 4C 03 3A 03 27 03 47 03 35 03 41 03 4F 03 4D 03 3D 89 66
15:50:38.939 dir=RX prefix=reb: len=210 hex=72 65 62 3A 17 02 00 64 08 D1 07 9E 06 E6 06 E2 06 D8 05 9B 05 CB 05 CC 06 4E 04 E9 04 92 04 55 04 05 03 A1 03 78 03 58 03 43 03 4D 03 4B 03 4D 03 24 03 6C 03 7D 03 71 03 7C 03 6C 03 83 03 75 03 7B 03 8E 03 84 03 82 03 75 03 79 03 82 03 89 03 70 03 87 03 76 03 7D 03 7B 03 6F 03 87 03 82 03 90 03 7E 03 90 03 80 03 79 03 85 03 7C 03 82 03 7C 03 75 03 86 03 81 03 85 03 8A 03 7A 03 77 03 5C 03 44 03 41 03 47 03 4A 03 54 03 4C 03 3F 03 3C 03 4D 03 33 03 40 03 62 03 41 03 3F 03 45 03 15 03 47 03 4A 03 48 03 23 03 57 03 46 03 42 03 49 03 3D 03 44 03 42 03 41 03 31 03 56 03 55 03 69 03 52 03 43 03 38 03 4F 03 42 03 4C 03 51 04 4C
15:50:38.969 dir=RX prefix=reb: len=210 hex=72 65 62 3A 17 03 00 64 09 31 08 DB 07 BF 07 1F 06 EC 06 2D 05 C0 06 0F 05 F2 05 95 04 C7 03 EC 04 93 03 A1 03 5B 03 79 03 68 03 4B 03 42 03 53 03 31 03 54 03 3C 03 4A 03 40 03 4B 03 5F 03 38 03 4C 03 36 03 4B 03 2C 03 38 03 46 03 57 03 54 03 47 03 33 03 47 03 36 03 44 03 46 03 59 03 48 03 45 03 41 03 42 03 51 03 41 03 40 03 47 03 49 03 36 03 4E 03 34 03 5E 03 40 03 49 03 28 03 3E 03 49 03 4F 03 3C 03 3C 03 42 03 47 03 49 03 3F 03 4D 03 41 03 39 03 4E 03 40 03 55 03 38 03 35 03 4F 03 51 03 44 03 43 03 45 03 4A 03 46 03 4A 03 44 03 26 03 49 03 3C 03 25 03 51 03 47 03 30 03 56 03 44 03 43 03 49 03 41 03 3E 03 44 03 3F B0 79
15:50:38.999 dir=RX prefix=reb: len=210 hex=72 65 62 3A 17 04 00 64 07 26 06 DF 06 8E 05 C2 05 BF 05 B8 05 2A 05 67 05 4A 04 C9 04 17 03 D7 03 78 03 63 03 43 03 57 03 3F 03 5E 03 56 03 3E 03 3D 03 4F 03 46 03 3D 03 69 03 46 03 40 03 5B 03 4A 03 40 03 4B 03 42 03 5E 03 46 03 41 03 3D 03 4B 03 3E 03 42 03 52 03 3E 03 4A 03 40 03 44 03 3D 03 60 03 49 03 46 03 41 03 48 03 2D 03 43 03 56 03 36 03 55 03 3B 03 4A 03 5A 03 53 03 52 03 55 03 3F 03 47 03 3E 03 4E 03 54 03 4B 03 53 03 39 03 4C 03 48 03 48 03 49 03 49 03 3A 03 3F 03 53 03 49 03 57 03 56 03 44 03 33 03 46 03 41 03 48 03 48 03 43 03 3D 03 43 03 86 03 7F 03 78 03 8B 03 80 03 9A 03 A6 03 97 03 82 03 78 03 87 8D B4
15:50:39.030 dir=RX prefix=reb: len=210 hex=72 65 62 3A 17 05 00 64 07 8C 06 84 06 DA 06 50 06 03 05 E8 05 5B 05 97 05 65 04 AC 04 65 03 8F 03 7C 03 66 03 CD 03 6C 03 4B 03 5C 03 65 03 4E 03 55 03 55 03 3E 03 4E 03 4D 03 42 03 40 03 51 03 52 03 6F 03 5D 03 3A 03 55 03 5F 03 54 03 57 03 5A 03 4B 03 5F 03 52 03 49 03 4E 03 64 03 52 03 5C 03 60 03 43 03 5C 03 5C 03 62 03 4F 03 60 03 30 03 46 03 45 03 24 03 52 03 5F 03 5E 03 5E 03 55 03 4C 03 3C 03 42 03 60 03 48 03 51 03 5C 03 60 03 3C 03 3E 03 4A 03 3E 03 43 03 40 03 40 03 50 03 4C 03 5C 03 54 03 51 03 51 03 47 03 5D 03 4E 03 54 03 4A 03 55 03 65 03 5C 03 5C 03 48 03 4F 03 57 03 59 03 4B 03 5F 03 55 03 52 03 43 86 73
15:50:39.057 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
15:50:39.149 dir=RX prefix=rim: len=188 hex=72 69 6D 3A 00 0F 00 6A 00 10 10 27 FF F9 00 00 00 04 00 69 00 0A 10 23 FF F9 00 00 00 05 00 6C 00 0A 10 20 FF F9 00 00 00 05 00 69 00 0C 10 22 FF F9 00 01 00 04 00 67 00 0B 10 27 FF F9 00 01 00 05 00 69 00 0C 10 27 FF FA 00 01 00 05 00 68 00 0B 10 25 FF F9 00 00 00 05 00 6A 00 0D 10 24 FF F9 00 00 00 04 00 6C 00 0B 10 25 FF F9 00 01 00 04 00 6B 00 0D 10 24 FF FA 00 01 00 05 00 6B 00 0D 10 22 FF FA 00 00 00 05 00 6A 00 0D 10 22 FF F9 00 00 00 04 00 6B 00 0E 10 24 FF F9 FF FF 00 04 00 6A 00 0F 10 21 FF F9 00 01 00 04 00 6B 00 0E 10 25 FF F9 00 01 00 05 22 D6
15:50:39.509 dir=RX prefix=reb: len=210 hex=72 65 62 3A 18 00 00 64 08 77 08 AD 08 F8 09 27 08 BF 08 78 07 E7 06 E4 06 D5 06 A9 06 A7 06 74 06 32 05 F5 05 8F 05 42 05 15 04 D1 04 A1 04 4D 03 D9 03 84 03 70 03 67 03 46 03 4D 03 57 03 4C 03 4C 03 40 03 4C 03 3A 03 55 03 4C 03 38 03 4B 03 3A 03 3B 03 3B 03 3E 03 3F 03 43 03 45 03 37 03 36 03 42 03 33 03 28 03 46 03 3E 03 43 03 40 03 4D 03 27 03 3A 03 34 03 48 03 38 03 42 03 44 03 48 03 30 03 32 03 45 03 47 03 3F 03 53 03 59 03 50 03 41 03 3D 03 4A 03 41 03 36 03 3E 03 3D 03 4E 03 3F 03 46 03 46 03 40 03 2E 03 42 03 45 03 5C 03 4B 03 44 03 33 03 44 03 3F 03 3E 03 41 03 3B 03 40 03 3D 03 3C 03 3D 03 38 03 49 03 5D 19 6C
15:50:39.538 dir=RX prefix=reb: len=210 hex=72 65 62 3A 18 01 00 64 08 87 07 53 07 3D 06 CA 06 98 06 A5 06 08 05 C4 05 41 04 5E 04 4E 04 05 03 A0 03 7C 03 63 03 50 03 45 03 47 03 4D 03 30 03 42 03 2D 03 3E 03 3D 03 40 03 3F 03 39 03 30 03 38 03 40 03 43 03 3A 03 36 03 52 03 30 03 43 03 50 03 36 03 2D 03 48 03 40 03 40 03 2E 03 37 03 3F 03 42 03 4A 03 45 03 3F 03 3C 03 39 03 4B 03 51 03 50 03 58 03 37 03 48 03 50 03 54 03 4B 03 55 03 56 03 47 03 3C 03 3A 03 45 03 40 03 6B 03 48 03 4B 03 2F 03 35 03 4B 03 4B 03 40 03 4A 03 69 03 54 03 3B 03 23 03 39 03 4A 03 4A 03 43 03 50 03 4D 03 42 03 35 03 41 03 55 03 3B 03 32 03 4F 03 4B 03 51 03 26 03 36 03 5A 03 46 03 40 75 FB
15:50:39.568 dir=RX prefix=reb: len=210 hex=72 65 62 3A 18 02 00 64 08 40 07 32 06 7D 06 70 06 82 05 5E 05 5D 05 7F 06 05 04 CA 04 84 04 26 03 DC 03 8C 03 68 03 43 03 4D 03 4A 03 4C 03 3E 03 4D 03 46 03 54 03 30 03 45 03 22 03 50 03 37 03 32 03 4C 03 3D 03 4D 03 47 03 3C 03 4D 03 3F 03 34 03 52 03 2D 03 42 03 47 03 43 03 46 03 46 03 3B 03 81 03 80 03 86 03 7D 03 7A 03 79 03 95 03 93 03 6C 03 85 03 78 03 79 03 88 03 74 03 8A 03 94 03 85 03 82 03 77 03 75 03 80 03 7F 03 86 03 8F 03 78 03 79 03 88 03 85 03 77 03 5D 03 6D 03 82 03 7F 03 85 03 7E 03 5F 03 80 03 6B 03 3D 03 44 03 3E 03 55 03 4F 03 3B 03 38 03 57 03 37 03 50 03 54 03 40 03 2E 03 45 03 5A 03 41 03 5A A8 87
15:50:39.599 dir=RX prefix=reb: len=210 hex=72 65 62 3A 18 03 00 64 09 30 08 DE 07 C1 07 25 06 EB 06 2E 05 BC 06 15 05 EA 05 9D 04 D4 03 DD 04 99 03 9F 03 71 03 69 03 5D 03 4B 03 54 03 3B 03 46 03 4B 03 44 03 3B 03 3A 03 3E 03 52 03 43 03 49 03 39 03 51 03 49 03 40 03 39 03 40 03 49 03 49 03 4D 03 46 03 31 03 4A 03 48 03 3B 03 3F 03 39 03 4C 03 5A 03 4E 03 54 03 4D 03 4B 03 4B 03 3C 03 4F 03 47 03 1F 03 52 03 33 03 3E 03 39 03 23 03 51 03 3A 03 51 03 4A 03 33 03 47 03 25 03 57 03 3E 03 3D 03 39 03 51 03 45 03 2C 03 3C 03 37 03 4E 03 3A 03 4B 03 50 03 45 03 37 03 45 03 3B 03 4D 03 39 03 38 03 37 03 40 03 38 03 3D 03 2D 03 3E 03 48 03 43 03 3D 03 56 03 4B 03 58 FE 0F
15:50:39.629 dir=RX prefix=reb: len=210 hex=72 65 62 3A 18 04 00 64 07 43 07 10 06 9F 05 D4 05 C9 05 BE 05 3B 05 6B 05 62 04 B6 03 FB 03 CD 03 70 03 50 03 56 03 51 03 45 03 61 03 5A 03 47 03 50 03 4F 03 3B 03 36 03 39 03 3E 03 46 03 59 03 47 03 4D 03 56 03 4A 03 3E 03 3A 03 2E 03 41 03 53 03 37 03 46 03 4D 03 53 03 59 03 48 03 3F 03 43 03 28 03 31 03 49 03 51 03 51 03 43 03 3D 03 43 03 53 03 4E 03 42 03 59 03 46 03 52 03 58 03 40 03 5A 03 3E 03 48 03 46 03 3A 03 3F 03 49 03 50 03 5B 03 3F 03 46 03 3D 03 4E 03 4B 03 3C 03 41 03 4D 03 50 03 42 03 47 03 3C 03 3C 03 36 03 45 03 56 03 45 03 43 03 54 03 5D 03 4D 03 3A 03 59 03 3F 03 49 03 4A 03 8D 03 A2 03 A7 03 83 8D 96
15:50:39.658 dir=RX prefix=reb: len=210 hex=72 65 62 3A 18 05 00 64 07 87 06 87 06 D9 06 54 06 05 05 E8 05 66 05 8E 05 6A 04 A6 04 5B 03 94 03 80 03 6E 03 CC 03 6F 03 61 03 62 03 5A 03 4E 03 4B 03 54 03 5C 03 6B 03 41 03 49 03 44 03 58 03 49 03 3C 03 59 03 5B 03 37 03 55 03 45 03 55 03 30 03 4B 03 40 03 54 03 57 03 5B 03 4F 03 48 03 38 03 5B 03 3C 03 69 03 46 03 59 03 65 03 55 03 4B 03 58 03 35 03 4C 03 63 03 3E 03 53 03 58 03 58 03 61 03 53 03 44 03 49 03 58 03 4B 03 51 03 4C 03 5C 03 50 03 4B 03 43 03 37 03 54 03 56 03 53 03 41 03 4F 03 5C 03 63 03 5E 03 5C 03 33 03 33 03 46 03 53 03 5B 03 50 03 66 03 66 03 4B 03 46 03 45 03 48 03 56 03 53 03 59 03 55 03 52 B7 52
15:50:39.687 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
15:50:40.182 dir=RX prefix=rls: len=8 hex=72 6C 73 3A 00 04 72 C9
15:50:40.453 dir=RX prefix=reb: len=210 hex=72 65 62 3A 19 00 00 64 08 7F 08 AF 08 F6 09 27 08 BF 08 79 07 F1 06 E1 06 D6 06 A3 06 A1 06 71 06 30 05 F1 05 93 05 49 05 14 04 C8 04 9C 04 3A 03 E6 03 76 03 63 03 4F 03 58 03 3B 03 3B 03 42 03 45 03 3B 03 3F 03 57 03 3F 03 4E 03 32 03 44 03 35 03 4C 03 40 03 3A 03 3B 03 34 03 3D 03 41 03 30 03 48 03 33 03 45 03 46 03 4C 03 38 03 4D 03 46 03 40 03 34 03 39 03 3D 03 33 03 53 03 49 03 50 03 4C 03 28 03 34 03 3A 03 39 03 4D 03 52 03 40 03 49 03 30 03 5A 03 46 03 3F 03 29 03 5A 03 2D 03 44 03 52 03 23 03 40 03 3B 03 3E 03 2C 03 5A 03 49 03 53 03 48 03 47 03 4B 03 5E 03 43 03 3B 03 42 03 55 03 3E 03 3F 03 29 03 39 03 3A 18 21
15:50:40.483 dir=RX prefix=reb: len=210 hex=72 65 62 3A 19 01 00 64 08 85 07 51 07 3C 06 C9 06 95 06 9D 06 11 05 BC 05 43 04 6E 04 3E 04 08 03 9B 03 77 03 4B 03 5E 03 45 03 47 03 4F 03 37 03 31 03 63 03 5D 03 43 03 3D 03 38 03 45 03 44 03 26 03 5A 03 42 03 3D 03 37 03 3F 03 44 03 42 03 51 03 45 03 46 03 3E 03 5B 03 47 03 53 03 35 03 52 03 46 03 45 03 4A 03 44 03 4C 03 49 03 3E 03 38 03 3C 03 48 03 37 03 54 03 32 03 41 03 35 03 34 03 43 03 30 03 47 03 30 03 42 03 34 03 53 03 49 03 41 03 3A 03 39 03 37 03 41 03 42 03 46 03 48 03 4A 03 4C 03 3E 03 41 03 33 03 57 03 39 03 4B 03 46 03 47 03 5B 03 4D 03 3A 03 36 03 31 03 46 03 42 03 30 03 3B 03 52 03 3E 03 4E 03 4C 6E 57
15:50:40.515 dir=RX prefix=reb: len=210 hex=72 65 62 3A 19 02 00 64 08 D5 07 A9 06 E1 06 D1 06 E1 05 8D 05 A3 05 D3 06 55 04 DF 04 78 04 21 03 E3 03 96 03 6B 03 4A 03 45 03 4D 03 4D 03 41 03 42 03 56 03 4C 03 3F 03 4E 03 41 03 2C 03 4F 03 3E 03 52 03 31 03 51 03 42 03 48 03 4C 03 44 03 3D 03 2C 03 64 03 3E 03 46 03 72 03 6B 03 6A 03 90 03 6E 03 77 03 7A 03 66 03 6D 03 7F 03 81 03 79 03 84 03 7B 03 7F 03 8B 03 87 03 75 03 74 03 81 03 62 03 6D 03 8C 03 77 03 70 03 63 03 6F 03 6B 03 6C 03 7D 03 69 03 7F 03 84 03 7A 03 7C 03 69 03 87 03 7D 03 82 03 5A 03 4D 03 3B 03 5C 03 50 03 48 03 51 03 3F 03 37 03 53 03 43 03 54 03 48 03 45 03 41 03 2E 03 43 03 2B 03 48 03 4C 45 24
15:50:40.543 dir=RX prefix=reb: len=210 hex=72 65 62 3A 19 03 00 64 09 34 08 DA 07 BE 07 20 06 EF 06 31 05 CA 06 11 05 E4 05 9C 04 C8 03 DE 04 9E 03 B9 03 60 03 7C 03 71 03 49 03 4C 03 43 03 47 03 50 03 50 03 40 03 36 03 43 03 58 03 39 03 40 03 47 03 3E 03 50 03 49 03 44 03 32 03 46 03 54 03 3D 03 34 03 3E 03 4A 03 28 03 41 03 4D 03 51 03 48 03 44 03 45 03 4F 03 4B 03 3B 03 44 03 3A 03 49 03 3B 03 42 03 3E 03 4A 03 44 03 39 03 4B 03 44 03 35 03 42 03 44 03 3B 03 36 03 56 03 38 03 47 03 5B 03 43 03 3C 03 5B 03 3A 03 40 03 44 03 38 03 49 03 40 03 40 03 4D 03 38 03 38 03 47 03 44 03 4C 03 3E 03 3E 03 4F 03 46 03 4A 03 4A 03 43 03 3A 03 38 03 41 03 30 03 57 03 46 3C A0
15:50:40.573 dir=RX prefix=reb: len=210 hex=72 65 62 3A 19 04 00 64 07 41 06 E9 06 9C 05 CE 05 C5 05 BD 05 3A 05 52 05 6C 04 C3 04 0B 03 CC 03 78 03 4D 03 6F 03 44 03 4C 03 46 03 49 03 4C 03 51 03 4B 03 56 03 47 03 43 03 3D 03 46 03 42 03 4C 03 41 03 45 03 57 03 54 03 4A 03 41 03 40 03 2E 03 45 03 47 03 47 03 52 03 3C 03 4F 03 4C 03 4E 03 4C 03 42 03 3F 03 52 03 2F 03 49 03 50 03 3D 03 3C 03 36 03 43 03 39 03 48 03 4C 03 33 03 46 03 48 03 46 03 40 03 49 03 57 03 4A 03 2D 03 46 03 3C 03 2F 03 39 03 37 03 5B 03 41 03 4E 03 57 03 43 03 28 03 56 03 5D 03 44 03 4D 03 49 03 50 03 3F 03 5A 03 4D 03 6B 03 52 03 4A 03 47 03 65 03 47 03 44 03 89 03 7A 03 72 03 69 03 A0 41 9E
15:50:40.603 dir=RX prefix=reb: len=210 hex=72 65 62 3A 19 05 00 64 07 86 06 85 06 DB 06 4F 06 0D 05 EC 05 4A 05 86 05 6B 04 BA 04 62 03 7A 03 84 03 6C 03 DE 03 5C 03 44 03 38 03 68 03 54 03 55 03 63 03 54 03 40 03 47 03 51 03 46 03 48 03 5D 03 50 03 60 03 56 03 39 03 54 03 45 03 4A 03 4B 03 51 03 55 03 63 03 52 03 50 03 48 03 54 03 41 03 39 03 52 03 5E 03 54 03 58 03 53 03 50 03 52 03 51 03 48 03 40 03 51 03 53 03 4C 03 6D 03 46 03 5A 03 50 03 24 03 30 03 31 03 43 03 4D 03 5B 03 55 03 65 03 5C 03 42 03 56 03 39 03 41 03 54 03 58 03 59 03 54 03 52 03 5F 03 54 03 53 03 51 03 44 03 4A 03 4F 03 57 03 4B 03 52 03 48 03 58 03 4F 03 4E 03 40 03 49 03 5E 03 48 03 5A AF 6C
15:50:40.633 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
15:50:41.023 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1A 00 00 64 08 80 08 AF 08 F4 09 27 08 BE 08 77 07 F4 06 E1 06 D2 06 A1 06 9F 06 72 06 32 05 F5 05 92 05 47 05 12 04 C8 04 A3 04 50 03 E7 03 94 03 64 03 72 03 5A 03 48 03 3E 03 49 03 4A 03 41 03 4C 03 49 03 42 03 54 03 47 03 3A 03 3C 03 49 03 45 03 41 03 44 03 49 03 30 03 4F 03 2B 03 45 03 4E 03 40 03 3F 03 54 03 39 03 31 03 34 03 41 03 3D 03 3F 03 4C 03 4E 03 44 03 57 03 40 03 43 03 50 03 3B 03 38 03 36 03 45 03 45 03 46 03 3C 03 4E 03 46 03 4F 03 35 03 3A 03 47 03 48 03 48 03 38 03 27 03 3A 03 3E 03 3B 03 37 03 37 03 5D 03 40 03 40 03 43 03 44 03 33 03 2C 03 4C 03 52 03 47 03 50 03 46 03 2E 03 3F 03 49 0F 72
15:50:41.053 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1A 01 00 64 08 84 07 53 07 39 06 CC 06 95 06 AC 06 0A 05 C6 05 44 04 6B 04 47 04 0A 03 9A 03 80 03 56 03 5F 03 3D 03 62 03 61 03 46 03 47 03 37 03 6E 03 36 03 55 03 53 03 56 03 53 03 39 03 38 03 3B 03 3A 03 4E 03 47 03 49 03 2A 03 48 03 4A 03 40 03 5B 03 37 03 40 03 4B 03 47 03 47 03 35 03 41 03 5D 03 31 03 38 03 2C 03 49 03 4C 03 53 03 44 03 3E 03 56 03 49 03 4A 03 38 03 3D 03 36 03 50 03 3F 03 39 03 37 03 53 03 37 03 5F 03 48 03 56 03 4D 03 41 03 39 03 36 03 55 03 4B 03 41 03 32 03 41 03 56 03 3A 03 52 03 47 03 48 03 3C 03 4D 03 46 03 48 03 4B 03 56 03 3A 03 33 03 50 03 38 03 5F 03 4C 03 46 03 3F 03 39 6E D9
15:50:41.084 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1A 02 00 64 08 D2 07 9E 06 E2 06 E5 06 DA 05 8E 05 B3 05 D5 06 56 05 0A 04 A9 04 61 04 14 03 BB 03 9A 03 8A 03 89 03 75 03 7B 03 75 03 6D 03 74 03 70 03 78 03 6A 03 72 03 67 03 7E 03 7F 03 7B 03 70 03 79 03 76 03 7E 03 6E 03 8B 03 76 03 6F 03 8A 03 70 03 76 03 74 03 85 03 7F 03 72 03 76 03 78 03 7D 03 58 03 35 03 3C 03 43 03 4E 03 37 03 3A 03 5B 03 51 03 49 03 56 03 41 03 4F 03 38 03 3C 03 4F 03 4E 03 51 03 4B 03 3C 03 45 03 42 03 44 03 37 03 42 03 37 03 43 03 47 03 3F 03 5C 03 39 03 42 03 3F 03 46 03 4D 03 63 03 5C 03 60 03 42 03 39 03 55 03 4A 03 50 03 4D 03 3E 03 61 03 2E 03 45 03 3E 03 35 03 60 03 46 71 3E
15:50:41.114 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1A 03 00 64 09 34 08 D5 07 B8 07 1E 06 EE 06 2F 05 C8 06 14 05 F2 05 9D 04 E5 03 D4 04 8D 03 AD 03 85 03 72 03 4F 03 67 03 42 03 4E 03 53 03 3F 03 58 03 56 03 4D 03 51 03 54 03 50 03 66 03 4A 03 36 03 39 03 4E 03 3E 03 46 03 3C 03 40 03 4B 03 35 03 32 03 39 03 3B 03 41 03 3E 03 49 03 55 03 54 03 50 03 38 03 46 03 41 03 3D 03 45 03 46 03 4D 03 44 03 3F 03 45 03 53 03 3E 03 42 03 48 03 2D 03 36 03 41 03 4F 03 4C 03 50 03 3E 03 47 03 37 03 31 03 57 03 58 03 41 03 44 03 3E 03 46 03 3F 03 45 03 4A 03 5A 03 3F 03 41 03 53 03 30 03 48 03 3D 03 67 03 45 03 4A 03 44 03 40 03 3B 03 52 03 4D 03 47 03 38 03 58 03 46 66 9E
15:50:41.143 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1A 04 00 64 07 49 07 0C 06 C1 05 D4 05 FE 05 EE 05 5B 05 AB 05 A9 04 E8 04 12 03 B1 03 78 03 4A 03 4B 03 45 03 34 03 4C 03 4E 03 5E 03 29 03 58 03 4F 03 42 03 40 03 34 03 55 03 4F 03 40 03 44 03 57 03 38 03 3B 03 51 03 4F 03 30 03 53 03 45 03 61 03 4A 03 49 03 4B 03 48 03 3D 03 59 03 42 03 48 03 31 03 50 03 52 03 50 03 51 03 54 03 36 03 44 03 52 03 4F 03 3D 03 77 03 8C 03 72 03 7B 03 73 03 78 03 86 03 63 03 87 03 79 03 75 03 7F 03 79 03 85 03 78 03 6C 03 6A 03 7C 03 82 03 8A 03 88 03 78 03 52 03 7D 03 84 03 75 03 82 03 6E 03 78 03 7D 03 82 03 82 03 8E 03 8B 03 8C 03 71 03 76 03 74 03 71 03 46 03 52 03 3A F2 0A
15:50:41.173 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1A 05 00 64 07 8D 06 2C 06 81 06 0A 05 BF 05 AB 05 1E 05 47 05 2F 04 87 04 46 03 7F 03 8A 03 55 03 B7 03 66 03 5D 03 61 03 49 03 4C 03 4A 03 64 03 41 03 3E 03 28 03 57 03 35 03 40 03 4E 03 60 03 60 03 28 03 3B 03 3C 03 38 03 47 03 45 03 47 03 5B 03 67 03 66 03 51 03 5E 03 3E 03 34 03 4C 03 34 03 42 03 75 03 5C 03 4F 03 42 03 51 03 49 03 56 03 58 03 40 03 41 03 5E 03 54 03 64 03 4F 03 4E 03 4C 03 43 03 40 03 62 03 52 03 57 03 6E 03 45 03 57 03 4A 03 43 03 4C 03 3F 03 5C 03 6F 03 57 03 40 03 55 03 5A 03 49 03 42 03 35 03 48 03 4D 03 59 03 53 03 51 03 5B 03 52 03 3A 03 43 03 57 03 5B 03 50 03 69 03 70 03 63 65 B3
15:50:41.201 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
15:50:41.625 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1B 00 00 64 08 7A 08 B0 08 FA 09 26 08 BF 08 75 07 DE 06 E4 06 D5 06 AB 06 A6 06 72 06 31 05 EE 05 8E 05 46 05 14 04 CB 04 99 04 4A 03 F2 03 8F 03 73 03 5A 03 44 03 49 03 50 03 51 03 44 03 39 03 4E 03 4A 03 46 03 42 03 4E 03 55 03 48 03 3D 03 37 03 3C 03 30 03 2F 03 40 03 4C 03 44 03 3B 03 42 03 43 03 63 03 5A 03 37 03 4B 03 53 03 39 03 42 03 4A 03 45 03 55 03 58 03 45 03 38 03 49 03 3A 03 43 03 4E 03 53 03 3A 03 4B 03 47 03 4F 03 45 03 37 03 30 03 2A 03 4B 03 29 03 2A 03 3A 03 45 03 40 03 68 03 45 03 39 03 45 03 54 03 3A 03 41 03 3C 03 4F 03 4D 03 3E 03 51 03 41 03 40 03 55 03 33 03 34 03 3E 03 4D 03 41 F7 0B
15:50:41.664 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1B 01 00 64 08 80 07 4F 07 3C 06 CA 06 95 06 A2 06 15 05 BA 05 45 04 83 04 4C 04 0B 03 88 03 85 03 62 03 5C 03 3B 03 4A 03 4A 03 37 03 4C 03 38 03 38 03 46 03 34 03 23 03 37 03 43 03 3B 03 47 03 39 03 2E 03 49 03 37 03 3F 03 49 03 33 03 30 03 52 03 4D 03 6B 03 4F 03 40 03 40 03 4E 03 4D 03 3C 03 56 03 3C 03 3C 03 4B 03 41 03 48 03 43 03 27 03 43 03 49 03 2B 03 3C 03 3C 03 40 03 46 03 3E 03 44 03 42 03 40 03 5A 03 37 03 2D 03 4D 03 2A 03 51 03 28 03 43 03 42 03 48 03 59 03 2E 03 40 03 25 03 38 03 3C 03 3C 03 44 03 3A 03 27 03 45 03 28 03 4D 03 3E 03 3B 03 4D 03 42 03 49 03 3F 03 49 03 59 03 23 03 36 03 40 0D 2A
15:50:41.687 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1B 02 00 64 07 B5 06 D5 06 22 06 09 06 25 05 1E 05 20 05 4C 05 B3 04 A4 04 73 04 11 03 D7 03 87 03 58 03 44 03 53 03 33 03 58 03 4A 03 35 03 2B 03 4B 03 3D 03 48 03 45 03 42 03 48 03 67 03 7A 03 78 03 82 03 8C 03 70 03 77 03 6E 03 7C 03 89 03 82 03 78 03 70 03 8C 03 74 03 90 03 6C 03 83 03 8A 03 8B 03 8F 03 8A 03 86 03 8D 03 77 03 80 03 87 03 7F 03 7D 03 7F 03 79 03 86 03 7A 03 7D 03 83 03 73 03 7A 03 7E 03 7F 03 8E 03 52 03 4A 03 41 03 3F 03 53 03 44 03 39 03 37 03 4F 03 3D 03 60 03 2F 03 42 03 45 03 51 03 23 03 36 03 4B 03 3B 03 2F 03 3C 03 56 03 49 03 41 03 40 03 51 03 3B 03 36 03 56 03 47 03 4F 03 4A 94 D8
15:50:41.714 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1B 03 00 64 09 34 08 D9 07 BC 07 1E 06 EB 06 2D 05 BE 06 0B 05 EA 05 9F 04 D4 03 D2 04 96 03 B9 03 5E 03 77 03 73 03 4F 03 41 03 48 03 43 03 3C 03 4F 03 4F 03 54 03 4F 03 53 03 4C 03 34 03 59 03 43 03 35 03 3B 03 48 03 35 03 47 03 35 03 49 03 41 03 62 03 4B 03 37 03 45 03 31 03 3B 03 3E 03 3F 03 4E 03 4C 03 3D 03 4C 03 4F 03 46 03 44 03 43 03 5E 03 47 03 42 03 49 03 47 03 72 03 4F 03 69 03 43 03 4E 03 41 03 47 03 36 03 4E 03 30 03 46 03 54 03 4F 03 4E 03 41 03 3E 03 43 03 42 03 42 03 48 03 47 03 50 03 56 03 38 03 47 03 4D 03 4C 03 4D 03 34 03 43 03 4A 03 4A 03 4A 03 56 03 55 03 53 03 44 03 45 03 5A 03 52 F8 FD
15:50:41.744 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1B 04 00 64 07 3F 07 08 06 C5 05 E1 05 EE 05 F3 05 5D 05 9F 05 8D 04 FA 04 09 03 AB 03 79 03 33 03 40 03 39 03 48 03 52 03 3A 03 60 03 49 03 40 03 4F 03 42 03 2E 03 34 03 43 03 47 03 4E 03 3D 03 3C 03 42 03 3E 03 4E 03 40 03 44 03 62 03 4C 03 40 03 3E 03 45 03 3E 03 4C 03 5A 03 38 03 33 03 35 03 39 03 46 03 51 03 41 03 3D 03 4E 03 54 03 45 03 47 03 58 03 46 03 66 03 51 03 54 03 58 03 2F 03 4B 03 5B 03 50 03 3F 03 45 03 57 03 4C 03 50 03 45 03 4D 03 3C 03 32 03 51 03 3C 03 4D 03 5D 03 41 03 40 03 55 03 86 03 93 03 7E 03 7B 03 88 03 74 03 7F 03 7A 03 82 03 73 03 79 03 91 03 6D 03 86 03 80 03 81 03 7C 03 A8 65 2D
15:50:41.774 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1B 05 00 64 07 8B 06 85 06 D7 06 4D 06 01 05 F2 05 67 05 A1 05 7E 04 A8 04 6D 03 AF 03 AC 03 86 03 D6 03 66 03 56 03 5D 03 59 03 4D 03 6D 03 48 03 3F 03 3C 03 4F 03 43 03 49 03 47 03 48 03 4F 03 53 03 57 03 52 03 71 03 42 03 50 03 44 03 47 03 3D 03 57 03 4B 03 47 03 58 03 5B 03 4A 03 46 03 43 03 51 03 42 03 4F 03 5F 03 4D 03 5E 03 49 03 57 03 3A 03 5A 03 4C 03 2F 03 51 03 6E 03 52 03 49 03 58 03 51 03 41 03 42 03 34 03 54 03 60 03 5E 03 4E 03 5A 03 49 03 55 03 2F 03 35 03 56 03 4E 03 57 03 51 03 67 03 5C 03 55 03 4C 03 3C 03 44 03 57 03 5B 03 50 03 56 03 5A 03 54 03 47 03 3A 03 50 03 2F 03 41 03 4F 03 6A 2A C1
15:50:41.803 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
15:50:42.255 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1C 00 00 64 08 7A 08 B2 08 FC 09 24 08 BC 08 72 07 DB 06 D6 06 D2 06 A9 06 A3 06 6F 06 2B 05 E9 05 8B 05 3B 05 0D 04 BC 04 91 04 4E 03 E4 03 97 03 70 03 69 03 51 03 5C 03 4C 03 32 03 56 03 57 03 42 03 3E 03 45 03 3B 03 3C 03 3B 03 3C 03 38 03 3F 03 26 03 44 03 41 03 37 03 47 03 22 03 45 03 39 03 3F 03 4D 03 4E 03 4B 03 48 03 4F 03 2D 03 35 03 3F 03 25 03 3D 03 47 03 3E 03 43 03 46 03 39 03 31 03 3D 03 40 03 4A 03 50 03 5C 03 4A 03 35 03 49 03 2D 03 4E 03 4B 03 54 03 3D 03 4A 03 45 03 40 03 36 03 43 03 3D 03 3D 03 50 03 4A 03 36 03 51 03 41 03 44 03 49 03 3D 03 4E 03 41 03 45 03 49 03 39 03 3F 03 3B 03 4F A7 E6
15:50:42.283 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1C 01 00 64 08 85 07 51 07 38 06 CC 06 A4 06 AB 06 00 05 C5 05 3C 04 63 04 3E 04 0B 03 8B 03 5C 03 76 03 55 03 31 03 40 03 4E 03 3B 03 3F 03 55 03 50 03 43 03 49 03 4B 03 2B 03 5B 03 45 03 3C 03 3C 03 3B 03 44 03 2A 03 42 03 4A 03 52 03 44 03 4A 03 3F 03 4F 03 3E 03 48 03 42 03 39 03 47 03 3F 03 55 03 34 03 2E 03 49 03 44 03 42 03 53 03 2C 03 4B 03 24 03 31 03 5B 03 3F 03 38 03 36 03 4B 03 44 03 46 03 4A 03 5A 03 48 03 37 03 5B 03 3B 03 38 03 56 03 5D 03 43 03 4D 03 4F 03 4E 03 3D 03 4E 03 44 03 45 03 48 03 47 03 4A 03 44 03 39 03 50 03 43 03 43 03 45 03 46 03 3A 03 43 03 42 03 4F 03 4A 03 54 03 3D 03 39 8A 8B
15:50:42.315 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1C 02 00 64 08 43 07 38 06 7E 06 80 06 7A 05 6E 05 6E 05 83 05 FA 04 C8 04 5F 04 3D 04 02 03 9D 03 68 03 5D 03 4A 03 45 03 4F 03 46 03 48 03 49 03 57 03 90 03 80 03 83 03 7C 03 6F 03 75 03 7E 03 7A 03 70 03 7F 03 72 03 7E 03 7B 03 93 03 89 03 64 03 74 03 7B 03 78 03 7A 03 6E 03 5F 03 86 03 8C 03 73 03 83 03 7E 03 83 03 89 03 8D 03 6F 03 7F 03 6E 03 79 03 7E 03 79 03 81 03 81 03 6B 03 46 03 44 03 55 03 39 03 3F 03 41 03 42 03 3B 03 3F 03 59 03 34 03 47 03 43 03 42 03 4A 03 39 03 51 03 49 03 44 03 4A 03 3B 03 4B 03 3B 03 2C 03 48 03 3F 03 42 03 47 03 58 03 3D 03 38 03 3B 03 4B 03 40 03 49 03 3E 03 57 03 48 A7 25
15:50:42.344 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1C 03 00 64 09 34 08 DA 07 BB 07 1C 06 EB 06 28 05 BE 06 14 05 DF 05 A1 04 C5 03 E8 04 96 03 8E 03 60 03 62 03 65 03 44 03 39 03 3F 03 42 03 4C 03 51 03 4F 03 46 03 49 03 4E 03 44 03 37 03 3D 03 3E 03 43 03 44 03 41 03 5C 03 32 03 43 03 3E 03 43 03 47 03 4B 03 5E 03 38 03 3D 03 57 03 49 03 4B 03 4B 03 2F 03 4B 03 3F 03 48 03 30 03 42 03 34 03 39 03 45 03 5C 03 4E 03 3B 03 35 03 39 03 3F 03 4E 03 5C 03 32 03 5F 03 5C 03 43 03 34 03 46 03 35 03 56 03 3A 03 35 03 2B 03 42 03 37 03 3C 03 3D 03 35 03 4E 03 48 03 4C 03 50 03 41 03 39 03 40 03 37 03 2D 03 55 03 3B 03 46 03 42 03 38 03 2E 03 55 03 4A 03 46 03 4E AE 43
15:50:42.373 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1C 04 00 64 07 1A 06 E7 06 9E 05 C1 05 C5 05 AB 05 1E 05 68 05 69 04 C1 04 04 03 C9 03 84 03 42 03 3E 03 35 03 42 03 5B 03 5D 03 4D 03 4E 03 57 03 3C 03 3E 03 4F 03 58 03 5C 03 3E 03 45 03 4A 03 33 03 47 03 54 03 57 03 46 03 40 03 43 03 45 03 59 03 3B 03 49 03 35 03 56 03 4A 03 3F 03 43 03 3A 03 45 03 40 03 42 03 3D 03 33 03 51 03 2F 03 59 03 4D 03 40 03 49 03 59 03 4E 03 35 03 45 03 3F 03 3E 03 3B 03 44 03 4D 03 3D 03 4A 03 62 03 58 03 48 03 3A 03 49 03 46 03 7F 03 93 03 84 03 95 03 84 03 87 03 88 03 70 03 87 03 90 03 93 03 93 03 79 03 80 03 82 03 7E 03 8A 03 84 03 83 03 8D 03 87 03 7A 03 8C 03 9A 03 7F AC B0
15:50:42.403 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1C 05 00 64 07 91 06 70 06 D6 06 56 06 00 05 F5 05 5C 05 82 05 58 04 B1 04 62 03 77 03 7F 03 72 03 D5 03 69 03 52 03 53 03 70 03 4A 03 4A 03 4F 03 40 03 5B 03 43 03 36 03 55 03 58 03 54 03 42 03 5E 03 43 03 4E 03 49 03 42 03 4A 03 49 03 47 03 4B 03 4C 03 4E 03 3C 03 4F 03 52 03 43 03 48 03 49 03 55 03 4F 03 49 03 62 03 55 03 40 03 4A 03 57 03 46 03 43 03 55 03 6B 03 4B 03 3D 03 4E 03 43 03 5F 03 4C 03 49 03 43 03 65 03 51 03 5B 03 52 03 26 03 4D 03 4E 03 50 03 43 03 66 03 61 03 64 03 57 03 4F 03 49 03 56 03 43 03 54 03 3E 03 4F 03 52 03 5A 03 59 03 32 03 51 03 63 03 55 03 3F 03 51 03 51 03 56 03 5D 03 40 EE AC
15:50:42.431 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
15:50:42.794 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1D 00 00 64 08 7B 08 B7 08 FC 09 23 08 BA 08 75 07 E8 06 DA 06 D0 06 A4 06 A2 06 70 06 2C 05 EE 05 90 05 41 05 11 04 C6 04 A1 04 42 03 E5 03 95 03 5F 03 4A 03 4B 03 4A 03 3A 03 4A 03 4E 03 4B 03 51 03 38 03 3A 03 58 03 43 03 46 03 54 03 46 03 48 03 39 03 4A 03 57 03 55 03 27 03 4E 03 38 03 3C 03 31 03 3F 03 36 03 44 03 33 03 57 03 42 03 3A 03 47 03 3B 03 51 03 4E 03 41 03 38 03 31 03 45 03 55 03 48 03 3F 03 37 03 38 03 48 03 35 03 3B 03 4D 03 3C 03 50 03 2F 03 43 03 32 03 32 03 36 03 3C 03 45 03 4C 03 3C 03 43 03 3D 03 3F 03 42 03 3B 03 30 03 33 03 3C 03 4A 03 4B 03 48 03 53 03 45 03 2F 03 46 03 3F 03 23 C8 99
15:50:42.823 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1D 01 00 64 08 85 07 52 07 38 06 C4 06 98 06 A9 06 05 05 C3 05 3A 04 5E 04 58 03 F5 03 8F 03 7B 03 58 03 51 03 4A 03 30 03 5A 03 4F 03 4E 03 3F 03 3B 03 25 03 45 03 51 03 30 03 4D 03 3C 03 49 03 47 03 44 03 40 03 2E 03 56 03 3B 03 37 03 34 03 57 03 54 03 46 03 3C 03 2F 03 42 03 39 03 3B 03 3C 03 5B 03 4F 03 3A 03 36 03 3D 03 4E 03 4B 03 57 03 4D 03 46 03 47 03 5D 03 37 03 20 03 4B 03 52 03 49 03 48 03 49 03 3F 03 48 03 4B 03 44 03 37 03 48 03 42 03 3B 03 39 03 35 03 59 03 49 03 40 03 44 03 2F 03 2B 03 57 03 49 03 3F 03 4B 03 3E 03 3E 03 42 03 3D 03 43 03 38 03 5B 03 46 03 42 03 40 03 2D 03 55 03 39 03 3F FD 5D
15:50:42.854 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1D 02 00 64 08 D2 07 A1 06 7E 06 80 06 82 05 57 05 76 05 8C 05 F7 04 D5 04 88 04 1E 03 ED 03 81 03 5F 03 48 03 67 03 42 03 42 03 53 03 49 03 3A 03 37 03 2F 03 50 03 3E 03 40 03 38 03 38 03 4E 03 38 03 43 03 48 03 44 03 4F 03 82 03 79 03 81 03 69 03 6E 03 8B 03 7D 03 7E 03 86 03 84 03 77 03 7C 03 70 03 94 03 7C 03 82 03 8B 03 73 03 76 03 86 03 8E 03 7C 03 74 03 71 03 89 03 66 03 90 03 93 03 7D 03 7C 03 8C 03 90 03 78 03 81 03 80 03 91 03 89 03 73 03 8B 03 51 03 52 03 35 03 3F 03 49 03 3D 03 41 03 4D 03 4C 03 42 03 59 03 2C 03 55 03 48 03 2B 03 3C 03 56 03 44 03 45 03 52 03 4B 03 47 03 4B 03 3B 03 4B 03 43 5D F7
15:50:42.868 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1D 03 00 64 08 A1 08 4B 07 4D 06 C3 06 8F 05 EE 05 7D 05 D1 05 A3 05 64 04 B7 03 CB 04 89 03 B7 03 62 03 6E 03 5F 03 54 03 46 03 48 03 38 03 41 03 51 03 42 03 4B 03 36 03 41 03 47 03 42 03 4C 03 3E 03 44 03 4F 03 39 03 3C 03 3A 03 54 03 4F 03 3C 03 3F 03 46 03 46 03 48 03 40 03 3F 03 5E 03 4A 03 47 03 50 03 36 03 4E 03 55 03 47 03 43 03 4D 03 39 03 3A 03 38 03 43 03 57 03 45 03 46 03 4A 03 37 03 35 03 4B 03 44 03 4A 03 51 03 45 03 39 03 49 03 56 03 56 03 45 03 37 03 3F 03 42 03 38 03 48 03 40 03 4D 03 37 03 48 03 46 03 45 03 45 03 4E 03 49 03 62 03 39 03 2C 03 4C 03 3F 03 56 03 56 03 35 03 47 03 40 03 5B FA C5
15:50:42.899 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1D 04 00 64 07 3F 07 09 06 B5 05 CB 05 E8 05 EF 05 56 05 A4 05 91 04 FB 04 0C 03 FD 03 8B 03 54 03 43 03 43 03 44 03 5B 03 4E 03 44 03 32 03 50 03 4F 03 3A 03 32 03 3D 03 2E 03 3D 03 42 03 43 03 47 03 49 03 37 03 4F 03 5F 03 4C 03 57 03 3F 03 4F 03 43 03 3E 03 31 03 63 03 57 03 4A 03 44 03 5C 03 59 03 4C 03 51 03 5D 03 37 03 50 03 38 03 3F 03 3E 03 3E 03 49 03 44 03 3D 03 4F 03 48 03 2B 03 5C 03 31 03 3C 03 47 03 4F 03 45 03 35 03 44 03 4A 03 67 03 51 03 3D 03 4C 03 4A 03 44 03 38 03 43 03 4F 03 4E 03 3F 03 4D 03 4E 03 4F 03 41 03 4A 03 4B 03 47 03 53 03 49 03 3D 03 59 03 55 03 64 03 5A 03 3D 03 45 03 39 BF 67
15:50:42.929 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1D 05 00 64 07 88 06 77 06 D7 06 4C 06 02 05 F0 05 40 05 81 05 61 04 C4 04 60 03 6C 03 6F 03 6C 03 E1 03 6F 03 4F 03 49 03 44 03 62 03 54 03 4F 03 46 03 48 03 34 03 36 03 3D 03 39 03 56 03 5E 03 52 03 59 03 4D 03 3A 03 5A 03 48 03 3E 03 48 03 50 03 5F 03 5D 03 5C 03 59 03 42 03 3E 03 47 03 5F 03 51 03 5C 03 4B 03 4E 03 38 03 4F 03 50 03 4A 03 34 03 39 03 46 03 6A 03 62 03 55 03 39 03 43 03 4F 03 43 03 35 03 41 03 40 03 43 03 68 03 50 03 52 03 44 03 4C 03 50 03 46 03 4B 03 52 03 54 03 51 03 55 03 44 03 41 03 40 03 46 03 48 03 4E 03 5B 03 6C 03 4E 03 42 03 42 03 40 03 4A 03 40 03 47 03 4A 03 57 03 5C 03 5E 15 2D
15:50:42.956 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
15:50:43.453 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1E 00 00 64 08 80 08 AE 08 F5 09 26 08 BD 08 76 07 EE 06 D8 06 D4 06 9F 06 A0 06 70 06 31 05 F4 05 8B 05 49 05 10 04 C2 04 9C 04 43 03 D9 03 81 03 6D 03 4F 03 4F 03 57 03 4E 03 52 03 47 03 47 03 39 03 44 03 48 03 41 03 41 03 41 03 34 03 31 03 30 03 36 03 48 03 34 03 4A 03 3D 03 4B 03 40 03 4D 03 3A 03 2F 03 56 03 53 03 48 03 3A 03 49 03 50 03 4B 03 3F 03 46 03 41 03 3F 03 46 03 30 03 67 03 3B 03 45 03 3F 03 4C 03 46 03 2D 03 43 03 25 03 31 03 3E 03 43 03 3A 03 39 03 3A 03 45 03 45 03 53 03 34 03 2F 03 32 03 4C 03 4A 03 35 03 47 03 49 03 3F 03 59 03 52 03 3B 03 47 03 44 03 43 03 41 03 46 03 36 03 31 03 43 F4 F8
15:50:43.484 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1E 01 00 64 08 84 07 4D 07 3B 06 C7 06 A0 06 A1 06 03 05 C6 05 45 04 64 04 36 04 08 03 95 03 88 03 49 03 53 03 40 03 61 03 41 03 57 03 4A 03 4A 03 62 03 2F 03 3F 03 3E 03 3C 03 41 03 28 03 4C 03 30 03 36 03 3E 03 4A 03 64 03 4A 03 35 03 3E 03 30 03 46 03 3D 03 53 03 33 03 39 03 4E 03 38 03 48 03 32 03 48 03 49 03 3F 03 3B 03 4B 03 49 03 50 03 32 03 48 03 4D 03 47 03 4C 03 40 03 40 03 45 03 3F 03 45 03 4F 03 3E 03 56 03 48 03 38 03 43 03 3B 03 5D 03 59 03 3D 03 4A 03 36 03 3D 03 4E 03 3E 03 49 03 4B 03 4A 03 2F 03 3F 03 54 03 44 03 56 03 53 03 43 03 42 03 2E 03 2E 03 49 03 41 03 58 03 3B 03 65 03 37 03 3F 62 31
15:50:43.515 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1E 02 00 64 08 43 07 36 06 7E 06 83 06 7E 05 68 05 72 05 9B 06 02 04 E1 04 7F 04 3B 03 D5 03 93 03 67 03 48 03 5D 03 34 03 42 03 3C 03 41 03 37 03 41 03 61 03 57 03 4B 03 5A 03 49 03 92 03 79 03 80 03 8F 03 6C 03 7F 03 7C 03 85 03 9C 03 86 03 80 03 80 03 76 03 86 03 78 03 82 03 74 03 7F 03 6F 03 8D 03 84 03 8D 03 93 03 8B 03 86 03 7A 03 77 03 7A 03 85 03 83 03 90 03 82 03 8E 03 76 03 81 03 7A 03 A4 03 7F 03 75 03 52 03 35 03 60 03 52 03 4E 03 46 03 3F 03 1E 03 51 03 55 03 4C 03 40 03 39 03 3F 03 4E 03 43 03 33 03 35 03 4F 03 43 03 55 03 42 03 58 03 52 03 44 03 4A 03 4F 03 52 03 47 03 58 03 49 03 49 03 50 A9 80
15:50:43.543 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1E 03 00 64 09 37 08 D5 07 B7 07 1B 06 EC 06 32 05 C9 06 0F 05 EE 05 9A 04 C5 03 BC 04 8E 03 9D 03 6C 03 6C 03 47 03 43 03 4C 03 53 03 61 03 39 03 52 03 43 03 3C 03 39 03 26 03 43 03 39 03 4A 03 53 03 50 03 45 03 2F 03 46 03 2D 03 3C 03 47 03 54 03 5B 03 41 03 3D 03 41 03 5B 03 56 03 4D 03 51 03 4E 03 44 03 38 03 33 03 30 03 53 03 4E 03 3E 03 34 03 46 03 51 03 57 03 4B 03 3A 03 55 03 5C 03 3E 03 4F 03 50 03 44 03 42 03 31 03 4D 03 3D 03 43 03 3C 03 35 03 68 03 28 03 32 03 3E 03 3E 03 4B 03 48 03 51 03 2D 03 3E 03 41 03 49 03 36 03 34 03 4C 03 35 03 4A 03 43 03 40 03 41 03 4E 03 42 03 4E 03 41 03 42 03 45 F0 A2
15:50:43.573 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1E 04 00 64 07 45 07 10 06 BF 05 DA 05 F0 05 EF 05 5A 05 9A 05 8D 04 EA 04 2E 03 AD 03 89 03 3A 03 3D 03 44 03 52 03 5B 03 55 03 53 03 55 03 76 03 50 03 4F 03 4F 03 59 03 4D 03 47 03 40 03 52 03 61 03 59 03 47 03 43 03 46 03 37 03 27 03 3B 03 57 03 45 03 42 03 3D 03 4F 03 46 03 49 03 4C 03 57 03 52 03 4F 03 3D 03 3F 03 52 03 40 03 3A 03 43 03 61 03 50 03 44 03 49 03 44 03 52 03 62 03 50 03 3E 03 49 03 46 03 4D 03 4F 03 3E 03 5E 03 47 03 55 03 44 03 4F 03 50 03 56 03 42 03 5F 03 51 03 51 03 3D 03 48 03 47 03 4B 03 52 03 4D 03 65 03 5B 03 62 03 51 03 59 03 52 03 3C 03 49 03 35 03 37 03 5C 03 6C 03 74 03 5D 5B 80
15:50:43.603 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1E 05 00 64 07 8A 06 72 06 DD 06 54 05 F6 05 F0 05 59 05 7C 05 73 04 A7 04 52 03 7F 03 8F 03 65 03 D2 03 68 03 47 03 58 03 66 03 57 03 61 03 66 03 41 03 42 03 48 03 4C 03 5E 03 63 03 57 03 52 03 69 03 58 03 5C 03 3B 03 54 03 54 03 37 03 46 03 45 03 5D 03 53 03 5F 03 4F 03 51 03 38 03 46 03 54 03 4B 03 5E 03 59 03 46 03 44 03 3F 03 38 03 2E 03 4A 03 51 03 4F 03 50 03 72 03 45 03 52 03 4E 03 3F 03 59 03 3F 03 52 03 58 03 52 03 51 03 56 03 4A 03 51 03 56 03 40 03 4B 03 6A 03 53 03 58 03 4B 03 50 03 42 03 61 03 39 03 5D 03 53 03 4E 03 50 03 60 03 40 03 4B 03 68 03 46 03 5A 03 3A 03 4E 03 53 03 44 03 57 03 52 54 3C
15:50:43.633 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
15:50:43.980 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1F 00 00 64 08 7C 08 BD 08 FE 09 22 08 B7 08 76 07 ED 06 D5 06 CF 06 A0 06 9D 06 6D 06 2B 05 EA 05 86 05 3C 05 06 04 C8 04 A2 04 54 03 F3 03 9D 03 73 03 68 03 46 03 52 03 38 03 59 03 47 03 30 03 4E 03 50 03 44 03 2F 03 3B 03 2B 03 41 03 26 03 31 03 51 03 37 03 36 03 46 03 47 03 49 03 44 03 5F 03 47 03 47 03 4C 03 42 03 46 03 46 03 44 03 3E 03 33 03 50 03 39 03 30 03 38 03 4B 03 41 03 43 03 34 03 4D 03 41 03 69 03 52 03 39 03 2C 03 43 03 4F 03 43 03 43 03 36 03 3A 03 2F 03 49 03 5A 03 37 03 3E 03 46 03 33 03 4E 03 46 03 2E 03 4B 03 39 03 3B 03 26 03 2F 03 35 03 53 03 4B 03 43 03 45 03 43 03 57 03 41 03 37 C2 0D
15:50:44.009 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1F 01 00 64 08 85 07 51 07 3D 06 C7 06 97 06 A7 06 0F 05 BF 05 16 04 59 04 3B 04 0D 03 A0 03 68 03 66 03 51 03 3F 03 49 03 48 03 4C 03 42 03 4B 03 4D 03 5A 03 3F 03 48 03 47 03 26 03 4C 03 3E 03 51 03 3F 03 39 03 4C 03 39 03 42 03 2C 03 4A 03 44 03 33 03 32 03 54 03 38 03 4B 03 3F 03 40 03 52 03 63 03 3E 03 44 03 37 03 3C 03 3B 03 2C 03 4B 03 3F 03 41 03 45 03 44 03 4D 03 49 03 2B 03 34 03 39 03 44 03 40 03 3E 03 43 03 46 03 4B 03 4B 03 4B 03 37 03 46 03 36 03 50 03 3F 03 44 03 34 03 34 03 2B 03 3C 03 48 03 4B 03 36 03 4D 03 3A 03 31 03 48 03 37 03 42 03 4D 03 57 03 36 03 36 03 38 03 4F 03 45 03 4C 03 42 38 CB
15:50:44.039 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1F 02 00 64 08 D6 07 30 06 6D 06 85 06 86 05 64 05 64 05 8D 05 F7 04 D2 04 7A 04 2A 03 EB 03 8C 03 68 03 57 03 4A 03 40 03 41 03 48 03 4F 03 3D 03 3C 03 4F 03 49 03 4C 03 4D 03 48 03 49 03 45 03 39 03 3F 03 40 03 4C 03 85 03 84 03 7B 03 7A 03 86 03 9E 03 80 03 8C 03 81 03 76 03 7C 03 7F 03 83 03 6C 03 85 03 7F 03 7E 03 7F 03 8A 03 79 03 81 03 86 03 87 03 7B 03 8E 03 7F 03 86 03 81 03 82 03 84 03 8F 03 80 03 94 03 8B 03 8B 03 97 03 8C 03 8B 03 74 03 44 03 4A 03 56 03 47 03 53 03 4C 03 52 03 50 03 42 03 3A 03 65 03 3A 03 57 03 52 03 39 03 56 03 3C 03 1A 03 2F 03 42 03 3D 03 3B 03 42 03 25 03 41 03 4B 03 58 A1 AD
15:50:44.069 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1F 03 00 64 09 37 08 D9 07 BD 07 18 06 EB 06 2F 05 C4 06 0C 05 E5 05 A0 04 DF 03 D4 04 98 03 9C 03 7B 03 7A 03 62 03 58 03 46 03 51 03 44 03 4F 03 43 03 52 03 4D 03 4B 03 36 03 44 03 3C 03 48 03 33 03 4A 03 4F 03 45 03 31 03 3C 03 36 03 38 03 3F 03 45 03 3E 03 34 03 42 03 37 03 5B 03 4C 03 48 03 3A 03 53 03 54 03 33 03 2A 03 51 03 67 03 38 03 4E 03 47 03 49 03 20 03 40 03 45 03 45 03 2E 03 41 03 45 03 53 03 4E 03 4B 03 3F 03 38 03 41 03 4B 03 4D 03 43 03 54 03 48 03 59 03 4A 03 36 03 30 03 37 03 50 03 44 03 58 03 4A 03 4F 03 38 03 4E 03 35 03 38 03 43 03 3D 03 41 03 47 03 4E 03 51 03 6D 03 39 03 3D 03 44 DD D4
15:50:44.099 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1F 04 00 64 07 37 07 0B 06 B0 05 C5 05 F2 05 E5 05 5A 05 98 05 8F 04 E9 03 DC 03 CA 03 73 03 55 03 4F 03 44 03 43 03 5A 03 32 03 38 03 3E 03 49 03 41 03 5F 03 50 03 47 03 62 03 48 03 4D 03 58 03 56 03 53 03 57 03 46 03 41 03 2B 03 5A 03 4D 03 45 03 48 03 44 03 59 03 4D 03 43 03 4F 03 51 03 5A 03 52 03 3E 03 51 03 49 03 3F 03 45 03 38 03 56 03 5C 03 4A 03 41 03 52 03 46 03 46 03 47 03 4B 03 3E 03 40 03 51 03 5A 03 4B 03 45 03 41 03 3E 03 3C 03 50 03 4D 03 52 03 4E 03 43 03 4A 03 45 03 4E 03 3B 03 48 03 4D 03 2C 03 3A 03 46 03 46 03 46 03 40 03 5D 03 38 03 3C 03 53 03 3C 03 55 03 48 03 49 03 6C 03 72 03 5D 9C 30
15:50:44.129 dir=RX prefix=reb: len=210 hex=72 65 62 3A 1F 05 00 64 07 90 06 7C 06 D8 06 54 06 07 05 E5 05 67 05 97 05 7A 04 C0 04 39 03 A7 03 AE 03 63 03 CE 03 56 03 4F 03 63 03 66 03 56 03 4B 03 62 03 55 03 54 03 52 03 36 03 3D 03 65 03 34 03 49 03 4D 03 57 03 5A 03 35 03 48 03 41 03 37 03 4D 03 3E 03 40 03 5D 03 46 03 5A 03 5C 03 45 03 4D 03 3C 03 52 03 3F 03 4B 03 62 03 5F 03 51 03 5A 03 3F 03 5E 03 2E 03 50 03 5D 03 5A 03 5E 03 61 03 41 03 4A 03 4E 03 4C 03 55 03 4B 03 59 03 55 03 6D 03 6C 03 51 03 51 03 45 03 3A 03 4B 03 64 03 57 03 56 03 68 03 63 03 4B 03 58 03 2D 03 49 03 49 03 48 03 5C 03 48 03 50 03 44 03 61 03 56 03 2E 03 40 03 3A 03 63 03 41 03 4A AD D9
15:50:44.157 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
15:50:48.826 dir=RX prefix=rsn: len=8 hex=72 73 6E 3A 10 26 A3 8D
15:50:48.901 dir=RX prefix=reb: len=210 hex=72 65 62 3A 20 00 00 64 08 7F 08 B5 08 F9 09 25 08 BB 08 7A 07 F2 06 D5 06 CE 06 9F 06 9B 06 6D 06 2E 05 EC 05 8A 05 44 05 10 04 B8 04 A2 04 3A 03 EA 03 9C 03 83 03 50 03 3C 03 49 03 57 03 51 03 5E 03 42 03 3C 03 3B 03 3D 03 46 03 3B 03 5D 03 48 03 48 03 3B 03 2C 03 42 03 32 03 43 03 40 03 3F 03 47 03 39 03 35 03 37 03 41 03 4E 03 2D 03 4D 03 36 03 47 03 3F 03 44 03 33 03 4C 03 3C 03 53 03 5A 03 3A 03 41 03 40 03 4B 03 53 03 40 03 47 03 4E 03 3D 03 38 03 32 03 42 03 37 03 3F 03 4F 03 2D 03 4A 03 42 03 44 03 3B 03 38 03 35 03 4A 03 4F 03 42 03 50 03 35 03 49 03 4C 03 5C 03 4E 03 48 03 45 03 4C 03 3B 03 54 03 3C 03 45 E8 96
15:50:48.960 dir=RX prefix=reb: len=210 hex=72 65 62 3A 20 01 00 64 08 87 07 50 07 3E 06 CB 06 A5 06 A5 05 F8 05 CF 05 37 04 7D 04 3A 04 23 03 C3 03 71 03 66 03 41 03 55 03 3F 03 39 03 39 03 2E 03 40 03 3C 03 52 03 46 03 4C 03 28 03 45 03 4B 03 47 03 46 03 5C 03 2E 03 4A 03 37 03 48 03 3E 03 2E 03 49 03 4E 03 4B 03 55 03 35 03 3F 03 43 03 56 03 2F 03 3A 03 37 03 35 03 44 03 41 03 32 03 35 03 4F 03 3E 03 3D 03 4C 03 52 03 47 03 40 03 45 03 51 03 4F 03 52 03 47 03 39 03 46 03 49 03 44 03 5C 03 3E 03 36 03 35 03 39 03 40 03 4B 03 34 03 49 03 65 03 4B 03 3E 03 4F 03 3C 03 4D 03 38 03 83 03 7C 03 75 03 7E 03 80 03 73 03 80 03 6F 03 75 03 77 03 75 03 8F 03 8F 03 86 B6 12
15:50:48.997 dir=RX prefix=reb: len=210 hex=72 65 62 3A 20 02 00 64 08 D4 07 A3 06 DD 06 DF 06 D9 05 A0 05 C6 05 CE 06 45 05 01 04 AA 04 3B 03 F1 03 A9 03 6B 03 34 03 55 03 4C 03 5F 03 50 03 3A 03 3F 03 41 03 44 03 56 03 41 03 4E 03 5F 03 3A 03 39 03 38 03 33 03 3C 03 53 03 41 03 34 03 57 03 56 03 60 03 40 03 44 03 34 03 44 03 4B 03 47 03 40 03 5A 03 48 03 4B 03 4C 03 41 03 3B 03 46 03 5A 03 36 03 54 03 3A 03 37 03 42 03 67 03 59 03 53 03 4A 03 46 03 47 03 5A 03 5F 03 45 03 32 03 48 03 3E 03 4C 03 53 03 44 03 47 03 40 03 4F 03 46 03 38 03 44 03 4B 03 54 03 46 03 48 03 4E 03 61 03 3E 03 3E 03 3F 03 42 03 62 03 38 03 36 03 3F 03 2F 03 51 03 49 03 69 03 5F 03 55 19 1C
15:50:49.024 dir=RX prefix=reb: len=210 hex=72 65 62 3A 20 03 00 64 09 35 08 D8 07 BD 07 15 06 E8 06 2C 05 DD 06 08 05 E0 05 96 04 DE 03 E5 04 8E 03 B1 03 73 03 7C 03 6E 03 66 03 3F 03 5B 03 49 03 3A 03 46 03 42 03 3A 03 2C 03 35 03 32 03 39 03 4F 03 4F 03 47 03 33 03 4D 03 3D 03 35 03 42 03 35 03 47 03 57 03 4A 03 35 03 3F 03 4B 03 34 03 50 03 49 03 50 03 26 03 40 03 53 03 5D 03 4D 03 46 03 43 03 3C 03 39 03 49 03 54 03 47 03 52 03 46 03 2E 03 3C 03 38 03 59 03 53 03 40 03 45 03 44 03 34 03 45 03 49 03 49 03 38 03 58 03 48 03 4E 03 54 03 38 03 59 03 35 03 4E 03 33 03 49 03 3A 03 44 03 38 03 4A 03 4C 03 5C 03 4B 03 3D 03 57 03 4A 03 4E 03 42 03 3B 03 3E 03 42 72 B0
15:50:49.049 dir=RX prefix=reb: len=210 hex=72 65 62 3A 20 04 00 64 07 45 07 12 06 A3 05 BE 05 E5 05 DE 05 5A 05 AC 05 A3 04 E8 04 2D 03 C5 03 6E 03 51 03 4C 03 4E 03 58 03 72 03 59 03 5B 03 3E 03 4D 03 60 03 53 03 43 03 47 03 2C 03 3F 03 3A 03 58 03 63 03 40 03 3C 03 50 03 43 03 59 03 49 03 53 03 57 03 39 03 50 03 43 03 62 03 52 03 3C 03 46 03 32 03 51 03 40 03 43 03 4E 03 3A 03 4E 03 2C 03 52 03 38 03 4B 03 49 03 48 03 4E 03 50 03 38 03 43 03 57 03 43 03 4A 03 2D 03 44 03 52 03 56 03 44 03 53 03 35 03 35 03 32 03 65 03 37 03 4B 03 41 03 3B 03 4C 03 43 03 34 03 46 03 45 03 45 03 39 03 3F 03 49 03 47 03 40 03 63 03 45 03 53 03 38 03 3C 03 4F 03 4B 03 46 03 38 16 B8
15:50:49.080 dir=RX prefix=reb: len=210 hex=72 65 62 3A 20 05 00 64 07 95 06 6E 06 D8 06 51 05 FF 05 E9 05 73 05 8A 05 5E 04 AD 04 5A 03 9F 03 8B 03 68 03 CC 03 60 03 50 03 51 03 66 03 5A 03 4B 03 53 03 4B 03 4E 03 4B 03 42 03 4E 03 4C 03 61 03 4E 03 54 03 5A 03 62 03 56 03 4F 03 4C 03 58 03 4F 03 58 03 41 03 43 03 4F 03 30 03 57 03 60 03 39 03 3C 03 5B 03 5F 03 4F 03 57 03 44 03 49 03 40 03 42 03 4D 03 55 03 49 03 52 03 5F 03 50 03 3C 03 48 03 56 03 61 03 4E 03 59 03 49 03 5C 03 45 03 4B 03 49 03 3E 03 7F 03 56 03 52 03 44 03 60 03 51 03 45 03 63 03 50 03 43 03 56 03 57 03 59 03 56 03 63 03 46 03 47 03 4A 03 4A 03 5C 03 53 03 54 03 4A 03 55 03 4A 03 52 03 45 EC 5F
15:50:49.108 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
15:50:49.201 dir=RX prefix=rim: len=188 hex=72 69 6D 3A 00 0F 00 3A 00 1E 10 22 FF F9 00 00 00 05 00 3F 00 1C 10 20 FF F9 00 00 00 05 00 40 00 1B 10 1F FF FA 00 01 00 05 00 3E 00 1E 10 1F FF FA 00 00 00 05 00 41 00 1D 10 20 FF FA 00 00 00 04 00 3F 00 1E 10 20 FF F9 00 01 00 04 00 3E 00 1E 10 20 FF FA 00 01 00 05 00 3B 00 1C 10 1D FF FA 00 00 00 05 00 3E 00 1B 10 1F FF FA 00 00 00 05 00 3E 00 19 10 1F FF FA 00 00 00 05 00 3D 00 19 10 24 FF F9 00 01 00 05 00 3B 00 1B 10 21 FF FA 00 00 00 05 00 3A 00 1C 10 22 FF FA 00 01 00 04 00 3D 00 1C 10 20 FF FA 00 01 00 05 00 41 00 1C 10 1C FF FA 00 01 00 05 6C F9
# stopped 15:50:50.871 — 82 packets
+12
View File
@@ -0,0 +1,12 @@
# RawBleLogger session — started 16:14:00.349
# Format: HH:mm:ss.SSS dir=RX prefix=XXX len=N hex=AA BB ...
16:14:01.077 dir=RX prefix=rfv: len=18 hex=72 66 76 3A 56 42 54 46 57 30 31 32 30 00 00 00 7A 73
16:14:09.373 dir=RX prefix=reb: len=210 hex=72 65 62 3A 09 00 00 64 04 66 04 69 04 74 04 5C 04 5A 04 4D 03 B4 03 56 03 4D 03 59 03 5B 03 4C 03 57 03 42 03 59 03 48 03 54 03 44 03 36 03 2D 03 3F 03 3C 03 3F 03 39 03 4D 03 3A 03 43 03 40 03 3F 03 39 03 4B 03 3D 03 50 03 46 03 40 03 3A 03 55 03 39 03 40 03 33 03 35 03 3C 03 4D 03 4C 03 44 03 2D 03 40 03 39 03 44 03 49 03 3E 03 61 03 40 03 3D 03 56 03 35 03 42 03 43 03 41 03 3E 03 2F 03 45 03 42 03 52 03 54 03 4B 03 26 03 3E 03 65 03 32 03 51 03 52 03 42 03 2E 03 47 03 37 03 3F 03 3A 03 53 03 4C 03 25 03 3D 03 33 03 44 03 56 03 3C 03 4E 03 53 03 43 03 5C 03 37 03 42 03 51 03 45 03 53 03 51 03 5A 03 4A 03 43 03 2B FE 90
16:14:09.406 dir=RX prefix=reb: len=210 hex=72 65 62 3A 09 01 00 64 04 6F 04 84 04 92 04 72 04 62 04 78 03 D1 03 62 03 36 03 4A 03 54 03 42 03 39 03 47 03 50 03 43 03 31 03 2C 03 35 03 41 03 42 03 3C 03 3D 03 46 03 33 03 44 03 43 03 42 03 43 03 58 03 5B 03 41 03 32 03 5D 03 41 03 35 03 2B 03 50 03 2E 03 3D 03 59 03 3A 03 38 03 35 03 5B 03 47 03 37 03 3D 03 40 03 2E 03 3E 03 35 03 45 03 4C 03 43 03 4D 03 51 03 49 03 48 03 34 03 4A 03 28 03 50 03 43 03 39 03 3F 03 42 03 47 03 43 03 45 03 28 03 45 03 66 03 49 03 44 03 3A 03 35 03 58 03 48 03 4A 03 57 03 68 03 47 03 2F 03 39 03 4E 03 4B 03 3B 03 3A 03 55 03 5C 03 3D 03 3C 03 58 03 30 03 4B 03 51 03 3A 03 43 03 37 2E E0
16:14:09.435 dir=RX prefix=reb: len=210 hex=72 65 62 3A 09 02 00 64 04 6A 04 66 04 7F 04 74 04 64 04 72 03 D2 03 68 03 5D 03 56 03 4F 03 43 03 31 03 28 03 3D 03 40 03 3E 03 3A 03 38 03 3A 03 43 03 38 03 3E 03 51 03 51 03 2A 03 35 03 4D 03 54 03 59 03 43 03 45 03 4E 03 31 03 20 03 59 03 50 03 2F 03 49 03 4D 03 3C 03 43 03 45 03 2B 03 46 03 4F 03 3D 03 39 03 3D 03 34 03 39 03 46 03 53 03 3A 03 3A 03 40 03 36 03 42 03 41 03 32 03 46 03 34 03 42 03 3B 03 3C 03 45 03 2B 03 52 03 2F 03 4D 03 3A 03 36 03 40 03 46 03 42 03 36 03 3C 03 55 03 4F 03 4C 03 57 03 50 03 40 03 36 03 39 03 59 03 3A 03 39 03 3A 03 36 03 3D 03 49 03 3E 03 3C 03 2F 03 56 03 37 03 3D 03 4D 03 4D 9A AE
16:14:09.470 dir=RX prefix=reb: len=210 hex=72 65 62 3A 09 03 00 64 04 51 04 5D 04 6A 04 5F 04 47 04 55 03 C4 03 50 03 66 03 5C 03 3F 03 32 03 5E 03 3B 03 40 03 47 03 44 03 4A 03 34 03 30 03 45 03 49 03 42 03 44 03 49 03 4B 03 55 03 4D 03 4E 03 4B 03 41 03 39 03 55 03 48 03 55 03 3D 03 51 03 4C 03 41 03 3B 03 3D 03 37 03 41 03 4E 03 4D 03 51 03 41 03 44 03 3B 03 45 03 5F 03 52 03 43 03 40 03 41 03 3F 03 4C 03 3B 03 35 03 40 03 40 03 3C 03 49 03 3B 03 3D 03 4D 03 3D 03 48 03 2D 03 55 03 4C 03 42 03 43 03 3A 03 52 03 3A 03 42 03 48 03 5B 03 47 03 51 03 4C 03 35 03 47 03 4C 03 5F 03 52 03 3D 03 54 03 43 03 48 03 3D 03 41 03 40 03 40 03 55 03 40 03 3D 03 3E 03 3B 26 EF
16:14:09.494 dir=RX prefix=reb: len=210 hex=72 65 62 3A 09 04 00 64 04 80 04 72 04 91 04 82 04 55 04 6D 03 C8 03 37 03 47 03 48 03 3B 03 3C 03 3F 03 3E 03 49 03 53 03 46 03 37 03 4F 03 35 03 39 03 4F 03 4A 03 3F 03 5B 03 21 03 46 03 3D 03 34 03 4A 03 62 03 45 03 4C 03 4E 03 25 03 37 03 47 03 3B 03 50 03 35 03 38 03 52 03 41 03 44 03 50 03 4B 03 4A 03 4C 03 42 03 2D 03 40 03 42 03 44 03 35 03 4E 03 58 03 3A 03 2B 03 41 03 38 03 5C 03 47 03 3D 03 41 03 52 03 3D 03 2B 03 4C 03 47 03 42 03 42 03 3F 03 31 03 46 03 56 03 48 03 41 03 41 03 3B 03 38 03 47 03 46 03 40 03 3B 03 5E 03 4A 03 64 03 44 03 6D 03 55 03 47 03 3B 03 53 03 42 03 43 03 36 03 45 03 26 03 3C 03 4D EC C0
16:14:09.523 dir=RX prefix=reb: len=210 hex=72 65 62 3A 09 05 00 64 04 58 04 58 04 61 04 42 04 28 04 3E 03 C7 03 62 03 54 03 4C 03 60 03 41 03 46 03 43 03 50 03 4B 03 47 03 53 03 41 03 4C 03 39 03 37 03 33 03 40 03 23 03 3F 03 51 03 47 03 5C 03 5F 03 4F 03 4C 03 60 03 48 03 4F 03 33 03 36 03 52 03 4F 03 33 03 46 03 4C 03 3E 03 3D 03 43 03 43 03 55 03 42 03 3A 03 50 03 32 03 58 03 46 03 34 03 59 03 49 03 45 03 54 03 4E 03 4F 03 47 03 3C 03 4F 03 49 03 4D 03 42 03 33 03 40 03 50 03 50 03 5D 03 61 03 4F 03 49 03 3F 03 42 03 49 03 41 03 3C 03 4A 03 3A 03 3C 03 4A 03 37 03 58 03 48 03 50 03 4E 03 49 03 45 03 4B 03 54 03 53 03 50 03 37 03 46 03 46 03 3F 03 42 03 40 B9 36
16:14:09.552 dir=RX prefix=raa: len=8 hex=72 61 61 3A 00 00 43 5E
16:14:09.571 dir=RX prefix=rim: len=152 hex=72 69 6D 3A 00 0C 0B DD E5 84 FD 33 01 5F EF F5 16 2A 09 76 E4 17 FE A4 01 07 DB 86 15 DF 09 F2 DC FC FB 45 00 1D A5 1C 15 AA 0C 42 DE 51 FD AE 03 93 C2 9A 14 50 09 AD DD E2 FD 94 FD E2 F8 05 09 BC 08 A9 E0 92 FA CB F7 0E 06 5F 05 72 07 F6 E2 54 FB 6F EF BB 0E B7 02 ED 07 6A E2 4D FA 77 EE 74 06 5C 00 8D 06 93 E1 0F FA 36 F0 8D 05 73 00 15 07 3D E0 01 FB EC EB 3B 02 1D FC 79 0A 25 E0 80 F7 6B EF 53 08 98 03 67 09 1F E0 D5 F7 C5 03 D0 16 E0 0F B0 C0 1F
# stopped 16:14:16.363 — 9 packets
+159
View File
@@ -0,0 +1,159 @@
timestamp_ms,type,posture,isWalking,pitch,wmean,wstd,accMag,gyroMag,alarm_event,annotation
1782277825446,CYCLE,NON_LYING,false,32.55,13.61,3.77,1.002,13.42,,
1782277826416,CYCLE,NON_LYING,false,31.36,10.09,4.73,1.010,5.00,,
1782277827574,CYCLE,NON_LYING,false,29.45,6.65,2.56,1.005,5.30,,
1782277828431,CYCLE,NON_LYING,false,30.85,5.93,3.38,1.009,2.39,,
1782277829513,CYCLE,NON_LYING,false,32.39,4.70,3.73,1.006,1.65,,
1782277830563,CYCLE,NON_LYING,false,33.15,3.27,1.98,1.002,1.64,,
1782277831494,CYCLE,NON_LYING,false,33.59,2.94,1.84,1.003,0.54,,
1782277832542,CYCLE,NON_LYING,false,33.60,3.73,2.52,1.007,1.90,,
1782277833546,CYCLE,NON_LYING,false,33.58,5.48,3.40,1.005,0.50,,
1782277834582,CYCLE,NON_LYING,false,34.57,6.55,3.80,1.000,0.72,,
1782277835570,CYCLE,NON_LYING,false,34.15,6.48,3.66,1.001,0.71,,
1782277836591,CYCLE,NON_LYING,false,35.46,7.42,4.28,1.006,8.20,,
1782277837812,CYCLE,NON_LYING,false,40.61,4.88,5.08,1.006,0.55,,
1782277838837,CYCLE,NON_LYING,false,40.37,1.57,0.90,1.004,1.59,,
1782277840001,CYCLE,NON_LYING,false,42.08,1.46,0.88,1.004,0.67,,
1782277841024,CYCLE,NON_LYING,false,44.47,3.93,3.48,1.004,6.77,,
1782277842013,CYCLE,NON_LYING,false,44.88,3.75,3.65,1.004,0.60,,
1782277843048,CYCLE,NON_LYING,false,44.76,0.63,0.31,1.004,0.44,,
1782277844023,CYCLE,NON_LYING,false,44.95,0.62,0.17,1.004,0.54,,
1782277845028,CYCLE,NON_LYING,false,45.93,0.72,0.21,1.003,0.57,,
1782277846087,CYCLE,NON_LYING,false,45.35,0.75,0.21,1.004,0.68,,
1782277847089,CYCLE,NON_LYING,false,43.82,4.29,3.83,1.006,6.71,,
1782277848111,CYCLE,NON_LYING,false,37.78,16.02,10.71,1.012,23.58,,
1782277849117,CYCLE,NON_LYING,false,28.12,36.85,16.62,1.025,47.45,,
1782277850147,CYCLE,LYING,false,12.59,47.30,9.73,1.009,41.16,,
1782277851178,CYCLE,LYING,false,6.61,42.74,8.61,1.016,38.80,,
1782277852162,CYCLE,LYING,false,-8.60,28.92,15.05,1.015,6.55,,
1782277852782,ANNOTATION,,,0.00,0.00,0.00,0.000,0.00,,LIE
1782277853210,CYCLE,LYING,false,-6.18,9.38,10.57,1.009,0.67,,
1782277854150,CYCLE,LYING,false,-6.65,1.86,1.09,1.009,2.24,,
1782277855224,CYCLE,LYING,false,-6.17,2.43,0.98,1.008,1.21,,
1782277856238,CYCLE,LYING,false,-9.13,2.23,0.99,1.009,1.46,,
1782277857251,CYCLE,LYING,false,-9.40,1.39,1.03,1.010,0.33,,
1782277858298,CYCLE,LYING,false,-9.02,1.92,1.53,1.007,2.38,,
1782277859300,CYCLE,LYING,false,-10.04,2.17,1.41,1.010,1.07,,
1782277860322,CYCLE,LYING,false,-8.57,2.27,1.94,1.010,2.74,,
1782277861335,CYCLE,LYING,false,-5.22,2.95,1.89,1.010,2.30,,
1782277862350,CYCLE,LYING,false,-6.45,2.22,1.21,1.011,1.01,,
1782277862945,ANNOTATION,,,0.00,0.00,0.00,0.000,0.00,,LIE
1782277863354,CYCLE,LYING,false,-9.22,1.31,0.85,1.010,0.32,,
1782277864386,CYCLE,LYING,false,-5.48,8.30,9.97,1.002,14.78,,
1782277865396,CYCLE,LYING,false,22.86,25.46,13.03,1.013,34.72,,
1782277866406,ALARM,,,0.00,0.00,0.00,0.000,0.00,wakeup_alarm_lying_16s,
1782277866405,CYCLE,NON_LYING,false,69.64,49.64,21.34,0.953,46.81,,
1782277867426,CYCLE,NON_LYING,false,87.73,36.97,21.00,0.997,18.43,,
1782277868467,CYCLE,NON_LYING,false,65.87,23.80,10.06,1.023,11.97,,
1782277869499,CYCLE,NON_LYING,false,79.19,59.12,56.95,0.960,40.02,,
1782277870490,CYCLE,NON_LYING,false,76.81,52.21,61.19,1.001,9.38,,
1782277870893,ANNOTATION,,,0.00,0.00,0.00,0.000,0.00,,STAND
1782277871510,CYCLE,NON_LYING,false,75.82,5.91,4.55,0.996,2.04,,
1782277872550,CYCLE,NON_LYING,false,75.61,2.76,0.66,0.995,3.13,,
1782277873563,CYCLE,NON_LYING,false,76.15,3.72,2.31,0.998,3.31,,
1782277874577,CYCLE,NON_LYING,false,75.25,2.93,2.64,0.997,1.25,,
1782277875576,CYCLE,NON_LYING,false,75.37,1.26,0.73,0.997,0.86,,
1782277876603,CYCLE,NON_LYING,false,75.17,0.90,0.48,0.997,0.51,,
1782277877613,CYCLE,NON_LYING,false,74.91,0.93,0.39,0.997,0.84,,
1782277878639,CYCLE,NON_LYING,false,74.79,0.79,0.36,0.997,0.23,,
1782277879641,CYCLE,NON_LYING,false,74.60,0.62,0.19,0.997,0.57,,
1782277880673,CYCLE,NON_LYING,false,74.45,0.76,0.25,0.997,0.85,,
1782277881685,CYCLE,NON_LYING,false,74.31,0.77,0.35,0.997,0.13,,
1782277882710,CYCLE,NON_LYING,false,74.23,0.61,0.41,0.997,0.49,,
1782277883728,CYCLE,NON_LYING,false,74.17,0.67,0.34,0.997,0.58,,
1782277884754,CYCLE,NON_LYING,false,74.15,0.78,0.20,0.996,0.70,,
1782277885776,CYCLE,NON_LYING,false,73.92,0.78,0.19,0.997,0.69,,
1782277886775,CYCLE,NON_LYING,false,74.25,5.54,5.65,0.996,9.39,,
1782277887801,CYCLE,NON_LYING,false,74.37,6.96,4.64,0.994,2.18,,
1782277888807,CYCLE,NON_LYING,false,74.58,2.53,1.55,0.997,0.90,,
1782277889850,CYCLE,NON_LYING,false,74.47,1.55,0.77,0.992,1.12,,
1782277890831,CYCLE,NON_LYING,false,78.01,4.63,3.19,0.998,7.53,,
1782277891882,CYCLE,NON_LYING,false,66.37,53.32,48.31,1.031,92.97,,
1782277892874,CYCLE,NON_LYING,false,77.70,133.90,39.89,1.037,165.24,,
1782277893910,CYCLE,NON_LYING,false,69.35,121.11,54.35,1.108,49.86,,
1782277894919,CYCLE,NON_LYING,false,64.59,92.44,40.73,1.062,96.59,,
1782277895929,CYCLE,NON_LYING,false,68.48,85.01,40.62,1.044,47.66,,
1782277896934,ALARM,,,0.00,0.00,0.00,0.000,0.00,walking_start,
1782277896934,CYCLE,WALKING,true,71.55,66.19,27.17,1.076,46.45,,
1782277898081,CYCLE,WALKING,true,77.38,70.97,31.36,0.863,55.78,,
1782277899069,CYCLE,WALKING,true,77.21,88.48,33.97,0.861,105.41,,
1782277900069,CYCLE,WALKING,true,74.37,95.63,29.19,0.915,70.24,,
1782277901074,CYCLE,WALKING,true,77.86,68.83,31.65,0.876,23.57,,
1782277902111,CYCLE,WALKING,true,80.44,79.48,34.06,0.948,87.94,,
1782277903114,CYCLE,WALKING,true,77.72,89.16,25.29,0.982,54.11,,
1782277904122,CYCLE,WALKING,true,72.62,59.70,25.54,1.070,23.00,,
1782277905142,CYCLE,WALKING,true,78.30,50.33,20.62,1.080,30.10,,
1782277906155,CYCLE,WALKING,true,74.44,52.98,19.24,1.109,32.59,,
1782277907167,CYCLE,WALKING,true,69.39,42.43,16.67,0.966,19.71,,
1782277907184,ANNOTATION,,,0.00,0.00,0.00,0.000,0.00,,WALK↑
1782277908202,CYCLE,WALKING,true,66.67,45.57,26.23,0.897,23.26,,
1782277909207,CYCLE,WALKING,true,73.22,52.03,32.56,1.016,32.64,,
1782277910257,CYCLE,WALKING,true,73.78,81.91,48.01,1.043,114.00,,
1782277911235,CYCLE,WALKING,true,66.64,109.12,30.79,0.994,100.06,,
1782277912250,CYCLE,WALKING,true,80.63,69.93,40.26,1.112,13.62,,
1782277913276,CYCLE,WALKING,true,78.98,42.48,24.09,0.986,18.77,,
1782277914205,CYCLE,WALKING,true,79.00,50.81,24.89,0.883,36.06,,
1782277915309,CYCLE,WALKING,true,76.95,69.73,32.89,0.902,74.90,,
1782277916327,CYCLE,WALKING,true,72.27,73.62,28.13,1.018,49.76,,
1782277917370,CYCLE,WALKING,true,74.03,54.25,19.15,1.079,29.05,,
1782277918381,CYCLE,WALKING,true,69.22,39.39,18.99,1.072,18.84,,
1782277919378,CYCLE,WALKING,true,68.92,36.14,18.40,0.986,23.28,,
1782277920367,ANNOTATION,,,0.00,0.00,0.00,0.000,0.00,,WALK↓
1782277920413,CYCLE,WALKING,true,78.25,25.22,19.70,0.992,6.82,,
1782277921409,CYCLE,WALKING,true,77.53,6.97,5.57,0.997,3.08,,
1782277922430,CYCLE,WALKING,true,77.50,2.73,0.84,0.997,1.99,,
1782277923446,CYCLE,WALKING,true,78.03,3.00,1.35,0.998,3.73,,
1782277924479,CYCLE,WALKING,true,76.34,37.12,34.08,0.985,68.97,,
1782277925509,CYCLE,WALKING,true,68.15,68.12,9.24,1.023,64.64,,
1782277926499,CYCLE,WALKING,true,71.43,53.93,21.19,0.954,37.85,,
1782277927525,CYCLE,WALKING,true,81.69,47.74,20.07,1.003,49.60,,
1782277928523,CYCLE,WALKING,true,64.73,74.40,35.37,1.045,85.60,,
1782277929563,CYCLE,WALKING,true,11.98,103.50,43.68,1.051,111.16,,
1782277930566,ALARM,,,0.00,0.00,0.00,0.000,0.00,walking_end,
1782277930566,CYCLE,LYING,false,-4.17,60.56,61.09,1.008,9.19,,
1782277931585,CYCLE,LYING,false,-6.04,6.32,3.66,1.008,3.02,,
1782277932470,ANNOTATION,,,0.00,0.00,0.00,0.000,0.00,,SIT
1782277932613,CYCLE,LYING,false,-7.22,2.37,1.31,1.011,1.13,,
1782277933627,CYCLE,LYING,false,-5.08,14.51,20.54,1.173,26.26,,
1782277934635,CYCLE,NON_LYING,false,85.02,54.38,20.27,1.044,36.69,,
1782277935668,CYCLE,NON_LYING,false,80.83,56.34,22.86,0.922,43.36,,
1782277936683,CYCLE,NON_LYING,false,77.04,66.94,24.26,0.925,53.71,,
1782277937722,CYCLE,NON_LYING,false,75.87,77.19,19.20,0.860,47.96,,
1782277938731,CYCLE,NON_LYING,false,76.17,78.95,25.12,0.892,67.98,,
1782277939766,CYCLE,NON_LYING,false,85.96,69.91,32.43,0.906,42.55,,
1782277940770,ALARM,,,0.00,0.00,0.00,0.000,0.00,walking_start,
1782277940770,CYCLE,WALKING,true,82.39,72.64,37.39,0.958,61.39,,
1782277941774,CYCLE,WALKING,true,77.03,79.54,39.02,0.900,57.75,,
1782277942791,CYCLE,WALKING,true,74.52,67.80,29.18,0.922,52.14,,
1782277943802,CYCLE,WALKING,true,52.05,55.44,22.96,1.024,26.38,,
1782277944829,CYCLE,WALKING,true,65.04,26.10,31.51,0.996,2.02,,
1782277945849,CYCLE,WALKING,true,64.65,2.01,0.82,0.995,0.78,,
1782277946864,CYCLE,WALKING,true,65.75,6.45,6.24,0.999,9.43,,
1782277947853,CYCLE,WALKING,true,63.36,17.13,8.26,0.977,21.78,,
1782277948917,CYCLE,WALKING,true,51.36,17.35,7.42,0.994,11.17,,
1782277949909,CYCLE,WALKING,true,47.69,23.58,12.95,0.971,31.78,,
1782277950939,CYCLE,WALKING,true,76.51,88.18,71.08,0.863,135.74,,
1782277951975,CYCLE,WALKING,true,46.67,85.57,73.05,1.009,26.40,,
1782277952971,CYCLE,WALKING,true,54.28,27.73,6.55,1.010,22.45,,
1782277954044,CYCLE,WALKING,true,53.25,20.44,7.75,1.001,14.99,,
1782277955003,CYCLE,WALKING,true,52.17,14.09,5.95,1.005,12.26,,
1782277956065,CYCLE,WALKING,true,54.74,7.20,6.19,1.003,1.79,,
1782277957073,CYCLE,WALKING,true,54.59,1.20,0.71,1.004,0.47,,
1782277958099,ALARM,,,0.00,0.00,0.00,0.000,0.00,walking_end,
1782277958099,CYCLE,NON_LYING,false,54.32,0.87,0.44,1.003,0.95,,
1782277959111,CYCLE,NON_LYING,false,54.26,0.97,0.32,1.002,0.68,,
1782277960167,CYCLE,NON_LYING,false,54.25,0.95,0.23,1.002,1.09,,
1782277961216,CYCLE,NON_LYING,false,54.14,0.81,0.38,1.003,0.35,,
1782277962206,CYCLE,NON_LYING,false,54.22,0.54,0.24,1.003,0.54,,
1782277963205,CYCLE,NON_LYING,false,54.17,0.64,0.17,1.003,0.66,,
1782277964209,CYCLE,NON_LYING,false,54.08,0.65,0.16,1.003,0.54,,
1782277965258,CYCLE,NON_LYING,false,54.71,2.55,2.07,1.002,4.32,,
1782277966256,CYCLE,NON_LYING,false,55.67,3.15,1.60,1.003,1.71,,
1782277967319,CYCLE,NON_LYING,false,57.39,8.73,10.62,1.020,13.60,,
1782277968325,CYCLE,NON_LYING,false,54.33,12.20,9.64,0.994,5.53,,
1782277969346,CYCLE,NON_LYING,false,56.86,9.98,4.80,0.991,6.85,,
1782277970365,CYCLE,NON_LYING,false,57.87,11.24,3.46,0.971,3.32,,
1782277971387,CYCLE,NON_LYING,false,57.40,12.16,5.15,0.965,2.34,,
1782277972400,CYCLE,NON_LYING,false,57.48,13.40,6.27,0.993,4.11,,
1782277973426,ALARM,,,0.00,0.00,0.00,0.000,0.00,walking_start,
1782277973426,CYCLE,WALKING,true,58.11,13.65,6.14,1.027,2.76,,
1 timestamp_ms type posture isWalking pitch wmean wstd accMag gyroMag alarm_event annotation
2 1782277825446 CYCLE NON_LYING false 32.55 13.61 3.77 1.002 13.42
3 1782277826416 CYCLE NON_LYING false 31.36 10.09 4.73 1.010 5.00
4 1782277827574 CYCLE NON_LYING false 29.45 6.65 2.56 1.005 5.30
5 1782277828431 CYCLE NON_LYING false 30.85 5.93 3.38 1.009 2.39
6 1782277829513 CYCLE NON_LYING false 32.39 4.70 3.73 1.006 1.65
7 1782277830563 CYCLE NON_LYING false 33.15 3.27 1.98 1.002 1.64
8 1782277831494 CYCLE NON_LYING false 33.59 2.94 1.84 1.003 0.54
9 1782277832542 CYCLE NON_LYING false 33.60 3.73 2.52 1.007 1.90
10 1782277833546 CYCLE NON_LYING false 33.58 5.48 3.40 1.005 0.50
11 1782277834582 CYCLE NON_LYING false 34.57 6.55 3.80 1.000 0.72
12 1782277835570 CYCLE NON_LYING false 34.15 6.48 3.66 1.001 0.71
13 1782277836591 CYCLE NON_LYING false 35.46 7.42 4.28 1.006 8.20
14 1782277837812 CYCLE NON_LYING false 40.61 4.88 5.08 1.006 0.55
15 1782277838837 CYCLE NON_LYING false 40.37 1.57 0.90 1.004 1.59
16 1782277840001 CYCLE NON_LYING false 42.08 1.46 0.88 1.004 0.67
17 1782277841024 CYCLE NON_LYING false 44.47 3.93 3.48 1.004 6.77
18 1782277842013 CYCLE NON_LYING false 44.88 3.75 3.65 1.004 0.60
19 1782277843048 CYCLE NON_LYING false 44.76 0.63 0.31 1.004 0.44
20 1782277844023 CYCLE NON_LYING false 44.95 0.62 0.17 1.004 0.54
21 1782277845028 CYCLE NON_LYING false 45.93 0.72 0.21 1.003 0.57
22 1782277846087 CYCLE NON_LYING false 45.35 0.75 0.21 1.004 0.68
23 1782277847089 CYCLE NON_LYING false 43.82 4.29 3.83 1.006 6.71
24 1782277848111 CYCLE NON_LYING false 37.78 16.02 10.71 1.012 23.58
25 1782277849117 CYCLE NON_LYING false 28.12 36.85 16.62 1.025 47.45
26 1782277850147 CYCLE LYING false 12.59 47.30 9.73 1.009 41.16
27 1782277851178 CYCLE LYING false 6.61 42.74 8.61 1.016 38.80
28 1782277852162 CYCLE LYING false -8.60 28.92 15.05 1.015 6.55
29 1782277852782 ANNOTATION 0.00 0.00 0.00 0.000 0.00 LIE
30 1782277853210 CYCLE LYING false -6.18 9.38 10.57 1.009 0.67
31 1782277854150 CYCLE LYING false -6.65 1.86 1.09 1.009 2.24
32 1782277855224 CYCLE LYING false -6.17 2.43 0.98 1.008 1.21
33 1782277856238 CYCLE LYING false -9.13 2.23 0.99 1.009 1.46
34 1782277857251 CYCLE LYING false -9.40 1.39 1.03 1.010 0.33
35 1782277858298 CYCLE LYING false -9.02 1.92 1.53 1.007 2.38
36 1782277859300 CYCLE LYING false -10.04 2.17 1.41 1.010 1.07
37 1782277860322 CYCLE LYING false -8.57 2.27 1.94 1.010 2.74
38 1782277861335 CYCLE LYING false -5.22 2.95 1.89 1.010 2.30
39 1782277862350 CYCLE LYING false -6.45 2.22 1.21 1.011 1.01
40 1782277862945 ANNOTATION 0.00 0.00 0.00 0.000 0.00 LIE
41 1782277863354 CYCLE LYING false -9.22 1.31 0.85 1.010 0.32
42 1782277864386 CYCLE LYING false -5.48 8.30 9.97 1.002 14.78
43 1782277865396 CYCLE LYING false 22.86 25.46 13.03 1.013 34.72
44 1782277866406 ALARM 0.00 0.00 0.00 0.000 0.00 wakeup_alarm_lying_16s
45 1782277866405 CYCLE NON_LYING false 69.64 49.64 21.34 0.953 46.81
46 1782277867426 CYCLE NON_LYING false 87.73 36.97 21.00 0.997 18.43
47 1782277868467 CYCLE NON_LYING false 65.87 23.80 10.06 1.023 11.97
48 1782277869499 CYCLE NON_LYING false 79.19 59.12 56.95 0.960 40.02
49 1782277870490 CYCLE NON_LYING false 76.81 52.21 61.19 1.001 9.38
50 1782277870893 ANNOTATION 0.00 0.00 0.00 0.000 0.00 STAND
51 1782277871510 CYCLE NON_LYING false 75.82 5.91 4.55 0.996 2.04
52 1782277872550 CYCLE NON_LYING false 75.61 2.76 0.66 0.995 3.13
53 1782277873563 CYCLE NON_LYING false 76.15 3.72 2.31 0.998 3.31
54 1782277874577 CYCLE NON_LYING false 75.25 2.93 2.64 0.997 1.25
55 1782277875576 CYCLE NON_LYING false 75.37 1.26 0.73 0.997 0.86
56 1782277876603 CYCLE NON_LYING false 75.17 0.90 0.48 0.997 0.51
57 1782277877613 CYCLE NON_LYING false 74.91 0.93 0.39 0.997 0.84
58 1782277878639 CYCLE NON_LYING false 74.79 0.79 0.36 0.997 0.23
59 1782277879641 CYCLE NON_LYING false 74.60 0.62 0.19 0.997 0.57
60 1782277880673 CYCLE NON_LYING false 74.45 0.76 0.25 0.997 0.85
61 1782277881685 CYCLE NON_LYING false 74.31 0.77 0.35 0.997 0.13
62 1782277882710 CYCLE NON_LYING false 74.23 0.61 0.41 0.997 0.49
63 1782277883728 CYCLE NON_LYING false 74.17 0.67 0.34 0.997 0.58
64 1782277884754 CYCLE NON_LYING false 74.15 0.78 0.20 0.996 0.70
65 1782277885776 CYCLE NON_LYING false 73.92 0.78 0.19 0.997 0.69
66 1782277886775 CYCLE NON_LYING false 74.25 5.54 5.65 0.996 9.39
67 1782277887801 CYCLE NON_LYING false 74.37 6.96 4.64 0.994 2.18
68 1782277888807 CYCLE NON_LYING false 74.58 2.53 1.55 0.997 0.90
69 1782277889850 CYCLE NON_LYING false 74.47 1.55 0.77 0.992 1.12
70 1782277890831 CYCLE NON_LYING false 78.01 4.63 3.19 0.998 7.53
71 1782277891882 CYCLE NON_LYING false 66.37 53.32 48.31 1.031 92.97
72 1782277892874 CYCLE NON_LYING false 77.70 133.90 39.89 1.037 165.24
73 1782277893910 CYCLE NON_LYING false 69.35 121.11 54.35 1.108 49.86
74 1782277894919 CYCLE NON_LYING false 64.59 92.44 40.73 1.062 96.59
75 1782277895929 CYCLE NON_LYING false 68.48 85.01 40.62 1.044 47.66
76 1782277896934 ALARM 0.00 0.00 0.00 0.000 0.00 walking_start
77 1782277896934 CYCLE WALKING true 71.55 66.19 27.17 1.076 46.45
78 1782277898081 CYCLE WALKING true 77.38 70.97 31.36 0.863 55.78
79 1782277899069 CYCLE WALKING true 77.21 88.48 33.97 0.861 105.41
80 1782277900069 CYCLE WALKING true 74.37 95.63 29.19 0.915 70.24
81 1782277901074 CYCLE WALKING true 77.86 68.83 31.65 0.876 23.57
82 1782277902111 CYCLE WALKING true 80.44 79.48 34.06 0.948 87.94
83 1782277903114 CYCLE WALKING true 77.72 89.16 25.29 0.982 54.11
84 1782277904122 CYCLE WALKING true 72.62 59.70 25.54 1.070 23.00
85 1782277905142 CYCLE WALKING true 78.30 50.33 20.62 1.080 30.10
86 1782277906155 CYCLE WALKING true 74.44 52.98 19.24 1.109 32.59
87 1782277907167 CYCLE WALKING true 69.39 42.43 16.67 0.966 19.71
88 1782277907184 ANNOTATION 0.00 0.00 0.00 0.000 0.00 WALK↑
89 1782277908202 CYCLE WALKING true 66.67 45.57 26.23 0.897 23.26
90 1782277909207 CYCLE WALKING true 73.22 52.03 32.56 1.016 32.64
91 1782277910257 CYCLE WALKING true 73.78 81.91 48.01 1.043 114.00
92 1782277911235 CYCLE WALKING true 66.64 109.12 30.79 0.994 100.06
93 1782277912250 CYCLE WALKING true 80.63 69.93 40.26 1.112 13.62
94 1782277913276 CYCLE WALKING true 78.98 42.48 24.09 0.986 18.77
95 1782277914205 CYCLE WALKING true 79.00 50.81 24.89 0.883 36.06
96 1782277915309 CYCLE WALKING true 76.95 69.73 32.89 0.902 74.90
97 1782277916327 CYCLE WALKING true 72.27 73.62 28.13 1.018 49.76
98 1782277917370 CYCLE WALKING true 74.03 54.25 19.15 1.079 29.05
99 1782277918381 CYCLE WALKING true 69.22 39.39 18.99 1.072 18.84
100 1782277919378 CYCLE WALKING true 68.92 36.14 18.40 0.986 23.28
101 1782277920367 ANNOTATION 0.00 0.00 0.00 0.000 0.00 WALK↓
102 1782277920413 CYCLE WALKING true 78.25 25.22 19.70 0.992 6.82
103 1782277921409 CYCLE WALKING true 77.53 6.97 5.57 0.997 3.08
104 1782277922430 CYCLE WALKING true 77.50 2.73 0.84 0.997 1.99
105 1782277923446 CYCLE WALKING true 78.03 3.00 1.35 0.998 3.73
106 1782277924479 CYCLE WALKING true 76.34 37.12 34.08 0.985 68.97
107 1782277925509 CYCLE WALKING true 68.15 68.12 9.24 1.023 64.64
108 1782277926499 CYCLE WALKING true 71.43 53.93 21.19 0.954 37.85
109 1782277927525 CYCLE WALKING true 81.69 47.74 20.07 1.003 49.60
110 1782277928523 CYCLE WALKING true 64.73 74.40 35.37 1.045 85.60
111 1782277929563 CYCLE WALKING true 11.98 103.50 43.68 1.051 111.16
112 1782277930566 ALARM 0.00 0.00 0.00 0.000 0.00 walking_end
113 1782277930566 CYCLE LYING false -4.17 60.56 61.09 1.008 9.19
114 1782277931585 CYCLE LYING false -6.04 6.32 3.66 1.008 3.02
115 1782277932470 ANNOTATION 0.00 0.00 0.00 0.000 0.00 SIT
116 1782277932613 CYCLE LYING false -7.22 2.37 1.31 1.011 1.13
117 1782277933627 CYCLE LYING false -5.08 14.51 20.54 1.173 26.26
118 1782277934635 CYCLE NON_LYING false 85.02 54.38 20.27 1.044 36.69
119 1782277935668 CYCLE NON_LYING false 80.83 56.34 22.86 0.922 43.36
120 1782277936683 CYCLE NON_LYING false 77.04 66.94 24.26 0.925 53.71
121 1782277937722 CYCLE NON_LYING false 75.87 77.19 19.20 0.860 47.96
122 1782277938731 CYCLE NON_LYING false 76.17 78.95 25.12 0.892 67.98
123 1782277939766 CYCLE NON_LYING false 85.96 69.91 32.43 0.906 42.55
124 1782277940770 ALARM 0.00 0.00 0.00 0.000 0.00 walking_start
125 1782277940770 CYCLE WALKING true 82.39 72.64 37.39 0.958 61.39
126 1782277941774 CYCLE WALKING true 77.03 79.54 39.02 0.900 57.75
127 1782277942791 CYCLE WALKING true 74.52 67.80 29.18 0.922 52.14
128 1782277943802 CYCLE WALKING true 52.05 55.44 22.96 1.024 26.38
129 1782277944829 CYCLE WALKING true 65.04 26.10 31.51 0.996 2.02
130 1782277945849 CYCLE WALKING true 64.65 2.01 0.82 0.995 0.78
131 1782277946864 CYCLE WALKING true 65.75 6.45 6.24 0.999 9.43
132 1782277947853 CYCLE WALKING true 63.36 17.13 8.26 0.977 21.78
133 1782277948917 CYCLE WALKING true 51.36 17.35 7.42 0.994 11.17
134 1782277949909 CYCLE WALKING true 47.69 23.58 12.95 0.971 31.78
135 1782277950939 CYCLE WALKING true 76.51 88.18 71.08 0.863 135.74
136 1782277951975 CYCLE WALKING true 46.67 85.57 73.05 1.009 26.40
137 1782277952971 CYCLE WALKING true 54.28 27.73 6.55 1.010 22.45
138 1782277954044 CYCLE WALKING true 53.25 20.44 7.75 1.001 14.99
139 1782277955003 CYCLE WALKING true 52.17 14.09 5.95 1.005 12.26
140 1782277956065 CYCLE WALKING true 54.74 7.20 6.19 1.003 1.79
141 1782277957073 CYCLE WALKING true 54.59 1.20 0.71 1.004 0.47
142 1782277958099 ALARM 0.00 0.00 0.00 0.000 0.00 walking_end
143 1782277958099 CYCLE NON_LYING false 54.32 0.87 0.44 1.003 0.95
144 1782277959111 CYCLE NON_LYING false 54.26 0.97 0.32 1.002 0.68
145 1782277960167 CYCLE NON_LYING false 54.25 0.95 0.23 1.002 1.09
146 1782277961216 CYCLE NON_LYING false 54.14 0.81 0.38 1.003 0.35
147 1782277962206 CYCLE NON_LYING false 54.22 0.54 0.24 1.003 0.54
148 1782277963205 CYCLE NON_LYING false 54.17 0.64 0.17 1.003 0.66
149 1782277964209 CYCLE NON_LYING false 54.08 0.65 0.16 1.003 0.54
150 1782277965258 CYCLE NON_LYING false 54.71 2.55 2.07 1.002 4.32
151 1782277966256 CYCLE NON_LYING false 55.67 3.15 1.60 1.003 1.71
152 1782277967319 CYCLE NON_LYING false 57.39 8.73 10.62 1.020 13.60
153 1782277968325 CYCLE NON_LYING false 54.33 12.20 9.64 0.994 5.53
154 1782277969346 CYCLE NON_LYING false 56.86 9.98 4.80 0.991 6.85
155 1782277970365 CYCLE NON_LYING false 57.87 11.24 3.46 0.971 3.32
156 1782277971387 CYCLE NON_LYING false 57.40 12.16 5.15 0.965 2.34
157 1782277972400 CYCLE NON_LYING false 57.48 13.40 6.27 0.993 4.11
158 1782277973426 ALARM 0.00 0.00 0.00 0.000 0.00 walking_start
159 1782277973426 CYCLE WALKING true 58.11 13.65 6.14 1.027 2.76
Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

+2 -2
View File
@@ -5,13 +5,13 @@ plugins {
}
android {
namespace = "com.example.medilightv2android"
namespace = "com.medithings.vesiscan"
compileSdk {
version = release(36)
}
defaultConfig {
applicationId = "com.example.medilightv2android"
applicationId = "com.medithings.vesiscan"
minSdk = 24
targetSdk = 36
versionCode = 27
@@ -1,4 +1,4 @@
package com.example.medilightv2android
package com.medithings.vesiscan
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -19,6 +19,6 @@ class ExampleInstrumentedTest {
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.medilightv2android", appContext.packageName)
assertEquals("com.medithings.vesiscan", appContext.packageName)
}
}
@@ -1,14 +1,14 @@
package com.example.medilightv2android
package com.medithings.vesiscan
import android.content.Context
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import com.example.medilightv2android.ble.BleManager
import com.example.medilightv2android.managers.NirsManager
import com.example.medilightv2android.models.*
import com.example.medilightv2android.services.*
import com.medithings.vesiscan.ble.BleManager
import com.medithings.vesiscan.managers.NirsManager
import com.medithings.vesiscan.models.*
import com.medithings.vesiscan.services.*
enum class AppScreen {
ONBOARDING, CONSENT, REGISTRATION, HOME, SENSOR_SELECT, DEVICE_SCAN,
@@ -121,7 +121,7 @@ class AppState(private val context: Context) {
fun deviceConnected() {
isDeviceConnected = true
// 임상 모드에서 BLE 연결 시 ClinicalHome으로 복귀 (Personalization 우회)
if (com.example.medilightv2android.services.ClinicalSessionStore.inClinicalFlow) {
if (com.medithings.vesiscan.services.ClinicalSessionStore.inClinicalFlow) {
currentScreen = AppScreen.CLINICAL_HOME
return
}
@@ -1,4 +1,4 @@
package com.example.medilightv2android
package com.medithings.vesiscan
import android.os.Bundle
import androidx.activity.ComponentActivity
@@ -20,34 +20,34 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import app.rive.runtime.kotlin.core.Rive
import com.example.medilightv2android.services.KeychainService
import com.example.medilightv2android.services.NotificationService
import com.example.medilightv2android.R
import com.example.medilightv2android.ui.theme.Medilightv2androidTheme
import com.example.medilightv2android.ui.views.calibration.CalibrationView
import com.example.medilightv2android.ui.views.connection.DeviceScanView
import com.example.medilightv2android.ui.views.history.MeasurementHistoryView
import com.example.medilightv2android.ui.views.home.HomeView
import com.example.medilightv2android.ui.views.monitoring.PlacementGuideView
import com.example.medilightv2android.ui.views.monitoring.PiezoMonitoringView
import com.example.medilightv2android.ui.views.monitoring.VivamyoMonitoringView
import com.example.medilightv2android.ui.views.monitoring.UrineCameraScreen
import com.example.medilightv2android.ui.views.monitoring.VoidingDiaryView
import com.example.medilightv2android.ui.views.onboarding.OnboardingView
import com.example.medilightv2android.ui.views.personalization.PiezoPersonalizationView
import com.example.medilightv2android.ui.views.pin.PinMode
import com.example.medilightv2android.ui.views.pin.PinView
import com.example.medilightv2android.ui.views.registration.RegistrationView
import com.example.medilightv2android.ui.views.consent.ConsentView
import com.example.medilightv2android.ui.views.reminder.ReminderSettingsView
import com.example.medilightv2android.ui.views.sensorselect.SensorSelectView
import com.example.medilightv2android.ui.views.clinical.ClinicalHomeView
import com.example.medilightv2android.ui.views.clinical.ClinicalLiveView
import com.medithings.vesiscan.services.KeychainService
import com.medithings.vesiscan.services.NotificationService
import com.medithings.vesiscan.R
import com.medithings.vesiscan.ui.theme.Medilightv2androidTheme
import com.medithings.vesiscan.ui.views.calibration.CalibrationView
import com.medithings.vesiscan.ui.views.connection.DeviceScanView
import com.medithings.vesiscan.ui.views.history.MeasurementHistoryView
import com.medithings.vesiscan.ui.views.home.HomeView
import com.medithings.vesiscan.ui.views.monitoring.PlacementGuideView
import com.medithings.vesiscan.ui.views.monitoring.PiezoMonitoringView
import com.medithings.vesiscan.ui.views.monitoring.VivamyoMonitoringView
import com.medithings.vesiscan.ui.views.monitoring.UrineCameraScreen
import com.medithings.vesiscan.ui.views.monitoring.VoidingDiaryView
import com.medithings.vesiscan.ui.views.onboarding.OnboardingView
import com.medithings.vesiscan.ui.views.personalization.PiezoPersonalizationView
import com.medithings.vesiscan.ui.views.pin.PinMode
import com.medithings.vesiscan.ui.views.pin.PinView
import com.medithings.vesiscan.ui.views.registration.RegistrationView
import com.medithings.vesiscan.ui.views.consent.ConsentView
import com.medithings.vesiscan.ui.views.reminder.ReminderSettingsView
import com.medithings.vesiscan.ui.views.sensorselect.SensorSelectView
import com.medithings.vesiscan.ui.views.clinical.ClinicalHomeView
import com.medithings.vesiscan.ui.views.clinical.ClinicalLiveView
class MainActivity : ComponentActivity() {
/** 사용자가 선택한 앱 언어 적용 — Activity 생성 전에 Locale wrap. */
override fun attachBaseContext(newBase: android.content.Context) {
super.attachBaseContext(com.example.medilightv2android.services.LocalePref.wrap(newBase))
super.attachBaseContext(com.medithings.vesiscan.services.LocalePref.wrap(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
@@ -106,28 +106,28 @@ fun MedilightApp(modifier: Modifier = Modifier) {
// DeviceScan Back: 임상 흐름이면 ClinicalHome으로, 아니면 HOME
AppScreen.DEVICE_SCAN ->
appState.currentScreen =
if (com.example.medilightv2android.services.ClinicalSessionStore.inClinicalFlow)
if (com.medithings.vesiscan.services.ClinicalSessionStore.inClinicalFlow)
AppScreen.CLINICAL_HOME
else AppScreen.HOME
AppScreen.PIEZO_PERSONALIZATION -> appState.currentScreen = AppScreen.DEVICE_SCAN
// 임상 모드 측정 중이면 endMeasurement → ClinicalHome 복귀
AppScreen.PLACEMENT_GUIDE ->
if (com.example.medilightv2android.services.ClinicalSessionStore.currentSession != null) {
com.example.medilightv2android.services.ClinicalSessionStore.endMeasurement(context)
if (com.medithings.vesiscan.services.ClinicalSessionStore.currentSession != null) {
com.medithings.vesiscan.services.ClinicalSessionStore.endMeasurement(context)
appState.currentScreen = AppScreen.CLINICAL_HOME
} else appState.backFromPlacementGuide()
AppScreen.PIEZO_MONITORING ->
if (com.example.medilightv2android.services.ClinicalSessionStore.currentSession != null) {
com.example.medilightv2android.services.ClinicalSessionStore.endMeasurement(context)
if (com.medithings.vesiscan.services.ClinicalSessionStore.currentSession != null) {
com.medithings.vesiscan.services.ClinicalSessionStore.endMeasurement(context)
appState.currentScreen = AppScreen.CLINICAL_HOME
} else appState.currentScreen = AppScreen.PLACEMENT_GUIDE
AppScreen.CLINICAL_HOME -> {
com.example.medilightv2android.services.ClinicalSessionStore.inClinicalFlow = false
com.medithings.vesiscan.services.ClinicalSessionStore.inClinicalFlow = false
appState.currentScreen = AppScreen.HOME
}
AppScreen.CLINICAL_LIVE -> {
// 측정 폴더 finalize 후 ClinicalHome 복귀
com.example.medilightv2android.services.ClinicalSessionStore.endMeasurement(context)
com.medithings.vesiscan.services.ClinicalSessionStore.endMeasurement(context)
appState.currentScreen = AppScreen.CLINICAL_HOME
}
// 모니터링 하위 화면 → 모니터링
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ble
package com.medithings.vesiscan.ble
import android.annotation.SuppressLint
import android.bluetooth.*
@@ -8,7 +8,7 @@ import android.os.Build
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.example.medilightv2android.BuildConfig
import com.medithings.vesiscan.BuildConfig
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import java.util.UUID
@@ -57,7 +57,7 @@ class BleManager private constructor(private val context: Context) {
@Volatile private var txCharacteristic: BluetoothGattCharacteristic? = null
@Volatile private var rxCharacteristic: BluetoothGattCharacteristic? = null
private val handler = Handler(Looper.getMainLooper())
val debugLogger = com.example.medilightv2android.services.BleDebugLogger.getInstance(context)
val debugLogger = com.medithings.vesiscan.services.BleDebugLogger.getInstance(context)
private var scanTimer: Runnable? = null
private var batteryTimer: Runnable? = null
private var batteryRetryTimer: Runnable? = null
@@ -299,7 +299,7 @@ class BleManager private constructor(private val context: Context) {
logw { "removeBond failed: ${e.message}" }
}
}
com.example.medilightv2android.services.KnownDeviceStore.remove(context, address)
com.medithings.vesiscan.services.KnownDeviceStore.remove(context, address)
debugLogger.info("DEVICE_UNREGISTERED $address")
}
@@ -326,7 +326,7 @@ class BleManager private constructor(private val context: Context) {
/** 저장된 마지막 기기에 자동 연결 시도 */
fun autoConnectLastDevice() {
if (isConnected.value) return
val recent = com.example.medilightv2android.services.KnownDeviceStore.mostRecent(context) ?: return
val recent = com.medithings.vesiscan.services.KnownDeviceStore.mostRecent(context) ?: return
debugLogger.info("AUTO_CONNECT attempting ${recent.name} (${recent.address})")
lastConnectedAddress = recent.address
scheduleAutoReconnect()
@@ -340,7 +340,7 @@ class BleManager private constructor(private val context: Context) {
connectionTimer?.let { handler.removeCallbacks(it) }
connectionTimer = null
bluetoothGatt?.disconnect()
com.example.medilightv2android.services.BleForegroundService.stop(context)
com.medithings.vesiscan.services.BleForegroundService.stop(context)
}
fun disconnectAndUnbond() {
@@ -348,7 +348,7 @@ class BleManager private constructor(private val context: Context) {
cancelAutoReconnect()
stopWatchdog()
stopBatteryPolling()
com.example.medilightv2android.services.BleForegroundService.stop(context)
com.medithings.vesiscan.services.BleForegroundService.stop(context)
connectionTimer?.let { handler.removeCallbacks(it) }
connectionTimer = null
@@ -386,7 +386,7 @@ class BleManager private constructor(private val context: Context) {
// 저장된 기기 정보 삭제 — known device list 에서도 제거
try {
device?.let { dev ->
com.example.medilightv2android.services.KnownDeviceStore.remove(context, dev.address)
com.medithings.vesiscan.services.KnownDeviceStore.remove(context, dev.address)
}
} catch (_: Exception) {}
@@ -900,9 +900,9 @@ class BleManager private constructor(private val context: Context) {
isConnected.value = true
connectedDeviceName.value = try { gatt.device.name ?: "Unknown" } catch (_: Exception) { "Unknown" }
// Auto-detect device preset + endian from name
com.example.medilightv2android.managers.PiezoHW.autoDetectPreset(connectedDeviceName.value)
com.medithings.vesiscan.managers.PiezoHW.autoDetectPreset(connectedDeviceName.value)
piezoCollector.forceBigEndian = connectedDeviceName.value.startsWith("VBT")
logd { "Device preset: ${com.example.medilightv2android.managers.PiezoHW.presetName}, endian: ${if (piezoCollector.forceBigEndian) "BE" else "LE"} (from '${connectedDeviceName.value}')" }
logd { "Device preset: ${com.medithings.vesiscan.managers.PiezoHW.presetName}, endian: ${if (piezoCollector.forceBigEndian) "BE" else "LE"} (from '${connectedDeviceName.value}')" }
lastConnectedAddress = gatt.device.address
reconnectAttempt = 0
@@ -911,9 +911,9 @@ class BleManager private constructor(private val context: Context) {
// Clinical 흐름에서만 KnownDeviceStore 영속화. 일반 사용자는
// 매 세션 fresh scan + pair — 저장 0개.
if (com.example.medilightv2android.services.ClinicalSessionStore.inClinicalFlow) {
if (com.medithings.vesiscan.services.ClinicalSessionStore.inClinicalFlow) {
try {
com.example.medilightv2android.services.KnownDeviceStore.add(
com.medithings.vesiscan.services.KnownDeviceStore.add(
context, gatt.device.address, connectedDeviceName.value
)
} catch (_: Exception) {}
@@ -1030,8 +1030,8 @@ class BleManager private constructor(private val context: Context) {
} catch (_: Exception) { false }
logd { "requestConnectionPriority(HIGH) → $priorityOk" }
debugLogger.info("CONN_PRIORITY HIGH requested (ok=$priorityOk)")
com.example.medilightv2android.services.AdcCsvLogger.newSession()
com.example.medilightv2android.services.BleForegroundService.start(context)
com.medithings.vesiscan.services.AdcCsvLogger.newSession()
com.medithings.vesiscan.services.BleForegroundService.start(context)
startBatteryPolling()
startWatchdog()
sendDeviceInfoQuery()
@@ -1105,7 +1105,7 @@ class BleManager private constructor(private val context: Context) {
private fun processReceivedData(data: ByteArray) {
lastRxTimestamp = System.currentTimeMillis()
// Raw BLE capture (디버그 — 사용자가 토글로 enable 했을 때만 writes)
com.example.medilightv2android.services.RawBleLogger.write(data)
com.medithings.vesiscan.services.RawBleLogger.write(data)
val prefix = String(data, 0, minOf(4, data.size), Charsets.US_ASCII)
logd { "Received: $prefix (${data.size} bytes)" }
when (prefix) {
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ble
package com.medithings.vesiscan.ble
object CRC16 {
private const val POLYNOMIAL: Int = 0x1021
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ble
package com.medithings.vesiscan.ble
/**
* IMU 6축 raw 샘플 (Accel xyz + Gyro xyz).
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ble
package com.medithings.vesiscan.ble
/**
* Collects multi-packet Piezo echo responses: reb: → (red:) → raa:
@@ -16,12 +16,12 @@
*
* 기존 PlacementGuide computePlacementGuide(...) 와 병행 — V1/V2 토글로 분기.
*/
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import com.example.medilightv2android.R
import com.example.medilightv2android.walldetect.MethodDResult
import com.example.medilightv2android.walldetect.MethodDRunner
import com.example.medilightv2android.walldetect.algo.methodd.MethodDParams
import com.medithings.vesiscan.R
import com.medithings.vesiscan.walldetect.MethodDResult
import com.medithings.vesiscan.walldetect.MethodDRunner
import com.medithings.vesiscan.walldetect.algo.methodd.MethodDParams
import kotlin.math.abs
import kotlin.math.max
@@ -1,4 +1,4 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import kotlin.math.abs
import kotlin.math.max
@@ -1,4 +1,4 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import kotlin.math.abs
@@ -1,4 +1,4 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import kotlin.math.cos
import kotlin.math.sin
@@ -1,4 +1,4 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import kotlin.math.abs
import kotlin.math.sqrt
@@ -1,4 +1,4 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
/**
* Green Zone 전체 파이프라인의 공유 상수 — Single Source of Truth.
@@ -1,6 +1,6 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import com.example.medilightv2android.ble.ImuSample
import com.medithings.vesiscan.ble.ImuSample
import kotlin.math.abs
import kotlin.math.atan2
import kotlin.math.sqrt
@@ -13,9 +13,9 @@
* ≤ threshold → NON_LYING (앉음/섬)
* threshold default = 25°, dev 모드 설정에서 변경 가능.
*/
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import com.example.medilightv2android.ble.ImuSample
import com.medithings.vesiscan.ble.ImuSample
import kotlin.math.abs
import kotlin.math.atan
import kotlin.math.sqrt
@@ -1,8 +1,8 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import com.example.medilightv2android.models.NirsConstants
import com.example.medilightv2android.models.NirsMagResponse
import com.example.medilightv2android.models.NirsOxyResult
import com.medithings.vesiscan.models.NirsConstants
import com.medithings.vesiscan.models.NirsMagResponse
import com.medithings.vesiscan.models.NirsOxyResult
import kotlin.math.abs
import kotlin.math.ln
import kotlin.math.max
@@ -1,13 +1,13 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import com.example.medilightv2android.models.NirsMagResponse
import com.example.medilightv2android.models.NirsMcjPacket
import com.example.medilightv2android.models.NirsConstants
import com.example.medilightv2android.BuildConfig
import com.example.medilightv2android.models.NirsOxyResult
import com.medithings.vesiscan.models.NirsMagResponse
import com.medithings.vesiscan.models.NirsMcjPacket
import com.medithings.vesiscan.models.NirsConstants
import com.medithings.vesiscan.BuildConfig
import com.medithings.vesiscan.models.NirsOxyResult
class NirsManager private constructor() {
companion object {
@@ -1,6 +1,6 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import com.example.medilightv2android.walldetect.core.WdConfig
import com.medithings.vesiscan.walldetect.core.WdConfig
import kotlin.math.abs
import kotlin.math.cos
import kotlin.math.hypot
@@ -484,7 +484,7 @@ fun estimateBladderVolume6ch(
val lateralWalls = PiezoHW.lateralCh.map { if (it < allWalls.size) allWalls[it] else null }
// 2026-07-01: algorithm 팀 최신 표준 (piezophantomtest 4830e7c) — lr_ratio_override=1.0
// Phantom 검증: computed lr 은 6채널 HW 한계로 -38% 오차. Dev panel 로 전환 가능.
val lrRatio = com.example.medilightv2android.managers.GreenZoneConstants.lrRatioOverride
val lrRatio = com.medithings.vesiscan.managers.GreenZoneConstants.lrRatioOverride
?: computeLrRatio(centerWalls, lateralWalls, sensorZMm = PiezoHW.sensorZMmAll)
return estimateBladderVolume(
walls = centerWalls,
@@ -1,6 +1,6 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import com.example.medilightv2android.ble.PiezoChannelData
import com.medithings.vesiscan.ble.PiezoChannelData
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
@@ -1,4 +1,4 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import kotlin.math.abs
import kotlin.math.max
@@ -1,4 +1,4 @@
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
/**
* UrinAI (UrinGateKeeper) — 소변(액체) 존재 판정 엔진.
@@ -15,7 +15,7 @@
* // 매 posture 갱신 시:
* detector.update(currentPosture, System.currentTimeMillis())
*/
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
class WakeupDetector(
/** 알람 발동을 위해 직전 LYING 상태로 유지되어야 하는 최소 시간 (초). */
@@ -18,9 +18,9 @@
* 입력: 매 mtb cycle (≈1초 주기) 마다 IMU sample 리스트 + 현재 pitch + 시각
* 출력: 현재 walking 상태 (Boolean) + 진단 정보
*/
package com.example.medilightv2android.managers
package com.medithings.vesiscan.managers
import com.example.medilightv2android.ble.ImuSample
import com.medithings.vesiscan.ble.ImuSample
import kotlin.math.abs
import kotlin.math.sqrt
@@ -1,4 +1,4 @@
package com.example.medilightv2android.measure
package com.medithings.vesiscan.measure
data class CCPosition(
val cc: Int,
@@ -1,4 +1,4 @@
package com.example.medilightv2android.measure
package com.medithings.vesiscan.measure
import android.graphics.Bitmap
import android.graphics.Color
@@ -6,7 +6,7 @@ import android.util.Log
import com.google.mlkit.vision.common.InputImage
import com.google.mlkit.vision.text.TextRecognition
import com.google.mlkit.vision.text.latin.TextRecognizerOptions
import com.example.medilightv2android.measure.CCPosition
import com.medithings.vesiscan.measure.CCPosition
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
@@ -1,4 +1,4 @@
package com.example.medilightv2android.measure
package com.medithings.vesiscan.measure
import android.content.Context
import android.content.SharedPreferences
@@ -1,4 +1,4 @@
package com.example.medilightv2android.measure
package com.medithings.vesiscan.measure
import android.content.Context
import android.graphics.Bitmap
@@ -1,4 +1,4 @@
package com.example.medilightv2android.models
package com.medithings.vesiscan.models
data class BladderLevel(
var currentLevel: Int = 0,
@@ -1,4 +1,4 @@
package com.example.medilightv2android.models
package com.medithings.vesiscan.models
import java.text.SimpleDateFormat
import java.util.Date
@@ -1,4 +1,4 @@
package com.example.medilightv2android.models
package com.medithings.vesiscan.models
import java.util.Date
import java.util.UUID
@@ -1,4 +1,4 @@
package com.example.medilightv2android.models
package com.medithings.vesiscan.models
import androidx.compose.ui.graphics.Color
@@ -1,4 +1,4 @@
package com.example.medilightv2android.models
package com.medithings.vesiscan.models
data class NirsMcjPacket(
val battery: Int,
@@ -16,7 +16,7 @@ data class NirsMcjPacket(
fun parse(data: ByteArray): NirsMcjPacket? {
if (data.size < 72) {
if (com.example.medilightv2android.BuildConfig.DEBUG) {
if (com.medithings.vesiscan.BuildConfig.DEBUG) {
android.util.Log.e(TAG, "parse: data too small: ${data.size} < 72")
}
return null
@@ -42,7 +42,7 @@ data class NirsMcjPacket(
for (i in 0 until 24) {
val offset = base + 20 + (i * 2)
if (offset + 1 >= data.size) {
if (com.example.medilightv2android.BuildConfig.DEBUG) {
if (com.medithings.vesiscan.BuildConfig.DEBUG) {
android.util.Log.e(TAG, "parse: LED[$i] out of bounds: offset=${offset+1} >= size=${data.size}")
}
return null
@@ -50,7 +50,7 @@ data class NirsMcjPacket(
ledValues[i] = u16(offset)
}
if (com.example.medilightv2android.BuildConfig.DEBUG) {
if (com.medithings.vesiscan.BuildConfig.DEBUG) {
android.util.Log.d(TAG, "parse OK: battery=$battery led[0..5]=${ledValues.take(6)}")
}
@@ -1,4 +1,4 @@
package com.example.medilightv2android.models
package com.medithings.vesiscan.models
enum class Posture(val displayName: String) {
STANDING("Standing"),
@@ -1,4 +1,4 @@
package com.example.medilightv2android.models
package com.medithings.vesiscan.models
enum class SensorMode(val displayName: String) {
NIRS("NIRS"),
@@ -1,4 +1,4 @@
package com.example.medilightv2android.models
package com.medithings.vesiscan.models
import androidx.compose.ui.graphics.Color
@@ -1,4 +1,4 @@
package com.example.medilightv2android.models
package com.medithings.vesiscan.models
enum class Sex { MALE, FEMALE }
@@ -1,4 +1,4 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.os.Environment
import java.io.File
@@ -63,15 +63,15 @@ object AdcCsvLogger {
val timestamp = timeFmt.format(Date())
val volStr = volumeMl?.let { "%.1f".format(it) } ?: ""
val lrStr = "%.2f".format(lrRatio)
val analyzer = com.example.medilightv2android.managers.PiezoEchoAnalyzer.shared
val analyzer = com.medithings.vesiscan.managers.PiezoEchoAnalyzer.shared
val thrStr = if (analyzer.useAdaptiveThreshold && analyzer.lastOtsuThreshold > 0)
"%.0f".format(analyzer.lastOtsuThreshold) else "%.0f".format(com.example.medilightv2android.managers.GreenZoneConstants.lowEchoAmp)
val dpsStr = "%.3f".format(com.example.medilightv2android.managers.PiezoHW.distancePerSample)
"%.0f".format(analyzer.lastOtsuThreshold) else "%.0f".format(com.medithings.vesiscan.managers.GreenZoneConstants.lowEchoAmp)
val dpsStr = "%.3f".format(com.medithings.vesiscan.managers.PiezoHW.distancePerSample)
val sgStr = if (analyzer.useSgFilter) "ON" else "OFF"
val clinicalLabel = ClinicalSessionStore.currentLabel() // 일반 모드면 ""
// BLE 펌웨어 버전 (연결 안 됐으면 "")
val fwVersion = com.example.medilightv2android.ble.BleManager.current?.firmwareVersion?.value ?: ""
val fwVersion = com.medithings.vesiscan.ble.BleManager.current?.firmwareVersion?.value ?: ""
java.io.FileWriter(file, !isNew).buffered().use { writer ->
if (isNew) {
@@ -1,4 +1,4 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import android.content.Intent
@@ -1,4 +1,4 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.app.Notification
import android.app.NotificationChannel
@@ -11,8 +11,8 @@ import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import androidx.core.app.NotificationCompat
import com.example.medilightv2android.MainActivity
import com.example.medilightv2android.R
import com.medithings.vesiscan.MainActivity
import com.medithings.vesiscan.R
/**
* BLE 연결 유지를 위한 Foreground Service.
@@ -25,8 +25,8 @@ class BleForegroundService : Service() {
companion object {
const val CHANNEL_ID = "vesiscan_ble_channel"
const val NOTIFICATION_ID = 1001
const val ACTION_START = "com.example.medilightv2android.BLE_START"
const val ACTION_STOP = "com.example.medilightv2android.BLE_STOP"
const val ACTION_START = "com.medithings.vesiscan.BLE_START"
const val ACTION_STOP = "com.medithings.vesiscan.BLE_STOP"
fun start(context: Context) {
// 배터리 최적화 제외 요청 제거 — 다른 페이지로 이동되는 UX 문제
@@ -1,10 +1,10 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import android.os.Environment
import com.example.medilightv2android.ble.ImuSample
import com.example.medilightv2android.ble.PiezoChannelData
import com.example.medilightv2android.models.ClinicalSession
import com.medithings.vesiscan.ble.ImuSample
import com.medithings.vesiscan.ble.PiezoChannelData
import com.medithings.vesiscan.models.ClinicalSession
import org.json.JSONArray
import org.json.JSONObject
import java.io.File
@@ -59,16 +59,16 @@ object ClinicalSessionStore {
/** 다음 측정 시 기본값으로 자동 채울 사용자 입력 — 같은 피험자/검사자 여러 측정 시 편의 */
var lastExaminer: String = ""
var lastNotes: String = ""
var lastSubjectType: com.example.medilightv2android.models.SubjectType =
com.example.medilightv2android.models.SubjectType.PHANTOM
var lastSubjectType: com.medithings.vesiscan.models.SubjectType =
com.medithings.vesiscan.models.SubjectType.PHANTOM
var lastSubject: String = "" // 카테고리 내 식별자 (예: "500mL", "S001")
var lastTrueVolumeMl: String = "" // 문자열로 보관 (입력 폼과 동일 형식)
var lastAbdomenThicknessMm: String = ""
// 회의 결정: Step/Posture 마지막 선택 유지 — 매번 0cm로 리셋되는 불편 제거
var lastPosture: com.example.medilightv2android.models.ClinicalPosture =
com.example.medilightv2android.models.ClinicalPosture.SUPINE
var lastStep: com.example.medilightv2android.models.ClinicalStep =
com.example.medilightv2android.models.ClinicalStep.ALIGN_0CM
var lastPosture: com.medithings.vesiscan.models.ClinicalPosture =
com.medithings.vesiscan.models.ClinicalPosture.SUPINE
var lastStep: com.medithings.vesiscan.models.ClinicalStep =
com.medithings.vesiscan.models.ClinicalStep.ALIGN_0CM
/** End 시점에 measurement.json 통합 생성용 — 측정 중 사이클 누적 */
private val cyclesBuffer = mutableListOf<MeasurementCycle>()
@@ -186,7 +186,7 @@ object ClinicalSessionStore {
put("android_release", android.os.Build.VERSION.RELEASE)
put("android_sdk", android.os.Build.VERSION.SDK_INT)
// VBT 디바이스 정보 (mid?/rid: 응답 파싱값) — 분석 시 펌웨어별 데이터 grouping용
val ble = com.example.medilightv2android.ble.BleManager.getInstance(context)
val ble = com.medithings.vesiscan.ble.BleManager.getInstance(context)
val fw = ble.firmwareVersion.value
val hw = ble.hardwareVersion.value
val sn = ble.serialNumber.value
@@ -224,7 +224,7 @@ object ClinicalSessionStore {
// meta: writeMeta()와 동일 내용 포함 (단독 파일로 자족 가능)
// alignment 모드 → dataType=002, 그 외 = 001 (기존 measurement)
val effectiveDataType = if (s.mode == com.example.medilightv2android.models.SessionMode.ALIGNMENT)
val effectiveDataType = if (s.mode == com.medithings.vesiscan.models.SessionMode.ALIGNMENT)
"002" else DATA_TYPE
val meta = JSONObject().apply {
put("data_type", effectiveDataType)
@@ -254,7 +254,7 @@ object ClinicalSessionStore {
put("app_version_name", try {
context.packageManager.getPackageInfo(context.packageName, 0).versionName ?: "unknown"
} catch (_: Exception) { "unknown" })
val ble = com.example.medilightv2android.ble.BleManager.current
val ble = com.medithings.vesiscan.ble.BleManager.current
ble?.firmwareVersion?.value?.takeIf { it.isNotEmpty() }?.let { put("firmware_version", it) }
ble?.hardwareVersion?.value?.takeIf { it.isNotEmpty() }?.let { put("hardware_version", it) }
ble?.serialNumber?.value?.takeIf { it.isNotEmpty() }?.let { put("serial_number", it) }
@@ -1,6 +1,6 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import com.example.medilightv2android.ble.ImuSample
import com.medithings.vesiscan.ble.ImuSample
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
@@ -38,7 +38,7 @@ object ImuCsvLogger {
val scanId = AdcCsvLogger.lastScanId // piezo adc.csv와 매칭용
val timestamp = timeFmt.format(Date())
val clinicalLabel = ClinicalSessionStore.currentLabel()
val fwVersion = com.example.medilightv2android.ble.BleManager.current?.firmwareVersion?.value ?: ""
val fwVersion = com.medithings.vesiscan.ble.BleManager.current?.firmwareVersion?.value ?: ""
file.bufferedWriter().use { _ -> } // ensure exists
java.io.FileWriter(file, !isNew).buffered().use { writer ->
@@ -1,4 +1,4 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import android.content.SharedPreferences
@@ -1,4 +1,4 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import org.json.JSONArray
@@ -13,7 +13,7 @@
* Android 13+ 의 per-app locale API (AppCompatDelegate.setApplicationLocales) 와
* 무관하게 Configuration override 방식으로 모든 SDK 에서 동작.
*/
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import android.content.res.Configuration
@@ -1,8 +1,8 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import android.content.SharedPreferences
import com.example.medilightv2android.models.MeasurementRecord
import com.medithings.vesiscan.models.MeasurementRecord
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
@@ -1,4 +1,4 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import android.os.Build
@@ -70,7 +70,7 @@ class MeasurementLogService private constructor(private val context: Context) {
val clinical = ClinicalSessionStore.currentLabel()
if (clinical.isNotEmpty()) put("clinical_label", clinical)
// BLE 펌웨어 버전 (연결 시 mid?/rid: 응답에서 받음)
val fw = com.example.medilightv2android.ble.BleManager.current?.firmwareVersion?.value
val fw = com.medithings.vesiscan.ble.BleManager.current?.firmwareVersion?.value
if (!fw.isNullOrEmpty()) put("firmware_version", fw)
}
@@ -136,7 +136,7 @@ class MeasurementLogService private constructor(private val context: Context) {
val clinical = ClinicalSessionStore.currentLabel()
if (clinical.isNotEmpty()) put("clinical_label", clinical)
// BLE 펌웨어 버전
val fw = com.example.medilightv2android.ble.BleManager.current?.firmwareVersion?.value
val fw = com.medithings.vesiscan.ble.BleManager.current?.firmwareVersion?.value
if (!fw.isNullOrEmpty()) put("firmware_version", fw)
}
appendLog(entry, "placements.jsonl")
@@ -1,9 +1,9 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import androidx.compose.runtime.mutableStateOf
import com.example.medilightv2android.ble.BleManager
import com.example.medilightv2android.models.SensorMode
import com.medithings.vesiscan.ble.BleManager
import com.medithings.vesiscan.models.SensorMode
class MeasurementService private constructor(context: Context) {
companion object {
@@ -1,4 +1,4 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.app.NotificationChannel
import android.app.NotificationManager
@@ -6,8 +6,8 @@ import android.content.Context
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.example.medilightv2android.R
import com.example.medilightv2android.models.UrgencyLevel
import com.medithings.vesiscan.R
import com.medithings.vesiscan.models.UrgencyLevel
class NotificationService private constructor(private val context: Context) {
companion object {
@@ -23,7 +23,7 @@
*
* 분석: CSV → Excel / python pandas → ANNOTATION 과 CYCLE 의 walking 전이 대조.
*/
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import android.os.Environment
@@ -9,10 +9,10 @@
* saveAll(context) — slider 변경 시 호출 → 현재 GreenZoneConstants → SharedPreferences
* resetAll(context) — 사용자가 reset 누름 → defaults 로 복원
*/
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import com.example.medilightv2android.managers.GreenZoneConstants
import com.medithings.vesiscan.managers.GreenZoneConstants
object PostureTuningPrefs {
@@ -10,7 +10,7 @@
* 사용: startCapture() / stopCapture() 토글. 활성화 시 BleManager.processReceivedData
* 가 매 notification 마다 write() 호출.
*/
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.os.Environment
import java.io.File
@@ -1,4 +1,4 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.app.AlarmManager
import android.app.NotificationChannel
@@ -15,7 +15,7 @@ import android.os.Vibrator
import android.os.VibratorManager
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.example.medilightv2android.R
import com.medithings.vesiscan.R
import java.util.Calendar
class ReminderService private constructor(private val context: Context) {
@@ -1,6 +1,6 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import com.example.medilightv2android.ble.PiezoChannelData
import com.medithings.vesiscan.ble.PiezoChannelData
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -1,8 +1,8 @@
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import android.content.SharedPreferences
import com.example.medilightv2android.models.*
import com.medithings.vesiscan.models.*
import com.google.gson.Gson
class UserStorage private constructor(context: Context) {
@@ -4,7 +4,7 @@
* 사용자가 "설정 탭" 에서 toggle on/off → 일어남 감지 시 빨간 팝업.
* LYING 유지 시간 임계 (default 3 min) 도 함께.
*/
package com.example.medilightv2android.services
package com.medithings.vesiscan.services
import android.content.Context
import android.content.SharedPreferences
@@ -1,9 +1,9 @@
package com.example.medilightv2android.services.labdb
package com.medithings.vesiscan.services.labdb
import android.content.Context
import android.os.Build
import android.util.Log
import com.example.medilightv2android.ble.BleManager
import com.medithings.vesiscan.ble.BleManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaType
@@ -1,6 +1,6 @@
package com.example.medilightv2android.services.labdb
package com.medithings.vesiscan.services.labdb
import com.example.medilightv2android.services.KeychainService
import com.medithings.vesiscan.services.KeychainService
/**
* labdb (https://labdb.medithings.net) 자격 증명 저장소.
@@ -1,4 +1,4 @@
package com.example.medilightv2android.services.labdb
package com.medithings.vesiscan.services.labdb
import android.content.Context
import android.util.Log
@@ -4,7 +4,7 @@
* MEDiThings Inc.
* All rights reserved.
*/
package com.example.medilightv2android.speech
package com.medithings.vesiscan.speech
import android.util.Log
import kotlinx.coroutines.Dispatchers
@@ -4,7 +4,7 @@
* MEDiThings Inc.
* All rights reserved.
*/
package com.example.medilightv2android.speech
package com.medithings.vesiscan.speech
import android.content.Context
import android.content.Intent
@@ -4,7 +4,7 @@
* MEDiThings Inc.
* All rights reserved.
*/
package com.example.medilightv2android.speech
package com.medithings.vesiscan.speech
/**
* Local (offline) parser that extracts a volume in milliliters from speech-recognition text.
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.components
package com.medithings.vesiscan.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
@@ -22,8 +22,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.R
import com.example.medilightv2android.ble.BleManager
import com.medithings.vesiscan.R
import com.medithings.vesiscan.ble.BleManager
/**
* 배터리 잔량 경고 배너 — PlacementGuide / PiezoMonitoring 상단.
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.components
package com.medithings.vesiscan.ui.components
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
@@ -13,8 +13,8 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import app.rive.runtime.kotlin.RiveAnimationView
import app.rive.runtime.kotlin.core.Fit
import com.example.medilightv2android.R
import com.example.medilightv2android.models.UrgencyLevel
import com.medithings.vesiscan.R
import com.medithings.vesiscan.models.UrgencyLevel
import kotlinx.coroutines.delay
import kotlin.random.Random
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.components
package com.medithings.vesiscan.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
@@ -13,7 +13,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.ui.theme.MlPrimary
import com.medithings.vesiscan.ui.theme.MlPrimary
enum class BleReconnectionState {
DISCONNECTED, RECONNECTING, FAILED
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.components
package com.medithings.vesiscan.ui.components
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
@@ -14,7 +14,7 @@ import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.example.medilightv2android.models.UrgencyLevel
import com.medithings.vesiscan.models.UrgencyLevel
@Composable
fun DonutChartView(
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.components
package com.medithings.vesiscan.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
@@ -26,8 +26,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.R
import com.example.medilightv2android.ble.BleManager
import com.medithings.vesiscan.R
import com.medithings.vesiscan.ble.BleManager
import kotlinx.coroutines.delay
/**
@@ -15,7 +15,7 @@
* UX 톤:
* "1회 터치 후 조정" 패턴 — 의도된 조작만 허용.
*/
package com.example.medilightv2android.ui.components
package com.medithings.vesiscan.ui.components
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -39,7 +39,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.example.medilightv2android.R
import com.medithings.vesiscan.R
@Composable
fun LockableSlider(
@@ -5,7 +5,7 @@
* measurement, newest at the bottom, monospace, long-press to select spans
* across entries. Copy puts the full log on the system clipboard.
*/
package com.example.medilightv2android.ui.components
package com.medithings.vesiscan.ui.components
import android.content.ClipData
import android.content.ClipboardManager
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.theme
package com.medithings.vesiscan.ui.theme
import androidx.compose.ui.graphics.Color
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.theme
package com.medithings.vesiscan.ui.theme
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.gestures.detectTapGestures
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.theme
package com.medithings.vesiscan.ui.theme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.lightColorScheme
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.theme
package com.medithings.vesiscan.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.calibration
package com.medithings.vesiscan.ui.views.calibration
import android.os.Handler
import android.os.Looper
@@ -22,13 +22,13 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppState
import com.example.medilightv2android.R
import com.example.medilightv2android.ble.BleManager
import com.example.medilightv2android.managers.NirsManager
import com.example.medilightv2android.models.NirsMagResponse
import com.example.medilightv2android.ui.components.BladdyIdleRiveView
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.R
import com.medithings.vesiscan.ble.BleManager
import com.medithings.vesiscan.managers.NirsManager
import com.medithings.vesiscan.models.NirsMagResponse
import com.medithings.vesiscan.ui.components.BladdyIdleRiveView
import com.medithings.vesiscan.ui.theme.*
@Composable
fun CalibrationView(appState: AppState) {
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.clinical
package com.medithings.vesiscan.ui.views.clinical
import android.widget.Toast
import androidx.compose.foundation.background
@@ -23,15 +23,15 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppScreen
import com.example.medilightv2android.AppState
import com.example.medilightv2android.ble.BleManager
import com.example.medilightv2android.models.*
import com.example.medilightv2android.services.ClinicalSessionStore
import com.example.medilightv2android.services.labdb.LabdbClient
import com.example.medilightv2android.services.labdb.LabdbCredentials
import com.example.medilightv2android.services.labdb.LabdbUploader
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppScreen
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.ble.BleManager
import com.medithings.vesiscan.models.*
import com.medithings.vesiscan.services.ClinicalSessionStore
import com.medithings.vesiscan.services.labdb.LabdbClient
import com.medithings.vesiscan.services.labdb.LabdbCredentials
import com.medithings.vesiscan.services.labdb.LabdbUploader
import com.medithings.vesiscan.ui.theme.*
import kotlinx.coroutines.launch
/**
@@ -397,7 +397,7 @@ fun ClinicalHomeView(appState: AppState) {
// 측정 대상 분류 — Phantom/Human/ETC 버튼 (회의 결정)
LabeledSegmented(
label = "Subject Type",
options = com.example.medilightv2android.models.SubjectType.values().toList(),
options = com.medithings.vesiscan.models.SubjectType.values().toList(),
selected = subjectType,
onSelect = { subjectType = it }
) { it.label }
@@ -492,7 +492,7 @@ fun ClinicalHomeView(appState: AppState) {
subjectType = subjectType, subject = subject.trim(),
trueVolumeMl = trueVolText.toDoubleOrNull(),
abdomenThicknessMm = abdomenText.toDoubleOrNull(),
mode = com.example.medilightv2android.models.SessionMode.MEASUREMENT,
mode = com.medithings.vesiscan.models.SessionMode.MEASUREMENT,
)
)
appState.currentScreen = AppScreen.CLINICAL_LIVE
@@ -517,9 +517,9 @@ fun ClinicalHomeView(appState: AppState) {
subjectType = subjectType, subject = subject.trim(),
trueVolumeMl = trueVolText.toDoubleOrNull(),
abdomenThicknessMm = abdomenText.toDoubleOrNull(),
mode = com.example.medilightv2android.models.SessionMode.ALIGNMENT,
mode = com.medithings.vesiscan.models.SessionMode.ALIGNMENT,
// 현재 dev 토글된 algo 그대로 — V1 (default) 또는 V2.
alignmentAlgo = com.example.medilightv2android.managers.GreenZoneConstants.alignmentAlgo.name,
alignmentAlgo = com.medithings.vesiscan.managers.GreenZoneConstants.alignmentAlgo.name,
)
)
appState.enterAlignmentSession()
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.clinical
package com.medithings.vesiscan.ui.views.clinical
import android.widget.Toast
import androidx.compose.foundation.Canvas
@@ -25,17 +25,17 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppScreen
import com.example.medilightv2android.AppState
import com.example.medilightv2android.ble.BleManager
import com.example.medilightv2android.ble.ImuSample
import com.example.medilightv2android.ble.PiezoChannelData
import com.example.medilightv2android.managers.ImuAnalysis
import com.example.medilightv2android.services.AdcCsvLogger
import com.example.medilightv2android.services.ClinicalSessionStore
import com.example.medilightv2android.services.ImuCsvLogger
import com.example.medilightv2android.services.MeasurementLogService
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppScreen
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.ble.BleManager
import com.medithings.vesiscan.ble.ImuSample
import com.medithings.vesiscan.ble.PiezoChannelData
import com.medithings.vesiscan.managers.ImuAnalysis
import com.medithings.vesiscan.services.AdcCsvLogger
import com.medithings.vesiscan.services.ClinicalSessionStore
import com.medithings.vesiscan.services.ImuCsvLogger
import com.medithings.vesiscan.services.MeasurementLogService
import com.medithings.vesiscan.ui.theme.*
import kotlinx.coroutines.delay
import kotlin.math.max
import kotlin.math.min
@@ -79,7 +79,7 @@ fun ClinicalLiveView(appState: AppState) {
var pendingPiezo by remember { mutableStateOf<List<PiezoChannelData>?>(null) }
// V4.1 wall detection — 채널별 ant/post peak 표시용 (사내 테스트 가시화 요청)
val v41 = remember { com.example.medilightv2android.walldetect.V41Detector() }
val v41 = remember { com.medithings.vesiscan.walldetect.V41Detector() }
var channelWalls by remember { mutableStateOf<List<Pair<Int, Int>?>>(List(6) { null }) }
DisposableEffect(Unit) {
@@ -91,13 +91,13 @@ fun ClinicalLiveView(appState: AppState) {
val adcMatrix = (0 until 6).map { ch ->
channels.find { it.channel == ch }?.buffer?.map { it.toInt() } ?: List(100) { 0 }
}
val probe = com.example.medilightv2android.walldetect.dto.ProbeProfileDto(
name = com.example.medilightv2android.managers.PiezoHW.presetName,
val probe = com.medithings.vesiscan.walldetect.dto.ProbeProfileDto(
name = com.medithings.vesiscan.managers.PiezoHW.presetName,
rMm = 50.2, anteriorAnchorMm = 32.0,
fsHz = 537500, cMmPerUs = 1.54,
anglesDeg = com.example.medilightv2android.managers.PiezoHW.degreeAll.toList()
anglesDeg = com.medithings.vesiscan.managers.PiezoHW.degreeAll.toList()
)
val sweepInput = com.example.medilightv2android.walldetect.dto.SweepInput(
val sweepInput = com.medithings.vesiscan.walldetect.dto.SweepInput(
requestId = "clinical_${System.currentTimeMillis()}",
timestampMs = System.currentTimeMillis(),
deviceId = bleManager.connectedDeviceName.value,
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.connection
package com.medithings.vesiscan.ui.views.connection
import android.Manifest
import android.content.pm.PackageManager
@@ -34,15 +34,15 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
import com.example.medilightv2android.AppState
import com.example.medilightv2android.R
import com.example.medilightv2android.ble.BleDevice
import com.example.medilightv2android.ble.BleManager
import com.example.medilightv2android.models.SensorMode
import com.example.medilightv2android.services.KnownDevice
import com.example.medilightv2android.services.KnownDeviceStore
import com.example.medilightv2android.ui.components.BladdyIdleRiveView
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.R
import com.medithings.vesiscan.ble.BleDevice
import com.medithings.vesiscan.ble.BleManager
import com.medithings.vesiscan.models.SensorMode
import com.medithings.vesiscan.services.KnownDevice
import com.medithings.vesiscan.services.KnownDeviceStore
import com.medithings.vesiscan.ui.components.BladdyIdleRiveView
import com.medithings.vesiscan.ui.theme.*
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@@ -55,7 +55,7 @@ fun DeviceScanView(appState: AppState) {
var permissionsGranted by remember { mutableStateOf(false) }
// Clinical 흐름에서만 다중 기기 저장/표시 — 일반 사용자는 fresh scan & pair.
val isClinicalFlow = com.example.medilightv2android.services.ClinicalSessionStore.inClinicalFlow
val isClinicalFlow = com.medithings.vesiscan.services.ClinicalSessionStore.inClinicalFlow
var knownDevices by remember {
mutableStateOf(if (isClinicalFlow) KnownDeviceStore.getAll(context) else emptyList())
}
@@ -287,7 +287,7 @@ fun DeviceScanView(appState: AppState) {
Button(
onClick = {
appState.isDeviceConnected = true
appState.currentScreen = com.example.medilightv2android.AppScreen.PIEZO_PERSONALIZATION
appState.currentScreen = com.medithings.vesiscan.AppScreen.PIEZO_PERSONALIZATION
},
modifier = Modifier.fillMaxWidth().height(48.dp),
shape = RoundedCornerShape(12.dp),
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.consent
package com.medithings.vesiscan.ui.views.consent
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -15,13 +15,13 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import com.example.medilightv2android.R
import com.medithings.vesiscan.R
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppState
import com.example.medilightv2android.services.UserStorage
import com.example.medilightv2android.ui.components.BladdyIdleRiveView
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.services.UserStorage
import com.medithings.vesiscan.ui.components.BladdyIdleRiveView
import com.medithings.vesiscan.ui.theme.*
@Composable
fun ConsentView(appState: AppState) {
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.history
package com.medithings.vesiscan.ui.views.history
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
@@ -31,11 +31,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppState
import com.example.medilightv2android.R
import com.example.medilightv2android.models.*
import com.example.medilightv2android.services.MeasurementHistoryStore
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.R
import com.medithings.vesiscan.models.*
import com.medithings.vesiscan.services.MeasurementHistoryStore
import com.medithings.vesiscan.ui.theme.*
import java.text.SimpleDateFormat
import java.util.*
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.home
package com.medithings.vesiscan.ui.views.home
import android.widget.Toast
import androidx.compose.foundation.background
@@ -28,12 +28,12 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import com.example.medilightv2android.R
import com.medithings.vesiscan.R
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppState
import com.example.medilightv2android.ui.components.BladdyIdleRiveView
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.ui.components.BladdyIdleRiveView
import com.medithings.vesiscan.ui.theme.*
@Composable
fun HomeView(appState: AppState) {
@@ -147,7 +147,7 @@ fun HomeView(appState: AppState) {
// Dev 모드 한정 — Clinical R&D Mode 진입
if (appState.isDevMode) {
Button(
onClick = { appState.currentScreen = com.example.medilightv2android.AppScreen.CLINICAL_HOME },
onClick = { appState.currentScreen = com.medithings.vesiscan.AppScreen.CLINICAL_HOME },
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 32.dp)
@@ -166,7 +166,7 @@ fun HomeView(appState: AppState) {
// 언어 선택 다이얼로그 — 시스템 / 한국어 / English. 변경 시 Activity recreate.
if (showLanguageDialog) {
val curMode = com.example.medilightv2android.services.LocalePref.getMode(context)
val curMode = com.medithings.vesiscan.services.LocalePref.getMode(context)
var selected by remember { mutableStateOf(curMode) }
AlertDialog(
onDismissRequest = { showLanguageDialog = false },
@@ -174,9 +174,9 @@ fun HomeView(appState: AppState) {
text = {
Column {
listOf(
com.example.medilightv2android.services.LocalePref.Mode.SYSTEM to stringResource(R.string.language_system_default),
com.example.medilightv2android.services.LocalePref.Mode.KO to stringResource(R.string.language_korean),
com.example.medilightv2android.services.LocalePref.Mode.EN to stringResource(R.string.language_english),
com.medithings.vesiscan.services.LocalePref.Mode.SYSTEM to stringResource(R.string.language_system_default),
com.medithings.vesiscan.services.LocalePref.Mode.KO to stringResource(R.string.language_korean),
com.medithings.vesiscan.services.LocalePref.Mode.EN to stringResource(R.string.language_english),
).forEach { (mode, label) ->
Row(
verticalAlignment = Alignment.CenterVertically,
@@ -197,7 +197,7 @@ fun HomeView(appState: AppState) {
},
confirmButton = {
TextButton(onClick = {
com.example.medilightv2android.services.LocalePref.setMode(context, selected)
com.medithings.vesiscan.services.LocalePref.setMode(context, selected)
showLanguageDialog = false
// Activity recreate → attachBaseContext 다시 호출 → 새 locale 적용
(context as? android.app.Activity)?.recreate()
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.monitoring
package com.medithings.vesiscan.ui.views.monitoring
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
@@ -21,11 +21,11 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
import com.example.medilightv2android.R
import com.example.medilightv2android.measure.VoidingRecord
import com.example.medilightv2android.measure.VoidingRecordStore
import com.example.medilightv2android.speech.SpeechRecognizerManager
import com.example.medilightv2android.speech.VolumeParser
import com.medithings.vesiscan.R
import com.medithings.vesiscan.measure.VoidingRecord
import com.medithings.vesiscan.measure.VoidingRecordStore
import com.medithings.vesiscan.speech.SpeechRecognizerManager
import com.medithings.vesiscan.speech.VolumeParser
/**
* Catheterize 바텀시트 — 수기/음성/카메라 3가지 입력
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.monitoring
package com.medithings.vesiscan.ui.views.monitoring
import android.os.Handler
import android.os.Looper
@@ -6,7 +6,7 @@ import android.util.Log
import androidx.compose.runtime.rememberCoroutineScope
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import com.example.medilightv2android.AppScreen
import com.medithings.vesiscan.AppScreen
import androidx.compose.material3.OutlinedTextField
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
@@ -42,23 +42,23 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppState
import com.example.medilightv2android.ble.BleManager
import com.example.medilightv2android.ble.PiezoChannelData
import com.example.medilightv2android.managers.PiezoEchoAnalyzer
import com.example.medilightv2android.managers.PiezoConstants
import com.example.medilightv2android.managers.GreenZoneConstants
import com.example.medilightv2android.managers.PiezoHW
import com.example.medilightv2android.managers.estimateBladderVolume6ch
import com.example.medilightv2android.models.BladderLevel
import com.example.medilightv2android.models.UrgencyLevel
import com.example.medilightv2android.services.ScanLogStore
import com.example.medilightv2android.ui.components.BladdyRiveView
import com.example.medilightv2android.ui.components.DonutChartView
import com.example.medilightv2android.ui.components.LockableSlider
import com.example.medilightv2android.ui.components.ScanLogDialog
import com.example.medilightv2android.R
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.ble.BleManager
import com.medithings.vesiscan.ble.PiezoChannelData
import com.medithings.vesiscan.managers.PiezoEchoAnalyzer
import com.medithings.vesiscan.managers.PiezoConstants
import com.medithings.vesiscan.managers.GreenZoneConstants
import com.medithings.vesiscan.managers.PiezoHW
import com.medithings.vesiscan.managers.estimateBladderVolume6ch
import com.medithings.vesiscan.models.BladderLevel
import com.medithings.vesiscan.models.UrgencyLevel
import com.medithings.vesiscan.services.ScanLogStore
import com.medithings.vesiscan.ui.components.BladdyRiveView
import com.medithings.vesiscan.ui.components.DonutChartView
import com.medithings.vesiscan.ui.components.LockableSlider
import com.medithings.vesiscan.ui.components.ScanLogDialog
import com.medithings.vesiscan.R
import com.medithings.vesiscan.ui.theme.*
import androidx.compose.ui.res.stringResource
import kotlin.math.roundToInt
@@ -132,21 +132,21 @@ fun PiezoMonitoringView(appState: AppState) {
val analyzer = remember { PiezoEchoAnalyzer.shared }
// Posture (flowchart-based, IMU polling — Phase 1) + Wakeup/Walking detector (Phase 2)
var currentPosture by remember { mutableStateOf(com.example.medilightv2android.managers.Posture.UNKNOWN) }
var currentPosture by remember { mutableStateOf(com.medithings.vesiscan.managers.Posture.UNKNOWN) }
var showWakeupAlarm by remember { mutableStateOf(false) } // 주황 — LYING → NON_LYING/WALKING
var wakeupAlarmElapsedSec by remember { mutableStateOf(0L) }
var showWalkingAlarm by remember { mutableStateOf(false) } // 빨강 — NON_LYING → WALKING
val walkingDetector = remember { com.example.medilightv2android.managers.WalkingDetector() }
val walkingDetector = remember { com.medithings.vesiscan.managers.WalkingDetector() }
val wakeupDetector = remember {
com.example.medilightv2android.managers.WakeupDetector(
lyingDurationSec = com.example.medilightv2android.services.WakeupAlarmPrefs.lyingDurationSec(context)
com.medithings.vesiscan.managers.WakeupDetector(
lyingDurationSec = com.medithings.vesiscan.services.WakeupAlarmPrefs.lyingDurationSec(context)
).apply {
onWakeup = { elapsed ->
if (com.example.medilightv2android.services.WakeupAlarmPrefs.isEnabled(context)) {
if (com.medithings.vesiscan.services.WakeupAlarmPrefs.isEnabled(context)) {
wakeupAlarmElapsedSec = elapsed
showWakeupAlarm = true
}
com.example.medilightv2android.services.PostureEventLogger.logAlarm(
com.medithings.vesiscan.services.PostureEventLogger.logAlarm(
System.currentTimeMillis(),
"wakeup_alarm_lying_${elapsed}s"
)
@@ -317,7 +317,7 @@ fun PiezoMonitoringView(appState: AppState) {
val fullChannels = channels.filter { it.buffer.size >= 20 }
if (fullChannels.size >= 6) {
val sortedBuffers = channels.sortedBy { it.channel }.map { it.buffer }
val detachResult = com.example.medilightv2android.managers.DetachmentDetection.detect(sortedBuffers)
val detachResult = com.medithings.vesiscan.managers.DetachmentDetection.detect(sortedBuffers)
if (detachResult.isDetached) {
if (!wasDetached) {
Log.w("PiezoMonitor", "DETACHED mean=${"%.1f".format(detachResult.meanAbs)} std=${"%.1f".format(detachResult.stdVal)}")
@@ -341,28 +341,28 @@ fun PiezoMonitoringView(appState: AppState) {
val validChannels = channels.filter { it.isValid }
val allChannelsReceived = channels.filter { it.buffer.size >= 20 }.size >= 6
if (validChannels.isNotEmpty() && allChannelsReceived) {
val method = com.example.medilightv2android.managers.GreenZoneConstants.detectionMethod
val analyzerA = com.example.medilightv2android.managers.PiezoEchoAnalyzerA.shared
val method = com.medithings.vesiscan.managers.GreenZoneConstants.detectionMethod
val analyzerA = com.medithings.vesiscan.managers.PiezoEchoAnalyzerA.shared
var methodCBvMl: Double? = null
val methodLabel: String
when (method) {
com.example.medilightv2android.managers.DetectionMethod.METHOD_C -> {
com.medithings.vesiscan.managers.DetectionMethod.METHOD_C -> {
methodLabel = "C"
// V4.1 detector
val v41 = com.example.medilightv2android.walldetect.V41Detector()
val v41 = com.medithings.vesiscan.walldetect.V41Detector()
val adcMatrix = (0 until 6).map { ch ->
val chData = channels.find { it.channel == ch }
chData?.buffer?.map { it.toInt() } ?: List(100) { 0 }
}
val probe = com.example.medilightv2android.walldetect.dto.ProbeProfileDto(
name = com.example.medilightv2android.managers.PiezoHW.presetName,
val probe = com.medithings.vesiscan.walldetect.dto.ProbeProfileDto(
name = com.medithings.vesiscan.managers.PiezoHW.presetName,
rMm = 50.2, anteriorAnchorMm = 32.0,
fsHz = 537500, cMmPerUs = 1.54,
anglesDeg = com.example.medilightv2android.managers.PiezoHW.degreeAll.toList()
anglesDeg = com.medithings.vesiscan.managers.PiezoHW.degreeAll.toList()
)
val sweepInput = com.example.medilightv2android.walldetect.dto.SweepInput(
val sweepInput = com.medithings.vesiscan.walldetect.dto.SweepInput(
requestId = "measure_${System.currentTimeMillis()}",
timestampMs = System.currentTimeMillis(),
deviceId = bleManager.connectedDeviceName.value,
@@ -395,7 +395,7 @@ fun PiezoMonitoringView(appState: AppState) {
Log.d("PiezoMonitor", " CH${ch.ch}[C]: ant=${ch.antIdx} post=${ch.postIdx} chord=${ch.chordMm?.let { "%.1f".format(it) }}mm")
}
}
com.example.medilightv2android.managers.DetectionMethod.METHOD_A -> {
com.medithings.vesiscan.managers.DetectionMethod.METHOD_A -> {
methodLabel = "A"
val channelResults = validChannels.map { analyzerA.analyzeChannel(it.buffer, it.channel) }
for (ch in channelResults) {
@@ -407,14 +407,14 @@ fun PiezoMonitoringView(appState: AppState) {
if (ch.isValid && ch.result != null) Log.d("PiezoMonitor", " CH${ch.channel}[A]: ant=${ch.result.ant} post=${ch.result.post} urine=${ch.result.urineLen}")
}
}
com.example.medilightv2android.managers.DetectionMethod.METHOD_D -> {
com.medithings.vesiscan.managers.DetectionMethod.METHOD_D -> {
// 2026-06-30: Detection + BV 통합. MethodDRunner 로 6채널 raw → walls.
methodLabel = "D"
val signals = (0..5).map { ch ->
val cd = channels.find { it.channel == ch }
cd?.buffer?.map { it.toDouble() }?.toDoubleArray() ?: DoubleArray(0)
}
val dets = com.example.medilightv2android.walldetect.MethodDRunner
val dets = com.medithings.vesiscan.walldetect.MethodDRunner
.detectMultichannel(signals)
for (i in 0..5) {
val r = dets.getOrNull(i)
@@ -443,10 +443,10 @@ fun PiezoMonitoringView(appState: AppState) {
totalWallCount = allWalls.count { it != null }
// ADC 로그 저장 — allWalls (선택된 Method) 기준으로 통일
val logService = com.example.medilightv2android.services.MeasurementLogService.getInstance(context)
val logService = com.medithings.vesiscan.services.MeasurementLogService.getInstance(context)
val channelLogs = (0..5).map { ch ->
val w = allWalls[ch]
com.example.medilightv2android.services.ChannelLogEntry(
com.medithings.vesiscan.services.ChannelLogEntry(
channel = ch,
ant = w?.first,
post = w?.second,
@@ -456,7 +456,7 @@ fun PiezoMonitoringView(appState: AppState) {
}
val rawADC = channels.sortedBy { it.channel }.map { it.buffer }
val bvMethodSetting = com.example.medilightv2android.managers.GreenZoneConstants.bvMethod
val bvMethodSetting = com.medithings.vesiscan.managers.GreenZoneConstants.bvMethod
// ── Ant-offset adjustment for BV calculation ───────────────────────────────
// The user-facing setting is a non-negative magnitude in mm. BV calculation
// subtracts it from each channel's anterior wall index (probe-ward shift).
@@ -467,13 +467,13 @@ fun PiezoMonitoringView(appState: AppState) {
val antOffsetSamples =
if (antOffsetMm != 0)
(antOffsetMm.toDouble() /
com.example.medilightv2android.managers.PiezoHW.distancePerSample).toInt()
com.medithings.vesiscan.managers.PiezoHW.distancePerSample).toInt()
else 0
// 2026-06-30: BvMethod.METHOD_D 시 Method D walls 사용. 단 detection 이
// 이미 METHOD_D 면 allWalls 가 곧 Method D → recompute 생략.
val useMethodDBv = bvMethodSetting == com.example.medilightv2android.managers.BvMethod.METHOD_D
val detectionIsMethodD = method == com.example.medilightv2android.managers.DetectionMethod.METHOD_D
val useMethodDBv = bvMethodSetting == com.medithings.vesiscan.managers.BvMethod.METHOD_D
val detectionIsMethodD = method == com.medithings.vesiscan.managers.DetectionMethod.METHOD_D
val sourceAllWalls: List<Pair<Int, Int>?> = if (useMethodDBv && !detectionIsMethodD) {
val signals = (0..5).map { ch ->
val cd = channels.find { it.channel == ch }
@@ -482,10 +482,10 @@ fun PiezoMonitoringView(appState: AppState) {
if (signals.all { it.isEmpty() }) allWalls
// 2026-07-02: NEW BV lib (piezophantomtest 4830e7c) lumen_inset_frac=0.15
// MethodDResult 의 (ls, le) 로 벽을 lumen 안쪽으로 15% 이동.
else com.example.medilightv2android.walldetect.MethodDRunner
else com.medithings.vesiscan.walldetect.MethodDRunner
.detectMultichannel(signals)
.map { r -> r?.let {
com.example.medilightv2android.managers.applyLumenInsetOne(
com.medithings.vesiscan.managers.applyLumenInsetOne(
it.ant, it.post, it.lowStart, it.lowEnd
)
} }
@@ -498,8 +498,8 @@ fun PiezoMonitoringView(appState: AppState) {
}
val effectiveCenterWalls = (0..3).count { effectiveAllWalls[it] != null }
val useV41Bv = method == com.example.medilightv2android.managers.DetectionMethod.METHOD_C
&& bvMethodSetting == com.example.medilightv2android.managers.BvMethod.V41
val useV41Bv = method == com.medithings.vesiscan.managers.DetectionMethod.METHOD_C
&& bvMethodSetting == com.medithings.vesiscan.managers.BvMethod.V41
&& methodCBvMl != null
&& antOffsetSamples == 0
&& effectiveCenterWalls >= 4 // center 4 모두 필요
@@ -510,7 +510,7 @@ fun PiezoMonitoringView(appState: AppState) {
bleManager.debugLogger.measurementResult(methodCBvMl, 1.0, totalWallCount,
(0..5).map { allWalls[it]?.let { w -> w.second - w.first } ?: 0 })
logService.logMeasurement(methodCBvMl, channelLogs, rawADC)
com.example.medilightv2android.services.AdcCsvLogger.log(rawADC, methodCBvMl)
com.medithings.vesiscan.services.AdcCsvLogger.log(rawADC, methodCBvMl)
} else if (effectiveCenterWalls >= 4) {
// 검증 로그 — ant offset 비활성(0)이 아닐 때 chord 변화 출력
if (antOffsetSamples != 0) {
@@ -534,18 +534,18 @@ fun PiezoMonitoringView(appState: AppState) {
(0..5).map { allWalls[it]?.let { w -> w.second - w.first } ?: 0 },
otsuThreshold = analyzer.lastOtsuThreshold)
logService.logMeasurement(bvResult.volumeMl, channelLogs, rawADC)
com.example.medilightv2android.services.AdcCsvLogger.log(rawADC, bvResult.volumeMl, bvResult.lrRatio)
com.medithings.vesiscan.services.AdcCsvLogger.log(rawADC, bvResult.volumeMl, bvResult.lrRatio)
}
} else if (totalWallCount > 0) {
Log.w("PiezoMonitor", "No center channels: center=0 total=$totalWallCount/6")
bleManager.debugLogger.warn("BV_SKIP scan=${com.example.medilightv2android.services.AdcCsvLogger.lastScanId} center=0 total=$totalWallCount/6")
com.example.medilightv2android.services.AdcCsvLogger.log(rawADC, null)
bleManager.debugLogger.warn("BV_SKIP scan=${com.medithings.vesiscan.services.AdcCsvLogger.lastScanId} center=0 total=$totalWallCount/6")
com.medithings.vesiscan.services.AdcCsvLogger.log(rawADC, null)
}
} else {
Log.d("PiezoMonitor", "No valid channels — volume unchanged")
bleManager.debugLogger.warn("BV_FAIL scan=${com.example.medilightv2android.services.AdcCsvLogger.lastScanId} no valid channels")
bleManager.debugLogger.warn("BV_FAIL scan=${com.medithings.vesiscan.services.AdcCsvLogger.lastScanId} no valid channels")
val failADC = channels.sortedBy { it.channel }.map { it.buffer }
com.example.medilightv2android.services.AdcCsvLogger.log(failADC, null)
com.medithings.vesiscan.services.AdcCsvLogger.log(failADC, null)
}
// allWalls를 UI state에 저장 (ChannelPanel에서 사용)
@@ -754,8 +754,8 @@ fun PiezoMonitoringView(appState: AppState) {
// Posture event 로깅 — 검증용 CSV (앱 진입 시 새 파일)
// + 사용자 튜닝 임계값 SharedPreferences 에서 로드
LaunchedEffect(Unit) {
com.example.medilightv2android.services.PostureTuningPrefs.loadAll(context)
com.example.medilightv2android.services.PostureEventLogger.startSession(context)
com.medithings.vesiscan.services.PostureTuningPrefs.loadAll(context)
com.medithings.vesiscan.services.PostureEventLogger.startSession(context)
}
// IMU polling + 자세 분류 — msp 명령 (rsp: 응답, IMU-only).
@@ -766,12 +766,12 @@ fun PiezoMonitoringView(appState: AppState) {
LaunchedEffect(isConnected, isDemoMode) {
Log.d("ImuDbg", "LaunchedEffect start isConnected=$isConnected isDemoMode=$isDemoMode")
if (isDemoMode) {
currentPosture = com.example.medilightv2android.managers.Posture.LYING
currentPosture = com.medithings.vesiscan.managers.Posture.LYING
return@LaunchedEffect
}
var unknownStreak = 0
bleManager.imuCollector.onComplete = { samples ->
val r = com.example.medilightv2android.managers.ImuPostureClassifier.classify(samples)
val r = com.medithings.vesiscan.managers.ImuPostureClassifier.classify(samples)
val nowMs = System.currentTimeMillis()
// Walking detector — pitch 가 valid 일 때만 의미. acc gate fail 시 그대로 update (wmean/wstd 계산 + 시간 grace 처리).
val walkSnap = walkingDetector.update(samples, r.pitchDeg, nowMs)
@@ -779,34 +779,34 @@ fun PiezoMonitoringView(appState: AppState) {
// Composite posture — WALKING 이 UNKNOWN/NON_LYING 보다 우선 (자체 게이트 신뢰)
val composite = when {
isWalkingNow -> com.example.medilightv2android.managers.Posture.WALKING
r.posture == com.example.medilightv2android.managers.Posture.UNKNOWN -> com.example.medilightv2android.managers.Posture.UNKNOWN
isWalkingNow -> com.medithings.vesiscan.managers.Posture.WALKING
r.posture == com.medithings.vesiscan.managers.Posture.UNKNOWN -> com.medithings.vesiscan.managers.Posture.UNKNOWN
else -> r.posture // LYING or NON_LYING
}
if (composite != com.example.medilightv2android.managers.Posture.UNKNOWN) {
if (composite != com.medithings.vesiscan.managers.Posture.UNKNOWN) {
currentPosture = composite
wakeupDetector.update(composite)
unknownStreak = 0
} else {
unknownStreak++
if (unknownStreak >= 3) currentPosture = com.example.medilightv2android.managers.Posture.UNKNOWN
if (unknownStreak >= 3) currentPosture = com.medithings.vesiscan.managers.Posture.UNKNOWN
}
// Walking 시작 전이 (NON_WALKING → WALKING) — critical 알람 (alarm enabled 시)
if (isWalkingNow && !prevIsWalking) {
if (com.example.medilightv2android.services.WakeupAlarmPrefs.isEnabled(context)) {
if (com.medithings.vesiscan.services.WakeupAlarmPrefs.isEnabled(context)) {
showWalkingAlarm = true
}
com.example.medilightv2android.services.PostureEventLogger.logAlarm(nowMs, "walking_start")
com.medithings.vesiscan.services.PostureEventLogger.logAlarm(nowMs, "walking_start")
}
if (!isWalkingNow && prevIsWalking) {
com.example.medilightv2android.services.PostureEventLogger.logAlarm(nowMs, "walking_end")
com.medithings.vesiscan.services.PostureEventLogger.logAlarm(nowMs, "walking_end")
}
prevIsWalking = isWalkingNow
// CSV logging — 검증용
com.example.medilightv2android.services.PostureEventLogger.logCycle(
com.medithings.vesiscan.services.PostureEventLogger.logCycle(
nowMs, composite.name, isWalkingNow,
r.pitchDeg, walkSnap.wmean, walkSnap.wstd, r.accMag, r.gyroMagDps,
)
@@ -961,8 +961,8 @@ fun PiezoMonitoringView(appState: AppState) {
val quickVol = if (lastVolumeMl > 0) lastVolumeMl.toInt() else appState.estimatedVolume
Surface(
onClick = {
com.example.medilightv2android.measure.VoidingRecordStore.add(
context, com.example.medilightv2android.measure.VoidingRecord(
com.medithings.vesiscan.measure.VoidingRecordStore.add(
context, com.medithings.vesiscan.measure.VoidingRecord(
volume = quickVol, method = "catheterize"
)
)
@@ -1021,8 +1021,8 @@ fun PiezoMonitoringView(appState: AppState) {
TextButton(onClick = {
val vol = volumeText.toIntOrNull()
if (vol != null && vol in 1..1000) {
com.example.medilightv2android.measure.VoidingRecordStore.add(
context, com.example.medilightv2android.measure.VoidingRecord(volume = vol, method = "manual")
com.medithings.vesiscan.measure.VoidingRecordStore.add(
context, com.medithings.vesiscan.measure.VoidingRecord(volume = vol, method = "manual")
)
appState.resetLevel()
android.widget.Toast.makeText(context, context.getString(R.string.registered_diary), android.widget.Toast.LENGTH_SHORT).show()
@@ -1038,7 +1038,7 @@ fun PiezoMonitoringView(appState: AppState) {
if (showVoiceInput) {
var voiceResult by remember { mutableStateOf<String?>(null) }
var isListening by remember { mutableStateOf(false) }
var speechMgr by remember { mutableStateOf<com.example.medilightv2android.speech.SpeechRecognizerManager?>(null) }
var speechMgr by remember { mutableStateOf<com.medithings.vesiscan.speech.SpeechRecognizerManager?>(null) }
DisposableEffect(Unit) { onDispose { speechMgr?.destroy() } }
@@ -1047,14 +1047,14 @@ fun PiezoMonitoringView(appState: AppState) {
if (androidx.core.content.ContextCompat.checkSelfPermission(context, android.Manifest.permission.RECORD_AUDIO)
== android.content.pm.PackageManager.PERMISSION_GRANTED) {
isListening = true
speechMgr = com.example.medilightv2android.speech.SpeechRecognizerManager(
speechMgr = com.medithings.vesiscan.speech.SpeechRecognizerManager(
context = context,
onResult = { candidates ->
isListening = false
val parsed = com.example.medilightv2android.speech.VolumeParser.parseBest(candidates)
val parsed = com.medithings.vesiscan.speech.VolumeParser.parseBest(candidates)
if (parsed != null) {
com.example.medilightv2android.measure.VoidingRecordStore.add(
context, com.example.medilightv2android.measure.VoidingRecord(volume = parsed.volumeMl, method = "voice")
com.medithings.vesiscan.measure.VoidingRecordStore.add(
context, com.medithings.vesiscan.measure.VoidingRecord(volume = parsed.volumeMl, method = "voice")
)
appState.resetLevel()
android.widget.Toast.makeText(context, context.getString(R.string.registered_ml, parsed.volumeMl), android.widget.Toast.LENGTH_SHORT).show()
@@ -1168,19 +1168,19 @@ fun PiezoMonitoringView(appState: AppState) {
// Dev mode 에서만 노출 (legacy 유지) — 일반 사용자에겐 숨김.
if (appState.isDevMode) {
var rawBleCapturing by remember {
mutableStateOf(com.example.medilightv2android.services.RawBleLogger.isCapturing)
mutableStateOf(com.medithings.vesiscan.services.RawBleLogger.isCapturing)
}
IconButton(
onClick = {
if (rawBleCapturing) {
val f = com.example.medilightv2android.services.RawBleLogger.stopCapture()
val n = com.example.medilightv2android.services.RawBleLogger.count
val f = com.medithings.vesiscan.services.RawBleLogger.stopCapture()
val n = com.medithings.vesiscan.services.RawBleLogger.count
rawBleCapturing = false
android.widget.Toast.makeText(context,
"Raw BLE: $n packets saved to ${f?.name}",
android.widget.Toast.LENGTH_LONG).show()
} else {
val f = com.example.medilightv2android.services.RawBleLogger.startCapture()
val f = com.medithings.vesiscan.services.RawBleLogger.startCapture()
rawBleCapturing = true
android.widget.Toast.makeText(context,
"Raw BLE capture started → ${f.name}",
@@ -1256,8 +1256,8 @@ fun PiezoMonitoringView(appState: AppState) {
// BLE 끊김 banner는 사내 테스트 피드백으로 제거됨 — 백그라운드 자동 재연결만 유지.
// 펌웨어 구버전 경고
com.example.medilightv2android.ui.components.FirmwareWarningBanner(bleManager)
com.example.medilightv2android.ui.components.BatteryWarningBanner(bleManager)
com.medithings.vesiscan.ui.components.FirmwareWarningBanner(bleManager)
com.medithings.vesiscan.ui.components.BatteryWarningBanner(bleManager)
val scrollState = rememberScrollState()
LaunchedEffect(showSettings) {
@@ -1306,22 +1306,22 @@ fun PiezoMonitoringView(appState: AppState) {
label = "posture-chip"
) { posture ->
val icon = when (posture) {
com.example.medilightv2android.managers.Posture.LYING -> Icons.Default.Hotel
com.example.medilightv2android.managers.Posture.NON_LYING -> Icons.Default.AccessibilityNew
com.example.medilightv2android.managers.Posture.WALKING -> Icons.Default.DirectionsWalk
com.example.medilightv2android.managers.Posture.UNKNOWN -> Icons.Default.HelpOutline
com.medithings.vesiscan.managers.Posture.LYING -> Icons.Default.Hotel
com.medithings.vesiscan.managers.Posture.NON_LYING -> Icons.Default.AccessibilityNew
com.medithings.vesiscan.managers.Posture.WALKING -> Icons.Default.DirectionsWalk
com.medithings.vesiscan.managers.Posture.UNKNOWN -> Icons.Default.HelpOutline
}
val tint = when (posture) {
com.example.medilightv2android.managers.Posture.LYING -> Color(0xFF2196F3)
com.example.medilightv2android.managers.Posture.NON_LYING -> Color(0xFF4CAF50)
com.example.medilightv2android.managers.Posture.WALKING -> Color(0xFFD32F2F)
com.example.medilightv2android.managers.Posture.UNKNOWN -> Color(0xFF616161) // 진한 회색 — 가시성 확보
com.medithings.vesiscan.managers.Posture.LYING -> Color(0xFF2196F3)
com.medithings.vesiscan.managers.Posture.NON_LYING -> Color(0xFF4CAF50)
com.medithings.vesiscan.managers.Posture.WALKING -> Color(0xFFD32F2F)
com.medithings.vesiscan.managers.Posture.UNKNOWN -> Color(0xFF616161) // 진한 회색 — 가시성 확보
}
val label = when (posture) {
com.example.medilightv2android.managers.Posture.LYING -> stringResource(R.string.piezo_posture_lying)
com.example.medilightv2android.managers.Posture.NON_LYING -> stringResource(R.string.piezo_posture_upright)
com.example.medilightv2android.managers.Posture.WALKING -> stringResource(R.string.piezo_posture_walking)
com.example.medilightv2android.managers.Posture.UNKNOWN -> stringResource(R.string.piezo_posture_detecting)
com.medithings.vesiscan.managers.Posture.LYING -> stringResource(R.string.piezo_posture_lying)
com.medithings.vesiscan.managers.Posture.NON_LYING -> stringResource(R.string.piezo_posture_upright)
com.medithings.vesiscan.managers.Posture.WALKING -> stringResource(R.string.piezo_posture_walking)
com.medithings.vesiscan.managers.Posture.UNKNOWN -> stringResource(R.string.piezo_posture_detecting)
}
Row(
verticalAlignment = Alignment.CenterVertically,
@@ -1458,8 +1458,8 @@ fun PiezoMonitoringView(appState: AppState) {
Button(
onClick = {
val quickVol = if (lastVolumeMl > 0) lastVolumeMl.toInt() else appState.estimatedVolume
com.example.medilightv2android.measure.VoidingRecordStore.add(
context, com.example.medilightv2android.measure.VoidingRecord(
com.medithings.vesiscan.measure.VoidingRecordStore.add(
context, com.medithings.vesiscan.measure.VoidingRecord(
volume = quickVol, method = "catheterize"
)
)
@@ -1847,22 +1847,22 @@ fun PiezoMonitoringView(appState: AppState) {
HorizontalDivider(modifier = Modifier.padding(vertical = dividerPadding))
// Detection Method A/B/C
var selectedMethod by remember { mutableStateOf(com.example.medilightv2android.managers.GreenZoneConstants.detectionMethod) }
var selectedMethod by remember { mutableStateOf(com.medithings.vesiscan.managers.GreenZoneConstants.detectionMethod) }
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
Text("Detection", fontSize = labelSize, fontWeight = FontWeight.SemiBold)
Spacer(modifier = Modifier.weight(1f))
val methods = listOf(
com.example.medilightv2android.managers.DetectionMethod.METHOD_A to "A",
com.example.medilightv2android.managers.DetectionMethod.METHOD_B to "B",
com.example.medilightv2android.managers.DetectionMethod.METHOD_C to "C",
com.example.medilightv2android.managers.DetectionMethod.METHOD_D to "D"
com.medithings.vesiscan.managers.DetectionMethod.METHOD_A to "A",
com.medithings.vesiscan.managers.DetectionMethod.METHOD_B to "B",
com.medithings.vesiscan.managers.DetectionMethod.METHOD_C to "C",
com.medithings.vesiscan.managers.DetectionMethod.METHOD_D to "D"
)
val colors = listOf(Color(0xFF9C27B0), MlPrimary, Color(0xFFFF5722), Color(0xFF7C3AED))
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
methods.forEachIndexed { idx, (m, label) ->
val sel = selectedMethod == m
Button(
onClick = { selectedMethod = m; com.example.medilightv2android.managers.GreenZoneConstants.detectionMethod = m },
onClick = { selectedMethod = m; com.medithings.vesiscan.managers.GreenZoneConstants.detectionMethod = m },
modifier = Modifier.height(32.dp),
shape = RoundedCornerShape(8.dp),
colors = ButtonDefaults.buttonColors(
@@ -1880,21 +1880,21 @@ fun PiezoMonitoringView(appState: AppState) {
HorizontalDivider(modifier = Modifier.padding(vertical = dividerPadding))
// BV Method (Frustum / V41)
var selectedBvMethod by remember { mutableStateOf(com.example.medilightv2android.managers.GreenZoneConstants.bvMethod) }
var selectedBvMethod by remember { mutableStateOf(com.medithings.vesiscan.managers.GreenZoneConstants.bvMethod) }
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
Text("BV", fontSize = labelSize, fontWeight = FontWeight.SemiBold)
Spacer(modifier = Modifier.weight(1f))
val bvMethods = listOf(
com.example.medilightv2android.managers.BvMethod.FRUSTUM to "Frustum",
com.example.medilightv2android.managers.BvMethod.V41 to "V41",
com.example.medilightv2android.managers.BvMethod.METHOD_D to "Method D"
com.medithings.vesiscan.managers.BvMethod.FRUSTUM to "Frustum",
com.medithings.vesiscan.managers.BvMethod.V41 to "V41",
com.medithings.vesiscan.managers.BvMethod.METHOD_D to "Method D"
)
val bvColors = listOf(MlPrimary, Color(0xFFFF5722), Color(0xFF7C3AED))
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
bvMethods.forEachIndexed { idx, (m, label) ->
val sel = selectedBvMethod == m
Button(
onClick = { selectedBvMethod = m; com.example.medilightv2android.managers.GreenZoneConstants.bvMethod = m },
onClick = { selectedBvMethod = m; com.medithings.vesiscan.managers.GreenZoneConstants.bvMethod = m },
modifier = Modifier.height(32.dp),
shape = RoundedCornerShape(8.dp),
colors = ButtonDefaults.buttonColors(
@@ -1913,7 +1913,7 @@ fun PiezoMonitoringView(appState: AppState) {
// 2026-07-01: lr_ratio override (algorithm 팀 4830e7c 표준)
var lrFixed by remember {
mutableStateOf(com.example.medilightv2android.managers.GreenZoneConstants.lrRatioOverride != null)
mutableStateOf(com.medithings.vesiscan.managers.GreenZoneConstants.lrRatioOverride != null)
}
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
Text("lr=1.0 fixed", fontSize = labelSize, fontWeight = FontWeight.SemiBold)
@@ -1921,7 +1921,7 @@ fun PiezoMonitoringView(appState: AppState) {
Switch(checked = lrFixed,
onCheckedChange = {
lrFixed = it
com.example.medilightv2android.managers.GreenZoneConstants.lrRatioOverride =
com.medithings.vesiscan.managers.GreenZoneConstants.lrRatioOverride =
if (it) 1.0 else null
},
colors = SwitchDefaults.colors(checkedTrackColor = MlPrimary))
@@ -1970,7 +1970,7 @@ fun PiezoMonitoringView(appState: AppState) {
LockableSlider(
value = pitchThrVal,
onValueChange = { pitchThrVal = it; GreenZoneConstants.pitchLyingThreshold = it
com.example.medilightv2android.services.PostureTuningPrefs.saveAll(context) },
com.medithings.vesiscan.services.PostureTuningPrefs.saveAll(context) },
valueRange = 10f..70f,
steps = 11,
colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary)
@@ -1980,7 +1980,7 @@ fun PiezoMonitoringView(appState: AppState) {
// Wakeup Alarm toggle (Personalization 페이지 와 동일 prefs)
var wakeupEnabled by remember {
mutableStateOf(com.example.medilightv2android.services.WakeupAlarmPrefs.isEnabled(context))
mutableStateOf(com.medithings.vesiscan.services.WakeupAlarmPrefs.isEnabled(context))
}
Row(verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()) {
@@ -1993,7 +1993,7 @@ fun PiezoMonitoringView(appState: AppState) {
checked = wakeupEnabled,
onCheckedChange = {
wakeupEnabled = it
com.example.medilightv2android.services.WakeupAlarmPrefs.setEnabled(context, it)
com.medithings.vesiscan.services.WakeupAlarmPrefs.setEnabled(context, it)
},
colors = SwitchDefaults.colors(checkedTrackColor = Color(0xFFD32F2F))
)
@@ -2002,7 +2002,7 @@ fun PiezoMonitoringView(appState: AppState) {
// Wakeup 알람 발동을 위한 LYING 유지 시간 (dev 조절 가능)
var lyingDurVal by remember {
mutableStateOf(
com.example.medilightv2android.services.WakeupAlarmPrefs.lyingDurationSec(context).toFloat()
com.medithings.vesiscan.services.WakeupAlarmPrefs.lyingDurationSec(context).toFloat()
)
}
Row(verticalAlignment = Alignment.CenterVertically) {
@@ -2021,7 +2021,7 @@ fun PiezoMonitoringView(appState: AppState) {
onValueChange = {
lyingDurVal = it
val sec = it.toInt()
com.example.medilightv2android.services.WakeupAlarmPrefs.setLyingDurationSec(context, sec)
com.medithings.vesiscan.services.WakeupAlarmPrefs.setLyingDurationSec(context, sec)
wakeupDetector.lyingDurationSec = sec
},
valueRange = 5f..600f, // 5초 ~ 10분
@@ -2046,7 +2046,7 @@ fun PiezoMonitoringView(appState: AppState) {
onValueChange = {
pollIntervalVal = it
GreenZoneConstants.posturePollIntervalMs = (it * 1000).toLong()
com.example.medilightv2android.services.PostureTuningPrefs.saveAll(context)
com.medithings.vesiscan.services.PostureTuningPrefs.saveAll(context)
},
valueRange = 1f..15f, // 1초 ~ 15초
steps = 0,
@@ -2066,7 +2066,7 @@ fun PiezoMonitoringView(appState: AppState) {
}
LockableSlider(value = walkPitchVal, onValueChange = {
walkPitchVal = it; GreenZoneConstants.walkingMinPitchDeg = it
com.example.medilightv2android.services.PostureTuningPrefs.saveAll(context)
com.medithings.vesiscan.services.PostureTuningPrefs.saveAll(context)
}, valueRange = 20f..70f, colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary))
var walkStartWmean by remember { mutableStateOf(GreenZoneConstants.walkingStartWmean) }
@@ -2077,7 +2077,7 @@ fun PiezoMonitoringView(appState: AppState) {
}
LockableSlider(value = walkStartWmean, onValueChange = {
walkStartWmean = it; GreenZoneConstants.walkingStartWmean = it
com.example.medilightv2android.services.PostureTuningPrefs.saveAll(context)
com.medithings.vesiscan.services.PostureTuningPrefs.saveAll(context)
}, valueRange = 1f..30f, colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary))
var walkStartWstd by remember { mutableStateOf(GreenZoneConstants.walkingStartWstd) }
@@ -2088,7 +2088,7 @@ fun PiezoMonitoringView(appState: AppState) {
}
LockableSlider(value = walkStartWstd, onValueChange = {
walkStartWstd = it; GreenZoneConstants.walkingStartWstd = it
com.example.medilightv2android.services.PostureTuningPrefs.saveAll(context)
com.medithings.vesiscan.services.PostureTuningPrefs.saveAll(context)
}, valueRange = 0.5f..10f, colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary))
var walkKeepWmean by remember { mutableStateOf(GreenZoneConstants.walkingKeepWmean) }
@@ -2099,7 +2099,7 @@ fun PiezoMonitoringView(appState: AppState) {
}
LockableSlider(value = walkKeepWmean, onValueChange = {
walkKeepWmean = it; GreenZoneConstants.walkingKeepWmean = it
com.example.medilightv2android.services.PostureTuningPrefs.saveAll(context)
com.medithings.vesiscan.services.PostureTuningPrefs.saveAll(context)
}, valueRange = 0.5f..30f, colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary))
// Walking 시간 변수 (sec)
@@ -2111,7 +2111,7 @@ fun PiezoMonitoringView(appState: AppState) {
}
LockableSlider(value = walkStartHold, onValueChange = {
walkStartHold = it; GreenZoneConstants.walkingStartHoldMs = (it * 1000).toLong()
com.example.medilightv2android.services.PostureTuningPrefs.saveAll(context)
com.medithings.vesiscan.services.PostureTuningPrefs.saveAll(context)
}, valueRange = 0.5f..10f, colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary))
var walkKeepHold by remember { mutableStateOf(GreenZoneConstants.walkingKeepHoldMs / 1000f) }
@@ -2122,7 +2122,7 @@ fun PiezoMonitoringView(appState: AppState) {
}
LockableSlider(value = walkKeepHold, onValueChange = {
walkKeepHold = it; GreenZoneConstants.walkingKeepHoldMs = (it * 1000).toLong()
com.example.medilightv2android.services.PostureTuningPrefs.saveAll(context)
com.medithings.vesiscan.services.PostureTuningPrefs.saveAll(context)
}, valueRange = 0.5f..10f, colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary))
var walkWindow by remember { mutableStateOf(GreenZoneConstants.walkingWindowMs / 1000f) }
@@ -2133,7 +2133,7 @@ fun PiezoMonitoringView(appState: AppState) {
}
LockableSlider(value = walkWindow, onValueChange = {
walkWindow = it; GreenZoneConstants.walkingWindowMs = (it * 1000).toLong()
com.example.medilightv2android.services.PostureTuningPrefs.saveAll(context)
com.medithings.vesiscan.services.PostureTuningPrefs.saveAll(context)
}, valueRange = 0.5f..5f, colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary))
HorizontalDivider(modifier = Modifier.padding(vertical = dividerPadding))
@@ -2149,7 +2149,7 @@ fun PiezoMonitoringView(appState: AppState) {
}
LockableSlider(value = accMagMin, onValueChange = {
accMagMin = it; GreenZoneConstants.postureAccMagMin = it
com.example.medilightv2android.services.PostureTuningPrefs.saveAll(context)
com.medithings.vesiscan.services.PostureTuningPrefs.saveAll(context)
}, valueRange = 0.3f..1.0f, colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary))
var accMagMax by remember { mutableStateOf(GreenZoneConstants.postureAccMagMax) }
@@ -2160,7 +2160,7 @@ fun PiezoMonitoringView(appState: AppState) {
}
LockableSlider(value = accMagMax, onValueChange = {
accMagMax = it; GreenZoneConstants.postureAccMagMax = it
com.example.medilightv2android.services.PostureTuningPrefs.saveAll(context)
com.medithings.vesiscan.services.PostureTuningPrefs.saveAll(context)
}, valueRange = 1.0f..3.0f, colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary))
HorizontalDivider(modifier = Modifier.padding(vertical = dividerPadding))
@@ -2168,7 +2168,7 @@ fun PiezoMonitoringView(appState: AppState) {
// Reset to defaults — 모든 threshold 를 default 로 복원 + prefs 저장.
OutlinedButton(
onClick = {
com.example.medilightv2android.services.PostureTuningPrefs.resetAll(context)
com.medithings.vesiscan.services.PostureTuningPrefs.resetAll(context)
android.widget.Toast.makeText(context,
"Defaults restored — close & reopen Settings to refresh sliders",
android.widget.Toast.LENGTH_LONG).show()
@@ -2201,7 +2201,7 @@ fun PiezoMonitoringView(appState: AppState) {
for ((tag, label) in annotateLabels) {
Button(
onClick = {
com.example.medilightv2android.services.PostureEventLogger.annotate(tag)
com.medithings.vesiscan.services.PostureEventLogger.annotate(tag)
android.widget.Toast.makeText(context,
"Marked: $label", android.widget.Toast.LENGTH_SHORT).show()
},
@@ -2281,7 +2281,7 @@ fun PiezoMonitoringView(appState: AppState) {
Text(stringResource(R.string.piezo_settings_app), fontSize = 13.sp, color = MlSecondaryText)
Spacer(modifier = Modifier.weight(1f))
Text(
com.example.medilightv2android.BuildConfig.VERSION_NAME,
com.medithings.vesiscan.BuildConfig.VERSION_NAME,
fontSize = 13.sp,
fontWeight = FontWeight.SemiBold,
color = MlPrimary,
@@ -2378,7 +2378,7 @@ fun PiezoMonitoringView(appState: AppState) {
Button(onClick = {
showRealignPrompt = false
autoFailCount = 0
appState.currentScreen = com.example.medilightv2android.AppScreen.PLACEMENT_GUIDE
appState.currentScreen = com.medithings.vesiscan.AppScreen.PLACEMENT_GUIDE
}) { Text(stringResource(R.string.piezo_realign_button)) }
},
dismissButton = {
@@ -2443,11 +2443,11 @@ private fun ChannelPanel(
}
} else {
// Zone indicator
val curMethod = com.example.medilightv2android.managers.GreenZoneConstants.detectionMethod
val analyzerAPanel = com.example.medilightv2android.managers.PiezoEchoAnalyzerA.shared
val curMethod = com.medithings.vesiscan.managers.GreenZoneConstants.detectionMethod
val analyzerAPanel = com.medithings.vesiscan.managers.PiezoEchoAnalyzerA.shared
val analyses = lastMultiChannelResult.map { chData ->
when (curMethod) {
com.example.medilightv2android.managers.DetectionMethod.METHOD_A -> analyzerAPanel.analyzeChannel(chData.buffer, chData.channel)
com.medithings.vesiscan.managers.DetectionMethod.METHOD_A -> analyzerAPanel.analyzeChannel(chData.buffer, chData.channel)
else -> analyzer.analyzeChannel(chData.buffer, chData.channel)
}
}
@@ -2509,7 +2509,7 @@ private fun ChannelPanel(
// Per-channel waveforms
for (chData in lastMultiChannelResult.filter { it.buffer.isNotEmpty() }) {
val chAnalysis = when (curMethod) {
com.example.medilightv2android.managers.DetectionMethod.METHOD_A -> analyzerAPanel.analyzeChannel(chData.buffer, chData.channel)
com.medithings.vesiscan.managers.DetectionMethod.METHOD_A -> analyzerAPanel.analyzeChannel(chData.buffer, chData.channel)
else -> analyzer.analyzeChannel(chData.buffer, chData.channel)
}
@@ -2537,8 +2537,8 @@ private fun ChannelPanel(
fontSize = 10.sp, fontWeight = FontWeight.SemiBold, color = Color.Cyan
)
Spacer(modifier = Modifier.width(4.dp))
val dps = com.example.medilightv2android.managers.PiezoHW.distancePerSample
val offset = com.example.medilightv2android.managers.PiezoHW.delayOffsetMm
val dps = com.medithings.vesiscan.managers.PiezoHW.distancePerSample
val offset = com.medithings.vesiscan.managers.PiezoHW.delayOffsetMm
Text(
"(${"%.0f".format(offset + antIdx * dps)}–${"%.0f".format(offset + postIdx * dps)}mm)",
fontSize = 9.sp, color = MlSecondaryText
@@ -2804,13 +2804,13 @@ private fun BleDebugPanel(bleManager: BleManager) {
) {
for (entry in entries) {
val color = when (entry.level) {
com.example.medilightv2android.services.BleDebugLogger.Level.TX -> Color(0xFF64B5F6)
com.example.medilightv2android.services.BleDebugLogger.Level.RX -> Color(0xFF81C784)
com.example.medilightv2android.services.BleDebugLogger.Level.ERROR -> Color.Red
com.example.medilightv2android.services.BleDebugLogger.Level.WARN -> Color(0xFFFFB74D)
com.example.medilightv2android.services.BleDebugLogger.Level.RSSI -> Color(0xFFFFD54F)
com.example.medilightv2android.services.BleDebugLogger.Level.CONN -> Color(0xFFCE93D8)
com.example.medilightv2android.services.BleDebugLogger.Level.INFO -> Color.White
com.medithings.vesiscan.services.BleDebugLogger.Level.TX -> Color(0xFF64B5F6)
com.medithings.vesiscan.services.BleDebugLogger.Level.RX -> Color(0xFF81C784)
com.medithings.vesiscan.services.BleDebugLogger.Level.ERROR -> Color.Red
com.medithings.vesiscan.services.BleDebugLogger.Level.WARN -> Color(0xFFFFB74D)
com.medithings.vesiscan.services.BleDebugLogger.Level.RSSI -> Color(0xFFFFD54F)
com.medithings.vesiscan.services.BleDebugLogger.Level.CONN -> Color(0xFFCE93D8)
com.medithings.vesiscan.services.BleDebugLogger.Level.INFO -> Color.White
}
Text(
entry.toLogLine(),
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.monitoring
package com.medithings.vesiscan.ui.views.monitoring
import android.util.Log
import androidx.compose.animation.core.animateFloatAsState
@@ -44,17 +44,17 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppScreen
import com.example.medilightv2android.AppState
import com.example.medilightv2android.R
import com.example.medilightv2android.ble.BleManager
import com.example.medilightv2android.ble.PiezoChannelData
import com.example.medilightv2android.managers.DetachmentDetection
import com.example.medilightv2android.managers.PiezoEchoAnalyzer
import com.example.medilightv2android.managers.PiezoHW
import com.example.medilightv2android.managers.UrinAI
import com.example.medilightv2android.services.MeasurementLogService
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppScreen
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.R
import com.medithings.vesiscan.ble.BleManager
import com.medithings.vesiscan.ble.PiezoChannelData
import com.medithings.vesiscan.managers.DetachmentDetection
import com.medithings.vesiscan.managers.PiezoEchoAnalyzer
import com.medithings.vesiscan.managers.PiezoHW
import com.medithings.vesiscan.managers.UrinAI
import com.medithings.vesiscan.services.MeasurementLogService
import com.medithings.vesiscan.ui.theme.*
/**
* Sensor Alignment Guide -- shown after BLE connection, before measurement.
@@ -80,8 +80,8 @@ fun PlacementGuideView(appState: AppState) {
var phaseHoldHint by remember { mutableStateOf("") } // 강제 힌트
val channelDetected = remember { mutableStateListOf(false, false, false, false, false, false) }
val channelUrineLen = remember { mutableStateListOf(0, 0, 0, 0, 0, 0) }
val isSweepMode = com.example.medilightv2android.managers.GreenZoneConstants.placementGuideMode ==
com.example.medilightv2android.managers.PlacementGuideMode.SWEEP
val isSweepMode = com.medithings.vesiscan.managers.GreenZoneConstants.placementGuideMode ==
com.medithings.vesiscan.managers.PlacementGuideMode.SWEEP
var directionHint by remember { mutableStateOf(
if (isSweepMode) context.getString(R.string.placement_sweep_initial)
else context.getString(R.string.placement_initial_hint)
@@ -96,16 +96,16 @@ fun PlacementGuideView(appState: AppState) {
var greenFailCount by remember { mutableIntStateOf(0) } // GREEN 이탈 디바운스
var lastChannelData by remember { mutableStateOf<List<PiezoChannelData>>(emptyList()) }
// 최근 IMU 샘플 (15개, ODR 50Hz, ~300ms 분량). 자세 판정/흔들림 감지/임상 로그용.
var lastImuSamples by remember { mutableStateOf<List<com.example.medilightv2android.ble.ImuSample>>(emptyList()) }
var lastImuSamples by remember { mutableStateOf<List<com.medithings.vesiscan.ble.ImuSample>>(emptyList()) }
var lastWallResults by remember { mutableStateOf<List<Pair<Int, Int>?>>(List(6) { null }) }
var debounceCount by remember { mutableIntStateOf(0) }
var lastGuidePhase by remember { mutableStateOf(PlacementPhase.VERTICAL) }
var lastHintChangeMs by remember { mutableStateOf(0L) }
// V2 alignment (alignment.py 포팅) — dev 토글로 활성화.
val v2Aligner = remember { com.example.medilightv2android.managers.RollingAligner() }
val v2Aligner = remember { com.medithings.vesiscan.managers.RollingAligner() }
// SWEEP 모드용 sphere-fit state
val rTracker = remember { com.example.medilightv2android.managers.BladderSeekRTracker() }
val rTracker = remember { com.medithings.vesiscan.managers.BladderSeekRTracker() }
var currentRMm by remember { mutableStateOf<Double?>(null) }
var bestRMm by remember { mutableStateOf(0.0) }
var sagittalArgMaxCh by remember { mutableStateOf<Int?>(null) }
@@ -127,13 +127,13 @@ fun PlacementGuideView(appState: AppState) {
// V2 (4-stage Method D) 는 R&D/clinical alignment session 전용.
// 일반 사용자 flow (Home → Start → Personalization → PlacementGuide) 는 V1 사용.
LaunchedEffect(Unit) {
val sess = com.example.medilightv2android.services.ClinicalSessionStore.currentSession
val sess = com.medithings.vesiscan.services.ClinicalSessionStore.currentSession
val isClinicalAlign = !appState.placementFromMonitoring &&
sess != null &&
sess.mode == com.example.medilightv2android.models.SessionMode.ALIGNMENT
com.example.medilightv2android.managers.GreenZoneConstants.alignmentAlgo =
if (isClinicalAlign) com.example.medilightv2android.managers.AlignmentAlgo.V2
else com.example.medilightv2android.managers.AlignmentAlgo.V1
sess.mode == com.medithings.vesiscan.models.SessionMode.ALIGNMENT
com.medithings.vesiscan.managers.GreenZoneConstants.alignmentAlgo =
if (isClinicalAlign) com.medithings.vesiscan.managers.AlignmentAlgo.V2
else com.medithings.vesiscan.managers.AlignmentAlgo.V1
v2Aligner.reset()
// Clinical alignment session 진입 시 — 자동으로 scan 시작 (Step 0 baseline 캡쳐).
// waitingForStart 는 true 유지 — 사용자는 여전히 Start 눌러 알고리즘 시작 결정.
@@ -256,10 +256,10 @@ fun PlacementGuideView(appState: AppState) {
// Clinical alignment session 진입한 경우 — 저장 후 Clinical Home 으로.
// (PiezoMonitoring / Personalization 으로 떨어지지 않게)
// Back / Skip 도 endMeasurement → measurement.json + labdb 자동 업로드 (Complete 와 동일).
val curSess = com.example.medilightv2android.services.ClinicalSessionStore.currentSession
if (curSess != null && curSess.mode == com.example.medilightv2android.models.SessionMode.ALIGNMENT) {
com.example.medilightv2android.services.ClinicalSessionStore.endMeasurement(context)
com.example.medilightv2android.services.ClinicalSessionStore.inClinicalFlow = true
val curSess = com.medithings.vesiscan.services.ClinicalSessionStore.currentSession
if (curSess != null && curSess.mode == com.medithings.vesiscan.models.SessionMode.ALIGNMENT) {
com.medithings.vesiscan.services.ClinicalSessionStore.endMeasurement(context)
com.medithings.vesiscan.services.ClinicalSessionStore.inClinicalFlow = true
appState.currentScreen = AppScreen.CLINICAL_HOME
} else {
appState.backFromPlacementGuide()
@@ -279,10 +279,10 @@ fun PlacementGuideView(appState: AppState) {
// Skip — top bar 우측 (유일한 Skip 진입점)
TextButton(onClick = {
isContinuousMode = false
val curSess = com.example.medilightv2android.services.ClinicalSessionStore.currentSession
if (curSess != null && curSess.mode == com.example.medilightv2android.models.SessionMode.ALIGNMENT) {
com.example.medilightv2android.services.ClinicalSessionStore.endMeasurement(context)
com.example.medilightv2android.services.ClinicalSessionStore.inClinicalFlow = true
val curSess = com.medithings.vesiscan.services.ClinicalSessionStore.currentSession
if (curSess != null && curSess.mode == com.medithings.vesiscan.models.SessionMode.ALIGNMENT) {
com.medithings.vesiscan.services.ClinicalSessionStore.endMeasurement(context)
com.medithings.vesiscan.services.ClinicalSessionStore.inClinicalFlow = true
appState.currentScreen = AppScreen.CLINICAL_HOME
} else {
appState.placementComplete()
@@ -311,9 +311,9 @@ fun PlacementGuideView(appState: AppState) {
}
// 펌웨어 구버전 경고
com.example.medilightv2android.ui.components.FirmwareWarningBanner(bleManager)
com.medithings.vesiscan.ui.components.FirmwareWarningBanner(bleManager)
// 배터리 잔량 경고 (<15%)
com.example.medilightv2android.ui.components.BatteryWarningBanner(bleManager)
com.medithings.vesiscan.ui.components.BatteryWarningBanner(bleManager)
Box(modifier = Modifier.fillMaxSize()) {
Column(
@@ -435,7 +435,7 @@ fun PlacementGuideView(appState: AppState) {
) {
// 1) 하복부 일러스트 (배경 — 박스 가득)
Image(
painter = painterResource(id = com.example.medilightv2android.R.drawable.body_silhouette),
painter = painterResource(id = com.medithings.vesiscan.R.drawable.body_silhouette),
contentDescription = stringResource(R.string.placement_body_desc),
modifier = Modifier.matchParentSize(),
contentScale = ContentScale.FillBounds
@@ -444,14 +444,14 @@ fun PlacementGuideView(appState: AppState) {
val sensorBitmap = remember {
android.graphics.BitmapFactory.decodeResource(
context.resources,
com.example.medilightv2android.R.drawable.sensor_device,
com.medithings.vesiscan.R.drawable.sensor_device,
).asImageBitmap()
}
// 방향 화살표 PNG (132x112, 우향). 회전 + tint 로 4방향 + 색감 통일.
val arrowBitmap = remember {
android.graphics.BitmapFactory.decodeResource(
context.resources,
com.example.medilightv2android.R.drawable.arrow_transparent,
com.medithings.vesiscan.R.drawable.arrow_transparent,
).asImageBitmap()
}
Canvas(modifier = Modifier.fillMaxSize()) {
@@ -575,17 +575,17 @@ fun PlacementGuideView(appState: AppState) {
) {
// V2 활성 시 5-stage step indicator, 아니면 V1 의 3-stage.
// 2026-07-01: FINAL_CONFIRM phase 추가 (feature/tab-navigation 동기화).
val isV2Active = com.example.medilightv2android.managers.GreenZoneConstants.alignmentAlgo ==
com.example.medilightv2android.managers.AlignmentAlgo.V2
val isV2Active = com.medithings.vesiscan.managers.GreenZoneConstants.alignmentAlgo ==
com.medithings.vesiscan.managers.AlignmentAlgo.V2
// 2026-07-02: CENTER_OPTIMIZE 추가 (5-stage → 6-stage)
val (currentStepIdx, totalSteps) = if (isV2Active) {
val idx = when (v2Aligner.phase) {
com.example.medilightv2android.managers.AlignGuide4Stage.Phase4.INITIAL_ACCUM -> 0
com.example.medilightv2android.managers.AlignGuide4Stage.Phase4.VERTICAL_CLIMB -> 1
com.example.medilightv2android.managers.AlignGuide4Stage.Phase4.CH3_STABILIZE -> 2
com.example.medilightv2android.managers.AlignGuide4Stage.Phase4.CENTER_OPTIMIZE -> 3
com.example.medilightv2android.managers.AlignGuide4Stage.Phase4.LR_BALANCE -> 4
com.example.medilightv2android.managers.AlignGuide4Stage.Phase4.FINAL_CONFIRM -> 5
com.medithings.vesiscan.managers.AlignGuide4Stage.Phase4.INITIAL_ACCUM -> 0
com.medithings.vesiscan.managers.AlignGuide4Stage.Phase4.VERTICAL_CLIMB -> 1
com.medithings.vesiscan.managers.AlignGuide4Stage.Phase4.CH3_STABILIZE -> 2
com.medithings.vesiscan.managers.AlignGuide4Stage.Phase4.CENTER_OPTIMIZE -> 3
com.medithings.vesiscan.managers.AlignGuide4Stage.Phase4.LR_BALANCE -> 4
com.medithings.vesiscan.managers.AlignGuide4Stage.Phase4.FINAL_CONFIRM -> 5
}
idx to 6
} else {
@@ -634,13 +634,13 @@ fun PlacementGuideView(appState: AppState) {
}
if (appState.isDevMode && lastImuSamples.isNotEmpty()) {
val posture = remember(lastImuSamples) {
com.example.medilightv2android.managers.ImuAnalysis.estimatePosture(lastImuSamples)
com.medithings.vesiscan.managers.ImuAnalysis.estimatePosture(lastImuSamples)
}
val shake = remember(lastImuSamples) {
com.example.medilightv2android.managers.ImuAnalysis.shakeRmsDps(lastImuSamples)
com.medithings.vesiscan.managers.ImuAnalysis.shakeRmsDps(lastImuSamples)
}
val tilt = remember(lastImuSamples) {
com.example.medilightv2android.managers.ImuAnalysis.tiltDegrees(lastImuSamples)
com.medithings.vesiscan.managers.ImuAnalysis.tiltDegrees(lastImuSamples)
}
Text(
"IMU: $posture · tilt=${"%.0f".format(tilt)}° · shake=${"%.1f".format(shake)}dps",
@@ -720,7 +720,7 @@ fun PlacementGuideView(appState: AppState) {
val detected = if (ch < channelDetected.size) channelDetected[ch] else false
val wallPair = if (ch < lastWallResults.size) lastWallResults[ch] else null
val showWalls = if (wallPair != null) {
com.example.medilightv2android.managers.LowEchoResult(
com.medithings.vesiscan.managers.LowEchoResult(
ant = wallPair.first, post = wallPair.second,
lowStart = wallPair.first, lowEnd = wallPair.second,
lowMean = 0.0, urineLen = wallPair.second - wallPair.first,
@@ -746,8 +746,8 @@ fun PlacementGuideView(appState: AppState) {
if (chData != null && chData.buffer.isNotEmpty()) {
// V2 활성 시 RollingAligner 의 10-cycle 평균 신호로 표시 →
// 알고리즘 입력 신호와 그래프 일치 (실제 측정 시 보는 화면).
val isV2 = com.example.medilightv2android.managers.GreenZoneConstants.alignmentAlgo ==
com.example.medilightv2android.managers.AlignmentAlgo.V2
val isV2 = com.medithings.vesiscan.managers.GreenZoneConstants.alignmentAlgo ==
com.medithings.vesiscan.managers.AlignmentAlgo.V2
val avgRaw = if (isV2) v2Aligner.lastAvg?.getOrNull(ch) else null
PlacementWaveformChart(
buffer = chData.buffer,
@@ -806,26 +806,26 @@ fun PlacementGuideView(appState: AppState) {
val MIN_URINE_LEN_PLACEMENT = 12
val method = com.example.medilightv2android.managers.GreenZoneConstants.detectionMethod
val analyzerA = com.example.medilightv2android.managers.PiezoEchoAnalyzerA.shared
val method = com.medithings.vesiscan.managers.GreenZoneConstants.detectionMethod
val analyzerA = com.medithings.vesiscan.managers.PiezoEchoAnalyzerA.shared
for (ch in channels) {
if (ch.buffer.isNotEmpty() && ch.channel < 6) {
when (method) {
com.example.medilightv2android.managers.DetectionMethod.METHOD_C -> {
val v41 = com.example.medilightv2android.walldetect.V41Detector()
com.medithings.vesiscan.managers.DetectionMethod.METHOD_C -> {
val v41 = com.medithings.vesiscan.walldetect.V41Detector()
val adcSingle = listOf(ch.buffer.map { it.toInt() })
val probe = com.example.medilightv2android.walldetect.dto.ProbeProfileDto(
name = com.example.medilightv2android.managers.PiezoHW.presetName,
val probe = com.medithings.vesiscan.walldetect.dto.ProbeProfileDto(
name = com.medithings.vesiscan.managers.PiezoHW.presetName,
rMm = 50.2, anteriorAnchorMm = 32.0,
fsHz = 537500, cMmPerUs = 1.54,
anglesDeg = com.example.medilightv2android.managers.PiezoHW.degreeAll.toList()
anglesDeg = com.medithings.vesiscan.managers.PiezoHW.degreeAll.toList()
)
// V4.1은 6ch 입력 필요 — 현재 채널만 해당 위치에, 나머지 빈 값
val adcMatrix = (0 until 6).map { i ->
if (i == ch.channel) ch.buffer.map { it.toInt() } else List(100) { 0 }
}
val input = com.example.medilightv2android.walldetect.dto.SweepInput(
val input = com.medithings.vesiscan.walldetect.dto.SweepInput(
requestId = "placement", timestampMs = System.currentTimeMillis(),
deviceId = "", sweepSeq = 0, probe = probe, adc = adcMatrix
)
@@ -841,7 +841,7 @@ fun PlacementGuideView(appState: AppState) {
}
Log.d("PlacementGuide", "CH${ch.channel}[C] ant=${chResult?.antIdx} post=${chResult?.postIdx}")
}
com.example.medilightv2android.managers.DetectionMethod.METHOD_A -> {
com.medithings.vesiscan.managers.DetectionMethod.METHOD_A -> {
val analysis = analyzerA.analyzeChannel(ch.buffer, ch.channel)
Log.d("PlacementGuide", "CH${ch.channel}[A] valid=${analysis.isValid} urine=${analysis.result?.urineLen ?: 0}")
if (analysis.isValid && analysis.result != null && analysis.result.urineLen >= MIN_URINE_LEN_PLACEMENT) {
@@ -864,7 +864,7 @@ fun PlacementGuideView(appState: AppState) {
}
// postMaxIdx 필터: 후벽이 이 샘플 이상이면 바닥반사로 판단 → 제거
val postMax = com.example.medilightv2android.managers.GreenZoneConstants.postMaxIdx
val postMax = com.medithings.vesiscan.managers.GreenZoneConstants.postMaxIdx
for (ch in 0..5) {
val w = allWalls[ch]
if (w != null && w.second > postMax) {
@@ -903,8 +903,8 @@ fun PlacementGuideView(appState: AppState) {
bleManager.debugLogger.warn("DETACHED mean=${"%.1f".format(detachResult.meanAbs)} std=${"%.1f".format(detachResult.stdVal)}")
Log.w("PlacementGuide", "DETACHED mean=${
"%.1f".format(detachResult.meanAbs)} std=${"%.1f".format(detachResult.stdVal)}")
} else if (com.example.medilightv2android.managers.GreenZoneConstants.alignmentAlgo ==
com.example.medilightv2android.managers.AlignmentAlgo.V2) {
} else if (com.medithings.vesiscan.managers.GreenZoneConstants.alignmentAlgo ==
com.medithings.vesiscan.managers.AlignmentAlgo.V2) {
// ═══ V2 alignment (alignment.py 포팅, method_d 기반) ═══
// Clinical alignment session + waitingForStart 일 땐 알고리즘 skip —
// baseline cycles 만 누적 (Start 누르기 전 자동 phase 진행 차단).
@@ -941,20 +941,20 @@ fun PlacementGuideView(appState: AppState) {
directionHint = localizedMsg
// STOP 액션은 두 경우 — CH3_STABILIZE 의 "위치 유지" (still in progress) vs
// LR_BALANCE 의 "정렬 완료" (truly done). 후자만 finalStop 으로 GREEN lock.
val finalStop = st.action == com.example.medilightv2android.managers.AlignAction.STOP &&
v2Aligner.phase == com.example.medilightv2android.managers.AlignGuide4Stage.Phase4.LR_BALANCE
val finalStop = st.action == com.medithings.vesiscan.managers.AlignAction.STOP &&
v2Aligner.phase == com.medithings.vesiscan.managers.AlignGuide4Stage.Phase4.LR_BALANCE
directionIcon = when (st.action) {
com.example.medilightv2android.managers.AlignAction.MOVE_UP -> "arrow.up"
com.example.medilightv2android.managers.AlignAction.MOVE_DOWN -> "arrow.down"
com.example.medilightv2android.managers.AlignAction.MOVE_LEFT -> "arrow.left"
com.example.medilightv2android.managers.AlignAction.MOVE_RIGHT -> "arrow.right"
com.example.medilightv2android.managers.AlignAction.PROBE_LR -> "" // ↔ — 한쪽 화살표 안 어울림. msg 의 ↔ 만 표시
com.example.medilightv2android.managers.AlignAction.STOP -> if (finalStop) "checkmark.circle" else ""
com.medithings.vesiscan.managers.AlignAction.MOVE_UP -> "arrow.up"
com.medithings.vesiscan.managers.AlignAction.MOVE_DOWN -> "arrow.down"
com.medithings.vesiscan.managers.AlignAction.MOVE_LEFT -> "arrow.left"
com.medithings.vesiscan.managers.AlignAction.MOVE_RIGHT -> "arrow.right"
com.medithings.vesiscan.managers.AlignAction.PROBE_LR -> "" // ↔ — 한쪽 화살표 안 어울림. msg 의 ↔ 만 표시
com.medithings.vesiscan.managers.AlignAction.STOP -> if (finalStop) "checkmark.circle" else ""
null -> ""
}
placementScore = when {
finalStop -> 100
st.action == com.example.medilightv2android.managers.AlignAction.STOP -> 60 // CH3_STABILIZE 유지 중
st.action == com.medithings.vesiscan.managers.AlignAction.STOP -> 60 // CH3_STABILIZE 유지 중
else -> 40
}
if (finalStop) {
@@ -970,14 +970,14 @@ fun PlacementGuideView(appState: AppState) {
} // end of !waitingForStart V2 algorithm
} else {
// Sphere-fit 계산 (SWEEP 모드에서 사용, 다른 모드에서는 무시됨)
val fitResult = com.example.medilightv2android.managers.BladderSphereSeek
val fitResult = com.medithings.vesiscan.managers.BladderSphereSeek
.fitSagittalCircle(allWalls, detected)
val rStatus = rTracker.submit(fitResult?.radiusMm)
currentRMm = rStatus.currentR
bestRMm = rStatus.bestR
sagittalArgMaxCh = com.example.medilightv2android.managers.BladderSphereSeek
sagittalArgMaxCh = com.medithings.vesiscan.managers.BladderSphereSeek
.sagittalArgMaxCh(allWalls, detected)
val coronalResult = com.example.medilightv2android.managers.BladderSphereSeek
val coronalResult = com.medithings.vesiscan.managers.BladderSphereSeek
.computeCoronalLateral(allWalls, detected)
lateralOffsetMm = coronalResult?.lateralOffsetMm
@@ -1112,11 +1112,11 @@ fun PlacementGuideView(appState: AppState) {
// Phase 라벨 — V2 활성이면 V2 4-stage phase, 아니면 V1 placementPhase.
// Step 0 (Start 전 baseline) 은 alignment session 에서만 명시.
val isV2 = com.example.medilightv2android.managers.GreenZoneConstants.alignmentAlgo ==
com.example.medilightv2android.managers.AlignmentAlgo.V2
val clinSess = com.example.medilightv2android.services.ClinicalSessionStore.currentSession
val isV2 = com.medithings.vesiscan.managers.GreenZoneConstants.alignmentAlgo ==
com.medithings.vesiscan.managers.AlignmentAlgo.V2
val clinSess = com.medithings.vesiscan.services.ClinicalSessionStore.currentSession
val isClinAlign = clinSess != null &&
clinSess.mode == com.example.medilightv2android.models.SessionMode.ALIGNMENT
clinSess.mode == com.medithings.vesiscan.models.SessionMode.ALIGNMENT
val phaseLabel = when {
isClinAlign && waitingForStart -> "STEP_0_BASELINE"
isV2 -> v2Aligner.phase.name
@@ -1136,10 +1136,10 @@ fun PlacementGuideView(appState: AppState) {
// 임상 모드에서는 raw ADC도 adc.csv에 자동 저장.
if (clinSess != null) {
val rawADC = channels.sortedBy { it.channel }.map { it.buffer }
com.example.medilightv2android.services.AdcCsvLogger.log(rawADC, null)
com.medithings.vesiscan.services.AdcCsvLogger.log(rawADC, null)
// Alignment session 진행 중이면 measurement.json 용 frame 누적.
if (clinSess.mode == com.example.medilightv2android.models.SessionMode.ALIGNMENT) {
com.example.medilightv2android.services.ClinicalSessionStore.addAlignmentFrame(
if (clinSess.mode == com.medithings.vesiscan.models.SessionMode.ALIGNMENT) {
com.medithings.vesiscan.services.ClinicalSessionStore.addAlignmentFrame(
piezo = channels,
imu = lastImuSamples,
// Step 0 baseline / V2 phase / V1 phase 통일된 라벨 사용
@@ -1159,8 +1159,8 @@ fun PlacementGuideView(appState: AppState) {
bleManager.imuCollector.onComplete = { imuSamples ->
handler.post {
lastImuSamples = imuSamples
if (com.example.medilightv2android.services.ClinicalSessionStore.currentSession != null) {
com.example.medilightv2android.services.ImuCsvLogger.log(imuSamples)
if (com.medithings.vesiscan.services.ClinicalSessionStore.currentSession != null) {
com.medithings.vesiscan.services.ImuCsvLogger.log(imuSamples)
}
}
}
@@ -1241,16 +1241,16 @@ fun PlacementGuideView(appState: AppState) {
}
// Start Scanning / Complete Alignment 버튼 — clinical alignment 모드면 후자
val curClinSess = com.example.medilightv2android.services.ClinicalSessionStore.currentSession
val curClinSess = com.medithings.vesiscan.services.ClinicalSessionStore.currentSession
val isClinicalAlign = curClinSess != null &&
curClinSess.mode == com.example.medilightv2android.models.SessionMode.ALIGNMENT
curClinSess.mode == com.medithings.vesiscan.models.SessionMode.ALIGNMENT
if (!waitingForStart) Button(
onClick = {
isContinuousMode = false
if (isClinicalAlign) {
// endMeasurement → measurement.json finalize + labdb 자동 업로드
com.example.medilightv2android.services.ClinicalSessionStore.endMeasurement(context)
com.example.medilightv2android.services.ClinicalSessionStore.inClinicalFlow = true
com.medithings.vesiscan.services.ClinicalSessionStore.endMeasurement(context)
com.medithings.vesiscan.services.ClinicalSessionStore.inClinicalFlow = true
appState.currentScreen = AppScreen.CLINICAL_HOME
} else {
appState.placementComplete()
@@ -1300,21 +1300,21 @@ fun PlacementGuideView(appState: AppState) {
) {
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
// Method A/B/C
var selectedMethod by remember { mutableStateOf(com.example.medilightv2android.managers.GreenZoneConstants.detectionMethod) }
var selectedMethod by remember { mutableStateOf(com.medithings.vesiscan.managers.GreenZoneConstants.detectionMethod) }
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
Text("Detection", fontSize = 14.sp, fontWeight = FontWeight.SemiBold)
Spacer(modifier = Modifier.weight(1f))
val methods = listOf(
com.example.medilightv2android.managers.DetectionMethod.METHOD_A to "A",
com.example.medilightv2android.managers.DetectionMethod.METHOD_B to "B",
com.example.medilightv2android.managers.DetectionMethod.METHOD_C to "C"
com.medithings.vesiscan.managers.DetectionMethod.METHOD_A to "A",
com.medithings.vesiscan.managers.DetectionMethod.METHOD_B to "B",
com.medithings.vesiscan.managers.DetectionMethod.METHOD_C to "C"
)
val colors = listOf(Color(0xFF9C27B0), MlPrimary, Color(0xFFFF5722))
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
methods.forEachIndexed { idx, (m, label) ->
val sel = selectedMethod == m
Button(
onClick = { selectedMethod = m; com.example.medilightv2android.managers.GreenZoneConstants.detectionMethod = m },
onClick = { selectedMethod = m; com.medithings.vesiscan.managers.GreenZoneConstants.detectionMethod = m },
modifier = Modifier.height(32.dp),
shape = RoundedCornerShape(8.dp),
colors = ButtonDefaults.buttonColors(
@@ -1332,14 +1332,14 @@ fun PlacementGuideView(appState: AppState) {
HorizontalDivider()
// Guide mode (Gradient / Boundary / SWEEP)
var selectedGuide by remember { mutableStateOf(com.example.medilightv2android.managers.GreenZoneConstants.placementGuideMode) }
var selectedGuide by remember { mutableStateOf(com.medithings.vesiscan.managers.GreenZoneConstants.placementGuideMode) }
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
Text("Guide", fontSize = 14.sp, fontWeight = FontWeight.SemiBold)
Spacer(modifier = Modifier.weight(1f))
val guideModes = listOf(
com.example.medilightv2android.managers.PlacementGuideMode.SIMPLE to "Gradient",
com.example.medilightv2android.managers.PlacementGuideMode.BOUNDARY to "Boundary",
com.example.medilightv2android.managers.PlacementGuideMode.SWEEP to "SWEEP"
com.medithings.vesiscan.managers.PlacementGuideMode.SIMPLE to "Gradient",
com.medithings.vesiscan.managers.PlacementGuideMode.BOUNDARY to "Boundary",
com.medithings.vesiscan.managers.PlacementGuideMode.SWEEP to "SWEEP"
)
val guideColors = listOf(MlPrimary, Color(0xFFFF5722), Color(0xFF7C3AED))
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
@@ -1348,7 +1348,7 @@ fun PlacementGuideView(appState: AppState) {
Button(
onClick = {
selectedGuide = mode
com.example.medilightv2android.managers.GreenZoneConstants.placementGuideMode = mode
com.medithings.vesiscan.managers.GreenZoneConstants.placementGuideMode = mode
},
modifier = Modifier.height(32.dp),
shape = RoundedCornerShape(8.dp),
@@ -1368,14 +1368,14 @@ fun PlacementGuideView(appState: AppState) {
// Alignment 알고리즘 V1/V2
var selectedAlgo by remember {
mutableStateOf(com.example.medilightv2android.managers.GreenZoneConstants.alignmentAlgo)
mutableStateOf(com.medithings.vesiscan.managers.GreenZoneConstants.alignmentAlgo)
}
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
Text("Alignment", fontSize = 14.sp, fontWeight = FontWeight.SemiBold)
Spacer(modifier = Modifier.weight(1f))
val algoModes = listOf(
com.example.medilightv2android.managers.AlignmentAlgo.V1 to "V1 (legacy)",
com.example.medilightv2android.managers.AlignmentAlgo.V2 to "V2 (new)",
com.medithings.vesiscan.managers.AlignmentAlgo.V1 to "V1 (legacy)",
com.medithings.vesiscan.managers.AlignmentAlgo.V2 to "V2 (new)",
)
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
algoModes.forEach { (algo, label) ->
@@ -1383,8 +1383,8 @@ fun PlacementGuideView(appState: AppState) {
Button(
onClick = {
selectedAlgo = algo
com.example.medilightv2android.managers.GreenZoneConstants.alignmentAlgo = algo
if (algo == com.example.medilightv2android.managers.AlignmentAlgo.V2) {
com.medithings.vesiscan.managers.GreenZoneConstants.alignmentAlgo = algo
if (algo == com.medithings.vesiscan.managers.AlignmentAlgo.V2) {
v2Aligner.reset()
}
},
@@ -1410,7 +1410,7 @@ fun PlacementGuideView(appState: AppState) {
Text("Threshold", fontSize = 14.sp, fontWeight = FontWeight.SemiBold)
Spacer(modifier = Modifier.width(8.dp))
Text(
if (otsuEnabled) "Otsu: ${"%.0f".format(analyzer.lastOtsuThreshold)}" else "${"%.0f".format(com.example.medilightv2android.managers.GreenZoneConstants.lowEchoAmp)}",
if (otsuEnabled) "Otsu: ${"%.0f".format(analyzer.lastOtsuThreshold)}" else "${"%.0f".format(com.medithings.vesiscan.managers.GreenZoneConstants.lowEchoAmp)}",
fontSize = 13.sp, fontWeight = FontWeight.Bold,
color = if (otsuEnabled) Color(0xFF4CAF50) else Color(0xFFFF9800)
)
@@ -1426,7 +1426,7 @@ fun PlacementGuideView(appState: AppState) {
HorizontalDivider()
// Post Max Index (바닥반사 무시 경계)
var postMaxVal by remember { mutableStateOf(com.example.medilightv2android.managers.GreenZoneConstants.postMaxIdx.toFloat()) }
var postMaxVal by remember { mutableStateOf(com.medithings.vesiscan.managers.GreenZoneConstants.postMaxIdx.toFloat()) }
Row(verticalAlignment = Alignment.CenterVertically) {
Text("Post Max", fontSize = 14.sp, fontWeight = FontWeight.SemiBold)
Spacer(modifier = Modifier.width(8.dp))
@@ -1434,7 +1434,7 @@ fun PlacementGuideView(appState: AppState) {
}
Slider(
value = postMaxVal,
onValueChange = { postMaxVal = it; com.example.medilightv2android.managers.GreenZoneConstants.postMaxIdx = it.toInt() },
onValueChange = { postMaxVal = it; com.medithings.vesiscan.managers.GreenZoneConstants.postMaxIdx = it.toInt() },
valueRange = 50f..95f,
steps = 8,
colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary)
@@ -1651,10 +1651,10 @@ data class PlacementGuideResult(
// CV threshold는 기기 preset에 따라 다름
private val DEFAULT_CV_THR: Double
get() = when (com.example.medilightv2android.managers.PiezoHW.activePreset) {
com.example.medilightv2android.managers.PiezoHW.DevicePreset.V0 -> 0.07
com.example.medilightv2android.managers.PiezoHW.DevicePreset.V1,
com.example.medilightv2android.managers.PiezoHW.DevicePreset.V2 -> 0.10
get() = when (com.medithings.vesiscan.managers.PiezoHW.activePreset) {
com.medithings.vesiscan.managers.PiezoHW.DevicePreset.V0 -> 0.07
com.medithings.vesiscan.managers.PiezoHW.DevicePreset.V1,
com.medithings.vesiscan.managers.PiezoHW.DevicePreset.V2 -> 0.10
else -> 0.08
}
private const val DEFAULT_LR_DEV_THR = 0.20
@@ -1727,10 +1727,10 @@ private fun computePlacementGuide(
// ═══ 1단계: 상하 탐색 ═══
if (currentPhase == PlacementPhase.VERTICAL) {
val guideMode = com.example.medilightv2android.managers.GreenZoneConstants.placementGuideMode
val guideMode = com.medithings.vesiscan.managers.GreenZoneConstants.placementGuideMode
// ═══ SWEEP 모드 (CKLaw): top-down sweep → Ch3 dropout → pull-back ═══
if (guideMode == com.example.medilightv2android.managers.PlacementGuideMode.SWEEP) {
if (guideMode == com.medithings.vesiscan.managers.PlacementGuideMode.SWEEP) {
val vs = verticalState ?: VerticalState()
val prev = vs.lastDetectedCount
vs.lastDetectedCount = centerDetected
@@ -2054,8 +2054,8 @@ private fun computePlacementGuide(
}
// R-peak gate (SWEEP 모드에서만 적용)
val isSweep = com.example.medilightv2android.managers.GreenZoneConstants.placementGuideMode ==
com.example.medilightv2android.managers.PlacementGuideMode.SWEEP
val isSweep = com.medithings.vesiscan.managers.GreenZoneConstants.placementGuideMode ==
com.medithings.vesiscan.managers.PlacementGuideMode.SWEEP
val rPeakOk = !isSweep || currentRMm == null || bestRMm <= 0.0 ||
(bestRMm - currentRMm) <= 1.5
val isPass = cv <= cvThr && lrPass && rPeakOk && edgePass
@@ -2159,7 +2159,7 @@ private fun PlacementWaveformChart(
val denoised = analyzer.denoise(raw)
val maxVal = 2500f
val thrVal = if (analyzer.useAdaptiveThreshold && analyzer.lastOtsuThreshold > 0)
analyzer.lastOtsuThreshold.toFloat() else com.example.medilightv2android.managers.GreenZoneConstants.lowEchoAmp
analyzer.lastOtsuThreshold.toFloat() else com.medithings.vesiscan.managers.GreenZoneConstants.lowEchoAmp
Canvas(modifier = modifier.clip(RoundedCornerShape(4.dp))) {
val w = size.width
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.monitoring
package com.medithings.vesiscan.ui.views.monitoring
import android.Manifest
import android.content.pm.PackageManager
@@ -35,11 +35,11 @@ import androidx.compose.ui.unit.sp
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat
import com.example.medilightv2android.R
import com.example.medilightv2android.measure.SimpleMeasureService
import com.example.medilightv2android.measure.VoidingRecord
import com.example.medilightv2android.measure.VoidingRecordStore
import com.example.medilightv2android.measure.YoloDetector
import com.medithings.vesiscan.R
import com.medithings.vesiscan.measure.SimpleMeasureService
import com.medithings.vesiscan.measure.VoidingRecord
import com.medithings.vesiscan.measure.VoidingRecordStore
import com.medithings.vesiscan.measure.YoloDetector
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.monitoring
package com.medithings.vesiscan.ui.views.monitoring
import android.os.Handler
import android.os.Looper
@@ -29,14 +29,14 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppState
import com.example.medilightv2android.R
import com.example.medilightv2android.ble.BleManager
import com.example.medilightv2android.managers.NirsManager
import com.example.medilightv2android.models.NirsMcjPacket
import com.example.medilightv2android.models.NirsOxyResult
import com.example.medilightv2android.ui.components.BladdyIdleRiveView
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.R
import com.medithings.vesiscan.ble.BleManager
import com.medithings.vesiscan.managers.NirsManager
import com.medithings.vesiscan.models.NirsMcjPacket
import com.medithings.vesiscan.models.NirsOxyResult
import com.medithings.vesiscan.ui.components.BladdyIdleRiveView
import com.medithings.vesiscan.ui.theme.*
import kotlin.random.Random
@Composable
@@ -84,7 +84,7 @@ fun VivamyoMonitoringView(appState: AppState) {
if (packet != null) {
nirsManager.processMcjPacket(packet)
} else {
if (com.example.medilightv2android.BuildConfig.DEBUG) {
if (com.medithings.vesiscan.BuildConfig.DEBUG) {
android.util.Log.e("VivamyoMonitor", "NirsMcjPacket.parse returned null! data.size=${data.size}")
}
}
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.monitoring
package com.medithings.vesiscan.ui.views.monitoring
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
@@ -20,12 +20,12 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.R
import com.example.medilightv2android.measure.VoidingRecord
import com.example.medilightv2android.measure.VoidingRecordStore
import com.example.medilightv2android.ui.theme.MlCardBackground
import com.example.medilightv2android.ui.theme.MlPrimary
import com.example.medilightv2android.ui.theme.MlSecondaryText
import com.medithings.vesiscan.R
import com.medithings.vesiscan.measure.VoidingRecord
import com.medithings.vesiscan.measure.VoidingRecordStore
import com.medithings.vesiscan.ui.theme.MlCardBackground
import com.medithings.vesiscan.ui.theme.MlPrimary
import com.medithings.vesiscan.ui.theme.MlSecondaryText
import java.text.SimpleDateFormat
import java.util.*
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.onboarding
package com.medithings.vesiscan.ui.views.onboarding
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
@@ -16,10 +16,10 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppState
import com.example.medilightv2android.R
import com.example.medilightv2android.ui.components.BladdyIdleRiveView
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.R
import com.medithings.vesiscan.ui.components.BladdyIdleRiveView
import com.medithings.vesiscan.ui.theme.*
@Composable
fun OnboardingView(appState: AppState) {
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.personalization
package com.medithings.vesiscan.ui.views.personalization
import android.os.Handler
import android.os.Looper
@@ -25,11 +25,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppState
import com.example.medilightv2android.R
import com.example.medilightv2android.ble.BleManager
import com.example.medilightv2android.ui.components.BladdyIdleRiveView
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.R
import com.medithings.vesiscan.ble.BleManager
import com.medithings.vesiscan.ui.components.BladdyIdleRiveView
import com.medithings.vesiscan.ui.theme.*
import kotlin.math.roundToInt
/**
@@ -338,7 +338,7 @@ private fun WakeupAlarmCard() {
val context = LocalContext.current
var enabled by androidx.compose.runtime.remember {
androidx.compose.runtime.mutableStateOf(
com.example.medilightv2android.services.WakeupAlarmPrefs.isEnabled(context)
com.medithings.vesiscan.services.WakeupAlarmPrefs.isEnabled(context)
)
}
Card(
@@ -370,7 +370,7 @@ private fun WakeupAlarmCard() {
checked = enabled,
onCheckedChange = {
enabled = it
com.example.medilightv2android.services.WakeupAlarmPrefs.setEnabled(context, it)
com.medithings.vesiscan.services.WakeupAlarmPrefs.setEnabled(context, it)
},
colors = androidx.compose.material3.SwitchDefaults.colors(
checkedTrackColor = Color(0xFFD32F2F)
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.pin
package com.medithings.vesiscan.ui.views.pin
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
@@ -12,10 +12,10 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppState
import com.example.medilightv2android.services.UserStorage
import com.example.medilightv2android.ui.components.BladdyIdleRiveView
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.services.UserStorage
import com.medithings.vesiscan.ui.components.BladdyIdleRiveView
import com.medithings.vesiscan.ui.theme.*
enum class PinMode { SETUP, ENTER }
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.pin
package com.medithings.vesiscan.ui.views.pin
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -20,8 +20,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.R
import com.example.medilightv2android.ui.theme.MlCardBackground
import com.medithings.vesiscan.R
import com.medithings.vesiscan.ui.theme.MlCardBackground
@Composable
fun ShuffledKeypad(
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.registration
package com.medithings.vesiscan.ui.views.registration
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@@ -18,11 +18,11 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppState
import com.example.medilightv2android.R
import com.example.medilightv2android.models.Sex
import com.example.medilightv2android.ui.components.BladdyIdleRiveView
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.R
import com.medithings.vesiscan.models.Sex
import com.medithings.vesiscan.ui.components.BladdyIdleRiveView
import com.medithings.vesiscan.ui.theme.*
@Composable
fun RegistrationView(appState: AppState) {
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.reminder
package com.medithings.vesiscan.ui.views.reminder
import android.content.Intent
import android.provider.Settings
@@ -20,10 +20,10 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.R
import com.example.medilightv2android.services.ReminderService
import com.example.medilightv2android.ui.components.LockableSlider
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.R
import com.medithings.vesiscan.services.ReminderService
import com.medithings.vesiscan.ui.components.LockableSlider
import com.medithings.vesiscan.ui.theme.*
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -1,4 +1,4 @@
package com.example.medilightv2android.ui.views.sensorselect
package com.medithings.vesiscan.ui.views.sensorselect
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -22,11 +22,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.medilightv2android.AppState
import com.example.medilightv2android.R
import com.example.medilightv2android.models.SensorMode
import com.example.medilightv2android.ui.components.BladdyIdleRiveView
import com.example.medilightv2android.ui.theme.*
import com.medithings.vesiscan.AppState
import com.medithings.vesiscan.R
import com.medithings.vesiscan.models.SensorMode
import com.medithings.vesiscan.ui.components.BladdyIdleRiveView
import com.medithings.vesiscan.ui.theme.*
@Composable
fun SensorSelectView(appState: AppState) {
@@ -15,9 +15,9 @@
* own anatomical gate already drops genuinely-bad detections. This layer
* just surfaces "this channel's reading just jumped, double-check".
*/
package com.example.medilightv2android.walldetect
package com.medithings.vesiscan.walldetect
import com.example.medilightv2android.walldetect.dto.ChannelResult
import com.medithings.vesiscan.walldetect.dto.ChannelResult
import kotlin.math.abs
class DetectionSanity(
@@ -4,7 +4,7 @@
* Project: CharlesKWONsLaw — wall-detect live compare
* All rights reserved.
*/
package com.example.medilightv2android.walldetect
package com.medithings.vesiscan.walldetect
object DetectorIds {
const val V2 = "v2"
@@ -13,14 +13,14 @@
* 인터페이스는 WallDetector 와 무관 — alignment.py 가 channels[i].urine_len 만
* 필요로 하므로 가벼운 단일-함수 API 로 유지.
*/
package com.example.medilightv2android.walldetect
package com.medithings.vesiscan.walldetect
import com.example.medilightv2android.walldetect.algo.methodd.MethodDParams
import com.example.medilightv2android.walldetect.algo.methodd.MethodDPreprocessing
import com.example.medilightv2android.walldetect.algo.methodd.MethodDSpan
import com.example.medilightv2android.walldetect.algo.methodd.MethodDWallSelect
import com.example.medilightv2android.walldetect.algo.methodd.MethodDWallSelect.CType
import com.example.medilightv2android.walldetect.algo.methodd.MethodDWallSelect.Side
import com.medithings.vesiscan.walldetect.algo.methodd.MethodDParams
import com.medithings.vesiscan.walldetect.algo.methodd.MethodDPreprocessing
import com.medithings.vesiscan.walldetect.algo.methodd.MethodDSpan
import com.medithings.vesiscan.walldetect.algo.methodd.MethodDWallSelect
import com.medithings.vesiscan.walldetect.algo.methodd.MethodDWallSelect.CType
import com.medithings.vesiscan.walldetect.algo.methodd.MethodDWallSelect.Side
import kotlin.math.max
data class MethodDResult(

Some files were not shown because too many files have changed in this diff Show More