mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
refactoring of webui and event based websocket layer (#219)
* make hyperion websocket api event based * implement new websocket handling for generalconf * migrate all webui stuff to new event based websocket api some cleanup ... now all html templates are in content refactoring of web stuff * add hyperionport to global start impl. removing advanced key * separate dashboard serverinfo is updated every 3 seconds automatily add input selection cleanup and remove not needed stuff * prepare infrastructure for server sided file execution * webui minor fixes * fix compile
This commit is contained in:
parent
c17c3bd273
commit
4a27f3d43e
1
.gitignore
vendored
1
.gitignore
vendored
@ -16,3 +16,4 @@ CMakeCache.txt
|
||||
*.log
|
||||
/HyperionConfig.h
|
||||
/lib
|
||||
.directory
|
||||
|
91
assets/webconfig/content/dashboard.html
Normal file
91
assets/webconfig/content/dashboard.html
Normal file
@ -0,0 +1,91 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header">Dashboard</h1>
|
||||
<div class="introd">
|
||||
<h4 lang="en" data-lang-token="dashboard_label_intro">The dashboard give you a quick overview about the status of Hyperion and show you the latest news of the Hyperion Blog.</h4>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="col-lg-4">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-info-circle fa-fw"></i>
|
||||
<span lang="en" data-lang-token="dashboard_label_infobox_title">Information</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td lang="en" data-lang-token="dashboard_label_infobox_currenthyp">Your Hyperion version:</td>
|
||||
<td id="currentversion">unknown</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td lang="en" data-lang-token="dashboard_label_infobox_latesthyp">Latest version:</td>
|
||||
<td id="latestversion">unknown</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td lang="en" data-lang-token="dashboard_label_infobox_leddevice">LED type:</td>
|
||||
<td id="dash_leddevice">unknown</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td lang="en" data-lang-token="dashboard_label_infobox_device">Device:</td>
|
||||
<td id="dash_systeminfo"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr>
|
||||
<span id="versioninforesult"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-eye fa-fw"></i>
|
||||
<span lang="en" data-lang-token="dashboard_label_componentbox_title">Components status</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Component</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Kodi Watch</td>
|
||||
<td><i class="fa fa-circle component-on"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Blackborder</td>
|
||||
<td><i class="fa fa-circle component-off"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Booteffect</td>
|
||||
<td><i class="fa fa-circle component-off"></i></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-newspaper-o fa-fw"></i>
|
||||
<span lang="en" data-lang-token="dashboard_label_newsbox_title">Latest blog posts</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- /.col-lg-12 -->
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
</div>
|
||||
<!-- /.container-fluid -->
|
||||
|
25
assets/webconfig/content/effects.html
Normal file
25
assets/webconfig/content/effects.html
Normal file
@ -0,0 +1,25 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header" lang="en" data-lang-token="main_menu_effects_token">Effects</h1>
|
||||
<div class="introd">
|
||||
<h4 lang="en" data-lang-token="remote_effects_intro">The Effects remote enables you to set an effect for testing or demonstration purposes. Don't forget to stop it afterwards.</h4>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="col-lg-12" id="buttondiv">
|
||||
<button type="button" class="btn btn-danger" id="effect_stop" onclick="requestPriorityClear()"><i class="fa fa-stop"></i></button><span lang="en" data-lang-token="remote_effects_label_stopeffect">Stop Effect</span><br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready( function() {
|
||||
for(i = 0; i < parsedServerInfoJSON.info.effects.length; i++) {
|
||||
//console.log(parsedServerInfoJSON.info.effects[i].name);
|
||||
var effectName = parsedServerInfoJSON.info.effects[i].name;
|
||||
|
||||
$('#buttondiv').append('<button type="button" class="btn btn-success" onclick="requestPlayEffect(\''+effectName+'\')"><i class="fa fa-play"></i></button> '+effectName+'<br />');
|
||||
}
|
||||
});
|
||||
</script>
|
106
assets/webconfig/content/generalconf.html
Normal file
106
assets/webconfig/content/generalconf.html
Normal file
@ -0,0 +1,106 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header" lang="en" data-lang-token="main_menu_general_conf_token">General</h1>
|
||||
<div class="introd">
|
||||
<h4 lang="en" data-lang-token="remote_general_conf_intro">You can edit the general configuration here.</h4>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="col-lg-12">
|
||||
<form id="generalConfForm"></form>
|
||||
<div id='editor_holder'></div>
|
||||
<button id='submit'>Submit (console.log)</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
function removeAdvanced(obj,searchStack = [])
|
||||
{
|
||||
$.each(obj, function(key, val) {
|
||||
if ( typeof(val) == 'object' )
|
||||
{
|
||||
searchStack.push(key);
|
||||
if (! removeAdvanced(val,searchStack) )
|
||||
searchStack.pop();
|
||||
}
|
||||
else if ( key == "advanced" && val == true )
|
||||
{
|
||||
console.log(searchStack);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
$(hyperion).on("cmd-config-getschema", function(event) {
|
||||
parsedConfSchemaJSON = event.response.result;
|
||||
|
||||
// remove all "advanced" options from schema
|
||||
//removeAdvanced(parsedConfSchemaJSON); // not working atm
|
||||
//console.log(JSON.stringify(parsedConfSchemaJSON));
|
||||
|
||||
schema_smoothing = parsedConfSchemaJSON.properties.smoothing;
|
||||
schema_kodiVideoChecker = parsedConfSchemaJSON.properties.kodiVideoChecker;
|
||||
schema_initialEffect = parsedConfSchemaJSON.properties.initialEffect;
|
||||
//schema_grabber-v4l2 = parsedConfSchemaJSON.properties.grabber-v4l2;
|
||||
schema_framegrabber = parsedConfSchemaJSON.properties.framegrabber;
|
||||
schema_forwarder = parsedConfSchemaJSON.properties.forwarder;
|
||||
schema_effects = parsedConfSchemaJSON.properties.effects;
|
||||
schema_device = parsedConfSchemaJSON.properties.device;
|
||||
schema_color = parsedConfSchemaJSON.properties.color;
|
||||
schema_blackborderdetector = parsedConfSchemaJSON.properties.blackborderdetector;
|
||||
schema_logger = parsedConfSchemaJSON.properties.logger;
|
||||
schema_jsonServer = parsedConfSchemaJSON.properties.jsonServer;
|
||||
schema_protoServer = parsedConfSchemaJSON.properties.protoServer;
|
||||
schema_boblightServer = parsedConfSchemaJSON.properties.boblightServer;
|
||||
schema_udpListener = parsedConfSchemaJSON.properties.udpListener;
|
||||
schema_webConfig = parsedConfSchemaJSON.properties.webConfig;
|
||||
|
||||
var element = document.getElementById('editor_holder');
|
||||
//JSONEditor.defaults.options.theme = 'bootstrap3';
|
||||
var general_conf_editor = new JSONEditor(element,{
|
||||
theme: 'bootstrap3',
|
||||
disable_collapse: 'true',
|
||||
form_name_root: 'sa',
|
||||
disable_edit_json: 'true',
|
||||
disable_properties: 'true',
|
||||
no_additional_properties: 'true',
|
||||
schema: {
|
||||
title:' ',
|
||||
properties: {
|
||||
schema_blackborderdetector,
|
||||
schema_color,
|
||||
schema_device,
|
||||
schema_effects,
|
||||
schema_forwarder,
|
||||
schema_framegrabber,
|
||||
//schema_grabber-v4l2,
|
||||
schema_initialEffect,
|
||||
schema_kodiVideoChecker,
|
||||
schema_smoothing,
|
||||
schema_logger,
|
||||
schema_jsonServer,
|
||||
schema_protoServer,
|
||||
schema_boblightServer,
|
||||
schema_udpListener,
|
||||
schema_webConfig
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready( function() {
|
||||
requestServerConfigSchema();
|
||||
|
||||
document.getElementById('submit').addEventListener('click',function() {
|
||||
// Get the value from the editor
|
||||
console.log(general_conf_editor.getValue());
|
||||
});
|
||||
// $("[type='checkbox']").bootstrapSwitch();
|
||||
});
|
||||
|
||||
|
||||
</script>
|
34
assets/webconfig/content/input_selection.html
Normal file
34
assets/webconfig/content/input_selection.html
Normal file
@ -0,0 +1,34 @@
|
||||
<div style="text-align:center;margin:auto;padding:auto">
|
||||
<div id="hyperion_inputs" />
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(hyperion).on("cmd-serverinfo", function(event) {
|
||||
var data = "";
|
||||
var i;
|
||||
for(i = 0; i < parsedServerInfoJSON.info.priorities.length; i++) {
|
||||
var owner = parsedServerInfoJSON.info.priorities[i].owner;
|
||||
var active = parsedServerInfoJSON.info.priorities[i].active;
|
||||
var visible = parsedServerInfoJSON.info.priorities[i].visible;
|
||||
var priority = parsedServerInfoJSON.info.priorities[i].priority;
|
||||
var btn_type = "default";
|
||||
if (active) btn_type = "warning";
|
||||
if (visible) btn_type = "success";
|
||||
|
||||
data += '<button id="srcBtn'+i+'" type="button" class="btn btn-lg btn-'+btn_type+' btn_input_selection" style="margin:10px;min-width:200px" title="prio '+priority+'" onclick="requestSetSource('+priority+');">'+owner+'</button><br/>';
|
||||
}
|
||||
data += '<button id="srcBtn'+i+'" type="button" class="btn btn-lg btn-info btn_input_selection" style="margin:10px;min-width:200px" onclick="requestSetSource(\'auto\');">auto select</button><br/>';
|
||||
$('#hyperion_inputs').html(data);
|
||||
|
||||
var max_width=200;
|
||||
$('.btn_input_selection').each(function() {
|
||||
elem_width = $(this).css('width')
|
||||
elem_width = elem_width.substring(0, elem_width.length - 2);
|
||||
if (elem_width > max_width)
|
||||
max_width = elem_width;
|
||||
});
|
||||
$('.btn_input_selection').css("min-width",max_width+"px");
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header" lang="en" data-lang-token="main_menu_colors_token">Colors</h1>
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header" lang="en" data-lang-token="main_menu_colors_token">Colors</h1>
|
||||
<div class="col-lg-1">
|
||||
<span lang="en" data-lang-token="remote_colors_label_color">Set color: </span>
|
||||
</div>
|
||||
@ -25,12 +25,13 @@
|
||||
$('#cp2').colorpicker({
|
||||
format: 'rgb',
|
||||
|
||||
colorSelectors: {'default': '#777777',
|
||||
colorSelectors: {
|
||||
'default': '#777777',
|
||||
'primary': '#337ab7',
|
||||
'success': '#5cb85c',
|
||||
'info': '#5bc0de',
|
||||
'info' : '#5bc0de',
|
||||
'warning': '#f0ad4e',
|
||||
'danger': '#d9534f'
|
||||
'danger' : '#d9534f'
|
||||
},
|
||||
customClass: 'colorpicker-2x',
|
||||
sliders: {
|
||||
@ -48,19 +49,10 @@
|
||||
});
|
||||
|
||||
$('#cp2').colorpicker().on('changeColor', function(e) {
|
||||
//console.log(e.color.toRGB());
|
||||
webSocket.send('{"command":"color", "color":['+e.color.toRGB().r+','+e.color.toRGB().g+','+e.color.toRGB().b+'], "priority":1}');
|
||||
color = e.color.toRGB();
|
||||
requestSetColor(color.r, color.g, color.b);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$("#reset_color").on("click", function() {
|
||||
webSocket.send('{"command":"clear", "priority":1}');
|
||||
});
|
||||
|
||||
|
||||
|
||||
webSocket.onmessage = function(event){
|
||||
console.log(event.data);
|
||||
}
|
||||
$("#reset_color").on("click", requestPriorityClear);
|
||||
</script>
|
26
assets/webconfig/content/remote_components.html
Normal file
26
assets/webconfig/content/remote_components.html
Normal file
@ -0,0 +1,26 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header" lang="en" data-lang-token="main_menu_component_token">Effects</h1>
|
||||
<div class="introd">
|
||||
<h4 lang="en" data-lang-token="remote_components_intro">The components remote enables you to disable and enable certain components of Hyperion during runtime. Keep in mind this persist just until the next reboot! To enable/disable components permament, use the configuration section.</h4>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="col-lg-12" id="componentsbutton">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
new Enum('SMOOTHING', 'BLACKBORDER', 'KODICHECKER', 'FORWARDER', 'UDPLISTENER', 'BOBLIGHT_SERVER','GRABBER');
|
||||
|
||||
function Enum() {
|
||||
for (var i in arguments)
|
||||
{
|
||||
this[arguments[i]] = i;
|
||||
$('#componentsbutton').append('<button type="button" class="btn btn-success" onclick="requestSetComponentState(\''+arguments[i]+'\',true)"><i class="fa fa-play"></i></button> '+arguments[i]+'<br />');
|
||||
$('#componentsbutton').append('<button type="button" class="btn btn-danger" onclick="requestSetComponentState(\''+arguments[i]+'\',false)"><i class="fa fa-play"></i></button> '+arguments[i]+'<br />');
|
||||
}
|
||||
}
|
||||
</script>
|
@ -110,4 +110,4 @@
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
23
assets/webconfig/content/update.html
Normal file
23
assets/webconfig/content/update.html
Normal file
@ -0,0 +1,23 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header" lang="en" data-lang-token="main_menu_update_token">Update</h1>
|
||||
<div class="introd">
|
||||
<h4 lang="en" data-lang-token="update_label_intro">This page gives you an overview of all Hyperion versions available. On top you could update or downgrade your version of Hyperion whenever you want. Sorted from newest to oldest</h4>
|
||||
</div>
|
||||
<hr>
|
||||
<h4 id="update_currver"></h4>
|
||||
<hr>
|
||||
<div class="col-lg-12" id="versionlist">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
for (key in parsedUpdateJSON)
|
||||
{
|
||||
$('#versionlist').append('<div class="col-lg-6"><div class="panel panel-default"><div class="panel-heading"><i class="fa fa-television fa-fw"></i>Hyperion V'+parsedUpdateJSON[key].versionnr+'</div><div class="panel-body"><p><span style="font-weight:bold;" lang="en" data-lang-token="update_label_type">Type:</span> '+ parsedUpdateJSON[key].channel +'</p><p><span style="font-weight:bold;" lang="en" data-lang-token="update_label_description">Description:</span> '+parsedUpdateJSON[key].versiondesc+'</p><hr><a class="btn btn-primary" href="'+ parsedUpdateJSON[key].versionchangelog +'" target="_blank"><i class="fa fa-list fa-fw"></i><span style="font-weight:bold;" lang="en" data-lang-token="update_button_changelog">Full changelog</span></a><button type="button" class="btn btn-warning pull-right"><i class="fa fa-download fa-fw"></i><span lang="en" data-lang-token="update_button_install">Install</span></button></div></div></div>');
|
||||
}
|
||||
$('#update_currver').append(currentVersion);
|
||||
</script>
|
@ -1,39 +0,0 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header" lang="en" data-lang-token="main_menu_effects_token">Effects</h1>
|
||||
<div class="introd">
|
||||
<h4 lang="en" data-lang-token="remote_effects_intro">The Effects remote enables you to set an effect for testing or demonstration purposes. Don't forget to stop it afterwards.</h4>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="col-lg-12" id="buttondiv">
|
||||
<button type="button" class="btn btn-danger" id="effect_stop"><i class="fa fa-stop"></i></button><span lang="en" data-lang-token="remote_effects_label_stopeffect">Stop Effect</span><br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
$(document).ready( function() {
|
||||
|
||||
for(i = 0; i < parsedServerInfoJSON.info.effects.length; i++) {
|
||||
//console.log(parsedServerInfoJSON.info.effects[i].name);
|
||||
var effectName = parsedServerInfoJSON.info.effects[i].name;
|
||||
|
||||
$('#buttondiv').append('<button type="button" class="btn btn-success" onclick="playEffect(\''+effectName+'\')"><i class="fa fa-play"></i></button> '+effectName+'<br />');
|
||||
}
|
||||
|
||||
|
||||
$("#effect_stop").on("click", function() {
|
||||
webSocket.send('{"command":"clear", "priority":1}');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function playEffect(effectName) {
|
||||
console.log(effectName);
|
||||
webSocket.send('{"command":"effect","effect":{"name":"'+effectName+'"},"priority":1}');
|
||||
}
|
||||
|
||||
</script>
|
@ -1,105 +0,0 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header" lang="en" data-lang-token="main_menu_general_conf_token">General</h1>
|
||||
<div class="introd">
|
||||
<h4 lang="en" data-lang-token="remote_general_conf_intro">You can edit the general configuration here.</h4>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="col-lg-12">
|
||||
<form id="generalConfForm"></form>
|
||||
<div id='editor_holder'></div>
|
||||
|
||||
<button id='submit'>Submit (console.log)</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
$(document).ready( function() {
|
||||
|
||||
webSocket = new WebSocket('ws://'+document.location.hostname+':'+hyperionport);
|
||||
var serverInfo;
|
||||
|
||||
webSocket.onerror = function(event) {
|
||||
alert(event.data);
|
||||
};
|
||||
|
||||
|
||||
webSocket.onopen = function(event) {
|
||||
webSocket.send('{"command":"config","subcommand":"getschema"}');
|
||||
};
|
||||
|
||||
webSocket.onmessage = function(response){
|
||||
parsedConfSchemaJSON = JSON.parse(response.data);
|
||||
console.log(parsedConfSchemaJSON)
|
||||
|
||||
schema_smoothing = parsedConfSchemaJSON.result.properties.smoothing;
|
||||
schema_kodiVideoChecker = parsedConfSchemaJSON.result.properties.kodiVideoChecker;
|
||||
schema_initialEffect = parsedConfSchemaJSON.result.properties.initialEffect;
|
||||
//schema_grabber-v4l2 = parsedConfSchemaJSON.result.properties.grabber-v4l2;
|
||||
schema_framegrabber = parsedConfSchemaJSON.result.properties.framegrabber;
|
||||
schema_forwarder = parsedConfSchemaJSON.result.properties.forwarder;
|
||||
schema_effects = parsedConfSchemaJSON.result.properties.effects;
|
||||
schema_device = parsedConfSchemaJSON.result.properties.device;
|
||||
schema_color = parsedConfSchemaJSON.result.properties.color;
|
||||
schema_blackborderdetector = parsedConfSchemaJSON.result.properties.blackborderdetector;
|
||||
schema_logger = parsedConfSchemaJSON.result.properties.logger;
|
||||
schema_jsonServer = parsedConfSchemaJSON.result.properties.jsonServer;
|
||||
schema_protoServer = parsedConfSchemaJSON.result.properties.protoServer;
|
||||
schema_boblightServer = parsedConfSchemaJSON.result.properties.boblightServer;
|
||||
schema_udpListener = parsedConfSchemaJSON.result.properties.udpListener;
|
||||
schema_webConfig = parsedConfSchemaJSON.result.properties.webConfig;
|
||||
|
||||
var element = document.getElementById('editor_holder');
|
||||
//JSONEditor.defaults.options.theme = 'bootstrap3';
|
||||
var general_conf_editor = new JSONEditor(element,{
|
||||
theme: 'bootstrap3',
|
||||
disable_collapse: 'true',
|
||||
form_name_root: 'sa',
|
||||
disable_edit_json: 'true',
|
||||
disable_properties: 'true',
|
||||
no_additional_properties: 'true',
|
||||
schema: {
|
||||
title:' ',
|
||||
properties: {
|
||||
schema_blackborderdetector,
|
||||
schema_color,
|
||||
schema_device,
|
||||
schema_effects,
|
||||
schema_forwarder,
|
||||
schema_framegrabber,
|
||||
//schema_grabber-v4l2,
|
||||
schema_initialEffect,
|
||||
schema_kodiVideoChecker,
|
||||
schema_smoothing,
|
||||
schema_logger,
|
||||
schema_jsonServer,
|
||||
schema_protoServer,
|
||||
schema_boblightServer,
|
||||
schema_udpListener,
|
||||
schema_webConfig
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('submit').addEventListener('click',function() {
|
||||
// Get the value from the editor
|
||||
console.log(general_conf_editor.getValue());
|
||||
});
|
||||
|
||||
|
||||
// $("[type='checkbox']").bootstrapSwitch();
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
@ -3,31 +3,32 @@
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="">
|
||||
|
||||
|
||||
<title>Hyperion - WebUI</title>
|
||||
<title>Hyperion - WebUI</title>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="js/lib/jquery.min.js"></script>
|
||||
<script src="js/lib/jquery.min.js"></script>
|
||||
|
||||
<script src="js/hyperion.js"></script>
|
||||
<script src="js/hyperion.js"></script>
|
||||
<script src="js/ui_utils.js"></script>
|
||||
|
||||
<!-- Colorpicker -->
|
||||
<script src="js/lib/bootstrap-colorpicker.min.js"></script>
|
||||
<link href="css/bootstrap-colorpicker.min.css" rel="stylesheet">
|
||||
<script src="js/lib/bootstrap-colorpicker.min.js"></script>
|
||||
<link href="css/bootstrap-colorpicker.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Bootstrap Switch -->
|
||||
<script src="js/lib/bootstrap-switch.min.js"></script>
|
||||
<link href="css/bootstrap-switch.min.css" rel="stylesheet">
|
||||
<script src="js/lib/bootstrap-switch.min.js"></script>
|
||||
<link href="css/bootstrap-switch.min.css" rel="stylesheet">
|
||||
|
||||
<!-- JSONForm -->
|
||||
<!--<script src="js/lib/underscore.js"></script>
|
||||
<script src="js/lib/jsonform.js"></script>-->
|
||||
<script src="js/lib/jsoneditor.min.js"></script>
|
||||
<!--<script src="js/lib/underscore.js"></script>
|
||||
<script src="js/lib/jsonform.js"></script>-->
|
||||
<script src="js/lib/jsoneditor.min.js"></script>
|
||||
|
||||
<!--Language Support -->
|
||||
<script src="js/lib/jquery-lang.js" charset="utf-8" type="text/javascript"></script>
|
||||
@ -49,481 +50,279 @@
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Bootstrap Core CSS -->
|
||||
<link href="css/bootstrap.css" rel="stylesheet">
|
||||
<!-- Bootstrap Core CSS -->
|
||||
<link href="css/bootstrap.css" rel="stylesheet">
|
||||
|
||||
<!-- Flags -->
|
||||
<link href="css/flag-icon.min.css" rel="stylesheet">
|
||||
|
||||
<!-- MetisMenu CSS -->
|
||||
<link href="css/metisMenu.css" rel="stylesheet">
|
||||
<!-- MetisMenu CSS -->
|
||||
<link href="css/metisMenu.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom CSS -->
|
||||
<link href="css/sb-admin-2.css" rel="stylesheet">
|
||||
<!-- Custom CSS -->
|
||||
<link href="css/sb-admin-2.css" rel="stylesheet">
|
||||
|
||||
<link href="css/hyperion.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom Fonts -->
|
||||
<link href="css/font-awesome.min.css" rel="stylesheet" type="text/css">
|
||||
<!-- Custom Fonts -->
|
||||
<link href="css/font-awesome.min.css" rel="stylesheet" type="text/css">
|
||||
|
||||
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="wrapper">
|
||||
<div id="wrapper">
|
||||
|
||||
<!-- Navigation -->
|
||||
<nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<!-- Navigation -->
|
||||
<nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
|
||||
<a class="navbar-brand" href="index.html"><img src="img/hyperion/hyperionlogo.png" alt="Redefine ambient light!"></a>
|
||||
<a class="navbar-brand" href="/"><img src="img/hyperion/hyperionlogo.png" alt="Redefine ambient light!"></a>
|
||||
|
||||
</div>
|
||||
<!-- /.navbar-header -->
|
||||
|
||||
<ul class="nav navbar-top-links navbar-right">
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-globe fa-fw"></i> <i class="fa fa-caret-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-language">
|
||||
<li>
|
||||
<a href="#lang-en" onclick="window.lang.change('en'); return false;"><span lang="en" class="flag-icon flag-icon-gb" data-lang-token="general_speech_en">  English</span></a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#lang-de" onclick="window.lang.change('de'); return false;"><span lang="en" class="flag-icon flag-icon-de" data-lang-token="general_speech_de">  German</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- /.dropdown-language -->
|
||||
</li>
|
||||
<!-- /.dropdown -->
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-tasks fa-fw"></i> <i class="fa fa-caret-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-tasks">
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<p>
|
||||
<strong>Task 1</strong>
|
||||
<span class="pull-right text-muted">40% Complete</span>
|
||||
</p>
|
||||
<div class="progress progress-striped active">
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: 40%">
|
||||
<span class="sr-only">40% Complete (success)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<p>
|
||||
<strong>Task 2</strong>
|
||||
<span class="pull-right text-muted">20% Complete</span>
|
||||
</p>
|
||||
<div class="progress progress-striped active">
|
||||
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100" style="width: 20%">
|
||||
<span class="sr-only">20% Complete</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<p>
|
||||
<strong>Task 3</strong>
|
||||
<span class="pull-right text-muted">60% Complete</span>
|
||||
</p>
|
||||
<div class="progress progress-striped active">
|
||||
<div class="progress-bar progress-bar-warning" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%">
|
||||
<span class="sr-only">60% Complete (warning)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<p>
|
||||
<strong>Task 4</strong>
|
||||
<span class="pull-right text-muted">80% Complete</span>
|
||||
</p>
|
||||
<div class="progress progress-striped active">
|
||||
<div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="80" aria-valuemin="0" aria-valuemax="100" style="width: 80%">
|
||||
<span class="sr-only">80% Complete (danger)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a class="text-center" href="#">
|
||||
<strong>See All Tasks</strong>
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- /.dropdown-tasks -->
|
||||
</li>
|
||||
<!-- /.dropdown -->
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-bell fa-fw"></i> <i class="fa fa-caret-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-alerts">
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<i class="fa fa-comment fa-fw"></i> New Comment
|
||||
<span class="pull-right text-muted small">4 minutes ago</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<i class="fa fa-twitter fa-fw"></i> 3 New Followers
|
||||
<span class="pull-right text-muted small">12 minutes ago</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<i class="fa fa-envelope fa-fw"></i> Message Sent
|
||||
<span class="pull-right text-muted small">4 minutes ago</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<i class="fa fa-tasks fa-fw"></i> New Task
|
||||
<span class="pull-right text-muted small">4 minutes ago</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<i class="fa fa-upload fa-fw"></i> Server Rebooted
|
||||
<span class="pull-right text-muted small">4 minutes ago</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a class="text-center" href="#">
|
||||
<strong>See All Alerts</strong>
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- /.dropdown-alerts -->
|
||||
</li>
|
||||
<!-- /.dropdown -->
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-user fa-fw"></i> <i class="fa fa-caret-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
<li><a href="#"><i class="fa fa-user fa-fw"></i>User Profile</a>
|
||||
</li>
|
||||
<li><a href="#"><i class="fa fa-gear fa-fw"></i>Settings</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="login.html"><i class="fa fa-sign-out fa-fw"></i>Logout</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- /.dropdown-user -->
|
||||
</li>
|
||||
<!-- /.dropdown -->
|
||||
</ul>
|
||||
<!-- /.navbar-top-links -->
|
||||
|
||||
<div class="navbar-default sidebar" role="navigation">
|
||||
<div class="sidebar-nav navbar-collapse">
|
||||
<ul class="nav" id="side-menu">
|
||||
<li class="sidebar-search">
|
||||
<div class="input-group custom-search-form">
|
||||
<input type="text" class="form-control" placeholder="Search...">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<!-- /input-group -->
|
||||
</li>
|
||||
<li>
|
||||
<a class="active" href="index.html"><i class="fa fa-dashboard fa-fw"></i><span lang="en" data-lang-token="main_menu_dashboard_token">Dashboard</span></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="inactive" href="#"><i class="fa fa-cog fa-fw"></i><span lang="en" data-lang-token="main_menu_configuration_token">Configuration</span><span class="fa arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li>
|
||||
<a class="inactive" href="#" id="load_confGeneral"><i class="fa fa-play-circle-o fa-fw"></i><span lang="en" data-lang-token="main_menu_general_conf_token">General</span></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="inactive" href="#" id="load_confKodi"><i class="fa fa-play-circle-o fa-fw"></i><span lang="en" data-lang-token="main_menu_kodiwatch_token">Kodi Watch</span></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="inactive" href="#" id="load_huebridge"><i class="fa fa-cog fa-fw"></i><span lang="en" data-lang-token="main_menu_huebridge_token">Hue Bridge</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a class="inactive" href="#"><i class="fa fa-lightbulb-o fa-fw"></i><span lang="en" data-lang-token="main_menu_remotecontrol_token">Remote Control</span><span class="fa arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li>
|
||||
<a class="inactive" href="#" id="load_lighttest"><i class="fa fa-lightbulb-o fa-fw"></i><span lang="en" data-lang-token="main_menu_colors_token">Colors</span></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="inactive" href="#" id="load_effects"><i class="fa fa-certificate fa-fw"></i><span lang="en" data-lang-token="main_menu_effects_token">Effects</span></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="inactive" href="#" id="load_components"><i class="fa fa-list fa-fw"></i><span lang="en" data-lang-token="main_menu_component_token">Components</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a class="inactive" href="#" id="load_support"><i class="fa fa-info fa-fw"></i><span lang="en" data-lang-token="main_menu_support_token">Support</span></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="inactive" href="#"><i class="fa fa-cog fa-fw"></i><span lang="en" data-lang-token="main_menu_system_token">System</span><span class="fa arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li>
|
||||
<a class="inactive" href="#" id="load_update"><i class="fa fa-download fa-fw"></i><span lang="en" data-lang-token="main_menu_update_token">Update</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<!-- /.sidebar-collapse -->
|
||||
</div>
|
||||
<!-- /.navbar-static-side -->
|
||||
</nav>
|
||||
|
||||
<!-- Page Content -->
|
||||
<div id="page-wrapper">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header">Dashboard</h1>
|
||||
<div class="introd">
|
||||
<h4 lang="en" data-lang-token="dashboard_label_intro">The dashboard give you a quick overview about the status of Hyperion and show you the latest news of the Hyperion Blog.</h4>
|
||||
</div>
|
||||
<hr>
|
||||
<button type="button" class="btn btn-info" data-toggle="modal" data-target="#myModal">Change JSON port</button>
|
||||
<hr>
|
||||
<div class="col-lg-4">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-info-circle fa-fw"></i>
|
||||
<span lang="en" data-lang-token="dashboard_label_infobox_title">Information</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td lang="en" data-lang-token="dashboard_label_infobox_currenthyp">Your Hyperion version:</td>
|
||||
<td id="currentversion">unknown</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td lang="en" data-lang-token="dashboard_label_infobox_latesthyp">Latest version:</td>
|
||||
<td id="latestversion">unknown</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td lang="en" data-lang-token="dashboard_label_infobox_leddevice">LED type:</td>
|
||||
<td id="dash_leddevice">unknown</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td lang="en" data-lang-token="dashboard_label_infobox_device">Device:</td>
|
||||
<td id="dash_systeminfo"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr>
|
||||
<span id="versioninforesult"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-eye fa-fw"></i>
|
||||
<span lang="en" data-lang-token="dashboard_label_componentbox_title">Components status</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Component</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Kodi Watch</td>
|
||||
<td><i class="fa fa-circle component-on"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Blackborder</td>
|
||||
<td><i class="fa fa-circle component-off"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Booteffect</td>
|
||||
<td><i class="fa fa-circle component-off"></i></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-newspaper-o fa-fw"></i>
|
||||
<span lang="en" data-lang-token="dashboard_label_newsbox_title">Latest blog posts</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- /.col-lg-12 -->
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
</div>
|
||||
<!-- /.container-fluid -->
|
||||
</div>
|
||||
<!-- /#page-wrapper -->
|
||||
|
||||
</div>
|
||||
<!-- /#wrapper -->
|
||||
|
||||
<!-- Modal -->
|
||||
<div id="myModal" 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">×</button>
|
||||
<h4 class="modal-title">Modal Test and port changer</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Input the JSON port you want to connect and press reload</p>
|
||||
<form class="form-inline">
|
||||
<div class="form-group">
|
||||
<label for="port">Your JSON Port:</label>
|
||||
<input type="number" min="100" max="65535" value="19444" class="form-control" id="json_port">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" onclick="button_reloaddata()" class="btn btn-primary" data-dismiss="modal">Reload!</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.navbar-header -->
|
||||
|
||||
<div id="con_error_modal" class="modal fade" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<!-- Modal content-->
|
||||
<div class="modal-content" id="con_error_modal">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Oh noes! Something went wrong!</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>We are sorry, the json port was not found. Just try another one!</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Okay!</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="nav navbar-top-links navbar-right">
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-globe fa-fw"></i> <i class="fa fa-caret-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-language">
|
||||
<li>
|
||||
<a href="#lang-en" onclick="window.lang.change('en'); return false;"><span lang="en" class="flag-icon flag-icon-gb" data-lang-token="general_speech_en">  English</span></a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#lang-de" onclick="window.lang.change('de'); return false;"><span lang="en" class="flag-icon flag-icon-de" data-lang-token="general_speech_de">  German</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- /.dropdown-language -->
|
||||
</li>
|
||||
<!-- /.dropdown -->
|
||||
</li>
|
||||
<!-- /.dropdown -->
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-bell fa-fw"></i> <i class="fa fa-caret-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-alerts">
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<i class="fa fa-comment fa-fw"></i> New Comment
|
||||
<span class="pull-right text-muted small">4 minutes ago</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<i class="fa fa-twitter fa-fw"></i> 3 New Followers
|
||||
<span class="pull-right text-muted small">12 minutes ago</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<i class="fa fa-envelope fa-fw"></i> Message Sent
|
||||
<span class="pull-right text-muted small">4 minutes ago</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<i class="fa fa-tasks fa-fw"></i> New Task
|
||||
<span class="pull-right text-muted small">4 minutes ago</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<div>
|
||||
<i class="fa fa-upload fa-fw"></i> Server Rebooted
|
||||
<span class="pull-right text-muted small">4 minutes ago</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a class="text-center" href="#">
|
||||
<strong>See All Alerts</strong>
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- /.dropdown-alerts -->
|
||||
</li>
|
||||
<!-- /.dropdown -->
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-user fa-fw"></i> <i class="fa fa-caret-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
<li><a href="#"><i class="fa fa-user fa-fw"></i>User Profile</a>
|
||||
</li>
|
||||
<li><a href="#"><i class="fa fa-gear fa-fw"></i>Settings</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="login.html"><i class="fa fa-sign-out fa-fw"></i>Logout</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- /.dropdown-user -->
|
||||
</li>
|
||||
<!-- /.dropdown -->
|
||||
</ul>
|
||||
<!-- /.navbar-top-left -->
|
||||
|
||||
<!-- Bootstrap Core JavaScript -->
|
||||
<script src="js/lib/bootstrap.min.js"></script>
|
||||
<div class="navbar-default sidebar" role="navigation">
|
||||
<div class="sidebar-nav navbar-collapse">
|
||||
<ul class="nav" id="side-menu">
|
||||
<li> <a class="active" id="load_dashboard"><i class="fa fa-dashboard fa-fw"></i><span lang="en" data-lang-token="main_menu_dashboard_token">Dashboard</span></a> </li>
|
||||
<li>
|
||||
<a class="inactive"><i class="fa fa-cog fa-fw"></i><span lang="en" data-lang-token="main_menu_configuration_token">Configuration</span><span class="fa arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li> <a class="inactive" id="load_confGeneral"><i class="fa fa-play-circle-o fa-fw"></i><span lang="en" data-lang-token="main_menu_general_conf_token">General</span></a> </li>
|
||||
<li> <a class="inactive" id="load_confKodi"><i class="fa fa-play-circle-o fa-fw"></i><span lang="en" data-lang-token="main_menu_kodiwatch_token">Kodi Watch</span></a> </li>
|
||||
<li> <a class="inactive" id="load_huebridge"><i class="fa fa-cog fa-fw"></i><span lang="en" data-lang-token="main_menu_huebridge_token">Hue Bridge</span></a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a class="inactive" href="#"><i class="fa fa-lightbulb-o fa-fw"></i><span lang="en" data-lang-token="main_menu_remotecontrol_token">Remote Control</span><span class="fa arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li> <a class="inactive" id="load_lighttest"><i class="fa fa-lightbulb-o fa-fw"></i><span lang="en" data-lang-token="main_menu_colors_token">Colors</span></a> </li>
|
||||
<li> <a class="inactive" id="load_effects"><i class="fa fa-certificate fa-fw"></i><span lang="en" data-lang-token="main_menu_effects_token">Effects</span></a> </li>
|
||||
<li> <a class="inactive" id="load_components"><i class="fa fa-list fa-fw"></i><span lang="en" data-lang-token="main_menu_component_token">Components</span></a> </li>
|
||||
<li> <a class="inactive" id="load_input_selection"><i class="fa fa-random fa-fw"></i><span lang="en" data-lang-token="main_menu_input_selection_token">Input Selection</span></a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
<li> <a class="inactive" id="load_support"><i class="fa fa-info fa-fw"></i><span lang="en" data-lang-token="main_menu_support_token">Support</span></a> </li>
|
||||
<li>
|
||||
<a class="inactive"><i class="fa fa-cog fa-fw"></i><span lang="en" data-lang-token="main_menu_system_token">System</span><span class="fa arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li> <a class="inactive" id="load_update"><i class="fa fa-download fa-fw"></i><span lang="en" data-lang-token="main_menu_update_token">Update</span></a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- /.sidebar-collapse -->
|
||||
</div>
|
||||
<!-- /.navbar-static-side -->
|
||||
</nav>
|
||||
|
||||
<!-- Metis Menu Plugin JavaScript -->
|
||||
<script src="js/lib/metisMenu.min.js"></script>
|
||||
<!-- Page Content -->
|
||||
<div id="page-wrapper" />
|
||||
|
||||
<!-- Custom Theme JavaScript -->
|
||||
<script src="js/lib/sb-admin-2.js"></script>
|
||||
</div>
|
||||
<!-- /#wrapper -->
|
||||
|
||||
<div id="error_dialog" 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">×</button>
|
||||
<h4 class="modal-title" />
|
||||
</div>
|
||||
<div class="modal-body" />
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Okay!</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bootstrap Core JavaScript -->
|
||||
<script src="js/lib/bootstrap.min.js"></script>
|
||||
|
||||
<!-- Metis Menu Plugin JavaScript -->
|
||||
<script src="js/lib/metisMenu.min.js"></script>
|
||||
|
||||
<!-- Custom Theme JavaScript -->
|
||||
<script src="js/lib/sb-admin-2.js"></script>
|
||||
<script>
|
||||
$(document).ready( function() {
|
||||
$("#load_lighttest").on("click", function() {
|
||||
$("#page-wrapper").load("lighttest.html");
|
||||
});
|
||||
$("#load_effects").on("click", function() {
|
||||
$("#page-wrapper").load("effects.html");
|
||||
initWebSocket();
|
||||
bindNavToContent("#load_dashboard","dashboard",true);
|
||||
bindNavToContent("#load_lighttest","lighttest");
|
||||
bindNavToContent("#load_effects","effects");
|
||||
bindNavToContent("#load_components","remote_components");
|
||||
bindNavToContent("#load_input_selection","input_selection");
|
||||
bindNavToContent("#load_huebridge","huebridge");
|
||||
bindNavToContent("#load_support","support");
|
||||
bindNavToContent("#load_confKodi","kodiconf");
|
||||
bindNavToContent("#load_update","update");
|
||||
bindNavToContent("#load_confGeneral","generalconf");
|
||||
|
||||
//Change all Checkboxes to Switches
|
||||
$("[type='checkbox']").bootstrapSwitch();
|
||||
|
||||
$(hyperion).on("open",function(event){
|
||||
requestServerInfo();
|
||||
});
|
||||
|
||||
$("#load_components").on("click", function() {
|
||||
$("#page-wrapper").load("remote_components.html");
|
||||
});
|
||||
$("#load_huebridge").on("click", function() {
|
||||
$("#page-wrapper").load("huebridge.html");
|
||||
});
|
||||
$("#load_support").on("click", function() {
|
||||
$("#page-wrapper").load("support.html");
|
||||
});
|
||||
$("#load_confKodi").on("click", function() {
|
||||
$("#page-wrapper").load("kodiconf.html");
|
||||
});
|
||||
$("#load_update").on("click", function() {
|
||||
$("#page-wrapper").load("update.html");
|
||||
});
|
||||
$("#load_confGeneral").on("click", function() {
|
||||
$("#page-wrapper").load("generalconf.html");
|
||||
});
|
||||
//Change all Checkboxes to Switches
|
||||
$("[type='checkbox']").bootstrapSwitch();
|
||||
loaddata();
|
||||
$(hyperion).on("cmd-serverinfo",function(event){
|
||||
parsedServerInfoJSON = event.response;
|
||||
currentVersion = parsedServerInfoJSON.info.hyperion[0].version;
|
||||
cleanCurrentVersion = currentVersion.replace(/\./g, '');
|
||||
// get active led device
|
||||
var leddevice = parsedServerInfoJSON.info.ledDevices.active;
|
||||
$('#dash_leddevice').html(leddevice);
|
||||
// get host
|
||||
var hostname = parsedServerInfoJSON.info.hostname;
|
||||
$('#dash_systeminfo').html(hostname+':'+hyperionport);
|
||||
|
||||
});
|
||||
$(function(){
|
||||
var sidebar = $('#side-menu'); // cache sidebar to a variable for performance
|
||||
sidebar.delegate('a.inactive','click',function(){
|
||||
sidebar.find('.active').toggleClass('active inactive');
|
||||
$(this).toggleClass('active inactive');
|
||||
$.get( "https://raw.githubusercontent.com/hyperion-project/hyperion.ng/master/version.json", function( data ) {
|
||||
parsedUpdateJSON = JSON.parse(data);
|
||||
latestVersion = parsedUpdateJSON[0].versionnr;
|
||||
cleanLatestVersion = latestVersion.replace(/\./g, '');
|
||||
|
||||
$('#currentversion').html(' V'+currentVersion);
|
||||
$('#latestversion').html(' V'+latestVersion);
|
||||
|
||||
if ( cleanCurrentVersion < cleanLatestVersion )
|
||||
{
|
||||
$('#versioninforesult').html('<div lang="en" data-lang-token="dashboard_message_infobox_updatewarning" style="margin:0px;" class="alert alert-warning">A newer version of Hyperion is available!</div>');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#versioninforesult').html('<div lang="en" data-lang-token="dashboard_message_infobox_updatesuccess" style="margin:0px;" class="alert alert-success">You run the latest version of Hyperion.</div>');
|
||||
}
|
||||
});
|
||||
}); // end cmd-serverinfo
|
||||
|
||||
$(hyperion).on("error",function(event){
|
||||
$('#error_dialog .modal-title').html("error");
|
||||
$('#error_dialog .modal-body').html(event.reason);
|
||||
$('#error_dialog').modal('show');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$(function(){
|
||||
var sidebar = $('#side-menu'); // cache sidebar to a variable for performance
|
||||
sidebar.delegate('a.inactive','click',function(){
|
||||
sidebar.find('.active').toggleClass('active inactive');
|
||||
$(this).toggleClass('active inactive');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
@ -30,50 +30,130 @@ var parsedServerInfoJSON;
|
||||
var parsedUpdateJSON;
|
||||
var parsedConfSchemaJSON;
|
||||
var hyperionport = 19444;
|
||||
var websocket = null;
|
||||
var hyperion = {};
|
||||
var wsTan = 1;
|
||||
var cronId = 0;
|
||||
|
||||
function button_reloaddata(){
|
||||
hyperionport = $("#json_port").val();
|
||||
loaddata();
|
||||
};
|
||||
//
|
||||
function cron()
|
||||
{
|
||||
requestServerInfo();
|
||||
}
|
||||
|
||||
function loaddata() {
|
||||
// init websocket to hyperion and bind socket events to jquery events of $(hyperion) object
|
||||
function initWebSocket()
|
||||
{
|
||||
if ("WebSocket" in window)
|
||||
{
|
||||
if (websocket == null)
|
||||
{
|
||||
$.ajax({ url: "/cgi/cfg_jsonserver" }).done(function(data) {
|
||||
hyperionport = data.substr(1);
|
||||
websocket = new WebSocket('ws://'+document.location.hostname+data);
|
||||
|
||||
webSocket = new WebSocket('ws://'+document.location.hostname+':'+hyperionport);
|
||||
websocket.onopen = function (event) {
|
||||
$(hyperion).trigger({type:"open"});
|
||||
cronId = window.setInterval(cron,3000);
|
||||
};
|
||||
|
||||
webSocket.onerror = function(event) {
|
||||
$('#con_error_modal').modal('show');
|
||||
};
|
||||
|
||||
webSocket.onopen = function(event) {
|
||||
webSocket.send('{"command":"serverinfo"}');
|
||||
};
|
||||
|
||||
webSocket.onmessage = function(response){
|
||||
parsedServerInfoJSON = JSON.parse(response.data );
|
||||
currentVersion = parsedServerInfoJSON.info.hyperion[0].version;
|
||||
cleanCurrentVersion = currentVersion.replace(/\./g, '');
|
||||
// get active led device
|
||||
var leddevice = parsedServerInfoJSON.info.ledDevices.active;
|
||||
$('#dash_leddevice').html(leddevice);
|
||||
// get host
|
||||
var hostname = parsedServerInfoJSON.info.hostname;
|
||||
$('#dash_systeminfo').html(hostname+':'+hyperionport);
|
||||
|
||||
$.get( "https://raw.githubusercontent.com/hyperion-project/hyperion.ng/master/version.json", function( data ) {
|
||||
parsedUpdateJSON = JSON.parse(data);
|
||||
latestVersion = parsedUpdateJSON[0].versionnr;
|
||||
cleanLatestVersion = latestVersion.replace(/\./g, '');
|
||||
|
||||
$('#currentversion').html(' V'+currentVersion);
|
||||
$('#latestversion').html(' V'+latestVersion);
|
||||
|
||||
if ( cleanCurrentVersion < cleanLatestVersion ) {
|
||||
$('#versioninforesult').html('<div lang="en" data-lang-token="dashboard_message_infobox_updatewarning" style="margin:0px;" class="alert alert-warning">A newer version of Hyperion is available!</div>');
|
||||
websocket.onclose = function (event) {
|
||||
// See http://tools.ietf.org/html/rfc6455#section-7.4.1
|
||||
var reason;
|
||||
switch(event.code)
|
||||
{
|
||||
case 1000: reason = "Normal closure, meaning that the purpose for which the connection was established has been fulfilled."; break;
|
||||
case 1001: reason = "An endpoint is \"going away\", such as a server going down or a browser having navigated away from a page."; break;
|
||||
case 1002: reason = "An endpoint is terminating the connection due to a protocol error"; break;
|
||||
case 1003: reason = "An endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands only text data MAY send this if it receives a binary message)."; break;
|
||||
case 1004: reason = "Reserved. The specific meaning might be defined in the future."; break;
|
||||
case 1005: reason = "No status code was actually present."; break;
|
||||
case 1006: reason = "The connection was closed abnormally, e.g., without sending or receiving a Close control frame"; break;
|
||||
case 1007: reason = "An endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 [http://tools.ietf.org/html/rfc3629] data within a text message)."; break;
|
||||
case 1008: reason = "An endpoint is terminating the connection because it has received a message that \"violates its policy\". This reason is given either if there is no other sutible reason, or if there is a need to hide specific details about the policy."; break;
|
||||
case 1009: reason = "An endpoint is terminating the connection because it has received a message that is too big for it to process."; break;
|
||||
case 1010: reason = "An endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake. <br /> Specifically, the extensions that are needed are: " + event.reason; break;
|
||||
case 1011: reason = "A server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request."; break;
|
||||
case 1015: reason = "The connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified)."; break;
|
||||
default: reason = "Unknown reason";
|
||||
}
|
||||
else{
|
||||
$('#versioninforesult').html('<div lang="en" data-lang-token="dashboard_message_infobox_updatesuccess" style="margin:0px;" class="alert alert-success">You run the latest version of Hyperion.</div>');
|
||||
$(hyperion).trigger({type:"close", reason:reason});
|
||||
};
|
||||
|
||||
websocket.onmessage = function (event) {
|
||||
try
|
||||
{
|
||||
response = JSON.parse(event.data);
|
||||
success = response.success;
|
||||
cmd = response.command;
|
||||
if (success)
|
||||
{
|
||||
$(hyperion).trigger({type:"cmd-"+cmd, response:response});
|
||||
}
|
||||
else
|
||||
{
|
||||
error = response.hasOwnProperty("error")? response.error : "unknown";
|
||||
$(hyperion).trigger({type:"error",reason:error});
|
||||
console.log("[websocket::onmessage] "+error)
|
||||
}
|
||||
}
|
||||
catch(exception_error)
|
||||
{
|
||||
$(hyperion).trigger({type:"error",reason:exception_error});
|
||||
console.log("[websocket::onmessage] "+exception_error)
|
||||
}
|
||||
};
|
||||
|
||||
websocket.onerror = function (error) {
|
||||
$(hyperion).trigger({type:"error",reason:error});
|
||||
console.log("[websocket::onerror] "+error)
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$(hyperion).trigger("error");
|
||||
alert("Websocket is not supported by your browser");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// wrapped server commands
|
||||
|
||||
function requestServerInfo() {
|
||||
websocket.send('{"command":"serverinfo", "tan":'+wsTan+'}');
|
||||
}
|
||||
|
||||
function requestServerConfigSchema() {
|
||||
websocket.send('{"command":"config", "tan":'+wsTan+',"subcommand":"getschema"}');
|
||||
}
|
||||
|
||||
function requestPriorityClear() {
|
||||
websocket.send('{"command":"clear", "tan":'+wsTan+', "priority":1}');
|
||||
}
|
||||
|
||||
function requestPlayEffect(effectName) {
|
||||
websocket.send('{"command":"effect", "tan":'+wsTan+',"effect":{"name":"'+effectName+'"},"priority":1}');
|
||||
}
|
||||
|
||||
function requestSetColor(r,g,b) {
|
||||
websocket.send('{"command":"color", "tan":'+wsTan+', "color":['+r+','+g+','+b+'], "priority":1}');
|
||||
}
|
||||
|
||||
|
||||
function requestSetComponentState(comp, state){
|
||||
state_str = state?"true":"false";
|
||||
websocket.send('{"command":"componentstate", "tan":'+wsTan+',"componentstate":{"component":"'+comp+'","state":'+state_str+'}}');
|
||||
console.log(comp+' state: '+state_str);
|
||||
}
|
||||
|
||||
function requestSetSource( prio )
|
||||
{
|
||||
if ( prio == "auto" )
|
||||
websocket.send('{"command":"sourceselect", "tan":'+wsTan+', "auto" : true}');
|
||||
else
|
||||
websocket.send('{"command":"sourceselect", "tan":'+wsTan+', "priority" : '+prio+'}');
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
12
assets/webconfig/js/ui_utils.js
Normal file
12
assets/webconfig/js/ui_utils.js
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
function bindNavToContent(containerId, fileName, loadNow=false)
|
||||
{
|
||||
$("#page-wrapper").off();
|
||||
$(containerId).on("click", function() {
|
||||
$("#page-wrapper").load("/content/"+fileName+".html");
|
||||
});
|
||||
if (loadNow)
|
||||
{
|
||||
$("#page-wrapper").load("/content/"+fileName+".html");
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header" lang="en" data-lang-token="main_menu_component_token">Effects</h1>
|
||||
<div class="introd">
|
||||
<h4 lang="en" data-lang-token="remote_components_intro">The components remote enables you to disable and enable certain components of Hyperion during runtime. Keep in mind this persist just until the next reboot! To enable/disable components permament, use the configuration section.</h4>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="col-lg-12" id="componentsbutton">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
new Enum('SMOOTHING', 'BLACKBORDER', 'KODICHECKER', 'FORWARDER', 'UDPLISTENER', 'BOBLIGHT_SERVER','GRABBER');
|
||||
|
||||
function Enum() {
|
||||
for (var i in arguments) {
|
||||
this[arguments[i]] = i;
|
||||
$('#componentsbutton').append('<button type="button" class="btn btn-success" onclick="compenable(\''+arguments[i]+'\')"><i class="fa fa-play"></i></button> '+arguments[i]+'<br />');
|
||||
$('#componentsbutton').append('<button type="button" class="btn btn-danger" onclick="compdisable(\''+arguments[i]+'\')"><i class="fa fa-play"></i></button> '+arguments[i]+'<br />');
|
||||
}
|
||||
}
|
||||
|
||||
function compenable(comp){
|
||||
|
||||
webSocket.send('{"command":"componentstate","componentstate":{"component":"'+comp+'","state":true}}');
|
||||
console.log('enable: '+comp);
|
||||
|
||||
}
|
||||
function compdisable(comp){
|
||||
|
||||
webSocket.send('{"command":"componentstate","componentstate":{"component":"'+comp+'","state":false}}');
|
||||
console.log('disable: '+comp);
|
||||
|
||||
}
|
||||
|
||||
</script>
|
@ -1,98 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>Hyperion web control</title>
|
||||
|
||||
<!-- bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
|
||||
<!-- Optional theme -->
|
||||
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> -->
|
||||
<link href="starter-template.css" rel="stylesheet">
|
||||
|
||||
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<!-- <span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>-->
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Hyperion</a>
|
||||
</div>
|
||||
<div id="navbar" class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="#">Source Selection</a></li>
|
||||
<!-- <li><a href="#about">About</a></li> -->
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<div class="starter-template">
|
||||
<div id="inputs"></div>
|
||||
</div>
|
||||
</div><!-- /.container -->
|
||||
|
||||
|
||||
<!-- ====================================================================== -->
|
||||
<script>
|
||||
var webSocket = new WebSocket('ws://'+document.location.hostname+':19444');
|
||||
var serverInfo;
|
||||
|
||||
function setSource( prio )
|
||||
{
|
||||
if ( prio == "auto" )
|
||||
webSocket.send('{"command":"sourceselect", "auto" : true}');
|
||||
else
|
||||
webSocket.send('{"command":"sourceselect", "priority" : '+prio+'}');
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
function updateButtons()
|
||||
{
|
||||
webSocket.send('{"command":"serverinfo"}');
|
||||
}
|
||||
|
||||
webSocket.onerror = function(event) {
|
||||
alert(event.data);
|
||||
};
|
||||
|
||||
webSocket.onopen = function(event) {
|
||||
updateButtons();
|
||||
setInterval(function() {updateButtons();}, 3000);
|
||||
};
|
||||
|
||||
webSocket.onmessage = function(event) {
|
||||
serverInfo = JSON.parse( event.data );
|
||||
var data = "";
|
||||
var i;
|
||||
for(i = 0; i < serverInfo.info.priorities.length; i++) {
|
||||
var owner = serverInfo.info.priorities[i].owner;
|
||||
var active = serverInfo.info.priorities[i].active;
|
||||
var visible = serverInfo.info.priorities[i].visible;
|
||||
var priority = serverInfo.info.priorities[i].priority;
|
||||
var btn_type = "default";
|
||||
if (active) btn_type = "warning";
|
||||
if (visible) btn_type = "success";
|
||||
|
||||
data += '<button id="srcBtn'+i+'" type="button" class="btn btn-lg btn-'+btn_type+'" style="margin:10px;min-width:200px" title="prio '+priority+'" onclick="setSource('+priority+');">'+owner+'</button><br/>';
|
||||
}
|
||||
data += '<button id="srcBtn'+i+'" type="button" class="btn btn-lg btn-info" style="margin:10px;min-width:200px" onclick="setSource(\'auto\');">auto select</button><br/>';
|
||||
$('#inputs').html(data);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,8 +0,0 @@
|
||||
body {
|
||||
padding-top: 50px;
|
||||
}
|
||||
.starter-template {
|
||||
padding: 40px 15px;
|
||||
text-align: center;
|
||||
}
|
||||
|
5
assets/webconfig/server_scripts/demo.py
Normal file
5
assets/webconfig/server_scripts/demo.py
Normal file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
print ("hello world");
|
||||
|
||||
|
5
assets/webconfig/server_scripts/demo.sh
Normal file
5
assets/webconfig/server_scripts/demo.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "hello world"
|
||||
pwd
|
||||
|
@ -1,26 +0,0 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header" lang="en" data-lang-token="main_menu_update_token">Update</h1>
|
||||
<div class="introd">
|
||||
<h4 lang="en" data-lang-token="update_label_intro">This page gives you an overview of all Hyperion versions available. On top you could update or downgrade your version of Hyperion whenever you want. Sorted from newest to oldest</h4>
|
||||
</div>
|
||||
<hr>
|
||||
<h4 id="update_currver"></h4>
|
||||
<hr>
|
||||
<div class="col-lg-12" id="versionlist">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
for (key in parsedUpdateJSON)
|
||||
{
|
||||
$('#versionlist').append('<div class="col-lg-6"><div class="panel panel-default"><div class="panel-heading"><i class="fa fa-television fa-fw"></i>Hyperion V'+parsedUpdateJSON[key].versionnr+'</div><div class="panel-body"><p><span style="font-weight:bold;" lang="en" data-lang-token="update_label_type">Type:</span> '+ parsedUpdateJSON[key].channel +'</p><p><span style="font-weight:bold;" lang="en" data-lang-token="update_label_description">Description:</span> '+parsedUpdateJSON[key].versiondesc+'</p><hr><a class="btn btn-primary" href="'+ parsedUpdateJSON[key].versionchangelog +'" target="_blank"><i class="fa fa-list fa-fw"></i><span style="font-weight:bold;" lang="en" data-lang-token="update_button_changelog">Full changelog</span></a><button type="button" class="btn btn-warning pull-right"><i class="fa fa-download fa-fw"></i><span lang="en" data-lang-token="update_button_install">Install</span></button></div></div></div>');
|
||||
}
|
||||
$('#update_currver').append(currentVersion);
|
||||
|
||||
|
||||
</script>
|
8
include/utils/FileUtils.h
Normal file
8
include/utils/FileUtils.h
Normal file
@ -0,0 +1,8 @@
|
||||
#include <string>
|
||||
|
||||
namespace FileUtils {
|
||||
|
||||
std::string getBaseName( std::string sourceFile);
|
||||
std::string command_exec(const char* cmd);
|
||||
|
||||
};
|
@ -12,6 +12,7 @@
|
||||
|
||||
// hyperion util includes
|
||||
#include <utils/jsonschema/JsonSchemaChecker.h>
|
||||
#include <utils/FileUtils.h>
|
||||
|
||||
// effect engine includes
|
||||
#include <effectengine/EffectEngine.h>
|
||||
@ -181,7 +182,7 @@ int EffectEngine::runEffectScript(const std::string &script, const Json::Value &
|
||||
_activeEffects.push_back(effect);
|
||||
|
||||
// start the effect
|
||||
_hyperion->registerPriority("EFFECT: "+script, priority);
|
||||
_hyperion->registerPriority("EFFECT: "+FileUtils::getBaseName(script), priority);
|
||||
effect->start();
|
||||
|
||||
return 0;
|
||||
|
@ -684,6 +684,30 @@
|
||||
"maximum" : 1.0,
|
||||
"default" : 0.05
|
||||
},
|
||||
"unknownFrameCnt" :
|
||||
{
|
||||
"type" : "number",
|
||||
"minimum" : 0,
|
||||
"advanced" : true
|
||||
},
|
||||
"borderFrameCnt" :
|
||||
{
|
||||
"type" : "number",
|
||||
"minimum" : 0,
|
||||
"advanced" : true
|
||||
},
|
||||
"maxInconsistentCnt" :
|
||||
{
|
||||
"type" : "number",
|
||||
"minimum" : 0,
|
||||
"advanced" : true
|
||||
},
|
||||
"blurRemoveCnt" :
|
||||
{
|
||||
"type" : "number",
|
||||
"minimum" : 0,
|
||||
"advanced" : true
|
||||
},
|
||||
"mode" :
|
||||
{
|
||||
"type" : "string",
|
||||
|
@ -852,21 +852,22 @@ void JsonClientConnection::handleSourceSelectCommand(const Json::Value & message
|
||||
void JsonClientConnection::handleConfigCommand(const Json::Value & message, const std::string &command, const int tan)
|
||||
{
|
||||
std::string subcommand = message.get("subcommand","").asString();
|
||||
std::string full_command = command + "-" + subcommand;
|
||||
if (subcommand == "getschema")
|
||||
{
|
||||
handleSchemaGetCommand(message, command, tan);
|
||||
handleSchemaGetCommand(message, full_command, tan);
|
||||
}
|
||||
else if (subcommand == "getconfig")
|
||||
{
|
||||
handleConfigGetCommand(message, command, tan);
|
||||
handleConfigGetCommand(message, full_command, tan);
|
||||
}
|
||||
else if (subcommand == "setconfig")
|
||||
{
|
||||
handleConfigSetCommand(message, command, tan);
|
||||
handleConfigSetCommand(message, full_command, tan);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendErrorReply("unknown or missing subcommand", command, tan);
|
||||
sendErrorReply("unknown or missing subcommand", full_command, tan);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@ add_library(hyperion-utils
|
||||
${CURRENT_SOURCE_DIR}/ColorRgbw.cpp
|
||||
${CURRENT_HEADER_DIR}/Image.h
|
||||
${CURRENT_HEADER_DIR}/Sleep.h
|
||||
${CURRENT_HEADER_DIR}/FileUtils.h
|
||||
${CURRENT_SOURCE_DIR}/FileUtils.cpp
|
||||
|
||||
${CURRENT_HEADER_DIR}/Logger.h
|
||||
${CURRENT_SOURCE_DIR}/Logger.cpp
|
||||
|
35
libsrc/utils/FileUtils.cpp
Normal file
35
libsrc/utils/FileUtils.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include <utils/FileUtils.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
namespace FileUtils {
|
||||
|
||||
std::string getBaseName( std::string sourceFile)
|
||||
{
|
||||
QFileInfo fi( sourceFile.c_str() );
|
||||
return fi.fileName().toStdString();
|
||||
}
|
||||
|
||||
std::string command_exec(const char* cmd)
|
||||
{
|
||||
char buffer[128];
|
||||
std::string result = "";
|
||||
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
|
||||
if (pipe)
|
||||
{
|
||||
while (!feof(pipe.get()))
|
||||
{
|
||||
if (fgets(buffer, 128, pipe.get()) != NULL)
|
||||
result += buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
@ -1,4 +1,5 @@
|
||||
#include "utils/Logger.h"
|
||||
#include <utils/Logger.h>
|
||||
#include <utils/FileUtils.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
@ -7,11 +8,6 @@
|
||||
#include <QFileInfo>
|
||||
#include <QString>
|
||||
|
||||
std::string getBaseName( std::string sourceFile)
|
||||
{
|
||||
QFileInfo fi( sourceFile.c_str() );
|
||||
return fi.fileName().toStdString();
|
||||
}
|
||||
|
||||
static const char * LogLevelStrings[] = { "", "DEBUG", "INFO", "WARNING", "ERROR" };
|
||||
static const int LogLevelSysLog[] = { LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR };
|
||||
@ -134,7 +130,7 @@ void Logger::Message(LogLevel level, const char* sourceFile, const char* func, u
|
||||
std::string function(func);
|
||||
if ( level == Logger::DEBUG )
|
||||
{
|
||||
location = "<" + getBaseName(sourceFile) + ":" + QString::number(line).toStdString()+":"+ function + "()> ";
|
||||
location = "<" + FileUtils::getBaseName(sourceFile) + ":" + QString::number(line).toStdString()+":"+ function + "()> ";
|
||||
}
|
||||
|
||||
std::cout
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "HyperionConfig.h"
|
||||
#include "utils/Profiler.h"
|
||||
#include <utils/Profiler.h>
|
||||
#include <utils/FileUtils.h>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QString>
|
||||
@ -15,21 +16,11 @@ static unsigned int blockCounter = 0;
|
||||
static std::map<std::string,StopWatchItem> GlobalProfilerMap;
|
||||
Logger* Profiler::_logger = nullptr;
|
||||
|
||||
|
||||
|
||||
std::string profiler_getBaseName( std::string sourceFile)
|
||||
{
|
||||
QFileInfo fi( sourceFile.c_str() );
|
||||
return fi.fileName().toStdString();
|
||||
}
|
||||
|
||||
double getClockDelta(clock_t start)
|
||||
{
|
||||
return ((double)(clock() - start) / CLOCKS_PER_SEC) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Profiler::Profiler(const char* sourceFile, const char* func, unsigned int line) :
|
||||
_file(sourceFile),
|
||||
_func(func),
|
||||
@ -71,7 +62,7 @@ void Profiler::TimerStart(const std::string timerName, const char* sourceFile, c
|
||||
else
|
||||
{
|
||||
_logger->Message(Logger::DEBUG, sourceFile, func, line, "ERROR timer '%s' started in multiple locations. First occurence %s:%d:%s()",
|
||||
timerName.c_str(), profiler_getBaseName(ret.first->second.sourceFile).c_str(), ret.first->second.line, ret.first->second.func );
|
||||
timerName.c_str(), FileUtils::getBaseName(ret.first->second.sourceFile).c_str(), ret.first->second.line, ret.first->second.func );
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -88,7 +79,7 @@ void Profiler::TimerGetTime(const std::string timerName, const char* sourceFile,
|
||||
if (ret != GlobalProfilerMap.end())
|
||||
{
|
||||
_logger->Message(Logger::DEBUG, sourceFile, func, line, "timer '%s' started at %s:%d:%s() took %f s execution time until here", timerName.c_str(),
|
||||
profiler_getBaseName(ret->second.sourceFile).c_str(), ret->second.line, ret->second.func, getClockDelta(ret->second.startTime) );
|
||||
FileUtils::getBaseName(ret->second.sourceFile).c_str(), ret->second.line, ret->second.func, getClockDelta(ret->second.startTime) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -108,7 +108,7 @@ void QJsonSchemaChecker::validate(const QJsonValue & value, const QJsonObject &s
|
||||
; // nothing to do. value is present so always oke
|
||||
else if (attribute == "id")
|
||||
; // references have already been collected
|
||||
else if (attribute == "title" || attribute == "description" || attribute == "default" || attribute == "format")
|
||||
else if (attribute == "title" || attribute == "description" || attribute == "default" || attribute == "format" || attribute == "advanced")
|
||||
; // nothing to do.
|
||||
else
|
||||
{
|
||||
|
@ -5,11 +5,13 @@
|
||||
|
||||
#include "CgiHandler.h"
|
||||
#include "QtHttpHeader.h"
|
||||
#include <utils/FileUtils.h>
|
||||
|
||||
CgiHandler::CgiHandler (Hyperion * hyperion, QObject * parent)
|
||||
CgiHandler::CgiHandler (Hyperion * hyperion, QString baseUrl, QObject * parent)
|
||||
: QObject(parent)
|
||||
, _hyperion(hyperion)
|
||||
, _hyperionConfig(_hyperion->getJsonConfig())
|
||||
, _baseUrl(baseUrl)
|
||||
{
|
||||
}
|
||||
|
||||
@ -26,6 +28,7 @@ void CgiHandler::exec(const QStringList & args, QtHttpRequest * request, QtHttpR
|
||||
|
||||
cmd_cfg_jsonserver(args,reply);
|
||||
cmd_cfg_hyperion(args,reply);
|
||||
cmd_runscript(args,reply);
|
||||
throw 1;
|
||||
}
|
||||
catch(int e)
|
||||
@ -71,3 +74,34 @@ void CgiHandler::cmd_cfg_hyperion(const QStringList & args, QtHttpReply * reply)
|
||||
throw 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CgiHandler::cmd_runscript(const QStringList & args, QtHttpReply * reply)
|
||||
{
|
||||
if ( args.at(0) == "run" )
|
||||
{
|
||||
QStringList scriptFilePathList(args);
|
||||
scriptFilePathList.removeAt(0);
|
||||
|
||||
QString scriptFilePath = scriptFilePathList.join('/');
|
||||
// relative path not allowed
|
||||
if (scriptFilePath.indexOf("..") >=0)
|
||||
{
|
||||
throw 1;
|
||||
}
|
||||
|
||||
scriptFilePath = _baseUrl+"/server_scripts/"+scriptFilePath;
|
||||
QString interpreter = "";
|
||||
if (scriptFilePath.endsWith(".sh")) interpreter = "sh";
|
||||
if (scriptFilePath.endsWith(".py")) interpreter = "python";
|
||||
|
||||
if (QFile::exists(scriptFilePath) && !interpreter.isEmpty())
|
||||
{
|
||||
QByteArray data = FileUtils::command_exec(QString(interpreter + " " + scriptFilePath).toUtf8().constData()).c_str();
|
||||
|
||||
reply->addHeader ("Content-Type", "text/plain");
|
||||
reply->appendRawData (data);
|
||||
throw 0;
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class CgiHandler : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CgiHandler (Hyperion * hyperion, QObject * parent = NULL);
|
||||
CgiHandler (Hyperion * hyperion, QString baseUrl, QObject * parent = NULL);
|
||||
virtual ~CgiHandler (void);
|
||||
|
||||
void exec(const QStringList & args,QtHttpRequest * request, QtHttpReply * reply);
|
||||
@ -23,11 +23,13 @@ public:
|
||||
// cgi commands
|
||||
void cmd_cfg_jsonserver(const QStringList & args, QtHttpReply * reply);
|
||||
void cmd_cfg_hyperion (const QStringList & args, QtHttpReply * reply);
|
||||
void cmd_runscript (const QStringList & args, QtHttpReply * reply);
|
||||
|
||||
private:
|
||||
Hyperion* _hyperion;
|
||||
QtHttpReply * _reply;
|
||||
const Json::Value &_hyperionConfig;
|
||||
const QString _baseUrl;
|
||||
};
|
||||
|
||||
#endif // CGIHANDLER_H
|
||||
|
@ -12,7 +12,7 @@ StaticFileServing::StaticFileServing (Hyperion *hyperion, QString baseUrl, quint
|
||||
: QObject (parent)
|
||||
, _hyperion(hyperion)
|
||||
, _baseUrl (baseUrl)
|
||||
, _cgi(hyperion, this)
|
||||
, _cgi(hyperion, baseUrl, this)
|
||||
, _log(Logger::getInstance("WEBSERVER"))
|
||||
{
|
||||
_mimeDb = new QMimeDatabase;
|
||||
@ -71,7 +71,7 @@ void StaticFileServing::onRequestNeedsReply (QtHttpRequest * request, QtHttpRepl
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
printErrorToReply (reply, "cgi script failed (" % path % ")");
|
||||
printErrorToReply (reply, "script failed (" % path % ")");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ private:
|
||||
QtHttpServer * _server;
|
||||
QMimeDatabase * _mimeDb;
|
||||
CgiHandler _cgi;
|
||||
Logger * _log;
|
||||
Logger * _log;
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user