Skip to content

Add outgoing power visualization to Sankey diagram - #20

Open
DinanathDash wants to merge 3 commits into
srimanachanta:mainfrom
DinanathDash:feat/display-outgoing-power
Open

Add outgoing power visualization to Sankey diagram#20
DinanathDash wants to merge 3 commits into
srimanachanta:mainfrom
DinanathDash:feat/display-outgoing-power

Conversation

@DinanathDash

Copy link
Copy Markdown
Contributor

This pull request adds support for visualizing output power and output ports in the app's power metrics and UI. It introduces new data structures and UI logic to track, compute, and display the power delivered to output ports, including per-port details and visualization controls. The changes affect models, services, view models, and UI components to provide a comprehensive and configurable representation of output power.

Key changes:

1. Output Power and Ports Tracking

  • Added a new OutputPortPower struct and associated fields to BatteryMetrics to represent and store per-port output power data. [1] [2]
  • Updated IOKitService to fetch, compute, and emit output power and per-port details using new helper methods (getOutputPortPowers, getSystemInputPowerWatts, etc.), and to include these in the emitted metrics. [1] [2]

2. Output Power Visualization and UI

  • Enhanced MenuViewModel to process, stabilize, and expose output port power data and formatted text for UI display. [1] [2]
  • Updated PowerSankeyView and related UI logic to visualize output power and per-port flows, including support for multiple output ports and dynamic Sankey diagram layouts. [1] [2] [3] [4]

3. User Preferences and Localization

  • Added new user settings for output visualization mode (OutputVisualizationMode enum) and for toggling the display of output ports text, with corresponding keys in DefaultsKeys.swift. [1] [2]
  • Added new localizable string entries for output visualization options and UI labels. [1] [2] [3] [4] [5]

4. UI Control Logic

  • Updated MenuBuilder and related UI components to conditionally show output ports information and visualization based on user preferences and current power source. [1] [2]

5. Adapter Metrics Improvements

  • Improved adapter metrics tracking by adding adapterCapacityWatts and refining logic for determining adapter connection status. [1] [2]

These changes collectively provide more detailed and configurable output power insights for users, both in the underlying data and in the app's UI.

Screenshot 2026-05-13 at 5 21 08 PM

Closes #11

@DinanathDash

Copy link
Copy Markdown
Contributor Author

"Hey! @srimanachanta Just a quick heads-up: I've submitted 6 modular PRs (PRs #17 through #22) to break down a larger set of features and make the review process much easier for you.

Because a few of these PRs touch the same core files (like MenuViewModel.swift and BatteryIndicatorView.swift), merging one might cause merge conflicts in the others. Please review and merge them in whatever order makes the most sense to you!

Once you merge a PR, if GitHub flags any of my remaining open PRs with conflicts, just let me know or leave them be—I will actively monitor the repo and locally rebase my remaining branches against your updated main to resolve the conflicts for you. You won't have to resolve the conflicts yourself!
For the easiest path with the least overlap, my suggested review/merge order is:

  1. Fix Homebrew install command by removing --no-quarantine flag #21 (Fix Homebrew install) - Standalone.
  2. Add app icons for multiple sizes and update Contents.json #19 (App icons) - Standalone.
  3. Refactor time remaining calculation and integrate estimator #18 (Refactor time remaining)
  4. Add battery percentage display option in menu bar icon #17 (Battery percentage in menu bar)
  5. feat: reflect Low Power Mode in the menu bar battery icon #22 (Low Power Mode icon) - builds slightly on the view from Add battery percentage display option in menu bar icon #17.
  6. Add outgoing power visualization to Sankey diagram #20 (Outgoing power Sankey diagram) - heaviest changes.

Thanks for maintaining Stasis! Let me know if you need any adjustments.

@srimanachanta

Copy link
Copy Markdown
Owner

ioreg -w 0 -r -c AppleSmartBattery | grep "PowerTelemetryData" returns nothing on macOS 15.7.5, this may be a macOS 26-only registry. Can you verify that?

@DinanathDash

Copy link
Copy Markdown
Contributor Author

ioreg -w 0 -r -c AppleSmartBattery | grep "PowerTelemetryData" returns nothing on macOS 15.7.5, this may be a macOS 26-only registry. Can you verify that?

Yeah its available on MacOS 26, the current version installed on my device is 26.5.

dinanath@Dinanaths-MacBook-Air Stasis % ioreg -w 0 -r -c AppleSmartBattery | grep "PowerTelemetryData"
      "PowerTelemetryData" = {
        "AccumulatedWallEnergyEstimate" = 224764618,
        "SystemEnergyConsumed" = 1648,
        "SystemPowerInAccumulatorCount" = 99773,
        "AdapterEfficiencyLoss" = 18446744073709551561,
        "SystemLoad" = 5933,
        "AccumulatedSystemLoad" = 781532860,
        "AccumulatedSystemEnergyConsumed" = 486985061425,
        "SystemCurrentIn" = 294,
        "WallEnergyEstimate" = 1593,
        "SystemLoadAccumulatorCount" = 320468,
        "AdapterEfficiencyLossAccumulatorCount" = 98439,
        "SystemVoltageIn" = 20180,
        "SystemPowerIn" = 5933,
        "AccumulatedBatteryPower" = 90369720,
        "PowerTelemetryErrorCount" = 0,
        "AccumulatedAdapterEfficiencyLoss" = 215985318490873,
        "BatteryPowerAccumulatorCount" = 4686,
        "AccumulatedSystemPowerIn" = 1753146347945,
        "BatteryPower" = 0,
        "AccumulatedBatteryDischarge" = 18446744073637340213,
        "BatteryDischargeAccumulatorCount" = 12559
      }
dinanath@Dinanaths-MacBook-Air Stasis %

@srimanachanta

Copy link
Copy Markdown
Owner

Given this value is from IORegistry, it will only update on percent changes or adapter changes which wouldn't achieve the desired effect. The better solution would be to use the SMC data we already get which is synchronous, real time data insted. Additionally, given this registry entry is only available on ~macOS 26+, it would require weird branching to use different APIs.

@DinanathDash

Copy link
Copy Markdown
Contributor Author

Given this value is from IORegistry, it will only update on percent changes or adapter changes which wouldn't achieve the desired effect. The better solution would be to use the SMC data we already get which is synchronous, real time data insted. Additionally, given this registry entry is only available on ~macOS 26+, it would require weird branching to use different APIs.

So how do you propose the solution? Can you help with it so I can try implementing that?

@srimanachanta

Copy link
Copy Markdown
Owner

Given this value is from IORegistry, it will only update on percent changes or adapter changes which wouldn't achieve the desired effect. The better solution would be to use the SMC data we already get which is synchronous, real time data insted. Additionally, given this registry entry is only available on ~macOS 26+, it would require weird branching to use different APIs.

So how do you propose the solution? Can you help with it so I can try implementing that?

Both "PowerOutDetails" and "PowerTelemetryData" don't exist on macOS 15.7 . You need to determine which SMC keys they are using and I'll see if they exist on macOS 15.7 . If they don't exist, we may want to guard this feature for macOS 26 only.

…eat/display-outgoing-power

# Conflicts:
#	Stasis/DefaultsKeys.swift
#	Stasis/L10n/Localizable.xcstrings
#	Stasis/ViewModels/MenuViewModel.swift
@DinanathDash

Copy link
Copy Markdown
Contributor Author

@srimanachanta I pushed a follow-up update addressing PR #20 feedback.

What was updated:

  1. Resolved merge conflicts with latest main in:
  • Stasis/DefaultsKeys.swift
  • Stasis/L10n/Localizable.xcstrings
  • Stasis/ViewModels/MenuViewModel.swift
  1. Removed unconditional dependence on IORegistry-only output telemetry.
  • PowerTelemetryData / PowerOutDetails handling is now guarded in IOKitService.
  • When unavailable (including OS versions where those entries do not exist), output telemetry is disabled cleanly.
  1. Added explicit SMC candidate-key availability probing for cross-version verification.
  • New SMCPowerTelemetry probe for candidate keys: PDTR, PSTR, PMVR, AC-W.
  • Exposed via helper XPC and logged from BatteryService at runtime.
  1. Fixed follow-up UI regressions:
  • Output ports text row toggle now updates menu rendering immediately (menu rebuild now observes showOutputPortsText and outputVisualizationMode).
  • Sankey right-side node/split alignment corrected for charging/battery layouts across 1/2/3 output-device cases.

Result:

  • Conflict-free branch
  • No hard dependency on macOS 26-only IORegistry entries
  • Runtime evidence path for SMC key availability
  • Output/menu behavior corrected

If useful, I can post sample runtime logs from both a macOS 26 machine and a macOS 15.7 machine for direct comparison.

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.

[FR] display devices charged by Mac

2 participants