22 Commits

Author SHA1 Message Date
33a760489e Remove NVIDIA stuff 2023-07-23 18:04:17 +02:00
10fbcdb0f6 Add missing classes 2023-03-15 15:20:35 +01:00
f383eb1b79 Add average and max aggregator functions 2023-03-15 15:16:56 +01:00
7b0b419a22 Fix crash on startup 2023-01-19 13:32:56 +01:00
ec480f5a17 Remove leftover include statement 2022-11-05 02:50:18 +01:00
0109f66be3 Remove leftover include statement 2022-11-05 02:47:44 +01:00
75d6af4c8b Remove leftover include statement 2022-11-05 02:47:13 +01:00
815b78aa67 Change required version of boost libs 2022-11-05 02:45:12 +01:00
f718f82ad1 Add option to set frequency in json 2022-10-18 11:05:05 +02:00
596a30b76a Improve logic to handle fans stopping 2022-10-10 00:25:09 +02:00
0f91960ef9 Adapt version 2022-10-06 10:47:55 +02:00
d9192f10be Add SIGTERM handling, adjust limit finding step 2022-10-06 10:39:43 +02:00
f606a1e450 Update version 2022-10-04 09:55:23 +02:00
2d744245fc Fix segmentation fault on shutdown 2022-10-04 09:53:57 +02:00
bd1695b4a7 Update version 2022-10-04 09:42:40 +02:00
987e65fd90 Add stuff to .gitignore 2022-10-04 09:42:14 +02:00
e567ede3ef Add logic to adjust minPWM on fan stop 2022-10-04 09:41:04 +02:00
d65934a278 Update version 2022-10-04 00:29:21 +02:00
46a06214a2 Fix severe bug, improve logging, handle fan stops
Conversion from power percentage to PWM value didn't take into floating
point arithmetic into account
Make log messages more helpful, add handling for fan stopping completely
2022-10-04 00:26:57 +02:00
1c2067286e Cleanup logging output 2022-10-03 14:39:09 +02:00
16c7a930c2 Update version, remove integrity check 2022-10-03 14:29:43 +02:00
95b6f248c8 Reduce file writes, add logging capability 2022-10-03 14:02:44 +02:00
25 changed files with 455 additions and 133 deletions

5
.gitignore vendored
View File

@@ -1,3 +1,8 @@
oot/
compile_commands.json
.cache/
pkg/
rel_oot/
./src
*.pkg.tar.zst
*.tar.gz

View File

@@ -1,13 +1,13 @@
pkgname=fantasize
pkgver=0.1.0
pkgver=0.2.0
pkgrel=1
pkgdesc='C++ fan control for Linux'
url='https://github.com/Tabascl/fantasize.git'
source=("$pkgname-$pkgver.tar.gz::https://github.com/Tabascl/fantasize/archive/refs/tags/v$pkgver.tar.gz")
arch=('x86_64')
license=('GPL3')
makedepends=('git' 'cmake' 'nlohmann-json' 'boost' 'cuda')
sha256sums=('69d61255edb49b66396f00b7bfadb39ce1220769838929ad74dc9f3301742ce7')
makedepends=('git' 'cmake' 'nlohmann-json' 'boost')
sha256sums=('SKIP')
build() {
cmake -S "$pkgname-$pkgver/app" -B build -DCMAKE_BUILD_TYPE=Release

View File

@@ -1,35 +1,39 @@
cmake_minimum_required(VERSION 3.0)
project(fantasize VERSION 0.1.0)
project(fantasize VERSION 0.1.8)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(nlohmann_json 3.11.2 REQUIRED)
find_package(Boost 1.80 COMPONENTS program_options REQUIRED)
find_package(Boost 1.74 COMPONENTS program_options log log_setup date_time REQUIRED)
add_executable(${PROJECT_NAME}
src/main.cxx
src/sensor/LMSensorsFacade.cxx
src/sensor/GPUSensorsFacade.cxx
# src/sensor/GPUSensorsFacade.cxx
src/sensor/Sensor.cxx
src/sensor/NvidiaSensor.cxx
# src/sensor/NvidiaSensor.cxx
src/sensor/LMSensor.cxx
src/pwm/PWMControl.cxx
src/pwm/PWMControlFacade.cxx
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
src/Controller.cxx
src/Settings.cxx
src/App.cxx
)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
target_include_directories(${PROJECT_NAME} PUBLIC include /opt/cuda)
target_link_libraries(${PROJECT_NAME} PUBLIC sensors nvidia-ml nlohmann_json::nlohmann_json tbb ${Boost_LIBRARIES})
# target_include_directories(${PROJECT_NAME} PUBLIC include /opt/cuda)
target_include_directories(${PROJECT_NAME} PUBLIC include)
# target_link_libraries(${PROJECT_NAME} PUBLIC sensors nvidia-ml nlohmann_json::nlohmann_json tbb ${Boost_LIBRARIES})
target_link_libraries(${PROJECT_NAME} PUBLIC sensors nlohmann_json::nlohmann_json tbb ${Boost_LIBRARIES})
install(TARGETS ${PROJECT_NAME} DESTINATION usr/local/bin)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/unit/fantasize.service DESTINATION usr/lib/systemd/system)

View File

@@ -26,7 +26,11 @@ private:
FanLabeler mFanLabeler;
FanGenerator mFanGenerator;
std::shared_ptr<Settings> mSettings;
std::unique_ptr<Controller> mController;
std::vector<std::shared_ptr<Fan>> mFans;
};
#endif // APP_H_

View File

@@ -5,11 +5,13 @@
#include <thread>
#include <vector>
#include <Settings.h>
#include <fan/FanCurve.h>
class Controller {
public:
Controller(std::vector<std::shared_ptr<FanCurve>> curves);
Controller(std::shared_ptr<Settings> settings,
std::vector<std::shared_ptr<FanCurve>> curves);
~Controller();
void StartFanControlLoop();
@@ -18,6 +20,8 @@ public:
private:
void Loop();
int mTimeout;
std::vector<std::shared_ptr<FanCurve>> mFanCurves;
std::atomic<bool> mRun;

View File

@@ -1,12 +1,13 @@
#ifndef SERIALIZER_H_
#define SERIALIZER_H_
#include "fan/HwmonFan.h"
#include <memory>
#include <vector>
#include <nlohmann/json.hpp>
#include <Settings.h>
#include <fan/Aggregators.h>
#include <fan/Fan.h>
#include <fan/FanCurve.h>
#include <sensor/Sensor.h>
@@ -16,19 +17,22 @@
using json = nlohmann::json;
class Serializer {
class Serializer
{
public:
Serializer();
void SerializeFans(std::vector<std::shared_ptr<Fan>> fans);
std::vector<std::shared_ptr<Fan>>
DeserializeFans(std::vector<std::shared_ptr<Sensor>> availableSensors);
std::vector<std::shared_ptr<FanCurve>>
DeserializeFanCurves(std::vector<std::shared_ptr<Sensor>> availableSensors,
std::vector<std::shared_ptr<Fan>> availableFans);
std::vector<std::shared_ptr<Fan>> DeserializeFans(
std::vector<std::shared_ptr<Sensor>> availableSensors);
std::vector<std::shared_ptr<FanCurve>> DeserializeFanCurves(
std::vector<std::shared_ptr<Sensor>> availableSensors,
std::vector<std::shared_ptr<Fan>> availableFans);
std::shared_ptr<Settings> DeserializeSettings();
private:
void WriteJson(json o);
json ReadJson();
std::unique_ptr<Aggregator> aggregatorFromString(std::string str) const;
};
#endif // SERIALIZER_H_

17
app/include/Settings.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef SETTINGS_H_
#define SETTINGS_H_
#define FREQUENCY_DEFAULT 1
class Settings {
public:
Settings(int frequency);
int Frequency() const;
private:
void LogSettings();
int mFrequency;
};
#endif // SETTINGS_H_

View File

@@ -0,0 +1,27 @@
#ifndef AGGREGATORS_H_
#define AGGREGATORS_H_
#include <sensor/Sensor.h>
class Aggregator
{
public:
virtual int aggregate(std::vector<std::shared_ptr<Sensor>> sensors) const = 0;
virtual const std::string toString() const = 0;
};
class AverageAggregator : public Aggregator
{
public:
int aggregate(std::vector<std::shared_ptr<Sensor>> sensors) const override;
const std::string toString() const override;
};
class MaxAggregator : public Aggregator
{
public:
int aggregate(std::vector<std::shared_ptr<Sensor>> sensors) const override;
const std::string toString() const override;
};
#endif // AGGERGATORS_H_

View File

@@ -10,11 +10,15 @@ public:
virtual int RPM() = 0;
virtual void Label(std::string label) = 0;
virtual void MinPWM(int value) = 0;
virtual void StartPWM(int value) = 0;
virtual void FindMinPWM() = 0;
virtual void FindStartPWM() = 0;
virtual void MinPWM(int value) = 0;
virtual int MinPWM() = 0;
virtual void StartPWM(int value) = 0;
virtual int StartPWM() = 0;
virtual void FindPWMLimits() = 0;
virtual void AdjustPWMLimits() = 0;
};
#endif // FAN_H_

View File

@@ -4,19 +4,23 @@
#include <memory>
#include <vector>
#include <fan/Aggregators.h>
#include <fan/HwmonFan.h>
#include <sensor/Sensor.h>
struct FanStep {
struct FanStep
{
int Temp;
int Percent;
};
class FanCurve {
class FanCurve
{
public:
FanCurve(std::vector<FanStep> steps,
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);
void DoFanControl();
@@ -27,6 +31,7 @@ private:
std::vector<FanStep> mSteps;
std::vector<std::shared_ptr<Sensor>> mTempSensors;
std::vector<std::shared_ptr<Fan>> mFans;
std::unique_ptr<Aggregator> mAggregator;
};
#endif // FANCURVE_H_

View File

@@ -1,7 +1,7 @@
#ifndef HWMONFAN_H_
#define HWMONFAN_H_
#include <boost/json/object.hpp>
#include <chrono>
#include <memory>
#include <fan/Fan.h>
@@ -17,11 +17,15 @@ public:
int RPM() override;
void Label(std::string label) override;
void MinPWM(int value) override;
void StartPWM(int value) override;
void FindMinPWM() override;
void FindStartPWM() override;
void MinPWM(int value) override;
int MinPWM() override;
void StartPWM(int value) override;
int StartPWM() override;
void FindPWMLimits() override;
void AdjustPWMLimits() override;
json toJson() const override;
@@ -34,6 +38,7 @@ private:
int mMinPWM;
int mStartPWM;
std::chrono::time_point<std::chrono::steady_clock> mLastAdjustmentTime;
};
#endif // HWMONFAN_H_

View File

@@ -1,7 +1,6 @@
#ifndef PWMCONTROL_H_
#define PWMCONTROL_H_
#include <boost/json/object.hpp>
#include <string>
#include <Printable.h>
@@ -16,8 +15,8 @@ public:
PWMControl(std::string controlPath);
~PWMControl();
void pwm(int percent);
int pwm();
void Power(int percent);
int Power();
void EnableManualControl();
void Reset();
@@ -27,7 +26,7 @@ public:
json toJson() const override;
private:
int readValue(std::string path);
int mCurrentValue;
std::string mControlPath;
std::string mEnablePath;

View File

@@ -5,12 +5,14 @@
using namespace std;
void App::Init() {
auto fans = mSerializer.DeserializeFans(mSensorManager.RPMSensors());
mFans = mSerializer.DeserializeFans(mSensorManager.RPMSensors());
auto fanCurves = mSerializer.DeserializeFanCurves(
mSensorManager.TemperatureSensors(), fans);
mSensorManager.TemperatureSensors(), mFans);
mController = make_unique<Controller>(fanCurves);
mSettings = mSerializer.DeserializeSettings();
mController = make_unique<Controller>(mSettings, fanCurves);
}
void App::InitialSetup() {
@@ -18,11 +20,13 @@ void App::InitialSetup() {
mPWMControlFacade.PWMControls());
std::for_each(std::execution::par, std::begin(fans), std::end(fans),
[](auto &&fan) { fan->FindMinPWM(); });
[](auto &&fan) { fan->FindPWMLimits(); });
mFanLabeler.RunFanLabelInteraction(fans);
mSerializer.SerializeFans(fans);
mFans = fans;
}
void App::NormalOperation() {
@@ -30,4 +34,8 @@ void App::NormalOperation() {
mController->StartFanControlLoop();
}
void App::Shutdown() { mController.reset(); }
void App::Shutdown() {
mSerializer.SerializeFans(mFans);
mFans.clear();
mController.reset();
}

View File

@@ -6,10 +6,10 @@
using namespace std;
#define TIMEOUT 500
Controller::Controller(vector<shared_ptr<FanCurve>> curves)
: mFanCurves(curves), mRun(false) {}
Controller::Controller(shared_ptr<Settings> settings,
vector<shared_ptr<FanCurve>> curves)
: mTimeout((1 / settings->Frequency()) * 1000), mFanCurves(curves),
mRun(false) {}
Controller::~Controller() { StopFanControlLoop(); }
@@ -32,6 +32,6 @@ void Controller::Loop() {
c->DoFanControl();
}
this_thread::sleep_for(chrono::milliseconds(TIMEOUT));
this_thread::sleep_for(chrono::milliseconds(mTimeout));
}
}

View File

@@ -22,7 +22,7 @@ FanGenerator::FindFans(vector<shared_ptr<Sensor>> rpmSensors,
cout << "Setting all fans to maximum speed" << endl;
for (auto c : pwmControls) {
c->EnableManualControl();
c->pwm(100);
c->Power(100);
}
// Wait for fans to settle
@@ -41,7 +41,7 @@ FanGenerator::FindFans(vector<shared_ptr<Sensor>> rpmSensors,
for (auto c : pwmControls) {
cout << "Setting " << c->toString()
<< " to 50% and wait for it to settle..." << endl;
c->pwm(50);
c->Power(50);
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;
c->pwm(100);
c->Power(100);
}
return mapping;

View File

@@ -1,5 +1,3 @@
#include "fan/FanCurve.h"
#include "sensor/Sensor.h"
#include <filesystem>
#include <fstream>
#include <iostream>
@@ -10,17 +8,21 @@
#include <fan/HwmonFan.h>
#include <pwm/PWMControl.h>
#include <sensor/LMSensor.h>
#include <string>
using namespace std;
namespace fs = filesystem;
Serializer::Serializer() {
Serializer::Serializer()
{
if (!fs::exists(SERIALIZATION_DIR)) {
fs::create_directory(SERIALIZATION_DIR);
}
}
void Serializer::SerializeFans(vector<shared_ptr<Fan>> fans) {
void
Serializer::SerializeFans(vector<shared_ptr<Fan>> fans)
{
json obj;
for (auto f : fans) {
@@ -31,7 +33,8 @@ void Serializer::SerializeFans(vector<shared_ptr<Fan>> fans) {
}
vector<shared_ptr<Fan>>
Serializer::DeserializeFans(vector<shared_ptr<Sensor>> availableSensors) {
Serializer::DeserializeFans(vector<shared_ptr<Sensor>> availableSensors)
{
vector<shared_ptr<Fan>> fans;
// Create a for the sensors first, then searching becomes cheaper
@@ -42,33 +45,37 @@ Serializer::DeserializeFans(vector<shared_ptr<Sensor>> availableSensors) {
auto data = ReadJson();
try {
for (auto &el : data["fans"].items()) {
for (auto& el : data["fans"].items()) {
auto pwmControl = make_shared<PWMControl>(el.value()["PWMControl"]);
auto rpmSensor = sensorMap[el.value()["LMSensor"]];
int minPWM = el.value()["MinPWM"];
int startPWM = el.value()["StartPWM"];
string label = el.value()["Label"];
auto fan = make_shared<HwmonFan>(pwmControl, rpmSensor);
fan->MinPWM(minPWM);
fan->StartPWM(startPWM);
fan->Label(label);
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;
}
@@ -76,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<shared_ptr<FanCurve>> Serializer::DeserializeFanCurves(
std::vector<std::shared_ptr<Sensor>> availableSensors,
std::vector<std::shared_ptr<Fan>> availableFans) {
vector<shared_ptr<FanCurve>>
Serializer::DeserializeFanCurves(
std::vector<std::shared_ptr<Sensor>> availableSensors,
std::vector<std::shared_ptr<Fan>> availableFans)
{
auto data = ReadJson();
map<string, shared_ptr<Sensor>> sensorMap;
@@ -98,27 +109,57 @@ vector<shared_ptr<FanCurve>> Serializer::DeserializeFanCurves(
vector<shared_ptr<FanCurve>> curves;
for (auto &el : data["fancurves"].items()) {
for (auto& el : data["fancurves"].items()) {
vector<FanStep> steps;
vector<shared_ptr<Sensor>> sensors;
vector<shared_ptr<Fan>> 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<FanCurve>(steps, sensors, fans));
std::unique_ptr<Aggregator> aggregator =
aggregatorFromString(el.value()["AggregateFunction"]);
curves.push_back(
make_shared<FanCurve>(steps, sensors, fans, std::move(aggregator)));
}
return curves;
}
std::unique_ptr<Aggregator>
Serializer::aggregatorFromString(std::string str) const
{
if (str == "max")
return std::make_unique<MaxAggregator>();
else
return std::make_unique<AverageAggregator>();
}
shared_ptr<Settings>
Serializer::DeserializeSettings()
{
int frequency = FREQUENCY_DEFAULT;
auto data = ReadJson();
if (data.contains("settings")) {
auto items = data["settings"];
if (items.contains("frequency"))
frequency = items["frequency"];
}
return make_shared<Settings>(frequency);
}

17
app/src/Settings.cxx Normal file
View File

@@ -0,0 +1,17 @@
#include <iostream>
#include <boost/log/attributes/named_scope.hpp>
#include <boost/log/trivial.hpp>
#include <Settings.h>
Settings::Settings(int frequency) : mFrequency(frequency) { LogSettings(); }
int Settings::Frequency() const { return mFrequency; }
void Settings::LogSettings() {
BOOST_LOG_FUNCTION();
BOOST_LOG_TRIVIAL(info) << "### Settings";
BOOST_LOG_TRIVIAL(info) << "Frequency: " << mFrequency << "Hz";
}

View File

@@ -0,0 +1,39 @@
#include <climits>
#include <fan/Aggregators.h>
int
AverageAggregator::aggregate(std::vector<std::shared_ptr<Sensor>> sensors) const
{
int sum = 0;
for (auto sensor : sensors) {
sum += sensor->value();
}
return sum / sensors.size();
}
const std::string
AverageAggregator::toString() const
{
return "Average";
}
int
MaxAggregator::aggregate(std::vector<std::shared_ptr<Sensor>> sensors) const
{
int max = INT_MIN;
for (auto sensor : sensors) {
if (sensor->value() > max)
max = sensor->value();
}
return max;
}
const std::string
MaxAggregator::toString() const
{
return "Max";
}

View File

@@ -1,27 +1,39 @@
#include <boost/log/attributes/named_scope.hpp>
#include <iostream>
#include <boost/log/trivial.hpp>
#include <fan/FanCurve.h>
#include <memory>
using namespace std;
FanCurve::FanCurve(std::vector<FanStep> steps,
std::vector<std::shared_ptr<Sensor>> sensors,
std::vector<std::shared_ptr<Fan>> fans)
: mSteps(steps), mTempSensors(sensors), mFans(fans) {
cout << "Initialized Fan Curve:" << endl;
std::vector<std::shared_ptr<Fan>> fans,
std::unique_ptr<Aggregator> aggregator)
: mSteps(steps)
, mTempSensors(sensors)
, mFans(fans)
, mAggregator(std::move(aggregator))
{
PrintInfo();
}
void FanCurve::DoFanControl() {
void
FanCurve::DoFanControl()
{
BOOST_LOG_FUNCTION();
int temp = AggregateTemperature();
int t0, t1, p0, p1;
int targetFanSpeed;
int targetFanPower;
if (temp <= mSteps[0].Temp) {
targetFanSpeed = mSteps[0].Percent;
targetFanPower = mSteps[0].Percent;
} else if (temp > mSteps[mSteps.size() - 1].Temp) {
targetFanSpeed = mSteps[mSteps.size() - 1].Percent;
targetFanPower = mSteps[mSteps.size() - 1].Percent;
} else {
for (int i = 0; i < mSteps.size(); i++) {
if (temp > mSteps[i].Temp) {
@@ -33,47 +45,61 @@ void FanCurve::DoFanControl() {
}
}
targetFanSpeed = p0 + ((p1 - p0) / (t1 - t0)) * (temp - t0);
targetFanPower = p0 + ((p1 - p0) / (t1 - t0)) * (temp - t0);
}
for (auto f : mFans) {
f->PWM(targetFanSpeed);
if (f->RPM() <= 0) {
BOOST_LOG_TRIVIAL(warning) << "Fan stopped completely!";
f->PWM(f->StartPWM());
f->AdjustPWMLimits();
} else {
f->PWM(targetFanPower);
}
}
}
// 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:";
stringstream sStream;
cout << "Steps: ";
sStream << "Steps: ";
for (auto s : mSteps) {
sStream << "[ " << s.Temp << "C, " << s.Percent << "% ] ";
}
cout << sStream.str() << endl;
BOOST_LOG_TRIVIAL(info) << sStream.str();
sStream.str(string());
cout << "Sensors: ";
sStream << "Sensors: ";
for (auto s : mTempSensors) {
sStream << s->toString() << ", ";
}
cout << sStream.str() << endl;
BOOST_LOG_TRIVIAL(info) << sStream.str();
sStream.str(string());
cout << "Fans: ";
sStream << "Fans: ";
for (auto s : mFans) {
sStream << s->toString() << ", ";
}
cout << sStream.str() << endl;
BOOST_LOG_TRIVIAL(info) << sStream.str();
sStream.str(string());
sStream << "Aggregate function: " << mAggregator->toString();
BOOST_LOG_TRIVIAL(info) << sStream.str();
}

View File

@@ -1,13 +1,15 @@
#include <chrono>
#include <iostream>
#include <ostream>
#include <thread>
#include "pwm/PWMControl.h"
#include <boost/json/object.hpp>
#include <fan/HwmonFan.h>
#include <boost/log/attributes/named_scope.hpp>
#include <boost/log/trivial.hpp>
#define TIMEOUT 5
#include <fan/HwmonFan.h>
#include <pwm/PWMControl.h>
#define TIMEOUT 10
#define STEP 2
using namespace std;
@@ -19,9 +21,9 @@ HwmonFan::HwmonFan(std::shared_ptr<PWMControl> pwmControl,
void HwmonFan::PWM(int percent) {
if (percent < mMinPWM) {
mPWMControl->pwm(mMinPWM);
mPWMControl->Power(mMinPWM);
} else {
mPWMControl->pwm(percent);
mPWMControl->Power(percent);
}
}
@@ -31,41 +33,73 @@ void HwmonFan::Label(std::string label) { mLabel = label; }
void HwmonFan::MinPWM(int value) { mMinPWM = value; }
int HwmonFan::MinPWM() { return mMinPWM; }
void HwmonFan::StartPWM(int value) { mStartPWM = value; }
void HwmonFan::FindMinPWM() {
int HwmonFan::StartPWM() { return mStartPWM; }
void HwmonFan::FindPWMLimits() {
cout << "Looking for minimal PWM" << endl;
int minPWM = 0;
mMinPWM = 0;
mStartPWM = 0;
for (int curPWM = 100; curPWM > 0; curPWM -= 5) {
for (int curPWM = 100; curPWM > 0; curPWM -= STEP) {
PWM(curPWM);
this_thread::sleep_for(chrono::seconds(TIMEOUT));
int curRPM = RPM();
if (curRPM <= 0) {
minPWM = curPWM + 5;
if (RPM() <= 0) {
minPWM = curPWM + STEP;
break;
}
}
cout << "Setting minimal PWM: " << minPWM << endl;
mMinPWM = minPWM;
if (minPWM == 0) {
cout << "Fan never stopped. ";
}
cout << "Setting minimal PWM: " << minPWM << endl;
} else {
int startPWM = 0;
mMinPWM = minPWM;
cout << "Looking for start PWM!" << endl;
for (int curPWM = minPWM - STEP; curPWM < 100; curPWM += STEP) {
PWM(curPWM);
this_thread::sleep_for(chrono::seconds(TIMEOUT));
if (RPM() > 0) {
cout << "Setting start PWM: " << startPWM << endl;
startPWM = curPWM;
break;
}
}
mStartPWM = startPWM;
}
}
void HwmonFan::FindStartPWM() {}
void HwmonFan::AdjustPWMLimits() {
BOOST_LOG_FUNCTION()
chrono::time_point now = chrono::steady_clock::now();
if ((now - mLastAdjustmentTime) >
chrono::duration(chrono::seconds(TIMEOUT))) {
BOOST_LOG_TRIVIAL(info) << "Increasing minimal fan speed";
mLastAdjustmentTime = now;
mMinPWM += 2;
}
}
json HwmonFan::toJson() const {
json obj;
obj = {mPWMControl->toJson(),
mRpmSensor->toJson(),
{"Label", mLabel},
{"MinPWM", mMinPWM}};
{"MinPWM", mMinPWM},
{"StartPWM", mStartPWM}};
return obj;
}

View File

@@ -1,15 +1,29 @@
#include <csignal>
#include <iostream>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/log/attributes/named_scope.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/expressions/formatters/named_scope.hpp>
#include <boost/log/expressions/message.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/program_options.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/value_semantic.hpp>
#include <boost/program_options/variables_map.hpp>
#include <csignal>
#include <iostream>
#include <boost/program_options.hpp>
#include <App.h>
#define PROJECT_VERSION "v0.2.0"
namespace po = boost::program_options;
namespace logging = boost::log;
App app;
@@ -17,18 +31,54 @@ static int doInitialSetup = 0;
void signal_handler(int s) { app.Shutdown(); }
void InitLogging(bool verbose) {
logging::add_console_log(
std::clog,
logging::keywords::format =
(logging::expressions::stream
<< "["
<< logging::expressions::format_date_time<boost::posix_time::ptime>(
"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());
BOOST_LOG_FUNCTION();
if (!verbose) {
logging::core::get()->set_filter(logging::trivial::severity >=
logging::trivial::info);
} else {
BOOST_LOG_TRIVIAL(info) << "Verbose logging enabled";
}
}
int main(int argc, char **argv) {
BOOST_LOG_FUNCTION()
BOOST_LOG_TRIVIAL(info) << "Version: " << PROJECT_VERSION;
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
po::options_description desc("Allowed options");
desc.add_options()("help", "produce help message")("setup", po::bool_switch(),
"run initial setup");
desc.add_options()("help,h", "produce help message")(
"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);
po::notify(vm);
try {
InitLogging(vm["verbose"].as<bool>());
if (vm.count("help")) {
std::cout << desc << "\n";
return 0;

View File

@@ -1,8 +1,10 @@
#include <boost/json/object.hpp>
#include <boost/log/attributes/named_scope.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <boost/log/trivial.hpp>
#include <pwm/PWMControl.h>
#define PWM_POSTFIX_ENABLE "_enable"
@@ -13,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);
@@ -22,6 +26,8 @@ PWMControl::PWMControl(string controlPath) : mControlPath(controlPath) {
ifstream istrm;
mCurrentValue = Power();
istrm.open(mEnablePath);
istrm >> mInitialEnable;
istrm.close();
@@ -31,36 +37,55 @@ PWMControl::PWMControl(string controlPath) : mControlPath(controlPath) {
istrm.close();
}
PWMControl::~PWMControl() {
cout << "Cleanup" << endl;
PWMControl::~PWMControl()
{
BOOST_LOG_FUNCTION();
BOOST_LOG_TRIVIAL(trace) << "Cleanup";
Reset();
}
void PWMControl::pwm(int percent) {
int pwmValue = PWM_MAX_VALUE * percent / 100;
void
PWMControl::Power(int percent)
{
BOOST_LOG_FUNCTION();
ofstream ostrm(mControlPath, ios::trunc);
ostrm << pwmValue;
ostrm.close();
int pwmValue = (PWM_MAX_VALUE * percent) / 100;
if (percent != mCurrentValue) {
BOOST_LOG_TRIVIAL(trace) << "Updating control value of " << toString()
<< " to " << percent << "% (" << pwmValue << ")";
ofstream ostrm(mControlPath, ios::trunc);
ostrm << pwmValue;
ostrm.close();
mCurrentValue = percent;
}
}
int PWMControl::pwm() {
int
PWMControl::Power()
{
int value;
ifstream istrm;
istrm.open(mControlPath);
istrm >> value;
return value;
return (value * 100) / PWM_MAX_VALUE;
}
void PWMControl::EnableManualControl() {
void
PWMControl::EnableManualControl()
{
ofstream ostrm(mEnablePath, ios::trunc);
ostrm << static_cast<int>(PWM_ENABLE::MANUAL_CONTROL);
ostrm.close();
}
void PWMControl::Reset() {
void
PWMControl::Reset()
{
ofstream ostrm(mEnablePath, ios::trunc);
ostrm << mInitialEnable;
@@ -72,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;
}

View File

@@ -1,4 +1,3 @@
#include <boost/json/object.hpp>
#include <include/nvml.h>
#include <sensor/NvidiaSensor.h>

View File

@@ -11,8 +11,9 @@ vector<shared_ptr<Sensor>> SensorManager::TemperatureSensors() {
tempSensors = mLMSensorsFacade->TemperatureSensors();
auto gpuSensors = mGPUSensorsFacade->TemperatureSensors();
tempSensors.insert(tempSensors.end(), gpuSensors.begin(), gpuSensors.end());
// auto gpuSensors = mGPUSensorsFacade->TemperatureSensors();
// tempSensors.insert(tempSensors.end(), gpuSensors.begin(),
// gpuSensors.end());
return tempSensors;
}

View File

@@ -7,4 +7,4 @@ ExecStart=/usr/local/bin/fantasize
Restart=always
[Install]
WantedBy=multi-user.target
WantedBy=graphical.target