Repository navigation
Wrap BLE logs with the phone's acquisition time and log VCSEC status - #148
Merged
Merged
Conversation
Every logged BLE reply is now wrapped in one envelope, BleRecord: the phone's clock when the reply arrived (acquired_at) next to the car's raw message, verbatim, as a oneof payload (charge_state, vehicle_status; DriveState joins as field 4 later). Car timestamps are never touched. Charge samples stay on ChargeState.timestamp (ADR-0006: never filled in; a record without it or without a level is still not logged), and VCSEC status, which has no clock, is timed by acquired_at. The proto lives in a second Wire source root, core/src/main/proto-teslable, so a re-vendor of Tesla's protos never touches it, and its header carries the evolution rules that keep old records readable. The controller reads the phone's clock once per incoming reply and hands it to HistoryStore.record (charge) and recordStatus. A status reading is logged when it is the first for the vehicle, the first after a (re)connect, or changed; otherwise every 15 minutes, so a sleeping car with a phone connected is distinguishable from a phone out of range (shouldLogStatus, a pure core function). TeslaVcsec.Status now carries the raw VehicleStatus, like TeslaCommands.Charge.raw. HistoryStore keeps one file per vehicle per kind through one VehicleLogs helper with the same 20k cap and trim: <vehicleId>.charge.pblog and <vehicleId>.status.pblog. BleRecord.toBatterySample and toStatusSample derive the read models; StatusSample is unchanged. The debug demo seeds the new charge file. Pre-1.0 reset: the old raw <vehicleId>.pblog charge files are no longer read or written, and are not deleted, so the history chart starts empty after the update. No migration code runs. Docs: ADR-0008 (BLE log envelope), a pointer in ADR-0006, PRIVACY.md, the master plan, and the two docs that named the old charge file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX
A build of the original #85 branch wrote an earlier record format to <vehicleId>.status.pblog. The envelope reader stops at the first such record, so that file would hide every later status reading. A new name leaves the old file ignored, like the old raw charge logs, with no manual delete before testing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX
dzid26
pushed a commit
that referenced
this pull request
Oct 8, 2026
#148 replaces this branch's StatusObservation status log with the BleRecord envelope (acquired_at, one file per vehicle per kind, status in <vehicleId>.vcsec.pblog). Every status-log file takes #148's version, and this branch's superseded status_observation.proto, StatusObservationMapping and its test, and the first ADR-0008 draft are removed. What remains on top of #148 is the parked-drain projection: statusHistory on the controller, HistorySamples, the projection and its tests, the car screen wiring, README and the master-plan projection line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX
9 of 14 tasks
Contributor
ScreenshotsCaptured from the demo build at 3f46af5. Debug APK: zip from Android CI (GitHub sign-in needed) |
7 of 12 tasks
Review on #148: - BleRecord fields now follow a reading's order: acquired_at (1), vehicle_status (2), charge_state (3), with DriveState as 4 next. A test pins the tags. Records from pre-merge test builds, numbered the other way, decode as the wrong kind or not at all: the read models skip records without their payload, and ProtoLog now skips a complete record that fails to decode (and empty frames) instead of stopping, so the records after it still read. A truncated tail still ends the read. - A status reading the policy skipped is held back, and logged when the link to the car drops (StatusLogGate in core, called from the controller's disconnect path). Each observed stretch then ends at the last reading before the phone lost the car instead of up to 15 minutes earlier. - Every charge reply is logged raw, including one without the car's timestamp or a level; those stay off the chart (owner: keep all raw). ADR-0008 and the ADR-0006 pointer record all three. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX
dzid26
pushed a commit
that referenced
this pull request
Oct 8, 2026
#148 now orders the envelope as time, status, charge (fields 1-3), so drive_state stays field 4 after charge_state, and the field-order test covers all four in place of the old numbering test. #148's link-lost status flush and raw charge logging merge in unchanged. Drive replies follow the same owner rule as charge (keep all raw): every reply is logged, including one without the car's own timestamp, which stays out of driveSamples. ADR-0008 records both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX
Contributor
ScreenshotsCaptured from the demo build at a5234e6. Debug APK: zip from Android CI (GitHub sign-in needed) |
7 of 13 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
Wraps every logged BLE reply in one envelope,
BleRecord, and logs VCSEC status through it. This is the status-log half of #85, split out to land first. #149 (DriveState) is stacked on it.core/src/main/proto-teslable/ble_record.proto). Fields follow a reading's order:acquired_at(1, the phone's clock at arrival), then apayloadoneof with the car's raw reply, verbatim:vehicle_status(2) orcharge_state(3). DriveState is field 4 in Log DriveState in the BLE envelope #149. Car timestamps are never touched. The proto header and ADR-0008 carry the evolution rules (additive only), and a test pins the tags.<vehicleId>.charge.pblog). Every reply is logged raw. One without the car's timestamp or a level stays in the log but off the chart (owner: keep all raw).<vehicleId>.vcsec.pblog). It is timed byacquired_at, since VCSEC has no clock. A reading is logged when it is the first, the first after a (re)connect, or a change; otherwise every 15 min. When the link drops, the newest skipped reading is logged too (StatusLogGate), so each observed stretch ends at the last reading before the phone lost the car.acquiredAtMillis, and the disconnect path callshistoryStore.onLinkLost.Decisions
<vehicleId>.pblogfiles are no longer read, and not deleted, so the chart starts empty after the update. No migration code..status.pblog) are skipped by the readers, so nothing needs deleting.Type
Testing
:core:test(169),:app:testDebugUnitTest(21),:app:assembleDebug,:app:lintDebug, ktlint and detekt. New tests cover the envelope mapping, the wire tags,StatusLogGate(hold back, link-lost hand-over, reconnect, seeding), and ProtoLog skipping undecodable and empty frames.Checklist
expected.txtregenerated, not hand-edited (n/a: storage format only)SPDX-License-Identifier: AGPL-3.0-only🤖 Generated with Claude Code
https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX