<? 
/*********************************************************************
 *
 *  Wattmon
 *    
 *  File : uphp.cgi
 * 
 *  Description: UPHP settings page
 *
 *********************************************************************
 * Company:         Cynergy Software
 *
 * Software License Agreement
 *
 * Copyright (c) 2013 Cynergy Software.  All rights reserved.
 *
 * Cynergy licenses to you the right to use, modify, copy, and 
 * distribute: 
 * (i)  the Software when used on a Wattmon device
 * (ii) the Software on any platform or device for personal use
 *
 * For commercial use please contact us via http://www.wattmon.com
 *
 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT 
 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT 
 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A 
 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL 
 * CYNERGY BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR 
 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF 
 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS 
 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE 
 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER 
 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT 
 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
 *
 * Author               Date        Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Akash Heimlich       20/08/13    v1.0
 *                      29/01/14    v1.1 new layout
 *						25/04/15	added role_timeout
 *						28/06/18	WattmonOS 3
 ********************************************************************/
include("/app/config.inc");
$angular_controller="uPHPEditCtrl"; 
$title=lang('UPHP_SETTINGS','uphp');
include("/app/header.inc");
?>


<!-- BREADCRUMBS -->
<nav aria-label="breadcrumb">
  <ol class="breadcrumb">
    <li class="breadcrumb-item"><a href="/"><? print(lang('HOME','settings')) ?></a></li>
    <li class="breadcrumb-item"><a href="/app/settings.cgi"><? print(lang('CONTROL_PANEL','settings')) ?></a></li>
    <li class="breadcrumb-item active" aria-current="page"><? print(lang('UPHP_SETTINGS','uphp')) ?></li>
  </ol>
</nav>

<!-- NAVBAR -->
<h4><i class="icon-cog"></i>&nbsp;<? print(lang('CONFIGURE_TITLE','uphp')) ?></h4>
<ul class="nav justify-content-end">
  <li class="nav-item">
    <a class="nav-link active" data-toggle="collapse" href="#collapseHelp" role="button" aria-expanded="false" aria-controls="collapseExample">
    <? print(lang('HELP','uphp')) ?>
  </a>
  </li>
  <li class="nav-item">
    <a class="nav-link" onclick="document.location='/app/settings.cgi';"><i class="icon-remove"></i> <? print(lang('CLOSE','uphp')) ?></a>
  </li>
  <li ng-hide='settings_locked' class="nav-item">
    <a class="nav-link {{getClass()}}" ng-hide='loading==1' ng-click="saveSettings()" ><i class="icon-check"></i> <? print(lang('APPLY','uphp')) ?></a>
  </li>
</ul>
<!-- HELP -->
<div class="collapse" id="collapseHelp">
  <div class="card card-body">
    <? 
    $cnt=intval(lang('HELP_CNT','uphp'));
    for ($i=1;$i<=$cnt;$i++) {
        print(lang('HELP'.$i,'uphp'));
    }
    ?>
  </div>
</div>
<div class="alert alert-success" ng-cloak ng-show="successmsg"> <button type="button" class="close" ng-click='successmsg=""'>&times;</button>{{successmsg}}</div>
<div class="alert alert-danger" ng-cloak ng-show="errormsg"> <button type="button" class="close" ng-click='errormsg=""'>&times;</button>{{errormsg}}</div>
<div class="alert alert-info" ng-cloak ng-show="infomsg"> <button type="button" class="close" data-dismiss="alert">&times;</button>{{infomsg}}</div>
<div class="alert alert-secondary" ng-cloak ng-show="loading"><i id='iconRepeatMain' class='icon-spinner icon-spin' style='font-size:36px; color:red'></i>&nbsp;<? print(lang('PLEASE_WAIT','uphp')) ?></div>
<form name="form" class="css-form form-horizontal" novalidate>
<!-- VARIABLES -->

<? 
  $arr=ini_get_array("/config/uphp.ini","debug");
  if (!$arr['call_depth']) $arr['call_depth']=5;
  if (!$arr['role_timeout']) $arr['role_timeout']=15;
  if (!$arr['device_timeout']) $arr['device_timeout']=15;
  if (!$arr['stack_size']) $arr['stack_size']=1200;
  if (!$arr['min_cron_heap_free']) $arr['min_cron_heap_free']=23000;
  if (!$arr['min_http_heap_free']) $arr['min_http_heap_free']=35000;
  if (!$arr['min_cron_freeze']) $arr['min_cron_freeze']=9000;
  if (!$arr['min_http_freeze']) $arr['min_http_freeze']=6000;
  if (!$arr['min_cron_freeze_time']) $arr['min_cron_freeze_time']=3000;
  if (!$arr['modbus_tcp_tasks']) $arr['modbus_tcp_tasks']=1;
  if (!$arr['max_backoff']) $arr['max_backoff']=30000;
  if (!$arr['dynamic_timeout']) $arr['dynamic_timeout']=0;
  $method=$arr["method"];
  $level=$arr["level"];
  $role_timeout=$arr["role_timeout"];
  $device_timeout=$arr["device_timeout"];
  $console=$arr["console"];
  $max_execution_time=$arr["max_execution_time"];
  $start_script=$arr["start_script"];
  $stack_size=$arr["stack_size"];
  $call_depth=$arr["call_depth"];
  $ignore_ffff=intval($arr["ignore_ffff"]);
  $md5_sync = intval($arr['md5_sync']);
  $md5_auto_restore = intval($arr['md5_auto_restore']);
  $firmware_logging = intval($arr['firmware_logging']);
  $max_concurrent_scripts=$arr['max_concurrent_scripts'];
  if (!$max_concurrent_scripts) $max_concurrent_scripts=2;
  $errorlog=$arr["errorlog"];   
  $session_lifetime=intval($arr["session_lifetime"]);
  $unified_log=intval($arr["unified_log"]);  
  
  if ($session_lifetime==0) $session_lifetime=600;
?>
<form name="form" class="css-form form-horizontal" novalidate>
<div ng-init="sysmsg='<? if ($_GLOBALS['needreboot']) print("You will need to reboot the device for changes to take effect."); ?>';"></div>
<div ng-init="method='<? print($method); ?>';"></div><div ng-init="level='<? print($level); ?>';"></div><div ng-init="console=<? print($console); ?>;"></div>
<div ng-init="start_script='<? print($start_script); ?>';"></div><div ng-init="errorlog='<? print($errorlog); ?>';"></div><div ng-init="max_execution_time=<? print($max_execution_time); ?>;"></div>
<div ng-init="session_lifetime=<? print($session_lifetime); ?>;"></div>
<div ng-init="stack_size=<? print($stack_size); ?>;"></div>
<div ng-init="role_timeout=<? print($role_timeout); ?>;"></div>
<div ng-init="device_timeout=<? print($device_timeout); ?>;"></div>
<div ng-init="call_depth=<? print($call_depth); ?>;"></div>
<div ng-init="ignore_ffff=<? print($ignore_ffff); ?>;"></div>
<div ng-init="firmware_logging=<? print($firmware_logging); ?>;"></div>
<div ng-init="md5_sync=<? print($md5_sync); ?>;"></div>
<div ng-init="md5_auto_restore=<? print($md5_auto_restore); ?>;"></div>
<div ng-init="max_concurrent_scripts=<? print($max_concurrent_scripts); ?>;"></div>
<div ng-init="unified_log=<? print($unified_log); ?>;"></div>
<div ng-init="ram_drive_disabled=<? print(intval($arr['ram_drive_disabled'])); ?>;"></div>
<div ng-init="modbus_tcp_tasks=<? print(intval($arr['modbus_tcp_tasks'])); ?>;"></div>
<div ng-init="dynamic_timeout=<? print($arr['dynamic_timeout']); ?>;"></div>
<div ng-init="max_backoff=<? print($arr['max_backoff']); ?>;"></div>


<div class="card">
    <div class="card-body">
        <h5 class="card-title"><? print(lang('PAGE_TITLE','uphp')) ?></h5>
        <p class="card-text">    
            <div class="form-group">
                <label for="method"><? print(lang('DEBUG_METHOD','uphp')) ?></label>
                <select ng-model="method" name='method' class="custom-select custom-select-sm">
                    <option value='0'>Serial Port</option>
                    <option value='1'>Log File</option>
                </select>
                <small id="langH" class="form-text text-muted"><? print(lang('DEBUG_METHOD_HELP','uphp')) ?></small>
            </div>
            <div class="form-group">
                <label for="level"><? print(lang('DEBUG_LEVEL','uphp')) ?></label>
                <select ng-model="level" name='level' class="custom-select custom-select-sm">
                   <option value='0'>Minimal: Only Errors</option>
                            <option value='1'>Medium</option>
                            <option value='2'>Verbose</option>
                </select>
                <small id="langH" class="form-text text-muted"><? print(lang('DEBUG_LEVEL_HELP','uphp')) ?></small>
            </div>
               
		    <div class="form-group">
                <label for="max_execution_time"><? print(lang('MAX_EXECUTION_TIME','uphp')) ?></label>
                <input class="form-control" type='number' ng-model="max_execution_time"  class='span12' name='max_execution_time' required integer aria-describedby="rHelp" placeholder="<? print(lang('MAX_EXECUTION_TIME','uphp')) ?>">
                <small id="rHelp" class="form-text text-muted"><? print(lang('MAX_EXECUTION_TIME_HELP','uphp')) ?></small>
                <small ng-cloak class='text-danger' ng-show="form.max_execution_time.$invalid"><? print(lang('MAX_EXECUTION_TIME_INVALID','uphp')) ?></small>
            </div>
            <div class="form-group">
                <label for="role_timeout"><? print(lang('ROLE_TIMEOUT','uphp')) ?></label>
                <input class="form-control" type='number' ng-model="role_timeout"  class='span12' name='role_timeout' required min=1 integer aria-describedby="rHelp" placeholder="<? print(lang('ROLE_TIMEOUT','uphp')) ?>">
                <small id="rHelp" class="form-text text-muted"><? print(lang('ROLE_TIMEOUT_HELP','uphp')) ?></small>
                <small ng-cloak class='text-danger' ng-show="form.role_timeout.$invalid"><? print(lang('ROLE_TIMEOUT_INVALID','uphp')) ?></small>
            </div>
            <div class="form-group">
                <label for="device_timeout"><? print(lang('DEVICE_TIMEOUT','uphp')) ?></label>
                <input class="form-control" type='number' ng-model="device_timeout"  class='span12' name='device_timeout' required min=1 integer aria-describedby="rHelp" placeholder="<? print(lang('DEVICE_TIMEOUT','uphp')) ?>">
                <small id="rHelp" class="form-text text-muted"><? print(lang('DEVICE_TIMEOUT_HELP','uphp')) ?></small>
                <small ng-cloak class='text-danger' ng-show="form.device_timeout.$invalid"><? print(lang('DEVICE_TIMEOUT_INVALID','uphp')) ?></small>
            </div>     
            <div class="form-group">
                <label for="dynamic_timeout">Dynamic Timeout for RS-485</label>
                <select ng-model="dynamic_timeout" name='dynamic_timeout' class="custom-select custom-select-sm">
                   <option value='0'>No</option>
                  <option value='1'>Yes</option>
                </select>
                <small id="langH" class="form-text text-muted">Auto calculate timeouts per device, with exponential backoff for optimized polling</small>
            </div>
            <div class="form-group">
                <label for="max_backoff">Max Backoff time (ms)</label>
                <input class="form-control" type='number' ng-model="max_backoff"  class='span12' name='max_backoff' required min=5000 integer aria-describedby="rHelp" placeholder="Max backoff time (ms)">
                <small id="rHelp" class="form-text text-muted">The maximum time between polls (exponentially increased to this)</small>
                <small ng-cloak class='text-danger' ng-show="form.max_backoff.$invalid">Invalid backoff interval in ms</small>
            </div>     
            <div class="form-group">
                <label for="ignore_ffff">Ignore persistent 0xFFFF modbus registers</label>
                <select ng-model="ignore_ffff" name='ignore_ffff' class="custom-select custom-select-sm">
                   <option value='0'>No</option>
                  <option value='1'>Yes</option>
                </select>
                <small id="langH" class="form-text text-muted">Some devices remain active but send 0xFFFF values in certain conditions</small>
            </div>
            <div class="form-group">
                <label for="max_concurrent_scripts"><? print(lang('MAX_CONCURRENT','uphp')) ?></label>
                <input class="form-control" type='number' ng-model="max_concurrent_scripts"  class='span12' name='max_concurrent_scripts' required min=1 integer aria-describedby="rHelp" placeholder="<? print(lang('MAX_CONCURRENT','uphp')) ?>">
                <small id="rHelp" class="form-text text-muted"><? print(lang('MAX_CONCURRENT_HELP','uphp')) ?></small>
                <small ng-cloak class='text-danger' ng-show="form.max_concurrent_scripts.$invalid"><? print(lang('MAX_CONCURRENT_INVALID','uphp')) ?></small>
            </div>     
		    <div class="form-group">
                <label for="modbus_tcp_tasks">Concurrent Modbus TCP Tasks</label>
                <input class="form-control" type='number' ng-model="modbus_tcp_tasks"  class='span12' name='max_execution_time' required integer aria-describedby="rHelp" placeholder="Number of parallel tasks">
                <small id="rHelp" class="form-text text-muted">Poll TCP devices in parallel by increasing this value.  Suggested max value is 3 or MINI3, and 5-10 on Mega2/Ultra</small>
                <small ng-cloak class='text-danger' ng-show="form.max_execution_time.$invalid">Select a value</small>
            </div>
            
            <div class="form-group">
                <label for="stack_size"><? print(lang('STACK_SIZE','uphp')) ?></label>
                <input class="form-control" type='number' ng-model="stack_size"  class='span12' name='stack_size' required min=200 integer aria-describedby="rHelp" placeholder="<? print(lang('STACK_SIZE','uphp')) ?>">
                <small id="rHelp" class="form-text text-muted"><? print(lang('STACK_SIZE_HELP','uphp')) ?></small>
                <small ng-cloak class='text-danger' ng-show="form.stack_size.$invalid"><? print(lang('STACK_SIZE_INVALID','uphp')) ?></small>
            </div>     
            <div class="form-group">
                <label for="call_depth"><? print(lang('CALL_DEPTH','uphp')) ?></label>
                <input class="form-control" type='number' ng-model="call_depth"  class='span12' name='call_depth' required min=5 integer aria-describedby="rHelp" placeholder="<? print(lang('CALL_DEPTH','uphp')) ?>">
                <small id="rHelp" class="form-text text-muted"><? print(lang('CALL_DEPTH_HELP','uphp')) ?></small>
                <small ng-cloak class='text-danger' ng-show="form.call_depth.$invalid"><? print(lang('CALL_DEPTH_INVALID','uphp')) ?></small>
            </div>     
            
            <div class="form-group">
                <label for="session_lifetime"><? print(lang('SESSION_LIFETIME','uphp')) ?></label>
                <input class="form-control" type='number' ng-model="session_lifetime"  class='span12' name='session_lifetime' required min=60 integer aria-describedby="rHelp" placeholder="<? print(lang('SESSION_LIFETIME','uphp')) ?>">
                <small id="rHelp" class="form-text text-muted"><? print(lang('SESSION_LIFETIME_HELP','uphp')) ?></small>
                <small ng-cloak class='text-danger' ng-show="form.session_lifetime.$invalid"><? print(lang('SESSION_LIFETIME_INVALID','uphp')) ?></small>
            </div>   
		    <div class="form-group">
                <label for="start_script"><? print(lang('START_SCRIPT','uphp')) ?></label>
                <input type="text" class="form-control" id="start_script" ng-model="start_script" aria-describedby="userHelp" placeholder="<? print(lang('START_SCRIPT_HELP','uphp')) ?>">
                <small id="userHelp" class="form-text text-muted"><? print(lang('START_SCRIPT_HELP','uphp')) ?></small>
            </div>     	
		    <div class="form-group">
                <label for="errorlog"><? print(lang('ERROR_LOG','uphp')) ?></label>
                <input type="text" class="form-control" id="errorlog" ng-model="errorlog" aria-describedby="userHelp" placeholder="<? print(lang('ERROR_LOG','uphp')) ?>"><button class="btn" ng-click="viewLog();"><i class="icon-file-alt"></i> View</button>
                <small id="userHelp" class="form-text text-muted"><? print(lang('ERROR_LOG_HELP','uphp')) ?></small>
            </div>
            <div class="form-group">
                <label for="method">Log File Mode</label>
                <select ng-model="unified_log" name='unified_log' class="custom-select custom-select-sm">
                    <option value='0'>Multiple files (network, ftp, mqtt, log, etc)</option>
                    <option value='1'>Single file (log.txt)</option>
                </select>
                <small id="langH" class="form-text text-muted">Choose how logs will be stored in the logs folder</small>
            </div>
            
        </p>
    </div>
</div>
<br/>
<div class="card">
    <div class="card-body">
        <h5 class="card-title">File System Consistency</h5>
        <p class="card-text">    

            <div class="form-group">
                <label for="md5_sync">Auto Check File System daily</label>
                <select ng-model="md5_sync" name='md5_sync' class="custom-select custom-select-sm">
                   <option value='0'>No</option>
                  <option value='1'>Yes</option>
                </select>
                <small id="langH" class="form-text text-muted">Automatically scan the file system every day for changes</small>
            </div>
            <div class="form-group">
                <label for="md5_auto_restore">Auto-restore changed packages</label>
                <select ng-model="md5_auto_restore" name='md5_auto_restore' class="custom-select custom-select-sm">
                   <option value='0'>No</option>
                  <option value='1'>Yes</option>
                </select>
                <small id="langH" class="form-text text-muted">Automatically restore files that have been installed from a repository if they are changed/corrupted</small>
            </div>
		        
		 </p>
	</div>
</div>

<br/>
<div class="card">
    <div class="card-body">
        <h5 class="card-title">Data Logging</h5>
        <p class="card-text">    

            <div class="form-group">
                <label for="firmware_logging">Firmware-based logging</label>
                <select ng-model="firmware_logging" firmware_logging='md5_sync' class="custom-select custom-select-sm">
                   <option value='0'>No</option>
                  <option value='1'>Yes</option>
                </select>
                <small id="langH" class="form-text text-muted">The role values will be automatically collected at the firmware level </small>
            </div>

		 </p>
	</div>
</div>
<br/>
<? if ($_SERVER['HW_PLATFORM']>=20) { ?>
<div class="card">
    <div class="card-body">
        <h5 class="card-title">RAM Drive</h5>
        <p class="card-text">    

            <div class="form-group">
                <label for="ram_drive_disabled">RAM Drive for CGC Files</label>
                <select ng-model="ram_drive_disabled" firmware_logging='md5_sync' class="custom-select custom-select-sm">
                   <option value='0'>Enabled</option>
                  <option value='1'>Disabled</option>
                </select>
                <small id="langH" class="form-text text-muted">If you have a device that is giving issues with DDR RAM you can disable this </small>
            </div>

		 </p>
	</div>
</div>
<? } ?>
</form>

     <script>
var app = angular.module('myApp', []);         
function uPHPEditCtrl($scope,$http) {
   var self = this;
    $scope.settings_locked=settings_locked;
    if (settings_locked) 
        $scope.errormsg="Unable to save settings since the Flash is locked.  Please unlock first.";
   
   $scope.infomsg="";
   $scope.viewLog=function () {
        window.open($scope.errorlog,'_blank');
   }
   $scope.editScript=function () {
        var path=$scope.start_script;
        var pos = path.lastIndexOf( "/" ); 
        if (pos<0) {
            var filename = path;
            var path="/";
        } else {
            var filename=path.substring( pos+1);
            path=path.substring( 0,pos+1)
        }
        alert( "path="+path+" and filename="+ filename );
        window.open("/app/edit.cgi?dir="+path+"&fn="+filename,'_blank');
   }
   
   $scope.saveSettings=function () {
       $scope.successmsg="";
       $scope.errormsg="";
       $scope.infomsg="";
       //alert();
       //
       $http.post('/app/configsave.cgi?config=uphp.ini&section=debug',"errorlog="+$scope.errorlog+
            "&method="+$scope.method+
            "&start_script="+$scope.start_script+
            "&console="+$scope.console+
            "&level="+$scope.level+
            "&max_execution_time="+$scope.max_execution_time+
            "&session_lifetime="+$scope.session_lifetime+
            "&max_concurrent_scripts="+$scope.max_concurrent_scripts+
            "&call_depth="+$scope.call_depth+
            "&stack_size="+$scope.stack_size+
            "&ignore_ffff="+$scope.ignore_ffff+
            "&dynamic_timeout="+$scope.dynamic_timeout+
            "&max_backoff="+$scope.max_backoff+
            "&md5_sync="+$scope.md5_sync+
            "&md5_auto_restore="+$scope.md5_auto_restore+
            "&device_timeout="+$scope.device_timeout+
            "&firmware_logging="+$scope.firmware_logging+
            "&unified_log="+$scope.unified_log+
            "&modbus_tcp_tasks="+$scope.modbus_tcp_tasks+
            "&ram_drive_disabled="+$scope.ram_drive_disabled+
            "&role_timeout="+$scope.role_timeout)
        .then(function (response) {
          var data = response.data;      
          $scope.successmsg=(data.status==1)?"Saved Settings":"";
          $scope.errormsg=data.error;
          $scope.sysmsg=data.sysmsg;
          return data;
        }, function(reason) {
            $scope.errormsg="Error saving settings";
            $scope.successmsg="";
            //alert('Failed: ' + reason);
           
        });
   }
    
  //poll();

}</script>
<? include("/app/footer.inc"); ?>







