diff --git a/README.md b/README.md index 7247333..2a6d5e5 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,8 @@ Usage: ./smctemp [options] -c : list CPU temperatures (Celsius) -g : list GPU temperatures (Celsius) + -C : list individual CPU core temperatures (Celsius) + -G : list individual GPU core temperatures (Celsius) -h : help -i : set interval in milliseconds (e.g. -i25, valid range is 20-1000, default: 1000) -l : list all keys and values @@ -40,6 +42,14 @@ $ smctemp -c $ smctemp -g 36.2 + +$ smctemp -C +P-Core 1: 62.4°C +P-Core 2: 63.8°C +P-Core 3: 65.2°C +P-Core 4: 64.8°C +E-Core 1: 58.6°C +E-Core 2: 59.1°C ``` ## Note for M2 Mac Users diff --git a/main.cc b/main.cc index db789b9..1f87603 100644 --- a/main.cc +++ b/main.cc @@ -10,6 +10,8 @@ void usage(char* prog) { std::cout << prog << " [options]" << std::endl; std::cout << " -c : list CPU temperatures (Celsius)" << std::endl; std::cout << " -g : list GPU temperatures (Celsius)" << std::endl; + std::cout << " -C : list individual CPU core temperatures (Celsius)" << std::endl; + std::cout << " -G : list individual GPU core temperatures (Celsius)" << std::endl; std::cout << " -h : help" << std::endl; std::cout << " -i : set interval in milliseconds (e.g. -i25, valid range is 20-1000, default: 1000)" << std::endl; @@ -29,7 +31,7 @@ int main(int argc, char *argv[]) { int op = smctemp::kOpNone; bool isFailSoft = false; - while ((c = getopt(argc, argv, "clvfhn:gi:")) != -1) { + while ((c = getopt(argc, argv, "clvfhn:gi:CG")) != -1) { switch(c) { case 'c': op = smctemp::kOpReadCpuTemp; @@ -37,6 +39,12 @@ int main(int argc, char *argv[]) { case 'g': op = smctemp::kOpReadGpuTemp; break; + case 'C': + op = smctemp::kOpReadIndividualCpuTemp; + break; + case 'G': + op = smctemp::kOpReadIndividualGpuTemp; + break; case 'i': if (optarg) { unsigned int temp_interval; @@ -81,6 +89,9 @@ int main(int argc, char *argv[]) { smctemp::SmcAccessor smc_accessor = smctemp::SmcAccessor(); smctemp::SmcTemp smc_temp = smctemp::SmcTemp(isFailSoft); + // Common variables for temperature measurements + double temp = 0.0; + const std::pair valid_temperature_limits{10, 120}; switch(op) { case smctemp::kOpList: @@ -94,39 +105,88 @@ int main(int argc, char *argv[]) { break; case smctemp::kOpReadGpuTemp: case smctemp::kOpReadCpuTemp: - double temp = 0.0; - const std::pair valid_temperature_limits{10, 120}; - while (attempts > 0) { - if (op == smctemp::kOpReadCpuTemp) { - temp = smc_temp.GetCpuTemp(); - } else if (op == smctemp::kOpReadGpuTemp) { - temp = smc_temp.GetGpuTemp(); + { + while (attempts > 0) { + if (op == smctemp::kOpReadCpuTemp) { + temp = smc_temp.GetCpuTemp(); + } else if (op == smctemp::kOpReadGpuTemp) { + temp = smc_temp.GetGpuTemp(); + } + if (smc_temp.IsValidTemperature(temp, valid_temperature_limits)) { + break; + } else { + usleep(interval_ms * 1'000); + attempts--; + } + } + if (isFailSoft) { + if (!smc_temp.IsValidTemperature(temp, valid_temperature_limits)) { + if (op == smctemp::kOpReadCpuTemp) { + temp = smc_temp.GetLastValidCpuTemp(); + } else if (op == smctemp::kOpReadGpuTemp) { + temp = smc_temp.GetLastValidGpuTemp(); + } + } } - if (smc_temp.IsValidTemperature(temp, valid_temperature_limits)) { - break; - } else { - usleep(interval_ms * 1'000); - attempts--; + std::cout << std::fixed << std::setprecision(1) << temp << std::endl; + if (temp == 0.0) { + std::cerr << "Could not get valid sensor value. Please use `-n` option and `-i` option." << std::endl; + std::cerr << "In M2 Mac, it would be work fine with `-i25 -n180 -f` options.`" << std::endl; + return 1; } } - if (isFailSoft) { - if (!smc_temp.IsValidTemperature(temp, valid_temperature_limits)) { - if (op == smctemp::kOpReadCpuTemp) { - temp = smc_temp.GetLastValidCpuTemp(); - } else if (op == smctemp::kOpReadGpuTemp) { - temp = smc_temp.GetLastValidGpuTemp(); + break; + case smctemp::kOpReadIndividualCpuTemp: + { + std::vector> temps; + unsigned int attempts_left = attempts; + while (attempts_left > 0) { + temps = smc_temp.GetIndividualCpuTemps(); + if (!temps.empty()) { + break; + } else { + usleep(interval_ms * 1'000); + attempts_left--; } } + + if (temps.empty()) { + std::cerr << "Could not get valid CPU core temperatures. Please use `-n` option and `-i` option." << std::endl; + std::cerr << "In M2 Mac, it would be work fine with `-i25 -n180 -f` options.`" << std::endl; + return 1; + } + + for (const auto& temp_pair : temps) { + std::cout << temp_pair.first << ": " << std::fixed << std::setprecision(1) << temp_pair.second << "°C" << std::endl; + } } - std::cout << std::fixed << std::setprecision(1) << temp << std::endl; - if (temp == 0.0) { - std::cerr << "Could not get valid sensor value. Please use `-n` option and `-i` option." << std::endl; - std::cerr << "In M2 Mac, it would be work fine with `-i25 -n180 -f` options.`" << std::endl; - return 1; + break; + case smctemp::kOpReadIndividualGpuTemp: + { + std::vector> temps; + unsigned int attempts_left = attempts; + while (attempts_left > 0) { + temps = smc_temp.GetIndividualGpuTemps(); + if (!temps.empty()) { + break; + } else { + usleep(interval_ms * 1'000); + attempts_left--; + } + } + + if (temps.empty()) { + std::cerr << "Could not get valid GPU core temperatures. Please use `-n` option and `-i` option." << std::endl; + std::cerr << "In M2 Mac, it would be work fine with `-i25 -n180 -f` options.`" << std::endl; + return 1; + } + + for (const auto& temp_pair : temps) { + std::cout << temp_pair.first << ": " << std::fixed << std::setprecision(1) << temp_pair.second << "°C" << std::endl; + } } break; } return 0; } - diff --git a/smctemp.cc b/smctemp.cc index dbb2e8e..b1aa97c 100644 --- a/smctemp.cc +++ b/smctemp.cc @@ -433,7 +433,109 @@ double SmcTemp::CalculateAverageTemperature(const std::vector& sens return temp; } -double SmcTemp::GetCpuTemp() { +// Get labeled CPU core sensors for the current CPU model +std::vector> SmcTemp::GetCpuCoreSensors() { + std::vector> labeled_sensors; + std::vector> aux_labeled_sensors; + + const std::string cpumodel = getCPUModel(); + if (cpumodel.find("m4") != std::string::npos) { // Apple M4 + labeled_sensors.emplace_back(std::string("CPU Sensor Tp01"), std::string(kSensorTp01)); + labeled_sensors.emplace_back(std::string("CPU Sensor Tp09"), std::string(kSensorTp09)); + labeled_sensors.emplace_back(std::string("CPU Sensor Tp0f"), std::string(kSensorTp0f)); + labeled_sensors.emplace_back(std::string("CPU Sensor Tp05"), std::string(kSensorTp05)); + labeled_sensors.emplace_back(std::string("CPU Sensor Tp0D"), std::string(kSensorTp0D)); + } else if (cpumodel.find("m3") != std::string::npos) { // Apple M3 + labeled_sensors.emplace_back(std::string("CPU Core 1"), std::string(kSensorTp01)); + labeled_sensors.emplace_back(std::string("CPU Core 2"), std::string(kSensorTp09)); + labeled_sensors.emplace_back(std::string("CPU Core 3"), std::string(kSensorTp0f)); + labeled_sensors.emplace_back(std::string("CPU Core 4"), std::string(kSensorTp0n)); + labeled_sensors.emplace_back(std::string("CPU Core 5"), std::string(kSensorTp05)); + labeled_sensors.emplace_back(std::string("CPU Core 6"), std::string(kSensorTp0D)); + labeled_sensors.emplace_back(std::string("CPU Core 7"), std::string(kSensorTp0j)); + labeled_sensors.emplace_back(std::string("CPU Core 8"), std::string(kSensorTp0r)); + } else if (cpumodel.find("m2") != std::string::npos) { // Apple M2 + // Efficiency cores (1 through 4 on M2 Max 12 Core Chip) + labeled_sensors.emplace_back(std::string("E-Core 1"), std::string(kSensorTp1h)); + labeled_sensors.emplace_back(std::string("E-Core 2"), std::string(kSensorTp1t)); + labeled_sensors.emplace_back(std::string("E-Core 3"), std::string(kSensorTp1p)); + labeled_sensors.emplace_back(std::string("E-Core 4"), std::string(kSensorTp1l)); + + // Performance cores + labeled_sensors.emplace_back(std::string("P-Core 1"), std::string(kSensorTp01)); + labeled_sensors.emplace_back(std::string("P-Core 2"), std::string(kSensorTp09)); + labeled_sensors.emplace_back(std::string("P-Core 3"), std::string(kSensorTp0f)); + labeled_sensors.emplace_back(std::string("P-Core 4"), std::string(kSensorTp0n)); + labeled_sensors.emplace_back(std::string("P-Core 5"), std::string(kSensorTp05)); + labeled_sensors.emplace_back(std::string("P-Core 6"), std::string(kSensorTp0D)); + labeled_sensors.emplace_back(std::string("P-Core 7"), std::string(kSensorTp0j)); + labeled_sensors.emplace_back(std::string("P-Core 8"), std::string(kSensorTp0r)); + } else if (cpumodel.find("m1") != std::string::npos) { // Apple M1 + // Efficiency cores + labeled_sensors.emplace_back(std::string("E-Core 1"), std::string(kSensorTp09)); + labeled_sensors.emplace_back(std::string("E-Core 2"), std::string(kSensorTp0T)); + + // Performance cores + labeled_sensors.emplace_back(std::string("P-Core 1"), std::string(kSensorTp01)); + labeled_sensors.emplace_back(std::string("P-Core 2"), std::string(kSensorTp05)); + labeled_sensors.emplace_back(std::string("P-Core 3"), std::string(kSensorTp0D)); + labeled_sensors.emplace_back(std::string("P-Core 4"), std::string(kSensorTp0H)); + labeled_sensors.emplace_back(std::string("P-Core 5"), std::string(kSensorTp0L)); + labeled_sensors.emplace_back(std::string("P-Core 6"), std::string(kSensorTp0P)); + labeled_sensors.emplace_back(std::string("P-Core 7"), std::string(kSensorTp0X)); + labeled_sensors.emplace_back(std::string("P-Core 8"), std::string(kSensorTp0b)); + + // Only use these if we don't get valid readings from the more specific sensors + aux_labeled_sensors.emplace_back(std::string("CPU Aux 1"), std::string(kSensorTc0a)); + aux_labeled_sensors.emplace_back(std::string("CPU Aux 2"), std::string(kSensorTc0b)); + aux_labeled_sensors.emplace_back(std::string("CPU Aux 3"), std::string(kSensorTc0x)); + aux_labeled_sensors.emplace_back(std::string("CPU Aux 4"), std::string(kSensorTc0z)); + } + + // If we didn't get any sensors, try the aux sensors + if (labeled_sensors.empty() && !aux_labeled_sensors.empty()) { + return aux_labeled_sensors; + } + + return labeled_sensors; +} + +// Get labeled GPU core sensors for the current CPU model +std::vector> smctemp::SmcTemp::GetGpuCoreSensors() { + std::vector> labeled_sensors; + + const std::string cpumodel = getCPUModel(); + if (cpumodel.find("m4") != std::string::npos) { // Apple M4 + labeled_sensors.emplace_back(std::string("GPU 1"), std::string(kSensorTg0D)); + labeled_sensors.emplace_back(std::string("GPU 2"), std::string(kSensorTg0P)); + labeled_sensors.emplace_back(std::string("GPU 3"), std::string(kSensorTg0X)); + labeled_sensors.emplace_back(std::string("GPU 4"), std::string(kSensorTg0j)); + } else if (cpumodel.find("m3") != std::string::npos) { // Apple M3 + labeled_sensors.emplace_back(std::string("GPU 1"), std::string(kSensorTg0D)); + labeled_sensors.emplace_back(std::string("GPU 2"), std::string(kSensorTg0P)); + labeled_sensors.emplace_back(std::string("GPU 3"), std::string(kSensorTg0X)); + labeled_sensors.emplace_back(std::string("GPU 4"), std::string(kSensorTg0b)); + labeled_sensors.emplace_back(std::string("GPU 5"), std::string(kSensorTg0j)); + labeled_sensors.emplace_back(std::string("GPU 6"), std::string(kSensorTg0v)); + } else if (cpumodel.find("m2") != std::string::npos) { // Apple M2 + // ref: https://github.com/exelban/stats/blob/6b88eb1f60a0eb5b1a7b51b54f044bf637fd785b/Modules/Sensors/values.swift#L369-L370 + labeled_sensors.emplace_back(std::string("GPU 1"), std::string(kSensorTg0f)); + labeled_sensors.emplace_back(std::string("GPU 2"), std::string(kSensorTg0j)); + } else if (cpumodel.find("m1") != std::string::npos) { // Apple M1 + // ref: https://github.com/exelban/stats/blob/6b88eb1f60a0eb5b1a7b51b54f044bf637fd785b/Modules/Sensors/values.swift#L354-L357 + labeled_sensors.emplace_back(std::string("GPU 1"), std::string(kSensorTg05)); + labeled_sensors.emplace_back(std::string("GPU 2"), std::string(kSensorTg0D)); + labeled_sensors.emplace_back(std::string("GPU 3"), std::string(kSensorTg0L)); + labeled_sensors.emplace_back(std::string("GPU 4"), std::string(kSensorTg0T)); + // ref: runtime detected on a M1 mac mini + labeled_sensors.emplace_back(std::string("GPU 5"), std::string(kSensorTg1b)); + labeled_sensors.emplace_back(std::string("GPU 6"), std::string(kSensorTg4b)); + } + + return labeled_sensors; +} + +double smctemp::SmcTemp::GetCpuTemp() { double temp = 0.0; #if defined(ARCH_TYPE_X86_64) const std::pair valid_temperature_limits{0, 110}; @@ -460,98 +562,22 @@ double SmcTemp::GetCpuTemp() { return temp; } #elif defined(ARCH_TYPE_ARM64) - std::vector sensors; - std::vector aux_sensors; const std::pair valid_temperature_limits{10, 120}; + std::vector sensors; + + // Get the labeled sensors and extract just the keys for averaging + auto labeled_sensors = GetCpuCoreSensors(); + for (const auto& sensor : labeled_sensors) { + sensors.push_back(sensor.second); + } - const std::string cpumodel = getCPUModel(); - if (cpumodel.find("m4") != std::string::npos) { // Apple M4 - sensors.emplace_back(static_cast(kSensorTp01)); - sensors.emplace_back(static_cast(kSensorTp09)); - sensors.emplace_back(static_cast(kSensorTp0f)); - sensors.emplace_back(static_cast(kSensorTp05)); - sensors.emplace_back(static_cast(kSensorTp0D)); - } else if (cpumodel.find("m3") != std::string::npos) { // Apple M3 - // CPU core 1 - sensors.emplace_back(static_cast(kSensorTp01)); - // CPU core 2 - sensors.emplace_back(static_cast(kSensorTp09)); - // CPU core 3 - sensors.emplace_back(static_cast(kSensorTp0f)); - // CPU core 4 - sensors.emplace_back(static_cast(kSensorTp0n)); - // CPU core 5 - sensors.emplace_back(static_cast(kSensorTp05)); - // CPU core 6 - sensors.emplace_back(static_cast(kSensorTp0D)); - // CPU core 7 - sensors.emplace_back(static_cast(kSensorTp0j)); - // CPU core 8 - sensors.emplace_back(static_cast(kSensorTp0r)); - } else if (cpumodel.find("m2") != std::string::npos) { // Apple M2 - // CPU efficient cores 1 through 4 on M2 Max 12 Core Chip - sensors.emplace_back(static_cast(kSensorTp1h)); - sensors.emplace_back(static_cast(kSensorTp1t)); - sensors.emplace_back(static_cast(kSensorTp1p)); - sensors.emplace_back(static_cast(kSensorTp1l)); - - // CPU core 1 - sensors.emplace_back(static_cast(kSensorTp01)); - // CPU core 2 - sensors.emplace_back(static_cast(kSensorTp09)); - // CPU core 3 - sensors.emplace_back(static_cast(kSensorTp0f)); - // CPU core 4 - sensors.emplace_back(static_cast(kSensorTp0n)); - // CPU core 5 - sensors.emplace_back(static_cast(kSensorTp05)); - // CPU core 6 - sensors.emplace_back(static_cast(kSensorTp0D)); - // CPU core 7 - sensors.emplace_back(static_cast(kSensorTp0j)); - // CPU core 8 - sensors.emplace_back(static_cast(kSensorTp0r)); - } else if (cpumodel.find("m1") != std::string::npos) { // Apple M1 - // CPU performance core 1 temperature - sensors.emplace_back(static_cast(kSensorTp01)); - // CPU performance core 2 temperature - sensors.emplace_back(static_cast(kSensorTp05)); - // CPU performance core 3 temperature - sensors.emplace_back(static_cast(kSensorTp0D)); - // CPU performance core 4 temperature - sensors.emplace_back(static_cast(kSensorTp0H)); - // CPU performance core 5 temperature - sensors.emplace_back(static_cast(kSensorTp0L)); - // CPU performance core 6 temperature - sensors.emplace_back(static_cast(kSensorTp0P)); - // CPU performance core 7 temperature - sensors.emplace_back(static_cast(kSensorTp0X)); - // CPU performance core 8 temperature - sensors.emplace_back(static_cast(kSensorTp0b)); - // CPU efficient core 1 temperature - sensors.emplace_back(static_cast(kSensorTp09)); - // CPU efficient core 2 temperature - sensors.emplace_back(static_cast(kSensorTp0T)); - - aux_sensors.emplace_back(static_cast(kSensorTc0a)); - aux_sensors.emplace_back(static_cast(kSensorTc0b)); - aux_sensors.emplace_back(static_cast(kSensorTc0x)); - aux_sensors.emplace_back(static_cast(kSensorTc0z)); - } else { + if (sensors.empty()) { // not supported return temp; } temp = CalculateAverageTemperature(sensors, valid_temperature_limits); - if (temp > std::numeric_limits::epsilon()) { - if (IsValidTemperature(temp, valid_temperature_limits)) { - StoreValidTemperature(temp, cpu_file_); - } - return temp; - } - - temp = CalculateAverageTemperature(aux_sensors, valid_temperature_limits); - if (IsValidTemperature(temp, valid_temperature_limits)) { + if (temp > std::numeric_limits::epsilon() && IsValidTemperature(temp, valid_temperature_limits)) { StoreValidTemperature(temp, cpu_file_); } #endif @@ -559,7 +585,7 @@ double SmcTemp::GetCpuTemp() { return temp; } -double SmcTemp::GetGpuTemp() { +double smctemp::SmcTemp::GetGpuTemp() { double temp = 0.0; #if defined(ARCH_TYPE_X86_64) const std::pair valid_temperature_limits{0, 110}; @@ -576,34 +602,17 @@ double SmcTemp::GetGpuTemp() { #elif defined(ARCH_TYPE_ARM64) std::vector sensors; const std::pair valid_temperature_limits{10, 120}; - const std::string cpumodel = getCPUModel(); - if (cpumodel.find("m4") != std::string::npos) { // Apple M4 - sensors.emplace_back(static_cast(kSensorTg0D)); // GPU 1 - sensors.emplace_back(static_cast(kSensorTg0P)); // GPU 2 - sensors.emplace_back(static_cast(kSensorTg0X)); // GPU 3 - sensors.emplace_back(static_cast(kSensorTg0j)); // GPU 4 - } else if (cpumodel.find("m3") != std::string::npos) { // Apple M3 - sensors.emplace_back(static_cast(kSensorTg0D)); // GPU 1 - sensors.emplace_back(static_cast(kSensorTg0P)); // GPU 2 - sensors.emplace_back(static_cast(kSensorTg0X)); // GPU 3 - sensors.emplace_back(static_cast(kSensorTg0b)); // GPU 4 - sensors.emplace_back(static_cast(kSensorTg0j)); // GPU 5 - sensors.emplace_back(static_cast(kSensorTg0v)); // GPU 6 - } else if (cpumodel.find("m2") != std::string::npos) { // Apple M2 - // ref: https://github.com/exelban/stats/blob/6b88eb1f60a0eb5b1a7b51b54f044bf637fd785b/Modules/Sensors/values.swift#L369-L370 - sensors.emplace_back(static_cast(kSensorTg0f)); // GPU 1 - sensors.emplace_back(static_cast(kSensorTg0j)); // GPU 2 - } else if (cpumodel.find("m1") != std::string::npos) { // Apple M1 - // ref: https://github.com/exelban/stats/blob/6b88eb1f60a0eb5b1a7b51b54f044bf637fd785b/Modules/Sensors/values.swift#L354-L357 - sensors.emplace_back(static_cast(kSensorTg05)); // GPU 1 - sensors.emplace_back(static_cast(kSensorTg0D)); // GPU 2 - sensors.emplace_back(static_cast(kSensorTg0L)); // GPU 3 - sensors.emplace_back(static_cast(kSensorTg0T)); // GPU 4 - // ref: runtime detected on a M1 mac mini - sensors.emplace_back(static_cast(kSensorTg1b)); // GPU 5 - sensors.emplace_back(static_cast(kSensorTg4b)); // GPU 6 - } else { - // not supported + + // Get sensor pairs + auto labeled_sensors = GetGpuCoreSensors(); + + // Extract just the sensor keys for the calculation + for (const auto& sensor_pair : labeled_sensors) { + sensors.emplace_back(sensor_pair.second); + } + + // If no sensors found, this chip is not supported + if (sensors.empty()) { return temp; } temp = CalculateAverageTemperature(sensors, valid_temperature_limits); @@ -614,7 +623,7 @@ double SmcTemp::GetGpuTemp() { return temp; } -double SmcTemp::GetLastValidCpuTemp() { +double smctemp::SmcTemp::GetLastValidCpuTemp() { std::string file_path = storage_path_ + cpu_file_; std::ifstream file(file_path); if (!file.is_open()) { @@ -631,7 +640,7 @@ double SmcTemp::GetLastValidCpuTemp() { return value; } -double SmcTemp::GetLastValidGpuTemp() { +double smctemp::SmcTemp::GetLastValidGpuTemp() { std::string file_path = storage_path_ + gpu_file_; std::ifstream file(file_path); if (!file.is_open()) { @@ -647,5 +656,74 @@ double SmcTemp::GetLastValidGpuTemp() { return value; } + +std::vector> smctemp::SmcTemp::GetIndividualCpuTemps() { + std::vector> temps; + const std::pair valid_temperature_limits{10, 120}; + +#if defined(ARCH_TYPE_X86_64) + // For x86_64 processors, try each sensor individually + double temp = smc_accessor_.ReadValue(kSensorTC0D); + if (IsValidTemperature(temp, valid_temperature_limits)) { + temps.emplace_back(std::string("TC0D"), temp); + } + + temp = smc_accessor_.ReadValue(kSensorTC0E); + if (IsValidTemperature(temp, valid_temperature_limits)) { + temps.emplace_back(std::string("TC0E"), temp); + } + + temp = smc_accessor_.ReadValue(kSensorTC0F); + if (IsValidTemperature(temp, valid_temperature_limits)) { + temps.emplace_back(std::string("TC0F"), temp); + } + + temp = smc_accessor_.ReadValue(kSensorTC0P); + if (IsValidTemperature(temp, valid_temperature_limits)) { + temps.emplace_back(std::string("TC0P"), temp); + } +#elif defined(ARCH_TYPE_ARM64) + // Get the labeled sensors + auto labeled_sensors = GetCpuCoreSensors(); + + // Read temperatures from labeled sensors + for (const auto& sensor : labeled_sensors) { + double temp = smc_accessor_.ReadValue(sensor.second.c_str()); + if (IsValidTemperature(temp, valid_temperature_limits)) { + temps.emplace_back(sensor.first, temp); + } + } +#endif + + return temps; } +std::vector> smctemp::SmcTemp::GetIndividualGpuTemps() { + std::vector> temps; + const std::pair valid_temperature_limits{10, 120}; + +#if defined(ARCH_TYPE_X86_64) + double temp = smc_accessor_.ReadValue(kSensorTG0D); + if (IsValidTemperature(temp, valid_temperature_limits)) { + temps.emplace_back(std::string("TG0D"), temp); + } + + temp = smc_accessor_.ReadValue(kSensorTPCD); + if (IsValidTemperature(temp, valid_temperature_limits)) { + temps.emplace_back(std::string("TPCD"), temp); + } +#elif defined(ARCH_TYPE_ARM64) + // Get sensor mapping + auto labeled_sensors = GetGpuCoreSensors(); + + for (const auto& sensor : labeled_sensors) { + double temp = smc_accessor_.ReadValue(sensor.second.c_str()); + if (IsValidTemperature(temp, valid_temperature_limits)) { + temps.emplace_back(sensor.first, temp); + } + } +#endif + + return temps; +} +} diff --git a/smctemp.h b/smctemp.h index 74af60e..00b1021 100644 --- a/smctemp.h +++ b/smctemp.h @@ -43,6 +43,8 @@ constexpr int kOpNone = 0; constexpr int kOpList = 1; constexpr int kOpReadCpuTemp = 2; constexpr int kOpReadGpuTemp = 3; +constexpr int kOpReadIndividualCpuTemp = 4; +constexpr int kOpReadIndividualGpuTemp = 5; // List of key and name: // - https://github.com/exelban/stats/blob/6b88eb1f60a0eb5b1a7b51b54f044bf637fd785b/Modules/Sensors/values.swift @@ -120,6 +122,10 @@ class SmcTemp { double CalculateAverageTemperature(const std::vector& sensors, const std::pair& limits); bool StoreValidTemperature(double temperature, std::string file_name); + // Get labeled CPU core sensors for the current CPU model + std::vector> GetCpuCoreSensors(); + // Get labeled GPU core sensors for the current CPU model + std::vector> GetGpuCoreSensors(); SmcAccessor smc_accessor_; bool is_fail_soft_; const std::string storage_path_ = "/tmp/smctemp/"; @@ -134,6 +140,10 @@ class SmcTemp { double GetLastValidCpuTemp(); double GetLastValidGpuTemp(); bool IsValidTemperature(double temperature, const std::pair& limits); + + // Individual core temperatures + std::vector> GetIndividualCpuTemps(); + std::vector> GetIndividualGpuTemps(); }; typedef struct {