Add mapping logic, refactor stuff

This commit is contained in:
2022-09-19 20:02:18 +02:00
parent dccd6f2773
commit f507912623
19 changed files with 275 additions and 187 deletions

76
app/src/Mapping.cxx Normal file
View File

@@ -0,0 +1,76 @@
#include <chrono>
#include <iostream>
#include <map>
#include <memory>
#include <thread>
#include <Mapping.h>
#include <fan/HwmonFan.h>
#include <fan/PwmControl.h>
#define SETTLE_TIMEOUT 5
using namespace std;
vector<shared_ptr<Fan>>
Mapping::createMapping(vector<shared_ptr<Sensor>> rpmSensors,
vector<shared_ptr<PwmControl>> pwmControls) {
print("RPM Sensors", rpmSensors);
print("PWM controllers", pwmControls);
vector<shared_ptr<Fan>> mapping;
cout << "Settings all fans to maximum speed" << endl;
for (auto c : pwmControls) {
c->enableManualControl();
c->pwm(100);
}
// Wait for fans to settle
cout << "Waiting for fans to settle" << endl;
this_thread::sleep_for(chrono::seconds(SETTLE_TIMEOUT));
// Record values of all RPM sensors
for (auto s : rpmSensors) {
int value = s->value();
s->max(value);
cout << s->toString() << " max value: " << s->max() << endl;
}
// Set each fan to 50% and check if a sensor matches
for (auto c : pwmControls) {
cout << "Setting " << c->toString()
<< " to 50% and wait for it to settle..." << endl;
c->pwm(50);
this_thread::sleep_for(chrono::seconds(SETTLE_TIMEOUT));
for (auto s : rpmSensors) {
if (s->value() < s->max() * 0.7) {
cout << "Found matching sensor " << s->toString() << endl;
mapping.push_back(make_shared<HwmonFan>(c, s));
}
}
cout << "Setting fan back to 100% and wait for settling" << endl;
c->pwm(100);
this_thread::sleep_for(chrono::seconds(SETTLE_TIMEOUT));
}
cout << "Resetting all fans" << endl;
for (auto c : pwmControls) {
c->reset();
}
return mapping;
}
template <class Printable>
void Mapping::print(string listLabel, vector<shared_ptr<Printable>> list) {
cout << listLabel << ": " << endl;
for (auto i : list) {
cout << i->toString() << endl;
}
cout << "\n";
}

View File

@@ -1,58 +0,0 @@
#include <exception>
#include <iostream>
#include <sensors/sensors.h>
#include <stdexcept>
#include <SensorsWrapper.h>
using namespace std;
#define CONFIG_FILE "/etc/conf.d/sensors"
SensorsWrapper::SensorsWrapper() {
auto config = fopen(CONFIG_FILE, "r");
if (sensors_init(config) != 0) {
throw runtime_error("Config file doesn't exist");
}
int c = 0;
for (const sensors_chip_name *chipName;
(chipName = sensors_get_detected_chips(0, &c)) != NULL;) {
int d = 0;
for (const sensors_feature *feature;
(feature = sensors_get_features(chipName, &d)) != NULL;) {
auto tempFeature = sensors_get_subfeature(chipName, feature,
SENSORS_SUBFEATURE_TEMP_INPUT);
if (tempFeature)
mTemperatureSensors.push_back(
Sensor{*chipName, *feature, *tempFeature});
auto fanFeature = sensors_get_subfeature(chipName, feature,
SENSORS_SUBFEATURE_FAN_INPUT);
if (fanFeature)
mFanSensors.push_back(Sensor{*chipName, *feature, *fanFeature});
}
}
}
SensorsWrapper::~SensorsWrapper() { sensors_cleanup(); }
std::vector<Sensor> SensorsWrapper::getTemperatureSensors() {
return mTemperatureSensors;
}
int SensorsWrapper::getValue(Sensor sensor) {
double value;
const sensors_chip_name *chipName = &sensor.chipName;
sensors_get_value(chipName, sensor.subFeature.number, &value);
return (int)value;
}
string SensorsWrapper::getLabel(Sensor sensor) {
const sensors_chip_name *chipName = &sensor.chipName;
const sensors_feature *feature = &sensor.feature;
return string(sensors_get_label(chipName, feature));
}

11
app/src/fan/HwmonFan.cxx Normal file
View File

@@ -0,0 +1,11 @@
#include <fan/HwmonFan.h>
using namespace std;
HwmonFan::HwmonFan(shared_ptr<PwmControl> pwmControl,
shared_ptr<Sensor> rpmSensor)
: mPwmControl(pwmControl), mRpmSensor(rpmSensor) {}
void HwmonFan::pwm(int percent) { mPwmControl->pwm(percent); }
int HwmonFan::rpm() { return mRpmSensor->value(); }

View File

@@ -64,3 +64,7 @@ void PwmControl::reset() {
ostrm.close();
}
const string PwmControl::toString() const {
return fs::path(mControlPath).filename();
}

View File

@@ -1,91 +1,20 @@
#include <exception>
#include <filesystem>
#include <iostream>
#include <memory>
#include <regex>
#include <vector>
#include <sensors/sensors.h>
#include <fan/PwmControl.h>
#include <sensor/HwmonSensor.h>
#include <Mapping.h>
#include <sensor/NvidiaSensor.h>
#define CONFIG_FILE "/etc/conf.d/sensors"
#define HWMON_BASE_PATH "/sys/class/hwmon"
namespace fs = std::filesystem;
template <sensors_subfeature_type T>
std::vector<std::shared_ptr<Sensor>> sensors() {
std::vector<std::shared_ptr<Sensor>> sensors;
int c = 0;
for (const sensors_chip_name *chipName;
(chipName = sensors_get_detected_chips(0, &c)) != NULL;) {
int d = 0;
for (const sensors_feature *feature;
(feature = sensors_get_features(chipName, &d)) != NULL;) {
auto subFeature = sensors_get_subfeature(chipName, feature, T);
if (subFeature) {
sensors.push_back(
std::make_shared<HwmonSensor>(chipName, feature, subFeature));
}
}
}
return sensors;
}
std::vector<std::shared_ptr<PwmControl>> pwmControls() {
std::vector<std::shared_ptr<PwmControl>> controls;
const std::regex re_ctrl_enable("pwm[0-9]_enable");
const std::regex re_ctrl_mode("pwm[0-9]_mode");
const std::regex re_ctrl("pwm[0-9]");
if (!fs::exists(HWMON_BASE_PATH)) {
std::cout << HWMON_BASE_PATH << " doesn't exist" << std::endl;
} else {
for (const fs::directory_entry &hwmon_device :
fs::directory_iterator{HWMON_BASE_PATH}) {
for (const fs::directory_entry &control :
fs::directory_iterator{hwmon_device}) {
auto filename = control.path().filename().string();
if (regex_match(filename, re_ctrl)) {
auto controlPath = control.path().string();
controls.push_back(std::make_shared<PwmControl>(controlPath));
}
}
}
}
return controls;
}
#include <sensor/SensorsWrapper.h>
int main() {
auto config = fopen(CONFIG_FILE, "r");
if (sensors_init(config) != 0) {
throw std::runtime_error("Config file doesn't exist");
}
SensorsWrapper sensorsWrapper;
auto tempSensors = sensors<SENSORS_SUBFEATURE_TEMP_INPUT>();
auto tempSensors = sensorsWrapper.Sensors(SENSORS_SUBFEATURE_TEMP_INPUT);
tempSensors.push_back(std::make_shared<NvidiaSensor>());
for (auto s : tempSensors) {
std::cout << s->name() << ": " << s->value() << std::endl;
}
auto pwmSensors = sensorsWrapper.Sensors(SENSORS_SUBFEATURE_FAN_INPUT);
std::cout << "pwm" << std::endl;
auto controls = sensorsWrapper.PwmControls();
auto pwmSensors = sensors<SENSORS_SUBFEATURE_FAN_INPUT>();
for (auto s : pwmSensors) {
std::cout << s->name() << ": " << s->value() << std::endl;
}
Mapping m;
m.createMapping(pwmSensors, controls);
return 0;
}

View File

@@ -1,6 +1,5 @@
#include <sensors/sensors.h>
#include <sensor/HwmonSensor.h>
#include <sensors/sensors.h>
using namespace std;
@@ -10,10 +9,12 @@ HwmonSensor::HwmonSensor(const sensors_chip_name *chipName,
: mChipName(chipName), mFeature(feature), mSubFeature(subfeature) {}
int HwmonSensor::value() {
double *value;
sensors_get_value(mChipName, mSubFeature->number, value);
double value;
sensors_get_value(mChipName, mSubFeature->number, &value);
return static_cast<int>(*value);
return static_cast<int>(value);
}
string HwmonSensor::name() { return sensors_get_label(mChipName, mFeature); }
const string HwmonSensor::toString() const {
return sensors_get_label(mChipName, mFeature);
}

View File

@@ -18,4 +18,4 @@ int NvidiaSensor::value() {
return static_cast<int>(temp);
}
string NvidiaSensor::name() { return "GPU"; }
const std::string NvidiaSensor::toString() const { return "Nvidia GPU"; }

View File

@@ -0,0 +1,5 @@
#include <sensor/Sensor.h>
int Sensor::max() const { return mMax; }
void Sensor::max(int value) { mMax = value; }

View File

@@ -0,0 +1,78 @@
#include <cstdio>
#include <filesystem>
#include <iostream>
#include <regex>
#include <stdexcept>
#include <type_traits>
#include <sensors/sensors.h>
#include <sensor/SensorsWrapper.h>
#include <sensor/HwmonSensor.h>
#include <sensor/NvidiaSensor.h>
using namespace std;
namespace fs = std::filesystem;
#define CONFIG_FILE "/etc/conf.d/sensors"
#define HWMON_BASE_PATH "/sys/class/hwmon"
SensorsWrapper::SensorsWrapper() : mConfigFile(fopen(CONFIG_FILE, "r")) {
if (sensors_init(mConfigFile) != 0) {
throw runtime_error("Config file doesn't exist");
}
}
SensorsWrapper::~SensorsWrapper() { sensors_cleanup(); }
std::vector<std::shared_ptr<Sensor>>
SensorsWrapper::Sensors(sensors_subfeature_type sensorType) {
std::vector<std::shared_ptr<Sensor>> sensors;
int c = 0;
for (const sensors_chip_name *chipName;
(chipName = sensors_get_detected_chips(0, &c)) != NULL;) {
int d = 0;
for (const sensors_feature *feature;
(feature = sensors_get_features(chipName, &d)) != NULL;) {
auto subFeature = sensors_get_subfeature(chipName, feature, sensorType);
if (subFeature) {
sensors.push_back(
std::make_shared<HwmonSensor>(chipName, feature, subFeature));
}
}
}
return sensors;
}
std::vector<std::shared_ptr<PwmControl>> SensorsWrapper::PwmControls() {
std::vector<std::shared_ptr<PwmControl>> controls;
const std::regex re_ctrl_enable("pwm[0-9]_enable");
const std::regex re_ctrl_mode("pwm[0-9]_mode");
const std::regex re_ctrl("pwm[0-9]");
if (!fs::exists(HWMON_BASE_PATH)) {
std::cout << HWMON_BASE_PATH << " doesn't exist" << std::endl;
} else {
for (const fs::directory_entry &hwmon_device :
fs::directory_iterator{HWMON_BASE_PATH}) {
for (const fs::directory_entry &control :
fs::directory_iterator{hwmon_device}) {
auto filename = control.path().filename().string();
if (regex_match(filename, re_ctrl)) {
auto controlPath = control.path().string();
controls.push_back(std::make_shared<PwmControl>(controlPath));
}
}
}
}
return controls;
}