www-thermferm/profiles.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 274
111b0e9663dc
child 378
313efe6bf5b3
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
 *   
 * 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');

/*
 * Each time this page is loaded, get the profiles from the server.
 * $arr contains the complete reply of he PROFILE LIST command.
 */
$answer = send_cmd("PROFILE LIST");
$arr = explode("\r\n", $answer);



if (isset($_GET['action'])) {
    switch ($_GET['action']) {
	case 'edit':		profile_edit();
				break;
	case 'esteps':		profile_steps();
				break;
	default:		break;
    }
} elseif (isset($_POST['action'])) {
    switch ($_POST['action']) {
	case 'testdata':	testdata();
				break;
	case 'teststeps':	teststeps();
				break;
	default:		break;
    }
} else {
    profile_list();
}

exit;



/*
 * Profile steps
 */
function profile_steps()
{
    global $arr;
    $UUID = $_GET['UUID'];
    
    /*
     * $steps contains all steps of a profile
     */
    $steps = array (
	1  => array("steptime" => 0, "resttime" => 0, "target" => 20.0 ),
	2  => array("steptime" => 0, "resttime" => 0, "target" => 20.0 ),
	3  => array("steptime" => 0, "resttime" => 0, "target" => 20.0 ),
	4  => array("steptime" => 0, "resttime" => 0, "target" => 20.0 ),
	5  => array("steptime" => 0, "resttime" => 0, "target" => 20.0 ),
	6  => array("steptime" => 0, "resttime" => 0, "target" => 20.0 ),
	7  => array("steptime" => 0, "resttime" => 0, "target" => 20.0 ),
	8  => array("steptime" => 0, "resttime" => 0, "target" => 20.0 ),
    );

    $answer = send_cmd("PROFILE GETS ".$UUID);
    $psteps = explode("\r\n", $answer);

    if (startsWith($arr[0], "212")) {
	$j = 1;
	while (1) {
	    if (strcmp($psteps[$j], ".") == 0)
		break;
	    $f = explode(",", $psteps[$j]);
	    $steps[$j]["steptime"] = $f[0];
	    $steps[$j]["resttime"] = $f[1];
	    $steps[$j]["target"] = $f[2];
	    $j++;
	}
    }

    edit_steps($UUID, $steps, "", "ThermFerm - Edit Profile Steps");
}


function edit_steps($UUID, $steps, $error_message, $heading)
{
    $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="profiles.php">'.PHP_EOL;
    $outstr .= '      <table class="editor">'.PHP_EOL;
    $outstr .= '       <tr class="trhead">'.PHP_EOL;
    $outstr .= '        <td>Step</td>'.PHP_EOL;
    $outstr .= '        <td>Steptime</td>'.PHP_EOL;
    $outstr .= '        <td>Resttime</td>'.PHP_EOL;
    $outstr .= '        <td>Temperature</td>'.PHP_EOL;
    $outstr .= '       </tr>'.PHP_EOL;

    for ($i = 1; $i <= 8; $i++) {
    	$outstr .= '       <tr class="editor">'.PHP_EOL;
    	$outstr .= '        <td>Step '.$i.'</td>'.PHP_EOL;
    	$outstr .= '        <td><input type="text" name="steptime'.$i.'" size="4" value="'.$steps[$i]["steptime"].'"></td>'.PHP_EOL;
    	$outstr .= '        <td><input type="text" name="resttime'.$i.'" size="4" value="'.$steps[$i]["resttime"].'"></td>'.PHP_EOL;
    	$outstr .= '        <td><input type="text" name="target'.$i.'" size="4" value="'.$steps[$i]["target"].'"></td>'.PHP_EOL;
    	$outstr .= '       </tr>'.PHP_EOL;
    }

    $outstr .= '       <tr class="editor">'.PHP_EOL;
    $outstr .= '        <td class="editname">&nbsp;</td>'.PHP_EOL;
    $outstr .= '        <td class="editname"><input type="submit" value="Save" name="key"></td>'.PHP_EOL;
    $outstr .= '        <td class="editname"><input type="submit" value="Cancel" name="key">';
    $outstr .= '<input type="hidden" value="teststeps" name="action">';
    $outstr .= '<input type="hidden" value="'.$UUID.'" name="UUID"></td>'.PHP_EOL;
    $outstr .= '        <td class="editname">&nbsp;</td>'.PHP_EOL;
    $outstr .= '       </tr>'.PHP_EOL;
    $outstr .= '      </table>'.PHP_EOL;
    $outstr .= '     </form>'.PHP_EOL;
    $outstr .= '    </div> <!-- etable -->'.PHP_EOL;
    $outstr .= '    <div id="atable" style="margin-left: 100px; width:780px;">'.PHP_EOL;
    $outstr .= '    The steptime is the time to go from the previous to the target temperature.'.PHP_EOL;
    $outstr .= '    The resttime is the time in this step holding the target temperature.'.PHP_EOL;
    $outstr .= '    The duration of the step is steptime + resttime.'.PHP_EOL;
    $outstr .= '    Steps are valid if the steptime or resttime is greater then zero.'.PHP_EOL;
    $outstr .= '    Order is important.'.PHP_EOL;
    $outstr .= '    Lines with a zero steptime and zero resttime are ignored.'.PHP_EOL;
    $outstr .= '    The step- and resttimes are in hours.'.PHP_EOL;
    $outstr .= '    </div> <!-- atable -->'.PHP_EOL;
    $outstr .= build_footer();
    echo $outstr;
}




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

    if ($_POST['key'] == 'Add') {
	send_cmd("PROFILE ADD ".$_POST['Name']);
    }
    unset($_POST['UUID']);
    unset($_POST['Name']);
    unset($_POST['Steps']);
    unset($_POST['key']);
    unset($_POST['command']);
    load('profiles.php');
}



/*
 * Profile update or delete
 *
 * @param string $_POST['UUID'] The profile UUID
 * @param string $_POST['Name'] The profile name
 * @param string $_POST['Inittemp'] The profile initial temperature
 * @param string $_POST['key'] The button pressed.
 */
function profile_update() {
    /*
     * Build the update command
     */
    if ($_POST['key'] == 'Delete') {
	send_cmd("PROFILE DEL ".$_POST['UUID']);
    }

    if ($_POST['key'] == 'Save') {
	$cmd = array("PROFILE PUT ".$_POST['UUID']);
	$cmd[] = "NAME,".$_POST['Name'];
	$cmd[] = "INITTEMP,".$_POST['Inittemp'];
	$cmd[] = ".";
	send_array($cmd);
    }

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



/*
 * Test input of a modified or new profile.
 *
 * @param string $_POST['UUID'] Unique record UUID
 * @param int $_POST['steptime'n] Profile steptime
 * @param int $_POST['resttime'n] Profile resttime
 * @param float $_POST['target'n] Profile target temperature
 * @param string $_POST['key'] Key choice, Save or Cancel
 *
 * Return: 0 = Ok
 *         1 = Missing data
 *         3 = A target temperature out of range
 *        99 = Cancel key
 */
function test_thesteps() {

    global $arr;

    for ($i = 1; $i <= 8; $i++) {
	if ((! isset($_POST['steptime'.$i])) || (! isset($_POST['resttime'.$i])) || (! isset($_POST['target'.$i])))
		return 1;
	if ((strlen($_POST['steptime'.$i]) == 0) || (strlen($_POST['resttime'.$i]) == 0) || (strlen($_POST['target'.$i]) == 0))
		return 1;
    }

    if (isset($_POST['UUID']) && isset($_POST['key'])) {

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

	for ($i = 1; $i <= 8; $i++) {

	    if (($_POST['target'.$i] < -5) || ($_POST['target'.$i] > 30))
		return 3;
	}
    } else {
        return 1;
    }

    return 0;
}



/*
 * Test result from edit_steps screen and do next action
 */
function teststeps() {

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

    switch ($result) {
    	case 0: $sock = open_socket();
		if ($sock != false) {
		    socket_write($sock, 'PROFILE PUTS '.$_POST['UUID'], 4096);
		    for ($i = 1; $i <= 8; $i++) {
			/*
			 * Use small delays so the remote really sees single lines.
			 * This is a real bug between client/server programming,
			 * the PHP side is line oriented, the server is reading blocks.
			 * So we just send the data slowly and the server just sees lines.
			 */
			if (($_POST['steptime'.$i] > 0) || ($_POST['resttime'.$i] > 0)) {
			    usleep(20000);
			    socket_write($sock, $_POST['steptime'.$i].','.$_POST['resttime'.$i].','.$_POST['target'.$i], 4096);
			}
			unset($_POST['steptime'.$i]);
			unset($_POST['resttime'.$i]);
			unset($_POST['target'.$i]);
		    }
		    usleep(20000);
		    socket_write($sock, '.', 4096);
		    /* Absorb response */
		    while (1) {
			$line = socket_read($sock, 4096);
			if ($line === '')
			    break;
		    }
		    socket_close($sock);
		    unset($_POST['UUID']);
		    unset($_POST['key']);
		    load('profiles.php');
		    return;
    		}
		break;
        case 1: $error = 'Missing data';
		break;
	case 2: $error = 'A resttime is shorter then the steptime';
		break;
	case 3:	$error = 'A target temperature is out of range';
		break;
        case 99:
                load('profiles.php');
                break;
    }

    $steps = array (
	1  => array("steptime" => $_POST['steptime1'], "resttime" => $_POST['resttime1'], "target" => $_POST['target1'] ),
	2  => array("steptime" => $_POST['steptime2'], "resttime" => $_POST['resttime2'], "target" => $_POST['target2'] ),
	3  => array("steptime" => $_POST['steptime3'], "resttime" => $_POST['resttime3'], "target" => $_POST['target3'] ),
	4  => array("steptime" => $_POST['steptime4'], "resttime" => $_POST['resttime4'], "target" => $_POST['target4'] ),
	5  => array("steptime" => $_POST['steptime5'], "resttime" => $_POST['resttime5'], "target" => $_POST['target5'] ),
	6  => array("steptime" => $_POST['steptime6'], "resttime" => $_POST['resttime6'], "target" => $_POST['target6'] ),
	7  => array("steptime" => $_POST['steptime7'], "resttime" => $_POST['resttime7'], "target" => $_POST['target7'] ),
	8  => array("steptime" => $_POST['steptime8'], "resttime" => $_POST['resttime8'], "target" => $_POST['target8'] ),
    );
    
    edit_steps($_POST['UUID'], $steps, $error, "ThermFerm - Edit Profile Steps");
}



/*
 * Test input of a modified or new profile.
 *
 * @param string $_POST['UUID'] Unique record UUID
 * @param string $_POST['Name'] Profile name
 * @param float $_POST['Inittemp'] Profile initial temperature
 * @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
 *        99 = Cancel key
 */
function test_thedata() {

    global $arr;

    if (isset($_POST['UUID']) && isset($_POST['Name']) && isset($_POST['Inittemp']) && 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++;
	    }
	}

    } 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') {
		    profile_add();
		    return;
	        } else if ($_POST['command'] == 'update') {
		    profile_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 99:	
		load('profiles.php');
		break;
    }

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

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



/*
 * Profiles edit screen. Used by profile_edit(), profile_add() and testdata()
 *
 * @param string $UUID The record UUID (fixed).
 * @param string $Name The Profile Name.
 * @param string $command 'add' or 'update'
 * @param string $heading Pagina heading title.
 * @Param string $error_message Blank or previous error.
 */
function edit_screen($UUID, $command, $heading, $error_message) {

    /*
     * Get current profile data
     */
    $answer = send_cmd("PROFILE 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="profiles.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">Profile 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] == "INITTEMP") {
		$outstr .= '       <tr class="editor">'.PHP_EOL;
		$outstr .= '        <td class="editname">Initial temperature</td>'.PHP_EOL;
		$outstr .= '        <td class="editfield"><input type="text" name="Inittemp" size="5" value="'.$f[1].'"></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 Profile. Fetches the record data and shows the edit screen.
 *
 * @param string $_GET['action'] Must be 'edit'.
 * @param string $_GET['UUID'] The UUID of the Profile.
 */
function profile_edit() {
    if ($_GET['action'] == 'edit') {
	edit_screen($_GET['UUID'], 'update', 'ThermFerm - Edit Profile', '');
	return;
    } else {
	load('profiles.php');
    }
}



/*
 * @link Edit profile
 * @link Add profile
 */
function profile_list() {

    global $arr;

    $outstr  = build_header("ThermFerm - Profiles");

    $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: 40px;">Steps</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;
	    if ($f[3] == 1) {
		$outstr .= '       <td class="setup">'.$f[2].'</td>'.PHP_EOL;
	    	$outstr .= '       <td class="setup">Busy</td>'.PHP_EOL;
	    } else {
		$outstr .= '       <td class="setup"><a href="profiles.php?action=esteps&amp;UUID='.$f[0].'">'.$f[2].'</a></td>'.PHP_EOL;
		$outstr .= '       <td class="setup"><a href="profiles.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="profiles.php">'.PHP_EOL;
    $outstr .= '      <table class="editor">'.PHP_EOL;
    $outstr .= '      <tr class="trhead"><td colspan="3">Add new profile</td></tr>'.PHP_EOL;
    $outstr .= '       <tr class="editor">'.PHP_EOL;
    $outstr .= '        <td class="editname">Profile 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="testdata" name="action">';
    $outstr .= '<input type="hidden" value="add" name="command">';
    $outstr .= '<input type="hidden" value="00000000-0000-0000-0000-000000000000" name="UUID">';
    $outstr .= '<input type="hidden" value="20.0" name="Inittemp"></td>';
    $outstr .= '       </tr>'.PHP_EOL;
    $outstr .= '      </table>'.PHP_EOL;
    $outstr .= '     </form>'.PHP_EOL;

    $outstr .= '    </div> <!-- atable -->'.PHP_EOL;
    $outstr .= build_footer();
    echo $outstr;
}

mercurial