mirror of https://github.com/sfeakes/AqualinkD.git
2811 lines
104 KiB
HTML
2811 lines
104 KiB
HTML
<!DOCTYPE html>
|
|
<html lang='en'>
|
|
|
|
<head>
|
|
<meta http-equiv='Content-Type' content='text/html; charset=windows-1252'>
|
|
<title>AqualinkD</title>
|
|
<meta name='viewport' content='width=device-width'>
|
|
<meta name='mobile-web-app-capable' content='yes'>
|
|
<meta name='apple-mobile-web-app-capable' content='yes'>
|
|
<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'>
|
|
<script src='config.js'></script>
|
|
<!--<script src='?command=dynamic_config'></script>-->
|
|
<script src='/api/dynamicconfig'></script>
|
|
<style>
|
|
:root {
|
|
--fonts: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
|
|
--tile-width: 100px;
|
|
--tile_icon-height: 35px;
|
|
--tile_name-height: 32px;
|
|
--tile_name-charlimit: 12;
|
|
--tile_name-height1line: 17px;
|
|
--tile_status-height: 15px;
|
|
--tile_grid-gap: 10px;
|
|
--tile_name-lineheight: 1.2;
|
|
/*
|
|
// Large display will use the below values, just here for testing.
|
|
--tile-width: 125px;
|
|
--tile_icon-height: 45px;
|
|
--tile_name-height: 42px;
|
|
--tile_status-height: 15px;
|
|
--tile_grid-gap: 20px;
|
|
--tile_name-lineheight: 1.4;
|
|
*/
|
|
/* These get overiden from config.js, don't edit */
|
|
--body_background: rgb(235, 235, 235);
|
|
--body_text: black;
|
|
--options_pane_background: rgb(245, 245, 245);
|
|
--options_pane_bordercolor: rgb(124, 124, 124);
|
|
--options_slider_ball: 30;
|
|
--options_slider_highlight: #2196F3;
|
|
--options_slider_lowlight: #d3d3d3;
|
|
--options_slider_height: 20px;
|
|
--head_background: rgb(43, 106, 143);
|
|
--head_text: #fff;
|
|
--error_background: rgb(143, 43, 43);
|
|
--tile_background: rgb(220, 220, 220);
|
|
--tile_text: rgb(110, 110, 110);
|
|
--tile_on_background: #fff;
|
|
--tile_on_text: #000;
|
|
--tile_status_text: rgb(87, 87, 87);
|
|
|
|
--options_radio_ball: 20px;
|
|
--options_radio_highlight: #2196F3;
|
|
--options_radio_lowlight: #d3d3d3;
|
|
|
|
--cronhelp_background: rgb(193, 193, 193);
|
|
--csinputcell_background: rgb(255, 255, 255);
|
|
}
|
|
|
|
div {
|
|
-webkit-touch-callout: none;
|
|
-webkit-user-select: none;
|
|
-khtml-user-select: none;
|
|
-moz-user-select: none;
|
|
-ms-user-select: none;
|
|
user-select: none;
|
|
}
|
|
|
|
div::-moz-selection {
|
|
background: transparent;
|
|
}
|
|
|
|
div::selection {
|
|
background: transparent;
|
|
}
|
|
|
|
html {}
|
|
|
|
body {
|
|
background-color: var(--body_background);
|
|
font-family: var(--fonts);
|
|
font-weight: 600;
|
|
font-size: 14px;
|
|
color: var(--body_text);
|
|
/*margin: 0 !important;*/
|
|
/*padding: 0 !important;*/
|
|
/*margin: 10px !important;*/
|
|
/* Font rendering (mainly for firefox) */
|
|
text-rendering: optimizeLegibility;
|
|
-webkit-font-smoothing: antialiased;
|
|
-moz-osx-font-smoothing: grayscale;
|
|
}
|
|
|
|
.body_wrap {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
top: 0px;
|
|
left: 0px;
|
|
background-repeat: no-repeat;
|
|
background-position: center;
|
|
background-size: cover;
|
|
height: 100%;
|
|
}
|
|
|
|
.opaque {
|
|
top: 0px;
|
|
left: 0px;
|
|
filter: alpha(opacity=60);
|
|
opacity: 0.6;
|
|
}
|
|
|
|
.vopaque {
|
|
top: 0px;
|
|
left: 0px;
|
|
filter: alpha(opacity=40);
|
|
opacity: 0.4;
|
|
}
|
|
|
|
.options_pane {
|
|
background-color: var(--options_pane_background);
|
|
border: 2px solid var(--options_pane_bordercolor);
|
|
border-radius: 20px;
|
|
justify-content: center;
|
|
align-items: center;
|
|
width: 345px;
|
|
/*height:245px;*/
|
|
}
|
|
|
|
.scheduler_pane {
|
|
background-color: var(--options_pane_background);
|
|
border: 2px solid var(--options_pane_bordercolor);
|
|
border-radius: 20px;
|
|
justify-content: center;
|
|
align-items: center;
|
|
width: 650px;
|
|
padding: 10px;
|
|
/*overflow-y: scroll; didn't work*/
|
|
/*height: 100%;*/
|
|
/*flex-basis: content;*/
|
|
/*flex-direction: column;*/
|
|
}
|
|
|
|
.simulator_pane {
|
|
background-color: var(--options_pane_background);
|
|
border: 2px solid var(--options_pane_bordercolor);
|
|
border-radius: 20px;
|
|
justify-content: center;
|
|
align-items: center;
|
|
/* Actual size of sim 305 by 385 */
|
|
width: 325px;
|
|
height: 405px;
|
|
padding: 10px;
|
|
/*overflow-y: scroll; didn't work*/
|
|
/*height: 100%;*/
|
|
/*flex-basis: content;*/
|
|
/*flex-direction: column;*/
|
|
}
|
|
|
|
.simiframe {
|
|
width: 305px;
|
|
height: 385px;
|
|
}
|
|
|
|
.options {
|
|
top: 10px;
|
|
/*left: 10px;*/
|
|
position: fixed;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
width: 100vw;
|
|
/*
|
|
height: 100%;
|
|
*/
|
|
}
|
|
|
|
/*
|
|
.show {
|
|
top: 0px;
|
|
left: 0px;
|
|
}
|
|
*/
|
|
|
|
.wrapper {
|
|
display: grid;
|
|
/*grid-template-columns: repeat(auto-fill, minmax(var(--tile-width), var(--tile-width)));
|
|
grid-auto-rows: 1fr, repeat(auto-fill, minmax(var(--tile-width), var(--tile-width)));*/
|
|
grid-template-columns: repeat(auto-fit, minmax(var(--tile-width), auto));
|
|
grid-auto-rows: 1fr, repeat(auto-fit, minmax(var(--tile-width), auto));
|
|
grid-gap: var(--tile_grid-gap);
|
|
padding: 0 !important;
|
|
margin: 10px !important;
|
|
}
|
|
|
|
.head {
|
|
/*background-color: rgb(124, 124, 124);*/
|
|
background-color: var(--head_background);
|
|
color: var(--head_text);
|
|
border-radius: 5px;
|
|
padding: 5px;
|
|
grid-column: 1 / -1;
|
|
}
|
|
|
|
.error {
|
|
background-color: var(--error_background) !important;
|
|
}
|
|
|
|
.hide {
|
|
display: none;
|
|
filter: alpha(opacity=0);
|
|
opacity: 0.0;
|
|
}
|
|
|
|
.tile {
|
|
background-color: var(--tile_background);
|
|
color: var(--tile_text);
|
|
border-radius: 10px;
|
|
padding: 0px;
|
|
/*font-size: 100%;*/
|
|
box-sizing: border-box;
|
|
padding: 5px;
|
|
height: var(--tile-width);
|
|
width: var(--tile-width);
|
|
filter: alpha(opacity=90);
|
|
opacity: 0.9;
|
|
}
|
|
|
|
.on {
|
|
background-color: var(--tile_on_background);
|
|
color: var(--tile_on_text);
|
|
filter: alpha(opacity=100);
|
|
opacity: 1.0;
|
|
}
|
|
|
|
.flash {
|
|
color: var(--tile_on_text);
|
|
filter: alpha(opacity=100);
|
|
opacity: 0.9;
|
|
-webkit-animation-name: tile-flash;
|
|
/* Safari 4.0 - 8.0 */
|
|
-webkit-animation-duration: 2s;
|
|
/* Safari 4.0 - 8.0 */
|
|
animation-name: tile-flash;
|
|
animation-duration: 2s;
|
|
animation-iteration-count: infinite;
|
|
}
|
|
|
|
/* Safari 4.0 - 8.0 */
|
|
|
|
@-webkit-keyframes tile-flash {
|
|
0% {
|
|
background-color: var(--tile_on_background);
|
|
opacity: 1.0;
|
|
}
|
|
50% {
|
|
background-color: var(--tile_background);
|
|
opacity: 0.9;
|
|
}
|
|
100% {
|
|
background-color: var(--tile_on_background);
|
|
opacity: 1.0;
|
|
}
|
|
}
|
|
|
|
/* Standard syntax */
|
|
|
|
@keyframes tile-flash {
|
|
0% {
|
|
background-color: var(--tile_on_background);
|
|
opacity: 1.0;
|
|
}
|
|
50% {
|
|
background-color: var(--tile_background);
|
|
opacity: 0.9;
|
|
}
|
|
100% {
|
|
background-color: var(--tile_on_background);
|
|
opacity: 1.0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
.off {
|
|
background-color: #ccc;
|
|
color: rgb(133, 133, 133);
|
|
}
|
|
*/
|
|
|
|
.tile_icon {
|
|
height: var(--tile_icon-height);
|
|
display: table;
|
|
margin: 0 auto;
|
|
/*background-color: red;*/
|
|
}
|
|
|
|
.tile_name {
|
|
height: var(--tile_name-height);
|
|
/*background-color: green;*/
|
|
line-height: var(--tile_name-lineheight);
|
|
}
|
|
.tile_name_1line {
|
|
height: var(--tile_name-height1line);
|
|
/*background-color: green;*/
|
|
line-height: var(--tile_name-lineheight);
|
|
}
|
|
|
|
.tile_status {
|
|
color: var(--tile_status_text);
|
|
height: var(--tile_status-height);
|
|
/*background-color: blue;*/
|
|
}
|
|
|
|
.tile_icon_value {
|
|
border-radius: calc(var(--tile_icon-height) / 2);
|
|
font-weight: 600;
|
|
/*border-radius: 27px;*/
|
|
height: var(--tile_icon-height);
|
|
min-width: var(--tile_icon-height);
|
|
text-align: center;
|
|
vertical-align: middle;
|
|
line-height: var(--tile_icon-height);
|
|
filter: alpha(opacity=100);
|
|
opacity: 1.0;
|
|
}
|
|
|
|
.heat {
|
|
background-color: rgb(255, 123, 0);
|
|
color: rgb(255, 255, 255);
|
|
}
|
|
|
|
.cool {
|
|
background-color: rgb(4, 159, 248);
|
|
color: rgb(255, 255, 255);
|
|
}
|
|
|
|
.enabled {
|
|
background-color: rgb(78, 196, 0);
|
|
color: rgb(255, 255, 255);
|
|
}
|
|
|
|
.disabled {
|
|
background-color: rgb(110, 110, 110);
|
|
color: rgb(220, 220, 220);
|
|
}
|
|
|
|
/* All for options panel */
|
|
|
|
.option_switch {
|
|
position: relative;
|
|
display: inline-block;
|
|
width: 60px;
|
|
height: 34px
|
|
}
|
|
|
|
.option_switch input {
|
|
display: none;
|
|
}
|
|
|
|
.option_switch_slide {
|
|
position: absolute;
|
|
cursor: pointer;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: var(--options_slider_lowlight);
|
|
-webkit-transition: .4s;
|
|
transition: .4s;
|
|
border-radius: 34px;
|
|
}
|
|
|
|
.option_switch_slide:before {
|
|
position: absolute;
|
|
content: "";
|
|
height: calc(var(--options_slider_ball)*1px);
|
|
width: calc(var(--options_slider_ball)*1px);
|
|
left: 2px;
|
|
bottom: 2px;
|
|
background-color: white;
|
|
-webkit-transition: .4s;
|
|
transition: .4s;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
input:checked+.option_switch_slide {
|
|
background-color: var(--options_slider_highlight);
|
|
}
|
|
|
|
input:focus+.option_switch_slide {
|
|
box-shadow: 0 0 1px var(--options_slider_highlight);
|
|
}
|
|
|
|
input:checked+.option_switch_slide:before {
|
|
-webkit-transform: translateX(26px);
|
|
-ms-transform: translateX(26px);
|
|
transform: translateX(26px);
|
|
}
|
|
|
|
.option_slider {
|
|
-webkit-appearance: none;
|
|
width: 300px;
|
|
height: var(--options_slider_height);
|
|
background: var(--options_slider_lowlight);
|
|
outline: none;
|
|
-webkit-transition: .2s;
|
|
transition: opacity .2s;
|
|
border-radius: var(--options_slider_height);
|
|
}
|
|
|
|
.option_slider::-webkit-slider-thumb {
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
width: calc(var(--options_slider_ball)*1px);
|
|
height: calc(var(--options_slider_ball)*1px);
|
|
background: var(--options_slider_highlight);
|
|
cursor: pointer;
|
|
border-radius: calc(var(--options_slider_ball)*1px);
|
|
}
|
|
|
|
.option_slider::-moz-range-thumb {
|
|
width: calc(var(--options_slider_ball)*1px);
|
|
height: calc(var(--options_slider_ball)*1px);
|
|
background: var(--options_slider_highlight);
|
|
cursor: pointer;
|
|
border-radius: var(--options_slider_height);
|
|
}
|
|
|
|
.options_title {
|
|
/*background-color: rgb(124, 124, 124);
|
|
color: #fff;
|
|
font-weight: 200;*/
|
|
font-size: 18px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.options_selector {
|
|
font-family: var(--fonts);
|
|
font-weight: 600;
|
|
font-size: 16px;
|
|
}
|
|
|
|
.options_button {
|
|
color: var(--body_text);
|
|
font-family: var(--fonts);
|
|
font-weight: 600;
|
|
font-size: 16px;
|
|
}
|
|
|
|
.option_text {
|
|
font-family: var(--fonts);
|
|
font-weight: 600;
|
|
font-size: 16px;
|
|
}
|
|
|
|
.option_radiocontainer {
|
|
padding: 0.2em 0;
|
|
/*font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;*/
|
|
font-weight: 500;
|
|
font-size: 14px;
|
|
}
|
|
|
|
/* hide the "real" radios visually */
|
|
|
|
.radio input {
|
|
border: 0;
|
|
clip: rect(0 0 0 0);
|
|
height: 1px;
|
|
margin: -1px;
|
|
overflow: hidden;
|
|
padding: 0;
|
|
position: absolute;
|
|
width: 1px;
|
|
}
|
|
|
|
/* style the "fake" radios */
|
|
|
|
.option_radio-value {
|
|
background-color: var(--options_radio_lowlight);
|
|
background-repeat: no-repeat;
|
|
background-position: center;
|
|
background-size: 95% auto;
|
|
border-radius: 50%;
|
|
display: inline-block;
|
|
height: var(--options_radio_ball);
|
|
width: var(--options_radio_ball);
|
|
margin-right: 0.2em;
|
|
margin-left: 0.5em;
|
|
position: relative;
|
|
vertical-align: -0.3em;
|
|
/* Beautify
|
|
border: 0.0625em solid #bbb;
|
|
box-shadow: inset 0 0.0625em 0 0.0625em rgba(0,0,0,0.075);*/
|
|
}
|
|
|
|
input:checked+.option_radio-value {
|
|
background-color: var(--options_radio_highlight);
|
|
/* Beautify
|
|
border-color: #169a9a;
|
|
box-shadow: 0 0.0625em 0 0.0625em rgba(0,0,0,0.075);*/
|
|
}
|
|
|
|
.sc_tablehead {
|
|
vertical-align: top;
|
|
text-align: center;
|
|
}
|
|
|
|
.cs_commandcell {
|
|
background-color: var(--csinputcell_background);
|
|
width:60px !important;
|
|
overflow: hidden;
|
|
overflow: -moz-hidden-unscrollable;
|
|
-webkit-appearance: none;
|
|
-moz-appearance: none;
|
|
padding: 0;
|
|
}
|
|
.cs_devicecell {
|
|
background-color: var(--csinputcell_background);
|
|
width:150px !important;
|
|
overflow: hidden;
|
|
overflow: -moz-hidden-unscrollable;
|
|
-webkit-appearance: none;
|
|
-moz-appearance: none;
|
|
padding: 0;
|
|
}
|
|
|
|
.cs_valuecell {
|
|
width:40px !important;
|
|
}
|
|
|
|
.cs_inputcell {
|
|
background-color: var(--csinputcell_background);
|
|
text-align: left;
|
|
width:50px;
|
|
padding: 2px;
|
|
/*background-color:#f0f0f0 ;*/
|
|
border:none;
|
|
/*-webkit-appearance: textfield;*/
|
|
/*-webkit-appearance: none;*/
|
|
/*-moz-appearance: textfield;*/
|
|
font-size: 14px;
|
|
color: var(--body_text);
|
|
}
|
|
|
|
.cs_deletebutton {
|
|
font-size: 14px;
|
|
font-weight: bold;
|
|
color: var(--body_text);
|
|
}
|
|
|
|
.cs_crontext {
|
|
font-size: 18px;
|
|
background-color: var(--cronhelp_background);
|
|
}
|
|
|
|
.cs_helpright {
|
|
background-color: var(--cronhelp_background);
|
|
font-size: 12px;
|
|
padding-top: 0px;
|
|
padding-right: 0px;
|
|
padding-bottom: 0px;
|
|
padding-left: 5px;
|
|
font-weight: 500;
|
|
text-align:left;
|
|
}
|
|
.cs_helpleft {
|
|
background-color: var(--cronhelp_background);
|
|
font-size: 12px;
|
|
padding-top: 0px;
|
|
padding-right: 5px;
|
|
padding-bottom: 0px;
|
|
padding-left: 0px;
|
|
font-weight: 600;
|
|
text-align:right;
|
|
}
|
|
.cs_error {
|
|
background-color: red;
|
|
}
|
|
|
|
/*
|
|
.timedate {
|
|
font-size: 10px;
|
|
}*/
|
|
</style>
|
|
|
|
<script type='text/javascript'>
|
|
//'use strict';
|
|
var _lightProgramDropdown = false;
|
|
var _pressEvent;
|
|
var _ignoreMouseEvent = false;
|
|
var _temperature_units;
|
|
var _aqualink_data;
|
|
var _landscape = false;
|
|
var _displayNames = [];
|
|
var _scheduler_devices_json= [];
|
|
|
|
|
|
var _swgALLStatus = {
|
|
0: "On",
|
|
1: "No flow",
|
|
2: "Low salt",
|
|
4: "High salt",
|
|
8: "Clean cell",
|
|
9: "Turning off",
|
|
16: "High current",
|
|
32: "Low volts",
|
|
64: "Low temp",
|
|
128: "Check PCB",
|
|
253: "General Fault",
|
|
254: "Unknown",
|
|
255: "Off"
|
|
}
|
|
|
|
if (typeof show_vsp_gpm !== 'undefined' && show_vsp_gpm == false)
|
|
var _show_vsp_gpm=false;
|
|
else
|
|
var _show_vsp_gpm=true;
|
|
|
|
if (typeof link_spa_and_spa_heater !== 'undefined' && link_spa_and_spa_heater == true)
|
|
var _link_spa_and_heater=true;
|
|
else
|
|
var _link_spa_and_heater=false;
|
|
|
|
// If swgStatus was defined in config.js, use it, else create our own
|
|
if (typeof swgStatus !== 'undefined') {
|
|
var _swgStatus = swgStatus;
|
|
} else {
|
|
var _swgStatus = _swgALLStatus
|
|
}
|
|
|
|
function init() {
|
|
setSizeSpecifics();
|
|
populateLightProgram(-1);
|
|
//populateLightProgram(0);
|
|
document.getElementById('thermostat_options').classList.remove("hide");
|
|
document.getElementById('swg_options').classList.remove("hide");
|
|
document.getElementById('pswitch_options').classList.remove("hide");
|
|
document.getElementById('vspswitch_options').classList.remove("hide");
|
|
document.getElementById('timer_options').classList.remove("hide");
|
|
document.getElementById('scheduler_options').classList.remove("hide");
|
|
//document.getElementById('simulator_options').classList.remove("hide");
|
|
document.getElementById('simulator_iframe').classList.remove("hide");
|
|
setColors();
|
|
load_background();
|
|
showTileOptions(false);
|
|
startWebsockets();
|
|
resetBackgroundSize();
|
|
}
|
|
|
|
function populateLightProgram(type=0) {
|
|
var light_program = _light_program[type];
|
|
|
|
if (_lightProgramDropdown) {
|
|
option = document.getElementById('pswitch_option_list');
|
|
try {
|
|
fLen = light_program.length;
|
|
for (i = 0; i < fLen; i++) {
|
|
var opt = document.createElement('option');
|
|
opt.value = i + 1;
|
|
opt.innerHTML = light_program[i];
|
|
option.appendChild(opt);
|
|
}
|
|
} catch (e) {}
|
|
} else {
|
|
var tbody = document.getElementById('pswitch_table').getElementsByTagName('tbody')[0];
|
|
if (type == -1) {
|
|
// -1 is Just init, so create another row, just to delete later.
|
|
row = tbody.insertRow(2);
|
|
row.innerHTML = "<td align='center'>Solid Color</td><td align='center'>Light Show</td>";
|
|
light_program = _light_program[0]; // Use aqualinkd light modes to set size below
|
|
}
|
|
var html1 = '';
|
|
var html2 = '';
|
|
var fLen = light_program.length;
|
|
var i;
|
|
for (i = 0; i < fLen; i++) {
|
|
if (light_program[i].endsWith(" - Show"))
|
|
html2 = html2 + "<div class='option_radiocontainer'><label><span class='radio'><input type='radio' name='light_program' value='" + (i+1) + "' onchange='updatePwsitchOptions(this, "+type+");'><span class='option_radio-value' aria-hidden='true'></span></span>" + light_program[i].substr(0, (light_program[i].length - 7)) + "</label></div>";
|
|
else
|
|
html1 = html1 + "<div class='option_radiocontainer'><label><span class='radio'><input type='radio' name='light_program' value='" + (i+1) + "' onchange='updatePwsitchOptions(this, "+type+");'><span class='option_radio-value' aria-hidden='true'></span></span>" + light_program[i] + "</label></div>";
|
|
}
|
|
var row;
|
|
row = tbody.deleteRow(2);
|
|
row = tbody.insertRow(2);
|
|
if (type == 6) {
|
|
row.innerHTML = "<td align='center'>Dimmer</td><td align='center'></td>";
|
|
} else {
|
|
row.innerHTML = "<td align='center'>Solid Color</td><td align='center'>Light Show</td>";
|
|
}
|
|
tbody.deleteRow(3);
|
|
row = tbody.insertRow(3);
|
|
row.innerHTML = "<td align='left' valign='top'>" + html1 + "</td><td align='left' valign='top'>" + html2 + "</td>";
|
|
}
|
|
}
|
|
|
|
function setProp(name) {
|
|
if (typeof window[name] !== 'undefined')
|
|
document.documentElement.style.setProperty('--' + name, window[name]);
|
|
}
|
|
|
|
function setColors() {
|
|
setProp("tile_on_background");
|
|
setProp("tile_on_background-crap");
|
|
setProp("body_background");
|
|
setProp("body_text");
|
|
setProp("options_pane_background");
|
|
setProp("options_pane_bordercolor");
|
|
setProp("options_slider_highlight");
|
|
setProp("options_slider_lowlight");
|
|
setProp("head_background");
|
|
setProp("head_text");
|
|
setProp("error_background");
|
|
setProp("tile_background");
|
|
setProp("tile_text");
|
|
setProp("tile_on_background");
|
|
setProp("tile_on_text");
|
|
setProp("tile_status_text");
|
|
}
|
|
|
|
function setSizeSpecifics() {
|
|
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
|
|
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
|
|
//alert(w+"x"+h+" = "+(w*h));
|
|
|
|
// 375x724 = 271500
|
|
if ((w * h) > 370000) { // 370000 is kind-a just guess
|
|
document.documentElement.style.setProperty('--tile-width', '125px');
|
|
document.documentElement.style.setProperty('--tile_icon-height', '45px');
|
|
document.documentElement.style.setProperty('--tile_name-height', '42px');
|
|
document.documentElement.style.setProperty('--tile_name-height1line', '27px');
|
|
document.documentElement.style.setProperty('--tile_name-charlimit', '15');
|
|
document.documentElement.style.setProperty('--tile_status-height', '15px');
|
|
document.documentElement.style.setProperty('--tile_grid-gap', '20px');
|
|
document.documentElement.style.setProperty('--tile_name-lineheight', '1.4');
|
|
}
|
|
if (w > h)
|
|
_landscape = true;
|
|
else
|
|
_landscape = false;
|
|
setOrientation(_landscape);
|
|
/*
|
|
Future change element sizes here if needed
|
|
*/
|
|
window.addEventListener("orientationchange", function() {
|
|
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
|
|
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
|
|
// Have no idea why this is reversed, but w is less then h in landscape when captured here.
|
|
if (w < h)
|
|
_landscape = true;
|
|
else
|
|
_landscape = false;
|
|
setOrientation(_landscape);
|
|
// Need to finish rendering before calling this, so wait a small time
|
|
setTimeout(resetBackgroundSize, 100);
|
|
}, false);
|
|
}
|
|
|
|
function setOrientation(isLandscape) {
|
|
if (isLandscape) {
|
|
//alert('lll')
|
|
document.getElementById("td_name").width = '72px';
|
|
document.getElementById("td_timedate").width = '72px';
|
|
} else {
|
|
document.getElementById("td_name").width = '72px';
|
|
document.getElementById("td_timedate").width = '102px';
|
|
}
|
|
}
|
|
|
|
function load_background() {
|
|
// check for undevined AND defined but empty
|
|
if (typeof background_url === 'undefined' || background_url === undefined)
|
|
return;
|
|
//alert("load");
|
|
// call the notify_complete function when the image has loaded
|
|
var image = new Image();
|
|
image.onload = function() {
|
|
document.getElementById("body_wrap").style.backgroundImage = "url('" + this.src + "')";
|
|
};
|
|
image.onerror = function() {
|
|
image.src = "hk/background.jpg"; // Use default if image fails.
|
|
};
|
|
if (typeof background_reload !== 'undefined' && background_reload > 0) {
|
|
if (background_url.indexOf('?') > 0 )
|
|
image.src = background_url + '&aqrnd=' + new Date().getTime();
|
|
else
|
|
image.src = background_url + '?' + new Date().getTime();
|
|
|
|
setTimeout(load_background, (background_reload * 1000));
|
|
} else {
|
|
image.src = background_url;
|
|
}
|
|
}
|
|
// If the grid continer is larger than the page container, increase page so background looks nice
|
|
// also reduce size if needed on page rotate.
|
|
function resetBackgroundSize() {
|
|
if (typeof background_url === 'undefined' || background_url === undefined)
|
|
return;
|
|
try {
|
|
//inside = document.getElementById('wrapper');
|
|
outside = document.getElementById('body_wrap');
|
|
insideH = parseInt(window.getComputedStyle(document.getElementById('wrapper')).height);
|
|
outsideH = parseInt(window.getComputedStyle(outside).height);
|
|
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
|
|
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
|
|
if (insideH > outsideH || outsideH > h) {
|
|
//outside.style.height = ((insideH > h)?(insideH + 40)+'px':(h + 40)+'px');
|
|
outside.style.height = ((insideH > h) ? (insideH + 40) + 'px' : h + 'px');
|
|
//alert("w:"+w+" h:"+h+" inH:"+insideH+" outH:"+outsideH+"\nUsed:"+outside.style.height);
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
|
|
function endPress(id) {
|
|
//pressEvent = 0;
|
|
//alert ("Long press "+id);
|
|
//switchTileState(id, true);
|
|
showTileOptions(true, id);
|
|
}
|
|
|
|
function add_clickEvent(tile, id) {
|
|
tile.addEventListener('touchstart', function() {
|
|
_ignoreMouseEvent = true;
|
|
_pressEvent = window.setTimeout(function() {
|
|
_pressEvent = 0;
|
|
endPress(id);
|
|
}, 1000);
|
|
});
|
|
tile.addEventListener('touchend', function() {
|
|
if (_pressEvent != 0) {
|
|
clearTimeout(_pressEvent);
|
|
switchTileState(id, false);
|
|
}
|
|
});
|
|
tile.addEventListener("mousedown", function() {
|
|
if (_ignoreMouseEvent == false) {
|
|
_pressEvent = window.setTimeout(function() {
|
|
_pressEvent = 0;
|
|
endPress(id);
|
|
}, 1000);
|
|
}
|
|
});
|
|
tile.addEventListener("mouseup", function() {
|
|
if (_pressEvent != 0 && _ignoreMouseEvent == false) {
|
|
clearTimeout(_pressEvent);
|
|
switchTileState(id, false);
|
|
}
|
|
});
|
|
}
|
|
|
|
function add_tile(id, name, status, type, subtype, off_imgurl, on_imgurl) {
|
|
var height = getComputedStyle(document.documentElement).getPropertyValue('--tile_icon-height');
|
|
|
|
var div = document.createElement('div');
|
|
div.setAttribute('class', 'tile');
|
|
div.setAttribute('id', id);
|
|
div.setAttribute('type', subtype);
|
|
//div.setAttribute('onclick', "switchTileState('" + id + "')");
|
|
var subdiv = document.createElement('div');
|
|
subdiv.setAttribute('class', 'tile_icon');
|
|
subdiv.setAttribute('id', id + '_icon');
|
|
if (off_imgurl != null) {
|
|
var imgdiv = document.createElement('img');
|
|
imgdiv.setAttribute('height', height + 'px');
|
|
imgdiv.setAttribute('src', off_imgurl);
|
|
subdiv.appendChild(imgdiv);
|
|
div.appendChild(subdiv);
|
|
if (on_imgurl != null) {
|
|
subdiv = document.createElement('div');
|
|
subdiv.setAttribute('class', 'tile_icon');
|
|
subdiv.setAttribute('id', id + '_icon_on');
|
|
imgdiv = document.createElement('img');
|
|
imgdiv.setAttribute('height', height + 'px');
|
|
imgdiv.setAttribute('src', on_imgurl);
|
|
subdiv.style.display = 'none';
|
|
subdiv.appendChild(imgdiv);
|
|
div.appendChild(subdiv);
|
|
}
|
|
} else if (type == "value" || type == "thermostat") {
|
|
var valdiv = document.createElement('div');
|
|
valdiv.setAttribute('class', 'tile_icon_value disabled');
|
|
valdiv.setAttribute('id', id + '_tile_icon_value');
|
|
valdiv.textContent = '--';
|
|
subdiv.appendChild(valdiv);
|
|
div.appendChild(subdiv);
|
|
}
|
|
/*else if (type == "thermostat") {
|
|
valdiv = document.createElement('div');
|
|
valdiv.setAttribute('class', 'tile_icon_value disabled');
|
|
valdiv.setAttribute('id', id + '_tile_icon_value');
|
|
valdiv.textContent = '--';
|
|
subdiv.appendChild(valdiv);
|
|
} */
|
|
title_subdiv = document.createElement('div');
|
|
title_subdiv.setAttribute('class', 'tile_name');
|
|
title_subdiv.setAttribute('id', id + '_name');
|
|
title_subdiv.textContent = name;
|
|
div.appendChild(title_subdiv);
|
|
// Value and Thermostat are the same, but value is read only and no state
|
|
if (type != "value") {
|
|
// Add extra status line to VSP if we can
|
|
if (subtype == "switch_vsp") {
|
|
var title1linechatlimit = getComputedStyle(document.documentElement).getPropertyValue('--tile_name-charlimit');
|
|
if ( name.length <= title1linechatlimit ) {
|
|
subdiv = document.createElement('div');
|
|
subdiv.setAttribute('class', 'tile_status');
|
|
subdiv.setAttribute('id', id + '_status_line2');
|
|
div.appendChild(subdiv);
|
|
title_subdiv.classList.add("tile_name_1line");
|
|
title_subdiv.classList.remove("tile_name");
|
|
}
|
|
}
|
|
subdiv = document.createElement('div');
|
|
subdiv.setAttribute('class', 'tile_status');
|
|
subdiv.setAttribute('id', id + '_status');
|
|
subdiv.textContent = formatSatus(status);
|
|
div.appendChild(subdiv);
|
|
if (type == "switch" && (subtype != "switch_program" && subtype != "switch_vsp" && subtype != "switch_timer") ) {
|
|
//if (type == "switch" && subtype != "switch_program" ) {
|
|
div.setAttribute('onclick', "switchTileState('" + id + "')");
|
|
//console.log("add onclick switchtilestate to "+id);
|
|
} else /*if (id != "SWG/Percent")*/ {
|
|
add_clickEvent(div, id);
|
|
//console.log("add click Event to "+id);
|
|
}
|
|
}
|
|
document.getElementById('wrapper').appendChild(div);
|
|
}
|
|
|
|
function switchTileState(id, details) {
|
|
if (details) {
|
|
console.log("TILE DETAILS WHAY ARE WE HERE??? '" + id + "'");
|
|
} else {
|
|
setTileState(id, (document.getElementById(id).getAttribute('status') == 'off'))
|
|
}
|
|
}
|
|
|
|
function setTileState(id, state) {
|
|
try {
|
|
if (state == (document.getElementById(id).getAttribute('status') == 'off')) {
|
|
send_command(id, (state==true?1:0) );
|
|
//console.log("Switch state "+id+" to "+(state)?"on":"off");
|
|
} else {
|
|
//console.log("state "+id+" to "+(state)?"on":"off")
|
|
}
|
|
|
|
setTileOn(id, ((state) ? "on" : "off"));
|
|
} catch(exception) {}
|
|
}
|
|
|
|
function setThermostatSetpoint(id, sp_value) {
|
|
var tile;
|
|
if ((tile = document.getElementById(id)) == null) {
|
|
return;
|
|
}
|
|
tile.setAttribute('setpoint', sp_value);
|
|
send_setpoint(id);
|
|
}
|
|
|
|
/*
|
|
function setTileValue(id, value) {
|
|
var ext = '';
|
|
var type;
|
|
if (value == undefined || value.startsWith("-999") || value.startsWith(" "))
|
|
value = '--';
|
|
else {
|
|
try {
|
|
if ((type = document.getElementById(id).getAttribute('type')) != null) {
|
|
if (type == 'temperature' || type == 'setpoint_thermo' || type == 'setpoint_freeze')
|
|
ext = '°';
|
|
else if (type == 'setpoint_swg')
|
|
ext = '%';
|
|
|
|
if ((type == 'temperature' || type == 'value') && turn_on_sensortiles == true) {
|
|
if (value == 0 || value == '--')
|
|
setTileOn(id, 'off');
|
|
else
|
|
setTileOn(id, 'on');
|
|
}
|
|
}
|
|
} catch (e) {
|
|
//console.log('ERROR id=' + id + ' Line 764 | element = '+document.getElementById(id));
|
|
}
|
|
}
|
|
//document.getElementById(id + '_tile_icon_value').textContent = value;
|
|
var tile;
|
|
if ((tile = document.getElementById(id + '_tile_icon_value')) != null)
|
|
tile.innerHTML = value + ext;
|
|
}
|
|
*/
|
|
function setTileValue(id, value) {
|
|
var ext = '';
|
|
var type = null;
|
|
try {
|
|
type = document.getElementById(id).getAttribute('type');
|
|
|
|
if (value == undefined || value.startsWith("-999") || value.startsWith(" ")) {
|
|
value = '--';
|
|
} else {
|
|
if ((type = document.getElementById(id).getAttribute('type')) != null) {
|
|
if (type == 'temperature' || type == 'setpoint_thermo' || type == 'setpoint_freeze')
|
|
ext = '°';
|
|
else if (type == 'setpoint_swg')
|
|
ext = '%';
|
|
}
|
|
}
|
|
|
|
if ((type == 'temperature' || type == 'value') && turn_on_sensortiles == true) {
|
|
// Anything specific (SWG PPM should be off if SWG is off)
|
|
// This needs a try catch, or is above try block good enough?
|
|
if (id == 'SWG/PPM' && document.getElementById('SWG').getAttribute('status') != 'on' )
|
|
setTileOn(id, 'off');
|
|
// Generic for all.
|
|
else if (value == 0 || value == '--')
|
|
setTileOn(id, 'off');
|
|
else
|
|
setTileOn(id, 'on');
|
|
}
|
|
} catch (e) {
|
|
// NSF Do we need to create the device?
|
|
console.log('ERROR id=' + id + ' Line 837 | element = '+document.getElementById(id));
|
|
}
|
|
//document.getElementById(id + '_tile_icon_value').textContent = value;
|
|
var tile;
|
|
if ((tile = document.getElementById(id + '_tile_icon_value')) != null)
|
|
tile.innerHTML = value + ext;
|
|
}
|
|
|
|
function setTileOnText(id, text) {
|
|
try {
|
|
if (document.getElementById(id).getAttribute('status') == 'on') {
|
|
document.getElementById(id + '_status').innerHTML = text;
|
|
} else {
|
|
//console.log("Tile "+id+" status is '"+document.getElementById(id).getAttribute('status')+"' not setting text to '"+text+"'");
|
|
}
|
|
} catch(exception) {}
|
|
}
|
|
function setTileOnTextLine2(id, text) {
|
|
try {
|
|
if (document.getElementById(id).getAttribute('status') == 'on') {
|
|
document.getElementById(id + '_status_line2').innerHTML = text;
|
|
} else {
|
|
//console.log("Tile "+id+" status is '"+document.getElementById(id).getAttribute('status')+"' not setting text to '"+text+"'");
|
|
}
|
|
} catch(exception) {}
|
|
}
|
|
|
|
function setThermostatTile(id, value, sp_value) {
|
|
setTileValue(id, value);
|
|
var tile;
|
|
if ((tile = document.getElementById(id)) != null) {
|
|
tile.setAttribute('setpoint', sp_value);
|
|
}
|
|
}
|
|
|
|
function setTileAttribute(id, attribute, value) {
|
|
var tile;
|
|
if ((tile = document.getElementById(id)) != null) {
|
|
//console.log("Set Attribute "+attribute+ " to "+value+" for "+id);
|
|
tile.setAttribute(attribute, value);
|
|
}
|
|
}
|
|
|
|
function getTileAttribute(id, attribute) {
|
|
var tile;
|
|
if ((tile = document.getElementById(id)) != null) {
|
|
//console.log("get Attribute "+attribute+ " to "+tile.getAttribute(attribute)+" for "+id);
|
|
return tile.getAttribute(attribute);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function formatSatus(status) {
|
|
var index;
|
|
var aux;
|
|
var status;
|
|
|
|
if ((index = status.indexOf("AUX")) >= 0) {
|
|
aux = status.substr(index, 4);
|
|
status = status.charAt(0).toUpperCase() + status.substr(1).toLowerCase();
|
|
if ((name = _displayNames[aux]) != undefined) {
|
|
status = status.substr(0, index) + name + status.substr(index + 4);
|
|
}
|
|
} else if ((index = status.indexOf("ERROR")) >= 0) {
|
|
status = status;
|
|
} else {
|
|
status = status.charAt(0).toUpperCase() + status.substr(1).toLowerCase();
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
function setTileOn(id, status) {
|
|
//console.log("setTileOn "+id+ " "+status);
|
|
var tile;
|
|
var text;
|
|
if ((tile = document.getElementById(id)) == null) {
|
|
//console.log("Error unknown ID '"+id+"' can't set to '"+status+"'");
|
|
return;
|
|
}
|
|
// Display is a special status to "brighten up" sensor values.
|
|
if (status != "on" && status != "off" && status != "enabled" && status != "flash") {
|
|
if (status == "unknown") {
|
|
status = "off"; // Just set it off for the moment
|
|
} else {
|
|
console.log("Error unknown status '" + status + "' for '" + id + "'");
|
|
return;
|
|
}
|
|
}
|
|
tile.setAttribute('status', status);
|
|
if (status != 'off') {
|
|
if (status == 'flash') {
|
|
tile.classList.add("flash");
|
|
tile.classList.remove("on");
|
|
text = "Delay";
|
|
} else {
|
|
tile.classList.add("on");
|
|
tile.classList.remove("flash");
|
|
text = "On";
|
|
}
|
|
var offimg;
|
|
var onimg;
|
|
if ((offimg = document.getElementById(id + '_icon')) != null &&
|
|
(onimg = document.getElementById(id + '_icon_on')) != null) {
|
|
offimg.style.display = 'none';
|
|
onimg.style.display = 'table';
|
|
}
|
|
var type;
|
|
if ((type = tile.getAttribute('type')) != null) {
|
|
if (type == 'setpoint_swg') {
|
|
var exstatus = parseInt(tile.getAttribute('fullstatus'))
|
|
// Could also ignore "Enabled" in below, that way we don't jump different stats on startup
|
|
if (exstatus > 0 && exstatus < 255) {// Not off or on
|
|
//text = swgFullstatus2String(exstatus);
|
|
text = _swgStatus[exstatus];
|
|
if (typeof text == 'undefined') {
|
|
text = _swgALLStatus[exstatus];
|
|
}
|
|
} else if (tile.getAttribute('Boost') == 'on')
|
|
text = "Boost";
|
|
else if (status == 'enabled')
|
|
text = 'Enabled';
|
|
else
|
|
text = 'Generating';
|
|
}
|
|
else if (type == 'setpoint_thermo')
|
|
//if (status == 'enabled')
|
|
text = 'Heat to ' + tile.getAttribute('setpoint');
|
|
//else
|
|
// text = 'Heating to ' + tile.getAttribute('setpoint'); // too large for phone
|
|
else if (type == 'setpoint_freeze')
|
|
text = 'Turn on ' + tile.getAttribute('setpoint') + "°";
|
|
//else
|
|
// text = "On";
|
|
}
|
|
//document.getElementById(id + '_status').innerHTML = "On";
|
|
} else {
|
|
tile.classList.remove("on");
|
|
tile.classList.remove("flash");
|
|
if ((offimg = document.getElementById(id + '_icon')) != null &&
|
|
(onimg = document.getElementById(id + '_icon_on')) != null) {
|
|
onimg.style.display = 'none';
|
|
offimg.style.display = 'table';
|
|
}
|
|
text = "Off";
|
|
}
|
|
|
|
try {
|
|
document.getElementById(id + '_status').innerHTML = text;
|
|
// Clear line 2 status if we have it.
|
|
document.getElementById(id + '_status_line2').innerHTML = "";
|
|
} catch (e) {}
|
|
var tile_icon = document.getElementById(id + '_tile_icon_value');
|
|
type = tile.getAttribute('type');
|
|
if (status != null && tile_icon != null) {
|
|
if (status == 'enabled' || status == 'flash') {
|
|
tile_icon.classList.add("enabled");
|
|
tile_icon.classList.remove("disabled");
|
|
tile_icon.classList.remove("cool");
|
|
tile_icon.classList.remove("heat");
|
|
} else if (status == 'off') {
|
|
tile_icon.classList.remove("enabled");
|
|
tile_icon.classList.add("disabled");
|
|
tile_icon.classList.remove("cool");
|
|
tile_icon.classList.remove("heat");
|
|
//} else if (status == 'on' && type != 'setpoint_swg' && type != 'setpoint_freeze' && type != 'temperature' && type != 'value') {
|
|
} else if (status == 'on' && type == 'setpoint_thermo') {
|
|
tile_icon.classList.remove("enabled");
|
|
tile_icon.classList.remove("disabled");
|
|
tile_icon.classList.remove("cool");
|
|
tile_icon.classList.add("heat");
|
|
} else if (status == 'on') {
|
|
tile_icon.classList.remove("enabled");
|
|
tile_icon.classList.remove("disabled");
|
|
tile_icon.classList.add("cool");
|
|
tile_icon.classList.remove("heat");
|
|
}
|
|
}
|
|
}
|
|
|
|
function toHoursAndMinutes(totalMinutes) {
|
|
const hours = Math.floor(totalMinutes / 60);
|
|
const minutes = totalMinutes % 60;
|
|
return `${padToTwoDigits(hours)}:${padToTwoDigits(minutes)}`;
|
|
}
|
|
function padToTwoDigits(num) {
|
|
return num.toString().padStart(2, "0");
|
|
}
|
|
|
|
function createTile(object) {
|
|
if (object.name == 'NONE') {
|
|
return;
|
|
}
|
|
if (typeof devices !== 'undefined' && devices.indexOf(object.id) < 0) {
|
|
return;
|
|
}
|
|
//if (object.type == 'switch' || object.type == 'switch_program') {
|
|
if (object.type == 'switch') {
|
|
var img = object.id.replace('/', '_');
|
|
var ext_type;
|
|
if (typeof object.type_ext !== 'undefined')
|
|
ext_type = object.type_ext;
|
|
else
|
|
ext_type = object.type;
|
|
|
|
add_tile(object.id, object.name, object.state, 'switch', ext_type, 'hk/' + img + '-off.png', 'hk/' + img + '-on.png');
|
|
setTileOn(object.id, object.status, null);
|
|
if (typeof object.type_ext !== 'undefined' && object.type_ext == 'switch_program') {
|
|
if (typeof object.Light_Type !== 'undefined') {
|
|
document.getElementById(object.id).setAttribute('lighttype', object.Light_Type);
|
|
}
|
|
// Other switch_program types (other than light_type) GO HERE
|
|
} else if (typeof object.type_ext !== 'undefined' && object.type_ext == 'switch_timer') {
|
|
if (typeof object.timer_active !== 'undefined' && object.timer_active) {
|
|
//console.log("Timer for "+object.name+" = "+object.timer_active);
|
|
if (object.timer_active == 'on') {
|
|
if (typeof object.timer_duration !== 'undefined') {
|
|
setTileOnText(object.id, 'On (timer '+toHoursAndMinutes(object.timer_duration)+')');
|
|
} else {
|
|
setTileOnText(object.id, 'On (timer)');
|
|
}
|
|
}
|
|
}
|
|
} else if (typeof object.type_ext !== 'undefined' && object.type_ext == 'switch_vsp') {
|
|
if (typeof object.Pump_RPM !== 'undefined' && object.Pump_RPM) {
|
|
if (object.Pump_RPM == -3) {
|
|
setTileOnText(object.id, 'Pump ERROR'); // Small txt
|
|
document.getElementById(object.id).setAttribute('setpoint', 0);
|
|
} else if (object.Pump_RPM == -2) {
|
|
setTileOnText(object.id, 'Pump Offline'); // Small txt
|
|
document.getElementById(object.id).setAttribute('setpoint', 0);
|
|
} else if (object.Pump_RPM == -1) {
|
|
setTileOnText(object.id, 'Pump Priming'); // Small text
|
|
document.getElementById(object.id).setAttribute('setpoint', 0);
|
|
} else {
|
|
if (object.Pump_Type == "vfPump") {
|
|
if (_show_vsp_gpm == true) {
|
|
setTileOnText(object.id, 'GPM:'+object.Pump_GPM);
|
|
setTileOnTextLine2(object.id, 'RPM:'+object.Pump_RPM);
|
|
} else {
|
|
setTileOnText(object.id, 'RPM:'+object.Pump_RPM);
|
|
setTileOnTextLine2(object.id, 'GPM:'+object.Pump_GPM);
|
|
}
|
|
document.getElementById(object.id).setAttribute('setpoint', object.Pump_GPM);
|
|
} else {
|
|
setTileOnText(object.id, 'RPM:'+object.Pump_RPM);
|
|
document.getElementById(object.id).setAttribute('setpoint', object.Pump_RPM);
|
|
if (object.Pump_GPM > 0) {
|
|
setTileOnTextLine2(object.id, 'GPM:'+object.Pump_GPM);
|
|
} else {
|
|
setTileOnTextLine2(object.id, "");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (typeof object.Pump_Type !== 'undefined') {
|
|
document.getElementById(object.id).setAttribute('pumptype', object.Pump_Type);
|
|
}
|
|
}
|
|
} else if (object.type == 'value' || object.type == 'temperature') {
|
|
add_tile(object.id, object.name, object.state, 'value', object.type);
|
|
setTileValue(object.id, object.value);
|
|
} else if (object.type == 'setpoint_thermo' || object.type == 'setpoint_swg' || object.type == 'setpoint_freeze') {
|
|
add_tile(object.id, object.name, object.state, 'thermostat', object.type);
|
|
document.getElementById(object.id).setAttribute('setpoint', object.spvalue);
|
|
setTileValue(object.id, object.value);
|
|
setTileOn(object.id, object.status);
|
|
} else {
|
|
//console.log("Unknown Device");
|
|
}
|
|
}
|
|
|
|
function showTileOptions(show, id, contex) {
|
|
var active_option;
|
|
if (show == true) {
|
|
var wrapH = document.getElementById('wrapper').clientHeight + 'px';
|
|
if (id != null && document.getElementById(id).getAttribute('type') == 'setpoint_thermo') {
|
|
active_option = document.getElementById('thermostat_options');
|
|
document.getElementById('swg_options').style.display = 'none';
|
|
document.getElementById('pswitch_options').style.display = 'none';
|
|
document.getElementById('vspswitch_options').style.display = 'none';
|
|
document.getElementById('timer_options').style.display = 'none';
|
|
document.getElementById('scheduler_options').style.display = 'none';
|
|
document.getElementById('simulator_iframe').style.display = 'none';
|
|
} else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_program') {
|
|
active_option = document.getElementById('pswitch_options');
|
|
document.getElementById('thermostat_options').style.display = 'none';
|
|
document.getElementById('swg_options').style.display = 'none';
|
|
document.getElementById('vspswitch_options').style.display = 'none';
|
|
document.getElementById('timer_options').style.display = 'none';
|
|
document.getElementById('scheduler_options').style.display = 'none';
|
|
document.getElementById('simulator_iframe').style.display = 'none';
|
|
} else if (id != null && document.getElementById(id).getAttribute('type') == 'setpoint_swg') {
|
|
active_option = document.getElementById('swg_options');
|
|
document.getElementById('thermostat_options').style.display = 'none';
|
|
document.getElementById('pswitch_options').style.display = 'none';
|
|
document.getElementById('vspswitch_options').style.display = 'none';
|
|
document.getElementById('timer_options').style.display = 'none';
|
|
document.getElementById('scheduler_options').style.display = 'none';
|
|
document.getElementById('simulator_iframe').style.display = 'none';
|
|
} else if (id != null && document.getElementById(id).getAttribute('type') == 'setpoint_freeze') {
|
|
active_option = document.getElementById('swg_options');
|
|
document.getElementById('thermostat_options').style.display = 'none';
|
|
document.getElementById('pswitch_options').style.display = 'none';
|
|
document.getElementById('vspswitch_options').style.display = 'none';
|
|
document.getElementById('timer_options').style.display = 'none';
|
|
document.getElementById('scheduler_options').style.display = 'none';
|
|
document.getElementById('simulator_iframe').style.display = 'none';
|
|
} else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_vsp') {
|
|
active_option = document.getElementById('vspswitch_options');
|
|
document.getElementById('thermostat_options').style.display = 'none';
|
|
document.getElementById('pswitch_options').style.display = 'none';
|
|
document.getElementById('swg_options').style.display = 'none';
|
|
document.getElementById('timer_options').style.display = 'none';
|
|
document.getElementById('scheduler_options').style.display = 'none';
|
|
document.getElementById('simulator_iframe').style.display = 'none';
|
|
} else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_timer') {
|
|
active_option = document.getElementById('timer_options');
|
|
document.getElementById('thermostat_options').style.display = 'none';
|
|
document.getElementById('pswitch_options').style.display = 'none';
|
|
document.getElementById('swg_options').style.display = 'none';
|
|
document.getElementById('vspswitch_options').style.display = 'none';
|
|
document.getElementById('scheduler_options').style.display = 'none';
|
|
document.getElementById('simulator_iframe').style.display = 'none';
|
|
} else if (id != null && document.getElementById(id).getAttribute('type') == 'scheduler') {
|
|
active_option = document.getElementById('scheduler_options');
|
|
document.getElementById('thermostat_options').style.display = 'none';
|
|
document.getElementById('pswitch_options').style.display = 'none';
|
|
document.getElementById('swg_options').style.display = 'none';
|
|
document.getElementById('vspswitch_options').style.display = 'none';
|
|
document.getElementById('timer_options').style.display = 'none';
|
|
document.getElementById('simulator_iframe').style.display = 'none';
|
|
} else if (id != null && document.getElementById(id).getAttribute('type') == 'simulator') {
|
|
active_option = document.getElementById('simulator_iframe');
|
|
document.getElementById('thermostat_options').style.display = 'none';
|
|
document.getElementById('pswitch_options').style.display = 'none';
|
|
document.getElementById('swg_options').style.display = 'none';
|
|
document.getElementById('vspswitch_options').style.display = 'none';
|
|
document.getElementById('timer_options').style.display = 'none';
|
|
document.getElementById('scheduler_options').style.display = 'none';
|
|
}
|
|
|
|
active_option.style.display = 'flex';
|
|
/*
|
|
Not sure why I added this, but it breakes scheduler pane growing, and setpoint (heater) panes
|
|
are located too high for some reason.
|
|
var optionH = window.getComputedStyle(active_option, null).getPropertyValue("height");
|
|
if (optionH <= wrapH)
|
|
active_option.style.height = wrapH;
|
|
*/
|
|
//console.log("Option:"+optionH+" wrapH:"+wrapH);
|
|
|
|
document.getElementById('wrapper').classList.add("opaque");
|
|
} else {
|
|
// Fake onclick to close and save any values if open
|
|
if (contex == null) {
|
|
if (document.getElementById('thermostat_options').style.display == 'flex')
|
|
document.getElementById("options_close").click();
|
|
else if (document.getElementById('swg_options').style.display == 'flex')
|
|
document.getElementById("swg_options_close").click();
|
|
else if (document.getElementById('pswitch_options').style.display == 'flex')
|
|
document.getElementById("pswitch_options_close").click();
|
|
else if (document.getElementById('vspswitch_options').style.display == 'flex')
|
|
document.getElementById("vspswitch_options").click();
|
|
else if (document.getElementById('timer_options').style.display == 'flex')
|
|
document.getElementById("timer_options").click();
|
|
else if (document.getElementById('scheduler_options').style.display == 'flex')
|
|
document.getElementById("scheduler_options").click();
|
|
}
|
|
document.getElementById('thermostat_options').style.display = 'none';
|
|
document.getElementById('swg_options').style.display = 'none';
|
|
document.getElementById('pswitch_options').style.display = 'none';
|
|
document.getElementById('vspswitch_options').style.display = 'none';
|
|
document.getElementById('timer_options').style.display = 'none';
|
|
document.getElementById('scheduler_options').style.display = 'none';
|
|
document.getElementById('simulator_iframe').style.display = 'none';
|
|
document.getElementById('wrapper').classList.remove("opaque");
|
|
return;
|
|
}
|
|
if (show == true) {
|
|
var tile = document.getElementById(id);
|
|
var sp_value = tile.getAttribute('setpoint');
|
|
//tile_state = tile.classList.contains("on");
|
|
var tile_state = !(tile.getAttribute('status') == 'off');
|
|
var type = tile.getAttribute('type');
|
|
var slider;
|
|
var slider_output;
|
|
var tm_slider;
|
|
var tm_slider_output;
|
|
var title;
|
|
var close_button;
|
|
var ext;
|
|
var tm_ext;
|
|
var oswitch;
|
|
var vsp_slider_changed = false;
|
|
if (type == 'setpoint_swg') {
|
|
slider = document.getElementById("swg_option_slider_range");
|
|
slider_output = document.getElementById("swg_option_slider_text_value");
|
|
title = document.getElementById("swg_option_title");
|
|
close_button = document.getElementById("swg_options_close");
|
|
ext = "%";
|
|
} else if (type == 'setpoint_freeze') {
|
|
slider = document.getElementById("swg_option_slider_range");
|
|
slider_output = document.getElementById("swg_option_slider_text_value");
|
|
title = document.getElementById("swg_option_title");
|
|
close_button = document.getElementById("swg_options_close");
|
|
ext = '°' + _temperature_units;
|
|
} else if (type == 'switch_program') {
|
|
populateLightProgram(tile.getAttribute('lighttype') );
|
|
title = document.getElementById("pswitch_option_title");
|
|
close_button = document.getElementById("pswitch_options_close");
|
|
tm_slider = document.getElementById("ps_timer_slider_range");
|
|
tm_slider_output = document.getElementById("ps_timer_slider_text_value");
|
|
} else if (type == 'switch_vsp') {
|
|
slider = document.getElementById("vspoption_slider_range");
|
|
slider_output = document.getElementById("vspoption_slider_text_value");
|
|
tm_slider = document.getElementById("vsp_timer_slider_range");
|
|
tm_slider_output = document.getElementById("vsp_timer_slider_text_value");
|
|
title = document.getElementById("vspswitch_option_title");
|
|
close_button = document.getElementById("vspswitch_option_close");
|
|
} else if (type == 'switch_timer') {
|
|
tm_slider = document.getElementById("timer_slider_range");
|
|
tm_slider_output = document.getElementById("timer_slider_text_value");
|
|
title = document.getElementById("timer_option_title");
|
|
close_button = document.getElementById("timer_options_close");
|
|
//tm_ext = ' runtime (min)';
|
|
} else if (type == 'scheduler') {
|
|
title = document.getElementById("scheduler_options_title");
|
|
close_button = document.getElementById("scheduler_options_close");
|
|
} else if (type == 'simulator') {
|
|
close_button = document.getElementById("simulator_iframe_close");
|
|
} else {
|
|
slider = document.getElementById("option_slider_range");
|
|
slider_output = document.getElementById("option_slider_text_value");
|
|
tm_slider = document.getElementById("th_timer_slider_range");
|
|
tm_slider_output = document.getElementById("th_timer_slider_text_value");
|
|
title = document.getElementById("option_title");
|
|
close_button = document.getElementById("options_close");
|
|
ext = '°' + _temperature_units;
|
|
}
|
|
|
|
if (type == 'setpoint_swg') {
|
|
slider.min = 0;
|
|
slider.max = 101;
|
|
slider.step = 5;
|
|
} else if (type == 'setpoint_freeze') {
|
|
if (_temperature_units != 'c') { // Change to DegF
|
|
slider.min = 34;
|
|
slider.max = 42;
|
|
slider.step = 1;
|
|
} else { // Change to DegF
|
|
slider.min = 1;
|
|
slider.max = 5;
|
|
slider.step = 1;
|
|
}
|
|
} else if (type == 'setpoint_thermo') {
|
|
if (_temperature_units != 'c') { // Change to DegF
|
|
//slider.min = 36;
|
|
//slider.max = 104;
|
|
slider.min = ((typeof heater_slider_min !== 'undefined')?heater_slider_min:36);
|
|
slider.max = ((typeof heater_slider_max !== 'undefined')?heater_slider_max:104);
|
|
slider.step = 1;
|
|
} else { // Change to DegF
|
|
slider.min = 0;
|
|
slider.max = 40;
|
|
slider.step = 1;
|
|
}
|
|
} else if (type == 'switch_vsp') {
|
|
if ( tile.getAttribute('pumptype') == "vfPump" ) { // RPM vs GPM
|
|
slider.min = 15;
|
|
slider.max = 130;
|
|
slider.step = 5;
|
|
ext = ' GPM';
|
|
} else {
|
|
slider.min = 600;
|
|
slider.max = 3450;
|
|
slider.step = 5;
|
|
ext = ' RPM';
|
|
}
|
|
}
|
|
|
|
if (type == 'scheduler') {
|
|
title.innerHTML = "Scheduler";
|
|
} else if (type == 'simulator') {
|
|
// title.innerHTML = "Simulator";
|
|
} else {
|
|
title.innerHTML = document.getElementById(id + '_name').innerHTML;
|
|
}
|
|
|
|
if (type == 'switch_program') {
|
|
var pswitch = document.getElementById("pswitch_option_list");
|
|
oswitch = document.getElementById("pswitch_option_switch");
|
|
var oswitch_output = document.getElementById("pswitch_option_switch_text_value");
|
|
oswitch.checked = tile_state;
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
|
|
oswitch.onclick = function() {
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
|
|
}
|
|
} else if (type == 'setpoint_swg') {
|
|
slider.value = sp_value;
|
|
oswitch = document.getElementById("swg_option_switch");
|
|
var oswitch_output = document.getElementById("swg_option_switch_text_value");
|
|
document.getElementById("swg_option_switch_row").style.display = "table-row";
|
|
oswitch.checked = getTileAttribute(id, "Boost")=='on'?true:false ;
|
|
slider_output.innerHTML = slider.value + ext;
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "Boost On" : "Boost Off");
|
|
slider.oninput = function() {
|
|
slider_output.innerHTML = this.value + ext;
|
|
}
|
|
oswitch.onclick = function() {
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "Boost On" : "Boost Off");
|
|
}
|
|
} else if (type == 'setpoint_freeze') {
|
|
slider.value = sp_value;
|
|
oswitch = document.getElementById("swg_option_switch");
|
|
document.getElementById("swg_option_switch_row").style.display = "none";
|
|
slider_output.innerHTML = slider.value + ext;
|
|
slider.oninput = function() {
|
|
slider_output.innerHTML = this.value + ext;
|
|
}
|
|
} else if (type == 'switch_vsp') {
|
|
slider.value = sp_value;
|
|
oswitch = document.getElementById("vspoption_switch");
|
|
oswitch.checked = tile_state;
|
|
var oswitch_output = document.getElementById("vspoption_switch_text_value");
|
|
slider_output.innerHTML = slider.value + ext;
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
|
|
|
|
slider.oninput = function() {
|
|
slider_output.innerHTML = this.value + ext;
|
|
vsp_slider_changed = true;
|
|
if (oswitch.checked != true) {
|
|
oswitch.checked = true;
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
|
|
}
|
|
}
|
|
oswitch.onclick = function() {
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
|
|
}
|
|
} else if (type == 'switch_timer') {
|
|
oswitch = document.getElementById("timer_switch");
|
|
oswitch.checked = tile_state;
|
|
var oswitch_output = document.getElementById("timer_switch_text_value");
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
|
|
// All timer slider options are set below for everyone.
|
|
} else if (type == 'scheduler') {
|
|
// NSF BUILD SCHEDULER DEFAULTS HERE
|
|
cs_clearSchedules();
|
|
//cs_loadJSON("/api/schedules", cs_schedules,'jsonp');
|
|
get_schedules();
|
|
} else if (type == 'simulator') {
|
|
startSimulator();
|
|
} else {
|
|
slider.value = sp_value;
|
|
oswitch = document.getElementById("option_switch");
|
|
oswitch.checked = tile_state;
|
|
var oswitch_output = document.getElementById("option_switch_text_value");
|
|
slider_output.innerHTML = slider.value + ext;
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
|
|
slider.oninput = function() {
|
|
slider_output.innerHTML = this.value + ext;
|
|
//sp_value = this.value
|
|
}
|
|
oswitch.onclick = function() {
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
|
|
//setTileOn(id, ((oswitch.checked)?"on":"off"), null);
|
|
}
|
|
}
|
|
|
|
if (typeof tm_slider !== 'undefined' && tm_slider != null) {
|
|
tm_slider.min = ((typeof timer_slider_min !== 'undefined')?timer_slider_min:0);
|
|
tm_slider.max = ((typeof timer_slider_max !== 'undefined')?timer_slider_max:360);
|
|
tm_slider.step = ((typeof timer_slider_step !== 'undefined')?timer_slider_step:10);
|
|
tm_ext = ' runtime (min)';
|
|
|
|
tm_slider.value = tm_slider.min;
|
|
|
|
tm_slider_output.innerHTML = tm_slider.value + tm_ext;
|
|
tm_slider.oninput = function() {
|
|
tm_slider_output.innerHTML = this.value + tm_ext;
|
|
if (this.value == 0) {
|
|
oswitch.checked = false;
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
|
|
} else {
|
|
oswitch.checked = true;
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
|
|
}
|
|
}
|
|
oswitch.onclick = function() {
|
|
oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off");
|
|
if (oswitch.checked == false) {
|
|
tm_slider.value = 0;
|
|
tm_slider_output.innerHTML = "0" + tm_ext;
|
|
}
|
|
}
|
|
}
|
|
|
|
var cTime;
|
|
try {
|
|
cTime = performance.now();
|
|
} catch (e) {
|
|
cTime = Date.now(); // NSF Probably won't test well below, need to check.
|
|
}
|
|
var clickHandler = function(e) {
|
|
// Short time diff means event was the one that launched the options pane, so ignore
|
|
// Above description is incorrect, we get here when click is OFF the tile
|
|
if ((e.timeStamp - cTime) > 1000) {
|
|
showTileOptions(false);
|
|
document.getElementById("body_wrap").removeEventListener("click", clickHandler);
|
|
}
|
|
};
|
|
document.getElementById("body_wrap").addEventListener("click", clickHandler);
|
|
close_button.onclick = function() {
|
|
document.getElementById("body_wrap").removeEventListener("click", clickHandler);
|
|
var state = oswitch?.checked;
|
|
if (type == 'switch_program') {
|
|
var mode=false;
|
|
if (_lightProgramDropdown) {
|
|
if (pswitch.selectedIndex > 0) {
|
|
send_light_mode(pswitch.selectedIndex, id, pswitch.options[pswitch.selectedIndex].text);
|
|
mode=true;
|
|
}
|
|
} else {
|
|
var radio = document.getElementsByName("light_program");
|
|
var x;
|
|
for (x = 0; x < radio.length; x++) {
|
|
if (radio[x].checked == true) {
|
|
send_light_mode(radio[x].value, id, document.getElementById('pswitch_option_switch_text_value').innerHTML);
|
|
mode=true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (mode == false) {
|
|
// if (state == (tile.getAttribute('status') == 'off')) // Only bother with this if we didn;t set the light mode.
|
|
setTileState(id, state);
|
|
}
|
|
} else if (type == 'setpoint_swg') {
|
|
//console.log ("Boost attribute = "+tile.getAttribute('boost'));
|
|
//console.log ("state = "+state);
|
|
if (state == (tile.getAttribute('Boost') == 'off')) {
|
|
//console.log ("change boost");
|
|
send_command( 'SWG/Boost', (state==true?"1":"0") );
|
|
} else {
|
|
if (sp_value != slider.value && slider.value != 101) // Don't change setpoint if slider is on boost
|
|
setThermostatSetpoint(id, slider.value);
|
|
}
|
|
} else if (type == 'switch_program') {
|
|
var value = slider.value;
|
|
if (state == (tile.getAttribute('status') == 'off'))
|
|
setTileState(id, state);
|
|
if (sp_value != slider.value)
|
|
setThermostatSetpoint(id, slider.value)
|
|
} else if (type == 'switch_timer') {
|
|
if (tm_slider.value == 0 && state == (tile.getAttribute('status') == 'off'))
|
|
setTileState(id, state);
|
|
} else if (type == 'switch_vsp') {
|
|
// VSP, first check is slider changed, as startup we have no ide on RPM
|
|
var value = slider.value;
|
|
if (state == (tile.getAttribute('status') == 'off'))
|
|
setTileState(id, state);
|
|
if (sp_value != slider.value && vsp_slider_changed == true)
|
|
setThermostatSetpoint(id, slider.value)
|
|
} else if (type == 'scheduler') {
|
|
// NSF SAVE SCHEDULE HERE
|
|
// validate input form, alert and return if error, contimue if ok.
|
|
if ( ! cs_createJSON() ) {
|
|
return // This stops pane from closing.
|
|
}
|
|
} else if (type == 'simulator') {
|
|
} else {
|
|
var value = slider.value;
|
|
if (state == (tile.getAttribute('status') == 'off'))
|
|
setTileState(id, state);
|
|
if (sp_value != slider.value)
|
|
setThermostatSetpoint(id, slider.value)
|
|
}
|
|
|
|
if (typeof tm_slider !== 'undefined' && tm_slider != null) {
|
|
if (tm_slider.value > 0)
|
|
send_switch_timer(id, tm_slider.value);
|
|
}
|
|
//showTileOptions(false, null, 'this');
|
|
active_option.style.display = 'none';
|
|
document.getElementById('wrapper').classList.remove("opaque");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
_displayMsgTimer=0;
|
|
_displayMsgTimeout=0;
|
|
|
|
function displayMessage(message, timeoutSeconds) {
|
|
// Check to see if we can display message
|
|
if (_displayMsgTimeout > 0) {
|
|
if ( _displayMsgTimer + (_displayMsgTimeout * 1000) > Date.now() ) {
|
|
// Can't diaply message, still on timer
|
|
//console.log("Can't display message '"+message+"'");
|
|
return;
|
|
}
|
|
_displayMsgTimer=0;
|
|
_displayMsgTimeout=0;
|
|
}
|
|
|
|
// Set the timer if needed
|
|
if (timeoutSeconds !== undefined && timeoutSeconds > 0) {
|
|
_displayMsgTimer = Date.now();
|
|
_displayMsgTimeout = timeoutSeconds;
|
|
}
|
|
|
|
document.getElementById("message").innerHTML = message;
|
|
}
|
|
/*********************************************************************
|
|
*
|
|
* SCHEDULER FUNCTIONS
|
|
*
|
|
*********************************************************************/
|
|
|
|
// NSF change this import to dynamic config in future.
|
|
//import("./cronstrue.min.js");
|
|
|
|
var CS_ROW_INDEX = 2;
|
|
var V_OFF = 0;
|
|
var V_ON = 1;
|
|
var V_SETPOINT = 3;
|
|
var V_PERCENT = 4;
|
|
var V_RPM = 5;
|
|
var V_GPM = 6;
|
|
|
|
function showScheduler(caller){
|
|
|
|
if (typeof _enable_schedules === "undefined" || _enable_schedules != false)
|
|
{
|
|
if ( parseInt(getComputedStyle(document.querySelector('.scheduler_pane')).width) > Math.max(document.documentElement.clientWidth, window.innerWidth) ) {
|
|
//alert("Sorry, Scheduler won't fit on screen\nPlease use a different device");
|
|
displayMessage("Scheduler won't fit on screen", 3);
|
|
return;
|
|
}
|
|
import("./cronstrue.min.js");
|
|
caller.setAttribute('type', 'scheduler');
|
|
showTileOptions(true, caller.id);
|
|
}
|
|
}
|
|
|
|
function showSimulator(caller){
|
|
caller.setAttribute('type', 'simulator');
|
|
showTileOptions(true, caller.id);
|
|
}
|
|
|
|
function startSimulator() {
|
|
console.log("Starting ifram sim init");
|
|
document.getElementById('onetouch_iframe').display = 'block';
|
|
}
|
|
|
|
// NSF CHANGE TO USING WS FOR THIS REQUEST
|
|
/*
|
|
function cs_loadJSON(path, success, error) {
|
|
var xhr = new XMLHttpRequest();
|
|
xhr.onreadystatechange = function () {
|
|
if (xhr.readyState === 4) {
|
|
if (xhr.status === 200) {
|
|
success(JSON.parse(xhr.responseText));
|
|
}
|
|
else {
|
|
error(xhr);
|
|
}
|
|
}
|
|
};
|
|
xhr.open('GET', path, true);
|
|
xhr.send();
|
|
}*/
|
|
|
|
function device2english(device, name) {
|
|
for (let i = 0, obj; i < _scheduler_devices_json.length, obj = _scheduler_devices_json[i]; i++) {
|
|
if (device == obj.id) {
|
|
if (name == true) {
|
|
return obj.name;
|
|
} else {
|
|
switch (obj.type) {
|
|
case "setpoint_thermo":
|
|
case "setpoint_freeze":
|
|
return "temperature";
|
|
break;
|
|
case "setpoint_swg":
|
|
return "percent";
|
|
break;
|
|
case "switch":
|
|
if (obj.type_ext == "switch_vsp") {
|
|
if (obj.Pump_Type == "vfPump" && _show_vsp_gpm == true) {
|
|
return "GPM";
|
|
} else {
|
|
return "RPM";
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function cs_crontext(caller){
|
|
|
|
for (let cell of caller.parentNode.parentNode.cells) {
|
|
switch (cell.firstChild.id) {
|
|
case "min":
|
|
min = cell.firstChild.value;
|
|
break;
|
|
case "hour":
|
|
hour = cell.firstChild.value;
|
|
break;
|
|
case "daym":
|
|
daym = cell.firstChild.value;
|
|
break;
|
|
case "month":
|
|
month = cell.firstChild.value;
|
|
break;
|
|
case "dayw":
|
|
dayw = cell.firstChild.value;
|
|
break;
|
|
case "device":
|
|
device = cell.firstChild.value;
|
|
break;
|
|
case "command":
|
|
command = cell.firstChild.value;
|
|
break;
|
|
case "value":
|
|
value = cell.firstChild.value;
|
|
break;
|
|
}
|
|
}
|
|
var extra = "";
|
|
|
|
if (command >= 2) {
|
|
//command=cs_getExtraCommand(device);
|
|
extra = " set "+device2english(device, true)+" "+device2english(device, false)+" to "+value
|
|
} else {
|
|
extra = " turn "+device2english(device, true)+" "+((value ==1) ? 'on' : 'off')
|
|
}
|
|
|
|
var cron = min + " " + hour + " " + daym + " " + month + " " + dayw
|
|
try {
|
|
document.getElementById("crontext").innerHTML = "<span class='cs_crontext'> " + cronstrue.toString(cron) + "<font size='-1'>" + extra + "</font> </span>";
|
|
} catch (error) {}
|
|
|
|
var html = ""
|
|
|
|
switch (caller.id) {
|
|
case "min":
|
|
html = html + "<tr><td class='cs_helpleft'>0-59</td><td class='cs_helpright'>allowed values</td></tr>";
|
|
break;
|
|
case "hour":
|
|
html = html + "<tr><td class='cs_helpleft'>0-23</td><td class='cs_helpright'>allowed values</td></tr>";
|
|
break;
|
|
case "daym":
|
|
html = html + "<tr><td class='cs_helpleft'>1-31</td><td class='cs_helpright'>allowed values</td></tr>";
|
|
break;
|
|
case "month":
|
|
html = html + "<tr><td class='cs_helpleft'>1-12</td><td class='cs_helpright'>allowed values</td></tr>" +
|
|
"<tr><td class='cs_helpleft'>JAN-DEC</td><td class='cs_helpright'>alternative single values</td></tr>";
|
|
break;
|
|
case "dayw":
|
|
html = html + "<tr><td class='cs_helpleft'>0-6</td><td class='cs_helpright'>allowed values</td></tr>" +
|
|
"<tr><td class='cs_helpleft'>SAT-SUN</td><td class='cs_helpright'>alternative single values</td></tr>";
|
|
break;
|
|
}
|
|
|
|
if (html != "") {
|
|
html = "<table align='center'>" +
|
|
html +
|
|
"<tr><td class='cs_helpleft'>*</td><td class='cs_helpright'>any vaue</td></tr>" +
|
|
"<tr><td class='cs_helpleft'>,</td><td class='cs_helpright'>value list seperator</td></tr>" +
|
|
"<tr><td class='cs_helpleft'>-</td><td class='cs_helpright'>range values</td></tr>" +
|
|
"<tr><td class='cs_helpleft'>/</td><td class='cs_helpright'>setp values</td></tr>" +
|
|
"</table>";
|
|
}
|
|
|
|
document.getElementById("cronhelp").innerHTML = html;
|
|
}
|
|
|
|
function cs_clearSchedules() {
|
|
var table = document.getElementById("cronschedules");
|
|
while (table.rows.length > 5) {
|
|
table.deleteRow(CS_ROW_INDEX+1);
|
|
}
|
|
}
|
|
|
|
function cs_addschedule(enabled, min, hour, daym, month, dayw, device, subdev, value) {
|
|
var table = document.getElementById("cronschedules");
|
|
//index = table.rows.length-ROW_INDEX;
|
|
|
|
var option = "";
|
|
var subOption = "";
|
|
//var value_type = "number";
|
|
//console.log("device'"+device+"'");
|
|
if (device === "") {
|
|
option = '<option selected value=""></option>';
|
|
//value_type="hidden";
|
|
}
|
|
|
|
for (let i = 0, obj; i < _scheduler_devices_json.length, obj = _scheduler_devices_json[i]; i++) {
|
|
if (device == obj.id) {
|
|
option = option + '<option selected value="' + obj.id + '">' + obj.name + '</option>';
|
|
subOption = cs_getDeviceOptions(obj, subdev, value)
|
|
} else {
|
|
option = option + '<option value="' + obj.id + '">' + obj.name + '</option>';
|
|
}
|
|
}
|
|
var checked
|
|
if (enabled==1) {checked="checked";}else{ehecked="";}
|
|
var html = '<tr> \
|
|
<td><input type="checkbox" class="cs_inputcell" id="enabled" onkeyup="cs_crontext(this);" onclick="cs_crontext(this);" '+checked+'></td> \
|
|
<td><input type="text" class="cs_inputcell" id="min" value="'+ min + '" onkeyup="cs_crontext(this);" onclick="cs_crontext(this);"></td> \
|
|
<td><input type="text" class="cs_inputcell" id="hour" value="'+ hour + '" onkeyup="cs_crontext(this);" onclick="cs_crontext(this);"></td> \
|
|
<td><input type="text" class="cs_inputcell" id="daym" value="'+ daym + '" onkeyup="cs_crontext(this);" onclick="cs_crontext(this);"></td> \
|
|
<td><input type="text" class="cs_inputcell" id="month" value="'+ month + '" onkeyup="cs_crontext(this);" onclick="cs_crontext(this);"></td> \
|
|
<td><input type="text" class="cs_inputcell" id="dayw" value="'+ dayw + '" onkeyup="cs_crontext(this);" onclick="cs_crontext(this);"></td> \
|
|
<td><select name="device" class="cs_inputcell cs_devicecell" id="device" onclick="cs_crontext(this);" onchange="cs_deviceChange(this);">'+ option + '<select></td> \
|
|
<td><select name="command" class="cs_inputcell cs_commandcell" id="command" onclick="cs_crontext(this);" onchange="cs_commandChange(this);">'+ subOption + '<select></td> \
|
|
<td><input type="text" class="cs_inputcell cs_valuecell" onclick="cs_crontext(this);" id="value" pattern="[0-9]+" value="'+ value + '"></td> \
|
|
<td><input type="button" class="cs_deletebutton sc_button" id="delete" value="X" onclick="cs_deleteschedule(this);"></td> \
|
|
</tr>';
|
|
|
|
//<td><input type="number" class="cs_inputcell cs_valuecell" onclick="cs_crontext(this);" min="0" max="9999" id="value" value="'+value+'"></td>
|
|
|
|
var row = table.insertRow(table.rows.length - CS_ROW_INDEX);
|
|
row.innerHTML = html;
|
|
//console.log("add row "+index)
|
|
|
|
// dummy an onchange event to the value input so they get hidded if needed.
|
|
var element = row.querySelector('#command')
|
|
var event = new Event('change');
|
|
element.dispatchEvent(event);
|
|
}
|
|
|
|
function cs_isSelected(option, val1, val2) {
|
|
var rtn = "";
|
|
if (val1 == "set") {
|
|
if (option == val2) { rtn = "selected" }
|
|
} else {
|
|
if (option == val1) { rtn = "selected" }
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
|
|
|
|
function cs_getDeviceOptions(deviceobj, val1, val2) {
|
|
//setpoint = Temp
|
|
var html = '<option value="' + V_ON + '" ' + cs_isSelected(V_ON, val1, val2) + '>On</option><option value="' + V_OFF + '" ' + cs_isSelected(V_OFF, val1, val2) + '>Off</option>';
|
|
|
|
switch (deviceobj.type) {
|
|
case "switch":
|
|
if (deviceobj.type_ext == "switch_vsp") {
|
|
if (deviceobj.Pump_Type == "vfPump") {
|
|
//html = html + '<option value="' + V_RPM + '" ' + cs_isSelected("RPM", val1, val2) + '>RPM</option><option value="' + V_GPM + '" ' + cs_isSelected("GPM", val1, val2) + '>GPM</option>';
|
|
html = html + '<option value="' + V_GPM + '" ' + cs_isSelected("GPM", val1, val2) + '>GPM</option>';
|
|
} else {
|
|
html = html + '<option value="' + V_RPM + '" ' + cs_isSelected("RPM", val1, val2) + '>RPM</option>';
|
|
}
|
|
}
|
|
break
|
|
case "setpoint_thermo":
|
|
html = html + '<option value="' + V_SETPOINT + '" ' + cs_isSelected("setpoint", val1, val2) + '>Temp</option>'
|
|
break
|
|
case "setpoint_swg":
|
|
html = '<option value="' + V_PERCENT + '">Percent</option>'
|
|
break
|
|
case "setpoint_freeze":
|
|
html = '<option value="' + V_SETPOINT + '">Temp</option>'
|
|
break
|
|
}
|
|
return html;
|
|
|
|
}
|
|
|
|
function cs_deviceChange(caller) {
|
|
|
|
for (let i = 0, obj; i < _scheduler_devices_json.length, obj = _scheduler_devices_json[i]; i++) {
|
|
if (caller.value == obj.id) {
|
|
var element = caller.parentNode.parentNode.querySelector('#command')
|
|
element.innerHTML = cs_getDeviceOptions(obj);
|
|
var event = new Event('change');
|
|
element.dispatchEvent(event);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function cs_commandChange(caller) {
|
|
//console.log("Called "+caller.value);
|
|
value = caller.parentNode.parentNode.querySelector('#value')
|
|
if (caller.value >= 2) {
|
|
value.type = "text";
|
|
} else {
|
|
value.type = "hidden";
|
|
}
|
|
}
|
|
|
|
function cs_deleteschedule(caller) {
|
|
var index = caller.parentNode.parentNode.rowIndex;
|
|
document.getElementById("cronschedules").deleteRow(index);
|
|
}
|
|
|
|
function cs_schedules(json) {
|
|
if (typeof json.schedules === "undefined"){
|
|
return
|
|
}
|
|
for (let i = 0; i < json.schedules.length; i++) {
|
|
let obj = json.schedules[i];
|
|
//console.log("Sched "+obj.url);
|
|
var f = 0;
|
|
var subdev = "";
|
|
var device = "";
|
|
for (var j = 0; j < obj.url.length; j++) {
|
|
if (obj.url[j] == "/") {
|
|
f++;
|
|
} else if (f == 2) {
|
|
device = device + obj.url[j];
|
|
} else if (f == 3) {
|
|
subdev = subdev + obj.url[j];
|
|
}
|
|
}
|
|
// If in release we add device, use obj.id rather than device in below and remove device from above.
|
|
cs_addschedule(obj.enabled, obj.min, obj.hour, obj.daym, obj.month, obj.dayw, device, subdev, obj.value);
|
|
}
|
|
}
|
|
|
|
function cs_getExtraCommand(device, commandID) {
|
|
for (let i = 0, obj; i < _scheduler_devices_json.length, obj = _scheduler_devices_json[i]; i++) {
|
|
if (device == obj.id) {
|
|
switch (obj.type) {
|
|
case "setpoint_thermo":
|
|
case "setpoint_freeze":
|
|
return "/setpoint";
|
|
break;
|
|
case "setpoint_swg":
|
|
return "/percent";
|
|
break;
|
|
case "switch":
|
|
if (obj.type_ext == "switch_vsp") {
|
|
if (commandID == 4) {
|
|
return "/GPM";
|
|
} else {
|
|
return "/RPM";
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function cs_createJSON() {
|
|
|
|
var json = {
|
|
uri: "schedules/set",
|
|
devices: []
|
|
};
|
|
var table = document.getElementById("cronschedules");
|
|
//console.log("ROWS = "+table.rows.length);
|
|
for (var r = CS_ROW_INDEX, row; row < table.rows.length-2, row = table.rows[r]; r++) {
|
|
enabled = Number(row.querySelector('#enabled')?.checked).toString();
|
|
min = row.querySelector('#min')?.value;
|
|
hour = row.querySelector('#hour')?.value;
|
|
daym = row.querySelector('#daym')?.value;
|
|
month = row.querySelector('#month')?.value;
|
|
dayw = row.querySelector('#dayw')?.value;
|
|
device = row.querySelector('#device')?.value;
|
|
command = row.querySelector('#command')?.value;
|
|
value = row.querySelector('#value')?.value;
|
|
if (min && hour && daym && month && dayw && device && command) {
|
|
if (command >= 2) {
|
|
command = cs_getExtraCommand(device, command);
|
|
if ( isNaN(value) ) {
|
|
row.querySelector('#value').classList.add("cs_error");
|
|
document.getElementById("crontext").innerHTML = "<span class='cs_crontext'> <font color='red'>FIX ERROR</font> </span>";
|
|
return false;
|
|
}
|
|
} else {
|
|
value = command;
|
|
command = "";
|
|
}
|
|
json.devices.push({
|
|
"enabled": enabled,
|
|
"min": min,
|
|
"hour": hour,
|
|
"daym": daym,
|
|
"month": month,
|
|
"dayw": dayw,
|
|
"url": "/api/" + device + command + "/set",
|
|
"value": value
|
|
})
|
|
}
|
|
}
|
|
//console.log(JSON.stringify(json));
|
|
set_schedules(json);
|
|
return true;
|
|
}
|
|
|
|
/*********************************************************************
|
|
*
|
|
* LOAD / INIT FUNCTIONS
|
|
*
|
|
*********************************************************************/
|
|
|
|
function update_status(data) {
|
|
//console.log("Received Update Satus");
|
|
_aqualink_data = data;
|
|
var el = document.getElementById("datetime");
|
|
|
|
if (data.time.toString() != "" && data.time.toString() != "xx")
|
|
el.innerHTML = data.time.toLowerCase().replace(" ", " ") + ((_landscape) ? " " : "<br>") + data.date.toLowerCase().replace(" ", " ");
|
|
|
|
if (document.getElementById("name").innerHTML == "AqualinkD") {
|
|
if (data.status != "Ready") {
|
|
//document.getElementById("message").innerHTML = formatSatus(data.status);
|
|
displayMessage(formatSatus(data.status));
|
|
} else {
|
|
//document.getElementById("message").innerHTML = '';
|
|
displayMessage(formatSatus(''));
|
|
}
|
|
}
|
|
|
|
if (data.status.indexOf("ERROR") >= 0)
|
|
document.getElementById("header").classList.add("error");
|
|
|
|
// Hard code value updated as I can't be bothered to update source.
|
|
// should come back and re-do these values.
|
|
// The ID's should ultimatly come from json
|
|
setThermostatTile("Pool_Heater", data.pool_temp, data.pool_htr_set_pnt);
|
|
setThermostatTile("Spa_Heater", data.spa_temp, data.spa_htr_set_pnt);
|
|
setThermostatTile("Freeze_Protect", data.air_temp, data.frz_protect_set_pnt);
|
|
|
|
setTileValue("Temperature/Air", data.air_temp);
|
|
setTileValue("Temperature/Pool", data.pool_temp);
|
|
setTileValue("Temperature/Spa", data.spa_temp);
|
|
|
|
if (typeof(data.swg_percent) !== 'undefined')
|
|
setThermostatTile("SWG", data.swg_percent, data.swg_percent);
|
|
|
|
if (typeof(data.swg_ppm) !== 'undefined')
|
|
setTileValue("SWG/PPM", data.swg_ppm);
|
|
if (typeof(data.swg_fullstatus) !== 'undefined')
|
|
setTileAttribute('SWG', "fullstatus", data.swg_fullstatus);
|
|
|
|
if (typeof(data.chem_ph) !== 'undefined')
|
|
setTileValue("CHEM/pH", data.chem_ph);
|
|
if (typeof(data.chem_orp) !== 'undefined')
|
|
setTileValue("CHEM/ORP", data.chem_orp);
|
|
|
|
/*
|
|
setTileValue("Air", data.air_temp);
|
|
setTileValue("Pool_Water", data.pool_temp);
|
|
setTileValue("Spa_Water", data.spa_temp);*/
|
|
for (var obj in data.leds) {
|
|
setTileOn(obj.toString(), data.leds[obj]);
|
|
|
|
if (obj.toString() == 'SWG/Boost') {
|
|
//console.log("BOOST IS "+data.leds[obj]);
|
|
setTileAttribute('SWG', "Boost", data.leds[obj]);
|
|
//setTileValue
|
|
}
|
|
}
|
|
for (var obj in data.timers) {
|
|
setTileOnText(obj.toString(),"On (timer)");
|
|
}
|
|
for (var obj in data.timer_durations) {
|
|
setTileOnText(obj.toString(),"Timer "+toHoursAndMinutes(data.timer_durations[obj]));
|
|
}
|
|
|
|
|
|
if (data.swg_boost_msg != null ) {
|
|
var tile = document.getElementById('SWG');
|
|
if (tile != null) {
|
|
var sp_value = tile.getAttribute('setpoint');
|
|
if (sp_value == 101)
|
|
document.getElementById('SWG' + '_status').innerHTML = 'Boost '+data.swg_boost_msg;
|
|
}
|
|
}
|
|
|
|
//obj.leds.'SWG/Boost'
|
|
|
|
// NSF Really quick hack to show RPM on filter pump. Need to come back and do this correctly.
|
|
/*
|
|
if ((typeof data.extra["Pump_1"] !== 'undefined') && (typeof data.extra["Pump_1"].RPM !== 'undefined')) {
|
|
console.log(data.extra["Pump_1"].RPM);
|
|
if (document.getElementById('Filter_Pump').getAttribute('status') == 'on') {
|
|
document.getElementById('Filter_Pump_status').innerHTML = 'RPM:'+data.extra["Pump_1"].RPM;
|
|
}
|
|
}*/
|
|
//console.log(data["Pump_1"].RPM);
|
|
|
|
var i = 1;
|
|
while (i < 5) {
|
|
//console.log(data["Pump_"+i].RPM);
|
|
if ((typeof data["Pump_"+i] !== 'undefined') && (typeof data["Pump_"+i].RPM !== 'undefined')) {
|
|
if (data["Pump_"+i].RPM == -3) {
|
|
setTileOnText(data["Pump_"+i].id, 'Pump ERROR');
|
|
} else if (data["Pump_"+i].RPM == -2) {
|
|
setTileOnText(data["Pump_"+i].id, 'Pump Offline');
|
|
} else if (data["Pump_"+i].RPM == -1) {
|
|
setTileOnText(data["Pump_"+i].id, 'Pump Priming');
|
|
} else {
|
|
//setTileOnText(object.id, 'RPM:'+object.Pump_RPM);
|
|
if (data["Pump_"+i].Pump_Type == "vfPump") {
|
|
if (_show_vsp_gpm == true) {
|
|
setTileOnText(data["Pump_"+i].id, 'GPM:'+data["Pump_"+i].GPM);
|
|
setTileOnTextLine2(data["Pump_"+i].id, 'RPM:'+data["Pump_"+i].RPM);
|
|
} else {
|
|
setTileOnText(data["Pump_"+i].id, 'RPM:'+data["Pump_"+i].RPM);
|
|
setTileOnTextLine2(data["Pump_"+i].id, 'GPM:'+data["Pump_"+i].GPM);
|
|
}
|
|
document.getElementById(data["Pump_"+i].id).setAttribute('setpoint', data["Pump_"+i].GPM);
|
|
} else {
|
|
document.getElementById(data["Pump_"+i].id).setAttribute('setpoint', data["Pump_"+i].RPM);
|
|
setTileOnText(data["Pump_"+i].id, 'RPM:'+data["Pump_"+i].RPM);
|
|
if (data["Pump_"+i].GPM > 0) {
|
|
setTileOnTextLine2(data["Pump_"+i].id, 'GPM:'+data["Pump_"+i].GPM);
|
|
} else {
|
|
setTileOnTextLine2(data["Pump_"+i].id, "");
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
if (document.getElementById(data["Pump_"+i].id).getAttribute('status') == 'on')
|
|
document.getElementById(data["Pump_"+i].id + '_status').innerHTML = 'RPM:'+data["Pump_"+i].RPM;
|
|
else
|
|
console.log(data["Pump_"+i].id + ' is off, not displaying RPM ' + data["Pump_"+i].RPM);*/
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
function deviceSort(a, b) {
|
|
var pa;
|
|
var pb;
|
|
try {
|
|
pa = devices.indexOf(a.id);
|
|
pb = devices.indexOf(b.id);
|
|
if (pa > pb)
|
|
return 1;
|
|
else if (pa < pb)
|
|
return -1;
|
|
} catch (e) {}
|
|
return 0;
|
|
}
|
|
|
|
function check_devices(data) {
|
|
_temperature_units = data['temp_units'];
|
|
_scheduler_devices_json = [];
|
|
data['devices'].sort(deviceSort);
|
|
for (var obj in data['devices']) {
|
|
|
|
if ((data['devices'][obj].type == "switch" || data['devices'][obj].type == "switch_vsp" || data['devices'][obj].type.substr(0,8) == "setpoint" ) && data['devices'][obj].name != "NONE") {
|
|
_scheduler_devices_json.push(data['devices'][obj]);
|
|
}
|
|
|
|
if (document.getElementById(data['devices'][obj].id) == null) {
|
|
_displayNames[data['devices'][obj].id.replace("Aux_", "AUX")] = data['devices'][obj].name;
|
|
createTile(data['devices'][obj]);
|
|
} else {
|
|
//console.log("CHECK "+document.getElementById(data['devices'][obj].id).getAttribute('type')+" | against "+data['devices'][obj].type+" | and "+data['devices'][obj].type_ext+" | for "+data['devices'][obj].id);
|
|
//CHECK switch | against setpoint_thermo | and undefined | for Pool_Heater
|
|
|
|
var element_type = document.getElementById(data['devices'][obj].id).getAttribute('type');
|
|
var ext_type;
|
|
if (typeof data['devices'][obj].type_ext !== 'undefined')
|
|
ext_type = data['devices'][obj].type_ext;
|
|
else
|
|
ext_type = element_type; // Just force next if to match.
|
|
|
|
//if ( (element_type != data['devices'][obj].type) &&
|
|
// (typeof data['devices'][obj].type_ext !== 'undefined' && (element_type != data['devices'][obj].type_ext) ) ) {
|
|
if ( (element_type != data['devices'][obj].type) && (ext_type != data['devices'][obj].type_ext) ) {
|
|
console.log("Remove and create "+data['devices'][obj].id);
|
|
console.log("Old type "+element_type+" | new type "+data['devices'][obj].type+" sub "+data['devices'][obj].type_ext);
|
|
var element = document.getElementById(data['devices'][obj].id);
|
|
element.parentNode.removeChild(element);
|
|
createTile(data['devices'][obj]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 */
|
|
var socket_di;
|
|
|
|
function startWebsockets() {
|
|
socket_di = new WebSocket(get_appropriate_ws_url());
|
|
try {
|
|
socket_di.onopen = function() {
|
|
// success!
|
|
get_devices();
|
|
// Set another load 1 minute from now just incase the server hasn't got all the devices yet
|
|
window.setTimeout(get_devices, (60 * 1000));
|
|
// Get Status just incase control panel hasn't connected yet
|
|
get_status();
|
|
}
|
|
socket_di.onmessage = function got_packet(msg) {
|
|
document.getElementById("header").classList.remove("error");
|
|
var data = JSON.parse(msg.data);
|
|
if (data.type == 'status') {
|
|
update_status(data);
|
|
} else if (data.type == 'devices') {
|
|
check_devices(data);
|
|
resetBackgroundSize();
|
|
//window.setTimeout(get_devices, (300 * 1000)); // Check for new dvices ever 5 mins.
|
|
window.setTimeout(get_devices, (60 * 1000)); // Check for new dvices ever 1 mins.
|
|
} else if (data.type == 'schedules') {
|
|
cs_schedules(data);
|
|
}
|
|
}
|
|
socket_di.onclose = function() {
|
|
// something went wrong
|
|
document.getElementById("message").innerHTML = ' Connection error! '
|
|
document.getElementById("header").classList.add("error");
|
|
// Try to reconnect every 5 seconds.
|
|
setTimeout(function() {
|
|
startWebsockets()
|
|
}, 5000);
|
|
}
|
|
} catch (exception) {
|
|
alert('<p>Error' + exception);
|
|
}
|
|
}
|
|
|
|
function get_devices() {
|
|
var msg = {
|
|
uri: "devices"
|
|
};
|
|
socket_di.send(JSON.stringify(msg));
|
|
}
|
|
|
|
function get_status() {
|
|
var msg = {
|
|
uri: "status"
|
|
};
|
|
socket_di.send(JSON.stringify(msg));
|
|
}
|
|
|
|
function get_schedules() {
|
|
var msg = {
|
|
uri: "schedules"
|
|
};
|
|
socket_di.send(JSON.stringify(msg));
|
|
}
|
|
function set_schedules(msg) {
|
|
msg.uri = "schedules/set";
|
|
socket_di.send(JSON.stringify(msg));
|
|
//socket_di.send(msg);
|
|
}
|
|
|
|
function send_command(cmd, value=null) {
|
|
var _cmd = {};
|
|
_cmd.command = cmd;
|
|
_cmd.uri = cmd+"/set";
|
|
if (value != null) {
|
|
_cmd.value = value;
|
|
}
|
|
socket_di.send(JSON.stringify(_cmd));
|
|
|
|
if ( _link_spa_and_heater && cmd == "Spa_Mode" ) {
|
|
var ncmd = {};
|
|
ncmd.command = "Spa_Heater";
|
|
ncmd.uri = "Spa_Heater/set";
|
|
if (value != null) {
|
|
ncmd.value = value;
|
|
}
|
|
socket_di.send(JSON.stringify(ncmd));
|
|
}
|
|
}
|
|
|
|
function send_setpoint(id) {
|
|
var message = {};
|
|
var tile;
|
|
if ((tile = document.getElementById(id)) == null) {
|
|
return;
|
|
}
|
|
var type = tile.getAttribute('type');
|
|
message.parameter = tile.getAttribute('id');
|
|
message.value = tile.getAttribute('setpoint');
|
|
|
|
if (type == "setpoint_swg")
|
|
message.uri = id+"/percent/set";
|
|
else if (type == "switch_vsp")
|
|
message.uri = id+"/RPM/set";
|
|
else
|
|
message.uri = id+"/setpoint/set";
|
|
//console.log("Send value back "+temperature.parameter+" "+temperature.value);
|
|
socket_di.send(JSON.stringify(message));
|
|
}
|
|
|
|
function send_light_mode(value, id, textvalue) {
|
|
console.log("Set light mode to "+value+" id="+id+" text="+textvalue);
|
|
var mode = {};
|
|
//mode.parameter = 'POOL_LIGHT_MODE';
|
|
//mode.parameter = 'LIGHT_MODE';
|
|
mode.value = value;
|
|
mode.button = id;
|
|
mode.uri = id+"/program/set";
|
|
mode.text_value = textvalue;
|
|
socket_di.send(JSON.stringify(mode));
|
|
}
|
|
|
|
function send_switch_timer(id, value) {
|
|
var message = {};
|
|
message.uri = id+"/timer/set";
|
|
message.value = value;
|
|
socket_di.send(JSON.stringify(message));
|
|
}
|
|
|
|
function reset() {
|
|
socket_di.send("reset\n");
|
|
}
|
|
|
|
function showBackground() {
|
|
wrapper = document.getElementById("wrapper");
|
|
if (wrapper.classList.contains("vopaque")) {
|
|
wrapper.classList.remove("vopaque");
|
|
} else {
|
|
wrapper.classList.add("vopaque");
|
|
}
|
|
}
|
|
|
|
function showVersion(source) {
|
|
displayMessage("AqualinkD : " + _aqualink_data.aqualinkd_version + " | AqualinkRS : " + _aqualink_data.version, 5);
|
|
/*
|
|
if ((message = document.getElementById("message")) != null) {
|
|
message.innerHTML = "AqualinkD : " + _aqualink_data.aqualinkd_version + " | AqualinkRS : " + _aqualink_data.version;
|
|
}
|
|
source.innerHTML = "Version(s)";
|
|
setTimeout(function() {
|
|
source.innerHTML = "AqualinkD";
|
|
}, 5000);
|
|
*/
|
|
}
|
|
|
|
function updatePwsitchOptions(source, light_type) {
|
|
if (source.type == 'radio') {
|
|
var modename = _light_program[light_type][source.value-1];
|
|
if (modename.endsWith(" - Show"))
|
|
modename = modename.substr(0, (modename.length - 7));
|
|
document.getElementById('pswitch_option_switch_text_value').innerHTML = modename;
|
|
document.getElementById('pswitch_option_switch').checked = true;
|
|
} else if (source.type == 'checkbox') {
|
|
//console.log(source);
|
|
var x;
|
|
if (document.getElementById('pswitch_option_switch').checked == false) {
|
|
var radio = document.getElementsByName("light_program");
|
|
for (x = 0; x < radio.length; x++) {
|
|
radio[x].checked = false
|
|
}
|
|
document.getElementById('pswitch_option_switch_text_value').innerHTML = 'Off';
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
function updateTimerOptions(source) {
|
|
if (source.type == 'range') {
|
|
if (source.value > 0) {
|
|
document.getElementById('timer_switch').checked = true;
|
|
} else {
|
|
document.getElementById('timer_switch').checked = false;
|
|
}
|
|
} else if (source.type == 'checkbox') {
|
|
if (document.getElementById('timer_switch').checked == false) {
|
|
//timer_slider_range = 0;
|
|
document.getElementById("timer_slider_range").value = 0;
|
|
document.getElementById("timer_slider_text_value").value = 0;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
</script>
|
|
</head>
|
|
|
|
<!--<body onload='showTileOptions(false); test_harness();startWebsockets();'> -->
|
|
|
|
<body onload='init();'>
|
|
<div id='body_wrap' class='body_wrap'>
|
|
<!-- <div id='body_wrap' class='body_wrap' onmousedown='showTileOptions(false);'> -->
|
|
<div id='wrapper' class="wrapper">
|
|
<!--<div id="header" class="head" onclick="showBackground();">-->
|
|
<div id="header" class="head" onclick="event.stopPropagation();showSimulator(this);">
|
|
<table border='0' width='100%' cellpadding='0' cellspacing='0'>
|
|
<tr>
|
|
<td width="70px" align='left' id='td_name'><span class='title' id='name'
|
|
onclick="showVersion(this);event.stopPropagation();">AqualinkD</span>
|
|
</td>
|
|
<td align='center'><span class='title' id='message'></span>
|
|
</td>
|
|
<td width="70px" align='right' id='td_timedate'><span class='timedate' id='datetime'
|
|
onclick="event.stopPropagation();showScheduler(this);">X</class>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div id='thermostat_options' class='options hide'>
|
|
<div id='thermostat_options_pane' class='options_pane' onclick='event.stopPropagation();'>
|
|
<table border='0' cellpadding='10px'>
|
|
<tr class='options_title'>
|
|
<th colspan='2'><span id="option_title"></span>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<td align='right' width='50%'><span class="option_text" id='option_switch_text_value'></span>
|
|
</td>
|
|
<td align='left' width='50%'>
|
|
<label class="option_switch">
|
|
<input type="checkbox" id='option_switch'>
|
|
<span class="option_switch_slide"></span>
|
|
</label>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2' align='center'><span class="option_text" id="option_slider_text_value"></span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2'>
|
|
<div class="slidecontainer">
|
|
<input type="range" class="option_slider" id='option_slider_range'>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td colspan='2' align='center'><span class="option_text" id="th_timer_slider_text_value"></span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2'>
|
|
<div class="slidecontainer">
|
|
<input type="range" class="option_slider" id='th_timer_slider_range'>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td colspan='2' align='center'>
|
|
<input type="button" value="close" id='options_close' class='options_button'>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div id='swg_options' class='options hide'>
|
|
<div id='swg_options_pane' class='options_pane' onclick='event.stopPropagation();'>
|
|
<table border='0' cellpadding='10px'>
|
|
<tr class='options_title'>
|
|
<th colspan='2'><span id="swg_option_title"></span>
|
|
</th>
|
|
</tr>
|
|
<tr id="swg_option_switch_row">
|
|
<td align='right' width='50%'><span class="option_text" id='swg_option_switch_text_value'></span>
|
|
</td>
|
|
<td align='left' width='50%'>
|
|
<label class="option_switch">
|
|
<input type="checkbox" id='swg_option_switch'>
|
|
<span class="option_switch_slide"></span>
|
|
</label>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2' align='center'><span class="option_text" id="swg_option_slider_text_value"></span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2'>
|
|
<div class="slidecontainer">
|
|
<input type="range" class="option_slider" id='swg_option_slider_range'>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2' align='center'>
|
|
<input type="button" value="close" id='swg_options_close' class='options_button'>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div id='pswitch_options' class='options hide'>
|
|
<div id='pswitch_options_pane' class='options_pane' onclick='event.stopPropagation();'>
|
|
<table id='pswitch_table' border='0' cellpadding='10px' width="100%">
|
|
<tr class='options_title'>
|
|
<th colspan='2'><span id="pswitch_option_title"></span>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<td align='right' width='50%'><span class="option_text" id='pswitch_option_switch_text_value'></span>
|
|
</td>
|
|
<td align='left' width='50%'>
|
|
<label class="option_switch">
|
|
<input type="checkbox" id='pswitch_option_switch' onchange='updatePwsitchOptions(this);'>
|
|
<span class="option_switch_slide"></span>
|
|
</label>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td colspan='2' align='center'>
|
|
<select id='pswitch_option_list' class='options_selector'>
|
|
<option value="0">Pool Light Program</option>
|
|
</select>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td colspan='2' align='center'><span class="option_text" id="ps_timer_slider_text_value"></span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2'>
|
|
<div class="slidecontainer">
|
|
<input type="range" class="option_slider" id='ps_timer_slider_range'>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td colspan='2' align='center'>
|
|
<input type="button" value="close" id='pswitch_options_close' class='options_button'>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div id='vspswitch_options' class='options hide'>
|
|
<div id='vspswitch_options_pane' class='options_pane' onclick='event.stopPropagation();'>
|
|
<table border='0' cellpadding='10px'>
|
|
<tr class='options_title'>
|
|
<th colspan='2'><span id="vspswitch_option_title"></span>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<td align='right' width='50%'><span class="option_text" id='vspoption_switch_text_value'></span>
|
|
</td>
|
|
<td align='left' width='50%'>
|
|
<label class="option_switch">
|
|
<input type="checkbox" id='vspoption_switch'>
|
|
<span class="option_switch_slide"></span>
|
|
</label>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2' align='center'><span class="option_text" id="vspoption_slider_text_value"></span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2'>
|
|
<div class="slidecontainer">
|
|
<input type="range" class="option_slider" id='vspoption_slider_range'>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td colspan='2' align='center'><span class="option_text" id="vsp_timer_slider_text_value"></span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2'>
|
|
<div class="slidecontainer">
|
|
<input type="range" class="option_slider" id='vsp_timer_slider_range'>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td colspan='2' align='center'>
|
|
<input type="button" value="close" id='vspswitch_option_close' class='options_button'>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div id='timer_options' class='options hide'>
|
|
<div id='timer_options_pane' class='options_pane' onclick='event.stopPropagation();'>
|
|
<table border='0' cellpadding='10px'>
|
|
<tr class='options_title'>
|
|
<th colspan='2'><span id="timer_option_title"></span>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<td align='right' width='50%'><span class="option_text" id='timer_switch_text_value'></span>
|
|
</td>
|
|
<td align='left' width='50%'>
|
|
<label class="option_switch">
|
|
<input type="checkbox" id='timer_switch'>
|
|
<span class="option_switch_slide"></span>
|
|
</label>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2' align='center'><span class="option_text" id="timer_slider_text_value"></span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2'>
|
|
<div class="slidecontainer">
|
|
<input type="range" class="option_slider" id='timer_slider_range'>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan='2' align='center'>
|
|
<input type="button" value="close" id='timer_options_close' class='options_button'>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="simulator_iframe" class='options hide'>
|
|
<div id="onetouch_iframe" class="simulator_pane" onclick='event.stopPropagation();''>
|
|
<iframe id="simulatoriframe" src="/onetouch_sim.html" class="simiframe"></iframe>
|
|
<input type="button" class="options_button" id="simulator_iframe_close" value="Close">
|
|
</div>
|
|
</div>
|
|
|
|
<div id='scheduler_options' class='options hide'>
|
|
<div id='scheduler_options_pane' class='scheduler_pane' onclick='event.stopPropagation();'>
|
|
<table id="cronschedules" border="0">
|
|
<th colspan='10'><span id="scheduler_options_title"></span></th>
|
|
<tr>
|
|
<td colspan="10" align="center" id="crontext"> </td>
|
|
</tr>
|
|
<tr class="sc_tablehead">
|
|
<td>Enable</td>
|
|
<td>Minute</td>
|
|
<td>Hour</td>
|
|
<td>Day<br><font size="-2">Month</font></td>
|
|
<td>Month</td>
|
|
<td>Day<br><font size="-2">Week</font></td>
|
|
<td>Device</td>
|
|
<td>Cmd</td>
|
|
<td>Value</td>
|
|
<td>Del</td>
|
|
</tr>
|
|
<!-- HTML will be added here -->
|
|
<tr class="sc_tablehead">
|
|
<td colspan="10">
|
|
<input type="button" class="options_button" id="Add" value="Add" onclick="cs_addschedule(1,0,0,'*','*','*','','','');">
|
|
|
|
<input type="button" class="options_button" id="scheduler_options_close" value="Save" onclick="cs_createJSON();">
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" id="cronhelp"></td>
|
|
</tr>
|
|
<table>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</body>
|
|
|
|
</html>
|