Power Consumption, Voltage & Current Sensor Telemetry #19

Closed
opened 2026-09-08 10:29:26 +01:00 by gronod · 2 comments
Owner

Purpose

Provide granular power, voltage, and electrical current telemetry on Intel Macs, detailing overall system wattage, CPU package power (Intel RAPL equivalent), GPU power, and rail voltages.

Priority

Medium (Valuable for power draw optimization, thermal management, and power supply monitoring)

Dependencies

  • Depends on #2 (SMC Interface Engine (AppleSMC IOKit Client))

Scope

  • Monitor electrical telemetry via SMC keys:
    • Total system power in Watts (PSTR, PDTR)
    • CPU package power in Watts (PCPR, PCTR)
    • GPU power in Watts (PG0R, PGTR)
    • Memory subsystem power (PMSR)
    • DC-in / AC adapter power draw
    • CPU core voltage (VC0C) and current (IC0C)
  • Calculate instantaneous total power and energy trends.
  • Present live power gauges and wattage breakdowns in SwiftUI.

Implementation Suggestions

  • Query SMC power keys (P*), voltage keys (V*), and current keys (I*).
  • Handle SMC numeric formats: sp78 (signed fixed-point), fpe2, and standard 32-bit floats (flt).
  • Fallback to AppleSmartBattery instantaneous power metrics when running on battery power.
### Purpose Provide granular power, voltage, and electrical current telemetry on Intel Macs, detailing overall system wattage, CPU package power (Intel RAPL equivalent), GPU power, and rail voltages. ### Priority **Medium** (Valuable for power draw optimization, thermal management, and power supply monitoring) ### Dependencies - Depends on #2 (SMC Interface Engine (AppleSMC IOKit Client)) ### Scope - Monitor electrical telemetry via SMC keys: - Total system power in Watts (`PSTR`, `PDTR`) - CPU package power in Watts (`PCPR`, `PCTR`) - GPU power in Watts (`PG0R`, `PGTR`) - Memory subsystem power (`PMSR`) - DC-in / AC adapter power draw - CPU core voltage (`VC0C`) and current (`IC0C`) - Calculate instantaneous total power and energy trends. - Present live power gauges and wattage breakdowns in SwiftUI. ### Implementation Suggestions - Query SMC power keys (`P*`), voltage keys (`V*`), and current keys (`I*`). - Handle SMC numeric formats: `sp78` (signed fixed-point), `fpe2`, and standard 32-bit floats (`flt`). - Fallback to AppleSmartBattery instantaneous power metrics when running on battery power.
Author
Owner

Technical Implementation Plan & Code Solution

1. Intel Electrical Telemetry Architecture

Intel Macs report electrical domain metrics across voltage rails, current sense resistors, and power meters via AppleSMC:

  • System Total Power: PSTR or PDTR (Watts)
  • CPU Package Power: PCPR (Intel RAPL energy accumulator exposed via SMC)
  • GPU Power: PG0R
  • Memory Power: PMSR
  • CPU Voltage & Current: VC0C (Volts) and IC0C (Amperes)

2. Objective-C Provider (MMElectricalProvider.m)

#import "MMElectricalProvider.h"
#import "MMAppleSMCClient.h"

@implementation MMElectricalProvider

- (NSDictionary<NSString *, id> *)sampleTelemetryWithError:(NSError **)error {
    MMAppleSMCClient *smc = [MMAppleSMCClient sharedClient];

    NSNumber *sysPower = [self readPowerValue:smc key:@"PSTR"] ?: [self readPowerValue:smc key:@"PDTR"];
    NSNumber *cpuPower = [self readPowerValue:smc key:@"PCPR"] ?: [self readPowerValue:smc key:@"PCTR"];
    NSNumber *gpuPower = [self readPowerValue:smc key:@"PG0R"] ?: [self readPowerValue:smc key:@"PGTR"];
    NSNumber *memPower = [self readPowerValue:smc key:@"PMSR"];

    return @{
        @"systemPowerWatts": sysPower ?: @(0.0),
        @"cpuPowerWatts": cpuPower ?: @(0.0),
        @"gpuPowerWatts": gpuPower ?: @(0.0),
        @"memoryPowerWatts": memPower ?: @(0.0)
    };
}

- (nullable NSNumber *)readPowerValue:(MMAppleSMCClient *)smc key:(NSString *)key {
    SMCVal_t val;
    if (![smc readKey:key value:&val]) return nil;

    // sp78: signed 8.8
    if (val.dataSize == 2) {
        int16_t raw = (val.bytes[0] << 8) | val.bytes[1];
        return @((float)raw / 256.0f);
    }
    // flt: 32-bit float
    if (val.dataSize == 4) {
        float watts = 0;
        memcpy(&watts, val.bytes, 4);
        return @(watts);
    }
    return nil;
}
@end

3. Swift UI Integration

@Observable
public final class ElectricalSnapshot {
    public var systemPowerWatts: Double = 0.0
    public var cpuPowerWatts: Double = 0.0
    public var gpuPowerWatts: Double = 0.0
    public var memoryPowerWatts: Double = 0.0

    public func update(from dict: [String: Any]) {
        self.systemPowerWatts = dict["systemPowerWatts"] as? Double ?? 0.0
        self.cpuPowerWatts = dict["cpuPowerWatts"] as? Double ?? 0.0
        self.gpuPowerWatts = dict["gpuPowerWatts"] as? Double ?? 0.0
        self.memoryPowerWatts = dict["memoryPowerWatts"] as? Double ?? 0.0
    }
}

4. Intel RAPL Alignment

PCPR reflects the Intel Running Average Power Limit (RAPL) package power domain, matching measurements from Intel Power Gadget.

## Technical Implementation Plan & Code Solution ### 1. Intel Electrical Telemetry Architecture Intel Macs report electrical domain metrics across voltage rails, current sense resistors, and power meters via AppleSMC: - **System Total Power**: `PSTR` or `PDTR` (Watts) - **CPU Package Power**: `PCPR` (Intel RAPL energy accumulator exposed via SMC) - **GPU Power**: `PG0R` - **Memory Power**: `PMSR` - **CPU Voltage & Current**: `VC0C` (Volts) and `IC0C` (Amperes) --- ### 2. Objective-C Provider (`MMElectricalProvider.m`) ```objc #import "MMElectricalProvider.h" #import "MMAppleSMCClient.h" @implementation MMElectricalProvider - (NSDictionary<NSString *, id> *)sampleTelemetryWithError:(NSError **)error { MMAppleSMCClient *smc = [MMAppleSMCClient sharedClient]; NSNumber *sysPower = [self readPowerValue:smc key:@"PSTR"] ?: [self readPowerValue:smc key:@"PDTR"]; NSNumber *cpuPower = [self readPowerValue:smc key:@"PCPR"] ?: [self readPowerValue:smc key:@"PCTR"]; NSNumber *gpuPower = [self readPowerValue:smc key:@"PG0R"] ?: [self readPowerValue:smc key:@"PGTR"]; NSNumber *memPower = [self readPowerValue:smc key:@"PMSR"]; return @{ @"systemPowerWatts": sysPower ?: @(0.0), @"cpuPowerWatts": cpuPower ?: @(0.0), @"gpuPowerWatts": gpuPower ?: @(0.0), @"memoryPowerWatts": memPower ?: @(0.0) }; } - (nullable NSNumber *)readPowerValue:(MMAppleSMCClient *)smc key:(NSString *)key { SMCVal_t val; if (![smc readKey:key value:&val]) return nil; // sp78: signed 8.8 if (val.dataSize == 2) { int16_t raw = (val.bytes[0] << 8) | val.bytes[1]; return @((float)raw / 256.0f); } // flt: 32-bit float if (val.dataSize == 4) { float watts = 0; memcpy(&watts, val.bytes, 4); return @(watts); } return nil; } @end ``` --- ### 3. Swift UI Integration ```swift @Observable public final class ElectricalSnapshot { public var systemPowerWatts: Double = 0.0 public var cpuPowerWatts: Double = 0.0 public var gpuPowerWatts: Double = 0.0 public var memoryPowerWatts: Double = 0.0 public func update(from dict: [String: Any]) { self.systemPowerWatts = dict["systemPowerWatts"] as? Double ?? 0.0 self.cpuPowerWatts = dict["cpuPowerWatts"] as? Double ?? 0.0 self.gpuPowerWatts = dict["gpuPowerWatts"] as? Double ?? 0.0 self.memoryPowerWatts = dict["memoryPowerWatts"] as? Double ?? 0.0 } } ``` --- ### 4. Intel RAPL Alignment `PCPR` reflects the Intel Running Average Power Limit (RAPL) package power domain, matching measurements from Intel Power Gadget.
gronod added this to the M2: Primary System & Thermal Telemetry milestone 2026-09-08 10:42:14 +01:00
gronod added a new dependency 2026-09-08 11:35:06 +01:00
Author
Owner

Completed in feat/19-power-voltage and merged into develop.

  • Implemented MMPowerTelemetryProvider querying SMC power keys (PSTR, PDTR, PCPR, PG0R, PMSR), voltage keys (VC0C, VD0R), and current keys (IC0C, ID0R).
  • Extended MMSMCParser to support generalized spXY and fpXY fixed point representations and ioft floats.
  • Integrated AppleSmartBattery IOKit fallback for instantaneous battery wattage calculation when on battery power.
  • Unit tested with 100% pass in MMPowerTests.swift.
Completed in `feat/19-power-voltage` and merged into `develop`. - Implemented `MMPowerTelemetryProvider` querying SMC power keys (`PSTR`, `PDTR`, `PCPR`, `PG0R`, `PMSR`), voltage keys (`VC0C`, `VD0R`), and current keys (`IC0C`, `ID0R`). - Extended `MMSMCParser` to support generalized `spXY` and `fpXY` fixed point representations and `ioft` floats. - Integrated AppleSmartBattery IOKit fallback for instantaneous battery wattage calculation when on battery power. - Unit tested with 100% pass in `MMPowerTests.swift`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: gronod/MacMonitor#19