<?php namespace App; use App\Model\Fan; use App\Model\Rule; use App\Model\Sensor; use Hugga\Console; use Hugga\Output\Drawing\Table; class FanConfig { protected $path = '/dev/null'; protected $loaded = false; /** @var array|Fan[] */ protected $fans = []; /** @var array|Sensor[] */ protected $sensors = []; /** @var array|Rule[] */ protected $rules = []; public function __construct(string $path) { $this->path = $path; } public function hasFans(): bool { $this->load(); return count($this->fans) > 0; } public function addFan(Fan $fan): self { $this->load(); $this->fans[$fan->name] = $fan; return $this; } /** @return Fan[]|array */ public function getFans(): array { $this->load(); 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) { $this->readConfig(); } } public function readConfig(): self { if (!file_exists($this->path)) { return $this; } $this->loaded = true; $cfg = include($this->path); // validate config if (!is_array($cfg)) { throw new \InvalidArgumentException('given configuration is not a fan-ctrl config'); } foreach ($cfg['fans'] ?? [] as $fanCfg) { $class = $fanCfg['type']; $fan = new $class($fanCfg['name'], $fanCfg['options']); $this->fans[$fan->name] = $fan; } foreach ($cfg['sensors'] ?? [] as $sensorCfg) { $class = $sensorCfg['type']; $sensor = new $class($sensorCfg['name'], $sensorCfg['options']); $this->sensors[$sensor->name] = $sensor; } foreach ($cfg['rules'] ?? [] as $ruleCfg) { $class = $ruleCfg['type']; $fans = array_map(fn($name) => $this->fans[$name] ?? null, $ruleCfg['fans']); if (in_array(null, $fans, true)) { continue; } $sensor = $this->sensors[$ruleCfg['sensor']] ?? null; if (!$sensor) { continue; } $rule = new $class($fans, $sensor, $ruleCfg['options']); $this->rules[] = $rule; } return $this; } public function save() { $code = '<?php' . PHP_EOL . PHP_EOL . 'return ' . $this->exportArray([ 'fans' => array_map(function (Fan $fan) { return $fan->toArray(); }, array_values($this->fans)), 'sensors' => array_map(function (Sensor $sensor) { return $sensor->toArray(); }, array_values($this->sensors)), 'rules' => array_map(function (Rule $rule) { return $rule->toArray(); }, $this->rules), ]) . ';' . PHP_EOL; file_put_contents($this->path, $code); } protected function exportArray(array $array, $indentation = 0) { $indexed = array_keys($array) === array_keys(array_keys($array)); $indentation += 4; $var = '[' . PHP_EOL; foreach ($array as $key => $value) { $var .= str_repeat(' ', $indentation); if (!$indexed) { $var .= var_export($key, true) . ' => '; } $var .= is_array($value) ? $this->exportArray($value, $indentation) : var_export($value, true); $var .= ',' . PHP_EOL; } $indentation -= 4; $var .= str_repeat(' ', $indentation) . ']'; return $var; } public function display(Console $console) { $this->load(); $console->info('Fans'); $table = new Table($console, array_map(function (Fan $fan) { if ($fan instanceof Fan\HwmonFan) { $options = $fan->toArray()['options']; return [ $fan->name, $options['hwmon'], $options['fan'], $options['pwm'], $options['start'], $options['max'], ]; } return [ $fan->name, null, null, null, null, ]; }, $this->fans), ['Name', 'hwmon', 'Fan', 'PWM', 'start', 'max']); $table->column(4, ['width' => 5]); $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(); } 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(); } } }