1.9.0 web - new implementation

This commit is contained in:
Paul
2019-08-02 09:26:13 +02:00
parent 89818b23bd
commit fc52f05453
41 changed files with 7206 additions and 931 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
src/websrc/3rdparty/css/sidebar.css vendored Normal file
View File

@@ -0,0 +1 @@
html {position: relative;overflow: scroll;overflow-x: hidden;min-height: 100% }::-webkit-scrollbar {width: 0px;background: transparent;}::-webkit-scrollbar-thumb {background: #e8e8e8;}body {background: #f1f3f6;margin-bottom: 60px }p {font-size: 1.1em;font-weight: 300;line-height: 1.7em;color: #999 }a, a:focus, a:hover {color: inherit;text-decoration: none;transition: all .3s }.navbar {padding: 15px 10px;background: #fff;border: none;border-radius: 0;margin-bottom: 40px;box-shadow: 1px 1px 3px rgba(0, 0, 0, .1) }#dismiss, #sidebar {background: #337ab7 }#content.navbar-btn {box-shadow: none;outline: 0;border: none }.line {width: 100%;height: 1px;border-bottom: 1px dashed #ddd;margin: 40px 0 }#sidebar {width: 250px;position: fixed;top: 0;left: -250px;height: 100vh;z-index: 999;color: #fff;transition: all .3s;overflow-y: auto;box-shadow: 3px 3px 3px rgba(0, 0, 0, .2) }@media screen and (min-width:768px) {#sidebar {left: 0 }.footer {margin-left: 250px }#ajaxcontent {margin-left: 250px }#dismiss, .navbar-btn {display: none }}#sidebar.active {left: 0 }#dismiss {width: 35px;height: 35px;line-height: 35px;text-align: center;position: absolute;top: 10px;right: 10px;cursor: pointer;-webkit-transition: all .3s;-o-transition: all .3s;transition: all .3s }#dismiss:hover {background: #fff;color: #337ab7 }.overlay {position: fixed;width: 100vw;height: 100vh;background: rgba(0, 0, 0, .7);z-index: 998;display: none }#sidebar .sidebar-header {padding: 20px;background: #337ab7 }#sidebar ul.components {padding: 20px 0;border-bottom: 1px solid #47748b }#content, ul.CTAs {padding: 20px }#sidebar ul p {color: #fff;padding: 10px }#sidebar ul li a {padding: 10px;font-size: 1.1em;display: block }#sidebar ul li a:hover {color: #337ab7;background: #fff }#sidebar ul li.active>a, a[aria-expanded=true] {color: #fff;background: #2e6da4 }a[data-toggle=collapse] {position: relative }a[aria-expanded=false]::before, a[aria-expanded=true]::before {content: '\e259';display: block;position: absolute;right: 20px;font-family: 'Glyphicons Halflings';font-size: .6em }#sidebar ul ul a, ul.CTAs a {font-size: .9em }a[aria-expanded=true]::before {content: '\e260' }#sidebar ul ul a {padding-left: 30px;background: #2e6da4 }ul.CTAs a {text-align: center;display: block;border-radius: 5px;margin-bottom: 5px }a.download {background: #fff;color: #337ab7 }#sidebar a.article, a.article:hover {background: #2e6da4;color: #fff }#content {width: 100%;min-height: 100vh;transition: all .3s;position: absolute;top: 0;right: 0 }.footer {position: fixed;bottom: 0;width: 100%;height: 45px;background-color: #f1f3f6 }i {margin-right: 1em }

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

280
src/websrc/index.html Normal file
View File

@@ -0,0 +1,280 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAYFBMVEX///8zMzM1NTU0NDQ2Njby8vJ4eHhBQUGSkpJdXV36+vqbm5tpaWlPT0/Ly8uGhoZxcXHAwMBVVVVJSUm3t7fu7u6mpqY8PDzo6OiPj4/U1NR+fn5ra2tGRkbb29vExMQQm/MfAAAA4klEQVQ4jd1SbXaDMAwD2/kAElpKIRTa7v63nGPY9gjhAKt+OZGeItspik9D3Vqt9eU+nPCtC0CMsh/rHN8EwjICga5Thicof4Dk1ME/CA8EYkOPNF9FYu5dhVGJYU4MSozOzVSrzkcF2b3AxktopJ4Ni6Had6L5BfDbAC58QKMOAnLbYTwR/LrajEBcQye1unEg9HvBHWMw33I5aOli2Xcx9NKGWUZ7WyfWJZOKwWQN68Tpme6rvm6rEtDrXaSY3J+C+q8Dz+Ft4E0hvwLPOcMzZlsZY/zSZf/LmkQxTtl/jG/cCAezKUvMMwAAAABJRU5ErkJggg=="
rel="icon" type="image/x-icon" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title id="customname"></title>
<!-- Bootstrap core CSS -->
<link href="css/required.css" rel="stylesheet">
</head>
<body>
<div class="wrapper">
<!-- Sidebar Holder -->
<nav id="sidebar">
<div id="dismiss">
<i class="glyphicon glyphicon-arrow-left"></i>
</div>
<div class="sidebar-header">
<h1 id="customname2" class="text-center"></h1>
<h6 id="mainver" class="text-center"></h6>
</div>
<ul class="list-unstyled components">
<li class="active">
<a href="#" id="custom_status"><i class="glyphicon glyphicon-home"></i>Dashboard</a>
</li>
<li>
<a href="#" id="status"><i class="glyphicon glyphicon-equalizer"></i>System Status</a>
</li>
<li>
<a href="#homeSubmenu" data-toggle="collapse" aria-expanded="false"><i
class="glyphicon glyphicon-cog"></i>Settings</a>
<ul class="collapse list-unstyled" id="homeSubmenu">
<li>
<a href="#" id="network"><i class="glyphicon glyphicon-signal"></i>Wireless Network</a>
</li>
<li>
<a href="#" id="general"><i class="glyphicon glyphicon-list-alt"></i>General Settings</a>
</li>
<li>
<a href="#" id="mqtt"><i class="glyphicon glyphicon-link"></i>MQTT Settings</a>
</li>
<li>
<a href="#" id="ntp"><i class="glyphicon glyphicon-hourglass"></i>NTP (Time) Settings</a>
</li>
<li>
<a href="#" id="custom"><i class="glyphicon glyphicon-wrench"></i>Custom Settings</a>
</li>
</ul>
</li>
<li>
<a href="#" id="eventlog"><i class="glyphicon glyphicon-transfer"></i>Event Log</a>
</li>
<li>
<a href="#" id="backup"><i class="glyphicon glyphicon-floppy-disk"></i>Backup & Restore</a>
</li>
<li>
<a href="#" id="reset"><i class="glyphicon glyphicon-repeat"></i>Factory Reset</a>
</li>
<li>
<a href="#" id="restart"><i class="glyphicon glyphicon-refresh"></i>Restart System</a>
</li>
<li>
<a data-toggle="modal" href="#update"><i class="glyphicon glyphicon-open"></i>Check for Updates</a>
</li>
</ul>
<ul class="list-unstyled CTAs">
<li>
<a id="helpurl" href="https://github.com/proddy" class="download">Help</a>
</li>
<li>
<a href="#" class="article" onclick="logout();">Logout</a>
</li>
</ul>
</nav>
<!-- Page Content Holder -->
<div id="content">
<button type="button" id="sidebarCollapse" class="btn btn-info navbar-btn">
<i class="glyphicon glyphicon-menu-hamburger"></i>
<span>Menu</span>
</button>
<div id="ajaxcontent">
</div>
<div id="revcommit" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Please review your system changes</h4>
</div>
<div class="modal-body">
<pre id="jsonholder"></pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" onclick="commit();" class="btn btn-success" data-dismiss="modal">Save
& Restart</button>
</div>
</div>
</div>
</div>
<div id="custom_revcommit" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Please review your custom changes</h4>
</div>
<div class="modal-body">
<pre id="jsonholder2"></pre>
Note: some settings my require a <b>Restart System</b> first to take effect.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" onclick="custom_commit();" class="btn btn-success"
data-dismiss="modal">Save
</button>
</div>
</div>
</div>
</div>
<div id="destroy" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Factory Reset</h4>
</div>
<div class="alert alert-warning">
<h5><b>Warning!</b> This action <strong>cannot</strong> be undone. This will permanently
delete <strong>all
the settings and logs.</strong> Please make sure you've made a backup first.</h5>
</div>
<div class="modal-body">
<h5>Please type in the hostname of the device to confirm.</h5>
<div style="clear:both;">
<br>
</div>
<p>
<input type="text" class="form-control input-block" id="compare"
oninput="compareDestroy()">
</p>
</div>
<div class="modal-footer">
<button id="destroybtn" type="button" disabled="" onclick="destroy();"
class="btn btn-block btn-danger">I understand, reset all my settings</button>
</div>
</div>
</div>
</div>
<div id="reboot" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Restart System</h4>
</div>
<div class="alert alert-warning">
<h5><b>Are you sure you want to restart the system?</b></h5>
</div>
<div class="modal-footer">
<button id="restartbtn" type="button" onclick="restart();"
class="btn btn-block btn-danger">Restart</button>
</div>
</div>
</div>
</div>
<div id="signin" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Please log in</h4>
</div>
<div class="row">
<br>
<div class="col-md-8 col-md-offset-2">
<div class="login-panel panel panel-default">
<div class="panel-body">
<form role="form" onsubmit="login(); return false">
<fieldset>
<div class="form-group">
<input id="password" class="form-control" placeholder="Password"
name="password" type="password" value="" required=""
title="Please enter your password">
</div>
<button type="submit"
class="btn btn-success btn-md pull-right">Login</button>
</fieldset>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="update" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Update Firmware</h4>
</div>
<div class="alert alert-warning">
<strong>Warning!</strong> Please make sure you've made a backup first
</div>
<div class="modal-body">
<div>
<h4>Latest Stable Release</h4>
<div id="onlineupdate">
<h5 id=releasehead></h5>
<div style="clear:both;">
<br>
</div>
<pre id="releasebody">Getting update information from GitHub...</pre>
<div class="pull-right">
<a class="pull-right" id="downloadupdate">
<button type="button" class="btn btn-primary">Download</button>
</a>
</div>
</div>
</div>
<div style="clear:both;">
<br>
</div>
<div>
<h4>Current Version:</h4>
<h5 id="versionhead"></h5>
<div class="form-group">
<input id="binform" onchange="allowUpload();" type="file" name="update"
accept=".bin">
</div>
<div class="pull-right">
<button onclick="upload();" class="btn btn-primary" id="upbtn"
disabled="">Update</button>
</div>
</div>
</div>
<div style="clear:both;">
<br>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
</div>
<footer class="footer">
<div id="commit" class="container">
<h6 class="text-muted">(running on <a href="https://github.com/proddy/MyESP">MyESP</a>)</h6>
</div>
</footer>
<div class="overlay"></div>
<script src="js/required.js"></script>
<script src="js/myesp.js"></script>
<script>start();</script>
</body>
</html>

484
src/websrc/myesp.htm Normal file
View File

@@ -0,0 +1,484 @@
<div id="backupcontent">
<br>
<br>
<div class="row">
<div class="col-sm-6">
<legend>Backup</legend>
<h6 class="text-muted">Please make sure that you have made a backup on regular basis.</h6>
<div>
<button class="btn btn-link btn-sm" onclick="backupset();">Backup System Settings</button>
<a id="downloadSet" style="display:none"></a>
<button class="btn btn-link btn-sm" onclick="backupCustomSet();">Backup Custom Settings</button>
<a id="downloadCustomSet" style="display:none"></a>
</div>
<br>
<div>
<legend>Restore</legend>
<h6 class="text-muted">Restore system and custom settings.</h6>
<label for="restoreSet" class="btn btn-link btn-sm">Restore System Settings</label>
<input id="restoreSet" type="file" accept="text/json" onchange="restoreSet();" style="display:none;">
<label for="restoreCustomSet" class="btn btn-link btn-sm">Restore Custom Settings</label>
<input id="restoreCustomSet" type="file" accept="text/json" onchange="restoreCustomSet();"
style="display:none;">
</div>
<br>
<div>
<legend>Restart</legend>
<h6 class="text-muted">Click to restart your device without saving changes.</h6>
<label for="restart" class="btn btn-link btn-sm">Restart Device</label>
<button id="restart" class="btn btn-link btn-sm" onclick="restartESP();" style="display:none;"></button>
</div>
<br>
<div id="restoremodal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Please wait while data is restoring...</h4>
</div>
<div class="modal-body">
<div id="pbar" class="progress">
<div id="dynamic" class="progress-bar progress-bar-primary progress-bar-striped active">
Restoring...</div>
</div>
</div>
<div class="modal-footer">
<button type="button" id="restoreclose" style="display:none;" class="btn btn-default"
data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</div>
<br>
<br>
</div>
<div id="progresscontent">
<br>
<br>
<div class="container">
<div class="row">
<br>
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Please wait about 10 seconds while the system restarts...</h3>
</div>
<div class="panel-body">
<div class="progress">
<div id="updateprog" class="progress-bar progress-bar-striped active" role="progressbar"
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%">0%
</div>
</div>
</div>
<div class="panel-footer text-center" id="reconnect" style="display:none;"></div>
</div>
</div>
</div>
</div>
</div>
<div id="generalcontent">
<br>
<br>
<legend>General Settings</legend>
<br>
<div class="row form-group">
<label class="col-xs-3">Admin Password<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="Log On password"></i></label>
<span class="col-xs-9 col-md-5">
<input class="form-control input-sm" placeholder="Administrator Password" id="adminpwd" type="password">
</span>
<br>
</div>
<div class="row form-group">
<label class="col-xs-3">Host Name<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="Hostname. When Bonjour is installed on your computer you can access via http://hostname.local"></i></label>
<span class="col-xs-9 col-md-5">
<input class="form-control input-sm" placeholder="Hostname" id="hostname" type="text">
</span>
<br>
</div>
<div class="row form-group">
<label class="col-xs-3">Serial<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="Please choose if you want to enable Serial output for debugging"></i></label>
<div class="col-xs-9">
<form>
<label class="radio-inline">
<input type="radio" value="1" name="serialenabled">Enabled</label>
<label class="radio-inline">
<input type="radio" value="0" name="serialenabled" checked>Disabled</label>
</form>
</div>
<br>
<br>
<div class="col-xs-9 col-md-8">
<button onclick="savegeneral()" class="btn btn-primary btn-sm pull-right">Save</button>
</div>
</div>
<div style="clear:both;">
<br>
<br>
</div>
</div>
<br>
<br>
</div>
<div id="eventcontent">
<br>
<br>
<div class="text-center" id="loading-img">
<h5>Please wait while fetching data...<span id="loadpages"></span></h5>
<br>
</div>
<div>
<legend>Event Log</legend>
<div class="panel panel-default">
<div>
<table id="eventtable" class="table" data-paging="true" data-filtering="true" data-sorting="true"
data-editing="false" data-state="true"></table>
</div>
</div>
<button onclick="clearevent()" class="btn btn-primary btn-sm">Clear Log</button>
<div style="clear:both;">
<br>
<br>
</div>
</div>
</div>
<div id="mqttcontent">
<br>
<br>
<legend>MQTT Settings</legend>
<br>
<div class="row form-group">
<label class="col-xs-3">MQTT<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="Please choose if you want to enable MQTT"></i></label>
<div class="col-xs-9">
<form>
<label class="radio-inline">
<input type="radio" value="1" name="mqttenabled">Enabled</label>
<label class="radio-inline">
<input type="radio" value="0" name="mqttenabled" checked>Disabled</label>
</form>
</div>
</div>
<div class="row form-group">
<label class="col-xs-3">IP<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign" aria-hidden="true"
data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="MQTT server IP Address"></i></label>
<span class="col-xs-9">
<input class="form-control input-sm" placeholder="MQTT IP" style="display:inline;max-width:185px"
id="mqttip" type="text">
</span>
<br>
</div>
<div class="row form-group">
<label class="col-xs-3">Port<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="MQTT server port"></i></label>
<span class="col-xs-9">
<input class="form-control input-sm" placeholder="MQTT Port" value="" style="display:inline;max-width:185px"
id="mqttport" type="text">
</span>
<br>
</div>
<div class="row form-group">
<label class="col-xs-3">Username<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="MQTT username"></i></label>
<span class="col-xs-9">
<input class="form-control input-sm" placeholder="" value="" style="display:inline;max-width:185px"
id="mqttuser" type="text">
</span>
<br>
</div>
<div class="row form-group">
<label class="col-xs-3">Password<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="MQTT server password if any"></i></label>
<span class="col-xs-9">
<input class="form-control input-sm" placeholder="" value="" style="display:inline;max-width:185px"
id="mqttpwd" type="password">
</span>
<br>
</div>
<div class="row form-group">
<label class="col-xs-3">Base<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="MQTT base prefix (optional)"></i></label>
<span class="col-xs-9">
<input class="form-control input-sm" placeholder="MQTT base" value="" style="display:inline;max-width:185px"
id="mqttbase" type="text">
</span>
</div>
<div class="row form-group">
<label class="col-xs-3">Heartbeat<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="Please choose if you want to enable the MQTT heartbeat"></i></label>
<div class="col-xs-9">
<form>
<label class="radio-inline">
<input type="radio" value="1" name="mqttheartbeat">Enabled</label>
<label class="radio-inline">
<input type="radio" value="0" name="mqttheartbeat" checked>Disabled</label>
</form>
</div>
</div>
<br>
<div class="col-xs-9 col-md-8">
<button onclick="savemqtt()" class="btn btn-primary btn-sm pull-right">Save</button>
</div>
</div>
<div id="networkcontent">
<br>
<br>
<legend>Wi-Fi Settings</legend>
<h6 class="text-muted">Type your Wi-Fi Network's SSID or Scan for nerby Wireless Networks to join.</h6>
<br>
<div class="row form-group">
<label class="col-xs-3">Wi-Fi Mode<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="You can run your ESP in AP Mode or Client Mode. In client mode you will need to connect to an existing Wi-Fi network, in AP Mode ESP creates a Wi-Fi network itself."></i></label>
<div class="col-xs-9">
<form>
<label class="radio-inline">
<input type="radio" value="1" name="wmode" id="wmodeap" onclick="handleAP();" checked>Access Point
</label>
<label class="radio-inline">
<input type="radio" value="0" name="wmode" id="wmodesta" onclick="handleSTA();">Client</label>
</form>
</div>
</div>
<div class="row form-group" style="display:none" id="hidessid">
<label class="col-xs-3">SSID<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="Wi-Fi Network's Name"></i></label>
<span class="col-xs-7 col-md-5">
<input class="form-control input-sm" id="inputtohide" type="text" name="ap_ssid">
<select class="form-control input-sm" style="display:none;" id="ssid" onchange="listBSSID();"></select>
</span>
<span class="col-xs-2">
<button id="scanb" type="button" class="btn btn-primary btn-xs" style="display:none;"
onclick="scanWifi()">Scan</button>
</span>
</div>
<div class="row form-group" style="display:none" id="hidepasswd">
<label class="col-xs-3">Password<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="Wi-Fi Password"></i></label>
<span class="col-xs-9 col-md-5">
<input id="wifipass" class="form-control input-sm" name="ap_passwd" type="password">
</span>
</div>
<br>
<div class="col-xs-9 col-md-8">
<button onclick="savenetwork()" class="btn btn-primary btn-sm pull-right">Save</button>
</div>
</div>
<div id="ntpcontent">
<br>
<br>
<legend>Time Settings</legend>
<h6 class="text-muted">Daylight saving times are taken into account</h6>
<br>
<div class="row form-group">
<label class="col-xs-3">Device Time</label>
<span id="utc" class="col-xs-9 col-md-5">
</span>
</div>
<div class="row form-group">
<label class="col-xs-3">Browser Time</label>
<span id="rtc" class="col-xs-9 col-md-5">
</span>
</div>
<div class="row form-group">
<div class="col-xs-3">
<button onclick="syncBrowserTime()" class="btn btn-link btn-sm">Sync Browser Time to Device</button><i
style="margin-left: 10px;" class="glyphicon glyphicon-info-sign" aria-hidden="true"
data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="Use your browser time. Useful when the system does not have an internet connection."></i>
</div>
</div>
<div class="row form-group">
<label class="col-xs-3">NTP<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="Enable NTP - requires an internet connection"></i></label>
<div class="col-xs-9">
<form>
<label class="radio-inline">
<input type="radio" value="1" name="ntpenabled">Enabled</label>
<label class="radio-inline">
<input type="radio" value="0" name="ntpenabled" checked>Disabled</label>
</form>
</div>
</div>
<div class="row form-group">
<label class="col-xs-3">NTP Server<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="The server for the time sync. Choose nearest server for better accuracy, see https://www.ntppool.org for servers nearby."></i></label>
<span class="col-xs-9 col-md-5">
<input class="form-control input-sm" placeholder="eg. pool.ntp.org" value="pool.ntp.org" id="ntpserver"
type="text">
</span>
<br>
</div>
<div class="row form-group">
<label class="col-xs-3">Intervals<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
data-content="Intervals between Time Sync in Minutes"></i></label>
<span class="col-xs-9 col-md-5">
<input class="form-control input-sm" placeholder="in Minutes" value="30" id="intervals" type="text">
</span>
<br>
</div>
<div class="row form-group">
<label class="col-xs-3">Time Zone</label>
<span class="col-xs-9 col-md-5">
<select class="form-control input-sm" name="DropDownTimezone" id="DropDownTimezone">
<option value="-12">(GMT -12:00) Eniwetok, Kwajalein</option>
<option value="-11">(GMT -11:00) Midway Island, Samoa</option>
<option value="-10">(GMT -10:00) Hawaii</option>
<option value="-9">(GMT -9:00) Alaska</option>
<option value="-8">(GMT -8:00) Pacific Time (US &amp; Canada)</option>
<option value="-7">(GMT -7:00) Mountain Time (US &amp; Canada)</option>
<option value="-6">(GMT -6:00) Central Time (US &amp; Canada), Mexico City</option>
<option value="-5">(GMT -5:00) Eastern Time (US &amp; Canada), Bogota, Lima</option>
<option value="-4">(GMT -4:00) Atlantic Time (Canada), Caracas, La Paz</option>
<option value="-3.5">(GMT -3:30) Newfoundland</option>
<option value="-3">(GMT -3:00) Brazil, Buenos Aires, Georgetown</option>
<option value="-2">(GMT -2:00) Mid-Atlantic</option>
<option value="-1">(GMT -1:00 hour) Azores, Cape Verde Islands</option>
<option value="0">(GMT) Western Europe Time, London, Lisbon, Casablanca</option>
<option selected="selected" value="1">(GMT +1:00 hour) Brussels, Copenhagen, Madrid, Paris</option>
<option value="2">(GMT +2:00) Kaliningrad, South Africa</option>
<option value="3">(GMT +3:00) Baghdad, Riyadh, Moscow, St. Petersburg</option>
<option value="3.5">(GMT +3:30) Tehran</option>
<option value="4">(GMT +4:00) Abu Dhabi, Muscat, Baku, Tbilisi</option>
<option value="4.5">(GMT +4:30) Kabul</option>
<option value="5">(GMT +5:00) Ekaterinburg, Islamabad, Karachi, Tashkent</option>
<option value="5.5">(GMT +5:30) Bombay, Calcutta, Madras, New Delhi</option>
<option value="5.75">(GMT +5:45) Kathmandu</option>
<option value="6">(GMT +6:00) Almaty, Dhaka, Colombo</option>
<option value="7">(GMT +7:00) Bangkok, Hanoi, Jakarta</option>
<option value="8">(GMT +8:00) Beijing, Perth, Singapore, Hong Kong</option>
<option value="9">(GMT +9:00) Tokyo, Seoul, Osaka, Sapporo, Yakutsk</option>
<option value="9.5">(GMT +9:30) Adelaide, Darwin</option>
<option value="10">(GMT +10:00) Eastern Australia, Guam, Vladivostok</option>
<option value="11">(GMT +11:00) Magadan, Solomon Islands, New Caledonia</option>
<option value="12">(GMT +12:00) Auckland, Wellington, Fiji, Kamchatka</option>
</select>
</span>
</div>
<br>
<div class="col-xs-9 col-md-8">
<button onclick="saventp()" class="btn btn-primary btn-sm pull-right">Save</button>
</div>
</div>
<div id="statuscontent">
<br><br>
<legend>System Status</legend>
<br>
<div class="row text-center">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default table-responsive">
<table class="table table-hover table-striped table-condensed">
<caption>System</caption>
<tr>
<th>Uptime</th>
<td id="uptime"></td>
</tr>
<tr>
<th>System Load</th>
<td id="systemload"> %</td>
</tr>
</table>
</div>
<div class="panel panel-default table-responsive">
<table class="table table-hover table-striped table-condensed">
<caption>Storage</caption>
<tr>
<th>Free Heap</th>
<td>
<div class="progress" style="margin-bottom: 0 !important;">
<div id="heap" class="progress-bar progress-bar-primary" role="progressbar">
Progress
</div>
</div>
</td>
</tr>
<tr>
<th>Free Flash</th>
<td>
<div class='progress' style="margin-bottom: 0 !important;">
<div id="flash" class="progress-bar progress-bar-primary" role="progressbar">
Progress
</div>
</div>
</td>
</tr>
<tr>
<th>Free SPIFFS</th>
<td>
<div class='progress' style="margin-bottom: 0 !important;">
<div id="spiffs" class="progress-bar progress-bar-primary" role="progressbar">
Progress
</div>
</div>
</td>
</tr>
</table>
</div>
<div class="panel panel-default table-responsive">
<table class="table table-hover table-striped table-condensed">
<caption>Wireless Network</caption>
<tr>
<th>SSID</th>
<td id="ssidstat"></td>
</tr>
<tr>
<th>IP Address</th>
<td id="ip"></td>
</tr>
<tr>
<th>MAC Address</th>
<td id="mac"></td>
</tr>
<tr>
<th>Signal Strength</th>
<td id="signalstr"> %</td>
</tr>
</table>
</div>
<div class="panel panel-default table-responsive">
<table class="table">
<caption>MQTT</caption>
<tr>
<td>
<div id="mqttconnected"></div>
</td>
<td>
<div id="mqttheartbeat"></div>
</td>
</tr>
</table>
</div>
</div>
<br>
<br>
</div>
</div>

934
src/websrc/myesp.js Normal file
View File

@@ -0,0 +1,934 @@
var version = "";
var websock = null;
var wsUri = "ws://" + window.location.host + "/ws";
var utcSeconds;
var timezone;
var data = [];
var ajaxobj;
var config = {
"command": "configfile",
"network": {
"ssid": "",
"wmode": 1,
"password": ""
},
"general": {
"hostname": "",
"serial": false,
"password": "admin"
},
"mqtt": {
"enabled": false,
"ip": "",
"port": 1883,
"base": "",
"user": "",
"password": "",
"heartbeat": false
},
"ntp": {
"server": "pool.ntp.org",
"interval": 30,
"timezone": 1,
"enabled": true
}
};
var page = 1;
var haspages;
var file = {};
var backupstarted = false;
var updateurl = "";
var myespcontent;
function browserTime() {
var d = new Date(0);
var c = new Date();
var timestamp = Math.floor((c.getTime() / 1000) + ((c.getTimezoneOffset() * 60) * -1));
d.setUTCSeconds(timestamp);
document.getElementById("rtc").innerHTML = d.toUTCString().slice(0, -3);
}
function deviceTime() {
var t = new Date(0); // The 0 there is the key, which sets the date to the epoch,
var devTime = Math.floor(utcSeconds + ((t.getTimezoneOffset() * 60) * -1));
t.setUTCSeconds(devTime);
document.getElementById("utc").innerHTML = t.toUTCString().slice(0, -3);
}
function syncBrowserTime() {
var d = new Date();
var timestamp = Math.floor((d.getTime() / 1000));
var datatosend = {};
datatosend.command = "settime";
datatosend.epoch = timestamp;
websock.send(JSON.stringify(datatosend));
$("#ntp").click();
}
function listntp() {
websock.send("{\"command\":\"gettime\"}");
document.getElementById("ntpserver").value = config.ntp.server;
document.getElementById("intervals").value = config.ntp.interval;
document.getElementById("DropDownTimezone").value = config.ntp.timezone;
if (config.ntp.enabled) {
$("input[name=\"ntpenabled\"][value=\"1\"]").prop("checked", true);
}
browserTime();
deviceTime();
}
function revcommit() {
document.getElementById("jsonholder").innerText = JSON.stringify(config, null, 2);
$("#revcommit").modal("show");
}
function uncommited() {
$("#commit").fadeOut(200, function () {
$(this).css("background", "gold").fadeIn(1000);
});
document.getElementById("commit").innerHTML = "<h6>Settings have changed. Click here to review and save.</h6>";
$("#commit").click(function () {
revcommit();
return false;
});
}
function custom_uncommited() {
document.getElementById("jsonholder2").innerText = JSON.stringify(custom_config.settings, null, 2);
$("#custom_revcommit").modal("show");
}
function saventp() {
config.ntp.server = document.getElementById("ntpserver").value;
config.ntp.interval = parseInt(document.getElementById("intervals").value);
config.ntp.timezone = parseInt(document.getElementById("DropDownTimezone").value);
config.ntp.enabled = false;
if (parseInt($("input[name=\"ntpenabled\"]:checked").val()) === 1) {
config.ntp.enabled = true;
}
uncommited();
}
function savegeneral() {
var a = document.getElementById("adminpwd").value;
if (a === null || a === "") {
alert("Administrator password cannot be empty");
return;
}
config.general.password = a;
config.general.hostname = document.getElementById("hostname").value;
config.general.serial = false;
if (parseInt($("input[name=\"serialenabled\"]:checked").val()) === 1) {
config.general.serial = true;
}
uncommited();
}
function savemqtt() {
config.mqtt.enabled = false;
if (parseInt($("input[name=\"mqttenabled\"]:checked").val()) === 1) {
config.mqtt.enabled = true;
}
config.mqtt.heartbeat = false;
if (parseInt($("input[name=\"mqttheartbeat\"]:checked").val()) === 1) {
config.mqtt.heartbeat = true;
}
config.mqtt.ip = document.getElementById("mqttip").value;
config.mqtt.port = parseInt(document.getElementById("mqttport").value);
config.mqtt.base = document.getElementById("mqttbase").value;
config.mqtt.user = document.getElementById("mqttuser").value;
config.mqtt.password = document.getElementById("mqttpwd").value;
uncommited();
}
function savenetwork() {
var wmode = 0;
if (document.getElementById("inputtohide").style.display === "none") {
var b = document.getElementById("ssid");
config.network.ssid = b.options[b.selectedIndex].value;
} else {
config.network.ssid = document.getElementById("inputtohide").value;
}
if (document.getElementById("wmodeap").checked) {
wmode = 1;
}
config.network.wmode = wmode;
config.network.password = document.getElementById("wifipass").value;
uncommited();
}
var formData = new FormData();
function inProgress(callback) {
$("body").load("myesp.html #progresscontent", function (responseTxt, statusTxt, xhr) {
if (statusTxt === "success") {
$(".progress").css("height", "40");
$(".progress").css("font-size", "xx-large");
var i = 0;
var prg = setInterval(function () {
$(".progress-bar").css("width", i + "%").attr("aria-valuenow", i).html(i + "%");
i++;
if (i === 101) {
clearInterval(prg);
var a = document.createElement("a");
a.href = "http://" + config.general.hostname + ".local";
a.innerText = "Try to reconnect ESP";
document.getElementById("reconnect").appendChild(a);
document.getElementById("reconnect").style.display = "block";
document.getElementById("updateprog").className = "progress-bar progress-bar-success";
document.getElementById("updateprog").innerHTML = "Completed";
}
}, 500);
switch (callback) {
case "upload":
$.ajax({
url: "/update",
type: "POST",
data: formData,
processData: false,
contentType: false
});
break;
case "commit":
websock.send(JSON.stringify(config));
break;
case "destroy":
websock.send("{\"command\":\"destroy\"}");
break;
case "restart":
websock.send("{\"command\":\"restart\"}");
break;
default:
break;
}
}
}).hide().fadeIn();
}
function commit() {
inProgress("commit");
}
function handleSTA() {
document.getElementById("scanb").style.display = "block";
document.getElementById("hidessid").style.display = "block";
document.getElementById("hidepasswd").style.display = "block";
}
function handleAP() {
document.getElementById("ssid").style.display = "none";
document.getElementById("scanb").style.display = "none";
document.getElementById("hidessid").style.display = "none";
document.getElementById("hidepasswd").style.display = "none";
document.getElementById("inputtohide").style.display = "block";
}
function listnetwork() {
document.getElementById("inputtohide").value = config.network.ssid;
document.getElementById("wifipass").value = config.network.password;
if (config.network.wmode === 1) {
document.getElementById("wmodeap").checked = true;
handleAP();
} else {
document.getElementById("wmodesta").checked = true;
handleSTA();
}
}
function listgeneral() {
document.getElementById("adminpwd").value = config.general.password;
document.getElementById("hostname").value = config.general.hostname;
if (config.general.serial) {
$("input[name=\"serialenabled\"][value=\"1\"]").prop("checked", true);
}
}
function listmqtt() {
if (config.mqtt.enabled) {
$("input[name=\"mqttenabled\"][value=\"1\"]").prop("checked", true);
}
if (config.mqtt.heartbeat) {
$("input[name=\"mqttheartbeat\"][value=\"1\"]").prop("checked", true);
}
document.getElementById("mqttip").value = config.mqtt.ip;
document.getElementById("mqttport").value = config.mqtt.port;
document.getElementById("mqttbase").value = config.mqtt.base;
document.getElementById("mqttuser").value = config.mqtt.user;
document.getElementById("mqttpwd").value = config.mqtt.password;
}
function listBSSID() {
var select = document.getElementById("ssid");
document.getElementById("wifibssid").value = select.options[select.selectedIndex].bssidvalue;
}
function listSSID(obj) {
var select = document.getElementById("ssid");
for (var i = 0; i < obj.list.length; i++) {
var x = parseInt(obj.list[i].rssi);
var percentage = Math.min(Math.max(2 * (x + 100), 0), 100);
var opt = document.createElement("option");
opt.value = obj.list[i].ssid;
opt.bssidvalue = obj.list[i].bssid;
opt.innerHTML = "BSSID: " + obj.list[i].bssid + ", Signal Strength: %" + percentage + ", Network: " + obj.list[i].ssid;
select.appendChild(opt);
}
document.getElementById("scanb").innerHTML = "Re-Scan";
listBSSID();
}
function scanWifi() {
websock.send("{\"command\":\"scan\"}");
document.getElementById("scanb").innerHTML = "...";
document.getElementById("inputtohide").style.display = "none";
var node = document.getElementById("ssid");
node.style.display = "inline";
while (node.hasChildNodes()) {
node.removeChild(node.lastChild);
}
}
function getEvents() {
websock.send("{\"command\":\"geteventlog\", \"page\":" + page + "}");
}
function isVisible(e) {
return !!(e.offsetWidth || e.offsetHeight || e.getClientRects().length);
}
function getnextpage(mode) {
if (!backupstarted) {
document.getElementById("loadpages").innerHTML = "Loading " + page + "/" + haspages;
}
if (page < haspages) {
page = page + 1;
var commandtosend = {};
commandtosend.command = mode;
commandtosend.page = page;
websock.send(JSON.stringify(commandtosend));
}
}
function builddata(obj) {
data = data.concat(obj.list);
}
function colorStatusbar(ref) {
var percentage = ref.style.width.slice(0, -1);
if (percentage > 50) { ref.className = "progress-bar progress-bar-success"; } else if (percentage > 25) { ref.className = "progress-bar progress-bar-warning"; } else { ref.class = "progress-bar progress-bar-danger"; }
}
function listStats() {
document.getElementById("uptime").innerHTML = ajaxobj.uptime;
document.getElementById("heap").innerHTML = ajaxobj.heap + " KB";
document.getElementById("heap").style.width = (ajaxobj.heap * 100) / 41 + "%";
colorStatusbar(document.getElementById("heap"));
document.getElementById("flash").innerHTML = ajaxobj.availsize + " KB";
document.getElementById("flash").style.width = (ajaxobj.availsize * 100) / (ajaxobj.availsize + ajaxobj.sketchsize) + "%";
colorStatusbar(document.getElementById("flash"));
document.getElementById("spiffs").innerHTML = ajaxobj.availspiffs + " KB";
document.getElementById("spiffs").style.width = (ajaxobj.availspiffs * 100) / ajaxobj.spiffssize + "%";
colorStatusbar(document.getElementById("spiffs"));
document.getElementById("ssidstat").innerHTML = ajaxobj.ssid;
document.getElementById("ip").innerHTML = ajaxobj.ip;
document.getElementById("mac").innerHTML = ajaxobj.mac;
document.getElementById("signalstr").innerHTML = ajaxobj.signalstr + " %";
document.getElementById("systemload").innerHTML = ajaxobj.systemload + " %";
if (ajaxobj.mqttconnected) {
document.getElementById("mqttconnected").innerHTML = "MQTT is connected";
document.getElementById("mqttconnected").className = "label label-success";
} else {
document.getElementById("mqttconnected").innerHTML = "MQTT is not connected";
document.getElementById("mqttconnected").className = "label label-danger";
}
if (ajaxobj.mqttheartbeat) {
document.getElementById("mqttheartbeat").innerHTML = "MQTT hearbeat is enabled";
document.getElementById("mqttheartbeat").className = "label label-success";
} else {
document.getElementById("mqttheartbeat").innerHTML = "MQTT hearbeat is disabled";
document.getElementById("mqttheartbeat").className = "label label-primary";
}
}
function getContent(contentname) {
$("#dismiss").click();
$(".overlay").fadeOut().promise().done(function () {
var content = $(contentname).html();
$("#ajaxcontent").html(content).promise().done(function () {
switch (contentname) {
case "#statuscontent":
listStats();
break;
case "#backupcontent":
break;
case "#ntpcontent":
listntp();
break;
case "#mqttcontent":
listmqtt();
break;
case "#generalcontent":
listgeneral();
break;
case "#networkcontent":
listnetwork();
break;
case "#eventcontent":
page = 1;
data = [];
getEvents();
break;
case "#customcontent":
listcustom();
break;
case "#custom_statuscontent":
var version = "version " + ajaxobj.version;
$("#mainver").text(version);
$("#customname").text(ajaxobj.customname);
var customname2 = " " + ajaxobj.customname;
$("#customname2").text(customname2);
var elem = document.getElementById("helpurl");
elem.setAttribute("href", ajaxobj.helpurl);
updateurl = ajaxobj.updateurl;
listCustomStats();
break;
default:
break;
}
$("[data-toggle=\"popover\"]").popover({
container: "body"
});
$(this).hide().fadeIn();
});
});
}
function backupset() {
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(config, null, 2));
var dlAnchorElem = document.getElementById("downloadSet");
dlAnchorElem.setAttribute("href", dataStr);
dlAnchorElem.setAttribute("download", "system_config.json");
dlAnchorElem.click();
}
function backupCustomSet() {
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(custom_config, null, 2));
var dlAnchorElem = document.getElementById("downloadCustomSet");
dlAnchorElem.setAttribute("href", dataStr);
dlAnchorElem.setAttribute("download", "custom_config.json");
dlAnchorElem.click();
}
function restoreSet() {
var input = document.getElementById("restoreSet");
var reader = new FileReader();
if ("files" in input) {
if (input.files.length === 0) {
alert("You did not select file to restore!");
} else {
reader.onload = function () {
var json;
try {
json = JSON.parse(reader.result);
} catch (e) {
alert("Not a valid backup file!");
return;
}
if (json.command === "configfile") {
var x = confirm("File seems to be valid, do you wish to continue?");
if (x) {
config = json;
uncommited();
}
}
};
reader.readAsText(input.files[0]);
}
}
}
function restoreCustomSet() {
var input = document.getElementById("restoreCustomSet");
var reader = new FileReader();
if ("files" in input) {
if (input.files.length === 0) {
alert("You did not select file to restore!");
} else {
reader.onload = function () {
var json;
try {
json = JSON.parse(reader.result);
} catch (e) {
alert("Not a valid backup file!");
return;
}
if (json.command === "custom_configfile") {
var x = confirm("File seems to be valid, do you wish to continue?");
if (x) {
custom_config = json;
custom_uncommited();
}
}
};
reader.readAsText(input.files[0]);
}
}
}
function twoDigits(value) {
if (value < 10) {
return "0" + value;
}
return value;
}
function initEventTable() {
var newlist = [];
for (var i = 0; i < data.length; i++) {
var dup = JSON.parse(data[i]);
dup.uid = i;
newlist[i] = {};
newlist[i].options = {};
newlist[i].value = {};
newlist[i].value = dup;
var c = dup.type;
switch (c) {
case "WARN":
newlist[i].options.classes = "warning";
break;
case "INFO":
newlist[i].options.classes = "info";
break;
case "ERRO":
newlist[i].options.classes = "danger";
break;
default:
break;
}
}
jQuery(function ($) {
window.FooTable.init("#eventtable", {
columns: [{
"name": "uid",
"title": "ID",
"type": "text",
"sorted": true,
"direction": "DESC"
},
{
"name": "type",
"title": "Event Type",
"type": "text"
},
{
"name": "src",
"title": "Source"
},
{
"name": "desc",
"title": "Description"
},
{
"name": "data",
"title": "Additional Data",
"breakpoints": "xs sm"
},
{
"name": "time",
"title": "Date",
"parser": function (value) {
if (value < 1563300000) {
return "(" + value + ")";
} else {
var comp = new Date();
value = Math.floor(value + ((comp.getTimezoneOffset() * 60) * -1));
var vuepoch = new Date(value * 1000);
var formatted = vuepoch.getUTCFullYear() +
"-" + twoDigits(vuepoch.getUTCMonth() + 1) +
"-" + twoDigits(vuepoch.getUTCDate()) +
" " + twoDigits(vuepoch.getUTCHours()) +
":" + twoDigits(vuepoch.getUTCMinutes()) +
":" + twoDigits(vuepoch.getUTCSeconds());
return formatted;
}
},
"breakpoints": "xs sm"
}
],
rows: newlist
});
});
}
function restartESP() {
inProgress("restart");
}
var nextIsNotJson = false;
function socketMessageListener(evt) {
var obj = JSON.parse(evt.data);
if (obj.hasOwnProperty("command")) {
switch (obj.command) {
case "status":
ajaxobj = obj;
getContent("#statuscontent");
break;
case "custom_settings":
ajaxobj = obj;
break;
case "custom_status":
ajaxobj = obj;
getContent("#custom_statuscontent");
break;
case "eventlist":
haspages = obj.haspages;
if (haspages === 0) {
document.getElementById("loading-img").style.display = "none";
initEventTable();
break;
}
builddata(obj);
break;
case "gettime":
utcSeconds = obj.epoch;
timezone = obj.timezone;
deviceTime();
break;
case "ssidlist":
listSSID(obj);
break;
case "configfile":
config = obj;
break;
case "custom_configfile":
custom_config = obj;
break;
default:
break;
}
}
if (obj.hasOwnProperty("resultof")) {
switch (obj.resultof) {
case "eventlist":
if (page < haspages && obj.result === true) {
getnextpage("geteventlog");
} else if (page === haspages) {
initEventTable();
document.getElementById("loading-img").style.display = "none";
}
break;
default:
break;
}
}
}
function clearevent() {
websock.send("{\"command\":\"clearevent\"}");
$("#eventlog").click();
}
function compareDestroy() {
if (config.general.hostname === document.getElementById("compare").value) {
$("#destroybtn").prop("disabled", false);
} else { $("#destroybtn").prop("disabled", true); }
}
function destroy() {
inProgress("destroy");
}
function restart() {
inProgress("restart");
}
$("#dismiss, .overlay").on("click", function () {
$("#sidebar").removeClass("active");
$(".overlay").fadeOut();
});
$("#sidebarCollapse").on("click", function () {
$("#sidebar").addClass("active");
$(".overlay").fadeIn();
$(".collapse.in").toggleClass("in");
$("a[aria-expanded=true]").attr("aria-expanded", "false");
});
$("#custom_status").click(function () {
websock.send("{\"command\":\"custom_status\"}");
return false;
});
$("#status").click(function () {
websock.send("{\"command\":\"status\"}");
return false;
});
$("#custom").click(function () { getContent("#customcontent"); return false; });
$("#network").on("click", (function () { getContent("#networkcontent"); return false; }));
$("#general").click(function () { getContent("#generalcontent"); return false; });
$("#mqtt").click(function () { getContent("#mqttcontent"); return false; });
$("#ntp").click(function () { getContent("#ntpcontent"); return false; });
$("#backup").click(function () { getContent("#backupcontent"); return false; });
$("#reset").click(function () { $("#destroy").modal("show"); return false; });
$("#restart").click(function () { $("#reboot").modal("show"); return false; });
$("#eventlog").click(function () { getContent("#eventcontent"); return false; });
$(".noimp").on("click", function () {
$("#noimp").modal("show");
});
window.FooTable.MyFiltering = window.FooTable.Filtering.extend({
construct: function (instance) {
this._super(instance);
this.acctypes = ["1", "99", "0"];
this.acctypesstr = ["Always", "Admin", "Disabled"];
this.def = "Access Type";
this.$acctype = null;
},
$create: function () {
this._super();
var self = this,
$formgrp = $("<div/>", {
"class": "form-group"
})
.append($("<label/>", {
"class": "sr-only",
text: "Status"
}))
.prependTo(self.$form);
self.$acctype = $("<select/>", {
"class": "form-control"
})
.on("change", {
self: self
}, self._onStatusDropdownChanged)
.append($("<option/>", {
text: self.def
}))
.appendTo($formgrp);
$.each(self.acctypes, function (i, acctype) {
self.$acctype.append($("<option/>").text(self.acctypesstr[i]).val(self.acctypes[i]));
});
},
_onStatusDropdownChanged: function (e) {
var self = e.data.self,
selected = $(this).val();
if (selected !== self.def) {
self.addFilter("acctype", selected, ["acctype"]);
} else {
self.removeFilter("acctype");
}
self.filter();
},
draw: function () {
this._super();
var acctype = this.find("acctype");
if (acctype instanceof window.FooTable.Filter) {
this.$acctype.val(acctype.query.val());
} else {
this.$acctype.val(this.def);
}
}
});
var xDown = null;
var yDown = null;
function handleTouchStart(evt) {
xDown = evt.touches[0].clientX;
yDown = evt.touches[0].clientY;
}
function handleTouchMove(evt) {
if (!xDown || !yDown) {
return;
}
var xUp = evt.touches[0].clientX;
var yUp = evt.touches[0].clientY;
var xDiff = xDown - xUp;
var yDiff = yDown - yUp;
if (Math.abs(xDiff) > Math.abs(yDiff)) { /*most significant*/
if (xDiff > 0) {
$("#dismiss").click();
} else {
$("#sidebarCollapse").click();
/* right swipe */
}
} else {
if (yDiff > 0) {
/* up swipe */
} else {
/* down swipe */
}
}
/* reset values */
xDown = null;
yDown = null;
}
function logout() {
jQuery.ajax({
type: "GET",
url: "/login",
async: false,
username: "logmeout",
password: "logmeout",
})
.done(function () {
// If we don"t get an error, we actually got an error as we expect an 401!
})
.fail(function () {
// We expect to get an 401 Unauthorized error! In this case we are successfully
// logged out and we redirect the user.
document.location = "index.html";
});
return false;
}
function connectWS() {
if (window.location.protocol === "https:") {
wsUri = "wss://" + window.location.host + "/ws";
} else if (window.location.protocol === "file:") {
wsUri = "ws://" + "localhost" + "/ws";
}
websock = new WebSocket(wsUri);
websock.addEventListener("message", socketMessageListener);
websock.onopen = function (evt) {
websock.send("{\"command\":\"getconf\"}");
websock.send("{\"command\":\"custom_status\"}");
};
}
function upload() {
formData.append("bin", $("#binform")[0].files[0]);
inProgress("upload");
}
function login() {
if (document.getElementById("password").value === "neo") {
$("#signin").modal("hide");
connectWS();
} else {
var username = "admin";
var password = document.getElementById("password").value;
var url = "/login";
var xhr = new XMLHttpRequest();
xhr.open("get", url, true, username, password);
xhr.onload = function (e) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
$("#signin").modal("hide");
connectWS();
} else {
alert("Incorrect password!");
}
}
};
xhr.send(null);
}
}
function getLatestReleaseInfo() {
$.getJSON(updateurl).done(function (release) {
var asset = release.assets[0];
var downloadCount = 0;
for (var i = 0; i < release.assets.length; i++) {
downloadCount += release.assets[i].download_count;
}
var oneHour = 60 * 60 * 1000;
var oneDay = 24 * oneHour;
var dateDiff = new Date() - new Date(release.published_at);
var timeAgo;
if (dateDiff < oneDay) {
timeAgo = (dateDiff / oneHour).toFixed(1) + " hours ago";
} else {
timeAgo = (dateDiff / oneDay).toFixed(1) + " days ago";
}
var releaseInfo = release.name + " was updated " + timeAgo + " and downloaded " + downloadCount.toLocaleString() + " times.";
$("#downloadupdate").attr("href", asset.browser_download_url);
$("#releasehead").text(releaseInfo);
$("#releasebody").text(release.body);
$("#releaseinfo").fadeIn("slow");
$("#versionhead").text(version);
}).error(function () { $("#onlineupdate").html("<h5>Couldn't get release details. Make sure there is an Internet connection.</h5>"); });
}
$("#update").on("shown.bs.modal", function (e) {
getLatestReleaseInfo();
});
function allowUpload() {
$("#upbtn").prop("disabled", false);
}
function start() {
myespcontent = document.createElement("div");
myespcontent.id = "mastercontent";
myespcontent.style.display = "none";
document.body.appendChild(myespcontent);
$("#signin").on("shown.bs.modal", function () {
$("#password").focus().select();
});
$("#mastercontent").load("myesp.html", function (responseTxt, statusTxt, xhr) {
if (statusTxt === "success") {
$("#signin").modal({ backdrop: "static", keyboard: false });
$("[data-toggle=\"popover\"]").popover({
container: "body"
});
}
});
}
function refreshEMS() {
websock.send("{\"command\":\"custom_status\"}");
}
document.addEventListener("touchstart", handleTouchStart, false);
document.addEventListener("touchmove", handleTouchMove, false);