AqualinkD/web/aquapda_sim.html

686 lines
24 KiB
HTML

<!DOCTYPE html>
<html lang='en'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=windows-1252'>
<title>AqualinkD Simulator</title>
<meta name='viewport' content='width=device-width'>
<meta name='apple-mobile-web-app-capable' content='yes'>
<meta name='apple-mobile-web-app-status-bar-style' content='black'>
<meta name='apple-mobile-web-app-status-bar-style' content='black'>
<link href="aqualinkd.png" rel="apple-touch-icon">
<link href="aqualinkd.png" rel="icon">
<style>
html {}
body {
font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
font-weight: 300;
background-color: white;
color: #000000;
margin: 0 !important;
padding: 0 !important;
display: flex;
flex-direction: column;
}
.inner {
display: inline;
}
.wrapper {
display: flex;
justify-content: center;
width: 100%;
align-items: center;
/*position: absolute;
justify-content: center;
width: 100%;
height: 100%;*/
}
table {
background-color: rgb(221, 221, 221);
border-collapse: collapse;
}
th {
/*
background-color: white;
border-spacing: 10px;*/
padding-top: 0px;
padding-bottom: 0px;
padding-left: 0px;
padding-right: 0px;
}
td {
/*
text-align: center;
vertical-align: middle;
*/
/*padding: 10px;*/
padding-top: 3px;
padding-bottom: 3px;
padding-left: 0px;
padding-right: 0px;
}
#title {
background-color: rgb(200, 200, 200);
font-weight: 600;
}
input[type=button],
input[type=submit],
input[type=reset] {
background-color: rgb(165, 165, 165);
border: none;
color: rgb(0, 0, 0);
padding: 2px 2px;
text-decoration: none;
margin: 0px 0px;
min-width: 70px;
border-radius: 70px;
}
.button_s {
min-width: 40px !important;
border-radius: 40px !important;
}
.led {
border-radius: calc(var(--tile_icon-height) / 2);
border-radius: 20px;
height: 20px;
width: 20px;
text-align: center;
vertical-align: middle;
filter: alpha(opacity=100);
opacity: 1.0;
}
.on {
background-color: rgb(255, 0, 0);
}
.off {
background-color: rgb(116, 116, 116);
}
.error {
background-color: rgb(255, 0, 0) !important;
font-weight: 600;
}
.hidden {
display: none;
}
.lcd_display {
font-family: monospace;
background-color: #2b2b2b;
color: white;
white-space: pre;
}
.lcd_highlight {
font-family: monospace;
background-color: #8e1e1e !important;
color: white !important;
white-space: pre;
}
.version {
/*font-family: monospace;*/
font-size: x-small;
}
.hide {
display: none;
/*
filter: alpha(opacity=0);
opacity: 0.0;
*/
}
</style>
<script type='text/javascript'>
var _socket_di;
var _keep_socket_alive=true;
const PKT_CMD = 3;
const PKT_DATA1 = 4;
const PKT_DATA2 = 5;
const PKT_DATA3 = 6;
const CMD_PROBE = 0;
const CMD_MSG_LONG = 4;
const CMD_PDA_CLEAR = 9;
const CMD_PDA_HIGHLIGHT = 8;
const CMD_PDA_HIGHLIGHTCHARS = 16;
const CMD_PDA_SHIFTLINES = 15;
const PDA_LINES = 9; // 0 to 9
var _hlightcharlineno = -1;
var _hlightcharline = "";
var _hlightcharstart = -1;
var _hlightcharend = -1;
var _initial_click=false;
// See if we are in an iframe and capture focus
function capture_iframe_focus() {
var targetNode = parent.document.getElementById('aquapda_iframe');
if (targetNode != null) {
var observer = new MutationObserver(function(){
if(targetNode.style.display != 'none'){
console.log("AquaPDA sim Displaying");
startWebsockets();
} else {
console.log("AquaPDA sim Hiding");
stopWebsockets();
}
});
observer.observe(targetNode, { attributes: true, childList: true });
return true;
}
return false;
}
function send(source) {
console.log("from" + source.id);
var cmd = {};
cmd.uri = "simcmd"
switch (source.id) {
case "Up":
cmd.value = "0x06";
break;
case "Down":
cmd.value = "0x05";
break;
case "Select":
cmd.value = "0x04";
break;
case "Page_up":
cmd.value = "0x03";
break;
case "Back":
cmd.value = "0x02";
break;
case "Page_down":
cmd.value = "0x01";
break;
default:
alert("Unknown button");
return;
break;
}
cmd.value = todec(cmd.value);
send_command(cmd);
}
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 lcd_clear() {
//var container = document.getElementById("lcd_display");
for (i = 0; i <= PDA_LINES; i++) {
//container.lastElementChild.remove();
//child = container.children[i];
//console.log("Line "+i+" replacing "+child.innerHTML)
//child.innerHTML = "&nbsp;";
var line = document.getElementById("lcd-l" + i);
//console.log("Line "+i+" replacing "+line.innerHTML)
line.innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
line.classList.remove("lcd_highlight");
line.classList.add("lcd_display");
}
lcd_clear_highlight_chrs(false);
}
function lcd_display(lineno, message) {
// We get lines 0,2,3,4,5,6.... no line 1. (so using 0 as 1)
if (lineno == 0) { lineno = 1; }
// Line 64 is time,
if (lineno == 64) { lineno = 0; }
// line 130 is pool air temp
if (lineno == 130) { lineno = 2; }
var line = document.getElementById("lcd-l" + lineno);
//console.log("Line "+lineno+" replacing '"+line.innerHTML+"' with '"+message+"'");
line.innerHTML = message;
// See if we need to re-highlight any chrs
check_rehighlight_chrs(lineno);
}
function lcd_display_shiftlines(first, last, direction) {
if (direction == 255) {
for (i = first; i <= last; i++) {
var line1 = document.getElementById("lcd-l" + i);
var line2 = document.getElementById("lcd-l" + (i + 1));
line1.innerHTML = line2.innerHTML;
}
} else if (direction == 1) {
for (i = last; i >= first; i--) {
var line1 = document.getElementById("lcd-l" + i);
var line2 = document.getElementById("lcd-l" + (i - 1) );
line1.innerHTML = line2.innerHTML;
}
}
}
function lcd_display_highlight(lineno) {
// We get lines 0,2,3,4,5,6.... no line 1. (so using 0 as 1)
if (lineno == 0) { lineno = 1; }
for (i = 0; i <= PDA_LINES; i++) {
var line = document.getElementById("lcd-l" + i);
if (i != lineno) {
line.classList.remove("lcd_highlight");
line.classList.add("lcd_display");
//console.log("remove highlight to line #"+i+" "+line.innerHTML)
} else {
line.classList.add("lcd_highlight");
line.classList.remove("lcd_display");
//console.log("add highlight to line #"+i+" "+line.innerHTML)
}
}
//line.classList.add("lcd_highlight");
//line.classList.remove("lcd_display");
}
function check_rehighlight_chrs(lineno) {
if (_hlightcharlineno == lineno && _hlightcharstart >= 0 && _hlightcharend > 0) {
// We would have received a new line text, so don't preserve old text
lcd_display_highlight_chrs(_hlightcharlineno, _hlightcharstart, _hlightcharend, false);
}
}
function lcd_clear_highlight_chrs(preserve = true) {
// if preserve, then we put back the old text.
if (preserve && _hlightcharlineno >= 0 && _hlightcharline != "") {
var line = document.getElementById("lcd-l" + _hlightcharlineno);
line.innerHTML = _hlightcharline;
}
_hlightcharlineno = -1;
_hlightcharline = "";
_hlightcharstart = -1;
_hlightcharend = -1;
}
function lcd_display_highlight_chrs(lineno, start, end, preserve = true) {
lcd_clear_highlight_chrs(preserve);
var line = document.getElementById("lcd-l" + lineno);
text = line.innerHTML;
var newtxt = text.slice(0, end + 1) + "</span>" + text.slice(end + 1);
var newtxt = newtxt.slice(0, start) + "<span class=\"lcd_highlight\">" + newtxt.slice(start);
line.innerHTML = newtxt;
_hlightcharlineno = lineno;
_hlightcharline = text;
_hlightcharstart = start;
_hlightcharend = end;
console.log("Line '" + text + "' now '" + newtxt + "'");
}
function packet_to_ascii(packet) {
var msg = "";
for (i = 5; i <= 20; i++) {
if (packet[i] >= 31 && packet[i] <= 127) {
msg = msg + String.fromCharCode(packet[i]);
} else if (packet[i] == 223) {
msg = msg + "&deg";
} else if (packet[i] == 0) {
break; // End on a nul
} else {
console.log("Bad char in string '" + msg + "' next (" + packet[i] + ")");
}
}
return msg;
}
function process_packet(data) {
if (data.simtype != "aquapda") {
update_status_message("Another simulator running", true);
return;
}
switch (data.dec[PKT_CMD]) {
case CMD_PROBE:
// We are about to start
break;
case CMD_PDA_CLEAR: // Clear
//console.log("Received Clear");
lcd_clear();
_shift_lines = false;
break;
case CMD_MSG_LONG: // Message
//console.log("Received Line " + data.dec[PKT_DATA1] + " = " + packet_to_ascii(data.dec));
lcd_display(data.dec[PKT_DATA1], packet_to_ascii(data.dec));
break;
case CMD_PDA_HIGHLIGHT:
//console.log("Received Highlight " + data.dec[PKT_DATA1]);
// We sometimes get 255 for line number, need to find out why
lcd_display_highlight(data.dec[PKT_DATA1]);
break;
case CMD_PDA_HIGHLIGHTCHARS:
//console.log("Received Highlight chars, Line=" + data.dec[PKT_DATA1] + ", Start=" + data.dec[PKT_DATA2] + ", Stop=" + data.dec[PKT_DATA3]);
lcd_display_highlight_chrs(data.dec[PKT_DATA1], data.dec[PKT_DATA2], data.dec[PKT_DATA3]);
break;
case CMD_PDA_SHIFTLINES:
//console.log("Received shift lines, Start=" + data.dec[PKT_DATA1] + ", End=" + data.dec[PKT_DATA2] + ", Direction=" + data.dec[PKT_DATA3]);
lcd_display_shiftlines(data.dec[PKT_DATA1], data.dec[PKT_DATA2], data.dec[PKT_DATA3]);
break;
default:
// 2 is READY for commands
console.log("Received unknown command " + data.dec[PKT_CMD] + " " + tohex(data.dec[PKT_CMD]));
break;
}
}
function update_status_message(message = null, error = false) {
const status = document.getElementById("status");
if (message != null) {
status.innerHTML = message;
} else {
status.innerHTML = "AqualinkD PDA Simulator";
}
if (error) {
status.classList.add("error");
} else {
status.classList.remove("error");
}
}
function update_status(data) {
// Some form of error if PDA only panel.
if (data.panel_type.startsWith("PDA")) {
// If we are a PDA only panel, we are already connected, send the back command to get some PDA clar
// message to reset the screen.
if (_initial_click == false) {
document.getElementById("pdaWarning").style.display = 'block';
document.getElementById("Back").click();
_initial_click = true;
}
}
const versionlabel = document.getElementById("version");
if (versionlabel.innerHTML = "&nbsp;") {
versionlabel.innerHTML = "AqualinkD " + data.aqualinkd_version + "<br>" + data.panel_type + " " + data.version;
}
}
function get_appropriate_ws_url() {
var pcol;
var u = document.URL;
/*
* We open the websocket encrypted if this page came on an
* https:// url itself, otherwise unencrypted
*/
if (u.substring(0, 5) == "https") {
pcol = "wss://";
u = u.substr(8);
} else {
pcol = "ws://";
if (u.substring(0, 4) == "http")
u = u.substr(7);
}
u = u.split('/');
//alert (pcol + u[0] + ":6500");
return pcol + u[0];
}
/* dumb increment protocol */
function startWebsockets() {
_socket_di = new WebSocket(get_appropriate_ws_url());
_keep_socket_alive = true;
try {
_socket_di.onopen = function () {
// success!
start_simulator();
//get_devices();
}
_socket_di.onmessage = function got_packet(msg) {
update_status_message();
var data = JSON.parse(msg.data);
if (data.type == 'simpacket') {
process_packet(data);
} else if (data.type == 'status') {
update_status(data);
}
}
_socket_di.onclose = function () {
// something went wrong
//document.getElementById("status").innerHTML = ' !!! Connection error !!! '
//document.getElementById("status").classList.add("error");
update_status_message("!!! Connection error !!!", true);
// Try to reconnect every 5 seconds.
setTimeout(function () {
if (_keep_socket_alive == true) {
startWebsockets();
}
}, 5000);
}
} catch (exception) {
alert('<p>Error' + exception);
}
}
function stopWebsockets() {
if (_socket_di) {
_socket_di.close();
}
_keep_socket_alive = false;
}
function start_simulator() {
var msg = {
//command: "simulator"
uri: "simulator/aquapda"
};
lcd_clear();
document.getElementById("lcd-l2").innerHTML = " Connecting ";
document.getElementById("lcd-l3").innerHTML = " Please wait! ";
_socket_di.send(JSON.stringify(msg));
}
function get_devices() {
var msg = {
uri: "devices"
};
_socket_di.send(JSON.stringify(msg));
}
function send_command(cmd) {
_socket_di.send(JSON.stringify(cmd));
}
/*
function reset() {
_socket_di.send("reset\n");
}
*/
function init() {
if ( capture_iframe_focus() ) {
// In iframe wait for focus event to start
} else {
update_status_message();
startWebsockets();
}
}
</script>
<body onload="init();">
<div class="wrapper">
<div class="inner">
<div>
<table border='0' id="deviceList">
<tr>
<th id="status" align="center" colspan="5">&nbsp;</th>
</tr>
<tr>
<td></td>
<td colspan="3" align="center">
<table border='0'>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l0">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l1">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l2"></td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l3">&nbsp;</td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l4">&nbsp;</td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l5">&nbsp;</td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l6">&nbsp;</td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l7">&nbsp;</td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l8">&nbsp;</td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l9">&nbsp;</td>
<td></td>
</tr>
<!--
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l10">&nbsp;</td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l11">&nbsp;</td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3" class="lcd_display" id="lcd-l12">&nbsp;</td>
<td></td>
</tr>
-->
</table>
</td>
<td></td>
</tr>
<tr>
<td></td>
<td align="center"><input class="button_s" id="Back" type="button" onclick="send(this);"value="&#8617;"></td>
<td align="center"><input class="button_s" id="Up" type="button" onclick="send(this);"value="&uarr;"></td>
<!--<td align="center"><input class="button_s" id="Power" type="button" onclick="send(this);"value="&#8635;"></td>-->
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td align="center" colspan="3"><input id="Select" type="button" onclick="send(this);"
value="Select"></td>
<td></td>
</tr>
<tr>
<td></td>
<td align="center"><input class="button_s" id="Page_up" type="button" onclick="send(this);" value="1"></td>
<td align="center"><input class="button_s" id="Down" type="button" onclick="send(this);"value="&darr;"></td>
<td align="center"><input class="button_s" id="Page_down" type="button" onclick="send(this);" value="2">
</td>
<td></td>
</tr>
<tr>
<td colspan="5" id="version" class="version">&nbsp;</td>
</tr>
</table>
</div>
<!--<div class="inner">END</div>-->
<div id="pdaWarning" class='hide'>
Warning<br>AqualinkD will not respond to commands while this window is open,<br>Please close when finished.
</div>
</div>
</div>
</body>
</html>