show HDD warnings based on sectors

This commit is contained in:
2026-04-28 21:20:30 +02:00
parent 157e769268
commit 831a892041
7 changed files with 191 additions and 9 deletions
+128 -1
View File
@@ -23,6 +23,9 @@ void SMART::readSMARTData(Drive *drive)
uint32_t powerOnHours = 0U;
uint32_t powerCycles = 0U;
uint32_t temperature = 0U;
uint32_t reallocatedSectors = 0U;
uint32_t pendingSectors = 0U;
uint32_t uncorrectableSectors = 0U;
modelFamily.clear();
modelName.clear();
@@ -57,6 +60,9 @@ void SMART::readSMARTData(Drive *drive)
SMART::parsePowerOnHours(sLine, powerOnHours);
SMART::parsePowerCycles(sLine, powerCycles);
SMART::parseTemperature(sLine, temperature);
SMART::parseReallocatedSectors(sLine, reallocatedSectors);
SMART::parsePendingSectors(sLine, pendingSectors);
SMART::parseUncorrectableSectors(sLine, uncorrectableSectors);
}
free(cLine);
@@ -70,7 +76,7 @@ void SMART::readSMARTData(Drive *drive)
}
}
drive->setDriveSMARTData(modelFamily, modelName, serial, capacity, errorCount, powerOnHours, powerCycles, temperature); // write data in drive
drive->setDriveSMARTData(modelFamily, modelName, serial, capacity, errorCount, powerOnHours, powerCycles, temperature, reallocatedSectors, pendingSectors, uncorrectableSectors); // write data in drive
}
/**
@@ -309,3 +315,124 @@ bool SMART::parseTemperature(string sLine, uint32_t &temperature)
return false;
}
}
/**
* \brief parse Reallocated Sectors Count (SMART ID 0x05)
* \param string output line of smartctl
* \param uint32_t parsed reallocated sectors count
* \return bool if parsing was possible
*/
bool SMART::parseReallocatedSectors(string sLine, uint32_t &reallocatedSectors)
{
string search("\"id\": 5,");
size_t found = sLine.find(search);
if (found != string::npos)
{
// Found attribute ID 5 (Reallocated_Sector_Ct)
// Now we need to find the raw value in the next lines
// smartctl JSON format: "raw": { "value": <number>, ... }
return true; // Mark that we found the attribute
}
// Look for the raw value if we're in the right attribute
search = "\"value\":";
found = sLine.find(search);
if (found != string::npos && sLine.find("\"raw\":") != string::npos)
{
// Extract value after "value":
sLine.erase(0U, sLine.find("\"value\":") + 8U);
// Remove trailing characters
size_t comma = sLine.find(",");
if (comma != string::npos)
{
sLine = sLine.substr(0, comma);
}
// Remove whitespace
sLine.erase(remove(sLine.begin(), sLine.end(), ' '), sLine.end());
if (!sLine.empty() && sLine.find_first_not_of("0123456789") == string::npos)
{
reallocatedSectors = stoul(sLine);
return true;
}
}
return false;
}
/**
* \brief parse Current Pending Sector Count (SMART ID 0xC5)
* \param string output line of smartctl
* \param uint32_t parsed pending sectors count
* \return bool if parsing was possible
*/
bool SMART::parsePendingSectors(string sLine, uint32_t &pendingSectors)
{
string search("\"id\": 197,"); // 0xC5 = 197 decimal
size_t found = sLine.find(search);
if (found != string::npos)
{
return true; // Mark that we found the attribute
}
// Look for the raw value
search = "\"value\":";
found = sLine.find(search);
if (found != string::npos && sLine.find("\"raw\":") != string::npos)
{
sLine.erase(0U, sLine.find("\"value\":") + 8U);
size_t comma = sLine.find(",");
if (comma != string::npos)
{
sLine = sLine.substr(0, comma);
}
sLine.erase(remove(sLine.begin(), sLine.end(), ' '), sLine.end());
if (!sLine.empty() && sLine.find_first_not_of("0123456789") == string::npos)
{
pendingSectors = stoul(sLine);
return true;
}
}
return false;
}
/**
* \brief parse Offline Uncorrectable Sectors (SMART ID 0xC6)
* \param string output line of smartctl
* \param uint32_t parsed uncorrectable sectors count
* \return bool if parsing was possible
*/
bool SMART::parseUncorrectableSectors(string sLine, uint32_t &uncorrectableSectors)
{
string search("\"id\": 198,"); // 0xC6 = 198 decimal
size_t found = sLine.find(search);
if (found != string::npos)
{
return true; // Mark that we found the attribute
}
// Look for the raw value
search = "\"value\":";
found = sLine.find(search);
if (found != string::npos && sLine.find("\"raw\":") != string::npos)
{
sLine.erase(0U, sLine.find("\"value\":") + 8U);
size_t comma = sLine.find(",");
if (comma != string::npos)
{
sLine = sLine.substr(0, comma);
}
sLine.erase(remove(sLine.begin(), sLine.end(), ' '), sLine.end());
if (!sLine.empty() && sLine.find_first_not_of("0123456789") == string::npos)
{
uncorrectableSectors = stoul(sLine);
return true;
}
}
return false;
}