# HG changeset patch # User Michiel Broek # Date 1713970005 -7200 # Node ID 344470c6bb1cafe08b79acc6326f2ce2b33fe6dd # Parent d77891f8915dd5990ab345768603ecff4cf8d5fb Fermenter editor layout is ready. Load record done. Add and Delete a new fermenter is done. diff -r d77891f8915d -r 344470c6bb1c thermferm/mqtt.c --- a/thermferm/mqtt.c Wed Apr 24 11:04:00 2024 +0200 +++ b/thermferm/mqtt.c Wed Apr 24 16:46:45 2024 +0200 @@ -936,6 +936,9 @@ payload = xstrcat(payload, (char *)"\",\"temperature\":"); sprintf(buf, "%.3f", unit->air_temperature / 1000.0); payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"idx\":"); + sprintf(buf, "%d", unit->air_idx); + payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)"}"); pub_domoticz_temp(unit->air_idx, unit->air_temperature); } else { @@ -953,6 +956,9 @@ payload = xstrcat(payload, (char *)"\",\"temperature\":"); sprintf(buf, "%.3f", unit->beer_temperature / 1000.0); payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"idx\":"); + sprintf(buf, "%d", unit->beer_idx); + payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)"}"); pub_domoticz_temp(unit->beer_idx, unit->beer_temperature); } else { @@ -970,6 +976,9 @@ payload = xstrcat(payload, (char *)"\",\"temperature\":"); sprintf(buf, "%.3f", unit->chiller_temperature / 1000.0); payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"idx\":"); + sprintf(buf, "%d", unit->chiller_idx); + payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)"}"); pub_domoticz_temp(unit->chiller_idx, unit->chiller_temperature); } else { @@ -988,6 +997,12 @@ payload = xstrcat(payload, (char *)",\"usage\":"); sprintf(buf, "%d", unit->heater_usage); payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"idx\":"); + sprintf(buf, "%d", unit->heater_idx); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"delay\":"); + sprintf(buf, "%d", unit->heater_delay); + payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)"}"); pub_domoticz_output(unit->heater_idx, unit->heater_state); } else { @@ -1006,6 +1021,12 @@ payload = xstrcat(payload, (char *)",\"usage\":"); sprintf(buf, "%d", unit->cooler_usage); payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"idx\":"); + sprintf(buf, "%d", unit->cooler_idx); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"delay\":"); + sprintf(buf, "%d", unit->cooler_delay); + payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)"}"); pub_domoticz_output(unit->cooler_idx, unit->cooler_state); } else { @@ -1024,6 +1045,12 @@ payload = xstrcat(payload, (char *)",\"usage\":"); sprintf(buf, "%d", unit->fan_usage); payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"idx\":"); + sprintf(buf, "%d", unit->fan_idx); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"delay\":"); + sprintf(buf, "%d", unit->fan_delay); + payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)"}"); pub_domoticz_output(unit->fan_idx, unit->fan_state); } else { @@ -1042,6 +1069,12 @@ payload = xstrcat(payload, (char *)",\"usage\":"); sprintf(buf, "%d", unit->light_usage); payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"idx\":"); + sprintf(buf, "%d", unit->light_idx); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"delay\":"); + sprintf(buf, "%d", unit->light_delay); + payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)"}"); pub_domoticz_output(unit->light_idx, unit->light_state); } else { @@ -1057,6 +1090,9 @@ payload = xstrcat(payload, (char *)"\",\"state\":"); sprintf(buf, "%d", (unit->door_state) ? 0:1); payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"idx\":"); + sprintf(buf, "%d", unit->door_idx); + payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)"}"); pub_domoticz_output(unit->door_idx, unit->door_state); } else { @@ -1072,6 +1108,9 @@ payload = xstrcat(payload, (char *)"\",\"state\":"); sprintf(buf, "%d", unit->psu_state); payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"idx\":"); + sprintf(buf, "%d", unit->psu_idx); + payload = xstrcat(payload, buf); payload = xstrcat(payload, (char *)"}"); pub_domoticz_output(unit->psu_idx, unit->psu_state); } else { @@ -1095,6 +1134,38 @@ sprintf(buf, "%d", unit->alarm_flag); payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"pidc\":{\"P\":"); + sprintf(buf, "%.3f", unit->PID_cool->pGain); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"I\":"); + sprintf(buf, "%.3f", unit->PID_cool->iGain); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"D\":"); + sprintf(buf, "%.3f", unit->PID_cool->dGain); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"imax\":"); + sprintf(buf, "%.1f", unit->PID_cool->iMax); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"idle\":"); + sprintf(buf, "%.2f", unit->PID_cool->idleRange); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)"},\"pidh\":{\"P\":"); + sprintf(buf, "%.3f", unit->PID_heat->pGain); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"I\":"); + sprintf(buf, "%.3f", unit->PID_heat->iGain); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"D\":"); + sprintf(buf, "%.3f", unit->PID_heat->dGain); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"imax\":"); + sprintf(buf, "%.1f", unit->PID_heat->iMax); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)",\"idle\":"); + sprintf(buf, "%.2f", unit->PID_heat->idleRange); + payload = xstrcat(payload, buf); + payload = xstrcat(payload, (char *)"}"); + /* * Loaded profile and state */ diff -r d77891f8915d -r 344470c6bb1c thermferm/server.c --- a/thermferm/server.c Wed Apr 24 11:04:00 2024 +0200 +++ b/thermferm/server.c Wed Apr 24 16:46:45 2024 +0200 @@ -1550,6 +1550,9 @@ unit->PID_heat = (pid_var *)malloc(sizeof(pid_var)); InitPID(unit->PID_cool, PID_TYPE_COOL); InitPID(unit->PID_heat, PID_TYPE_HEAT); + unit->PID_heat->pGain = unit->PID_cool->pGain = 5000.0; + unit->PID_heat->iGain = unit->PID_cool->iGain = 25.0; + unit->PID_heat->dGain = unit->PID_cool->dGain = 5.0; /* * Block main process diff -r d77891f8915d -r 344470c6bb1c www/dbfermenters.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/www/dbfermenters.php Wed Apr 24 16:46:45 2024 +0200 @@ -0,0 +1,163 @@ + 15, 'usec' => 0)); + } else { + socket_close($sock); + } + } + return $sock; +} + + +/** + * @param string $command to send to the server. + * @return string with the complete reply from the + * server. This can be a multiline reply. + */ +function send_cmd($command) +{ + $sock = open_socket(); + if ($sock == false) { + return ""; + } + socket_write($sock, $command . "\r\n", 4096); + + $answer = ""; + while (1) { + $line = socket_read($sock, 4096); + if ($line === '') + break; + $answer .= $line; + } + socket_close($sock); + + return $answer; +} + + +function startsWith($haystack, $needle) +{ + return !strncmp($haystack, $needle, strlen($needle)); +} + + +$response = array( + 'error' => false, + 'msg' => 'Ok', +); + + +if (isset($_POST['update'])) { + + $cmd = "UNIT PUT " . $_POST['uuid'] . "\r\n"; + if (isset($_POST['air_address'])) { + $cmd .= "AIR_ADDRESS," . $_POST['air_address'] . "\r\n"; + $cmd .= "AIR_IDX," . $_POST['air_idx'] . "\r\n"; + } + if (isset($_POST['beer_address'])) { + $cmd .= "BEER_ADDRESS," . $_POST['beer_address'] . "\r\n"; + if (isset($_POST['beer_address2'])) + $cmd .= "BEER_ADDRESS2," . $_POST['beer_address2'] . "\r\n"; + $cmd .= "BEER_IDX," . $_POST['beer_idx'] . "\r\n"; + } + if (isset($_POST['chiller_address'])) { + $cmd .= "CHILLER_ADDRESS," . $_POST['chiller_address'] . "\r\n"; + $cmd .= "CHILLER_IDX," . $_POST['chiller_idx'] . "\r\n"; + } + if (isset($_POST['heater_address'])) { + $cmd .= "HEATER_ADDRESS," . $_POST['heater_address'] . "\r\n"; + $cmd .= "HEATER_STATE," . $_POST['heater_state'] . "\r\n"; + $cmd .= "HEATER_DELAY," . $_POST['heater_delay'] . "\r\n"; + $cmd .= "HEATER_IDX," . $_POST['heater_idx'] . "\r\n"; + } + if (isset($_POST['cooler_address'])) { + $cmd .= "COOLER_ADDRESS," . $_POST['cooler_address'] . "\r\n"; + $cmd .= "COOLER_STATE," . $_POST['cooler_state'] . "\r\n"; + $cmd .= "COOLER_DELAY," . $_POST['cooler_delay'] . "\r\n"; + $cmd .= "COOLER_IDX," . $_POST['cooler_idx'] . "\r\n"; + } + if (isset($_POST['fan_address'])) { + $cmd .= "FAN_ADDRESS," . $_POST['fan_address'] . "\r\n"; + $cmd .= "FAN_STATE," . $_POST['fan_state'] . "\r\n"; + $cmd .= "FAN_DELAY," . $_POST['fan_delay'] . "\r\n"; + $cmd .= "FAN_IDX," . $_POST['fan_idx'] . "\r\n"; + } + if (isset($_POST['light_address'])) { + $cmd .= "LIGHT_ADDRESS," . $_POST['light_address'] . "\r\n"; + $cmd .= "LIGHT_STATE," . $_POST['light_state'] . "\r\n"; + $cmd .= "LIGHT_DELAY," . $_POST['light_delay'] . "\r\n"; + $cmd .= "LIGHT_IDX," . $_POST['light_idx'] . "\r\n"; + } + if (isset($_POST['door_address'])) { + $cmd .= "DOOR_ADDRESS," . $_POST['door_address'] . "\r\n"; + $cmd .= "DOOR_IDX," . $_POST['door_idx'] . "\r\n"; + } + if (isset($_POST['psu_address'])) { + $cmd .= "PSU_ADDRESS," . $_POST['psu_address'] . "\r\n"; + $cmd .= "PSU_IDX," . $_POST['psu_idx'] . "\r\n"; + } + $cmd .= "STAGE," . $_POST['stage'] . "\r\n"; + $cmd .= "MODE," . $_POST['mode'] . "\r\n"; + $cmd .= "PIDC_IMAX," . $_POST['pidc_imax'] . "\r\n"; + $cmd .= "PIDC_PGAIN," . $_POST['pidc_pgain'] . "\r\n"; + $cmd .= "PIDC_IGAIN," . $_POST['pidc_igain'] . "\r\n"; + $cmd .= "PIDC_DGAIN," . $_POST['pidc_dgain'] . "\r\n"; + $cmd .= "PIDC_IDLERANGE," . $_POST['pidc_idlerange'] . "\r\n"; + $cmd .= "PIDH_IMAX," . $_POST['pidh_imax'] . "\r\n"; + $cmd .= "PIDH_PGAIN," . $_POST['pidh_pgain'] . "\r\n"; + $cmd .= "PIDH_IGAIN," . $_POST['pidh_igain'] . "\r\n"; + $cmd .= "PIDH_DGAIN," . $_POST['pidh_dgain'] . "\r\n"; + $cmd .= "PIDH_IDLERANGE," . $_POST['pidh_idlerange'] . "\r\n"; + $cmd .= "TEMP_SET_MIN," . $_POST['temp_set_min'] . "\r\n"; + $cmd .= "TEMP_SET_MAX," . $_POST['temp_set_max'] . "\r\n"; + $cmd .= "."; + $answer = send_cmd($cmd); + $arr = explode("\r\n", $answer); + if (! startsWith($arr[0], "219")) { + $response['error'] = true; + $response['msg'] = $arr[0]; + } + exit(json_encode($response)); + +} else if (isset($_POST['add'])) { + + // Name is not used and is generated. + $answer = send_cmd("UNIT ADD " . $_POST['name']); + $arr = explode("\r\n", $answer); + if (! startsWith($arr[0], "211")) { + $response['error'] = true; + $response['msg'] = $arr[0]; + } + exit(json_encode($response)); + +} else if (isset($_POST['del'])) { + + $answer = send_cmd("UNIT DEL " . $_POST['uuid']); + $arr = explode("\r\n", $answer); + if (! startsWith($arr[0], "211")) { + $response['error'] = true; + $response['msg'] = $arr[0]; + } + exit(json_encode($response)); + +} else { + + $answer = send_cmd("UNIT JSON"); + header("Content-type: application/json"); + + $arr = explode("\r\n", $answer); + if (startsWith($arr[0], "212")) { + echo $arr[1]; + } else { + echo '{}'; + } +} + +?> diff -r d77891f8915d -r 344470c6bb1c www/drop_contacts.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/www/drop_contacts.php Wed Apr 24 16:46:45 2024 +0200 @@ -0,0 +1,79 @@ + 15, 'usec' => 0)); + } else { + socket_close($sock); + } + } + return $sock; +} + + +/** + * @param string $command to send to the server. + * @return string with the complete reply from the + * server. This can be a multiline reply. + */ +function send_cmd($command) +{ + $sock = open_socket(); + if ($sock == false) { + return ""; + } + socket_write($sock, $command . "\r\n", 4096); + + $answer = ""; + while (1) { + $line = socket_read($sock, 4096); + if ($line === '') + break; + $answer .= $line; + } + socket_close($sock); + + return $answer; +} + + +function startsWith($haystack, $needle) +{ + return !strncmp($haystack, $needle, strlen($needle)); +} + +$answer = send_cmd("DEVICES JSON"); + +$arr = explode("\r\n", $answer); +if (startsWith($arr[0], "212")) { + + /* + * Build reply with only temperature sensors. + */ + $sensors[] = array( + 'uuid' => '', + 'name' => 'Not Assigned' + ); + + $rows = json_decode($arr[1], true); + + foreach($rows as $item) { + if ($item['direction'] == "IN_BIN") { + $sensors[] = array( + 'uuid' => $item['uuid'], + 'name' => $item['description']." ".$item['comment'] + ); + } + } + header("Content-type: application/json"); + exit(json_encode($sensors)); +} + +header("Content-type: application/json"); +echo '{}'; + +?> diff -r d77891f8915d -r 344470c6bb1c www/drop_switches.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/www/drop_switches.php Wed Apr 24 16:46:45 2024 +0200 @@ -0,0 +1,79 @@ + 15, 'usec' => 0)); + } else { + socket_close($sock); + } + } + return $sock; +} + + +/** + * @param string $command to send to the server. + * @return string with the complete reply from the + * server. This can be a multiline reply. + */ +function send_cmd($command) +{ + $sock = open_socket(); + if ($sock == false) { + return ""; + } + socket_write($sock, $command . "\r\n", 4096); + + $answer = ""; + while (1) { + $line = socket_read($sock, 4096); + if ($line === '') + break; + $answer .= $line; + } + socket_close($sock); + + return $answer; +} + + +function startsWith($haystack, $needle) +{ + return !strncmp($haystack, $needle, strlen($needle)); +} + +$answer = send_cmd("DEVICES JSON"); + +$arr = explode("\r\n", $answer); +if (startsWith($arr[0], "212")) { + + /* + * Build reply with only temperature sensors. + */ + $sensors[] = array( + 'uuid' => '', + 'name' => 'Not Assigned' + ); + + $rows = json_decode($arr[1], true); + + foreach($rows as $item) { + if ($item['direction'] == "OUT_BIN") { + $sensors[] = array( + 'uuid' => $item['uuid'], + 'name' => $item['description']." ".$item['comment'] + ); + } + } + header("Content-type: application/json"); + exit(json_encode($sensors)); +} + +header("Content-type: application/json"); +echo '{}'; + +?> diff -r d77891f8915d -r 344470c6bb1c www/includes/global.inc.php --- a/www/includes/global.inc.php Wed Apr 24 11:04:00 2024 +0200 +++ b/www/includes/global.inc.php Wed Apr 24 16:46:45 2024 +0200 @@ -198,9 +198,9 @@ Press "Cancel" to close without deleting this record.
-
+
- +
diff -r d77891f8915d -r 344470c6bb1c www/js/global.js --- a/www/js/global.js Wed Apr 24 11:04:00 2024 +0200 +++ b/www/js/global.js Wed Apr 24 16:46:45 2024 +0200 @@ -56,14 +56,42 @@ }, tempsensorlist = new $.jqx.dataAdapter(tempsensorSource), +// Switches dropdown list +switchesSource = { + datatype: 'json', + datafields: [ + { name: 'uuid', type: 'string' }, + { name: 'name', type: 'string' } + ], + url: 'drop_switches.php' +}, +switcheslist = new $.jqx.dataAdapter(switchesSource), + +// Contacts dropdown list +contactsSource = { + datatype: 'json', + datafields: [ + { name: 'uuid', type: 'string' }, + { name: 'name', type: 'string' } + ], + url: 'drop_contacts.php' +}, +contactslist = new $.jqx.dataAdapter(contactsSource), + + // options for editors Show0dec = { inputMode: 'simple', theme: theme, width: 90, height: 23, readOnly: true, decimalDigits: 0 }, Show1dec = { inputMode: 'simple', theme: theme, width: 90, height: 23, readOnly: true, decimalDigits: 1 }, Spin0dec = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, decimalDigits: 0, spinButtons: true }, +Spin1dec = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, decimalDigits: 1, spinButtons: true }, +Spin2dec = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, decimalDigits: 2, spinButtons: true }, +Spin3dec = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, decimalDigits: 3, spinButtons: true }, PosInt = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, decimalDigits: 0, spinButtons: true }, SubInt = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, max: 63, decimalDigits: 0, spinButtons: true }, - GPIOInt = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: -1, max:31, decimalDigits: 0, spinButtons: true }; + GPIOInt = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: -1, max:31, decimalDigits: 0, spinButtons: true }, +Perc1dec = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, max: 100, decimalDigits: 1, spinButtons: true }, + Perc0 = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, max: 100, decimalDigits: 0, spinButtons: true }; /* Websocket interface. Place "websocket.onmessage = function(evt) {}" in the user script. */ diff -r d77891f8915d -r 344470c6bb1c www/js/set_devices.js --- a/www/js/set_devices.js Wed Apr 24 11:04:00 2024 +0200 +++ b/www/js/set_devices.js Wed Apr 24 16:46:45 2024 +0200 @@ -24,8 +24,8 @@ function createDelElements() { $('#eventWindow').jqxWindow({ theme: theme, - position: { x: 490, y: 210 }, - width: 300, + position: { x: 430, y: 210 }, + width: 420, height: 175, resizable: false, isModal: true, diff -r d77891f8915d -r 344470c6bb1c www/js/set_fermenters.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/www/js/set_fermenters.js Wed Apr 24 16:46:45 2024 +0200 @@ -0,0 +1,373 @@ +/***************************************************************************** + * Copyright (C) 2024 + * + * Michiel Broek + * + * This file is part of mbsePi-apps + * + * 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. + * + * BrewCloud 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. + *****************************************************************************/ + + +function createDelElements() { + $('#eventWindow').jqxWindow({ + theme: theme, + position: { x: 430, y: 210 }, + width: 420, + height: 175, + resizable: false, + isModal: true, + modalOpacity: 0.4, + okButton: $('#delOk'), + cancelButton: $('#delCancel'), + initContent: function() { + $('#delOk').jqxButton({ template: 'danger', width: '65px', theme: theme }); + $('#delCancel').jqxButton({ template: 'success', width: '65px', theme: theme }); + $('#delCancel').focus(); + } + }); + $('#eventWindow').jqxWindow('hide'); +} + + +function createAddElements() { + $('#addWindow').jqxWindow({ + theme: theme, + position: { x: 400, y: 210 }, + width: 480, + height: 180, + resizable: false, + isModal: true, + modalOpacity: 0.4, + okButton: $('#addOk'), + cancelButton: $('#addCancel'), + initContent: function() { + $('#addOk').jqxButton({ template: 'success', width: '65px', theme: theme }); + $('#addCancel').jqxButton({ template: 'primary', width: '65px', theme: theme }); + $('#addCancel').focus(); + } + }); + $('#addWindow').jqxWindow('hide'); +} + + + +$(document).ready(function() { + var dataRecord = {}, + url = 'dbfermenters.php', + source = { + datatype: 'json', + cache: false, + datafields: [ + { name: 'uuid', type: 'string' }, + { name: 'alias', type: 'string' }, + { name: 'product_code', map: 'product>code' }, + { name: 'product_name', map: 'product>name' }, + { name: 'air_address', map: 'air>address' }, + { name: 'air_idx', map: 'air>idx', type: 'int' }, + { name: 'beer_address', map: 'beer>address' }, + { name: 'beer_idx', map: 'beer>idx', type: 'int' }, + { name: 'chiller_address', map: 'chiller>address' }, + { name: 'chiller_idx', map: 'chiller>idx', type: 'int' }, + { name: 'light_address', map: 'light>address' }, + { name: 'light_state', map: 'light>state', type: 'int' }, + { name: 'light_delay', map: 'light>delay', type: 'int' }, + { name: 'light_idx', map: 'light>idx', type: 'int' }, + { name: 'heater_address', map: 'heater>address' }, + { name: 'heater_state', map: 'heater>state', type: 'int' }, + { name: 'heater_delay', map: 'heater>delay', type: 'int' }, + { name: 'heater_idx', map: 'heater>idx', type: 'int' }, + { name: 'cooler_address', map: 'cooler>address' }, + { name: 'cooler_state', map: 'cooler>state', type: 'int' }, + { name: 'cooler_delay', map: 'cooler>delay', type: 'int' }, + { name: 'cooler_idx', map: 'cooler>idx', type: 'int' }, + { name: 'fan_address', map: 'fan>address' }, + { name: 'fan_state', map: 'fan>state', type: 'int' }, + { name: 'fan_delay', map: 'fan>delay', type: 'int' }, + { name: 'fan_idx', map: 'fan>idx', type: 'int' }, + { name: 'door_address', map: 'door>address' }, + { name: 'door_idx', map: 'door>idx', type: 'int' }, + { name: 'door_state', map: 'door>state', type: 'int' }, + { name: 'psu_address', map: 'psu>address' }, + { name: 'psu_idx', map: 'psu>idx', type: 'int' }, + { name: 'psu_state', map: 'psu>state', type: 'int' }, + { name: 'stage' }, + { name: 'mode' }, + { name: 'setpoint_low', map: 'setpoint>low', type: 'float' }, + { name: 'setpoint_high', map: 'setpoint>high', type: 'float' }, + { name: 'alarm', type: 'int' }, + { name: 'pidc_p', map: 'pidc>P', type: 'float' }, + { name: 'pidc_i', map: 'pidc>I', type: 'float' }, + { name: 'pidc_d', map: 'pidc>D', type: 'float' }, + { name: 'pidc_imax', map: 'pidc>imax', type: 'float' }, + { name: 'pidc_idle', map: 'pidc>idle', type: 'float' }, + { name: 'pidh_p', map: 'pidh>P', type: 'float' }, + { name: 'pidh_i', map: 'pidh>I', type: 'float' }, + { name: 'pidh_d', map: 'pidh>D', type: 'float' }, + { name: 'pidh_imax', map: 'pidh>imax', type: 'float' }, + { name: 'pidh_idle', map: 'pidh>idle', type: 'float' } + ], + id: 'uuid', + url: url + }, + dataAdapter = new $.jqx.dataAdapter(source), + editrow = -1; + + // initialize the input fields. + $('#uuid').jqxInput({ theme: theme, width: 360, height: 23 }); + $('#alias').jqxInput({ theme: theme, width: 120, height: 23 }); + $('#product_code').jqxInput({ theme: theme, width: 120, height: 23 }); + $('#product_name').jqxInput({ theme: theme, width: 360, height: 23 }); + $('#mode').jqxInput({ theme: theme, width: 120, height: 23 }); + $('#stage').jqxInput({ theme: theme, width: 120, height: 23 }); + $('#air_address,#beer_address,#beer_address2,#chiller_address').jqxDropDownList({ + theme: theme, + source: tempsensorlist, + valueMember: 'uuid', + displayMember: 'name', + width: 240, + dropDownWidth: 480, + autoDropDownHeight: true + }); + $('#air_idx,#beer_idx,#chiller_idx,#heater_idx,#cooler_idx,#fan_idx,#light_idx,#door_idx,#psu_idx').jqxNumberInput(Spin0dec); + $('#heater_address,#cooler_address,#fan_address,#light_address').jqxDropDownList({ + theme: theme, + source: switcheslist, + valueMember: 'uuid', + displayMember: 'name', + width: 240, + dropDownWidth: 480, + autoDropDownHeight: true + }); + $('#heater_state,#cooler_state,#fan_state,#light_state').jqxNumberInput(Perc0); + $('#heater_delay,#cooler_delay,#fan_delay,#light_delay').jqxNumberInput(Spin0dec); + $('#pidh_p,#pidh_i,#pidh_d,#pidc_p,#pidc_i,#pidc_d').jqxNumberInput(Spin3dec); + $('#pidh_imax,#pidc_imax').jqxNumberInput(Perc1dec); + $('#pidh_idle,#pidc_idle').jqxNumberInput(Spin2dec); + $('#door_address,#psu_address').jqxDropDownList({ + theme: theme, + source: contactslist, + valueMember: 'uuid', + displayMember: 'name', + width: 240, + dropDownWidth: 480, + autoDropDownHeight: true + }); + $('#door_state,#psu_state').jqxNumberInput(Show0dec); + + // initialize jqxGrid + $('#jqxgrid').jqxGrid({ + width: 1280, + height: 630, + source: dataAdapter, + theme: theme, + showstatusbar: true, + renderstatusbar: function(statusbar) { + var rowCount = $("#jqxgrid").jqxGrid('getrows').length; + statusbar.append('
Total items: ' + rowCount + '
'); + var container, addButton, impButton; + container = $('
'); + addButton = $('
New
'); + container.append(addButton); + statusbar.append(container); + addButton.jqxButton({ theme: theme, width: 90, height: 17 }); + // add new row. + addButton.click(function(event) { + $('#addWindow').jqxWindow('open'); + $('#addOk').click(function() { + var data, + data = 'add=true&name=dummy' + console.log(data); + $.ajax({ + dataType: 'json', + url: url, + cache: false, + data: data, + type: 'POST', + success: function(data) { + if (data.error) { + console.log('add: ' + data.msg); + alert('Error: ' + data.msg); + } else { + console.log('add: success'); + } + }, + error: function(jqXHR, textStatus, errorThrown) {} + }); + $('#jqxgrid').jqxGrid('updatebounddata'); + }); + }); + }, + columns: [ + { text: 'Unit', datafield: 'alias', width: 200 }, + { text: 'Mode', datafield: 'mode', width: 120 }, + { text: 'Code', datafield: 'product_code', width: 150 }, + { text: 'Beer', datafield: 'product_name' }, + { text: '', datafield: 'Edit', width: 100, align: 'center', columntype: 'button', cellsrenderer: function() { + return 'Edit'; + }, buttonclick: function(row) { + // open the popup window when the user clicks a button. + editrow = row; + $('#popupWindow').jqxWindow({ position: { x: 40, y: 15 } }); + dataRecord = $('#jqxgrid').jqxGrid('getrowdata', editrow); + $('#uuid').val(dataRecord.uuid); + $('#alias').val(dataRecord.alias); + $('#product_code').val(dataRecord.product_code); + $('#product_name').val(dataRecord.product_name); + $('#air_address').val(dataRecord.air_address); + $('#air_idx').val(dataRecord.air_idx); + $('#beer_address').val(dataRecord.beer_address); + $('#beer_address2').val(dataRecord.beer_address2); + $('#beer_idx').val(dataRecord.beer_idx); + $('#chiller_address').val(dataRecord.chiller_address); + $('#chiller_idx').val(dataRecord.chiller_idx); + $('#heater_address').val(dataRecord.heater_address); + $('#heater_idx').val(dataRecord.heater_idx); + $('#heater_state').val(dataRecord.heater_state); + $('#heater_delay').val(dataRecord.heater_delay); + $('#cooler_address').val(dataRecord.cooler_address); + $('#cooler_idx').val(dataRecord.cooler_idx); + $('#cooler_state').val(dataRecord.cooler_state); + $('#cooler_delay').val(dataRecord.cooler_delay); + $('#fan_address').val(dataRecord.fan_address); + $('#fan_idx').val(dataRecord.fan_idx); + $('#fan_state').val(dataRecord.fan_state); + $('#fan_delay').val(dataRecord.fan_delay); + $('#light_address').val(dataRecord.light_address); + $('#light_idx').val(dataRecord.light_idx); + $('#light_state').val(dataRecord.light_state); + $('#light_delay').val(dataRecord.light_delay); + $('#door_address').val(dataRecord.door_address); + $('#door_idx').val(dataRecord.door_idx); + $('#door_state').val(dataRecord.door_state); + $('#psu_address').val(dataRecord.psu_address); + $('#psu_idx').val(dataRecord.psu_idx); + $('#psu_state').val(dataRecord.psu_state); + $('#mode').val(dataRecord.mode); + $('#stage').val(dataRecord.stage); + $('#pidc_p').val(dataRecord.pidc_p); + $('#pidc_i').val(dataRecord.pidc_i); + $('#pidc_d').val(dataRecord.pidc_d); + $('#pidc_imax').val(dataRecord.pidc_imax); + $('#pidc_idle').val(dataRecord.pidc_idle); + $('#pidh_p').val(dataRecord.pidh_p); + $('#pidh_i').val(dataRecord.pidh_i); + $('#pidh_d').val(dataRecord.pidh_d); + $('#pidh_imax').val(dataRecord.pidh_imax); + $('#pidh_idle').val(dataRecord.pidh_idle); + + // show the popup window. + $('#popupWindow').jqxWindow('open'); + } + } + ], + }); + + // initialize the popup window and buttons. + $('#popupWindow').jqxWindow({ + width: 1280, + height: 625, + resizable: false, + theme: theme, + isModal: true, + autoOpen: false, + cancelButton: $('#Cancel'), + modalOpacity: 0.40 + }); + $('#popupWindow').on('open', function() { +// $('#dev_description').jqxInput('selectAll'); + }); + $('#Delete').jqxButton({ template: 'danger', width: '90px', theme: theme }); + $('#Delete').click(function() { + // Open a popup to confirm this action. + $('#eventWindow').jqxWindow('open'); + $('#delOk').click(function() { + var data, + data = 'del=true&uuid=' + $('#uuid').val(); + $.ajax({ + dataType: 'json', + url: url, + cache: false, + data: data, + type: 'POST', + success: function(data) { + if (data.error) { + console.log('del: ' + data.msg); + alert('Error: ' + data.msg); + } else { + console.log('del: success'); + } + }, + error: function(jqXHR, textStatus, errorThrown) {} + }); + $('#jqxgrid').jqxGrid('updatebounddata'); + }); + $('#popupWindow').jqxWindow('hide'); + }); + $('#Cancel').jqxButton({ template: 'primary', width: '90px', theme: theme }); + $('#Save').jqxButton({ template: 'success', width: '90px', theme: theme }); + $('#Save').click(function() { + var data, + row = { + uuid: dataRecord.uuid, +// type: $('#dev_type').val(), +// direction: $('#dev_direction').val(), +// value: parseInt($('#dev_value').jqxNumberInput('decimal')), +// offset: parseInt($('#dev_offset').jqxNumberInput('decimal')), +// present: $('#dev_present').val(), +// address: $('#dev_address').val(), +// subdevice: parseInt($('#dev_subdevice').jqxNumberInput('decimal')), +// gpiopin: parseInt($('#dev_gpiopin').jqxNumberInput('val')), +// description: $('#dev_description').val(), +// comment: $('#dev_comment').val() + }; + data = 'update=true&' + $.param(row); + console.log(data); + $.ajax({ + dataType: 'json', + url: url, + cache: false, + data: data, + type: 'POST', + success: function(data) { + if (data.error) { + console.log('update: ' + data.msg); + alert('Error: ' + data.msg); + } else { + console.log('update: success'); + } + }, + error: function(jqXHR, textStatus, errorThrown) {} + }); + $('#popupWindow').jqxWindow('hide'); + }); + createDelElements(); + createAddElements(); + + websocket.onmessage = function(evt) { + var msg = evt.data; + var obj = JSON.parse(msg); + + if (obj.ping) { + websocket.send('{"pong":' + obj.ping + '}'); + } + + if (obj.type == 'device') { + // Use the message to trigger update. + $('#jqxgrid').jqxGrid('updatebounddata'); + } + } +}); diff -r d77891f8915d -r 344470c6bb1c www/set_devices.php --- a/www/set_devices.php Wed Apr 24 11:04:00 2024 +0200 +++ b/www/set_devices.php Wed Apr 24 16:46:45 2024 +0200 @@ -68,9 +68,6 @@ -
- -
diff -r d77891f8915d -r 344470c6bb1c www/set_fermenters.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/www/set_fermenters.php Wed Apr 24 16:46:45 2024 +0200 @@ -0,0 +1,173 @@ + + +
+
+
+
+
+ + + + +
+
+ Add new device +
+
+
+ Press "OK" to create a new fermenter unit record.
+ Press "Cancel" to close without adding a new unit. +
+
+
+ + +
+
+
+
+ +