Conversation
WalkthroughBLE広告データを解析するための新しいユーティリティ「BleAdvertisementParser」を導入し、BLERepository内の手動iBeacon解析を置き換えました。BLEApiのスキャンコールバック署名を更新し、OtherFileStorageApiにキューフラッシング機能を追加しました。 Changes
Sequence DiagramsequenceDiagram
participant Scanner as BLE Scanner
participant BLEApi as BLEApi
participant Repository as BLERepository
participant Parser as BleAdvertisementParser
participant Queue as Data Queue
Scanner->>BLEApi: onBatchScanResults(results)
loop For each ScanResult
BLEApi->>Repository: resultBeacon(ScanResult)
Repository->>Parser: parseUuids(scanRecord.bytes)
Parser->>Parser: extractStructures()<br/>parseStructureUuids()
Parser-->>Repository: List<UUID>
loop For each UUID
Repository->>Queue: addQueue(timestamp, UUID, RSSI)
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
app/src/main/java/net/kajilab/elpissender/utils/BleAdvertisementParser.kt (1)
426-429:data classでByteArrayを使用する際の注意点。
data classのequals()とhashCode()はByteArrayの参照比較を行うため、内容が同じでも異なるインスタンスは等価とみなされません。現在の実装では
AdvertisementStructureはプライベートかつイテレーション用途のみで使用されているため、実質的な問題はありませんが、将来的に比較やセットへの格納が必要になった場合は注意が必要です。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/net/kajilab/elpissender/utils/BleAdvertisementParser.kt` around lines 426 - 429, AdvertisementStructure uses a ByteArray field which causes its generated equals()/hashCode() to do reference comparisons; to fix, either change the type to an immutable collection like List<Byte> for value-based equality or keep ByteArray but override equals() and hashCode() in AdvertisementStructure to use data.contentEquals(other.data) and data.contentHashCode() (and retain the data class semantics otherwise), referencing AdvertisementStructure, its data property, and the equals()/hashCode() behavior when making the change.app/src/main/java/net/kajilab/elpissender/api/BLEApi.kt (1)
62-77:onScanResultとonBatchScanResultsの両方を定義していますが、バッチスキャンは有効化されていません。現在の
ScanSettingsではsetReportDelay()が設定されていないため、スキャン結果はonScanResultのみを通じて配信されます。onBatchScanResultsはバッチレポートが有効な場合のみ呼び出されます。バッチスキャンを有効にする場合は、
ScanSettingsにsetReportDelay()を追加してください:💡 バッチスキャンを有効化する場合の修正案
val scanSettings = ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER) + .setReportDelay(1000) // ミリ秒単位でバッチ間隔を指定 .build()現状のままでも動作に問題はありませんが、
onBatchScanResultsのコードは実行されません。意図的な防御的コーディングであれば問題ありませんが、確認をお願いします。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/net/kajilab/elpissender/api/BLEApi.kt` around lines 62 - 77, The code defines both onScanResult and onBatchScanResults but ScanSettings does not enable batching, so onBatchScanResults will never be called; either remove/annotate the unused onBatchScanResults handler or enable batch reporting by updating the ScanSettings construction to call setReportDelay(...) (and keep onBatchScanResults) so batched results are delivered; locate the BLE scan setup (where ScanSettings is built) and adjust accordingly and/or remove the unused onBatchScanResults method in BLEApi.kt to match intended behavior.app/src/test/java/net/kajilab/elpissender/utils/BleAdvertisementParserTest.kt (1)
79-95: エッジケースのテスト追加を検討してください。現在のテストは正常系をカバーしていますが、以下のようなエッジケースのテスト追加を推奨します:
- 不正な形式のADストラクチャ(length=0、途中で切れたデータ)
- 複数のiBeaconを含むアドバタイズメント
- 16-bit/32-bit/128-bit UUIDの各パターン
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/test/java/net/kajilab/elpissender/utils/BleAdvertisementParserTest.kt` around lines 79 - 95, Add unit tests to BleAdvertisementParserTest that cover the edge cases missing from the current suite: write tests invoking BleAdvertisementParser.parseUuids for (1) an AD structure with length=0, (2) a truncated AD payload (cut off mid-structure) to ensure it fails gracefully or returns empty, (3) an advertisement containing multiple iBeacon structures to ensure all UUIDs are returned, and (4) advertisements containing 16-bit, 32-bit, and 128-bit UUID encodings to verify correct parsing for each size; place these as new `@Test` methods in the same test class and assert expected behavior (empty or correct identifiers) for each case.app/src/main/java/net/kajilab/elpissender/repository/BLERepository.kt (1)
42-42: CSVフォーマットにおけるスペースの扱いを確認してください。データフォーマットが
"$time , $uuid , $rssi"となっており、カンマの前後にスペースが含まれています。これは一般的なCSVフォーマット(カンマのみ)とは異なります。後続の処理でCSVパーサーを使用する場合、スペースがフィールド値の一部として扱われる可能性があります。意図的なフォーマットであれば問題ありませんが、確認をお願いします。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/net/kajilab/elpissender/repository/BLERepository.kt` at line 42, The CSV field string assigned to data ("data = \"$time , $uuid , $rssi\"") includes spaces around commas which may be treated as part of field values by CSV parsers; update the assignment in BLERepository.kt (the data variable/assignment line) to use a standard CSV format without spaces (e.g., "$time,$uuid,$rssi") or, if spaces are required, document and/or explicitly trim fields when parsing so downstream CSV consumers won't see leading/trailing spaces.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/src/main/java/net/kajilab/elpissender/api/OtherFileStorageApi.kt`:
- Around line 68-72: 停止時の toArray()→clear() に競合があり queue の項目が欠落するため、queue
のスナップショット取得とクリアを原子的に行うよう修正してください:queue への参照(queue)に対し synchronized
ブロック(または同等のロック)を導入し、停止時のブロック(現在の if (queue.isNotEmpty()) {...} 内)と定期排出側の
runnable(該当 Runnable/スレッド内の toArray()/clear()
を実行している箇所)の両方を同じロックで保護して、コピー作成(toArray 相当)と queue.clear() を一連の操作として実行し、そのコピーを
saveArrayDeque(...) に渡すようにしてください。
In `@app/src/main/java/net/kajilab/elpissender/utils/BleAdvertisementParser.kt`:
- Around line 94-96: The branch handling TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT
currently calls parseServiceDataUuid and thus only returns a single UUID; change
it to call parsePlainUuidList (with the same offset/length usage as other
plain-UUID parsers, e.g., parsePlainUuidList(data, 2)) so the full list of
16-bit UUIDs is parsed; update the mapping that uses
TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT to invoke parsePlainUuidList instead of
parseServiceDataUuid.
---
Nitpick comments:
In `@app/src/main/java/net/kajilab/elpissender/api/BLEApi.kt`:
- Around line 62-77: The code defines both onScanResult and onBatchScanResults
but ScanSettings does not enable batching, so onBatchScanResults will never be
called; either remove/annotate the unused onBatchScanResults handler or enable
batch reporting by updating the ScanSettings construction to call
setReportDelay(...) (and keep onBatchScanResults) so batched results are
delivered; locate the BLE scan setup (where ScanSettings is built) and adjust
accordingly and/or remove the unused onBatchScanResults method in BLEApi.kt to
match intended behavior.
In `@app/src/main/java/net/kajilab/elpissender/repository/BLERepository.kt`:
- Line 42: The CSV field string assigned to data ("data = \"$time , $uuid ,
$rssi\"") includes spaces around commas which may be treated as part of field
values by CSV parsers; update the assignment in BLERepository.kt (the data
variable/assignment line) to use a standard CSV format without spaces (e.g.,
"$time,$uuid,$rssi") or, if spaces are required, document and/or explicitly trim
fields when parsing so downstream CSV consumers won't see leading/trailing
spaces.
In `@app/src/main/java/net/kajilab/elpissender/utils/BleAdvertisementParser.kt`:
- Around line 426-429: AdvertisementStructure uses a ByteArray field which
causes its generated equals()/hashCode() to do reference comparisons; to fix,
either change the type to an immutable collection like List<Byte> for
value-based equality or keep ByteArray but override equals() and hashCode() in
AdvertisementStructure to use data.contentEquals(other.data) and
data.contentHashCode() (and retain the data class semantics otherwise),
referencing AdvertisementStructure, its data property, and the
equals()/hashCode() behavior when making the change.
In
`@app/src/test/java/net/kajilab/elpissender/utils/BleAdvertisementParserTest.kt`:
- Around line 79-95: Add unit tests to BleAdvertisementParserTest that cover the
edge cases missing from the current suite: write tests invoking
BleAdvertisementParser.parseUuids for (1) an AD structure with length=0, (2) a
truncated AD payload (cut off mid-structure) to ensure it fails gracefully or
returns empty, (3) an advertisement containing multiple iBeacon structures to
ensure all UUIDs are returned, and (4) advertisements containing 16-bit, 32-bit,
and 128-bit UUID encodings to verify correct parsing for each size; place these
as new `@Test` methods in the same test class and assert expected behavior (empty
or correct identifiers) for each case.
ℹ️ Review info
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
app/src/main/java/net/kajilab/elpissender/api/BLEApi.ktapp/src/main/java/net/kajilab/elpissender/api/OtherFileStorageApi.ktapp/src/main/java/net/kajilab/elpissender/repository/BLERepository.ktapp/src/main/java/net/kajilab/elpissender/utils/BleAdvertisementParser.ktapp/src/test/java/net/kajilab/elpissender/utils/BleAdvertisementParserTest.kt
| if (queue.isNotEmpty()) { | ||
| val copy = queue.toArray() | ||
| queue.clear() | ||
| saveArrayDeque(copy) | ||
| } |
There was a problem hiding this comment.
停止時フラッシュでキュー項目を取りこぼす可能性があります。
Line 69-70 の toArray()→clear() が非同期保護なしのため、別スレッドから同時に追加されると、copy に載らないデータが clear() で消えて CSV 未出力になります。PR目的に対してデータ欠損リスクがあるので、スナップショット化とクリアを原子的にしてください(synchronized 等)。同じ根本原因が runnable 側(Line 41-43)にもあるため、両方を同じ方式で保護するのが必要です。
修正例(排出処理を原子的にする)
class OtherFileStorageApi(
@@
private val queue: ArrayDeque<String>,
) {
+ private val queueLock = Any()
@@
override fun run() {
- // 1:コピー作成
- val pressureCopy = queue.toArray()
- // 2:本体をクリア
- queue.clear()
+ val pressureCopy =
+ synchronized(queueLock) {
+ queue.toArray().also { queue.clear() }
+ }
// 3:コピーをファイルに書き込む
saveArrayDeque(pressureCopy)
@@
fun stop(): File {
// 別スレッドを停止
handler.removeCallbacks(runnable)
- if (queue.isNotEmpty()) {
- val copy = queue.toArray()
- queue.clear()
- saveArrayDeque(copy)
- }
+ val copy =
+ synchronized(queueLock) {
+ if (queue.isEmpty()) emptyArray() else queue.toArray().also { queue.clear() }
+ }
+ if (copy.isNotEmpty()) saveArrayDeque(copy)
return File(filePath)
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/src/main/java/net/kajilab/elpissender/api/OtherFileStorageApi.kt` around
lines 68 - 72, 停止時の toArray()→clear() に競合があり queue の項目が欠落するため、queue
のスナップショット取得とクリアを原子的に行うよう修正してください:queue への参照(queue)に対し synchronized
ブロック(または同等のロック)を導入し、停止時のブロック(現在の if (queue.isNotEmpty()) {...} 内)と定期排出側の
runnable(該当 Runnable/スレッド内の toArray()/clear()
を実行している箇所)の両方を同じロックで保護して、コピー作成(toArray 相当)と queue.clear() を一連の操作として実行し、そのコピーを
saveArrayDeque(...) に渡すようにしてください。
| TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT, | ||
| TYPE_SERVICE_DATA_16_BIT, | ||
| -> parseServiceDataUuid(data, 2) |
There was a problem hiding this comment.
TYPE_SERVICE_SOLICITATION_UUIDS_16_BITのパース処理に誤りがあります。
TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT(0x14)は16-bit UUIDのリストを含むため、parsePlainUuidListを使用すべきです。現在の実装ではparseServiceDataUuidを使用しているため、最初のUUIDのみが抽出され、残りのUUIDが失われます。
BLE仕様:
- 0x14 (Service Solicitation 16-bit): 16-bit UUIDのリスト
- 0x16 (Service Data 16-bit): 1つの16-bit UUID + データペイロード
🐛 修正案
- TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT,
TYPE_SERVICE_DATA_16_BIT,
-> parseServiceDataUuid(data, 2)
+ TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT -> parsePlainUuidList(data, 2)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/src/main/java/net/kajilab/elpissender/utils/BleAdvertisementParser.kt`
around lines 94 - 96, The branch handling TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT
currently calls parseServiceDataUuid and thus only returns a single UUID; change
it to call parsePlainUuidList (with the same offset/length usage as other
plain-UUID parsers, e.g., parsePlainUuidList(data, 2)) so the full list of
16-bit UUIDs is parsed; update the mapping that uses
TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT to invoke parsePlainUuidList instead of
parseServiceDataUuid.
Summary by CodeRabbit
リリースノート
新機能
改善
テスト