4 Commits

Author SHA1 Message Date
Tabascl
8ff1d8be9d Bump version numbers 2024-07-07 23:52:03 +02:00
Tabascl
78b2a62643 Remove aggregator, fix changing HWMON paths
Add logic to use actual device paths for the PWM sensors instead of their
standart HWMON paths.

This was done after noticing that due to the load order of kernel modules,
the index of HWMON paths could change.
2024-07-07 22:19:27 +02:00
e2509cea8b Various fixes
- Change unit path
- Rename method
- Make CurrentPWM method return its value in PWM instead of percent
2023-10-08 13:50:33 +02:00
0a6bab36be Hysteresis, Inhibit-Stop Timeframe 2023-08-28 14:55:07 +02:00
20 changed files with 242 additions and 101 deletions

View File

@@ -1,5 +1,5 @@
pkgname=fantasize pkgname=fantasize
pkgver=0.2.0 pkgver=0.3.0
pkgrel=1 pkgrel=1
pkgdesc='C++ fan control for Linux' pkgdesc='C++ fan control for Linux'
url='https://github.com/Tabascl/fantasize.git' url='https://github.com/Tabascl/fantasize.git'

View File

@@ -17,16 +17,16 @@
using json = nlohmann::json; using json = nlohmann::json;
class Serializer class Serializer {
{
public: public:
Serializer(); Serializer();
void SerializeFans(std::vector<std::shared_ptr<Fan>> fans); void SerializeFans(std::vector<std::shared_ptr<Fan>> fans);
std::vector<std::shared_ptr<Fan>> DeserializeFans( std::vector<std::shared_ptr<Fan>>
std::vector<std::shared_ptr<Sensor>> availableSensors); DeserializeFans(std::vector<std::shared_ptr<Sensor>> availableSensors);
std::vector<std::shared_ptr<FanCurve>> DeserializeFanCurves( std::vector<std::shared_ptr<FanCurve>>
std::vector<std::shared_ptr<Sensor>> availableSensors, DeserializeFanCurves(std::vector<std::shared_ptr<Sensor>> availableSensors,
std::vector<std::shared_ptr<Fan>> availableFans); std::vector<std::shared_ptr<Fan>> availableFans,
bool &everythingFound);
std::shared_ptr<Settings> DeserializeSettings(); std::shared_ptr<Settings> DeserializeSettings();
private: private:

View File

@@ -22,6 +22,8 @@ public:
virtual void FindPWMLimits() = 0; virtual void FindPWMLimits() = 0;
virtual void AdjustPWMLimits() = 0; virtual void AdjustPWMLimits() = 0;
virtual void EnforceSetValue() = 0;
}; };
#endif // FAN_H_ #endif // FAN_H_

View File

@@ -8,30 +8,31 @@
#include <fan/HwmonFan.h> #include <fan/HwmonFan.h>
#include <sensor/Sensor.h> #include <sensor/Sensor.h>
struct FanStep struct FanStep {
{
int Temp; int Temp;
int Percent; int Percent;
}; };
class FanCurve class FanCurve {
{
public: public:
FanCurve(std::vector<FanStep> steps, FanCurve(std::vector<FanStep> steps,
std::vector<std::shared_ptr<Sensor>> sensors, std::vector<std::shared_ptr<Sensor>> sensors,
std::vector<std::shared_ptr<Fan>> fans, std::vector<std::shared_ptr<Fan>> fans,
std::unique_ptr<Aggregator> aggregator); std::unique_ptr<Aggregator> aggregator, int hysteresis);
void DoFanControl(); void DoFanControl();
private: private:
int AggregateTemperature();
void PrintInfo(); void PrintInfo();
bool ExceedsHysteresis(int temperature);
void ApplyFanPower(std::shared_ptr<Fan> fan, int targetFanPower);
std::vector<FanStep> mSteps; std::vector<FanStep> mSteps;
std::vector<std::shared_ptr<Sensor>> mTempSensors; std::vector<std::shared_ptr<Sensor>> mTempSensors;
std::vector<std::shared_ptr<Fan>> mFans; std::vector<std::shared_ptr<Fan>> mFans;
std::unique_ptr<Aggregator> mAggregator; std::unique_ptr<Aggregator> mAggregator;
int mHystersis;
int mLastTemperature;
}; };
#endif // FANCURVE_H_ #endif // FANCURVE_H_

View File

@@ -30,11 +30,16 @@ public:
void FindPWMLimits() override; void FindPWMLimits() override;
void AdjustPWMLimits() override; void AdjustPWMLimits() override;
void EnforceSetValue() override;
json toJson() const override; json toJson() const override;
const std::string toString() const override; const std::string toString() const override;
private: private:
bool InhibitStopPeriodExpired();
void SetPower(int percent);
std::shared_ptr<PWMControl> mPWMControl; std::shared_ptr<PWMControl> mPWMControl;
std::shared_ptr<Sensor> mRpmSensor; std::shared_ptr<Sensor> mRpmSensor;
std::string mLabel; std::string mLabel;
@@ -43,6 +48,9 @@ private:
int mStartPWM = 0; int mStartPWM = 0;
bool mZeroFanModeSupported = false; bool mZeroFanModeSupported = false;
std::chrono::time_point<std::chrono::steady_clock> mLastAdjustmentTime; std::chrono::time_point<std::chrono::steady_clock> mLastAdjustmentTime;
std::chrono::time_point<std::chrono::steady_clock> mLastStartTime;
int mSetValue = 0;
bool mWasStopped = false;
}; };
#endif // HWMONFAN_H_ #endif // HWMONFAN_H_

View File

@@ -12,11 +12,11 @@ enum class PWM_MODE { DC = 0, PWM };
class PWMControl : public Printable, public Serializable { class PWMControl : public Printable, public Serializable {
public: public:
PWMControl(std::string controlPath); PWMControl(std::string controlPath, int deviceIndex);
~PWMControl(); ~PWMControl();
void Power(int percent); void SetPower(int percent);
int Power(); int CurrentPWM();
void EnableManualControl(); void EnableManualControl();
void Reset(); void Reset();
@@ -26,11 +26,11 @@ public:
json toJson() const override; json toJson() const override;
private: private:
int mCurrentValue; std::string mConfigPath;
std::string mControlPath; std::string mControlPath;
std::string mEnablePath; std::string mEnablePath;
std::string mModePath; std::string mModePath;
int mDeviceIndex;
std::string mInitialEnable; std::string mInitialEnable;
std::string mInitialMode; std::string mInitialMode;

View File

@@ -16,9 +16,13 @@ public:
std::vector<std::shared_ptr<Sensor>> TemperatureSensors(); std::vector<std::shared_ptr<Sensor>> TemperatureSensors();
std::vector<std::shared_ptr<Sensor>> RPMSensors(); std::vector<std::shared_ptr<Sensor>> RPMSensors();
void ReloadSensors();
private: private:
template <sensors_subfeature_type T> template <sensors_subfeature_type T>
std::vector<std::shared_ptr<Sensor>> Sensors(); std::vector<std::shared_ptr<Sensor>> Sensors();
void InitSensors();
void CleanupSensors();
private: private:
FILE *mConfigFile; FILE *mConfigFile;

View File

@@ -12,6 +12,8 @@ public:
std::vector<std::shared_ptr<Sensor>> TemperatureSensors(); std::vector<std::shared_ptr<Sensor>> TemperatureSensors();
std::vector<std::shared_ptr<Sensor>> RPMSensors(); std::vector<std::shared_ptr<Sensor>> RPMSensors();
void ReloadSensors();
private: private:
std::unique_ptr<LMSensorsFacade> mLMSensorsFacade; std::unique_ptr<LMSensorsFacade> mLMSensorsFacade;
std::unique_ptr<GPUSensorsFacade> mGPUSensorsFacade; std::unique_ptr<GPUSensorsFacade> mGPUSensorsFacade;

View File

@@ -1,4 +1,4 @@
project('fantasize', 'cpp', version : '0.2.1', default_options : ['cpp_std=c++20']) project('fantasize', 'cpp', version : '0.3.0', default_options : 'cpp_std=c++20')
src = [ src = [
'src/main.cxx', 'src/main.cxx',
@@ -34,4 +34,4 @@ exe = executable('fantasize',
install: true, install: true,
include_directories: inc) include_directories: inc)
install_data('unit/fantasize.service', install_dir : 'usr/lib/systemd/system') install_data('unit/fantasize.service', install_dir : '/usr/lib/systemd/system')

View File

@@ -1,14 +1,35 @@
#include "fan/Fan.h"
#include "fan/FanCurve.h"
#include <chrono>
#include <execution> #include <execution>
#include <boost/log/attributes/named_scope.hpp>
#include <boost/log/trivial.hpp>
#include <App.h> #include <App.h>
#include <memory>
#include <thread>
using namespace std; using namespace std;
void App::Init() { void App::Init() {
mFans = mSerializer.DeserializeFans(mSensorManager.RPMSensors()); BOOST_LOG_FUNCTION();
bool everythingFound = false;
mFans = mSerializer.DeserializeFans(mSensorManager.RPMSensors());
auto fanCurves = mSerializer.DeserializeFanCurves( auto fanCurves = mSerializer.DeserializeFanCurves(
mSensorManager.TemperatureSensors(), mFans); mSensorManager.TemperatureSensors(), mFans, everythingFound);
while (!everythingFound) {
BOOST_LOG_TRIVIAL(info) << "Couldn't find every sensor. Retrying in 5s...";
this_thread::sleep_for(chrono::seconds(5));
mSensorManager.ReloadSensors();
mFans = mSerializer.DeserializeFans(mSensorManager.RPMSensors());
fanCurves = mSerializer.DeserializeFanCurves(
mSensorManager.TemperatureSensors(), mFans, everythingFound);
}
mSettings = mSerializer.DeserializeSettings(); mSettings = mSerializer.DeserializeSettings();

View File

@@ -8,7 +8,7 @@
#include <fan/HwmonFan.h> #include <fan/HwmonFan.h>
#include <pwm/PWMControl.h> #include <pwm/PWMControl.h>
#define SETTLE_TIMEOUT 5 #define SETTLE_TIMEOUT 30
using namespace std; using namespace std;
@@ -22,7 +22,7 @@ FanGenerator::FindFans(vector<shared_ptr<Sensor>> rpmSensors,
cout << "Setting all fans to maximum speed" << endl; cout << "Setting all fans to maximum speed" << endl;
for (auto c : pwmControls) { for (auto c : pwmControls) {
c->EnableManualControl(); c->EnableManualControl();
c->Power(100); c->SetPower(100);
} }
// Wait for fans to settle // Wait for fans to settle
@@ -41,7 +41,7 @@ FanGenerator::FindFans(vector<shared_ptr<Sensor>> rpmSensors,
for (auto c : pwmControls) { for (auto c : pwmControls) {
cout << "Setting " << c->toString() cout << "Setting " << c->toString()
<< " to 50% and wait for it to settle..." << endl; << " to 50% and wait for it to settle..." << endl;
c->Power(50); c->SetPower(50);
this_thread::sleep_for(chrono::seconds(SETTLE_TIMEOUT)); this_thread::sleep_for(chrono::seconds(SETTLE_TIMEOUT));
@@ -53,7 +53,7 @@ FanGenerator::FindFans(vector<shared_ptr<Sensor>> rpmSensors,
} }
cout << "Setting fan back to 100%" << endl; cout << "Setting fan back to 100%" << endl;
c->Power(100); c->SetPower(100);
} }
return mapping; return mapping;

View File

@@ -1,9 +1,11 @@
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <boost/log/attributes/named_scope.hpp>
#include <boost/log/trivial.hpp>
#include <Serializer.h> #include <Serializer.h>
#include <fan/HwmonFan.h> #include <fan/HwmonFan.h>
#include <pwm/PWMControl.h> #include <pwm/PWMControl.h>
@@ -31,9 +33,11 @@ void Serializer::SerializeFans(vector<shared_ptr<Fan>> fans) {
vector<shared_ptr<Fan>> vector<shared_ptr<Fan>>
Serializer::DeserializeFans(vector<shared_ptr<Sensor>> availableSensors) { Serializer::DeserializeFans(vector<shared_ptr<Sensor>> availableSensors) {
BOOST_LOG_FUNCTION();
vector<shared_ptr<Fan>> fans; vector<shared_ptr<Fan>> fans;
// Create a for the sensors first, then searching becomes cheaper // Create a map for the sensors first, then searching becomes cheaper
map<string, shared_ptr<Sensor>> sensorMap; map<string, shared_ptr<Sensor>> sensorMap;
for (auto s : availableSensors) { for (auto s : availableSensors) {
sensorMap[s->toString()] = s; sensorMap[s->toString()] = s;
@@ -42,7 +46,7 @@ Serializer::DeserializeFans(vector<shared_ptr<Sensor>> availableSensors) {
auto data = ReadJson(); auto data = ReadJson();
try { try {
for (auto &el : data["fans"].items()) { for (auto &el : data["fans"].items()) {
auto pwmControl = make_shared<PWMControl>(el.value()["PWMControl"]); auto pwmControl = make_shared<PWMControl>(el.value()["PWMControl"]["Path"], el.value()["PWMControl"]["Index"]);
auto rpmSensor = sensorMap[el.value()["LMSensor"]]; auto rpmSensor = sensorMap[el.value()["LMSensor"]];
int minPWM = el.value()["MinPWM"]; int minPWM = el.value()["MinPWM"];
@@ -61,6 +65,12 @@ Serializer::DeserializeFans(vector<shared_ptr<Sensor>> availableSensors) {
} catch (const std::exception &e) { } catch (const std::exception &e) {
std::cout << "Deserialization error! Message: " << e.what() << std::endl; std::cout << "Deserialization error! Message: " << e.what() << std::endl;
} }
BOOST_LOG_TRIVIAL(trace) << "### Available Fans";
for (auto f : fans) {
BOOST_LOG_TRIVIAL(trace) << f->toString();
}
return fans; return fans;
} }
@@ -86,7 +96,10 @@ json Serializer::ReadJson() {
vector<shared_ptr<FanCurve>> Serializer::DeserializeFanCurves( vector<shared_ptr<FanCurve>> Serializer::DeserializeFanCurves(
std::vector<std::shared_ptr<Sensor>> availableSensors, std::vector<std::shared_ptr<Sensor>> availableSensors,
std::vector<std::shared_ptr<Fan>> availableFans) { std::vector<std::shared_ptr<Fan>> availableFans, bool &everythingFound) {
BOOST_LOG_FUNCTION();
everythingFound = true;
auto data = ReadJson(); auto data = ReadJson();
map<string, shared_ptr<Sensor>> sensorMap; map<string, shared_ptr<Sensor>> sensorMap;
@@ -113,6 +126,11 @@ vector<shared_ptr<FanCurve>> Serializer::DeserializeFanCurves(
for (auto &sensor : el.value()["Sensors"].items()) { for (auto &sensor : el.value()["Sensors"].items()) {
if (sensorMap.contains(sensor.value())) if (sensorMap.contains(sensor.value()))
sensors.push_back(sensorMap[sensor.value()]); sensors.push_back(sensorMap[sensor.value()]);
else {
BOOST_LOG_TRIVIAL(warning)
<< "Sensor " << sensor.value() << " not found!";
everythingFound = false;
}
} }
for (auto &fan : el.value()["Fans"].items()) { for (auto &fan : el.value()["Fans"].items()) {
@@ -123,8 +141,10 @@ vector<shared_ptr<FanCurve>> Serializer::DeserializeFanCurves(
std::unique_ptr<Aggregator> aggregator = std::unique_ptr<Aggregator> aggregator =
aggregatorFromString(el.value()["AggregateFunction"]); aggregatorFromString(el.value()["AggregateFunction"]);
curves.push_back( int hysteresis = el.value()["Hysteresis"];
make_shared<FanCurve>(steps, sensors, fans, std::move(aggregator)));
curves.push_back(make_shared<FanCurve>(steps, sensors, fans,
std::move(aggregator), hysteresis));
} }
return curves; return curves;

View File

@@ -1,6 +1,6 @@
#include <boost/log/attributes/named_scope.hpp>
#include <iostream> #include <iostream>
#include <boost/log/attributes/named_scope.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <fan/FanCurve.h> #include <fan/FanCurve.h>
@@ -11,16 +11,25 @@ using namespace std;
FanCurve::FanCurve(std::vector<FanStep> steps, FanCurve::FanCurve(std::vector<FanStep> steps,
std::vector<std::shared_ptr<Sensor>> sensors, std::vector<std::shared_ptr<Sensor>> sensors,
std::vector<std::shared_ptr<Fan>> fans, std::vector<std::shared_ptr<Fan>> fans,
std::unique_ptr<Aggregator> aggregator) std::unique_ptr<Aggregator> aggregator, int hysteresis)
: mSteps(steps), mTempSensors(sensors), mFans(fans), : mSteps(steps), mTempSensors(sensors), mFans(fans),
mAggregator(std::move(aggregator)) { mAggregator(std::move(aggregator)), mHystersis(hysteresis),
mLastTemperature(INT_MIN) {
PrintInfo(); PrintInfo();
} }
void FanCurve::DoFanControl() { void FanCurve::DoFanControl() {
BOOST_LOG_FUNCTION(); BOOST_LOG_FUNCTION()
int temp = AggregateTemperature(); BOOST_LOG_TRIVIAL(trace) << "## Fans in curve";
for (auto f : mFans)
BOOST_LOG_TRIVIAL(trace) << f->toString();
BOOST_LOG_TRIVIAL(trace) << "## Sensors in curve";
for (auto s : mTempSensors)
BOOST_LOG_TRIVIAL(trace) << s->toString();
int temp = mAggregator->aggregate(mTempSensors);
int t0 = 0, t1 = 0, p0 = 0, p1 = 0; int t0 = 0, t1 = 0, p0 = 0, p1 = 0;
int targetFanPower; int targetFanPower;
@@ -43,19 +52,23 @@ void FanCurve::DoFanControl() {
targetFanPower = p0 + ((p1 - p0) / (t1 - t0)) * (temp - t0); targetFanPower = p0 + ((p1 - p0) / (t1 - t0)) * (temp - t0);
} }
for (auto f : mFans) { BOOST_LOG_TRIVIAL(trace) << "Current temp: " << temp;
if (!f->ZeroFanModeSupported() && f->RPM() <= 0) { BOOST_LOG_TRIVIAL(trace) << "Last temp: " << mLastTemperature;
BOOST_LOG_TRIVIAL(warning) << "Fan stopped completely!";
f->PWM(f->StartPWM());
f->AdjustPWMLimits();
} else {
f->PWM(targetFanPower);
}
}
}
int FanCurve::AggregateTemperature() { BOOST_LOG_TRIVIAL(trace) << "# Hysteresis check";
return mAggregator->aggregate(mTempSensors); if (ExceedsHysteresis(temp)) {
BOOST_LOG_TRIVIAL(trace) << "passed";
for (auto f : mFans) {
ApplyFanPower(f, targetFanPower);
mLastTemperature = temp;
}
} else {
for (auto f : mFans)
f->EnforceSetValue();
BOOST_LOG_TRIVIAL(trace) << "not passed";
}
} }
void FanCurve::PrintInfo() { void FanCurve::PrintInfo() {
@@ -94,3 +107,22 @@ void FanCurve::PrintInfo() {
BOOST_LOG_TRIVIAL(info) << sStream.str(); BOOST_LOG_TRIVIAL(info) << sStream.str();
} }
bool FanCurve::ExceedsHysteresis(int temperature) {
int lowThreshold = mLastTemperature - mHystersis;
int highThreshold = mLastTemperature + mHystersis;
return temperature <= lowThreshold || temperature >= highThreshold;
}
void FanCurve::ApplyFanPower(std::shared_ptr<Fan> fan, int targetFanPower) {
BOOST_LOG_FUNCTION();
if (!fan->ZeroFanModeSupported() && fan->RPM() <= 0) {
BOOST_LOG_TRIVIAL(warning) << "Fan " << fan->toString() << " stopped completely!";
fan->PWM(fan->StartPWM());
fan->AdjustPWMLimits();
} else {
fan->PWM(targetFanPower);
}
}

View File

@@ -16,7 +16,7 @@ void FanLabeler::RunFanLabelInteraction(
cout << endl; cout << endl;
for (auto f : fans) { for (auto f : fans) {
cout << "Setting fan to max power" << endl; cout << "Setting fan " << f->toString() << " to max power" << endl;
f->PWM(100); f->PWM(100);

View File

@@ -1,3 +1,4 @@
#include <chrono>
#include <iostream> #include <iostream>
#include <ostream> #include <ostream>
#include <thread> #include <thread>
@@ -9,6 +10,7 @@
#include <pwm/PWMControl.h> #include <pwm/PWMControl.h>
#define TIMEOUT 10 #define TIMEOUT 10
#define INHIBIT_STOP_PERIOD 120
#define STEP 2 #define STEP 2
using namespace std; using namespace std;
@@ -21,10 +23,38 @@ HwmonFan::HwmonFan(std::shared_ptr<PWMControl> pwmControl,
void HwmonFan::PWM(int percent) { void HwmonFan::PWM(int percent) {
if (percent < mMinPWM) { if (percent < mMinPWM) {
mPWMControl->Power(mMinPWM); if (mZeroFanModeSupported && InhibitStopPeriodExpired()) {
SetPower(percent);
mWasStopped = true;
} else { } else {
mPWMControl->Power(percent); SetPower(mMinPWM);
} }
} else {
if (mWasStopped) {
mWasStopped = false;
mLastStartTime = chrono::steady_clock::now();
SetPower(mStartPWM);
} else {
SetPower(percent);
}
}
}
bool HwmonFan::InhibitStopPeriodExpired() {
BOOST_LOG_FUNCTION();
auto result = chrono::steady_clock::now() - mLastStartTime >
chrono::duration(chrono::seconds(INHIBIT_STOP_PERIOD));
BOOST_LOG_TRIVIAL(trace) << "Inhibit-Stop period expired:"
<< (result ? "true" : "false");
return result;
}
void HwmonFan::SetPower(int percent) {
mPWMControl->SetPower(percent);
mSetValue = percent;
} }
int HwmonFan::RPM() { return mRpmSensor->value(); } int HwmonFan::RPM() { return mRpmSensor->value(); }
@@ -99,6 +129,8 @@ void HwmonFan::AdjustPWMLimits() {
} }
} }
void HwmonFan::EnforceSetValue() { mPWMControl->SetPower(mSetValue); }
json HwmonFan::toJson() const { json HwmonFan::toJson() const {
json obj; json obj;
obj = {mPWMControl->toJson(), mRpmSensor->toJson(), obj = {mPWMControl->toJson(), mRpmSensor->toJson(),
@@ -111,6 +143,6 @@ const string HwmonFan::toString() const {
if (!mLabel.empty()) { if (!mLabel.empty()) {
return mLabel; return mLabel;
} else { } else {
return "fan:" + mPWMControl->toString(); return mPWMControl->toString();
} }
} }

View File

@@ -20,15 +20,13 @@
#include <App.h> #include <App.h>
#define PROJECT_VERSION "v0.2.1" #define PROJECT_VERSION "v0.3.0"
namespace po = boost::program_options; namespace po = boost::program_options;
namespace logging = boost::log; namespace logging = boost::log;
App app; App app;
static int doInitialSetup = 0;
void signal_handler(int s) { app.Shutdown(); } void signal_handler(int s) { app.Shutdown(); }
void InitLogging(bool verbose) { void InitLogging(bool verbose) {

View File

@@ -1,8 +1,8 @@
#include <boost/log/attributes/named_scope.hpp>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <boost/log/attributes/named_scope.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <pwm/PWMControl.h> #include <pwm/PWMControl.h>
@@ -15,19 +15,27 @@
using namespace std; using namespace std;
namespace fs = filesystem; namespace fs = filesystem;
PWMControl::PWMControl(string controlPath) PWMControl::PWMControl(string controlPath, int deviceIndex)
: mControlPath(controlPath) : mConfigPath(controlPath), mDeviceIndex(deviceIndex) {
{ auto path = fs::path{controlPath};
fs::path pathEnable(mControlPath + PWM_POSTFIX_ENABLE);
fs::path pathMode(mControlPath + PWM_POSTFIX_MODE);
mEnablePath = pathEnable; int fileCount =
mModePath = pathMode; distance(fs::directory_iterator(path), fs::directory_iterator{});
if (fileCount != 1)
throw runtime_error("More than one HWMON device present, unsupported");
for (auto de : fs::directory_iterator(path)) {
auto testPath = de.path();
mControlPath =
fs::path{de.path() / (string("pwm").append(to_string(deviceIndex)))}
.string();
}
mEnablePath = fs::path{mControlPath + PWM_POSTFIX_ENABLE}.string();
mModePath = fs::path{mControlPath + PWM_POSTFIX_MODE}.string();
ifstream istrm; ifstream istrm;
mCurrentValue = Power();
istrm.open(mEnablePath); istrm.open(mEnablePath);
istrm >> mInitialEnable; istrm >> mInitialEnable;
istrm.close(); istrm.close();
@@ -37,55 +45,44 @@ PWMControl::PWMControl(string controlPath)
istrm.close(); istrm.close();
} }
PWMControl::~PWMControl() PWMControl::~PWMControl() {
{
BOOST_LOG_FUNCTION(); BOOST_LOG_FUNCTION();
BOOST_LOG_TRIVIAL(trace) << "Cleanup"; BOOST_LOG_TRIVIAL(trace) << "Cleanup";
Reset(); Reset();
} }
void void PWMControl::SetPower(int percent) {
PWMControl::Power(int percent)
{
BOOST_LOG_FUNCTION(); BOOST_LOG_FUNCTION();
int pwmValue = (PWM_MAX_VALUE * percent) / 100; int pwmValue = (PWM_MAX_VALUE * percent) / 100;
if (percent != mCurrentValue) { if (pwmValue != CurrentPWM()) {
BOOST_LOG_TRIVIAL(trace) << "Updating control value of " << toString() BOOST_LOG_TRIVIAL(trace) << "Updating control value of " << toString()
<< " to " << percent << "% (" << pwmValue << ")"; << " to " << percent << "% (" << pwmValue << ")";
ofstream ostrm(mControlPath, ios::trunc); ofstream ostrm(mControlPath, ios::trunc);
ostrm << pwmValue; ostrm << pwmValue;
ostrm.close(); ostrm.close();
mCurrentValue = percent;
} }
} }
int int PWMControl::CurrentPWM() {
PWMControl::Power()
{
int value; int value;
ifstream istrm; ifstream istrm;
istrm.open(mControlPath); istrm.open(mControlPath);
istrm >> value; istrm >> value;
return (value * 100) / PWM_MAX_VALUE; return value;
} }
void void PWMControl::EnableManualControl() {
PWMControl::EnableManualControl()
{
ofstream ostrm(mEnablePath, ios::trunc); ofstream ostrm(mEnablePath, ios::trunc);
ostrm << static_cast<int>(PWM_ENABLE::MANUAL_CONTROL); ostrm << static_cast<int>(PWM_ENABLE::MANUAL_CONTROL);
ostrm.close(); ostrm.close();
} }
void void PWMControl::Reset() {
PWMControl::Reset()
{
ofstream ostrm(mEnablePath, ios::trunc); ofstream ostrm(mEnablePath, ios::trunc);
ostrm << mInitialEnable; ostrm << mInitialEnable;
@@ -97,15 +94,9 @@ PWMControl::Reset()
ostrm.close(); ostrm.close();
} }
const string const string PWMControl::toString() const { return fs::path(mControlPath); }
PWMControl::toString() const
{
return fs::path(mControlPath).filename();
}
json json PWMControl::toJson() const {
PWMControl::toJson() const json obj = {"PWMControl", {{"Path", mConfigPath}, {"Index", mDeviceIndex}}};
{
json obj = { "PWMControl", mControlPath };
return obj; return obj;
} }

View File

@@ -1,6 +1,7 @@
#include <filesystem> #include <filesystem>
#include <iostream> #include <iostream>
#include <regex> #include <regex>
#include <string>
#include <pwm/PWMControlFacade.h> #include <pwm/PWMControlFacade.h>
@@ -20,14 +21,20 @@ vector<shared_ptr<PWMControl>> PWMControlFacade::PWMControls() {
for (const fs::directory_entry &hwmon_device : for (const fs::directory_entry &hwmon_device :
fs::directory_iterator{HWMON_BASE_PATH}) { fs::directory_iterator{HWMON_BASE_PATH}) {
// Resolve symlink to get device path instead of hwmon path, the latter of
// which can change
fs::path actual_path =
fs::canonical(HWMON_BASE_PATH / fs::read_symlink(hwmon_device));
for (const fs::directory_entry &control : for (const fs::directory_entry &control :
fs::directory_iterator{hwmon_device}) { fs::directory_iterator{actual_path}) {
auto filename = control.path().filename().string(); auto filename = control.path().filename().string();
if (regex_match(filename, re_ctrl)) { if (regex_match(filename, re_ctrl)) {
auto controlPath = control.path().string(); auto controlIndex = filename.back() - '0';
auto controlPath = actual_path.parent_path();
controls.push_back(make_shared<PWMControl>(controlPath)); controls.push_back(make_shared<PWMControl>(controlPath, controlIndex));
} }
} }
} }

View File

@@ -12,12 +12,10 @@ using namespace std;
#define CONFIG_FILE "/etc/conf.d/sensors" #define CONFIG_FILE "/etc/conf.d/sensors"
LMSensorsFacade::LMSensorsFacade() : mConfigFile(fopen(CONFIG_FILE, "r")) { LMSensorsFacade::LMSensorsFacade() : mConfigFile(fopen(CONFIG_FILE, "r")) {
if (sensors_init(mConfigFile) != 0) { InitSensors();
throw runtime_error("Config file doesn't exist");
}
} }
LMSensorsFacade::~LMSensorsFacade() { sensors_cleanup(); } LMSensorsFacade::~LMSensorsFacade() { CleanupSensors(); }
std::vector<std::shared_ptr<Sensor>> LMSensorsFacade::TemperatureSensors() { std::vector<std::shared_ptr<Sensor>> LMSensorsFacade::TemperatureSensors() {
return Sensors<SENSORS_SUBFEATURE_TEMP_INPUT>(); return Sensors<SENSORS_SUBFEATURE_TEMP_INPUT>();
@@ -48,3 +46,16 @@ std::vector<std::shared_ptr<Sensor>> LMSensorsFacade::Sensors() {
return sensors; return sensors;
} }
void LMSensorsFacade::ReloadSensors() {
CleanupSensors();
InitSensors();
}
void LMSensorsFacade::InitSensors() {
if (sensors_init(mConfigFile) != 0) {
throw runtime_error("Config file doesn't exist");
}
}
void LMSensorsFacade::CleanupSensors() { sensors_cleanup(); }

View File

@@ -1,5 +1,8 @@
#include <sensor/SensorManager.h> #include <sensor/SensorManager.h>
#include <boost/log/attributes/named_scope.hpp>
#include <boost/log/trivial.hpp>
using namespace std; using namespace std;
SensorManager::SensorManager() SensorManager::SensorManager()
@@ -7,10 +10,17 @@ SensorManager::SensorManager()
mGPUSensorsFacade(make_unique<GPUSensorsFacade>()) {} mGPUSensorsFacade(make_unique<GPUSensorsFacade>()) {}
vector<shared_ptr<Sensor>> SensorManager::TemperatureSensors() { vector<shared_ptr<Sensor>> SensorManager::TemperatureSensors() {
BOOST_LOG_FUNCTION();
vector<shared_ptr<Sensor>> tempSensors; vector<shared_ptr<Sensor>> tempSensors;
tempSensors = mLMSensorsFacade->TemperatureSensors(); tempSensors = mLMSensorsFacade->TemperatureSensors();
BOOST_LOG_TRIVIAL(trace) << "### Temperature sensors:";
for (auto s : tempSensors) {
BOOST_LOG_TRIVIAL(trace) << s->toString();
}
// auto gpuSensors = mGPUSensorsFacade->TemperatureSensors(); // auto gpuSensors = mGPUSensorsFacade->TemperatureSensors();
// tempSensors.insert(tempSensors.end(), gpuSensors.begin(), // tempSensors.insert(tempSensors.end(), gpuSensors.begin(),
// gpuSensors.end()); // gpuSensors.end());
@@ -21,3 +31,5 @@ vector<shared_ptr<Sensor>> SensorManager::TemperatureSensors() {
vector<shared_ptr<Sensor>> SensorManager::RPMSensors() { vector<shared_ptr<Sensor>> SensorManager::RPMSensors() {
return mLMSensorsFacade->RPMSensors(); return mLMSensorsFacade->RPMSensors();
} }
void SensorManager::ReloadSensors() { mLMSensorsFacade->ReloadSensors(); }