#!/usr/bin/php
<?php
##############################
######  DEAMON SECTION  ######
##############################
require_once '/usr/local/emhttp/plugins/ipmi/include/ipmi_options.php';
require_once '/usr/local/emhttp/plugins/ipmi/include/ipmi_settings_fan.php';
$debug = FALSE;

set_time_limit(0);
$prog     = pathinfo(__FILE__, PATHINFO_FILENAME);
$prog2    = "ipmifan";
$lockfile = "/var/run/${prog2}.pid";
$log      = "/var/log/${prog2}";

$usage = <<<EOF

Check ASRock IPMI fan locations using ipmi-raw command and
create a json array for ipmifan script.

Usage: $prog [options]

  -f, --force      force start
      --debug      turn on debugging
      --help       display this help and exit
      --version    output version information and exit


EOF;

$shortopts = 'f';
$longopts = [
    'debug',
    'force',
    'help',
    'version'
];
$args = getopt($shortopts, $longopts);

if (array_key_exists('help', $args)) {
    echo $usage.PHP_EOL;
    exit(0);
}

if (array_key_exists('version', $args)) {
    echo 'IPMI 2 JSON: 1.0'.PHP_EOL;
    exit(0);
}

$debug  = (array_key_exists('debug', $args));

if(file_exists($lockfile) && !$force){
    $lock_pid = file($lockfile, FILE_IGNORE_NEW_LINES)[0];
    fanlog("Please stop ${prog2} [$lock_pid] then try again");
    exit(0);
}

if (!array_key_exists($board, $boards)){
    $msg = "Your $board motherboard is not supported yet";
    logger($msg, $argq);
    exit(1);
}

##############################
###### FUNCTION SECTION ######
##############################

/* logfile */
function fanlog($msg) {
    global $log;

    echo PHP_EOL.$msg.PHP_EOL;

    $msg = date('Y-m-d H:i:s').' '.$msg.PHP_EOL;
    file_put_contents($log,$msg,FILE_APPEND);
}

/* debug */
function debug($m){
  global $prog, $debug;
  if($debug){
    $STDERR = fopen('php://stderr', 'w+');
    fwrite($STDERR, $m.PHP_EOL);
    fclose($STDERR);
  }
}

/* get fan sensors */
function ipmi_sensors_fans() {
    global $ipmi, $fanopts;

    // return empty array if no ipmi detected or network options
    if(!$ipmi && empty($fanopts))
        return [];

    $cmd = "/usr/sbin/ipmi-sensors --comma-separated-output --no-header-output $fanopts 2>/dev/null";
    $return_var=null ;
    exec($cmd, $output, $return_var);

    // return empty array if error
    if($return_var)
        return [];

    // key names for ipmi sensors output
    $keys = ['ID', 'Name', 'Type', 'Reading', 'Units', 'Event'];
    $sensors = [];

    foreach($output as $line){

    /// add sensor keys as keys to ipmi sensor output
        $sensor_raw = explode(",", $line);
        $size_raw = sizeof($sensor_raw);
        $sensor = ($size_raw < 6) ? []: array_combine($keys, array_slice($sensor_raw,0,6,true));

        if ($sensor['Type'] == 'Fan')
            $sensors[$sensor['ID']] = $sensor;
    }
    return $sensors; // sensor readings
    unset($sensors);
}

##############################
#####  PROGRAM SECTION  ######
##############################


#############################################
# ASRock                                    #
# ipmi-raw 00 3a 01 00 00 00 00 00 00 00 00 #
# ipmi-raw 00 3a 01 AA BB CC DD EE FF GG HH #
# 00 = smartfan mode                        #
# 01 - 64  = 1% - 100%                      #
#############################################

#############################################
# ASRock Dual Socket
# ipmi-raw 00 3a 01 CPU_1_OVERRIDE CPU_1 REAR_1 FRONT_1 FRONT_2 FRONT_3
# ipmi-raw 00 3a 11 CPU_2_OVERRIDE CPU_2 REAR_2 FRONT_4
# ipmi-raw 00 3a 01 00 AA BB CC DD EE
# ipmi-raw 00 3a 11 00 AA BB CC
#############################################
#

####  DO YOUR STUFF HERE  ####


$lun   = '00';
$netfn = '3a';
$com   = '01';
$raw   = '00 3a 01';
$board_json = [];
$board_tmp = $board;

if ($cmd_count == 0){
    $fans_start = 0;
    $fans_count = 7;
    $auto  = '00 00 00 00 00 00 00 00';
    $full  = '64 64 64 64 64 64 64 64';
}else{
    $fans_start = 1;
    $fans_count = 5;
    $auto  = '00 00 00 00 00 00';
    $full  = '01 64 64 64 64 64';
}

fanlog('Checking IPMI fan Locations...');

for($i = 0; $i <= $cmd_count; $i++){
    $fans   = [];
    if ($i !== 0){
        $fans_count = 3;
        $auto  = '00 00 00 00';
        $full  = '01 64 64 64';
    }

    $raw = "${lun} ${netfn} ${i}1";

    // set fans to full speed and get readings
    $cmd = "ipmi-raw $raw $full $fanopts 2>&1";

    if ($debug)
       fanlog($cmd);

    shell_exec($cmd);

    sleep(5);
    $fans_full = ipmi_sensors_fans();

// step through each raw command position
    for($ii = $fans_start; $ii <= $fans_count; $ii++){
        $msg  = 'none';
        $location = ($cmd_count < 1 ? ($ii+1) : $ii);
        $name = 'FAN_POS'.$location;

        // set postition in raw command to 1/3 and get readings
        $hex = substr_replace($full,'21',$ii*3,2);

        $cmd = "ipmi-raw $raw $hex $fanopts 2>&1";

        if ($debug)
            fanlog($cmd);

        shell_exec($cmd);

        sleep(5);
        $fans_1third = ipmi_sensors_fans();

        // check for fan speed changes
        foreach($fans_full as $fan){
            if($fan['Reading'] != 'N/A') {
                if(($fan['Reading']-$fans_1third[$fan['ID']]['Reading']) > 300) {
                    $name = $fan['Name'];
                    $msg  = $name.' 100%: '.$fan['Reading'].' 33%: '.$fans_1third[$fan['ID']]['Reading'];
                }
            }
        }
        unset($fans_1third);
        $fans[$name] = $i.'1';
        fanlog("Location $i-".$location.': '.$msg);
    }

    $cmd = "ipmi-raw $raw $auto $fanopts 2>&1";

    if ($debug)
       fanlog($cmd);

    shell_exec($cmd);

    if ($i !== 0)
        $board_tmp = $board.$i;

    $board_json[$board_tmp] =
        [ 'raw'   => $raw,
          'auto'  => $auto,
          'full'  => $full,
          'fans'  => $fans
        ];

}

fanlog('Saving board configuration...');
file_put_contents($board_file, json_encode($board_json,JSON_PRETTY_PRINT));

/* print variable */
$defined_vars = get_defined_vars();

foreach (array("_GET","_POST","_COOKIE","_FILES","argv","argc","_SERVER") as $i)
    unset($defined_vars[$i]);

debug("\nDECLARED VARIABLES:\n".print_r($defined_vars, true));
unset($defined_vars);

######  END OF SECTION  ######
?>