Integrated Ethernet Settings and Setup

This commit is contained in:
Carsten Schmiemann 2021-01-17 00:47:21 +01:00
parent 429e1ce61a
commit e874cff352
20 changed files with 574 additions and 130 deletions

File diff suppressed because one or more lines are too long

View File

@ -100,6 +100,10 @@ void Settings::patch(JsonObject parsedSettings) {
this->setIfPresent(parsedSettings, "enable_automatic_mode_switching", enableAutomaticModeSwitching);
this->setIfPresent(parsedSettings, "led_mode_packet_count", ledModePacketCount);
this->setIfPresent(parsedSettings, "hostname", hostname);
this->setIfPresent(parsedSettings, "ethernet_enable", ethernet_enable);
this->setIfPresent(parsedSettings, "ethernet_static_ip", ethernetStaticIP);
this->setIfPresent(parsedSettings, "ethernet_static_ip_gateway", ethernetStaticIPGateway);
this->setIfPresent(parsedSettings, "ethernet_static_ip_netmask", ethernetStaticIPNetmask);
this->setIfPresent(parsedSettings, "wifi_static_ip", wifiStaticIP);
this->setIfPresent(parsedSettings, "wifi_static_ip_gateway", wifiStaticIPGateway);
this->setIfPresent(parsedSettings, "wifi_static_ip_netmask", wifiStaticIPNetmask);
@ -292,6 +296,10 @@ void Settings::serialize(Print& stream, const bool prettyPrint) {
root["hostname"] = this->hostname;
root["rf24_power_level"] = RF24PowerLevelHelpers::nameFromValue(this->rf24PowerLevel);
root["rf24_listen_channel"] = RF24ChannelHelpers::nameFromValue(rf24ListenChannel);
root["ethernet_enable"] = this->ethernet_enable;
root["ethernet_static_ip"] = this->ethernetStaticIP;
root["ethernet_static_ip_gateway"] = this->ethernetStaticIPGateway;
root["ethernet_static_ip_netmask"] = this->ethernetStaticIPNetmask;
root["wifi_static_ip"] = this->wifiStaticIP;
root["wifi_static_ip_gateway"] = this->wifiStaticIPGateway;
root["wifi_static_ip_netmask"] = this->wifiStaticIPNetmask;

View File

@ -89,6 +89,7 @@ public:
Settings() :
adminUsername(""),
adminPassword(""),
ethernet_enable(false),
// CE and CSN pins from nrf24l01
cePin(4),
csnPin(15),
@ -188,6 +189,10 @@ public:
std::vector<GroupStateField> groupStateFields;
std::vector<std::shared_ptr<GatewayConfig>> gatewayConfigs;
RF24Channel rf24ListenChannel;
bool ethernet_enable;
String ethernetStaticIP;
String ethernetStaticIPNetmask;
String ethernetStaticIPGateway;
String wifiStaticIP;
String wifiStaticIPNetmask;
String wifiStaticIPGateway;

View File

@ -132,7 +132,7 @@ void MiLightHttpServer::handleSystemPost(RequestContext& request) {
#ifdef ESP8266
ESP.eraseConfig();
#elif ESP32
// TODO erase config
WiFi.disconnect();
#endif
delay(100);
ESP.restart();

View File

@ -28,6 +28,8 @@
#include <HomeAssistantDiscoveryClient.h>
#include <TransitionController.h>
#include <ESPId.h>
#include <ETH.h>
#ifdef ESP8266
#include <ESP8266mDNS.h>
@ -47,6 +49,7 @@ WiFiManagerParameter* wifiStaticIPNetmask = NULL;
WiFiManagerParameter* wifiStaticIPGateway = NULL;
static LEDStatus *ledStatus;
static bool eth_connected = false;
Settings settings;
@ -68,6 +71,43 @@ int numUdpServers = 0;
std::vector<std::shared_ptr<MiLightUdpServer>> udpServers;
WiFiUDP udpSeder;
void WiFiEvent(WiFiEvent_t event)
{
switch (event) {
case SYSTEM_EVENT_ETH_START:
Serial.println("ETH Started");
//set eth hostname here
ETH.setHostname("esp32-ethernet");
break;
case SYSTEM_EVENT_ETH_CONNECTED:
Serial.println("ETH Connected");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
Serial.print("ETH MAC: ");
Serial.print(ETH.macAddress());
Serial.print(", IPv4: ");
Serial.print(ETH.localIP());
if (ETH.fullDuplex()) {
Serial.print(", FULL_DUPLEX");
}
Serial.print(", ");
Serial.print(ETH.linkSpeed());
Serial.println("Mbps");
eth_connected = true;
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
Serial.println("ETH Disconnected");
eth_connected = false;
break;
case SYSTEM_EVENT_ETH_STOP:
Serial.println("ETH Stopped");
eth_connected = false;
break;
default:
break;
}
}
/**
* Set up UDP servers (both v5 and v6). Clean up old ones if necessary.
*/
@ -363,7 +403,7 @@ void setup() {
ledStatus->continuous(settings.ledModeWifiConfig);
// start up the wifi manager
if (! MDNS.begin("milight-hub")) {
if (! MDNS.begin("esp32-milight-hub")) {
Serial.println(F("Error setting up MDNS responder"));
}
// tell Wifi manager to call us during the setup. Note that this "setSetupLoopCallback" is an addition
@ -415,6 +455,19 @@ void setup() {
wifiManager.setSTAStaticIPConfig(_ip,_gw,_subnet);
}
if (settings.ethernet_enable == true) {
Serial.println("Ethernet activated. Loading config...");
WiFi.onEvent(WiFiEvent);
IPAddress eth_ip, eth_subnet, eth_gw;
eth_ip.fromString(settings.wifiStaticIP);
eth_subnet.fromString(settings.wifiStaticIPNetmask);
eth_gw.fromString(settings.wifiStaticIPGateway);
ETH.begin();
ETH.config(eth_ip, eth_gw, eth_subnet, eth_gw, eth_gw);
Serial.println(ETH.localIP());
} else {
Serial.println("Ethernet disabled.");
}
wifiManager.setConfigPortalTimeout(180);

6
web/src/css/bootstrap-select.min.css vendored Normal file

File diff suppressed because one or more lines are too long

41
web/src/css/bootstrap-slider.min.css vendored Normal file

File diff suppressed because one or more lines are too long

28
web/src/css/bootstrap-toggle.min.css vendored Normal file
View File

@ -0,0 +1,28 @@
/*! ========================================================================
* Bootstrap Toggle: bootstrap-toggle.css v2.2.0
* http://www.bootstraptoggle.com
* ========================================================================
* Copyright 2014 Min Hur, The New York Times Company
* Licensed under MIT
* ======================================================================== */
.checkbox label .toggle,.checkbox-inline .toggle{margin-left:-20px;margin-right:5px}
.toggle{position:relative;overflow:hidden}
.toggle input[type=checkbox]{display:none}
.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none}
.toggle.off .toggle-group{left:-100%}
.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0}
.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0}
.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px}
.toggle.btn{min-width:59px;min-height:34px}
.toggle-on.btn{padding-right:24px}
.toggle-off.btn{padding-left:24px}
.toggle.btn-lg{min-width:79px;min-height:45px}
.toggle-on.btn-lg{padding-right:31px}
.toggle-off.btn-lg{padding-left:31px}
.toggle-handle.btn-lg{width:40px}
.toggle.btn-sm{min-width:50px;min-height:30px}
.toggle-on.btn-sm{padding-right:20px}
.toggle-off.btn-sm{padding-left:20px}
.toggle.btn-xs{min-width:35px;min-height:22px}
.toggle-on.btn-xs{padding-right:12px}
.toggle-off.btn-xs{padding-left:12px}

6
web/src/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -6,28 +6,28 @@
<title>MiLight Hub</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" title="main"/>
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.0/css/bootstrap-slider.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.12.6/css/selectize.bootstrap3.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.12.4/css/bootstrap-select.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="css/bootstrap.min.css" title="main"/>
<link href="css/bootstrap-toggle.min.css" rel="stylesheet"/>
<link href="css/bootstrap-slider.min.css" rel="stylesheet"/>
<link href="css/selectize.bootstrap3.min.css" rel="stylesheet"/>
<link href="css/bootstrap-select.min.css" rel="stylesheet"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<script src="js/html5shiv.js"></script>
<![endif]-->
<link href="css/style.css" rel="stylesheet" />
<link href="data:image/x-icon;base64,AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAA/38NABD+CwD/jQsA9pUOABRu/wD/HQwA+gPrAP4MbAAZ8f8ACxb9AP4GkwCW/AoADYj+AP59CQD7FAkAC//nAJYK/QAQ/w4Acgv/AP71CwCSDP8A+AkYAP7rBAAN/+0A/xEcAP1rCwAM/okADf+HAI/7CgAL/5sADP95AA0U/wD4/gsADXr+ABAO/gDlC/8A+v0NAA3/EwB4Ef8A8wr7AP0IeAAN7P4Abf8LAAuJ/wCVDv8A+hcGACH+DgBz/wsA+g7/ABT+ZQAMCv0Aagn/AJT/DQD+EPsADP7sAOf/DAD/Dx0A/g2AAB4N/gB0/gwADZz/ABLu/wAM/BYA+wqMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkYAAAAAAAAAAAAAAUsAAA+NwAAGzIAAAAAAAAAIj0AKhAAHh8AAAAAAAoAAAANAAAAABwAAAA/AAAzIAAAAAAAAAAAAAAmAgAAADsjAAAAAAAAAAASLwAAAAAAAAAAAAAAAAAAAAAAABMnNAAAAAAAAAAAAAArMDwVLREAAAAAAAAAAAAADDUdAAAAAAAAAAAAAAAAAAAAAAAAJDEAAAAAAAAAACU4AAAAKDYAAAAAAAAAAAAAFCEAAAcAAAA6AAAAAAEAAAAXAAAAAABACAAWLgAaAwAAAAAAAAALKQAAOQYAAA4EAAAAAAAAAAAAABkPAAAAAAAAAP5/AADmZwAA8k8AALvdAACf+QAAz/MAAP//AAAf+AAAH/gAAP//AADP8wAAn/kAALvdAADyTwAA5mcAAP5/AAA=" rel="icon" type="image/x-icon" />
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="jquery.min.js"></script>
<script src="js/theme-select.js" lang="text/javascript"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.0/bootstrap-slider.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.12.6/js/standalone/selectize.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.12.4/js/bootstrap-select.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/bootstrap-toggle.min.js"></script>
<script src="js/underscore-min.js"></script>
<script src="js/bootstrap-slider.min.js"></script>
<script src="js/selectize.min.js"></script>
<script src="js/bootstrap-select.min.js"></script>
<script src="js/rgb2hsv.js" lang="text/javascript"></script>
<script src="js/script.js" lang="text/javascript"></script>
@ -57,15 +57,15 @@
<ul class="dropdown-menu">
<li><a href="#admin-actions" data-toggle="modal" data-target="#admin-actions-modal">Actions</a></li>
<li role="separator" class="divider"></li>
<li><a href="#check-updates" id="updates-btn" data-toggle="modal" data-target="#updates-modal">Check for Updates</a></li>
<li><a href="#updates" data-toggle="modal" data-target="#update-firmware-modal">Update Firmware</a></li>
<!--<li><a href="#check-updates" id="updates-btn" data-toggle="modal" data-target="#updates-modal">Check for Updates</a></li>
<li><a href="#updates" data-toggle="modal" data-target="#update-firmware-modal">Update Firmware</a></li>-->
<li><a href="#backup" data-toggle="modal" data-target="#backup-settings-modal">Backup</a></li>
</ul>
</li>
<li class="dropdown" id="theme-dropdown">
<a id="theme-label" href="#" class="dropdown-toggle" data-toggle="dropdown">Theme<b class="caret"></b></a>
<ul id="theme-list" class="dropdown-menu">
<li><a href="#" class="change-style-menu-item">Bootstrap (Default)</a></li>
<li><a href="#" class="change-style-menu-item">Simplex</a></li>
</ul>
</li>
</ul>
@ -74,6 +74,8 @@
</nav>
<div class="container" id="content">
<center><h2>ESP32 PoE MiLight Gateway</h2>
port by Carsten Schmiemann, 2021</center>
<div class="row" id="device-id-aliases-row">
<div class="col-sm-3">
<label for="deviceAliases" id="device-id-aliases">
@ -384,114 +386,7 @@
<h4>Traffic sniffed (sent and received)</h4>
<div id="sniffed-traffic"></div>
</div>
</div>
<div id="update-firmware-modal" 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>
<h2 class="modal-title">Update Firmware</h2>
</div>
<div class="modal-body">
<div class="alert alert-warning">
<p>
<b>
Always take a
<a href="/settings" download="settings.json">backup of your settings</a>
before upgrading.
</b>
Sometimes upgrades change flash offsets, which can corrupt the filesystem. If this happens, clear
flash, re-upload the firmware, and restore the backup of your settings.
</p>
</div>
<div class="alert alert-warning">
<p>
Download firmware binaries from the
<a href="https://github.com/sidoh/esp8266_milight_hub/releases">GitHub releases page</a>.
Check for a new version by clicking on the "Check for Updates" button.
</p>
<p>
<b>Make sure the binary you're uploading was compiled for your board!</b>
Firmware with incompatible settings could prevent boots. If this happens,
reflash the board with USB.
</p>
</div>
<form action="/firmware" method="post" enctype="multipart/form-data">
<div class="input-group">
<label class="input-group-btn">
<span class="btn btn-primary">
Browse
<input type="file" name="file" accept=".bin" style="display: none;">
</span>
</label>
<input type="text" class="form-control" readonly="">
<label class="input-group-btn">
<span class="btn btn-success">
Upload Firmware
<input type="submit" style="display: none;">
</span>
</label>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="updates-modal" 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>
<h2 class="modal-title">Update</h2>
</div>
<div class="modal-body">
<div id="version-summary"></div>
<hr />
<h4>Current Version</h4>
<div id="current-version"></div>
<div id="latest-version">
<h4>Latest Version</h4>
<div class="status"></div>
<div id="latest-version-info">
<label>Version</label>
<div class="info-key" data-key="tag_name"></div>
<label>Release Date</label>
<div class="info-key" data-key="published_at"></div>
<label>Release Notes</label>
<pre class="info-key" data-key="body"></pre>
<div>
<a class="info-key" data-prop="href" data-key="html_url">View on GitHub</a>
</div>
<div>
<a class="info-key" id="firmware-link">Download Firmware</a>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
<center>Fork from https://github.com/mrtncls/esp8266_milight_hub/tree/esp32</center>
</div>
<div id="backup-settings-modal" class="modal fade" role="dialog">

9
web/src/js/bootstrap-select.min.js vendored Normal file

File diff suppressed because one or more lines are too long

5
web/src/js/bootstrap-slider.min.js vendored Normal file

File diff suppressed because one or more lines are too long

9
web/src/js/bootstrap-toggle.min.js vendored Normal file
View File

@ -0,0 +1,9 @@
/*! ========================================================================
* Bootstrap Toggle: bootstrap-toggle.js v2.2.0
* http://www.bootstraptoggle.com
* ========================================================================
* Copyright 2014 Min Hur, The New York Times Company
* Licensed under MIT
* ======================================================================== */
+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-lg":"small"===this.options.size?"btn-sm":"mini"===this.options.size?"btn-xs":"",c=a('<label class="btn">').html(this.options.on).addClass(this._onstyle+" "+b),d=a('<label class="btn">').html(this.options.off).addClass(this._offstyle+" "+b+" active"),e=a('<span class="toggle-handle btn btn-default">').addClass(b),f=a('<div class="toggle-group">').append(c,d,e),g=a('<div class="toggle btn" data-toggle="toggle">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(b).addClass(this.options.style);this.$element.wrap(g),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:c,$toggleOff:d,$toggleGroup:f}),this.$toggle.append(f);var h=this.options.width||Math.max(c.outerWidth(),d.outerWidth())+e.outerWidth()/2,i=this.options.height||Math.max(c.outerHeight(),d.outerHeight());c.addClass("toggle-on"),d.addClass("toggle-off"),this.$toggle.css({width:h,height:i}),this.options.height&&(c.css("line-height",c.height()+"px"),d.css("line-height",d.height()+"px")),this.update(!0),this.trigger(!0)},c.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},c.prototype.on=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),void(a||this.trigger()))},c.prototype.off=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),void(a||this.trigger()))},c.prototype.enable=function(){this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},c.prototype.disable=function(){this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},c.prototype.update=function(a){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(a):this.off(a)},c.prototype.trigger=function(b){this.$element.off("change.bs.toggle"),b||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},c.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var d=a.fn.bootstrapToggle;a.fn.bootstrapToggle=b,a.fn.bootstrapToggle.Constructor=c,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=d,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(b){var c=a(this).find("input[type=checkbox]");c.bootstrapToggle("toggle"),b.preventDefault()})}(jQuery);
//# sourceMappingURL=bootstrap-toggle.min.js.map

7
web/src/js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

326
web/src/js/html5shiv.js vendored Normal file
View File

@ -0,0 +1,326 @@
/**
* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
;(function(window, document) {
/*jshint evil:true */
/** version */
var version = '3.7.3';
/** Preset options */
var options = window.html5 || {};
/** Used to skip problem elements */
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
/** Not all elements can be cloned in IE **/
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
/** Detect whether the browser supports default html5 styles */
var supportsHtml5Styles;
/** Name of the expando, to work with multiple documents or to re-shiv one document */
var expando = '_html5shiv';
/** The id for the the documents expando */
var expanID = 0;
/** Cached data for each document */
var expandoData = {};
/** Detect whether the browser supports unknown elements */
var supportsUnknownElements;
(function() {
try {
var a = document.createElement('a');
a.innerHTML = '<xyz></xyz>';
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
supportsHtml5Styles = ('hidden' in a);
supportsUnknownElements = a.childNodes.length == 1 || (function() {
// assign a false positive if unable to shiv
(document.createElement)('a');
var frag = document.createDocumentFragment();
return (
typeof frag.cloneNode == 'undefined' ||
typeof frag.createDocumentFragment == 'undefined' ||
typeof frag.createElement == 'undefined'
);
}());
} catch(e) {
// assign a false positive if detection fails => unable to shiv
supportsHtml5Styles = true;
supportsUnknownElements = true;
}
}());
/*--------------------------------------------------------------------------*/
/**
* Creates a style sheet with the given CSS text and adds it to the document.
* @private
* @param {Document} ownerDocument The document.
* @param {String} cssText The CSS text.
* @returns {StyleSheet} The style element.
*/
function addStyleSheet(ownerDocument, cssText) {
var p = ownerDocument.createElement('p'),
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
p.innerHTML = 'x<style>' + cssText + '</style>';
return parent.insertBefore(p.lastChild, parent.firstChild);
}
/**
* Returns the value of `html5.elements` as an array.
* @private
* @returns {Array} An array of shived element node names.
*/
function getElements() {
var elements = html5.elements;
return typeof elements == 'string' ? elements.split(' ') : elements;
}
/**
* Extends the built-in list of html5 elements
* @memberOf html5
* @param {String|Array} newElements whitespace separated list or array of new element names to shiv
* @param {Document} ownerDocument The context document.
*/
function addElements(newElements, ownerDocument) {
var elements = html5.elements;
if(typeof elements != 'string'){
elements = elements.join(' ');
}
if(typeof newElements != 'string'){
newElements = newElements.join(' ');
}
html5.elements = elements +' '+ newElements;
shivDocument(ownerDocument);
}
/**
* Returns the data associated to the given document
* @private
* @param {Document} ownerDocument The document.
* @returns {Object} An object of data.
*/
function getExpandoData(ownerDocument) {
var data = expandoData[ownerDocument[expando]];
if (!data) {
data = {};
expanID++;
ownerDocument[expando] = expanID;
expandoData[expanID] = data;
}
return data;
}
/**
* returns a shived element for the given nodeName and document
* @memberOf html5
* @param {String} nodeName name of the element
* @param {Document|DocumentFragment} ownerDocument The context document.
* @returns {Object} The shived element.
*/
function createElement(nodeName, ownerDocument, data){
if (!ownerDocument) {
ownerDocument = document;
}
if(supportsUnknownElements){
return ownerDocument.createElement(nodeName);
}
if (!data) {
data = getExpandoData(ownerDocument);
}
var node;
if (data.cache[nodeName]) {
node = data.cache[nodeName].cloneNode();
} else if (saveClones.test(nodeName)) {
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
} else {
node = data.createElem(nodeName);
}
// Avoid adding some elements to fragments in IE < 9 because
// * Attributes like `name` or `type` cannot be set/changed once an element
// is inserted into a document/fragment
// * Link elements with `src` attributes that are inaccessible, as with
// a 403 response, will cause the tab/window to crash
// * Script elements appended to fragments will execute when their `src`
// or `text` property is set
return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
}
/**
* returns a shived DocumentFragment for the given document
* @memberOf html5
* @param {Document} ownerDocument The context document.
* @returns {Object} The shived DocumentFragment.
*/
function createDocumentFragment(ownerDocument, data){
if (!ownerDocument) {
ownerDocument = document;
}
if(supportsUnknownElements){
return ownerDocument.createDocumentFragment();
}
data = data || getExpandoData(ownerDocument);
var clone = data.frag.cloneNode(),
i = 0,
elems = getElements(),
l = elems.length;
for(;i<l;i++){
clone.createElement(elems[i]);
}
return clone;
}
/**
* Shivs the `createElement` and `createDocumentFragment` methods of the document.
* @private
* @param {Document|DocumentFragment} ownerDocument The document.
* @param {Object} data of the document.
*/
function shivMethods(ownerDocument, data) {
if (!data.cache) {
data.cache = {};
data.createElem = ownerDocument.createElement;
data.createFrag = ownerDocument.createDocumentFragment;
data.frag = data.createFrag();
}
ownerDocument.createElement = function(nodeName) {
//abort shiv
if (!html5.shivMethods) {
return data.createElem(nodeName);
}
return createElement(nodeName, ownerDocument, data);
};
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
'var n=f.cloneNode(),c=n.createElement;' +
'h.shivMethods&&(' +
// unroll the `createElement` calls
getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
data.createElem(nodeName);
data.frag.createElement(nodeName);
return 'c("' + nodeName + '")';
}) +
');return n}'
)(html5, data.frag);
}
/*--------------------------------------------------------------------------*/
/**
* Shivs the given document.
* @memberOf html5
* @param {Document} ownerDocument The document to shiv.
* @returns {Document} The shived document.
*/
function shivDocument(ownerDocument) {
if (!ownerDocument) {
ownerDocument = document;
}
var data = getExpandoData(ownerDocument);
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
data.hasCSS = !!addStyleSheet(ownerDocument,
// corrects block display not defined in IE6/7/8/9
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
// adds styling not present in IE6/7/8/9
'mark{background:#FF0;color:#000}' +
// hides non-rendered elements
'template{display:none}'
);
}
if (!supportsUnknownElements) {
shivMethods(ownerDocument, data);
}
return ownerDocument;
}
/*--------------------------------------------------------------------------*/
/**
* The `html5` object is exposed so that more elements can be shived and
* existing shiving can be detected on iframes.
* @type Object
* @example
*
* // options can be changed before the script is included
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
*/
var html5 = {
/**
* An array or space separated string of node names of the elements to shiv.
* @memberOf html5
* @type Array|String
*/
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
/**
* current version of html5shiv
*/
'version': version,
/**
* A flag to indicate that the HTML5 style sheet should be inserted.
* @memberOf html5
* @type Boolean
*/
'shivCSS': (options.shivCSS !== false),
/**
* Is equal to true if a browser supports creating unknown/HTML5 elements
* @memberOf html5
* @type boolean
*/
'supportsUnknownElements': supportsUnknownElements,
/**
* A flag to indicate that the document's `createElement` and `createDocumentFragment`
* methods should be overwritten.
* @memberOf html5
* @type Boolean
*/
'shivMethods': (options.shivMethods !== false),
/**
* A string to describe the type of `html5` object ("default" or "default print").
* @memberOf html5
* @type String
*/
'type': 'default',
// shivs the document according to the specified `html5` object options
'shivDocument': shivDocument,
//creates a shived element
createElement: createElement,
//creates a shived documentFragment
createDocumentFragment: createDocumentFragment,
//extends list of elements
addElements: addElements
};
/*--------------------------------------------------------------------------*/
// expose html5
window.html5 = html5;
// shiv the document
shivDocument(document);
if(typeof module == 'object' && module.exports){
module.exports = html5;
}
}(typeof window !== "undefined" ? window : this, document));

4
web/src/js/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -25,17 +25,20 @@ var UNIT_PARAMS = {
};
var UI_TABS = [ {
tag: "tab-ethernet",
friendly: "Ethernet",
}, {
tag: "tab-wifi",
friendly: "Wifi",
}, {
tag: "tab-setup",
friendly: "Setup",
friendly: "PINs",
}, {
tag: "tab-led",
friendly: "LED",
}, {
tag: "tab-radio",
friendly: "Radio",
friendly: "MiLight Radio",
}, {
tag: "tab-mqtt",
friendly: "MQTT"
@ -46,6 +49,33 @@ var UI_TABS = [ {
];
var UI_FIELDS = [ {
tag: "ethernet_enable",
friendly: "Switch ethernet on or off",
type: "option_buttons",
options: {
true: 'Enable',
false: 'Disable'
},
tab: "tab-ethernet"
}, {
tag: "ethernet_static_ip",
friendly: "Static IP Address",
help: "Static IP address",
type: "string",
tab: "tab-ethernet"
}, {
tag: "ethernet_static_ip_netmask",
friendly: "Static IP Netmask",
help: "Netmask to use with Static IP",
type: "string",
tab: "tab-ethernet"
}, {
tag: "ethernet_static_ip_gateway",
friendly: "Static IP Gateway Address",
help: "IP address to use as gateway when a Static IP is speicifed",
type: "string",
tab: "tab-ethernet"
}, {
tag: "admin_username",
friendly: "Admin username",
help: "Username for logging into this webpage",

4
web/src/js/selectize.min.js vendored Normal file

File diff suppressed because one or more lines are too long

6
web/src/js/underscore-min.js vendored Normal file

File diff suppressed because one or more lines are too long