diff --git a/app/Command/Daemon.php b/app/Command/Daemon.php new file mode 100644 index 0000000000000000000000000000000000000000..06fc36715f5fee73228c6c0789f49547b042b757 --- /dev/null +++ b/app/Command/Daemon.php @@ -0,0 +1,51 @@ +<?php + +namespace App\Command; + +use App\Application; +use GetOpt\GetOpt; +use Hugga\Console; + +class Daemon extends AbstractCommand +{ + protected $name = 'daemon'; + + protected $description = 'Run the monitoring and control the fans'; + + public function __construct(Application $app, Console $console) + { + parent::__construct($app, $console); + } + + public function handle(GetOpt $getOpt): int + { + if (posix_getuid() !== 0) { + $this->warn('This programm has to run as root'); + return 1; + } + $fanConfig = $this->app->fanConfig; + try { + $fanConfig->readConfig(); + } catch (\Throwable $e) { + $this->error('Unable to read config: ' . $e->getMessage()); + return 2; + } + if (!$fanConfig->hasFans()) { + $this->error('No fans configured. Run config first'); + return 3; + } + + // @todo check that the fans are not in manual controll already + + // prepare + $rules = $fanConfig->getRules(); + + // main loop + while (true) { + foreach ($rules as $rule) { + $rule->apply($this->console); + } + sleep(1); + } + } +} diff --git a/app/FanConfig.php b/app/FanConfig.php index e9760eb00bd321c1dcb4589e081a18b23729e11b..57d16037e5bfd27316b6dd40de25d89eb5be17a7 100644 --- a/app/FanConfig.php +++ b/app/FanConfig.php @@ -48,6 +48,18 @@ class FanConfig return $this->fans; } + public function getSensors(): array + { + $this->load(); + return $this->sensors; + } + + public function getRules(): array + { + $this->load(); + return $this->rules; + } + protected function load() { if (!$this->loaded) { @@ -162,36 +174,40 @@ class FanConfig $table->column(4, ['width' => 5]); $table->draw(); - $console->line(''); - - $console->info('Sensors'); - $table = new Table($console, array_map(function (Sensor $sensor) { - $options = $sensor->toArray()['options']; - $result = [$sensor->name]; - if ($sensor instanceof Sensor\HwmonSensor) { - $result[] = $options['hwmon']; - $result[] = $options['temp']; - } elseif ($sensor instanceof Sensor\CommandSensor) { - $result[] = null; - $result[] = $options['command']; - } else { - $result[] = null; - $result[] = null; - } - return $result; - }, $this->sensors), ['Name', 'hwmon', 'sensor / command']); - $table->draw(); + if (!empty($this->sensors)) { + $console->line(''); + + $console->info('Sensors'); + $table = new Table($console, array_map(function (Sensor $sensor) { + $options = $sensor->toArray()['options']; + $result = [$sensor->name]; + if ($sensor instanceof Sensor\HwmonSensor) { + $result[] = $options['hwmon']; + $result[] = $options['temp']; + } elseif ($sensor instanceof Sensor\CommandSensor) { + $result[] = null; + $result[] = $options['command']; + } else { + $result[] = null; + $result[] = null; + } + return $result; + }, $this->sensors), ['Name', 'hwmon', 'sensor / command']); + $table->draw(); + } - $console->line(''); + if (!empty($this->rules)) { + $console->line(''); - $console->info('Rules'); - $table = new Table($console, array_map(function (Rule $rule) { - return [ - implode(', ', array_map(fn($fan) => $fan->name, $rule->fans)), - $rule->sensor->name, - $rule->describe(), - ]; - }, $this->rules), ['Fans', 'Sensor', 'Description']); - $table->draw(); + $console->info('Rules'); + $table = new Table($console, array_map(function (Rule $rule) { + return [ + implode(', ', array_map(fn($fan) => $fan->name, $rule->fans)), + $rule->sensor->name, + $rule->describe(), + ]; + }, $this->rules), ['Fans', 'Sensor', 'Description']); + $table->draw(); + } } } diff --git a/app/Kernel.php b/app/Kernel.php index dfbbd042cc16b19dbb51b7eddd60130bd5660952..ab1bc133fc5ada374b1b49c585d851fc7ea99bb9 100644 --- a/app/Kernel.php +++ b/app/Kernel.php @@ -17,6 +17,7 @@ class Kernel extends \Riki\Kernel protected static $commands = [ Command\Config::class, Command\ShowConfig::class, + Command\Daemon::class, ]; /** @var \Riki\Application|Application */ diff --git a/app/Model/Rule.php b/app/Model/Rule.php index 622c51faa6067a95d059dcc8d9a9af9d668ed963..41bcaff466928217eeae50dcb748d8351f720b3d 100644 --- a/app/Model/Rule.php +++ b/app/Model/Rule.php @@ -3,6 +3,7 @@ namespace App\Model; use App\Model; +use Hugga\Console; abstract class Rule extends Model { @@ -12,7 +13,7 @@ abstract class Rule extends Model /** @var Sensor */ public $sensor; - abstract public function apply(); + abstract public function apply(Console $console); abstract public function describe(): string; } diff --git a/app/Model/Rule/CurveRule.php b/app/Model/Rule/CurveRule.php index 29635cb0ba388756ef4e5e573251d90fc68ad620..c20a987e52895f87efd2f6adb82fe536ba31fa84 100644 --- a/app/Model/Rule/CurveRule.php +++ b/app/Model/Rule/CurveRule.php @@ -5,6 +5,7 @@ namespace App\Model\Rule; use App\Model\Fan; use App\Model\Rule; use App\Model\Sensor; +use Hugga\Console; class CurveRule extends Rule { @@ -43,29 +44,50 @@ class CurveRule extends Rule } } - public function apply() + public function apply(Console $console) { $temp = $this->sensor->getTemperature(); $lastPercentage = null; $lastLimit = null; foreach ($this->points as $percentage => $limit) { - if ($temp >= $limit) { + if ($temp > $limit) { $lastPercentage = $percentage; $lastLimit = $limit; continue; // somewhere between $lastV and $v - } + if (!$this->alwaysOn && $lastPercentage === null) { // stop the fans if they should not run all the time and first limit not reached $this->stopFans(); } elseif ($lastPercentage === null) { // run the fans with the lowest percentage value before the first point + $console->line(sprintf( + 'Temperature of %s: %d° C; Speed: %.2f%%', + $this->sensor->name, + $temp, + $percentage, + ), Console::WEIGHT_DEBUG); $this->setSpeed($percentage); } else { - $factor = $temp - $lastLimit / ($limit - $lastLimit); - $this->setSpeed(($percentage - $lastPercentage) * $factor); + $factor = ($temp - $lastLimit) / ($limit - $lastLimit); + $speed = round(($percentage - $lastPercentage) * $factor + $lastPercentage, 2); + $console->line(sprintf( + 'Temperature of %s: %d° C; Speed: %.2f%% (Calculation: (%d - %d) / (%d - %d) * (%d - %d) + %d)', + $this->sensor->name, + $temp, + $speed, + $temp, + $lastLimit, + $limit, + $lastLimit, + $percentage, + $lastPercentage, + $lastPercentage + ), Console::WEIGHT_DEBUG); + $this->setSpeed($speed); } + break; } }