diff --git a/PKGBUILD b/PKGBUILD index f02bb0a..5746709 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,5 +1,5 @@ pkgname=fantasize -pkgver=0.1.8 +pkgver=0.1.9 pkgrel=1 pkgdesc='C++ fan control for Linux' url='https://github.com/Tabascl/fantasize.git' diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 8d3e8be..b2f174d 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(${PROJECT_NAME} src/fan/HwmonFan.cxx src/fan/FanCurve.cxx src/fan/FanLabeler.cxx + src/fan/Aggregators.cxx src/FanGenerator.cxx src/Serializer.cxx src/sensor/SensorManager.cxx diff --git a/app/include/Serializer.h b/app/include/Serializer.h index aa1865c..6af9dcd 100644 --- a/app/include/Serializer.h +++ b/app/include/Serializer.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -16,20 +17,22 @@ using json = nlohmann::json; -class Serializer { +class Serializer +{ public: Serializer(); void SerializeFans(std::vector> fans); - std::vector> - DeserializeFans(std::vector> availableSensors); - std::vector> - DeserializeFanCurves(std::vector> availableSensors, - std::vector> availableFans); + std::vector> DeserializeFans( + std::vector> availableSensors); + std::vector> DeserializeFanCurves( + std::vector> availableSensors, + std::vector> availableFans); std::shared_ptr DeserializeSettings(); private: void WriteJson(json o); json ReadJson(); + std::unique_ptr aggregatorFromString(std::string str) const; }; #endif // SERIALIZER_H_ diff --git a/app/include/fan/FanCurve.h b/app/include/fan/FanCurve.h index 505de1a..a4cd045 100644 --- a/app/include/fan/FanCurve.h +++ b/app/include/fan/FanCurve.h @@ -4,19 +4,23 @@ #include #include +#include #include #include -struct FanStep { +struct FanStep +{ int Temp; int Percent; }; -class FanCurve { +class FanCurve +{ public: FanCurve(std::vector steps, std::vector> sensors, - std::vector> fans); + std::vector> fans, + std::unique_ptr aggregator); void DoFanControl(); @@ -27,6 +31,7 @@ private: std::vector mSteps; std::vector> mTempSensors; std::vector> mFans; + std::unique_ptr mAggregator; }; #endif // FANCURVE_H_ diff --git a/app/src/Serializer.cxx b/app/src/Serializer.cxx index 8f0cbf9..9c18384 100644 --- a/app/src/Serializer.cxx +++ b/app/src/Serializer.cxx @@ -1,4 +1,3 @@ -#include "Settings.h" #include #include #include @@ -9,17 +8,21 @@ #include #include #include +#include using namespace std; namespace fs = filesystem; -Serializer::Serializer() { +Serializer::Serializer() +{ if (!fs::exists(SERIALIZATION_DIR)) { fs::create_directory(SERIALIZATION_DIR); } } -void Serializer::SerializeFans(vector> fans) { +void +Serializer::SerializeFans(vector> fans) +{ json obj; for (auto f : fans) { @@ -30,7 +33,8 @@ void Serializer::SerializeFans(vector> fans) { } vector> -Serializer::DeserializeFans(vector> availableSensors) { +Serializer::DeserializeFans(vector> availableSensors) +{ vector> fans; // Create a for the sensors first, then searching becomes cheaper @@ -41,7 +45,7 @@ Serializer::DeserializeFans(vector> availableSensors) { auto data = ReadJson(); try { - for (auto &el : data["fans"].items()) { + for (auto& el : data["fans"].items()) { auto pwmControl = make_shared(el.value()["PWMControl"]); auto rpmSensor = sensorMap[el.value()["LMSensor"]]; @@ -56,20 +60,22 @@ Serializer::DeserializeFans(vector> availableSensors) { fans.push_back(fan); } - } catch (const std::exception &e) { + } catch (const std::exception& e) { std::cout << "Deserialization error! Message: " << e.what() << std::endl; } return fans; } -void Serializer::WriteJson(json o) { +void +Serializer::WriteJson(json o) +{ json obj; if (fs::exists(fs::path(SERIALIZATION_DIR) / FANS_JSON_FILENAME)) { obj = ReadJson(); } - for (auto &[key, value] : o.items()) { + for (auto& [key, value] : o.items()) { obj[key] = value; } @@ -77,14 +83,18 @@ void Serializer::WriteJson(json o) { ostrm << obj.dump(2) << "\n"; } -json Serializer::ReadJson() { +json +Serializer::ReadJson() +{ ifstream istrm(fs::path(SERIALIZATION_DIR) / FANS_JSON_FILENAME); return json::parse(istrm); } -vector> Serializer::DeserializeFanCurves( - std::vector> availableSensors, - std::vector> availableFans) { +vector> +Serializer::DeserializeFanCurves( + std::vector> availableSensors, + std::vector> availableFans) +{ auto data = ReadJson(); map> sensorMap; @@ -99,32 +109,47 @@ vector> Serializer::DeserializeFanCurves( vector> curves; - for (auto &el : data["fancurves"].items()) { + for (auto& el : data["fancurves"].items()) { vector steps; vector> sensors; vector> fans; - for (auto &step : el.value()["FanSteps"].items()) { - steps.push_back(FanStep{step.value()[0], step.value()[1]}); + for (auto& step : el.value()["FanSteps"].items()) { + steps.push_back(FanStep{ step.value()[0], step.value()[1] }); } - for (auto &sensor : el.value()["Sensors"].items()) { + for (auto& sensor : el.value()["Sensors"].items()) { if (sensorMap.contains(sensor.value())) sensors.push_back(sensorMap[sensor.value()]); } - for (auto &fan : el.value()["Fans"].items()) { + for (auto& fan : el.value()["Fans"].items()) { if (fanMap.contains(fan.value())) fans.push_back(fanMap[fan.value()]); } - curves.push_back(make_shared(steps, sensors, fans)); + std::unique_ptr aggregator = + aggregatorFromString(el.value()["AggregateFunction"]); + + curves.push_back( + make_shared(steps, sensors, fans, std::move(aggregator))); } return curves; } -shared_ptr Serializer::DeserializeSettings() { +std::unique_ptr +Serializer::aggregatorFromString(std::string str) const +{ + if (str == "max") + return std::make_unique(); + else + return std::make_unique(); +} + +shared_ptr +Serializer::DeserializeSettings() +{ int frequency = FREQUENCY_DEFAULT; auto data = ReadJson(); diff --git a/app/src/fan/FanCurve.cxx b/app/src/fan/FanCurve.cxx index e7067f3..70ad8f2 100644 --- a/app/src/fan/FanCurve.cxx +++ b/app/src/fan/FanCurve.cxx @@ -4,17 +4,25 @@ #include #include +#include using namespace std; FanCurve::FanCurve(std::vector steps, std::vector> sensors, - std::vector> fans) - : mSteps(steps), mTempSensors(sensors), mFans(fans) { + std::vector> fans, + std::unique_ptr aggregator) + : mSteps(steps) + , mTempSensors(sensors) + , mFans(fans) + , mAggregator(std::move(aggregator)) +{ PrintInfo(); } -void FanCurve::DoFanControl() { +void +FanCurve::DoFanControl() +{ BOOST_LOG_FUNCTION(); int temp = AggregateTemperature(); @@ -51,17 +59,15 @@ void FanCurve::DoFanControl() { } } -// Dummy Implementation using AVG -int FanCurve::AggregateTemperature() { - int sum = 0; - for (auto s : mTempSensors) { - sum += s->value(); - } - - return sum / mTempSensors.size(); +int +FanCurve::AggregateTemperature() +{ + return mAggregator->aggregate(mTempSensors); } -void FanCurve::PrintInfo() { +void +FanCurve::PrintInfo() +{ BOOST_LOG_FUNCTION() BOOST_LOG_TRIVIAL(info) << "### Fan curve:"; @@ -90,4 +96,10 @@ void FanCurve::PrintInfo() { } BOOST_LOG_TRIVIAL(info) << sStream.str(); + + sStream.str(string()); + + sStream << "Aggregate function: " << mAggregator->toString(); + + BOOST_LOG_TRIVIAL(info) << sStream.str(); } diff --git a/app/src/main.cxx b/app/src/main.cxx index bd8de33..e9cbc4b 100644 --- a/app/src/main.cxx +++ b/app/src/main.cxx @@ -20,7 +20,7 @@ #include -#define PROJECT_VERSION "v0.1.8" +#define PROJECT_VERSION "v0.1.9" namespace po = boost::program_options; namespace logging = boost::log; @@ -29,26 +29,32 @@ 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) +{ logging::add_console_log( - std::clog, - logging::keywords::format = - (logging::expressions::stream - << "[" - << logging::expressions::format_date_time( - "TimeStamp", "%Y-%m-%d %H:%M:%S") - << "][" - << logging::expressions::format_named_scope( - "Scope", logging::keywords::format = "%c") - << "]" - << "[" << logging::trivial::severity << "] " - << logging::expressions::smessage)); + std::clog, + logging::keywords::format = + (logging::expressions::stream + << "[" + << logging::expressions::format_date_time( + "TimeStamp", "%Y-%m-%d %H:%M:%S") + << "][" + << logging::expressions::format_named_scope( + "Scope", logging::keywords::format = "%c") + << "]" + << "[" << logging::trivial::severity << "] " + << logging::expressions::smessage)); logging::add_common_attributes(); logging::core::get()->add_global_attribute( - "Scope", logging::attributes::named_scope()); + "Scope", logging::attributes::named_scope()); BOOST_LOG_FUNCTION(); @@ -60,7 +66,9 @@ void InitLogging(bool verbose) { } } -int main(int argc, char **argv) { +int +main(int argc, char** argv) +{ BOOST_LOG_FUNCTION() BOOST_LOG_TRIVIAL(info) << "Version: " << PROJECT_VERSION; @@ -69,8 +77,8 @@ int main(int argc, char **argv) { po::options_description desc("Allowed options"); desc.add_options()("help,h", "produce help message")( - "setup,s", po::bool_switch(), - "run initial setup")("verbose,v", po::bool_switch(), "print debug info"); + "setup,s", po::bool_switch(), "run initial setup")( + "verbose,v", po::bool_switch(), "print debug info"); po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -90,7 +98,7 @@ int main(int argc, char **argv) { app.Init(); app.NormalOperation(); } - } catch (const std::exception &e) { + } catch (const std::exception& e) { std::cout << "An exception was caught: " << e.what() << std::endl; } diff --git a/app/src/pwm/PWMControl.cxx b/app/src/pwm/PWMControl.cxx index dea443b..395b66f 100644 --- a/app/src/pwm/PWMControl.cxx +++ b/app/src/pwm/PWMControl.cxx @@ -15,7 +15,9 @@ using namespace std; namespace fs = filesystem; -PWMControl::PWMControl(string controlPath) : mControlPath(controlPath) { +PWMControl::PWMControl(string controlPath) + : mControlPath(controlPath) +{ fs::path pathEnable(mControlPath + PWM_POSTFIX_ENABLE); fs::path pathMode(mControlPath + PWM_POSTFIX_MODE); @@ -35,21 +37,24 @@ PWMControl::PWMControl(string controlPath) : mControlPath(controlPath) { istrm.close(); } -PWMControl::~PWMControl() { +PWMControl::~PWMControl() +{ BOOST_LOG_FUNCTION(); BOOST_LOG_TRIVIAL(trace) << "Cleanup"; Reset(); } -void PWMControl::Power(int percent) { +void +PWMControl::Power(int percent) +{ BOOST_LOG_FUNCTION(); int pwmValue = (PWM_MAX_VALUE * percent) / 100; if (percent != mCurrentValue) { - BOOST_LOG_TRIVIAL(trace) - << "Updating control value to " << percent << "% (" << pwmValue << ")"; + BOOST_LOG_TRIVIAL(trace) << "Updating control value of " << toString() + << " to " << percent << "% (" << pwmValue << ")"; ofstream ostrm(mControlPath, ios::trunc); ostrm << pwmValue; ostrm.close(); @@ -58,7 +63,9 @@ void PWMControl::Power(int percent) { } } -int PWMControl::Power() { +int +PWMControl::Power() +{ int value; ifstream istrm; @@ -68,13 +75,17 @@ int PWMControl::Power() { return (value * 100) / PWM_MAX_VALUE; } -void PWMControl::EnableManualControl() { +void +PWMControl::EnableManualControl() +{ ofstream ostrm(mEnablePath, ios::trunc); ostrm << static_cast(PWM_ENABLE::MANUAL_CONTROL); ostrm.close(); } -void PWMControl::Reset() { +void +PWMControl::Reset() +{ ofstream ostrm(mEnablePath, ios::trunc); ostrm << mInitialEnable; @@ -86,11 +97,15 @@ void PWMControl::Reset() { ostrm.close(); } -const string PWMControl::toString() const { +const string +PWMControl::toString() const +{ return fs::path(mControlPath).filename(); } -json PWMControl::toJson() const { - json obj = {"PWMControl", mControlPath}; +json +PWMControl::toJson() const +{ + json obj = { "PWMControl", mControlPath }; return obj; }