Skip to content

feat(scale): show connected Skale firmware revision - #742

Merged
tadelv merged 14 commits into
decentespresso:mainfrom
MaxRink:feat/skale-firmware-revision-714
Sep 14, 2026
Merged

tadelv merged 14 commits into
decentespresso:mainfrom
MaxRink:feat/skale-firmware-revision-714

Conversation

@MaxRink

@MaxRink MaxRink commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Read the connected Skale firmware revision from the standard Device Information Service and show the opaque value in Devices and GET /api/v1/scale/info. Metadata belongs to the current connection and clears on disconnect.

Linked Issue

Fixes #714

Verification

  • Full Flutter 3.44.2 Linux suite: 4,170 passed, 1 skipped, 0 failed.
  • dart format lib test: no changes; flutter analyze: no issues.
  • Focused fake-transport and handler tests cover metadata clearing, valid/unknown values, and REST/WS inventory exclusion.
  • Simulated integration of the native Skale series exercised the metadata endpoint through sb-dev, including hot reload. The companion USB branch also verified settings persistence across cold restart.
  • Physical Skale hardware was not retested for this revision.

Impact

Firmware metadata uses the narrow DeviceInformationCapable capability; other scales do not need no-op metadata getters. Device inventory REST/WS contracts remain unchanged. No firmware update or DFU behavior is added. API and device documentation are updated.

Contributor Responsibility

AI-assisted development is allowed. The submitter remains responsible for the submitted work.

  • I have reviewed and understand all changes in this PR and take responsibility for their correctness, security, behavior, licensing, and provenance, including any AI-assisted or AI-generated work.

@tadelv tadelv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the API boundary here should be changed before merge.

GET /api/v1/devices is an inventory/discovery surface: it can contain connected devices, currently available devices, and remembered devices that are no longer present. Adding connection-scoped deviceInfo to those inventory entries makes the resource ambiguous, because the enclosing device can persist while the metadata only exists for an active connection.

We already have a clearer precedent with GET /api/v1/machine/info, which represents information about the currently connected machine. I would prefer the scale side to follow the same model:

  • do not add deviceInfo to /api/v1/devices or /ws/v1/devices;
  • add GET /api/v1/scale/info for information obtained from the currently connected scale;
  • keep firmwareVersion opaque and optional;
  • let #743 extend the same ScaleInfo contract with nullable/optional batteryLevel;
  • if live scale-info updates are eventually needed, prefer a dedicated /ws/v1/scale/info surface rather than causing the device-inventory stream to change for metadata refreshes. I would not add that WebSocket until there is a concrete need.

This keeps a useful API distinction going forward: /api/v1/devices answers what devices exist and their connection state; role-specific /machine/info and /scale/info endpoints answer what Decaid has learned from the currently connected device. That also keeps this generic across future scale implementations without coupling the public API to Skale.

@tadelv tadelv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The revised API boundary is now aligned with the requested design: connected scale metadata lives under /api/v1/scale/info, while device inventory remains inventory-only. I still see two code/docs issues called out inline, plus the current head fails the repository's Dart format check, which is a hard pre-PR/verification gate in AGENTS.md and prevents analyze/tests from running in CI. Please run dart format lib test, push the formatter output, and address the inline items.

Comment thread doc/DeviceManagement.md Outdated
Comment thread lib/src/models/device/scale.dart Outdated

@tadelv tadelv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The two previous blockers are resolved. One cleanup remains from the abandoned inventory-metadata implementation: please revert the unused multi-subscription bookkeeping in DevicesStateAggregator back to the original single connection-state subscription shape. With inventory no longer subscribing to metadata, this refactor has no purpose and conflicts with the repository guidance to avoid adjacent refactors that the task does not require.

final List<StreamSubscription> _subscriptions = [];

final Map<String, (Device, StreamSubscription)> _deviceStateSubs = {};
final Map<String, (Device, List<StreamSubscription>)> _deviceStateSubs = {};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This List<StreamSubscription> shape is leftover scaffolding from when the PR was going to subscribe device inventory to metadata. The corrected design no longer does that, so every device still has exactly one connection-state subscription. Please revert this map and the associated loops to the original (Device, StreamSubscription) bookkeeping rather than carrying an unrelated complexity increase into #742.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Restored the original (Device, StreamSubscription) bookkeeping in f860b0e, including the single cancellation calls. devices_handler.dart now has no diff against the base implementation. Applied the same cleanup to #743 and #745.

@tadelv tadelv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The API boundary and the previously requested cleanup are now in the right shape. I still want two things corrected before merge:

  1. Please remove the broad no-op ScaleInfo? get scaleInfo => null overrides from every non-Skale scale implementation/test double. Scale already provides that default, so these edits add churn across unrelated device implementations without changing behavior. This is exactly the kind of adjacent change AGENTS.md asks us to avoid; only implementations that actually provide scale info should override it.
  2. Please drop the remaining unrelated diff while doing that (tare/timer warning additions in scale_handler.dart and the newline-only websocket_v1.yml change). They are not needed for #714.

Also, please verify the result against current main before considering this ready. #820 has now merged the host-owned BLE/plugin-driver checkpoint, while this branch's local/full-suite evidence predates that merge and the current PR workflow is still action_required with no jobs. A rebase plus the relevant Scale/PluginScale/API tests (or a green merge-result CI run) is enough; no extra hardware testing is required for this review.

I do not think #742 itself needs to be held for the generic-driver work: /api/v1/scale/info is a generic host/domain surface and the Skale firmware read is narrowly scoped. But please keep the new metadata abstraction minimal here; richer plugin/device capabilities should continue to be defined through #809 rather than expanded from this Skale-specific PR.

MaxRink and others added 14 commits September 14, 2026 10:05
Remove duplicate firmware state and subscription bookkeeping identified during the ponytail review. The firmware revision still publishes only validated values while disconnect cleanup and UI behavior remain unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The top-right Settings page did not link to the existing Devices page, leaving firmware and scale controls hidden behind the launcher navigation. Add a direct Devices row so connected-device metadata and settings are reachable from the expected entry point.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Device Management is now reachable from the regular Settings page as well as the dashboard. Record both entry points so the user-facing navigation documentation matches the new discoverable route.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Expose generic connected-scale metadata through /api/v1/scale/info while keeping device inventory limited to discovery and connection state. Remove metadata refresh subscriptions from the inventory WebSocket and align REST and WebSocket contracts and API documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep scale metadata on the connected-scale endpoint and update affected implementations and tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the router's parameterized GET form so the connected-scale metadata endpoint is reachable, and align inventory tests with the boundary.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep inventory payloads metadata-free and cover connected scale info responses.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Do not document battery metadata before the battery API change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Observed: PR742 review identified batteryLevel as obsolete ScaleInfo state and a DeviceManagement description that put connected metadata in device inventories.

Change: Remove batteryLevel from ScaleInfo serialization, document GET /api/v1/scale/info as the REST metadata boundary, and apply the Dart formatter output.

Constraint: Preserve opaque firmware handling and the existing ScaleInfo handler and Skale tests; no unrelated API behavior changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the aggregator inventory in its original (Device, StreamSubscription) shape now that each device has one connection-state listener. Apply the same cleanup across related PR copies so stale, replacement, and disposal paths cancel exactly one subscription.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@tadelv
tadelv force-pushed the feat/skale-firmware-revision-714 branch from 50be3aa to c59a737 Compare September 14, 2026 08:05
@tadelv
tadelv merged commit 2e94160 into decentespresso:main Sep 14, 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.

feat(scale): show the connected Skale firmware revision

2 participants