www-thermferm/units.php

Sat, 16 May 2015 17:39:30 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 16 May 2015 17:39:30 +0200
changeset 362
c92651a54969
parent 349
1f89da6511a9
child 364
2f9bbbcd2407
permissions
-rw-r--r--

Made the client-server protocol more robust. When a change to a unit is made using the web interface, the main process is stopped during the update. Splitted the PID in two PID's, one for heating and one for cooling. Adjusted the web edit scrreen for this, but there are still rough edges. Replaced the PID code, maybe this one works better for our purpose. The simulator air temperature changes on the simulator heater and cooler, but it is not realistic at all. This is a development version, do not use in production. The version is 0.3.0

<?php
/*****************************************************************************
 * Copyright (C) 2014-2015
 *   
 * Michiel Broek <mbroek at mbse dot eu>
 *
 * This file is part of ThermFerm
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * ThermFerm is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ThermFerm; see the file COPYING.  If not, write to the Free
 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *****************************************************************************/

require_once('utilities.php');


/*
 * $arr contains the complete reply of the LIST command.
 */
$answer = send_cmd("UNIT LIST");
$arr = explode("\r\n", $answer);


if (isset($_GET['action'])) {
    switch ($_GET['action']) {
	case 'edit':            unit_edit();
				break;
	default:                break;
    }
} elseif (isset($_POST['action'])) {
    switch ($_POST['action']) {
	case 'testdata':	testdata();
			        break;
	default:                break;
    }
} else {
    unit_list();
}

exit;

/****************************************************************************
 *
 */

/*
 * Unit add
 *
 * @param string $_POST['Name'] The rpofile name
 */
function unit_add() {

    if ($_POST['key'] == 'Add') {
	send_cmd("UNIT ADD ".$_POST['Name']);
    }

    unset($_POST['UUID']);
    unset($_POST['Name']);
    unset($_POST['key']);
    unset($_POST['command']);
    load('units.php');
}



/*
 * Unit update
 *
 * @param string $_POST['UUID'] The unit UUID
 * @param string $_POST['Name'] The unit name
 * @param string $_POST['key'] The button pressed.
 */
function unit_update() {
    /*
     * Build the update command
     */
    if ($_POST['key'] == 'Delete') {
	send_cmd("UNIT DEL ".$_POST['UUID']);
    }

    if ($_POST['key'] == 'Save') {
	$cmd = array("UNIT PUT ".$_POST['UUID']);
	$cmd[] = "NAME,".$_POST['Name'];
	$cmd[] = "VOLUME,".$_POST['Volume'];
	$cmd[] = "AIR_ADDRESS,".$_POST['AirAddress'];
	$cmd[] = "BEER_ADDRESS,".$_POST['BeerAddress'];
	$cmd[] = "HEATER_ADDRESS,".$_POST['HeaterAddress'];
	$cmd[] = "HEATER_DELAY,".$_POST['HeaterDelay'];
	$cmd[] = "COOLER_ADDRESS,".$_POST['CoolerAddress'];
	$cmd[] = "COOLER_DELAY,".$_POST['CoolerDelay'];
	$cmd[] = "FAN_ADDRESS,".$_POST['FanAddress'];
	$cmd[] = "FAN_DELAY,".$_POST['FanDelay'];
	$cmd[] = "LIGHT_ADDRESS,".$_POST['LightAddress'];
	$cmd[] = "LIGHT_DELAY,".$_POST['LightDelay'];
	$cmd[] = "DOOR_ADDRESS,".$_POST['DoorAddress'];
	$cmd[] = "PSU_ADDRESS,".$_POST['PSUAddress'];
	$cmd[] = "TEMP_SET_MIN,".$_POST['TempSetMin'];
	$cmd[] = "TEMP_SET_MAX,".$_POST['TempSetMax'];
	$cmd[] = "PIDC_IMAX,".$_POST['PIDC_iMax'];
	$cmd[] = "PIDC_PGAIN,".$_POST['PIDC_pGain'];
	$cmd[] = "PIDC_DGAIN,".$_POST['PIDC_dGain'];
	$cmd[] = "PIDC_IGAIN,".$_POST['PIDC_iGain'];
	$cmd[] = "PIDC_IDLERANGE,".$_POST['PIDC_idleRange'];
	$cmd[] = "PIDH_IMAX,".$_POST['PIDC_iMax'];
	$cmd[] = "PIDH_PGAIN,".$_POST['PIDH_pGain'];
	$cmd[] = "PIDH_DGAIN,".$_POST['PIDH_dGain'];
	$cmd[] = "PIDH_IGAIN,".$_POST['PIDH_iGain'];
	$cmd[] = "PIDH_IDLERANGE,".$_POST['PIDH_idleRange'];
	$cmd[] = ".";
	send_array($cmd);
    }

    unset($_POST['UUID']);
    unset($_POST['Name']);
    unset($_POST['Volume']);
    unset($_POST['key']);
    unset($_POST['command']);
    unset($_POST['AirAddress']);
    unset($_POST['BeerAddress']);
    unset($_POST['HeaterAddress']);
    unset($_POST['HeaterDelay']);
    unset($_POST['CoolerAddress']);
    unset($_POST['CoolerDelay']);
    unset($_POST['LightAddress']);
    unset($_POST['LightDelay']);
    unset($_POST['FanAddress']);
    unset($_POST['FanDelay']);
    unset($_POST['DoorAddress']);
    unset($_POST['PSUAddress']);
    unset($_POST['TempSetMin']);
    unset($_POST['TempSetMax']);
    unset($_POST['PIDC_iMax']);
    unset($_POST['PIDC_pGain']);
    unset($_POST['PIDC_dGain']);
    unset($_POST['PIDC_iGain']);
    unset($_POST['PIDC_idleRange']);
    unset($_POST['PIDH_iMax']);
    unset($_POST['PIDH_pGain']);
    unset($_POST['PIDH_dGain']);
    unset($_POST['PIDH_iGain']);
    unset($_POST['PIDH_idleRange']);
    load('units.php');
}



/*
 * Test input of a modified or new profile.
 *
 * @param string $_POST['UUID'] Unique record UUID
 * @param string $_POST['Name'] Profile name
 * @param string $_POST['key'] Key choice, Save or Cancel
 * @param string $_POST['command'] Command used, 'add' or 'update'
 *
 * Return: 0 = Ok
 *         1 = Missing data
 *         2 = Name field too short
 *         3 = Name already in use
 *         4 = TempSetMax <= TempSetMin
 *         5 = TempSetMax < 25 or > 35
 *         6 = TempSetMin < -5 or > 15
 *         7 = HeaterDelay out of range
 *         8 = CoolerDelay out of range
 *         9 = PIDC idleRange out of range
 *        10 = PIDH idleRange out of range
 *        11 = LightDelay out of range
 *	  12 = FanDelay out of range
 *        99 = Cancel key
 */
function test_thedata() {

    global $arr;

    if (isset($_POST['UUID']) && isset($_POST['Name']) && isset($_POST['Volume']) && isset($_POST['AirAddress']) &&
	isset($_POST['BeerAddress']) && isset($_POST['HeaterAddress']) && isset($_POST['CoolerAddress']) && isset($_POST['LightAddress']) &&
	isset($_POST['HeaterDelay']) && isset($_POST['CoolerDelay']) && isset($_POST['LightDelay']) && isset($_POST['PSUAddress']) &&
	isset($_POST['FanAddress']) && isset($_POST['DoorAddress']) && isset($_POST['TempSetMin']) && isset($_POST['TempSetMax']) &&
	isset($_POST['PIDC_pGain']) && isset($_POST['PIDC_iGain']) && isset($_POST['PIDC_dGain']) && isset($_POST['PIDC_idleRange']) &&
	isset($_POST['PIDH_pGain']) && isset($_POST['PIDH_iGain']) && isset($_POST['PIDH_dGain']) && isset($_POST['PIDH_idleRange']) &&
	isset($_POST['PIDC_iMax']) && isset($_POST['PIDH_iMax']) &&
	isset($_POST['FanDelay']) && isset($_POST['key']) && isset($_POST['command'])) {

	if ($_POST['key'] == 'Cancel')
	    return 99;

    	if (strlen($_POST['Name']) < 2)
	    return 2;

    	if (startsWith($arr[0], "212")) {
	    $j = 1;
	    while (1) {
	    	if (strcmp($arr[$j], ".") == 0)
		    break;
	    	$f = explode(",", $arr[$j]);
	    	if (strcmp($f[0], $_POST['UUID']) && (strcmp($f[1], $_POST['Name']) == 0)) {
		    return 3;
	    	}
	    	$j++;
	    }
	}

	if ($_POST['TempSetMax'] <= $_POST['TempSetMin'])
	    return 4;

	if (($_POST['TempSetMax'] < 25) || ($_POST['TempSetMax'] > 35))
	    return 5;

	if (($_POST['TempSetMin'] < -5) || ($_POST['TempSetMin'] > 15))
	    return 6;

	if (($_POST['HeaterDelay'] < 0) || ($_POST['HeaterDelay'] > 720))
	    return 7;

	if (($_POST['CoolerDelay'] < 0) || ($_POST['CoolerDelay'] > 720))
	    return 8;

	if (($_POST['PIDC_idleRange'] < 0) || ($_POST['PIDC_idleRange'] > 5))
	    return 9;

	if (($_POST['PIDH_idleRange'] < 0) || ($_POST['PIDH_idleRange'] > 5))
	    return 10;

	if (($_POST['LightDelay'] < 0) || ($_POST['LightDelay'] > 720))
	    return 11;

	if (($_POST['FanDelay'] < 0) || ($_POST['FanDelay'] > 720))
	    return 12;

    } else {
	return 1;
    }

    return 0;
}



/*
 * Test result from edit screen and do next action
 */
function testdata() {

    $result = test_thedata();
    $error = '';

    switch ($result) {
	case 0: if ($_POST['command'] == 'add') {
		    unit_add();
		    return;
		} else if ($_POST['command'] == 'update') {
		    unit_update();
		    return;
		}
		break;
	case 1: $error = 'Missing data';
		break;
	case 2: $error = 'The name is too short';
		break;
	case 3: $error = 'The name is already in use, choose another one';
		break;
	case 4: $error = 'Temperature Maximum cannot be smaller then Temperature Minimum';
		break;
	case 5: $error = 'Temperature Maximum must be between 25 and 35 &deg;C';
		break;
	case 6:	$error = 'Temperature Minimum must be between -5 and 15 &deg;C';
		break;
	case 7: $error = 'Heater Delay must be bewteen 0 and 720 seconds';
		break;
	case 8:	$error = 'Cooler Delay must be bewteen 0 and 720 seconds';
		break;
	case 9: $error = 'PID cool Idle Range must be between 0 en 5';
		break;
	case 10: $error = 'PID heat Idle Range must be between 0 and 5';
		break;
	case 11: $error = 'Light Delay must be bewteen 0 and 720 seconds';
		break;
	case 12: $error = 'Fan Delay must be bewteen 0 and 720 seconds';
		break;
	case 99:        
		load('units.php');
		break;
    }

    if ($_POST['command'] == 'add') {
	$heading = 'ThermFerm - Add Unit';
    } else {
	$heading = 'ThermFerm - Edit Unit';
    }

    edit_screen($_POST['UUID'], $_POST['command'], $heading, $error);
}



/*
 * Unit edit screen. Used by unit_edit(), unit_add() and testdata()
 *
 * @param string $UUID The record UUID (fixed).
 * @param string $command 'add' or 'update'
 * @param string $heading Page heading title.
 * @Param string $error_message Blank or previous error.
 */
function edit_screen($UUID, $command, $heading, $error_message) {

    /*
     * Get list of devices, we need it later
     */
    $answer = send_cmd("DEVICE LIST");
    $devices = explode("\r\n", $answer);

    /*
     * Get current unit data
     */
    $answer = send_cmd("UNIT GET ".$UUID);
    $reply = explode("\r\n", $answer);

    $outstr  = build_header($heading);
    $outstr .= '    <div id="errors">'.PHP_EOL;
    $outstr .= '     '.$error_message.PHP_EOL;
    $outstr .= '    </div> <!-- errors -->'.PHP_EOL;
    $outstr .= '    <div id="etable">'.PHP_EOL;
    $outstr .= '     <form method="POST" action="units.php">'.PHP_EOL;
    $outstr .= '      <table class="editor">'.PHP_EOL;

    if (startsWith($reply[0], "213")) {
	$i = 1;
	while (1) {
	    if (strcmp($reply[$i], ".") == 0)
		break;
	    $f = explode(",", $reply[$i]);

	    if ($f[0] == "NAME") {
    		$outstr .= '       <tr class="editor">'.PHP_EOL;
    		$outstr .= '        <td class="editname">Unit Name</td>'.PHP_EOL;
    		$outstr .= '        <td class="editfield"><input type="text" name="Name" size="50" value="'.$f[1].'"></td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "VOLUME") {
    		$outstr .= '       <tr class="editor">'.PHP_EOL;
    		$outstr .= '        <td class="editname">Unit Volume</td>'.PHP_EOL;
    		$outstr .= '        <td class="editfield"><input type="text" name="Volume" size="5" value="'.$f[1].'"></td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "AIR_ADDRESS") {
    		$outstr .= '       <tr class="editor">'.PHP_EOL;
    		$outstr .= '        <td class="editname">Air Sensor Address</td>'.PHP_EOL;
    		$outstr .= '        <td class="editfield"><select name="AirAddress">'.PHP_EOL;
		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
		if (startsWith($devices[0], "212")) {
		    $j = 1;
		    while (1) {
	    	    	if (strcmp($devices[$j], ".") == 0)
			    break;
		    	$g = explode(",", $devices[$j]);
		    	if ($g[5] == "IN_ANALOG") {
			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
		    	}
		    	$j++;
		    }
		}
    		$outstr .= '        </select></td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "BEER_ADDRESS") {
                $outstr .= '       <tr class="editor">'.PHP_EOL;
                $outstr .= '        <td class="editname">Beer Sensor Address</td>'.PHP_EOL;
                $outstr .= '        <td class="editfield"><select name="BeerAddress">'.PHP_EOL;
                $outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
                if (startsWith($devices[0], "212")) {
                    $j = 1;
                    while (1) {
                        if (strcmp($devices[$j], ".") == 0)
                            break;
                        $g = explode(",", $devices[$j]);
			if ($g[5] == "IN_ANALOG") {
			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
                            $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
                        }
                        $j++;
                    }
		}
		$outstr .= '        </select></td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "HEATER_ADDRESS") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Heater Switch Address</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><select name="HeaterAddress">'.PHP_EOL;
		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
		if (startsWith($devices[0], "212")) {
		    $j = 1;
		    while (1) {
			if (strcmp($devices[$j], ".") == 0)
			    break;
			$g = explode(",", $devices[$j]);
			if (($g[5] == "OUT_ANALOG") || ($g[5] == "OUT_BIN")) {
			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
			}
			$j++;
		    }
		}
		$outstr .= '        </select></td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "HEATER_DELAY") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Heater Switch Delay</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="HeaterDelay" size="5" value="'.$f[1].'"> seconds (0..720)</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "PIDH_IMAX") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">PID Heat Maximum</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="PIDH_iMax" size="6" value="'.$f[1].'"> % (1..100)</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "PIDH_PGAIN") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">PID Heat pGain</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="PIDH_pGain" size="6" value="'.$f[1].'"> Proportional</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "PIDH_IGAIN") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">PID Heat iGain</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="PIDH_iGain" size="6" value="'.$f[1].'"> Intergral</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "PIDH_DGAIN") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">PID Heat dGain</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="PIDH_dGain" size="6" value="'.$f[1].'"> Derivative</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "PIDH_IDLERANGE") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">PID Heat Idle Range</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="PIDH_idleRange" size="6" value="'.$f[1].'"> &deg;C (Heater margin)</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "COOLER_ADDRESS") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Cooler Switch Address</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><select name="CoolerAddress">'.PHP_EOL;
		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
		if (startsWith($devices[0], "212")) {
		    $j = 1;
		    while (1) {
			if (strcmp($devices[$j], ".") == 0)
			    break;
			$g = explode(",", $devices[$j]);
			if (($g[5] == "OUT_ANALOG") || ($g[5] == "OUT_BIN")) {
			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
			}
			$j++;
		    }
		}
		$outstr .= '        </select></td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "COOLER_DELAY") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Cooler Switch Delay</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="CoolerDelay" size="5" value="'.$f[1].'"> seconds (0..720)</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "PIDC_IMAX") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">PID Cool Maximum</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="PIDC_iMax" size="6" value="'.$f[1].'"> % (1..100)</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "PIDC_PGAIN") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">PID Cool pGain</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="PIDC_pGain" size="6" value="'.$f[1].'"> Proportional</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "PIDC_IGAIN") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">PID Cool iGain</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="PIDC_iGain" size="6" value="'.$f[1].'"> Intergral</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "PIDC_DGAIN") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">PID Cool dGain</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="PIDC_dGain" size="6" value="'.$f[1].'"> Derivative</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "PIDC_IDLERANGE") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">PID Cool Idle Range</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="PIDC_idleRange" size="6" value="'.$f[1].'"> &deg;C (Cooler margin)</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "FAN_ADDRESS") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Fan Switch Address</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><select name="FanAddress">'.PHP_EOL;
		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
		if (startsWith($devices[0], "212")) {
		    $j = 1;
		    while (1) {
			if (strcmp($devices[$j], ".") == 0)
			    break;
			$g = explode(",", $devices[$j]);
			if (($g[5] == "OUT_ANALOG") || ($g[5] == "OUT_BIN")) {
			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
			}
			$j++;
		    }
		}
		$outstr .= '        </select></td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "FAN_DELAY") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Fan Switch Delay</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="FanDelay" size="5" value="'.$f[1].'"> seconds (0..720)</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "LIGHT_ADDRESS") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Lights Address</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><select name="LightAddress">'.PHP_EOL;
		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
		if (startsWith($devices[0], "212")) {
		    $j = 1;
		    while (1) {
			if (strcmp($devices[$j], ".") == 0)
			    break;
			$g = explode(",", $devices[$j]);
			if (($g[5] == "OUT_ANALOG") || ($g[5] == "OUT_BIN")) {
			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
			}
			$j++;
		    }
		}
		$outstr .= '        </select></td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "LIGHT_DELAY") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Lights Delay</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="LightDelay" size="5" value="'.$f[1].'"> seconds (0..720)</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "DOOR_ADDRESS") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Door Sensor Address</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><select name="DoorAddress">'.PHP_EOL;
		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
		if (startsWith($devices[0], "212")) {               
		    $j = 1;                                                                     
		    while (1) {                                                                                     
		    	if (strcmp($devices[$j], ".") == 0)                                                                                         
			    break;
		    	$g = explode(",", $devices[$j]);
		    	if ($g[5] == "IN_BIN") {
			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
		    	}
		    	$j++;
		    }
		}
		$outstr .= '        </select></td>'.PHP_EOL;                        
		$outstr .= '       </tr>'.PHP_EOL;                                  
	    }
	    if ($f[0] == "PSU_ADDRESS") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Power Supply Sensor Address</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><select name="PSUAddress">'.PHP_EOL;
		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
		if (startsWith($devices[0], "212")) {
		    $j = 1;
		    while (1) {
			if (strcmp($devices[$j], ".") == 0)
			    break;
			$g = explode(",", $devices[$j]);
			if ($g[5] == "IN_BIN") {
			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
			}
			$j++;
		    }
		}
		$outstr .= '        </select></td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "TEMP_SET_MIN") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Min. temp setting</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="TempSetMin" size="5" value="'.$f[1].'"> &deg;C</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    if ($f[0] == "TEMP_SET_MAX") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Max. temp setting</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="TempSetMax" size="5" value="'.$f[1].'"> &deg;C</td>'.PHP_EOL;
		$outstr .= '       </tr>'.PHP_EOL;
	    }
	    $i++;
	}
    }
    $outstr .= '       <tr class="editor">'.PHP_EOL;
    $outstr .= '        <td class="editname"><input type="submit" value="Save" name="key"></td>'.PHP_EOL;
    $outstr .= '        <td class="editfield"><input type="submit" value="Cancel" name="key">';
    $outstr .= '<input type="submit" value="Delete" name="key" style="margin-left: 100px;">';
    $outstr .= '<input type="hidden" value="testdata" name="action">';
    $outstr .= '<input type="hidden" value="'.$command.'" name="command">';
    $outstr .= '<input type="hidden" value="'.$UUID.'" name="UUID"></td>'.PHP_EOL;
    $outstr .= '       </tr>'.PHP_EOL;
    $outstr .= '      </table>'.PHP_EOL;
    $outstr .= '     </form>'.PHP_EOL;
    $outstr .= '    </div> <!-- etable -->'.PHP_EOL;
    $outstr .= build_footer();
    echo $outstr;
}



/*
 * Edit a Unit. Fetches the record data and shows the edit screen.
 *
 * @param string $_GET['action'] Must be 'edit'.
 * @param string $_GET['UUID'] The UUID of the Unit.
 */
function unit_edit() {
    if ($_GET['action'] == 'edit') {
	edit_screen($_GET['UUID'], 'update', 'ThermFerm - Edit Unit', '');
	return;
    } else {
	load('units.php');
    }
}



/*
 * @link edit unit
 * @link add unit
 */
function unit_list() {

    global $arr;

    $outstr  = build_header('ThermFerm - Units Maintenance');
    $outstr .= '    <div id="errors">'.PHP_EOL;
    $outstr .= '    </div> <!-- errors -->'.PHP_EOL;
    $outstr .= '    <div id="etable">'.PHP_EOL;
    $outstr .= '     <table class="setup">'.PHP_EOL;
    $outstr .= '      <tr class="trhead">'.PHP_EOL;
    $outstr .= '       <td class="setup" style="width: 300px;">UUID</td>'.PHP_EOL;
    $outstr .= '       <td class="setup" style="width: 300px;">Name</td>'.PHP_EOL;
    $outstr .= '       <td class="setup" style="width: 60px;">Mode</td>'.PHP_EOL;
    $outstr .= '       <td class="setup" style="width: 40px;">Edit</td>'.PHP_EOL;
    $outstr .= '      </tr>'.PHP_EOL;

    if (startsWith($arr[0], "212")) {
    	$j = 1;
    	while (1) {
	    if (strcmp($arr[$j], ".") == 0)
	    	break;
	    $f = explode(",", $arr[$j]);
	    $outstr .= '      <tr class="setup">'.PHP_EOL;
	    $outstr .= '       <td class="setup">'.$f[0].'</td>'.PHP_EOL;
	    $outstr .= '       <td class="setup">'.$f[1].'</td>'.PHP_EOL;
	    $outstr .= '       <td class="setup">'.$f[2].'</td>'.PHP_EOL;
	    if (strcmp($f[2], "OFF")) {
		$outstr .= '       <td class="setup">Busy</td>'.PHP_EOL;
	    } else {
		$outstr .= '       <td class="setup"><a href="units.php?action=edit&amp;UUID='.$f[0].'">Edit</a></td>'.PHP_EOL;
	    }
	    $outstr .= '      </tr>'.PHP_EOL;
	    $j++;
    	}
    }

    $outstr .= '     </table>'.PHP_EOL;
    $outstr .= '    </div> <!-- etable -->'.PHP_EOL;

    $outstr .= '    <div id="atable">'.PHP_EOL;
    $outstr .= '     <form method="POST" action="units.php">'.PHP_EOL;
    $outstr .= '      <table class="editor">'.PHP_EOL;
    $outstr .= '      <tr class="trhead"><td colspan="3">Add new unit</td></tr>'.PHP_EOL;
    $outstr .= '       <tr class="editor">'.PHP_EOL;
    $outstr .= '        <td class="editname">Unit Name</td>'.PHP_EOL;
    $outstr .= '        <td class="editfield"><input type="text" name="Name" size="50" value=""></td>'.PHP_EOL;
    $outstr .= '        <td class="editsub"><input type="submit" value="Add" name="key"></td>'.PHP_EOL;
    $outstr .= '<input type="hidden" value="0.0" name="Volume">';
    $outstr .= '<input type="hidden" value="" name="AirAddress">';
    $outstr .= '<input type="hidden" value="" name="BeerAddress">';
    $outstr .= '<input type="hidden" value="" name="HeaterAddress">';
    $outstr .= '<input type="hidden" value="20" name="HeaterDelay">';
    $outstr .= '<input type="hidden" value="" name="CoolerAddress">';
    $outstr .= '<input type="hidden" value="20" name="CoolerDelay">';
    $outstr .= '<input type="hidden" value="" name="FanAddress">';
    $outstr .= '<input type="hidden" value="" name="LightAddress">';
    $outstr .= '<input type="hidden" value="1" name="LightDelay">';
    $outstr .= '<input type="hidden" value="" name="DoorAddress">';
    $outstr .= '<input type="hidden" value="" name="PSUAdress">';
    $outstr .= '<input type="hidden" value="1.0" name="TempSetMin">';
    $outstr .= '<input type="hidden" value="30.0" name="TempSetMax">';
    $outstr .= '<input type="hidden" value="100" name="PIDC_iMax">';
    $outstr .= '<input type="hidden" value="4.0" name="PIDC_pGain">';
    $outstr .= '<input type="hidden" value="0.2" name="PIDC_dGain">';
    $outstr .= '<input type="hidden" value="1.0" name="PIDC_iGain">';
    $outstr .= '<input type="hidden" value="1.0" name="PIDC_idleRange">';
    $outstr .= '<input type="hidden" value="100" name="PIDH_iMax">';
    $outstr .= '<input type="hidden" value="4.0" name="PIDH_pGain">';
    $outstr .= '<input type="hidden" value="0.2" name="PIDH_dGain">';
    $outstr .= '<input type="hidden" value="1.0" name="PIDH_iGain">';
    $outstr .= '<input type="hidden" value="1.0" name="PIDH_idleRange">';
    $outstr .= '<input type="hidden" value="testdata" name="action">';
    $outstr .= '<input type="hidden" value="add" name="command">';
    $outstr .= '<input type="hidden" value="00000000-0000-0000-0000-000000000000" name="UUID">';
    $outstr .= '       </tr>'.PHP_EOL;
    $outstr .= '      </table>'.PHP_EOL;
    $outstr .= '     </form>'.PHP_EOL;
    $outstr .= '    </div> <!-- atable -->'.PHP_EOL;
    $outstr .= build_footer();
    echo $outstr;
}

mercurial