mirror of https://github.com/sfeakes/AqualinkD.git
Version 2.3.0d
parent
26d2064055
commit
4b8e739788
|
@ -79,7 +79,7 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
|
|||
* Add set time to OneTouch protocol.
|
||||
* Add support for dimmers in All button, Aqualink Touch & OneTouch protocols.
|
||||
|
||||
# Update in Release 2.3.0c (pre release)
|
||||
# Update in Release 2.3.0d (pre release)
|
||||
* This is pre-release, please treat it as such.
|
||||
* Don't use this release on PDA panels unless you can debug/change code <b>I have not been able to test it fully.</b>
|
||||
* Changed a lot of logic around different protocols.
|
||||
|
@ -89,7 +89,7 @@ Designed to mimic AqualinkRS6 All Button keypad and (like the keypad) is used to
|
|||
* Added timers for devices (ie can turn on Pump for x minutes), Long press on device in WebUI.
|
||||
* Timers supported in MQTT/API.
|
||||
* Serial logging / error checking enhancements.
|
||||
* Added simulator back. (still a number of issues).
|
||||
* Added simulator back. (+ Improved UI).
|
||||
* Fix issue with incorrect device state after duplicate MQTT messages being sent in rapid succession ( < 0.5 second).
|
||||
* Found workaround for panel firmware bug in iAqualink Touch protocol where VSP updates sometimes got lost.
|
||||
* Fix bug in IntelliBrite color lights
|
||||
|
|
|
@ -119,6 +119,8 @@ bool passJson_scObj(char* line, int length, aqs_cron *values)
|
|||
readingvalue=false;
|
||||
}
|
||||
}
|
||||
|
||||
return (captured >= 7)?true:false;
|
||||
}
|
||||
|
||||
int save_schedules_js(char* inBuf, int inSize, char* outBuf, int outSize)
|
||||
|
|
|
@ -4,9 +4,15 @@
|
|||
PROCESSNAME=aqualinkd
|
||||
MYPID=`pidof $PROCESSNAME`
|
||||
|
||||
echo "=======";
|
||||
echo PID:$MYPID
|
||||
echo "--------"
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "This script must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "===================";
|
||||
echo "Process : $PROCESSNAME"
|
||||
echo "PID : $MYPID"
|
||||
echo "-------------------"
|
||||
Rss=`echo 0 $(cat /proc/$MYPID/smaps | grep Rss | awk '{print $2}' | sed 's#^#+#') | bc;`
|
||||
Shared=`echo 0 $(cat /proc/$MYPID/smaps | grep Shared | awk '{print $2}' | sed 's#^#+#') | bc;`
|
||||
Private=`echo 0 $(cat /proc/$MYPID/smaps | grep Private | awk '{print $2}' | sed 's#^#+#') | bc;`
|
||||
|
@ -20,6 +26,6 @@ echo "Shared " $Shared
|
|||
echo "Private " $Private
|
||||
echo "Swap " $Swap
|
||||
echo "Pss " $Pss
|
||||
echo "=================";
|
||||
echo "===================";
|
||||
echo "Mem " $Mem
|
||||
echo "=================";
|
||||
echo "===================";
|
||||
|
|
5156
mongoose.c
5156
mongoose.c
File diff suppressed because it is too large
Load Diff
775
mongoose.h
775
mongoose.h
File diff suppressed because it is too large
Load Diff
|
@ -569,15 +569,18 @@ void set_macro_status()
|
|||
// OneTouch Menu Line 5 = CLEAN MODE ON
|
||||
// OneTouch Menu Line 8 = ONETOUCH 3 OFF
|
||||
if (get_onetouch_menu_type() == OTM_ONETOUCH) {
|
||||
strncpy(_macros[0].name, _menu[2], 13);
|
||||
//strncpy(_macros[0].name, _menu[2], 13); // Compiler warning, use memcpy
|
||||
memcpy(_macros[0].name, _menu[2], 13);
|
||||
chopwhitespace(_macros[0].name);
|
||||
_macros[0].ison = (_menu[2][15] == 'N'?true:false);
|
||||
|
||||
strncpy(_macros[1].name, _menu[5], 13);
|
||||
//strncpy(_macros[1].name, _menu[5], 13);// Compiler warning, use memcpy
|
||||
memcpy(_macros[1].name, _menu[5], 13);
|
||||
chopwhitespace(_macros[1].name);
|
||||
_macros[1].ison = (_menu[5][15] == 'N'?true:false);
|
||||
|
||||
strncpy(_macros[2].name, _menu[8], 13);
|
||||
//strncpy(_macros[2].name, _menu[8], 13);// Compiler warning, use memcpy
|
||||
memcpy(_macros[2].name, _menu[8], 13);
|
||||
chopwhitespace(_macros[2].name);
|
||||
_macros[2].ison = (_menu[8][15] == 'N'?true:false);
|
||||
|
||||
|
|
Binary file not shown.
|
@ -234,7 +234,8 @@ use_panel_aux_labels=no
|
|||
# button_01_pumpIndex=1
|
||||
# If you have assigned this pump an index number in your Aqualink control panel, (Between 1 & 4), put it here for VSP, RPM, Primp information to be captured.
|
||||
#
|
||||
|
||||
# button_xx_lightMode = (0=Aqualink program, 1=Jandy, 2=Jandy LED, 3=SAm/SAL, 4=Color Logic, 5=Intellibrite, 6=Dimmer)
|
||||
#
|
||||
# Below are settings for standard buttons on RS-8 Combo panel used as example.
|
||||
button_01_label=Filter Pump
|
||||
|
||||
|
|
Binary file not shown.
|
@ -56,6 +56,7 @@ char *rsm_strstr(const char *haystack, const char *needle)
|
|||
if (strlen(sp1) == 0 || strlen(sp2) == 0)
|
||||
return NULL;
|
||||
// Need to write this myself for speed
|
||||
// Maybe use stristr from utils.c in the future. Needs a lot of testing.
|
||||
//LOG(AQUA_LOG,LOG_DEBUG, "Compare (reset)%d chars of '%s' to '%s'\n",strlen(sp2),sp1,sp2);
|
||||
return strcasestr(sp1, sp2);
|
||||
}
|
||||
|
@ -149,6 +150,7 @@ int rsm_atoi(const char* str)
|
|||
return base * sign;
|
||||
}
|
||||
|
||||
// atof that can have blank start
|
||||
float rsm_atof(const char* str)
|
||||
{
|
||||
int i=0;
|
||||
|
|
23
utils.c
23
utils.c
|
@ -468,6 +468,8 @@ void _LOG(int16_t from, int msg_level, char *message)
|
|||
message[i] = ' ';
|
||||
}
|
||||
}
|
||||
// Add return to end of string if not already their.
|
||||
// NSF need to come back to this, doesn;t always work
|
||||
if (message[i] != '\n') {
|
||||
message[i] = '\n';
|
||||
message[i+1] = '\0';
|
||||
|
@ -496,7 +498,8 @@ void _LOG(int16_t from, int msg_level, char *message)
|
|||
//int len;
|
||||
message[8] = ' ';
|
||||
char *strLevel = elevel2text(msg_level);
|
||||
strncpy(message, strLevel, strlen(strLevel));
|
||||
//strncpy(message, strLevel, strlen(strLevel)); // Will give compiler warning, so use memcpy instead
|
||||
memcpy(message, strLevel, strlen(strLevel));
|
||||
//len = strlen(message);
|
||||
/*
|
||||
if ( message[len-1] != '\n') {
|
||||
|
@ -514,14 +517,20 @@ void _LOG(int16_t from, int msg_level, char *message)
|
|||
int fp = open(_log_filename, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
if (fp != -1) {
|
||||
timestamp(time);
|
||||
write(fp, time, strlen(time) );
|
||||
write(fp, message, strlen(message) );
|
||||
if ( write(fp, time, strlen(time) ) == -1 ||
|
||||
write(fp, time, strlen(time) ) == -1 )
|
||||
{
|
||||
syslog(LOG_ERR, "Can't write to log file %s\n %s", _log_filename, message);
|
||||
fprintf (stderr, "Can't write to log file %s\n %s", _log_filename, message);
|
||||
}
|
||||
//write(fp, time, strlen(time) );
|
||||
//write(fp, message, strlen(message) );
|
||||
close(fp);
|
||||
} else {
|
||||
if (_daemonise == TRUE)
|
||||
syslog(LOG_ERR, "Can't open log file\n %s", message);
|
||||
syslog(LOG_ERR, "Can't open log file %s\n %s", _log_filename, message);
|
||||
else
|
||||
fprintf (stderr, "Can't open debug log\n %s", message);
|
||||
fprintf (stderr, "Can't open debug log %s\n %s", _log_filename, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -603,7 +612,9 @@ void daemonise (char *pidFile, void (*main_function) (void))
|
|||
exit (EXIT_FAILURE);
|
||||
}
|
||||
// Change the current working directory to root.
|
||||
chdir ("/");
|
||||
if ( chdir ("/") == -1) {
|
||||
LOG(AQUA_LOG, LOG_ERR,"Can't set working dir to /");
|
||||
}
|
||||
// Close stdin. stdout and stderr
|
||||
close (STDIN_FILENO);
|
||||
close (STDOUT_FILENO);
|
||||
|
|
4
utils.h
4
utils.h
|
@ -41,8 +41,8 @@
|
|||
#define DBGT_LOG (1 << 11) // Debug Timer
|
||||
#define TIMR_LOG (1 << 12) // Timers
|
||||
|
||||
// Set scheduler log to aqualink general
|
||||
#define SCHD_LOG AQUA_LOG
|
||||
// Set scheduler log to timer log
|
||||
#define SCHD_LOG TIMR_LOG
|
||||
|
||||
/*
|
||||
typedef enum
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
|
||||
#define AQUALINKD_NAME "Aqualink Daemon"
|
||||
#define AQUALINKD_VERSION "2.3.0c"
|
||||
#define AQUALINKD_VERSION "2.3.0d"
|
||||
|
|
|
@ -22,15 +22,30 @@
|
|||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
/*position: absolute;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;*/
|
||||
}
|
||||
|
||||
table {
|
||||
background-color: rgb(221, 221, 221);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
th {
|
||||
th {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#title {
|
||||
background-color: rgb(200, 200, 200);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
input[type=button],
|
||||
input[type=submit],
|
||||
input[type=reset] {
|
||||
|
@ -62,9 +77,17 @@
|
|||
.off {
|
||||
background-color: rgb(116, 116, 116);
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type='text/javascript'>
|
||||
|
||||
var _panel_size = 6;
|
||||
var _panel_set = 0;
|
||||
|
||||
function send(source) {
|
||||
console.log("from" + source.id);
|
||||
|
||||
|
@ -72,62 +95,97 @@
|
|||
cmd.uri = "rawcommand"
|
||||
switch (source.id) {
|
||||
case "Filter_Pump_button":
|
||||
cmd.value = "2"; //"0x02";
|
||||
cmd.value = "0x02";
|
||||
break;
|
||||
case "Spa_Mode_button":
|
||||
cmd.value = "1"; // "0x01";
|
||||
cmd.value = "0x01";
|
||||
break;
|
||||
case "Aux_1_button":
|
||||
cmd.value = "5"; //"0x05";
|
||||
cmd.value = "0x05";
|
||||
break;
|
||||
case "Aux_2_button":
|
||||
cmd.value = "10"; //"0x0a";
|
||||
cmd.value = "0x0a";
|
||||
break;
|
||||
case "Aux_3_button":
|
||||
cmd.value = "15"; //"0x0f";
|
||||
cmd.value = "0x0f";
|
||||
break;
|
||||
case "Aux_4_button":
|
||||
cmd.value = "6"; //"0x06";
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x06";
|
||||
else
|
||||
cmd.value = "0x14"; //Different on RS12+ (0x14)
|
||||
break;
|
||||
case "Aux_5_button":
|
||||
cmd.value = "11"; //"0x0b";
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x0b";
|
||||
else
|
||||
cmd.value = "0x03"; //Different on RS12+ (0x03)
|
||||
break;
|
||||
case "Aux_6_button":
|
||||
cmd.value = "16"; //"0x10";
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x10";
|
||||
else
|
||||
cmd.value = "0x07"; //Different on RS12+ (0x07)
|
||||
break;
|
||||
case "Aux_7_button":
|
||||
cmd.value = "21"; //"0x15";
|
||||
if (_panel_size < 12)
|
||||
cmd.value = "0x15";
|
||||
else
|
||||
cmd.value = "0x06"; //Different on RS12+ (0x06)
|
||||
break;
|
||||
case "Aux_B1_button":
|
||||
cmd.value = "0x0b";
|
||||
break;
|
||||
case "Aux_B2_button":
|
||||
cmd.value = "0x10";
|
||||
break;
|
||||
case "Aux_B3_button":
|
||||
cmd.value = "0x15";
|
||||
break;
|
||||
case "Aux_B4_button":
|
||||
cmd.value = "0x1a";
|
||||
break;
|
||||
case "Aux_B5_button":
|
||||
cmd.value = "0x04";
|
||||
break;
|
||||
case "Aux_B6_button":
|
||||
cmd.value = "0x08";
|
||||
break;
|
||||
case "Aux_B7_button":
|
||||
cmd.value = "0x0d";
|
||||
break;
|
||||
case "Aux_B8_button":
|
||||
cmd.value = "0x0c";
|
||||
break;
|
||||
case "Pool_Heater_button":
|
||||
cmd.value = "18"; //"0x12";
|
||||
cmd.value = "0x12";
|
||||
break;
|
||||
case "Spa_Heater_button":
|
||||
cmd.value = "23"; //"0x17";
|
||||
cmd.value = "0x17";
|
||||
break;
|
||||
case "Solar_Heater_button":
|
||||
cmd.value = "28"; //"0x1c";
|
||||
cmd.value = "0x1c";
|
||||
break;
|
||||
case "B_menu":
|
||||
//cmd.value = "0x09";
|
||||
cmd.value = "9";
|
||||
cmd.value = "0x09";
|
||||
break;
|
||||
case "B_cancel":
|
||||
cmd.value = "14"; //"0x0e";
|
||||
cmd.value = "0x0e";
|
||||
break;
|
||||
case "B_back":
|
||||
cmd.value = "19"; //"0x13";
|
||||
cmd.value = "0x13";
|
||||
break;
|
||||
case "B_forward":
|
||||
cmd.value = "24"; //"0x18";
|
||||
cmd.value = "0x18";
|
||||
break;
|
||||
case "B_enter":
|
||||
cmd.value = "29"; //"0x1d";
|
||||
cmd.value = "0x1d";
|
||||
break;
|
||||
case "B_hold":
|
||||
cmd.value = "25"; //"0x19";
|
||||
cmd.value = "0x19";
|
||||
break;
|
||||
case "B_overide":
|
||||
cmd.value = "28"; //"0x1c";
|
||||
cmd.value = "0x1c";
|
||||
break;
|
||||
default:
|
||||
alert("Unknown button");
|
||||
|
@ -135,7 +193,55 @@
|
|||
break;
|
||||
}
|
||||
|
||||
cmd.value = todec(cmd.value);
|
||||
send_command(cmd);
|
||||
|
||||
// I know we are converting hex to dec and back to hex, but here for checking.
|
||||
document.getElementById("messages").innerHTML = "Sent "+tohex(cmd.value)+" please wait for response!";
|
||||
}
|
||||
|
||||
function tohex(value) {
|
||||
var rtn = parseInt(value).toString(16);
|
||||
if (rtn.length <= 1)
|
||||
return "0x0"+rtn;
|
||||
else
|
||||
return "0x"+rtn;
|
||||
}
|
||||
function todec(value) {
|
||||
let number = parseInt(value, 16);
|
||||
return number;
|
||||
}
|
||||
|
||||
function set_panel_size(size)
|
||||
{
|
||||
if (_panel_set == size){
|
||||
return;
|
||||
}
|
||||
|
||||
_panel_set = size;
|
||||
|
||||
switch(size){
|
||||
case 6:
|
||||
document.getElementById("Aux_6_led").classList.add("hidden");
|
||||
document.getElementById("Aux_6_button").classList.add("hidden");
|
||||
document.getElementById("Aux_7_led").classList.add("hidden");
|
||||
document.getElementById("Aux_7_button").classList.add("hidden");
|
||||
case 8:
|
||||
document.getElementById("Aux_B1_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B1_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B2_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B2_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B3_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B3_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B4_led").classList.add("hidden");
|
||||
document.getElementById("Aux_B4_button").classList.add("hidden");
|
||||
case 12:
|
||||
document.getElementById("Aux_B5_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B6_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B7_button").classList.add("hidden");
|
||||
document.getElementById("Aux_B8_button").classList.add("hidden");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -144,22 +250,45 @@
|
|||
if (document.getElementById("status").getAttribute("raw") != data.panel_message) {
|
||||
document.getElementById("status_three").innerHTML = document.getElementById("status_two").innerHTML;
|
||||
document.getElementById("status_two").innerHTML = document.getElementById("status").innerHTML;
|
||||
document.getElementById("status").innerHTML = data.panel_message;
|
||||
if (data.panel_message == "") {
|
||||
document.getElementById("status").innerHTML = " ";
|
||||
} else {
|
||||
document.getElementById("status").innerHTML = data.panel_message;
|
||||
}
|
||||
document.getElementById("status").setAttribute("raw", data.panel_message);
|
||||
document.getElementById("messages").innerHTML = " ";
|
||||
}
|
||||
|
||||
for (var obj in data.leds) {
|
||||
if ((led = document.getElementById(obj.toString() + "_led")) == null) {
|
||||
if ((led = document.getElementById(obj.toString() + "_led")) == null) {
|
||||
//console.log("Error " + obj.toString() + " LED not found");
|
||||
return;
|
||||
}
|
||||
if (data.leds[obj] == "on") {
|
||||
//return;
|
||||
} else {
|
||||
if (data.leds[obj] == "on" || data.leds[obj] == "enabled" || data.leds[obj] == "flash") {
|
||||
//console.log("Set " + obj.toString() + " LED on");
|
||||
led.classList.add("on");
|
||||
led.classList.remove("off");
|
||||
} else {
|
||||
//console.log("Set " + obj.toString() + " LED off");
|
||||
led.classList.add("off");
|
||||
led.classList.remove("on");
|
||||
}
|
||||
}
|
||||
if (obj.toString() == "Aux_4" && _panel_size < 6)
|
||||
_panel_size=6;
|
||||
if (obj.toString() == "Aux_6" && _panel_size < 8)
|
||||
_panel_size=8;
|
||||
if (obj.toString() == "Aux_B1" && _panel_size < 12)
|
||||
_panel_size=12;
|
||||
if (obj.toString() == "Aux_B4")
|
||||
_panel_size=16;
|
||||
}
|
||||
|
||||
set_panel_size(_panel_size);
|
||||
}
|
||||
|
||||
function update_device(data) {
|
||||
for (var obj in data['devices']) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,6 +329,7 @@
|
|||
socket_di.onopen = function () {
|
||||
// success!
|
||||
start_simulator();
|
||||
get_devices();
|
||||
}
|
||||
socket_di.onmessage = function got_packet(msg) {
|
||||
document.getElementById("status").classList.remove("error");
|
||||
|
@ -208,6 +338,7 @@
|
|||
update_status(data);
|
||||
} else if (data.type == 'devices') {
|
||||
//update_status(data);
|
||||
update_device(data);
|
||||
} else if (data.type == 'aux_labels') {
|
||||
set_labels(data);
|
||||
}
|
||||
|
@ -232,12 +363,13 @@
|
|||
uri: "simulator"
|
||||
};
|
||||
socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
/*
|
||||
var msg = {
|
||||
command: "simulator"
|
||||
};
|
||||
socket_di.send(JSON.stringify(msg));*/
|
||||
function get_devices() {
|
||||
var msg = {
|
||||
uri: "devices"
|
||||
};
|
||||
socket_di.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function send_command(cmd) {
|
||||
|
@ -251,6 +383,7 @@
|
|||
function init() {
|
||||
startWebsockets();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
@ -259,7 +392,9 @@
|
|||
<div class="wrapper">
|
||||
|
||||
<table border='0' id="deviceList">
|
||||
|
||||
<tr style="title">
|
||||
<td style="title" colspan="12" align="center"><label id="title"> AqualinkD All Button Simulator </label></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="12" align="center"><label id="status_three"> </label></td>
|
||||
</tr>
|
||||
|
@ -327,6 +462,82 @@
|
|||
<td align="left">
|
||||
<input id="Aux_7_button" type="button" onclick="send(this);" value="AUX7">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_B1_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B1_button" type="button" onclick="send(this);" value="AUXB1">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_B2_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B2_button" type="button" onclick="send(this);" value="AUXB2">
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Aux_B3_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B3_button" type="button" onclick="send(this);" value="AUXB3">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<div id="Aux_B4_led" class="led off"></div>
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B4_button" type="button" onclick="send(this);" value="AUXB4">
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B5_button" type="button" onclick="send(this);" value="AUXB5">
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B6_button" type="button" onclick="send(this);" value="AUXB6">
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B7_button" type="button" onclick="send(this);" value="AUXB7">
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
<input id="Aux_B8_button" type="button" onclick="send(this);" value="AUXB8">
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
</td>
|
||||
<td align="left">
|
||||
|
||||
</td>
|
||||
<td align="right">
|
||||
<div id="Pool_Heater_led" class="led off"></div>
|
||||
</td>
|
||||
|
@ -366,6 +577,9 @@
|
|||
<input type="button" onclick="send(this);" id="B_enter" value="Enter *">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="12" align="center"><label id="messages"> </label></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
|
|
Loading…
Reference in New Issue