From 90055bec81b35240576308f8f69f772f573a1825 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Thu, 5 Feb 2026 11:24:54 -0500 Subject: [PATCH] Fix temperature parsing to handle multiple SMART formats Temperature parsing now correctly handles: - SATA Temperature_Celsius attribute (extracts last numeric value) - Simple "Temperature: XX Celsius" format - "Current Temperature: XX Celsius" format - NVMe temperature reporting Also improved device type detection for NVMe, SSD (including 0 RPM), and fixed serial number parsing to capture full serial with spaces. Fixes: https://code.lotusguild.org/LotusGuild/driveAtlas/issues/2 Co-Authored-By: Claude Opus 4.5 --- driveAtlas.sh | 84 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 8 deletions(-) diff --git a/driveAtlas.sh b/driveAtlas.sh index 1742343..f46c452 100644 --- a/driveAtlas.sh +++ b/driveAtlas.sh @@ -272,16 +272,84 @@ build_drive_map() { fi } +#------------------------------------------------------------------------------ +# get_drive_smart_info +# +# Retrieves SMART data for a given device. +# +# Args: +# $1 - Device name (e.g., sda, nvme0n1) +# +# Returns: Pipe-delimited string: TYPE|TEMP|HEALTH|MODEL|SERIAL +# TYPE: SSD, HDD, or NVMe +# TEMP: Temperature in Celsius (or "-" if unavailable) +# HEALTH: ✓ for passed, ✗ for failed +# MODEL: Drive model string +# SERIAL: Drive serial number +#------------------------------------------------------------------------------ get_drive_smart_info() { - local device=$1 - local smart_info=$(sudo smartctl -A -i -H /dev/$device 2>/dev/null) - local temp=$(echo "$smart_info" | grep "Temperature" | awk '{print $10}' | head -1) - local type=$(echo "$smart_info" | grep "Rotation Rate" | grep -q "Solid State" && echo "SSD" || echo "HDD") - local health=$(echo "$smart_info" | grep "SMART overall-health" | grep -q "PASSED" && echo "✓" || echo "✗") - local model=$(echo "$smart_info" | grep "Device Model\|Model Number" | cut -d: -f2 | xargs) - local serial=$(echo "$smart_info" | grep "Serial Number" | awk '{print $3}') + local device="$1" + local smart_info + local temp="-" + local type="HDD" + local health="✗" + local model="-" + local serial="-" - echo "$type|$temp°C|$health|$model|$serial" + smart_info="$(sudo smartctl -A -i -H "/dev/$device" 2>/dev/null)" + + # Temperature parsing - handles multiple formats: + # - SATA: "194 Temperature_Celsius ... 35" (value at end of line) + # - SATA: "Temperature: 42 Celsius" + # - SATA: "Current Temperature: 35 Celsius" + # - NVMe: "Temperature: 42 Celsius" + if echo "$smart_info" | grep -q "Temperature_Celsius"; then + # SMART attribute format - temperature is typically the 10th field (raw value) + # But we use the last numeric field before any parentheses for reliability + temp="$(echo "$smart_info" | grep "Temperature_Celsius" | head -1 | awk '{for(i=NF;i>0;i--) if($i ~ /^[0-9]+$/) {print $i; exit}}')" + elif echo "$smart_info" | grep -qE "^(Current )?Temperature:"; then + # Simple "Temperature: XX Celsius" format + temp="$(echo "$smart_info" | grep -E "^(Current )?Temperature:" | head -1 | awk '{print $2}')" + fi + + # Device type detection - handles SSD, HDD, and NVMe + if [[ "$device" == nvme* ]]; then + type="NVMe" + elif echo "$smart_info" | grep -q "Rotation Rate"; then + if echo "$smart_info" | grep "Rotation Rate" | grep -qiE "solid state|0 rpm"; then + type="SSD" + else + type="HDD" + fi + elif echo "$smart_info" | grep -qiE "SSD|Solid State"; then + type="SSD" + fi + + # Health status + if echo "$smart_info" | grep -q "SMART overall-health.*PASSED"; then + health="✓" + elif echo "$smart_info" | grep -q "SMART Health Status.*OK"; then + # NVMe format + health="✓" + fi + + # Model - try multiple field names + model="$(echo "$smart_info" | grep -E "^(Device Model|Model Number|Product):" | head -1 | cut -d: -f2 | xargs)" + [[ -z "$model" ]] && model="-" + + # Serial number - capture everything after the colon to handle spaces + serial="$(echo "$smart_info" | grep -E "^Serial [Nn]umber:" | head -1 | cut -d: -f2 | xargs)" + [[ -z "$serial" ]] && serial="-" + + # Format temperature with unit if we have a value + local temp_display + if [[ -n "$temp" && "$temp" != "-" ]]; then + temp_display="${temp}°C" + else + temp_display="-" + fi + + echo "${type}|${temp_display}|${health}|${model}|${serial}" } #------------------------------------------------------------------------------