diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index f3cb0ce..a9dde3b 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -22,6 +22,8 @@ add_executable(app src/FanGenerator.cxx src/Serializer.cxx src/sensor/SensorManager.cxx + src/Controller.cxx + src/App.cxx ) set_property(TARGET app PROPERTY CXX_STANDARD 20) diff --git a/app/include/App.h b/app/include/App.h new file mode 100644 index 0000000..5e656d9 --- /dev/null +++ b/app/include/App.h @@ -0,0 +1,32 @@ +#ifndef APP_H_ +#define APP_H_ + +#include + +#include +#include +#include +#include +#include +#include + +class App { +public: + void Init(); + + void InitialSetup(); + void NormalOperation(); + + void Shutdown(); + +private: + SensorManager mSensorManager; + Serializer mSerializer; + PWMControlFacade mPWMControlFacade; + FanLabeler mFanLabeler; + FanGenerator mFanGenerator; + + std::unique_ptr mController; +}; + +#endif // APP_H_ diff --git a/app/include/Controller.h b/app/include/Controller.h new file mode 100644 index 0000000..54896fb --- /dev/null +++ b/app/include/Controller.h @@ -0,0 +1,27 @@ +#ifndef CONTROLLER_H_ +#define CONTROLLER_H_ + +#include +#include +#include + +#include + +class Controller { +public: + Controller(std::vector> curves); + ~Controller(); + + void StartFanControlLoop(); + void StopFanControlLoop(); + +private: + void Loop(); + + std::vector> mFanCurves; + std::atomic mRun; + + std::unique_ptr mWorker; +}; + +#endif // CONTROLLER_H_ diff --git a/app/include/fan/FanCurve.h b/app/include/fan/FanCurve.h index 3cbc675..505de1a 100644 --- a/app/include/fan/FanCurve.h +++ b/app/include/fan/FanCurve.h @@ -22,6 +22,7 @@ public: private: int AggregateTemperature(); + void PrintInfo(); std::vector mSteps; std::vector> mTempSensors; diff --git a/app/src/App.cxx b/app/src/App.cxx new file mode 100644 index 0000000..dfdd308 --- /dev/null +++ b/app/src/App.cxx @@ -0,0 +1,33 @@ +#include + +#include + +using namespace std; + +void App::Init() { + auto fans = mSerializer.DeserializeFans(mSensorManager.RPMSensors()); + + auto fanCurves = mSerializer.DeserializeFanCurves( + mSensorManager.TemperatureSensors(), fans); + + mController = make_unique(fanCurves); +} + +void App::InitialSetup() { + auto fans = mFanGenerator.FindFans(mSensorManager.RPMSensors(), + mPWMControlFacade.PWMControls()); + + std::for_each(std::execution::par, std::begin(fans), std::end(fans), + [](auto &&fan) { fan->FindMinPWM(); }); + + mFanLabeler.RunFanLabelInteraction(fans); + + mSerializer.SerializeFans(fans); +} + +void App::NormalOperation() { + if (mController) + mController->StartFanControlLoop(); +} + +void App::Shutdown() { mController.reset(); } diff --git a/app/src/Controller.cxx b/app/src/Controller.cxx new file mode 100644 index 0000000..e3adbc8 --- /dev/null +++ b/app/src/Controller.cxx @@ -0,0 +1,37 @@ +#include +#include + +#include +#include + +using namespace std; + +#define TIMEOUT 500 + +Controller::Controller(vector> curves) + : mFanCurves(curves), mRun(false) {} + +Controller::~Controller() { StopFanControlLoop(); } + +void Controller::StartFanControlLoop() { + mRun = true; + Loop(); + // mWorker = make_unique(&Controller::Loop, this); +} + +void Controller::StopFanControlLoop() { + mRun = false; + // if (mWorker->joinable()) + // mWorker->join(); + // mWorker.reset(); +} + +void Controller::Loop() { + while (mRun) { + for (auto c : mFanCurves) { + c->DoFanControl(); + } + + this_thread::sleep_for(chrono::milliseconds(TIMEOUT)); + } +} diff --git a/app/src/Controller.hxx b/app/src/Controller.hxx deleted file mode 100644 index 25e6a8d..0000000 --- a/app/src/Controller.hxx +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CONTROLLER_H_ -#define CONTROLLER_H_ - -class Controller { -public: -}; - -#endif // CONTROLLER_H_ diff --git a/app/src/Serializer.cxx b/app/src/Serializer.cxx index 59c2a02..ca6c36a 100644 --- a/app/src/Serializer.cxx +++ b/app/src/Serializer.cxx @@ -32,7 +32,7 @@ void Serializer::SerializeFans(vector> fans) { vector> Serializer::DeserializeFans(vector> availableSensors) { - vector> mapping; + vector> fans; // Create a for the sensors first, then searching becomes cheaper map> sensorMap; @@ -49,12 +49,16 @@ Serializer::DeserializeFans(vector> availableSensors) { int minPWM = el.value()["MinPWM"]; string label = el.value()["Label"]; - mapping.push_back(make_shared(pwmControl, rpmSensor)); + auto fan = make_shared(pwmControl, rpmSensor); + fan->MinPWM(minPWM); + fan->Label(label); + + fans.push_back(fan); } } catch (const std::exception &e) { std::cout << "Deserialization error! Message: " << e.what() << std::endl; } - return mapping; + return fans; } void Serializer::WriteJson(json o) { @@ -100,15 +104,17 @@ vector> Serializer::DeserializeFanCurves( vector> fans; for (auto &step : el.value()["FanSteps"].items()) { - FanStep fanStep{step.value()[0], step.value()[1]}; + steps.push_back(FanStep{step.value()[0], step.value()[1]}); } for (auto &sensor : el.value()["Sensors"].items()) { - sensors.push_back(sensorMap[sensor.value()]); + if (sensorMap.contains(sensor.value())) + sensors.push_back(sensorMap[sensor.value()]); } for (auto &fan : el.value()["Fans"].items()) { - fans.push_back(fanMap[fan.value()]); + if (fanMap.contains(fan.value())) + fans.push_back(fanMap[fan.value()]); } curves.push_back(make_shared(steps, sensors, fans)); diff --git a/app/src/fan/FanCurve.cxx b/app/src/fan/FanCurve.cxx index c03bc7b..53811ae 100644 --- a/app/src/fan/FanCurve.cxx +++ b/app/src/fan/FanCurve.cxx @@ -1,25 +1,28 @@ -#include +#include -#include +#include using namespace std; FanCurve::FanCurve(std::vector steps, std::vector> sensors, std::vector> fans) - : mSteps(steps), mTempSensors(sensors), mFans(fans) {} + : mSteps(steps), mTempSensors(sensors), mFans(fans) { + cout << "Initialized Fan Curve:" << endl; + PrintInfo(); +} void FanCurve::DoFanControl() { int temp = AggregateTemperature(); + cout << "Temp: " << temp << "C" << endl; int t0, t1, p0, p1; + int targetFanSpeed; if (temp <= mSteps[0].Temp) { - t0 = t1 = mSteps[0].Temp; - p0 = p1 = mSteps[0].Percent; + targetFanSpeed = mSteps[0].Percent; } else if (temp > mSteps[mSteps.size() - 1].Temp) { - t0 = t1 = mSteps[mSteps.size() - 1].Temp; - p0 = p1 = mSteps[mSteps.size() - 1].Percent; + targetFanSpeed = mSteps[mSteps.size() - 1].Percent; } else { for (int i = 0; i < mSteps.size(); i++) { if (temp > mSteps[i].Temp) { @@ -30,9 +33,11 @@ void FanCurve::DoFanControl() { p1 = mSteps[i + 1].Percent; } } + + targetFanSpeed = p0 + ((p1 - p0) / (t1 - t0)) * (temp - t0); } - int targetFanSpeed = p0 + ((p1 - p0) / (t1 - t0)) * (temp - t0); + cout << "Power: " << targetFanSpeed << "%" << endl; for (auto f : mFans) { f->PWM(targetFanSpeed); @@ -41,10 +46,37 @@ void FanCurve::DoFanControl() { // Dummy Implementation using AVG int FanCurve::AggregateTemperature() { - int sum; + int sum = 0; for (auto s : mTempSensors) { sum += s->value(); } return sum / mTempSensors.size(); } + +void FanCurve::PrintInfo() { + stringstream sStream; + cout << "Steps: "; + for (auto s : mSteps) { + sStream << "[ " << s.Temp << "C, " << s.Percent << "% ] "; + } + cout << sStream.str() << endl; + + sStream.str(string()); + + cout << "Sensors: "; + for (auto s : mTempSensors) { + sStream << s->toString() << ", "; + } + + cout << sStream.str() << endl; + + sStream.str(string()); + + cout << "Fans: "; + for (auto s : mFans) { + sStream << s->toString() << ", "; + } + + cout << sStream.str() << endl; +} diff --git a/app/src/fan/HwmonFan.cxx b/app/src/fan/HwmonFan.cxx index 66ea001..0ccd483 100644 --- a/app/src/fan/HwmonFan.cxx +++ b/app/src/fan/HwmonFan.cxx @@ -70,6 +70,9 @@ json HwmonFan::toJson() const { } const string HwmonFan::toString() const { - return "Fan!\nPWMControl: " + mPWMControl->toString() + - "\nRpmSensor: " + mRpmSensor->toString(); + if (!mLabel.empty()) { + return mLabel; + } else { + return "fan:" + mPWMControl->toString(); + } } diff --git a/app/src/main.cxx b/app/src/main.cxx index 4524279..3bcc8dd 100644 --- a/app/src/main.cxx +++ b/app/src/main.cxx @@ -1,40 +1,22 @@ -#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include + +App app; + +void signal_handler(int s) { app.Shutdown(); } int main() { - SensorManager sensorManager; - auto pwmSensors = sensorManager.RPMSensors(); - auto tempSensors = sensorManager.TemperatureSensors(); + signal(SIGINT, signal_handler); - PWMControlFacade pwmControlFacade; - auto controls = pwmControlFacade.PWMControls(); - - FanGenerator m; - Serializer s; - - std::vector> fans; - - // fans = m.FindFans(pwmSensors, controls); - // s.SerializeFans(fans); - fans = s.DeserializeFans(pwmSensors); - - std::for_each(std::execution::par, std::begin(fans), std::end(fans), - [](auto &&f) { f->FindMinPWM(); }); - - // auto curves = s.DeserializeFanCurves(tempSensors, fans); - FanLabeler labeler; - labeler.RunFanLabelInteraction(fans); - - s.SerializeFans(fans); + try { + app.Init(); + app.NormalOperation(); + } catch (const std::exception &e) { + std::cout << "An exception was caught: " << e.what() << std::endl; + } + app.Shutdown(); return 0; } diff --git a/app/src/sensor/NvidiaSensor.cxx b/app/src/sensor/NvidiaSensor.cxx index d1ad2d3..9709ce0 100644 --- a/app/src/sensor/NvidiaSensor.cxx +++ b/app/src/sensor/NvidiaSensor.cxx @@ -19,7 +19,7 @@ int NvidiaSensor::value() { return static_cast(temp); } -const std::string NvidiaSensor::toString() const { return "Nvidia GPU"; } +const std::string NvidiaSensor::toString() const { return "NvidiaGPU"; } json NvidiaSensor::toJson() const { json obj = {"NvidiaSensor", toString()};