Skip to content

Instantly share code, notes, and snippets.

@moorer2k
Created May 11, 2018 22:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moorer2k/8f63b354615dc40eb4d192e5607129b6 to your computer and use it in GitHub Desktop.
Save moorer2k/8f63b354615dc40eb4d192e5607129b6 to your computer and use it in GitHub Desktop.
Laravel console command for automated control over TP-Link HS100. Automatically turn on my plugged in fan if temps get over 55 C.
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Process\Process;
class FanController extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'temps:monitor';
/**
* Command description..
*
* @var string
*/
protected $description = 'Monitor TPLink HS100 to control fan if CPU temps are too high using lm_sensors.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->checkTemps();
}
private function checkTemps()
{
$curr = $this->getTemps();
foreach ($curr['Temps'] as $index => $temps) {
if ($temps[$index] >= 55) {
$this->info('Temp ' . $temps[$index] . ' detected! Too hot! Turning on fan...');
$this->sendSmartCmd('on');
} else {
$fanStatus = $this->sendSmartCmd('')->system->get_sysinfo->relay_state;
if ($fanStatus == 0) {
$this->info('Fan already off.');
return;
}
$this->info('Temp ' . $temps[$index] . ' detected. Cool enough, turning off fan...');
$this->sendSmartCmd('off');
}
}
}
private function getTemps()
{
$arrOut = [];
$process = new Process('sensors');
$process->run();
if (!$process->isSuccessful()) {
return 'fail';
}
$sensors_out = str_replace('°', ' ', $process->getOutput());
preg_match_all("/Core\s(?<Core>\N):\s+\+(?<Current>\N+)\s(?<Format>\w)\s+\(high\s=\s\+(?<Warn>\N+)\s\w,\scrit\s=\s\+(?<Crit>\N{5})\s\w/", $sensors_out, $matches);
for ($i = 0; $i < count($matches['Core']); $i++) {
$arrOut[$i] = [$i => $matches['Current'][$i]];
}
return (['Warn' => $matches['Warn'][0],
'Crit' => $matches['Crit'][0],
'Temps' => $arrOut,
]);
}
//https://github.com/Ramboss/TP-Link_HS100 < credit.
private function sendSmartCmd($command)
{
$host = '10.0.0.47';
$port = 9999;
switch ($command) {
case 'on':{
$command = '{"system":{"set_relay_state":{"state": 1}}}';
break;}
case 'off':{
$command = '{"system":{"set_relay_state":{"state": 0}}}';
break;}
case 'cloudinfo':{
$command = '{"cnCloud":{"get_info":{}}}';
break;}
case 'sysinfo':{
$command = '{"system":{"get_sysinfo":{}}}';
break;}
case 'wlanscan':{
$command = '{"netif":{"get_scaninfo":{"refresh":0}}}';
break;}
case 'time':{
$command = '{"time":{"get_time":{}}}';
break;}
case 'schedule':{
$command = '{"schedule":{"get_rules":{}}}';
break;}
case 'macaddress':{
$command = '{"system":{"get_sysinfo":{}}}';
break;}
case 'countdown':{
$command = '{"count_down":{"get_rules":{}}}';
break;}
case 'antitheft':{
$command = '{"anti_theft":{"get_rules":{}}}';
break;}
case 'reboot':{
$command = '{"system":{"reboot":{"delay":1}}}';
break;}
case 'reset':{
$command = '{"system":{"reset":{"delay":1}}}';
break;}
case 'nightModeOn':{
$command = '{"system":{"set_led_off":{"off":1}}}';
break;}
case 'nightModeOff':{
$command = '{"system":{"set_led_off":{"off":0}}}';
break;}
case 'realtimeVoltage':{
$command = '{"emeter":{"get_realtime":{}}}';
break;}
case 'EMeterVGain':{
$command = '{"emeter":{"get_vgain_igain":{}}}';
break;}
case 'currentRunTime':{
$command = '{"system":{"get_sysinfo":{}}}';
break;}
case 'currentPower':{
$command = '{"emeter":{"get_realtime":{}}}';
break;}
case 'gettime':{
$command = '{"emeter":{"get_daystat":{"month":5; break ; }"year":2017}}}';
break;}
case 'currentRunTimeHour':{
$command = '{"system":{"get_sysinfo":{}}}';
break;}
case 'resetcounter':{
$command = '{"emeter":{"erase_emeter_stat":null}}';
break;}
default:{ $command = '{"system":{"get_sysinfo":{}}}';}
}
$fp = fsockopen($host, $port);
if (!$fp) {exit;}
$request = pack('N', strlen($command));
$key = 0xAB;
for ($i = 0; $i < strlen($command); $i++) {
$key = ord(substr($command, $i, 1)) ^ $key;
$request .= chr($key);
}
fwrite($fp, $request, strlen($request));
$response = fread($fp, 4);
$response = fread($fp, unpack('N', $response)[1]);
fclose($fp);
$key = 0xAB;
$output = '';
for ($i = 0; $i < strlen($response); $i++) {
$nextKey = ord(substr($response, $i, 1));
$output .= chr($nextKey ^ $key);
$key = $nextKey;
}
return json_decode($output);
}
}
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
'\App\Console\Commands\FanController',
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('temps:monitor')->everyFiveMinutes();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__ . '/Commands');
require base_path('routes/console.php');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment