mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 19:01:39 -04:00
Fix SMART temperature always reporting null.
Real drives report attribute 194 raw values like "52 (Min/Max 16/57)" which int() cannot parse, so every drive's temperature was null. Prefer pySMART's `temperature` property, which parses these formats and also works for NVMe devices that have no ATA attribute table. Verified on real hardware (WD100EMAZ over USB-SAT): 51-53C now reported where null was returned before. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6088cbfe2a
commit
87ed286f7d
2 changed files with 46 additions and 1 deletions
|
|
@ -62,7 +62,16 @@ def _get_device_smart(device) -> dict:
|
|||
|
||||
|
||||
def _get_temperature(device) -> Optional[int]:
|
||||
"""Get drive temperature from SMART attributes."""
|
||||
"""Get drive temperature.
|
||||
|
||||
Prefer pySMART's `temperature` property: it parses real-world raw
|
||||
values like "52 (Min/Max 16/57)" that int() cannot, and works for
|
||||
NVMe devices which have no ATA attribute table. Fall back to the
|
||||
plain attributes for devices where the property is unavailable.
|
||||
"""
|
||||
temp = getattr(device, "temperature", None)
|
||||
if isinstance(temp, int):
|
||||
return temp
|
||||
temp = _get_attribute(device, "Temperature_Celsius")
|
||||
if temp is None:
|
||||
temp = _get_attribute(device, "Airflow_Temperature_Cel")
|
||||
|
|
|
|||
|
|
@ -119,11 +119,47 @@ class TestGetTemperature:
|
|||
def test_returns_none_if_not_found(self):
|
||||
"""Should return None if no temperature attribute."""
|
||||
mock_device = mock.Mock()
|
||||
mock_device.temperature = None
|
||||
mock_device.attributes = []
|
||||
|
||||
result = _get_temperature(mock_device)
|
||||
assert result is None
|
||||
|
||||
def test_prefers_pysmart_temperature_property(self):
|
||||
"""Real drives report raw values like '52 (Min/Max 16/57)' which
|
||||
int() cannot parse; pySMART's temperature property handles them."""
|
||||
mock_attr = mock.Mock()
|
||||
mock_attr.name = "Temperature_Celsius"
|
||||
mock_attr.raw = "52 (Min/Max 16/57)"
|
||||
|
||||
mock_device = mock.Mock()
|
||||
mock_device.temperature = 52
|
||||
mock_device.attributes = [mock_attr]
|
||||
|
||||
result = _get_temperature(mock_device)
|
||||
assert result == 52
|
||||
|
||||
def test_pysmart_temperature_property_for_nvme(self):
|
||||
"""NVMe devices have no ATA attribute table, only the property."""
|
||||
mock_device = mock.Mock()
|
||||
mock_device.temperature = 38
|
||||
mock_device.attributes = None
|
||||
|
||||
result = _get_temperature(mock_device)
|
||||
assert result == 38
|
||||
|
||||
def test_ignores_non_int_temperature_property(self):
|
||||
"""A missing/bogus temperature property falls back to attributes."""
|
||||
mock_attr = mock.Mock()
|
||||
mock_attr.name = "Temperature_Celsius"
|
||||
mock_attr.raw = "35"
|
||||
|
||||
mock_device = mock.Mock() # .temperature is a Mock, not an int
|
||||
mock_device.attributes = [mock_attr]
|
||||
|
||||
result = _get_temperature(mock_device)
|
||||
assert result == 35
|
||||
|
||||
|
||||
class TestGetAttribute:
|
||||
"""Tests for _get_attribute function."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue