|
|
@@ -16,643 +16,17 @@
|
|
|
<!--[if lt IE 9]>
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
|
|
|
<![endif]-->
|
|
|
-
|
|
|
- <style>
|
|
|
- .header-row { border-bottom: 1px solid #ccc; }
|
|
|
- label { display: block; }
|
|
|
- .radio-option { padding: 0 5px; cursor: pointer; }
|
|
|
- .command-buttons { list-style: none; margin: 0; padding: 0; }
|
|
|
- .command-buttons li { display: inline-block; margin-right: 1em; }
|
|
|
- .form-entry { margin: 0 0 20px 0; }
|
|
|
- .form-entry .form-control { width: 20em; }
|
|
|
- .form-entry label { display: inline-block; }
|
|
|
- label:not(.error) .error-info { display: none; }
|
|
|
- .error-info { color: #f00; font-size: 0.7em; }
|
|
|
- .error-info:before { content: '('; }
|
|
|
- .error-info:after { content: ')'; }
|
|
|
- .header-btn { margin: 20px; }
|
|
|
- #sniffed-traffic { max-height: 50em; overflow-y: auto; }
|
|
|
- .btn-secondary {
|
|
|
- background-color: #fff;
|
|
|
- border: 1px solid #ccc;
|
|
|
- }
|
|
|
- .inline { display: inline-block; }
|
|
|
- .white-temp-picker {
|
|
|
- height: 2em;
|
|
|
- background: linear-gradient(to right,
|
|
|
- rgb(166, 209, 255) 0%,
|
|
|
- rgb(255, 255, 255) 50%,
|
|
|
- rgb(255, 160, 0) 100%
|
|
|
- );
|
|
|
- display: inline-block;
|
|
|
- padding: 3px 0;
|
|
|
- }
|
|
|
- .hue-picker {
|
|
|
- height: 2em;
|
|
|
- width: 100%;
|
|
|
- display: block;
|
|
|
- }
|
|
|
- .hue-picker-inner {
|
|
|
- height: 2em;
|
|
|
- width: calc(100% - 3em);
|
|
|
- display: inline-block;
|
|
|
- cursor: pointer;
|
|
|
- background: linear-gradient(to right,
|
|
|
- rgb(255, 0, 0) 0%,
|
|
|
- rgb(255, 255, 0) 16.6667%,
|
|
|
- rgb(0, 255, 0) 33.3333%,
|
|
|
- rgb(0, 255, 255) 50%,
|
|
|
- rgb(0, 0, 255) 66.6667%,
|
|
|
- rgb(255, 0, 255) 83.3333%,
|
|
|
- rgb(255, 0, 0) 100%
|
|
|
- );
|
|
|
- }
|
|
|
- .hue-value-display {
|
|
|
- border: 1px solid #000;
|
|
|
- margin-left: 0.5em;
|
|
|
- width: 2em;
|
|
|
- height: 2em;
|
|
|
- display: inline-block;
|
|
|
- }
|
|
|
- .plus-minus-group {
|
|
|
- overflow: auto;
|
|
|
- width: 100%;
|
|
|
- clear: both;
|
|
|
- display: block;
|
|
|
- }
|
|
|
- .plus-minus-group button:first-of-type {
|
|
|
- border-bottom-right-radius: 0;
|
|
|
- border-top-right-radius: 0;
|
|
|
- float: left;
|
|
|
- display: block;
|
|
|
- }
|
|
|
- .plus-minus-group button:last-of-type {
|
|
|
- border-bottom-left-radius: 0;
|
|
|
- border-top-left-radius: 0;
|
|
|
- display: block;
|
|
|
- }
|
|
|
- .plus-minus-group .title {
|
|
|
- border-width: 1px 0;
|
|
|
- border-color: #ccc;
|
|
|
- border-style: solid;
|
|
|
- padding: 5px 5px 5px 7px;
|
|
|
- margin: 0;
|
|
|
- height: 34px;
|
|
|
- line-height: 1.49;
|
|
|
- float: left;
|
|
|
- display: block;
|
|
|
- }
|
|
|
- .field-help {
|
|
|
- display: inline-block;
|
|
|
- font-size: 1.25em;
|
|
|
- margin-left: 0.5em;
|
|
|
- }
|
|
|
- .glyphicon.spinning {
|
|
|
- animation: spin 1s infinite linear;
|
|
|
- -webkit-animation: spin2 1s infinite linear;
|
|
|
- }
|
|
|
-
|
|
|
- @keyframes spin {
|
|
|
- from { transform: scale(1) rotate(0deg); }
|
|
|
- to { transform: scale(1) rotate(360deg); }
|
|
|
- }
|
|
|
-
|
|
|
- @-webkit-keyframes spin2 {
|
|
|
- from { -webkit-transform: rotate(0deg); }
|
|
|
- to { -webkit-transform: rotate(360deg); }
|
|
|
- }
|
|
|
- </style>
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></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.4/js/standalone/selectize.min.js"></script>
|
|
|
|
|
|
- <script lang="text/javascript">
|
|
|
- var FORM_SETTINGS = [
|
|
|
- "admin_username", "admin_password", "ce_pin", "csn_pin", "reset_pin","packet_repeats",
|
|
|
- "http_repeat_factor", "auto_restart_period", "discovery_port", "mqtt_server",
|
|
|
- "mqtt_topic_pattern", "mqtt_update_topic_pattern", "mqtt_username", "mqtt_password",
|
|
|
- "radio_interface_type", "listen_repeats"
|
|
|
- ];
|
|
|
-
|
|
|
- var FORM_SETTINGS_HELP = {
|
|
|
- ce_pin : "'CE' for NRF24L01 interface, and 'PKT' for 'PL1167/LT8900' interface",
|
|
|
- packet_repeats : "The number of times to repeat RF packets sent to bulbs",
|
|
|
- http_repeat_factor : "Multiplicative factor on packet_repeats for " +
|
|
|
- "requests initiated by the HTTP API. UDP API typically receives " +
|
|
|
- "duplicate packets, so more repeats should be used for HTTP.",
|
|
|
- auto_restart_period : "Automatically restart the device every number of " +
|
|
|
- "minutes specified. Use 0 for disabled.",
|
|
|
- radio_interface_type : "2.4 GHz radio model. Only change this if you know " +
|
|
|
- "You're not using an NRF24L01!",
|
|
|
- mqtt_server : "Domain or IP address of MQTT broker. Optionally specify a port " +
|
|
|
- "with (example) mymqqtbroker.com:1884.",
|
|
|
- mqtt_topic_pattern : "Pattern for MQTT topics to listen on. Example: " +
|
|
|
- "lights/:device_id/:device_type/:group_id. See README for further details.",
|
|
|
- mqtt_update_topic_pattern : "Pattern to publish MQTT updates. Packets that " +
|
|
|
- "are received from other devices, and packets that are sent from this device will " +
|
|
|
- "result in updates being sent.",
|
|
|
- discovery_port : "UDP port to listen for discovery packets on. Defaults to " +
|
|
|
- "the same port used by MiLight devices, 48899. Use 0 to disable.",
|
|
|
- listen_repeats : "Increasing this increases the amount of time spent listening for " +
|
|
|
- "packets. Set to 0 to disable listening. Default is 3."
|
|
|
- }
|
|
|
-
|
|
|
- var UDP_PROTOCOL_VERSIONS = [ 5, 6 ];
|
|
|
- var DEFAULT_UDP_PROTOCL_VERSION = 5;
|
|
|
-
|
|
|
- var selectize;
|
|
|
-
|
|
|
- var toHex = function(v) {
|
|
|
- return "0x" + (v).toString(16).toUpperCase();
|
|
|
- }
|
|
|
-
|
|
|
- var activeUrl = function() {
|
|
|
- var deviceId = $('#deviceId option:selected').val()
|
|
|
- , groupId = $('#groupId .active input').data('value')
|
|
|
- , mode = getCurrentMode();
|
|
|
-
|
|
|
- if (deviceId == "") {
|
|
|
- alert("Please enter a device ID.");
|
|
|
- throw "Must enter device ID";
|
|
|
- }
|
|
|
-
|
|
|
- if (! $('#group-option').data('for').split(',').includes(mode)) {
|
|
|
- groupId = 0;
|
|
|
- }
|
|
|
-
|
|
|
- return "/gateways/" + deviceId + "/" + mode + "/" + groupId;
|
|
|
- }
|
|
|
-
|
|
|
- var getCurrentMode = function() {
|
|
|
- return $('input[name="mode"]:checked').data('value');
|
|
|
- };
|
|
|
-
|
|
|
- var updateGroup = _.throttle(
|
|
|
- function(params) {
|
|
|
- $.ajax(
|
|
|
- activeUrl(),
|
|
|
- {
|
|
|
- method: 'PUT',
|
|
|
- data: JSON.stringify(params),
|
|
|
- contentType: 'application/json'
|
|
|
- }
|
|
|
- );
|
|
|
- },
|
|
|
- 1000
|
|
|
- );
|
|
|
-
|
|
|
- var sendCommand = _.throttle(
|
|
|
- function(params) {
|
|
|
- $.ajax(
|
|
|
- '/system',
|
|
|
- {
|
|
|
- method: 'POST',
|
|
|
- data: JSON.stringify(params),
|
|
|
- contentType: 'application/json'
|
|
|
- }
|
|
|
- );
|
|
|
- },
|
|
|
- 1000
|
|
|
- )
|
|
|
-
|
|
|
- var sniffRequest;
|
|
|
- var sniffing = false;
|
|
|
- var getTraffic = function() {
|
|
|
- sniffRequest = $.get('/gateway_traffic', function(data) {
|
|
|
- $('#sniffed-traffic').prepend('<pre>' + data + '</pre>');
|
|
|
- getTraffic();
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- var gatewayServerRow = function(deviceId, port, version) {
|
|
|
- var elmt = '<tr>';
|
|
|
- elmt += '<td>';
|
|
|
- elmt += '<input name="deviceIds[]" class="form-control" value="' + deviceId + '"/>';
|
|
|
- elmt += '</td>';
|
|
|
- elmt += '<td>'
|
|
|
- elmt += '<input name="ports[]" class="form-control" value="' + port + '"/>';;
|
|
|
- elmt += '</td>';
|
|
|
- elmt += '<td>';
|
|
|
- elmt += '<div class="btn-group" data-toggle="buttons">';
|
|
|
-
|
|
|
- for (var i = 0; i < UDP_PROTOCOL_VERSIONS.length; i++) {
|
|
|
- var val = UDP_PROTOCOL_VERSIONS[i]
|
|
|
- , selected = (version == val || (val == DEFAULT_UDP_PROTOCL_VERSION && !UDP_PROTOCOL_VERSIONS.includes(version)));
|
|
|
-
|
|
|
- elmt += '<label class="btn btn-secondary' + (selected ? ' active' : '') + '">';
|
|
|
- elmt += '<input type="radio" name="versions[]" autocomplete="off" data-value="' + val + '" '
|
|
|
- + (selected ? 'checked' : '') +'> ' + val;
|
|
|
- elmt += '</label>';
|
|
|
- }
|
|
|
-
|
|
|
- elmt += '</div></td>';
|
|
|
- elmt += '<td>';
|
|
|
- elmt += '<button class="btn btn-danger remove-gateway-server">';
|
|
|
- elmt += '<i class="glyphicon glyphicon-remove"></i>';
|
|
|
- elmt += '</button>';
|
|
|
- elmt += '</td>';
|
|
|
- elmt += '</tr>';
|
|
|
- return elmt;
|
|
|
- }
|
|
|
-
|
|
|
- var loadSettings = function() {
|
|
|
- $.getJSON('/settings', function(val) {
|
|
|
- Object.keys(val).forEach(function(k) {
|
|
|
- var field = $('#settings input[name="' + k + '"]');
|
|
|
-
|
|
|
- if (field.length > 0) {
|
|
|
- if (field.attr('type') === 'radio') {
|
|
|
- field.filter('[value="' + val[k] + '"]').click();
|
|
|
- } else {
|
|
|
- field.val(val[k]);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- if (val.device_ids) {
|
|
|
- selectize.clearOptions();
|
|
|
- val.device_ids.forEach(function(v) {
|
|
|
- selectize.addOption({text: toHex(v), value: v});
|
|
|
- });
|
|
|
- selectize.refreshOptions();
|
|
|
- }
|
|
|
-
|
|
|
- var gatewayForm = $('#gateway-server-configs').html('');
|
|
|
- if (val.gateway_configs) {
|
|
|
- val.gateway_configs.forEach(function(v) {
|
|
|
- gatewayForm.append(gatewayServerRow(toHex(v[0]), v[1], v[2]));
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- var saveGatewayConfigs = function() {
|
|
|
- var form = $('#gateway-server-form')
|
|
|
- , errors = false;
|
|
|
-
|
|
|
- $('input', form).removeClass('error');
|
|
|
-
|
|
|
- var deviceIds = $('input[name="deviceIds[]"]', form).map(function(i, v) {
|
|
|
- var val = $(v).val();
|
|
|
-
|
|
|
- if (isNaN(val)) {
|
|
|
- errors = true;
|
|
|
- $(v).addClass('error');
|
|
|
- return null;
|
|
|
- } else {
|
|
|
- return val;
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- var ports = $('input[name="ports[]"]', form).map(function(i, v) {
|
|
|
- var val = $(v).val();
|
|
|
-
|
|
|
- if (isNaN(val)) {
|
|
|
- errors = true;
|
|
|
- $(v).addClass('error');
|
|
|
- return null;
|
|
|
- } else {
|
|
|
- return val;
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- var versions = $('.active input[name="versions[]"]', form).map(function(i, v) {
|
|
|
- return $(v).data('value');
|
|
|
- });
|
|
|
-
|
|
|
- if (!errors) {
|
|
|
- var data = [];
|
|
|
- for (var i = 0; i < deviceIds.length; i++) {
|
|
|
- data[i] = [deviceIds[i], ports[i], versions[i]];
|
|
|
- }
|
|
|
- $.ajax(
|
|
|
- '/settings',
|
|
|
- {
|
|
|
- method: 'put',
|
|
|
- contentType: 'application/json',
|
|
|
- data: JSON.stringify({gateway_configs: data})
|
|
|
- }
|
|
|
- )
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- var deviceIdError = function(v) {
|
|
|
- if (!v) {
|
|
|
- $('#device-id-label').removeClass('error');
|
|
|
- } else {
|
|
|
- $('#device-id-label').addClass('error');
|
|
|
- $('#device-id-label .error-info').html(v);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- var updateModeOptions = function() {
|
|
|
- var currentMode = getCurrentMode();
|
|
|
-
|
|
|
- $('.mode-option').map(function() {
|
|
|
- if ($(this).data('for').split(',').includes(currentMode)) {
|
|
|
- $(this).show();
|
|
|
- } else {
|
|
|
- $(this).hide();
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- var parseVersion = function(v) {
|
|
|
- var matches = v.match(/(\d+)\.(\d+)\.(\d+)(-(.*))?/);
|
|
|
-
|
|
|
- return {
|
|
|
- major: matches[1],
|
|
|
- minor: matches[2],
|
|
|
- patch: matches[3],
|
|
|
- revision: matches[5],
|
|
|
- parts: [matches[1], matches[2], matches[3], matches[5]]
|
|
|
- };
|
|
|
- };
|
|
|
-
|
|
|
- var isNewerVersion = function(a, b) {
|
|
|
- var va = parseVersion(a)
|
|
|
- , vb = parseVersion(b);
|
|
|
-
|
|
|
- return va.parts > vb.parts;
|
|
|
- };
|
|
|
-
|
|
|
- var handleCheckForUpdates = function() {
|
|
|
- var currentVersion = null
|
|
|
- , latestRelease = null;
|
|
|
-
|
|
|
- var handleReceiveData = function() {
|
|
|
- if (currentVersion != null) {
|
|
|
- $('#current-version').html(currentVersion.version + " (" + currentVersion.variant + ")");
|
|
|
- }
|
|
|
-
|
|
|
- if (latestRelease != null) {
|
|
|
- $('#latest-version .info-key').each(function() {
|
|
|
- var value = latestRelease[$(this).data('key')];
|
|
|
- var prop = $(this).data('prop');
|
|
|
-
|
|
|
- if (prop) {
|
|
|
- $(this).prop(prop, value);
|
|
|
- } else {
|
|
|
- $(this).html(value);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- if (currentVersion != null && latestRelease != null) {
|
|
|
- $('#latest-version .status').html('');
|
|
|
- $('#latest-version-info').show();
|
|
|
-
|
|
|
- var summary;
|
|
|
- if (isNewerVersion(latestRelease.tag_name, currentVersion.version)) {
|
|
|
- summary = "New version available!";
|
|
|
- } else {
|
|
|
- summary = "You're on the most recent version.";
|
|
|
- }
|
|
|
- $('#version-summary').html(summary);
|
|
|
-
|
|
|
- var releaseAsset = latestRelease.assets.filter(function(x) {
|
|
|
- return x.name.indexOf(currentVersion.variant) != -1;
|
|
|
- });
|
|
|
-
|
|
|
- if (releaseAsset.length > 0) {
|
|
|
- console.log(releaseAsset[0].url);
|
|
|
- $('#firmware-link').prop('href', releaseAsset[0].browser_download_url);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- console.log(latestRelease);
|
|
|
- }
|
|
|
-
|
|
|
- var handleError = function(e, d) {
|
|
|
- console.log(e);
|
|
|
- console.log(d);
|
|
|
- }
|
|
|
-
|
|
|
- $('#current-version,#latest-version .status').html('<i class="spinning glyphicon glyphicon-refresh"></i>');
|
|
|
- $('#version-summary').html('');
|
|
|
- $('#latest-version-info').hide();
|
|
|
- $('#updates-modal').modal();
|
|
|
-
|
|
|
- $.ajax(
|
|
|
- '/about',
|
|
|
- {
|
|
|
- success: function(data) {
|
|
|
- currentVersion = JSON.parse(data);
|
|
|
- handleReceiveData();
|
|
|
- },
|
|
|
- failure: handleError
|
|
|
- }
|
|
|
- );
|
|
|
-
|
|
|
- $.ajax(
|
|
|
- '/latest_release',
|
|
|
- {
|
|
|
- success: function(data) {
|
|
|
- latestRelease = data;
|
|
|
- handleReceiveData();
|
|
|
- },
|
|
|
- failure: handleError
|
|
|
- }
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
- $(function() {
|
|
|
- $('.radio-option').click(function() {
|
|
|
- $(this).prev().prop('checked', true);
|
|
|
- });
|
|
|
-
|
|
|
- var hueDragging = false;
|
|
|
- var colorUpdated = function(e) {
|
|
|
- var x = e.pageX - $(this).offset().left
|
|
|
- , pct = x/(1.0*$(this).width())
|
|
|
- , hue = Math.round(360*pct)
|
|
|
- ;
|
|
|
-
|
|
|
- $('.hue-value-display').css({
|
|
|
- backgroundColor: "hsl(" + hue + ",100%,50%)"
|
|
|
- });
|
|
|
-
|
|
|
- updateGroup({hue: hue});
|
|
|
- };
|
|
|
-
|
|
|
- $('.hue-picker-inner')
|
|
|
- .mousedown(function(e) {
|
|
|
- hueDragging = true;
|
|
|
- colorUpdated.call(this, e);
|
|
|
- })
|
|
|
- .mouseup(function(e) {
|
|
|
- hueDragging = false;
|
|
|
- })
|
|
|
- .mouseout(function(e) {
|
|
|
- hueDragging = false;
|
|
|
- })
|
|
|
- .mousemove(function(e) {
|
|
|
- if (hueDragging) {
|
|
|
- colorUpdated.call(this, e);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- $('.slider').slider();
|
|
|
-
|
|
|
- $('.raw-update').change(function() {
|
|
|
- var data = {}
|
|
|
- , val = $(this).attr('type') == 'checkbox' ? $(this).is(':checked') : $(this).val()
|
|
|
- ;
|
|
|
-
|
|
|
- data[$(this).attr('name')] = val;
|
|
|
- updateGroup(data);
|
|
|
- });
|
|
|
-
|
|
|
- $('.command-btn').click(function() {
|
|
|
- updateGroup({command: $(this).data('command')});
|
|
|
- });
|
|
|
-
|
|
|
- $('.system-btn').click(function() {
|
|
|
- sendCommand({command: $(this).data('command')});
|
|
|
- });
|
|
|
-
|
|
|
- $('#sniff').click(function() {
|
|
|
- if (sniffing) {
|
|
|
- sniffRequest.abort();
|
|
|
- sniffing = false;
|
|
|
- $(this).html('Start Sniffing');
|
|
|
- } else {
|
|
|
- sniffing = true;
|
|
|
- getTraffic();
|
|
|
- $(this).html('Stop Sniffing');
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- $('#add-server-btn').click(function() {
|
|
|
- $('#gateway-server-configs').append(gatewayServerRow('', ''));
|
|
|
- });
|
|
|
-
|
|
|
- $('#mode').change(updateModeOptions);
|
|
|
-
|
|
|
- $('body').on('click', '.remove-gateway-server', function() {
|
|
|
- $(this).closest('tr').remove();
|
|
|
- });
|
|
|
-
|
|
|
- selectize = $('#deviceId').selectize({
|
|
|
- create: true,
|
|
|
- sortField: 'text',
|
|
|
- onOptionAdd: function(v, item) {
|
|
|
- item.value = parseInt(item.value);
|
|
|
- },
|
|
|
- createFilter: function(v) {
|
|
|
- if (! v.match(/^(0x[a-fA-F0-9]{1,4}|[0-9]{1,5})$/)) {
|
|
|
- deviceIdError("Must be an integer between 0x0000 and 0xFFFF");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- var value = parseInt(v);
|
|
|
-
|
|
|
- if (! (0 <= v && v <= 0xFFFF)) {
|
|
|
- deviceIdError("Must be an integer between 0x0000 and 0xFFFF");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- deviceIdError(false);
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
- });
|
|
|
- selectize = selectize[0].selectize;
|
|
|
-
|
|
|
- var settings = "";
|
|
|
-
|
|
|
- FORM_SETTINGS.forEach(function(k) {
|
|
|
- var elmt = '<div class="form-entry">';
|
|
|
- elmt += '<div>';
|
|
|
- elmt += '<label for="' + k + '">' + k + '</label>';
|
|
|
-
|
|
|
- if (FORM_SETTINGS_HELP[k]) {
|
|
|
- elmt += '<div class="field-help" data-help-text="' + FORM_SETTINGS_HELP[k] + '"></div>';
|
|
|
- }
|
|
|
-
|
|
|
- elmt += '</div>';
|
|
|
-
|
|
|
- if(k === "radio_interface_type") {
|
|
|
- elmt += '<div class="btn-group" id="radio_interface_type" data-toggle="buttons">' +
|
|
|
- '<label class="btn btn-secondary active">' +
|
|
|
- '<input type="radio" id="nrf24" name="radio_interface_type" autocomplete="off" value="nRF24" /> nRF24' +
|
|
|
- '</label>'+
|
|
|
- '<label class="btn btn-secondary">' +
|
|
|
- '<input type="radio" id="lt8900" name="radio_interface_type" autocomplete="off" value="LT8900" /> PL1167/LT8900' +
|
|
|
- '</label>' +
|
|
|
- '</div>';
|
|
|
- } else {
|
|
|
- elmt += '<input type="text" class="form-control" name="' + k + '"/>';
|
|
|
- elmt += '</div>';
|
|
|
- }
|
|
|
-
|
|
|
- settings += elmt;
|
|
|
- });
|
|
|
-
|
|
|
- $('#settings').prepend(settings);
|
|
|
- $('#settings').submit(function(e) {
|
|
|
- var obj = {};
|
|
|
-
|
|
|
- FORM_SETTINGS.forEach(function(k) {
|
|
|
- var elmt = $('#settings input[name="' + k + '"]');
|
|
|
-
|
|
|
- if (elmt.attr('type') === 'radio') {
|
|
|
- obj[k] = elmt.filter(':checked').val();
|
|
|
- } else {
|
|
|
- obj[k] = elmt.val();
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- // pretty hacky. whatever.
|
|
|
- obj.device_ids = _.map(
|
|
|
- $('.selectize-control .option'),
|
|
|
- function(x) {
|
|
|
- return $(x).data('value')
|
|
|
- }
|
|
|
- );
|
|
|
-
|
|
|
- $.ajax(
|
|
|
- "/settings",
|
|
|
- {
|
|
|
- method: 'put',
|
|
|
- contentType: 'application/json',
|
|
|
- data: JSON.stringify(obj)
|
|
|
- }
|
|
|
- );
|
|
|
-
|
|
|
- e.preventDefault();
|
|
|
- return false;
|
|
|
- });
|
|
|
-
|
|
|
- $('#gateway-server-form').submit(function(e) {
|
|
|
- saveGatewayConfigs();
|
|
|
- e.preventDefault();
|
|
|
- return false;
|
|
|
- });
|
|
|
-
|
|
|
- $('.field-help').each(function() {
|
|
|
- var elmt = $('<i></i>')
|
|
|
- .addClass('glyphicon glyphicon-question-sign')
|
|
|
- .tooltip({
|
|
|
- placement: 'top',
|
|
|
- title: $(this).data('help-text'),
|
|
|
- container: 'body'
|
|
|
- });
|
|
|
- $(this).append(elmt);
|
|
|
- });
|
|
|
-
|
|
|
- $('#updates-btn').click(handleCheckForUpdates);
|
|
|
-
|
|
|
- loadSettings();
|
|
|
- updateModeOptions();
|
|
|
- });
|
|
|
- </script>
|
|
|
+ <link rel="stylesheet" href="style.css" />
|
|
|
+ <script src="bundle.js"></script>
|
|
|
|
|
|
<div id="update-firmware-modal" class="modal fade" role="dialog">
|
|
|
<div class="modal-dialog">
|