Skip to content

fix(sensors/darwin): parse sp78 temperatures instead of returning 0.0#2084

Open
drutsan wants to merge 1 commit into
shirou:masterfrom
drutsan:fix/darwin-temperature-sp78
Open

fix(sensors/darwin): parse sp78 temperatures instead of returning 0.0#2084
drutsan wants to merge 1 commit into
shirou:masterfrom
drutsan:fix/darwin-temperature-sp78

Conversation

@drutsan
Copy link
Copy Markdown

@drutsan drutsan commented Apr 30, 2026

Summary

sensors.TemperaturesWithContext() returns 0.0°C for every sensor on Intel Macs because getTemperature() in sensors_darwin.go explicitly returns 0.0 when it detects the sp78 data type — but sp78 is exactly the format Apple's SMC uses for temperature readings.

Bug

sensors/sensors_darwin.go:108-110:

if result.dataSize == 2 && result.dataType == toUint32(dataTypeSp78) {
    return 0.0
}

This branch is supposed to parse the sp78 reading, not discard it. Looks like an unfinished placeholder.

Fix

Parse the two-byte sp78 response according to spec — high byte = signed integer degrees, low byte = fractional part in 1/256 increments:

if result.dataSize == 2 && result.dataType == toUint32(dataTypeSp78) {
    return float64(int8(result.data[0])) + float64(result.data[1])/256.0
}

Verification

Tested on Mac mini 2018 (Intel Core i5-8500B, T2 chip) running macOS 15.7.5 (Sequoia):

Before:

TC0P: 0.0°C  TM0P: 0.0°C  TW0P: 0.0°C  ... (all 21 keys returned 0.0)

After:

TC0P: 60.3°C  (CPU 0 Proximity)
TM0P: 57.6°C  (Memory Slots Proximity)
TW0P: 49.6°C  (Wireless Module)

Cross-checked against osx-cpu-temp which reports 59.7°C for the same hardware/load — values match.

Other keys (TC0D, TC0H, TG0D, etc.) still legitimately return 0.0 — those sensors aren't physically present on T2-chip Mac mini hardware. The IOKit + SMC stack is fine; only the parsing was broken.

Affected platforms

darwin && !arm64 (Intel Macs). Apple Silicon Macs use a different code path (sensors_darwin_arm64.go) and are not affected.

Test plan

  • Build & run on Intel Mac mini 2018 (macOS 15.7.5)
  • Verify temperatures match osx-cpu-temp output
  • Verify other key types (single-byte readings) still work
  • CI to verify cross-compile still succeeds

The Intel macOS SMC returns temperature readings in sp78 format (signed
7.8 fixed-point: high byte = signed integer degrees, low byte = fractional
part in 1/256 increments). The previous code detected this format
correctly but then unconditionally returned 0.0 for it.

This caused all `TemperaturesWithContext` results on Intel Macs to report
0.0°C for every sensor — even though `NewSMC()` succeeded, the IOKit
connection was open, and the keys were being read successfully.

This patch parses the two-byte response according to the sp78 spec.

Verified on Mac mini 2018 (Intel Core i5-8500B, T2 chip) running macOS
15.7.5 (Sequoia):

  Before:
    TC0P: 0.0°C
    TM0P: 0.0°C
    TW0P: 0.0°C
    (all 21 keys returned 0.0)

  After:
    TC0P: 60.3°C  (CPU 0 Proximity)
    TM0P: 57.6°C  (Memory Slots Proximity)
    TW0P: 49.6°C  (Wireless Module)
    (other keys correctly return 0 on this hardware — they are not present
    on the T2 platform; values match `osx-cpu-temp` output of 59.7°C)

Affected platforms: all `darwin && !arm64` builds (Intel Macs).

Note that Apple Silicon Macs use a different sensor backend
(sensors_darwin_arm64.go) and are not affected by this bug.
@drutsan drutsan force-pushed the fix/darwin-temperature-sp78 branch from 13e4809 to 28add59 Compare April 30, 2026 13:58
Copy link
Copy Markdown
Owner

@shirou shirou left a comment

Choose a reason for hiding this comment

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

LGTM. The sp78 decoding is correct — equivalent to interpreting the two bytes as a signed 16-bit big-endian value and dividing by 256, which matches the canonical reading used by the Linux applesmc driver and other established SMC implementations. I have not checked on a real macOS, but verified the formula handles both positive and negative readings (e.g. 0xFE 0x80 → -1.5°C).

Two minor (non-blocking) suggestions:

  • The 5-line comment is heavier than the surrounding style; the historical "Previously this branch incorrectly returned 0.0" sentence will rot — git blame already records that. Trimming to a one-liner referencing the format would be enough.
  • Extracting the parser into a tiny pure helper (parseSp78(hi, lo uint8) float64) would make it unit-testable on any platform

Would be great to see both addressed in this PR before merge.

Reference implementations consulted:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants