Skip to content

Add charge start vibration capability#4

Merged
nonnil merged 4 commits into
mainfrom
fix/device-capability-matrix
Apr 21, 2026
Merged

Add charge start vibration capability#4
nonnil merged 4 commits into
mainfrom
fix/device-capability-matrix

Conversation

@nonnil
Copy link
Copy Markdown
Member

@nonnil nonnil commented Apr 21, 2026

Summary

  • Add DeviceCapability::ChargeStartVibration and route supports_charge_start_vibration() through the capability matrix.

  • Replace the capability tests with an explicit model-by-capability matrix covering all current variants.

  • Align FlexPuff documentation with the current ILUMA i-only capability gate and add the project rules capability matrix.

  • closes Audit and refine per-model capability matrix in DeviceCapability #3

Validation

  • cargo fmt --all --check
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo test --all-targets --all-features
  • RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
  • cargo check --all-targets --all-features

Summary by CodeRabbit

  • New Features

    • Introduced a new device capability system for managing supported features across device models.
  • Bug Fixes

    • Added validation to prevent FlexPuff operations on unsupported device models.
  • Documentation

    • Updated supported device information to clarify FlexPuff and FlexBattery/Pause Mode availability for ILUMA i and ILUMA i PRIME.
  • Refactor

    • Updated FlexPuff API methods to require explicit device model parameter for better validation and feature control.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

📝 Walkthrough

Walkthrough

This pull request updates FlexPuff capability gating to require an explicit DeviceModel parameter in read/set methods with pre-validation, introduces a new ChargeStartVibration device capability, refactors capability mapping logic, and updates documentation to reflect FlexPuff support on ILUMA i and ILUMA i PRIME models.

Changes

Cohort / File(s) Summary
FlexPuff Method Signatures
src/lib.rs
Updated read_flexpuff() and set_flexpuff() to accept DeviceModel parameter with pre-check returning Error::Unsupported if model lacks FlexPuff capability. Tests updated to pass model argument and verify unsupported models fail before transport operations.
FlexPuff Documentation
README.md, src/protocol/flexpuff.rs
Updated feature list and Rustdoc to reflect FlexPuff support on "ILUMA i and ILUMA i PRIME" instead of "ILUMA i" or earlier holder-based models.
Device Capability Architecture
src/protocol/types.rs
Introduced DeviceCapability::ChargeStartVibration variant and marked enum as #[non_exhaustive]. Refactored supports() method to handle the new capability and updated supports_charge_start_vibration() to delegate through capability API. Restructured unit tests into capability-by-model matrix with alignment assertions.
Debug and Test Code
debug/hardware_ble/exercises.rs, debug/hardware_ble/suites.rs
Updated flexpuff() function signature and all call sites to accept and propagate DeviceModel parameter through read/set/exercise operations.
Repository Configuration
.gitignore
Added entries for /docs/rules/ and package-lock.json; ensured file ends with newline.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • feat: add device status read #2 — Updates device-model/capability logic and modifies Iqos API signatures to accept DeviceModel for read operations; shares similar architectural patterns and capability-gating approach.

Poem

🐰 FlexPuff now checks its model first,
Before the vibrations quench its thirst!
ILUMA i PRIME joins the dance,
While capabilities get their chance! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'Add charge start vibration capability' accurately summarizes the main structural change in the PR (introduction of DeviceCapability::ChargeStartVibration), but the changeset is significantly broader, including FlexPuff signature updates, documentation corrections, and supporting infrastructure changes that constitute substantial portions of the work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/device-capability-matrix

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nonnil nonnil requested a review from Copilot April 21, 2026 09:33
@nonnil nonnil marked this pull request as ready for review April 21, 2026 09:34
@nonnil
Copy link
Copy Markdown
Member Author

nonnil commented Apr 21, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an explicit ChargeStartVibration device capability and centralizes charge-start vibration support behind the capability matrix, while tightening documentation and tests around the per-model feature matrix.

Changes:

  • Add DeviceCapability::ChargeStartVibration and route supports_charge_start_vibration() through DeviceModel::supports(...).
  • Replace ad-hoc capability tests with a single explicit model-by-capability matrix test.
  • Update FlexPuff documentation (and README) to reflect ILUMA i-family support; add project rules doc with the capability matrix.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/protocol/types.rs Introduces the new capability, updates the support matrix routing, and refactors tests into an explicit matrix.
src/protocol/flexpuff.rs Updates rustdoc to reflect correct FlexPuff model support.
src/lib.rs Aligns public API rustdoc for read_flexpuff() with the updated capability matrix.
docs/rules/project.md Adds AI-agent project rules and documents the model/capability matrix.
README.md Updates the “Programmatic device control” bullet to annotate FlexPuff model support.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md Outdated
### Programmatic device control

- Brightness, vibration, FlexPuff
- Brightness, vibration, FlexPuff _(ILUMA i)_
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README now says FlexPuff is available on “ILUMA i”, but elsewhere (and in the capability matrix) it’s specifically IlumaI and IlumaIPrime. Consider updating this bullet to mention ILUMA i and ILUMA i PRIME (or “ILUMA i family”) to avoid underspecifying support.

Suggested change
- Brightness, vibration, FlexPuff _(ILUMA i)_
- Brightness, vibration, FlexPuff _(ILUMA i and ILUMA i PRIME)_

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 3faa3f7: the README now separates Brightness/Vibration from ILUMA i-only controls and lists FlexPuff/FlexBattery/Pause Mode as ILUMA i / ILUMA i PRIME.

Comment thread src/protocol/types.rs
Comment on lines 123 to 127
/// Lock/unlock support.
DeviceLock,
/// Holder vibration feedback when the stick begins charging.
ChargeStartVibration,
}
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DeviceCapability is a public enum re-exported from the crate; adding a new variant is a SemVer-breaking change for downstream users that exhaustively match on it. If this crate intends to maintain 1.x SemVer stability, consider marking DeviceCapability as #[non_exhaustive] (and updating docs/changelog accordingly) or otherwise treating this as a major-version bump change.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 3faa3f7: DeviceCapability is now #[non_exhaustive], so downstream exhaustive matches must include a wildcard arm while this crate can continue matching internally.

Comment thread docs/rules/project.md Outdated
Comment on lines +3 to +5
Authoritative source of project-local constraints, gotchas, and best practices.
Read this before touching any code. Cross-reference with `AGENTS.md` for
architecture and git hygiene rules.
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doc references AGENTS.md as an architecture/git hygiene source, but that file does not exist in the repository. Either add the referenced file or update the text to point at the correct existing document so readers/agents aren’t sent to a dead link.

Suggested change
Authoritative source of project-local constraints, gotchas, and best practices.
Read this before touching any code. Cross-reference with `AGENTS.md` for
architecture and git hygiene rules.
Authoritative source of project-local constraints, gotchas, best practices,
architecture, and git hygiene rules.
Read this before touching any code.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/rules/project.md`:
- Line 24: Three fenced code blocks use plain triple backticks (```) with no
language, triggering markdownlint MD040; update each plain fence to specify a
language (e.g., change ``` to ```text or another appropriate language) for the
three occurrences of the triple-backtick fenced code blocks so markdownlint-cli2
stops flagging MD040 and the blocks render consistently.
- Around line 62-82: The command-prefix table is inverted for FlexPuff: change
the table so 0xD2 is listed as the FlexPuff request prefix
(LOAD_FLEXPUFF_COMMAND request byte 1 = 0xD2) and 0x90 is listed as the FlexPuff
response marker (parser checks bytes[1] == 0x90); also add a short example in
the "Critical gotcha" section mirroring the Holder example (e.g., request [0x00,
0xD2, ...] → response [0x00, 0x90, ...]) so readers see the request-vs-response
discriminant for LOAD_FLEXPUFF_COMMAND and FirmwareKind/response matching.

In `@README.md`:
- Line 26: The README's feature bullet wrongly tags "Brightness, vibration,
FlexPuff _(ILUMA i)_" as ILUMA i-only; update the README so that Brightness and
Vibration are shown as supported on all non-Unknown models (remove the trailing
"_(ILUMA i)_" qualifier from those capabilities) and ensure only FlexPuff is
gated to ILUMA i / ILUMA i PRIME (use the same phrasing as src/lib.rs and
src/protocol/flexpuff.rs, e.g., "_(ILUMA i / ILUMA i PRIME)_"); also adjust the
FlexBattery line similarly if present to "_(ILUMA i / ILUMA i PRIME)_". Use
references to the capability matrix in src/protocol/types.rs when editing to
match the canonical gating.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d5876b8d-6413-475a-b2c2-1858571c16be

📥 Commits

Reviewing files that changed from the base of the PR and between afaf752 and 7d87248.

📒 Files selected for processing (5)
  • README.md
  • docs/rules/project.md
  • src/lib.rs
  • src/protocol/flexpuff.rs
  • src/protocol/types.rs

Comment thread docs/rules/project.md Outdated

## Device Model Reference

```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

markdownlint MD040: specify a language for fenced code blocks.

Static analysis flags the three plain fences at lines 24, 55, and 88. Usetext (or an appropriate language) to keep markdownlint-cli2 clean.

Also applies to: 55-55, 88-88

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 24-24: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/rules/project.md` at line 24, Three fenced code blocks use plain triple
backticks (```) with no language, triggering markdownlint MD040; update each
plain fence to specify a language (e.g., change ``` to ```text or another
appropriate language) for the three occurrences of the triple-backtick fenced
code blocks so markdownlint-cli2 stops flagging MD040 and the blocks render
consistently.

Comment thread docs/rules/project.md Outdated
Comment on lines +62 to +82
**Known command prefix families:**

| Byte 1 | Component | Example |
|--------|-----------|---------|
| `0xC0` | Stick / device-wide | `LOAD_STICK_FIRMWARE_VERSION_COMMAND` |
| `0xC9` | Holder | `LOAD_HOLDER_FIRMWARE_VERSION_COMMAND` |
| `0x08` | Response marker (holder) | appears in holder response frames |
| `0x90` | FlexPuff | `LOAD_FLEXPUFF_COMMAND` |
| `0xD2` | (mapped in captures, TBD) | reserved — do not guess |

### Critical gotcha: FirmwareKind discriminant vs response byte

`FirmwareKind::Stick = 0xC0` — the **request** uses `0xC0` at byte 1.
`FirmwareKind::Holder = 0x08` — the **response** uses `0x08` at byte 1, even though
the **request** used `0xC9`. Do not confuse request prefix with response discriminant.

```rust
// FirmwareVersion::from_response checks bytes[1] == kind as u8
// Holder kind = 0x08 → expects 0x08 in response bytes[1]
// Holder request = [0x00, 0xC9, ...] → response arrives as [0x00, 0x08, ...]
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Command-prefix table contradicts LOAD_FLEXPUFF_COMMAND and undermines the gotcha section.

src/protocol/flexpuff.rs defines LOAD_FLEXPUFF_COMMAND = [0x00, 0xD2, 0x05, ...] (request byte 1 = 0xD2), and the parser matches bytes[1] == 0x90 on the response. The table here has this inverted:

  • Line 69 maps 0x90LOAD_FLEXPUFF_COMMAND, but 0x90 is the FlexPuff response marker, not the request prefix.
  • Line 70 lists 0xD2 as "reserved — do not guess", even though 0xD2 is actually the FlexPuff request prefix in use.

This is exactly the request-vs-response discriminant gotcha the following section warns about, so leaving it wrong in the authoritative rules doc is especially misleading.

📝 Proposed fix
-| `0x90` | FlexPuff | `LOAD_FLEXPUFF_COMMAND` |
-| `0xD2` | (mapped in captures, TBD) | reserved — do not guess |
+| `0xD2` | FlexPuff (request) | `LOAD_FLEXPUFF_COMMAND` |
+| `0x90` | Response marker (FlexPuff) | appears in FlexPuff response frames |

Consider also adding a FlexPuff bullet to the "Critical gotcha" section mirroring the Holder 0xC90x08 example.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/rules/project.md` around lines 62 - 82, The command-prefix table is
inverted for FlexPuff: change the table so 0xD2 is listed as the FlexPuff
request prefix (LOAD_FLEXPUFF_COMMAND request byte 1 = 0xD2) and 0x90 is listed
as the FlexPuff response marker (parser checks bytes[1] == 0x90); also add a
short example in the "Critical gotcha" section mirroring the Holder example
(e.g., request [0x00, 0xD2, ...] → response [0x00, 0x90, ...]) so readers see
the request-vs-response discriminant for LOAD_FLEXPUFF_COMMAND and
FirmwareKind/response matching.

Comment thread README.md Outdated
@nonnil nonnil force-pushed the fix/device-capability-matrix branch from 7d87248 to 9b1b56e Compare April 21, 2026 09:39
@nonnil
Copy link
Copy Markdown
Member Author

nonnil commented Apr 21, 2026

@coderabbitai @copilot review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

@nonnil Sure, I'll kick off a review of the PR right away!

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Member Author

@nonnil nonnil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nonnil nonnil merged commit 0da6b20 into main Apr 21, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Audit and refine per-model capability matrix in DeviceCapability

2 participants