ESPAsyncWebServer/examples/SmartSwitch/data/index.htm

626 lines
21 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Smart Switch</title>
<meta name="viewport" content="width=device-width">
<link rel="apple-touch-icon" href="/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="app.css" type="text/css" />
<style>
body {
font-family: arial;
color: #999
}
table {
margin: auto;
max-width: 600px;
}
td {
padding: 1%;
padding-inline: 2%
}
[id^="input-"] {
width: 70%;
text-align: center;
padding: 0px;
box-sizing: border-box;
border: none;
border-bottom: 1px solid #2196f3;
font-size: 22px;
color: #2196f3;
font-family: arial;
}
input[type=button] {
background-color: #2196f3;
border: none;
color: #fff;
padding: 10px 10px;
width: 62px;
text-decoration: none;
margin: 4px 2px;
cursor: pointer;
border-radius: 34px;
font-family: arial;
font-weight: 700;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px
}
.switch input {
opacity: 0;
width: 0;
height: 0
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: #fff;
-webkit-transition: .4s;
transition: .4s
}
input:checked+.slider {
background-color: #2196f3
}
input:focus+.slider {
box-shadow: 0 0 1px #2196f3
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px)
}
.slider.round {
border-radius: 34px
}
.slider.round:before {
border-radius: 50%
}
.clk {
font-size: 52px;
color: #444;
cursor: pointer
}
.clk2 {
font-size: 24px;
color: #444
}
.clear:after,
.clear:before {
content: "";
display: table
}
.clear:after {
clear: both
}
.wrapper {
position: relative;
top: 0px;
right: 0;
bottom: 0px;
left: 0;
margin: auto;
max-width: 500px;
text-align: center;
border: 0px solid #ccc
}
.gauge {
display: block;
float: left
}
#g1, #g2 {
width: 50%
}
.son {
color: green;
font-weight: bold
}
.soff {
color: red;
font-weight: bold
}
.blinking {
animation: blinkingText 1.2s infinite;
-webkit-animation: blinkingText 1.2s infinite;
}
@keyframes blinkingText {
0% {
color: #ec0b0b;
}
49% {
color: #ea7272;
}
60% {
color: transparent;
}
99% {
color: transparent;
}
100% {
color: #ff0404;
}
}
.container {
display: inline-block;
position: relative;
padding-left: 19px;
padding-top: 4px;
margin-top: 8px;
margin-bottom: 8px;
cursor: pointer;
font-size: 14px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
width: 12.5%;
user-select: none
}
.container input {
position: absolute;
opacity: 0;
cursor: pointer
}
.checkmark {
position: absolute;
top: 0;
left: 0;
height: 25px;
width: 25px;
background-color: #eee;
border-radius: 50%
}
.container:hover input ~ .checkmark {
background-color: #ccc
}
.container input:checked ~ .checkmark {
background-color: #2196F3
}
.checkmark:after {
content: "";
position: absolute;
display: none
}
.container input:checked ~ .checkmark:after {
display: block
}
.container .checkmark:after {
top: 6px;
left: 6px;
width: 13px;
height: 13px;
border-radius: 50%;
background: white
}
*:focus {outline:none !important}
</style>
</head>
<body>
<table align="center">
<tr align="center">
<td colspan=3>
<form name="sched">
<label class="container" id="LZ0">Def
<input type="radio" name="radio" onclick="handleClick(this);" value="Z0"><span class="checkmark"></span></label>
<label class="container" id="LZ1">M-F
<input type="radio" name="radio" onclick="handleClick(this);" value="Z1"><span class="checkmark"></span></label>
<label class="container" id="LZ2">Sat
<input type="radio" name="radio" onclick="handleClick(this);" value="Z2"><span class="checkmark"></span></label>
<label class="container" id="LZ3">Sun
<input type="radio" name="radio" onclick="handleClick(this);" value="Z3"><span class="checkmark"></span></label>
</form>
</td>
</tr>
<tr align="center">
<td onmousedown="ent1Click();">
<label for="input-temperature">Temp °C</label>
<input readonly="readonly" id="input-temperature" />
</td>
<td onmousedown="ent2Click();">
<label for="input-popup-start">Time On</label>
<input readonly="readonly" id="input-popup-start" />
</td>
<td onmousedown="ent2Click();">
<label for="input-popup-stop">Time Off</label>
<input readonly="readonly" id="input-popup-stop" />
</td>
</tr>
<tr align="center">
<td>
<input type="button" id="W" value="Temp" onclick="button2Click(this);" />
</td>
<td>
<label class="switch">
<input id="cbStyle" type="checkbox" onclick="checkboxClick(this);"><span class="slider round"></span></label>
</td>
<td>
<input type="button" id="T" value="Timer" onclick="buttonClick(this);" />
</td>
</tr>
<tr align="center">
<td>
<div id="reconnect">
<input type="button" id="N" value="WSoff" onclick="statusWs();" />
</div>
</td>
<td><span id="sid"></span><div id="free-ram"></div><div id="erase-wifi"></div><div id="hw-reset"></div><div id="get-time"></div></td>
<td>
<div id="ebut">
<input type="button" id="E" value="WEdit" onclick="buttonEClick();" />
</div>
</td>
</tr>
<tr align="center">
<td>
<input type="button" id="X" value="xWiFi" onclick="loadDoc('erase-wifi', 1);"/>
</td>
<td>
<input type="button" id="H" value="Heap" onclick="loadDoc('free-ram', 0);" />
</td>
<td>
<input type="button" id="R" value="HWrst" onclick="loadDoc('hw-reset', 1);"/>
</td>
</tr>
</table>
<div class="wrapper clear">
<div id="g1" class="gauge"></div>
<div id="g2" class="gauge"></div>
<div id="C" class="clk" onclick="getBtime();"></div>
<div id="C2" class="clk2"></div>
<input type="button" id="O" value="Logout" onclick="buttonOClick();" />
</div>
<script src="app.min.js"></script>
<script type="text/javascript">
const MYCORS = '192.168.1.12';
var g1, g2;
var Analog0 = new Array();
var auto = true;
const successNotification = window.createNotification({
positionClass: 'nfc-bottom-right',
theme: 'info',
showDuration: 3000
});
const warningNotification = window.createNotification({
positionClass: 'nfc-bottom-right',
theme: 'warning',
showDuration: 6000
});
document.addEventListener("DOMContentLoaded", function(event) {
console.log("DOM fully loaded and parsed");
document.getElementById("R").style.backgroundColor = "red";
document.getElementById("X").style.backgroundColor = "red";
g1 = new JustGage({
id: "g1",
value: -5.5,
min: -40,
max: 50,
decimals: 1,
labelFontColor: "#444",
valueFontColor: "#444",
title: "Temperature",
titlePosition: "below",
label: "°C",
relativeGaugeSize: true,
pointer: true,
customSectors: [{
color: "#328da8",
lo: -40,
hi: 0
}, {
color: "#32a852",
lo: 0,
hi: 35
}, {
color: "#ff4d4d",
lo: 35,
hi: 50
}],
formatNumber: true
});
g2 = new JustGage({
id: "g2",
value: 40.8,
min: 0,
max: 100,
decimals: 1,
labelFontColor: "#444",
valueFontColor: "#444",
title: "Humidity",
titlePosition: "below",
label: "%",
relativeGaugeSize: true,
pointer: true,
customSectors: [{
color: "#ffc926",
lo: 0,
hi: 45
}, {
color: "#32a852",
lo: 45,
hi: 55
}, {
color: "#328da8",
lo: 55,
hi: 100
}],
formatNumber: true
});
});
var servurl = document.location.host;
if (servurl.length < 5) servurl = MYCORS;
var connection = new WebSocket('ws://' + servurl + '/ws', ['arduino']);
connection.onopen = function() {
//connection.send('get_something');
document.getElementById("sid").className = "son";
document.getElementById('sid').innerHTML = "Smart Switch";
console.log("connection opened");
};
connection.onclose = function() {
document.getElementById("sid").className = "blinking";
document.getElementById('sid').innerHTML = "Detached";
document.getElementById("N").value = "WSon";
console.log("connection closed");
};
connection.onerror = function(error) {
document.getElementById("sid").className = "soff";
document.getElementById('sid').innerHTML = "Detached";
document.getElementById("N").value = "WSon";
console.log('WebSocket Error ', error);
};
connection.onmessage = function(evt) {
// handle websocket message. update attributes or values of elements that match the name on incoming message
console.log("msg rec", evt.data);
var msgArray = evt.data.split(","); // split message by delimiter into a string array
console.log("msgArray", msgArray[0]);
console.log("msgArray", msgArray[1]);
console.log("msgArray", msgArray[2]);
console.log("msgArray", msgArray[3]);
console.log("msgArray", msgArray[4]);
var indicator = msgArray[1]; // the first element in the message array is the ID of the object to update
console.log("indiactor", indicator);
var a = document.getElementById('cbStyle');
if (indicator) // if an object by the name of the message exists, update its value or its attributes
{
switch (msgArray[1]) {
case "Arduino":
console.log("Got Temp / Humidity");
g1.refresh(msgArray[2], null);
g2.refresh(msgArray[3], null);
if (msgArray[4] == "1") document.getElementById("T").style.backgroundColor = "#32a852";
else document.getElementById("T").style.backgroundColor = "#2196f3";
var delta = (parseFloat(document.getElementById('input-temperature').value).toFixed(1) - parseFloat(msgArray[2]).toFixed(1));
if (delta > 0.5) document.getElementById("W").style.backgroundColor = "red";
else if (delta < -0.5) document.getElementById("W").style.backgroundColor = "#2196f3";
break;
case "Clock":
var dn = parseInt(msgArray[3]);
var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
var dayName = days[dn] || '*'; // 0...6
var shedtype = 0;
if (dn == 0) shedtype = 3;
else if (dn == 6) shedtype = 2;
else if ((dn > 0) && (dn < 6)) shedtype = 1;
document.getElementById('C').innerHTML = msgArray[2];
document.getElementById('C2').innerHTML = dayName;
if (auto) document.getElementById('LZ' + shedtype).classList.add('son');
else document.getElementById('LZ' + shedtype).classList.remove('son');
break;
case "Setting":
document.getElementById('input-popup-start').value = msgArray[2];
document.getElementById('input-popup-stop').value = msgArray[3];
document.getElementById('input-temperature').value = parseFloat(msgArray[4]).toFixed(1);
document.getElementById('input-popup-start').className = "";
document.getElementById('input-popup-stop').className = "";
document.getElementById('input-temperature').className = "";
tpick.attach("input-popup-start");
tpick.attach("input-popup-stop");
fpick.attach("input-temperature");
warningNotification({
message: 'Client UPD'
});
break;
case "ledon":
a.checked = true;
break;
case "ledoff":
a.checked = false;
break;
case "remoff":
successNotification({
message: 'Client quit'
});
break;
case "OTA":
warningNotification({
message: 'OTA begin'
});
statusWs();
break;
case "sched":
document.sched.radio[msgArray[2]].checked = true;
break;
default:
// unrecognized message type. do nothing
break;
} // switch
} // if (indicator)
}; // connection.onmessage
function buttonClick(e) {
if (connection.readyState === WebSocket.OPEN) {
connection.send(e.id + document.getElementById("input-popup-start").value + "|" + document.getElementById("input-popup-stop").value + "|");
successNotification({
message: 'Timer REQ'
});
}
}
function button2Click(e) {
if (connection.readyState === WebSocket.OPEN) {
connection.send(e.id + parseFloat(document.getElementById("input-temperature").value).toFixed(1) + "|");
successNotification({
message: 'Temp. REQ'
});
}
}
function buttonEClick() {
var murl = '/edit';
if (document.location.host.length < 5) murl = 'http://' + MYCORS + '/edit'; //CORS
successNotification({message: 'Editor'});
window.open(murl, '_blank');
}
function buttonOClick() {
var murl = "";
// If base auth
//murl = document.location.href.replace("http://", "http://" + new Date().getTime() + "@");
// If cookie auth
murl += 'login/';
if (document.location.host.length < 5) murl = 'http://' + MYCORS + '/login/'; //CORS
warningNotification({ message: 'Logout'});
window.open(murl, '_self');
}
function checkboxClick(e) {
if (connection.readyState === WebSocket.OPEN) {
if (e.checked) connection.send('L1');
else connection.send('L0');
}
}
function ent1Click() {
document.getElementById("input-temperature").className = "blinking";
}
function ent2Click() {
document.getElementById("input-popup-stop").className = "blinking";
document.getElementById("input-popup-start").className = "blinking";
}
function handleClick(e) {
if (e.value == 'Z0' ) auto = true;
else auto = false;
document.getElementById('L' + e.value).classList.remove('son');
if (connection.readyState === WebSocket.OPEN) connection.send(e.value + "|");
}
// XMLHttpRequest /non WebSocket/ command. same as command' div' id to get response to
function loadDoc(cmd, r, param) {
var par = param || '';
var murl = '/' + cmd + par;
if (document.location.host.length < 5) murl = 'http://' + MYCORS + '/' + cmd + par; //CORS
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById(cmd).innerHTML = this.responseText;
}
};
xhttp.open("GET", murl, true);
xhttp.send();
successNotification({
message: 'Cmd: ' + cmd
});
if (r) { //restart?
connection.close();
document.getElementById("N").value = "WSon";
}
};
function getBtime() {
loadDoc('get-time', 0, '?btime=' + Math.round(new Date().getTime()/1000));
document.getElementById('C').innerHTML ='';
document.getElementById('C2').innerHTML ='';
window.location.reload();
}
function statusWs() {
if (connection.readyState === WebSocket.OPEN) {
connection.close();
document.getElementById("N").value = "WSon";
warningNotification({ message: 'WS Closed'});
} else {
window.location.reload();
}
};
</script>
</body>
</html>