diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
index d8c40e2b..e44a3cc5 100644
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -149,8 +149,10 @@ jobs:
with:
python-version: '3.x'
- - name: Install NSIS
- run: choco install --no-progress nsis -y
+ - name: Install NSIS & copy plugins
+ run: |
+ choco install --no-progress nsis -y
+ copy "cmake\nsis\template\*.dll" "C:\Program Files (x86)\NSIS\Plugins\x86-ansi\"
- name: Install OpenSSL
run: choco install --no-progress openssl -y
@@ -171,7 +173,7 @@ jobs:
shell: bash
run: |
mkdir -p windows
- mv build/*.zip windows
+ mv build/*.exe windows
# Upload artifacts
- name: Upload artifacts
diff --git a/.github/workflows/push-master.yml b/.github/workflows/push-master.yml
index df031f73..768599fd 100644
--- a/.github/workflows/push-master.yml
+++ b/.github/workflows/push-master.yml
@@ -113,8 +113,10 @@ jobs:
with:
python-version: '3.x'
- - name: Install NSIS
- run: choco install --no-progress nsis -y
+ - name: Install NSIS & copy plugins
+ run: |
+ choco install --no-progress nsis -y
+ copy "cmake\nsis\template\*.dll" "C:\Program Files (x86)\NSIS\Plugins\x86-ansi\"
- name: Install OpenSSL
run: choco install --no-progress openssl -y
diff --git a/.gitignore b/.gitignore
index fd2b546b..f92845f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,6 @@ compile_commands.json
# Autogenerated by flatbuffers
libsrc/flatbufserver/hyperion_reply_generated.h
libsrc/flatbufserver/hyperion_request_generated.h
+
+# Kdevelop project files
+*.kdev*
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4e507c9c..90c91022 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,9 +13,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
### Fixed
+ - Also allow an 8-LED configuration when using Karatelight
+
+- Fix Lightpack issue (#1015)
+
+- Fix color calibration for Kodi 18 (Fixes #771)
### Removed
+- Replace Multi-Lightpack by multi-instance Lightpack configuration
+
## [2.0.0-alpha.8](https://github.com/hyperion-project/hyperion.ng/releases/tag/2.0.0-alpha.8) - 2020-09-14
### Added
- Add XCB grabber, a faster and safer alternative for X11 grabbing (#912)
diff --git a/assets/webconfig/i18n/en.json b/assets/webconfig/i18n/en.json
index df22f96a..536bafa8 100644
--- a/assets/webconfig/i18n/en.json
+++ b/assets/webconfig/i18n/en.json
@@ -863,13 +863,13 @@
"wiz_cc_btn_stop": "Stop video",
"wiz_cc_btn_switchpic": "Switch picture",
"wiz_cc_chooseid": "Define a name for this color profile.",
- "wiz_cc_intro1": "This wizard will guide you through your led calibration. If you are using Kodi, the calibration pictures and videos can be sent directly to it without further actions on your side. If not, you will need to download these files yourself and display them when the wizard needs you to adjust the setting.",
- "wiz_cc_kodicon": "Kodi webserver found, proceed with Kodi support.",
- "wiz_cc_kodidiscon": "Kodi webserver not found, proceed without Kodi support.",
+ "wiz_cc_intro1": "This wizard will guide you through your led calibration. If you are using Kodi, the calibration pictures and videos can be sent directly to it. Prerequisite: You need to enable \"Allow remote control from applications on other systems\" in Kodi. Alternatively, you might want downloading these files yourself and display them when the wizard asks you to adjust the setting.",
+ "wiz_cc_kodicon": "Kodi found, proceed with Kodi support.",
+ "wiz_cc_kodidiscon": "Kodi not found, proceed without Kodi support.",
"wiz_cc_kodidisconlink": "Download link pictures:",
"wiz_cc_kodimsg_start": "Test success - time to proceed!",
"wiz_cc_kodishould": "Kodi should show the following picture: $1",
- "wiz_cc_kwebs": "Kodi webserver (IP:Port)",
+ "wiz_cc_kwebs": "Kodi webserver (Hostname or IP)",
"wiz_cc_lettvshow": "Let your TV show the following picture: $1",
"wiz_cc_lettvshowm": "Check this with the following pictures: $1",
"wiz_cc_link": "Click me!",
diff --git a/assets/webconfig/js/content_leds.js b/assets/webconfig/js/content_leds.js
index 56fd9d7a..e6f5c18f 100644
--- a/assets/webconfig/js/content_leds.js
+++ b/assets/webconfig/js/content_leds.js
@@ -571,6 +571,7 @@ $(document).ready(function() {
var devRPiSPI = ['apa102', 'apa104', 'ws2801', 'lpd6803', 'lpd8806', 'p9813', 'sk6812spi', 'sk6822spi', 'sk9822', 'ws2812spi'];
var devRPiPWM = ['ws281x'];
var devRPiGPIO = ['piblaster'];
+
var devNET = ['atmoorb', 'fadecandy', 'philipshue', 'nanoleaf', 'razer', 'tinkerforge', 'tpm2net', 'udpe131', 'udpartnet', 'udph801', 'udpraw', 'wled', 'yeelight'];
var devUSB = ['adalight', 'dmx', 'atmo', 'hyperionusbasp', 'lightpack', 'paintpack', 'rawhid', 'sedu', 'tpm2', 'karate'];
diff --git a/assets/webconfig/js/wizard.js b/assets/webconfig/js/wizard.js
index 53b4379e..0b48b032 100644
--- a/assets/webconfig/js/wizard.js
+++ b/assets/webconfig/js/wizard.js
@@ -1,19 +1,16 @@
//clear priority and other tasks if people reload the page or lost connection while a wizard was active
-$(window.hyperion).one("ready", function(event) {
- if(getStorage("wizardactive") === 'true')
- {
+$(window.hyperion).one("ready", function (event) {
+ if (getStorage("wizardactive") === 'true') {
requestPriorityClear();
setStorage("wizardactive", false);
- if(getStorage("kodiAddress") != null)
- {
+ if (getStorage("kodiAddress") != null) {
kodiAddress = getStorage("kodiAddress");
sendToKodi("stop");
}
}
});
-function resetWizard(reload)
-{
+function resetWizard(reload) {
$("#wizard_modal").modal('hide');
clearInterval(wIntveralId);
requestPriorityClear();
@@ -22,146 +19,138 @@ function resetWizard(reload)
$('#wizp2').toggle(false);
$('#wizp3').toggle(false);
//cc
- if(withKodi)
+ if (withKodi)
sendToKodi("stop");
step = 0;
- if(!reload) location.reload();
+ if (!reload) location.reload();
}
//rgb byte order wizard
var wIntveralId;
var new_rgb_order;
-function changeColor()
-{
+function changeColor() {
var color = $("#wiz_canv_color").css('background-color');
- if (color == 'rgb(255, 0, 0)')
- {
- $("#wiz_canv_color").css('background-color','rgb(0, 255, 0)');
- requestSetColor('0','255','0');
+ if (color == 'rgb(255, 0, 0)') {
+ $("#wiz_canv_color").css('background-color', 'rgb(0, 255, 0)');
+ requestSetColor('0', '255', '0');
}
- else
- {
- $("#wiz_canv_color").css('background-color','rgb(255, 0, 0)');
- requestSetColor('255','0','0');
+ else {
+ $("#wiz_canv_color").css('background-color', 'rgb(255, 0, 0)');
+ requestSetColor('255', '0', '0');
}
}
-function startWizardRGB()
-{
+function startWizardRGB() {
//create html
- $('#wiz_header').html(' '+$.i18n('wiz_rgb_title'));
- $('#wizp1_body').html('
'+$.i18n('wiz_rgb_title')+' '+$.i18n('wiz_rgb_intro1')+'
'+$.i18n('wiz_rgb_intro2')+'
');
- $('#wizp1_footer').html(' '+$.i18n('general_btn_continue')+' '+$.i18n('general_btn_cancel')+' ');
- $('#wizp2_body').html(''+$.i18n('wiz_rgb_expl')+'
');
- $('#wizp2_body').append('');
- $('#wizp2_body').append(''+$.i18n('wiz_rgb_q')+' ');
- $('#wizp2_body').append(''+$.i18n('wiz_rgb_qrend')+' '+$.i18n('wiz_rgb_qgend')+'
');
- $('#wizp2_footer').html(' '+$.i18n('general_btn_save')+' '+$.i18n('general_btn_ok')+' '+$.i18n('general_btn_cancel')+' ');
+ $('#wiz_header').html(' ' + $.i18n('wiz_rgb_title'));
+ $('#wizp1_body').html('' + $.i18n('wiz_rgb_title') + ' ' + $.i18n('wiz_rgb_intro1') + '
' + $.i18n('wiz_rgb_intro2') + '
');
+ $('#wizp1_footer').html(' ' + $.i18n('general_btn_continue') + ' ' + $.i18n('general_btn_cancel') + ' ');
+ $('#wizp2_body').html('' + $.i18n('wiz_rgb_expl') + '
');
+ $('#wizp2_body').append('');
+ $('#wizp2_body').append('' + $.i18n('wiz_rgb_q') + ' ');
+ $('#wizp2_body').append('' + $.i18n('wiz_rgb_qrend') + ' ' + $.i18n('wiz_rgb_qgend') + '
');
+ $('#wizp2_footer').html(' ' + $.i18n('general_btn_save') + ' ' + $.i18n('general_btn_ok') + ' ' + $.i18n('general_btn_cancel') + ' ');
//open modal
$("#wizard_modal").modal({
- backdrop : "static",
+ backdrop: "static",
keyboard: false,
show: true
});
//listen for continue
- $('#btn_wiz_cont').off().on('click',function() {
+ $('#btn_wiz_cont').off().on('click', function () {
beginWizardRGB();
$('#wizp1').toggle(false);
$('#wizp2').toggle(true);
});
}
-function beginWizardRGB()
-{
- $("#wiz_switchtime_select").off().on('change',function() {
+function beginWizardRGB() {
+ $("#wiz_switchtime_select").off().on('change', function () {
clearInterval(wIntveralId);
var time = $("#wiz_switchtime_select").val();
- wIntveralId = setInterval(function() { changeColor(); }, time*1000);
+ wIntveralId = setInterval(function () { changeColor(); }, time * 1000);
});
$('.wselect').change(function () {
var rgb_order = window.serverConfig.device.colorOrder.split("");
var redS = $("#wiz_r_select").val();
var greenS = $("#wiz_g_select").val();
- var blueS = rgb_order.toString().replace(/,/g,"").replace(redS, "").replace(greenS,"");
+ var blueS = rgb_order.toString().replace(/,/g, "").replace(redS, "").replace(greenS, "");
- for (var i = 0; i '+$.i18n('wiz_cc_kodishould',$.i18n('edt_conf_color_white_title'));
- sendToKodi('playP',"white");
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_white_title'));
+ if (withKodi) {
+ h += ' ' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_white_title'));
+ sendToKodi('playP', "white");
}
else
- h += ' '+$.i18n('wiz_cc_lettvshow',$.i18n('edt_conf_color_white_title'));
+ h += ' ' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_white_title'));
$('#wiz_cc_desc').html(h);
}
- if(step == 3)
- {
- updateWEditor(["gammaRed","gammaGreen","gammaBlue"]);
- h = ''+$.i18n('wiz_cc_adjustgamma')+'
';
- if(withKodi)
- {
- sendToKodi('playP',"HGradient");
- h +=''+$.i18n('wiz_cc_btn_switchpic')+' ';
+ if (step == 3) {
+ updateWEditor(["gammaRed", "gammaGreen", "gammaBlue"]);
+ h = '' + $.i18n('wiz_cc_adjustgamma') + '
';
+ if (withKodi) {
+ sendToKodi('playP', "HGradient");
+ h += '' + $.i18n('wiz_cc_btn_switchpic') + ' ';
}
else
- h += ''+$.i18n('wiz_cc_lettvshowm', "gey_1, grey_2, grey_3, HGradient, VGradient")+'
';
+ h += '' + $.i18n('wiz_cc_lettvshowm', "gey_1, grey_2, grey_3, HGradient, VGradient") + '
';
$('#wiz_cc_desc').html(h);
- $('#wiz_cc_btn_sp').off().on('click', function(){
- switchPicture(["VGradient","grey_1","grey_2","grey_3","HGradient"]);
+ $('#wiz_cc_btn_sp').off().on('click', function () {
+ switchPicture(["VGradient", "grey_1", "grey_2", "grey_3", "HGradient"]);
});
}
- if(step == 4)
- {
+ if (step == 4) {
updateWEditor(["red"]);
- h = $.i18n('wiz_cc_adjustit',$.i18n('edt_conf_color_red_title'));
- if(withKodi)
- {
- h += ' '+$.i18n('wiz_cc_kodishould',$.i18n('edt_conf_color_red_title'));
- sendToKodi('playP',"red");
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_red_title'));
+ if (withKodi) {
+ h += ' ' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_red_title'));
+ sendToKodi('playP', "red");
}
else
- h += ' '+$.i18n('wiz_cc_lettvshow',$.i18n('edt_conf_color_red_title'));
+ h += ' ' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_red_title'));
$('#wiz_cc_desc').html(h);
}
- if(step == 5)
- {
+ if (step == 5) {
updateWEditor(["green"]);
- h = $.i18n('wiz_cc_adjustit',$.i18n('edt_conf_color_green_title'));
- if(withKodi)
- {
- h += ' '+$.i18n('wiz_cc_kodishould',$.i18n('edt_conf_color_green_title'));
- sendToKodi('playP',"green");
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_green_title'));
+ if (withKodi) {
+ h += ' ' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_green_title'));
+ sendToKodi('playP', "green");
}
else
- h += ' '+$.i18n('wiz_cc_lettvshow',$.i18n('edt_conf_color_green_title'));
+ h += ' ' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_green_title'));
$('#wiz_cc_desc').html(h);
}
- if(step == 6)
- {
+ if (step == 6) {
updateWEditor(["blue"]);
- h = $.i18n('wiz_cc_adjustit',$.i18n('edt_conf_color_blue_title'));
- if(withKodi)
- {
- h += ' '+$.i18n('wiz_cc_kodishould',$.i18n('edt_conf_color_blue_title'));
- sendToKodi('playP',"blue");
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_blue_title'));
+ if (withKodi) {
+ h += ' ' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_blue_title'));
+ sendToKodi('playP', "blue");
}
else
- h += ' '+$.i18n('wiz_cc_lettvshow',$.i18n('edt_conf_color_blue_title'));
+ h += ' ' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_blue_title'));
$('#wiz_cc_desc').html(h);
}
- if(step == 7)
- {
+ if (step == 7) {
updateWEditor(["cyan"]);
- h = $.i18n('wiz_cc_adjustit',$.i18n('edt_conf_color_cyan_title'));
- if(withKodi)
- {
- h += ' '+$.i18n('wiz_cc_kodishould',$.i18n('edt_conf_color_cyan_title'));
- sendToKodi('playP',"cyan");
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_cyan_title'));
+ if (withKodi) {
+ h += ' ' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_cyan_title'));
+ sendToKodi('playP', "cyan");
}
else
- h += ' '+$.i18n('wiz_cc_lettvshow',$.i18n('edt_conf_color_cyan_title'));
+ h += ' ' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_cyan_title'));
$('#wiz_cc_desc').html(h);
}
- if(step == 8)
- {
+ if (step == 8) {
updateWEditor(["magenta"]);
- h = $.i18n('wiz_cc_adjustit',$.i18n('edt_conf_color_magenta_title'));
- if(withKodi)
- {
- h += ' '+$.i18n('wiz_cc_kodishould',$.i18n('edt_conf_color_magenta_title'));
- sendToKodi('playP',"magenta");
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_magenta_title'));
+ if (withKodi) {
+ h += ' ' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_magenta_title'));
+ sendToKodi('playP', "magenta");
}
else
- h += ' '+$.i18n('wiz_cc_lettvshow',$.i18n('edt_conf_color_magenta_title'));
+ h += ' ' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_magenta_title'));
$('#wiz_cc_desc').html(h);
}
- if(step == 9)
- {
+ if (step == 9) {
updateWEditor(["yellow"]);
- h = $.i18n('wiz_cc_adjustit',$.i18n('edt_conf_color_yellow_title'));
- if(withKodi)
- {
- h += ' '+$.i18n('wiz_cc_kodishould',$.i18n('edt_conf_color_yellow_title'));
- sendToKodi('playP',"yellow");
+ h = $.i18n('wiz_cc_adjustit', $.i18n('edt_conf_color_yellow_title'));
+ if (withKodi) {
+ h += ' ' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_yellow_title'));
+ sendToKodi('playP', "yellow");
}
else
- h += ' '+$.i18n('wiz_cc_lettvshow',$.i18n('edt_conf_color_yellow_title'));
+ h += ' ' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_yellow_title'));
$('#wiz_cc_desc').html(h);
}
- if(step == 10)
- {
- updateWEditor(["backlightThreshold","backlightColored"]);
+ if (step == 10) {
+ updateWEditor(["backlightThreshold", "backlightColored"]);
h = $.i18n('wiz_cc_backlight');
- if(withKodi)
- {
- h += ' '+$.i18n('wiz_cc_kodishould',$.i18n('edt_conf_color_black_title'));
- sendToKodi('playP',"black");
+ if (withKodi) {
+ h += ' ' + $.i18n('wiz_cc_kodishould', $.i18n('edt_conf_color_black_title'));
+ sendToKodi('playP', "black");
}
else
- h += ' '+$.i18n('wiz_cc_lettvshow',$.i18n('edt_conf_color_black_title'));
+ h += ' ' + $.i18n('wiz_cc_lettvshow', $.i18n('edt_conf_color_black_title'));
$('#wiz_cc_desc').html(h);
}
- if(step == 11)
- {
+ if (step == 11) {
updateWEditor([""], true);
- h = ''+$.i18n('wiz_cc_testintro')+'
';
- if(withKodi)
- {
- h += ''+$.i18n('wiz_cc_testintrok')+'
';
+ h = '' + $.i18n('wiz_cc_testintro') + '
';
+ if (withKodi) {
+ h += '' + $.i18n('wiz_cc_testintrok') + '
';
sendToKodi('stop');
- for(var i = 0; i '+txt+' ';
+ for (var i = 0; i < availVideos.length; i++) {
+ var txt = availVideos[i].replace(/_/g, " ");
+ h += ' ' + txt + '
';
}
- h +=' '+$.i18n('wiz_cc_btn_stop')+'
';
+ h += ' ' + $.i18n('wiz_cc_btn_stop') + '
';
}
else
- h += ''+$.i18n('wiz_cc_testintrowok')+' '+$.i18n('wiz_cc_link')+'
';
- h += ''+$.i18n('wiz_cc_summary')+'
';
+ h += '' + $.i18n('wiz_cc_testintrowok') + ' ' + $.i18n('wiz_cc_link') + '
';
+ h += '' + $.i18n('wiz_cc_summary') + '
';
$('#wiz_cc_desc').html(h);
- $('.videobtn').off().on('click', function(e){
- if(e.target.id == "stop")
+ $('.videobtn').off().on('click', function (e) {
+ if (e.target.id == "stop")
sendToKodi("stop");
else
- sendToKodi("playV",e.target.id+'.mp4');
+ sendToKodi("playV", e.target.id + '.mp4');
$(this).attr("disabled", true);
- setTimeout(function(){$('.videobtn').attr("disabled", false)},10000);
+ setTimeout(function () { $('.videobtn').attr("disabled", false) }, 10000);
});
$('#btn_wiz_next').attr("disabled", true);
$('#btn_wiz_save').toggle(true);
}
- else
- {
+ else {
$('#btn_wiz_next').attr("disabled", false);
$('#btn_wiz_save').toggle(false);
}
}
-function updateWEditor(el, all)
-{
- for (var key in cobj)
- {
- if(all === true || el[0] == key || el[1] == key || el[2] == key)
- $('#editor_container_wiz [data-schemapath*=".'+profile+'.'+key+'"]').toggle(true);
+function updateWEditor(el, all) {
+ for (var key in cobj) {
+ if (all === true || el[0] == key || el[1] == key || el[2] == key)
+ $('#editor_container_wiz [data-schemapath*=".' + profile + '.' + key + '"]').toggle(true);
else
- $('#editor_container_wiz [data-schemapath*=".'+profile+'.'+key+'"]').toggle(false);
+ $('#editor_container_wiz [data-schemapath*=".' + profile + '.' + key + '"]').toggle(false);
}
}
-function startWizardCC()
-{
+function startWizardCC() {
+ // Ensure that Kodi's default REST-API port is not used, as now the Web-Socket port is used
+ [kodiHost, kodiPort] = kodiAddress.split(":", 2);
+ if (kodiPort === "8080") {
+ kodiAddress = kodiHost;
+ kodiPort = undefined;
+ }
+
//create html
- $('#wiz_header').html(' '+$.i18n('wiz_cc_title'));
- $('#wizp1_body').html(''+$.i18n('wiz_cc_title')+' '+$.i18n('wiz_cc_intro1')+'
'+$.i18n('wiz_cc_kwebs')+' ');
- $('#wizp1_footer').html(' '+$.i18n('general_btn_continue')+' '+$.i18n('general_btn_cancel')+' ');
+ $('#wiz_header').html(' ' + $.i18n('wiz_cc_title'));
+ $('#wizp1_body').html('' + $.i18n('wiz_cc_title') + ' ' + $.i18n('wiz_cc_intro1') + '
' + $.i18n('wiz_cc_kwebs') + ' ');
+ $('#wizp1_footer').html(' ' + $.i18n('general_btn_continue') + ' ' + $.i18n('general_btn_cancel') + ' ');
$('#wizp2_body').html('
');
- $('#wizp2_footer').html(' '+$.i18n('general_btn_back')+''+$.i18n('general_btn_next')+' '+$.i18n('general_btn_save')+' '+$.i18n('general_btn_cancel')+' ');
+ $('#wizp2_footer').html(' ' + $.i18n('general_btn_back') + '' + $.i18n('general_btn_next') + ' ' + $.i18n('general_btn_save') + ' ' + $.i18n('general_btn_cancel') + ' ');
//open modal
$("#wizard_modal").modal({
- backdrop : "static",
+ backdrop: "static",
keyboard: false,
show: true
});
- $('#wiz_cc_kodiip').off().on('change',function() {
- kodiAddress = $(this).val();
- setStorage("kodiAddress", kodiAddress);
- sendToKodi("msg", $.i18n('wiz_cc_kodimsg_start'), function(cb){
- if(cb == "error")
- {
- $('#kodi_status').html(''+$.i18n('wiz_cc_kodidiscon')+'
'+$.i18n('wiz_cc_kodidisconlink')+' '+$.i18n('wiz_cc_link')+'
');
- withKodi = false;
- }
- else
- {
- $('#kodi_status').html(''+$.i18n('wiz_cc_kodicon')+'
');
- withKodi = true;
- }
+ $('#wiz_cc_kodiip').off().on('change', function () {
+ kodiAddress = $(this).val().trim();
+ $('#kodi_status').html('');
- $('#btn_wiz_cont').attr('disabled', false);
- });
+ // Remove Kodi's default Web-Socket port (9090) from display and ensure Kodi's default REST-API port (8080) is mapped to web-socket port to ease migration
+ if (kodiAddress !== "") {
+ [kodiHost, kodiPort] = kodiAddress.split(":", 2);
+ if (kodiPort === "9090" || kodiPort === "8080") {
+ kodiAddress = kodiHost;
+ kodiPort = undefined;
+ }
+ sendToKodi("msg", $.i18n('wiz_cc_kodimsg_start'), function (cb) {
+ if (cb == "error") {
+ $('#kodi_status').html('' + $.i18n('wiz_cc_kodidiscon') + '
' + $.i18n('wiz_cc_kodidisconlink') + ' ' + $.i18n('wiz_cc_link') + '
');
+ withKodi = false;
+ }
+ else {
+ setStorage("kodiAddress", kodiAddress);
+
+ $('#kodi_status').html('' + $.i18n('wiz_cc_kodicon') + '
');
+ withKodi = true;
+ }
+
+ $('#btn_wiz_cont').attr('disabled', false);
+ });
+ }
});
//listen for continue
- $('#btn_wiz_cont').off().on('click',function() {
+ $('#btn_wiz_cont').off().on('click', function () {
beginWizardCC();
$('#wizp1').toggle(false);
$('#wizp2').toggle(true);
@@ -453,59 +466,56 @@ function startWizardCC()
$('#wiz_cc_kodiip').trigger("change");
colorLength = window.serverConfig.color.channelAdjustment;
cobj = window.schema.color.properties.channelAdjustment.items.properties;
- websAddress = document.location.hostname+':'+window.serverConfig.webConfig.port;
- imgAddress = 'http://'+websAddress+'/img/cc/';
+ websAddress = document.location.hostname + ':' + window.serverConfig.webConfig.port;
+ imgAddress = 'http://' + websAddress + '/img/cc/';
setStorage("wizardactive", true);
//check profile count
- if(colorLength.length > 1)
- {
- $('#multi_cali').html(''+$.i18n('wiz_cc_morethanone')+'
');
- for(var i = 0; i 1) {
+ $('#multi_cali').html('' + $.i18n('wiz_cc_morethanone') + '
');
+ for (var i = 0; i < colorLength.length; i++)
+ $('#wiz_select').append(createSelOpt(i, i + 1 + ' (' + colorLength[i].id + ')'));
- $('#wiz_select').off().on('change', function(){
+ $('#wiz_select').off().on('change', function () {
profile = $(this).val();
});
}
//prepare editor
wiz_editor = createJsonEditor('editor_container_wiz', {
- color : window.schema.color
+ color: window.schema.color
}, true, true);
$('#editor_container_wiz h4').toggle(false);
$('#editor_container_wiz .btn-group').toggle(false);
$('#editor_container_wiz [data-schemapath="root.color.imageToLedMappingType"]').toggle(false);
- for(var i = 0; i'+$.i18n(hue_title));
- $('#wizp1_body').html(''+$.i18n(hue_title)+' '+$.i18n(hue_intro1)+'
');
- $('#wizp1_footer').html(' '+$.i18n('general_btn_continue')+' '+$.i18n('general_btn_cancel')+' ');
+ $('#wiz_header').html(' ' + $.i18n(hue_title));
+ $('#wizp1_body').html('' + $.i18n(hue_title) + ' ' + $.i18n(hue_intro1) + '
');
+ $('#wizp1_footer').html(' ' + $.i18n('general_btn_continue') + ' ' + $.i18n('general_btn_cancel') + ' ');
$('#wizp2_body').html('
');
- $('#wh_topcontainer').append(''+$.i18n(hue_desc1)+'
');
+ $('#wh_topcontainer').append('' + $.i18n(hue_desc1) + '
');
$('#wh_topcontainer').append();
$('#wh_topcontainer').append('
');
- if(hueType == 'philipshue')
- {
- $('#usrcont').append(''+$.i18n('wiz_hue_username')+'
');
+ if (hueType == 'philipshue') {
+ $('#usrcont').append('' + $.i18n('wiz_hue_username') + '
');
}
- if(hueType == 'philipshueentertainment')
- {
- $('#usrcont').append(''+$.i18n('wiz_hue_username')+'
'+$.i18n('wiz_hue_clientkey')+'
');
+ if (hueType == 'philipshueentertainment') {
+ $('#usrcont').append('' + $.i18n('wiz_hue_username') + '
' + $.i18n('wiz_hue_clientkey') + '
');
}
- $('#usrcont').append(' '+$.i18n(hue_create_user)+' ');
- if(hueType == 'philipshueentertainment')
- {
- $('#wizp2_body').append(''+$.i18n('wiz_hue_e_desc2')+'
');
+ $('#usrcont').append(' ' + $.i18n(hue_create_user) + ' ');
+ if (hueType == 'philipshueentertainment') {
+ $('#wizp2_body').append('' + $.i18n('wiz_hue_e_desc2') + '
');
createTable("gidsh", "gidsb", "hue_grp_ids_t");
- $('.gidsh').append(createTableRow([$.i18n('edt_dev_spec_groupId_title'),$.i18n('wiz_hue_e_use_group')], true));
- $('#wizp2_body').append(''+$.i18n('wiz_hue_e_desc3')+'
');
+ $('.gidsh').append(createTableRow([$.i18n('edt_dev_spec_groupId_title'), $.i18n('wiz_hue_e_use_group')], true));
+ $('#wizp2_body').append('' + $.i18n('wiz_hue_e_desc3') + '
');
}
- else
- {
- $('#wizp2_body').append(''+$.i18n('wiz_hue_desc2')+'
');
+ else {
+ $('#wizp2_body').append('' + $.i18n('wiz_hue_desc2') + '
');
}
createTable("lidsh", "lidsb", "hue_ids_t");
- $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lightid_title'),$.i18n('wiz_pos'),$.i18n('wiz_identify')], true));
- $('#wizp2_footer').html(' '+$.i18n('general_btn_save')+' '+$.i18n('general_btn_cancel')+' ');
- $('#wizp3_body').html(''+$.i18n('wiz_hue_press_link')+' ');
+ $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lightid_title'), $.i18n('wiz_pos'), $.i18n('wiz_identify')], true));
+ $('#wizp2_footer').html(' ' + $.i18n('general_btn_save') + ' ' + $.i18n('general_btn_cancel') + ' ');
+ $('#wizp3_body').html('' + $.i18n('wiz_hue_press_link') + ' ');
//open modal
$("#wizard_modal").modal({
- backdrop : "static",
+ backdrop: "static",
keyboard: false,
show: true
});
//listen for continue
- $('#btn_wiz_cont').off().on('click',function() {
+ $('#btn_wiz_cont').off().on('click', function () {
beginWizardHue();
$('#wizp1').toggle(false);
$('#wizp2').toggle(true);
});
}
-function checkHueBridge(cb,hueUser) {
+function checkHueBridge(cb, hueUser) {
var usr = (typeof hueUser != "undefined") ? hueUser : 'config';
- if(usr == 'config') $('#wiz_hue_discovered').html("");
+ if (usr == 'config') $('#wiz_hue_discovered').html("");
$.ajax({
- url: 'http://'+hueIPs[hueIPsinc].internalipaddress+'/api/'+usr,
+ url: 'http://' + hueIPs[hueIPsinc].internalipaddress + '/api/' + usr,
type: "GET",
dataType: "json",
- success: function( json ) {
+ success: function (json) {
if (json.config) {
cb(true, usr);
- } else if( json.name && json.bridgeid && json.modelid) {
+ } else if (json.name && json.bridgeid && json.modelid) {
$('#wiz_hue_discovered').html("Bridge: " + json.name + ", Modelid: " + json.modelid + ", API-Version: " + json.apiversion);
cb(true);
} else {
cb(false);
}
-
- },
+ },
timeout: 2500
- }).fail(function() {
+ }).fail(function () {
cb(false);
});
}
-function checkBridgeResult(reply, usr){
- if(reply)
- {
+function checkBridgeResult(reply, usr) {
+ if (reply) {
//abort checking, first reachable result is used
$('#wiz_hue_ipstate').html("");
$('#ip').val(hueIPs[hueIPsinc].internalipaddress)
//now check hue user on this bridge
$('#usrcont').toggle(true);
- checkHueBridge(checkUserResult,$('#user').val() ? $('#user').val() : "newdeveloper");
+ checkHueBridge(checkUserResult, $('#user').val() ? $('#user').val() : "newdeveloper");
}
- else
- {
+ else {
//increment and check again
- if(hueIPs.length-1 > hueIPsinc)
- {
+ if (hueIPs.length - 1 > hueIPsinc) {
hueIPsinc++;
checkHueBridge(checkBridgeResult);
}
- else
- {
+ else {
$('#usrcont').toggle(false);
$('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
}
@@ -699,129 +697,115 @@ function checkBridgeResult(reply, usr){
};
function checkUserResult(reply, usr) {
-
- if(reply)
- {
+ if (reply) {
$('#user').val(usr);
- if(hueType == 'philipshueentertainment' && $('#clientkey').val() == "") {
+ if (hueType == 'philipshueentertainment' && $('#clientkey').val() == "") {
$('#usrcont').toggle(true);
$('#wiz_hue_usrstate').html($.i18n('wiz_hue_e_clientkey_needed'));
$('#wiz_hue_create_user').toggle(true);
} else {
$('#wiz_hue_usrstate').html("");
$('#wiz_hue_create_user').toggle(false);
- if(hueType == 'philipshue')
- {
+ if (hueType == 'philipshue') {
get_hue_lights();
}
- if(hueType == 'philipshueentertainment')
- {
+ if (hueType == 'philipshueentertainment') {
get_hue_groups();
}
}
}
- else
- {
+ else {
$('#wiz_hue_usrstate').html($.i18n('wiz_hue_failure_user'));
$('#wiz_hue_create_user').toggle(true);
}
};
-function identHueId(id, off, oState)
-{
- if(off !== true)
- {
- setTimeout(identHueId,1500,id,true,oState);
+function identHueId(id, off, oState) {
+ if (off !== true) {
+ setTimeout(identHueId, 1500, id, true, oState);
var put_data = '{"on":true,"bri":254,"hue":47000,"sat":254}';
}
- else
- {
- var put_data = '{"on":'+oState.on+',"bri":' + oState.bri +',"hue":' + oState.hue +',"sat":' + oState.sat +'}';
+ else {
+ var put_data = '{"on":' + oState.on + ',"bri":' + oState.bri + ',"hue":' + oState.hue + ',"sat":' + oState.sat + '}';
}
$.ajax({
- url: 'http://'+$('#ip').val()+'/api/'+$('#user').val()+'/lights/'+id+'/state',
+ url: 'http://' + $('#ip').val() + '/api/' + $('#user').val() + '/lights/' + id + '/state',
type: 'PUT',
timeout: 2000,
data: put_data
})
}
-function useGroupId(id)
-{
+function useGroupId(id) {
$('#groupId').val(id);
groupLights = groupIDs[id].lights;
groupLightsLocations = groupIDs[id].locations;
get_hue_lights();
}
-async function discover_hue_bridges(){
+async function discover_hue_bridges() {
+ const res = await requestLedDeviceDiscovery('philipshue');
- const res = await requestLedDeviceDiscovery ('philipshue');
-
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info;
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info;
- // Process devices returned by discovery
- console.log(r);
-
- if(r.devices.length == 0)
- $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
- else
- {
- for(const device of r.devices)
- {
- console.log("Device:", device);
+ // Process devices returned by discovery
+ console.log(r);
- var ip = device.hostname + ":" + device.port;
- console.log("Host:", ip);
+ if (r.devices.length == 0)
+ $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
+ else {
+ for (const device of r.devices) {
+ console.log("Device:", device);
- hueIPs.push({internalipaddress : ip});
- }
- var usr = $('#user').val();
- if(usr != "") {
- checkHueBridge(checkUserResult, usr);
- } else {
- checkHueBridge(checkBridgeResult);
- }
- }
- }
+ var ip = device.hostname + ":" + device.port;
+ console.log("Host:", ip);
+
+ hueIPs.push({ internalipaddress: ip });
+ }
+ var usr = $('#user').val();
+ if (usr != "") {
+ checkHueBridge(checkUserResult, usr);
+ } else {
+ checkHueBridge(checkBridgeResult);
+ }
+ }
+ }
}
-async function getProperties_hue_bridge(hostAddress, username, resourceFilter){
+async function getProperties_hue_bridge(hostAddress, username, resourceFilter) {
+ let params = { host: hostAddress, user: username, filter: resourceFilter };
- let params = { host: hostAddress, user: username, filter: resourceFilter};
-
- const res = await requestLedDeviceProperties ('philipshue', params);
-
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info
+ const res = await requestLedDeviceProperties('philipshue', params);
- // Process properties returned
- console.log(r);
- }
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
+
+ // Process properties returned
+ console.log(r);
+ }
}
-function identify_hue_device(hostAddress, username, id){
+function identify_hue_device(hostAddress, username, id) {
+ console.log("identify_hue_device");
- console.log("identify_hue_device");
+ let params = { host: hostAddress, user: username, lightId: id };
- let params = { host: hostAddress, user: username, lightId: id };
-
- const res = requestLedDeviceIdentification ("philipshue", params);
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info
- console.log(r);
- }
+ const res = requestLedDeviceIdentification("philipshue", params);
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
+ console.log(r);
+ }
}
-function getHueIPs(){
+function getHueIPs() {
$('#wiz_hue_ipstate').html($.i18n('wiz_hue_searchb'));
$.ajax({
url: 'https://discovery.meethue.com',
@@ -829,97 +813,88 @@ function getHueIPs(){
type: 'GET',
timeout: 3000
})
- .done( function( data, textStatus, jqXHR ) {
- if(data.length == 0) {
+ .done(function (data, textStatus, jqXHR) {
+ if (data.length == 0) {
+ $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
+ } else {
+ hueIPs = data;
+ checkHueBridge(checkBridgeResult);
+ }
+ })
+ .fail(function (jqXHR, textStatus) {
$('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
- } else {
- hueIPs = data;
- checkHueBridge(checkBridgeResult);
- }
- })
- .fail( function( jqXHR, textStatus ) {
- $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
- });
+ });
};
//return editor Value
-function eV(vn)
-{
+function eV(vn) {
return (vn) ? conf_editor.getEditor("root.specificOptions." + vn).getValue() : "";
}
-function beginWizardHue()
-{
+function beginWizardHue() {
var usr = eV("username");
- if(usr != "") {
+ if (usr != "") {
$('#user').val(usr);
}
- if(hueType == 'philipshueentertainment') {
+ if (hueType == 'philipshueentertainment') {
var clkey = eV("clientkey");
- if(clkey != "")
- {
+ if (clkey != "") {
$('#clientkey').val(clkey);
}
}
//check if ip is empty/reachable/search for bridge
- if(eV("output") == "")
- {
+ if (eV("output") == "") {
//getHueIPs();
discover_hue_bridges();
}
- else
- {
+ else {
var ip = eV("output");
$('#ip').val(ip);
- hueIPs.unshift({internalipaddress : ip});
- if(usr != "") {
+ hueIPs.unshift({ internalipaddress: ip });
+ if (usr != "") {
checkHueBridge(checkUserResult, usr);
- }else{
+ } else {
checkHueBridge(checkBridgeResult);
}
}
- $('#retry_bridge').off().on('click', function(){
- if($('#ip').val()!="")
- {
- hueIPs.unshift({internalipaddress : $('#ip').val()})
- hueIPsinc = 0;
+ $('#retry_bridge').off().on('click', function () {
+ if ($('#ip').val() != "") {
+ hueIPs.unshift({ internalipaddress: $('#ip').val() })
+ hueIPsinc = 0;
}
- else discover_hue_bridges();
+ else discover_hue_bridges();
var usr = $('#user').val();
- if(usr != "") {
+ if (usr != "") {
checkHueBridge(checkUserResult, usr);
- }else{
+ } else {
checkHueBridge(checkBridgeResult);
}
});
- $('#retry_usr').off().on('click', function(){
- checkHueBridge(checkUserResult,$('#user').val() ? $('#user').val() : "newdeveloper");
+ $('#retry_usr').off().on('click', function () {
+ checkHueBridge(checkUserResult, $('#user').val() ? $('#user').val() : "newdeveloper");
});
- $('#wiz_hue_create_user').off().on('click',function() {
- if($('#ip').val()!="") hueIPs.unshift({internalipaddress : $('#ip').val()});
+ $('#wiz_hue_create_user').off().on('click', function () {
+ if ($('#ip').val() != "") hueIPs.unshift({ internalipaddress: $('#ip').val() });
createHueUser();
});
- $('#btn_wiz_save').off().on("click", function(){
+ $('#btn_wiz_save').off().on("click", function () {
var hueLedConfig = [];
var finalLightIds = [];
//create hue led config
- for(var key in lightIDs)
- {
- if(hueType == 'philipshueentertainment')
- {
- if(groupLights.indexOf(key) == -1) continue;
+ for (var key in lightIDs) {
+ if (hueType == 'philipshueentertainment') {
+ if (groupLights.indexOf(key) == -1) continue;
}
- if($('#hue_'+key).val() != "disabled")
- {
+ if ($('#hue_' + key).val() != "disabled") {
finalLightIds.push(key);
- var idx_content = assignLightPos(key, $('#hue_'+key).val(), lightIDs[key].name);
+ var idx_content = assignLightPos(key, $('#hue_' + key).val(), lightIDs[key].name);
hueLedConfig.push(JSON.parse(JSON.stringify(idx_content)));
}
}
@@ -937,47 +912,45 @@ function beginWizardHue()
//device config
- //Start with a clean configuration
- var d = {};
- d.output = $('#ip').val();
- d.username = $('#user').val();
- d.type = 'philipshue';
- d.colorOrder = 'rgb';
- d.lightIds = finalLightIds;
- d.latchTime = 0;
- d.transitiontime = parseInt(eV("transitiontime") );
- d.restoreOriginalState = (eV("restoreOriginalState") == true);
- d.switchOffOnBlack = (eV("switchOffOnBlack") == true);
- d.brightnessFactor = parseFloat(eV("brightnessFactor"));
+ //Start with a clean configuration
+ var d = {};
+ d.output = $('#ip').val();
+ d.username = $('#user').val();
+ d.type = 'philipshue';
+ d.colorOrder = 'rgb';
+ d.lightIds = finalLightIds;
+ d.latchTime = 0;
+ d.transitiontime = parseInt(eV("transitiontime"));
+ d.restoreOriginalState = (eV("restoreOriginalState") == true);
+ d.switchOffOnBlack = (eV("switchOffOnBlack") == true);
+ d.brightnessFactor = parseFloat(eV("brightnessFactor"));
- d.clientkey = $('#clientkey').val();
- d.groupId = parseInt($('#groupId').val());
- d.blackLightsTimeout = parseInt(eV("blackLightsTimeout"));
- d.brightnessMin = parseFloat(eV("brightnessMin"));
- d.brightnessMax = parseFloat(eV("brightnessMax"));
- d.brightnessThreshold = parseFloat(eV("brightnessThreshold"));
- d.sslReadTimeout = parseInt(eV("sslReadTimeout"));
- d.sslHSTimeoutMin = parseInt(eV("sslHSTimeoutMin"));
- d.sslHSTimeoutMax = parseInt(eV("sslHSTimeoutMax"));
- d.verbose = (eV("verbose") == true);
- d.debugStreamer = (eV("debugStreamer") == true);
- d.debugLevel = (eV("debugLevel"));
+ d.clientkey = $('#clientkey').val();
+ d.groupId = parseInt($('#groupId').val());
+ d.blackLightsTimeout = parseInt(eV("blackLightsTimeout"));
+ d.brightnessMin = parseFloat(eV("brightnessMin"));
+ d.brightnessMax = parseFloat(eV("brightnessMax"));
+ d.brightnessThreshold = parseFloat(eV("brightnessThreshold"));
+ d.sslReadTimeout = parseInt(eV("sslReadTimeout"));
+ d.sslHSTimeoutMin = parseInt(eV("sslHSTimeoutMin"));
+ d.sslHSTimeoutMax = parseInt(eV("sslHSTimeoutMax"));
+ d.verbose = (eV("verbose") == true);
+ d.debugStreamer = (eV("debugStreamer") == true);
+ d.debugLevel = (eV("debugLevel"));
- if(hueType == 'philipshue')
- {
+ if (hueType == 'philipshue') {
d.useEntertainmentAPI = false;
- d.hardwareLedCount = finalLightIds.length;
- d.rewriteTime = 0;
- d.verbose = false;
+ d.hardwareLedCount = finalLightIds.length;
+ d.rewriteTime = 0;
+ d.verbose = false;
//smoothing off
sc.smoothing.enable = false;
}
- if(hueType == 'philipshueentertainment')
- {
+ if (hueType == 'philipshueentertainment') {
d.useEntertainmentAPI = true;
- d.hardwareLedCount = groupLights.length;
- d.rewriteTime = 20;
+ d.hardwareLedCount = groupLights.length;
+ d.rewriteTime = 20;
//smoothing on
sc.smoothing.enable = true;
}
@@ -991,178 +964,160 @@ function beginWizardHue()
$('#btn_wiz_abort').off().on('click', resetWizard);
}
-function createHueUser()
-{
+function createHueUser() {
var connectionRetries = 30;
- var data = {"devicetype":"hyperion#"+Date.now()}
- if(hueType == 'philipshueentertainment')
- {
- data = {"devicetype":"hyperion#"+Date.now(), "generateclientkey":true}
+ var data = { "devicetype": "hyperion#" + Date.now() }
+ if (hueType == 'philipshueentertainment') {
+ data = { "devicetype": "hyperion#" + Date.now(), "generateclientkey": true }
}
- var UserInterval = setInterval(function(){
- $.ajax({
- type: "POST",
- url: 'http://'+$("#ip").val()+'/api',
- processData: false,
- timeout: 1000,
- contentType: 'application/json',
- data: JSON.stringify(data),
- success: function(r) {
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(false);
- $('#wizp3').toggle(true);
+ var UserInterval = setInterval(function () {
+ $.ajax({
+ type: "POST",
+ url: 'http://' + $("#ip").val() + '/api',
+ processData: false,
+ timeout: 1000,
+ contentType: 'application/json',
+ data: JSON.stringify(data),
+ success: function (r) {
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(false);
+ $('#wizp3').toggle(true);
- connectionRetries--;
- $("#connectionTime").html(connectionRetries);
- if(connectionRetries == 0) {
- abortConnection(UserInterval);
- }
- else
- {
- if (typeof r[0].error != 'undefined') {
- console.log(connectionRetries+": link not pressed");
+ connectionRetries--;
+ $("#connectionTime").html(connectionRetries);
+ if (connectionRetries == 0) {
+ abortConnection(UserInterval);
}
- if (typeof r[0].success != 'undefined') {
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
- $('#wizp3').toggle(false);
- if(r[0].success.username != 'undefined') {
- $('#user').val(r[0].success.username);
- conf_editor.getEditor("root.specificOptions.username").setValue( r[0].success.username );
+ else {
+ if (typeof r[0].error != 'undefined') {
+ console.log(connectionRetries + ": link not pressed");
}
- if(hueType == 'philipshueentertainment')
- {
- if(r[0].success.clientkey != 'undefined') {
- $('#clientkey').val(r[0].success.clientkey);
- conf_editor.getEditor("root.specificOptions.clientkey").setValue( r[0].success.clientkey );
+ if (typeof r[0].success != 'undefined') {
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ $('#wizp3').toggle(false);
+ if (r[0].success.username != 'undefined') {
+ $('#user').val(r[0].success.username);
+ conf_editor.getEditor("root.specificOptions.username").setValue(r[0].success.username);
}
+ if (hueType == 'philipshueentertainment') {
+ if (r[0].success.clientkey != 'undefined') {
+ $('#clientkey').val(r[0].success.clientkey);
+ conf_editor.getEditor("root.specificOptions.clientkey").setValue(r[0].success.clientkey);
+ }
+ }
+ checkHueBridge(checkUserResult, r[0].success.username);
+ clearInterval(UserInterval);
}
- checkHueBridge(checkUserResult,r[0].success.username);
- clearInterval(UserInterval);
}
+ },
+ error: function (XMLHttpRequest, textStatus, errorThrown) {
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ $('#wizp3').toggle(false);
+ clearInterval(UserInterval);
}
- },
- error: function(XMLHttpRequest, textStatus, errorThrown) {
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
- $('#wizp3').toggle(false);
- clearInterval(UserInterval);
- }
- });
- },1000);
+ });
+ }, 1000);
}
-function get_hue_groups(){
+function get_hue_groups() {
$.ajax({
type: "GET",
- url: 'http://'+$("#ip").val()+'/api/'+$("#user").val()+'/groups',
+ url: 'http://' + $("#ip").val() + '/api/' + $("#user").val() + '/groups',
processData: false,
contentType: 'application/json',
- success: function(r) {
- if(Object.keys(r).length > 0)
- {
+ success: function (r) {
+ if (Object.keys(r).length > 0) {
$('#wh_topcontainer').toggle(false);
$('#hue_grp_ids_t').toggle(true);
groupIDs = r;
var gC = 0;
- for(var groupid in r)
- {
- if(r[groupid].type=='Entertainment')
- {
- $('.gidsb').append(createTableRow([groupid+' ('+r[groupid].name+')', ''+$.i18n('wiz_hue_e_use_groupid',groupid)+' ']));
+ for (var groupid in r) {
+ if (r[groupid].type == 'Entertainment') {
+ $('.gidsb').append(createTableRow([groupid + ' (' + r[groupid].name + ')', '' + $.i18n('wiz_hue_e_use_groupid', groupid) + ' ']));
gC++;
}
}
- if(gC == 0)
- {
+ if (gC == 0) {
noAPISupport('wiz_hue_e_noegrpids');
}
}
- else
- {
+ else {
noAPISupport('wiz_hue_e_nogrpids');
}
}
});
}
-function noAPISupport(txt)
-{
+function noAPISupport(txt) {
showNotification('danger', $.i18n('wiz_hue_e_title'), $.i18n('wiz_hue_e_noapisupport_hint'));
- conf_editor.getEditor("root.specificOptions.useEntertainmentAPI").setValue( false );
+ conf_editor.getEditor("root.specificOptions.useEntertainmentAPI").setValue(false);
$("#root_specificOptions_useEntertainmentAPI").trigger("change");
- $('#btn_wiz_holder').append(''+$.i18n('wiz_hue_e_noapisupport_hint')+'
');
+ $('#btn_wiz_holder').append('' + $.i18n('wiz_hue_e_noapisupport_hint') + '
');
$('#hue_grp_ids_t').toggle(false);
var txt = (txt) ? $.i18n(txt) : $.i18n('wiz_hue_e_nogrpids');
- $(''+txt+' '+$.i18n('wiz_hue_e_noapisupport')+'
').insertBefore('#wizp2_body #hue_ids_t');
+ $('' + txt + ' ' + $.i18n('wiz_hue_e_noapisupport') + '
').insertBefore('#wizp2_body #hue_ids_t');
$('#hue_id_headline').html($.i18n('wiz_hue_desc2'));
hueType = 'philipshue';
get_hue_lights();
}
-function get_light_state(id){
+function get_light_state(id) {
$.ajax({
type: "GET",
- url: 'http://'+$("#ip").val()+'/api/'+$("#user").val()+'/lights/'+id,
+ url: 'http://' + $("#ip").val() + '/api/' + $("#user").val() + '/lights/' + id,
processData: false,
contentType: 'application/json',
- success: function(r) {
- if(Object.keys(r).length > 0)
- {
+ success: function (r) {
+ if (Object.keys(r).length > 0) {
identHueId(id, false, r['state']);
}
}
});
}
-function get_hue_lights(){
+function get_hue_lights() {
$.ajax({
type: "GET",
- url: 'http://'+$("#ip").val()+'/api/'+$("#user").val()+'/lights',
+ url: 'http://' + $("#ip").val() + '/api/' + $("#user").val() + '/lights',
processData: false,
contentType: 'application/json',
- success: function(r) {
- if(Object.keys(r).length > 0)
- {
- if(hueType == 'philipshue')
- {
+ success: function (r) {
+ if (Object.keys(r).length > 0) {
+ if (hueType == 'philipshue') {
$('#wh_topcontainer').toggle(false);
}
$('#hue_ids_t, #btn_wiz_save').toggle(true);
lightIDs = r;
var lightOptions = [
- "top", "topleft", "topright",
- "bottom", "bottomleft", "bottomright",
- "left", "lefttop", "leftmiddle", "leftbottom",
- "right", "righttop", "rightmiddle", "rightbottom",
- "entire"
- ];
+ "top", "topleft", "topright",
+ "bottom", "bottomleft", "bottomright",
+ "left", "lefttop", "leftmiddle", "leftbottom",
+ "right", "righttop", "rightmiddle", "rightbottom",
+ "entire"
+ ];
- if(hueType == 'philipshue')
- {
+ if (hueType == 'philipshue') {
lightOptions.unshift("disabled");
}
$('.lidsb').html("");
var pos = "";
- for(var lightid in r)
- {
- if(hueType == 'philipshueentertainment')
- {
- if(groupLights.indexOf(lightid) == -1) continue;
+ for (var lightid in r) {
+ if (hueType == 'philipshueentertainment') {
+ if (groupLights.indexOf(lightid) == -1) continue;
- if(groupLightsLocations.hasOwnProperty(lightid))
- {
+ if (groupLightsLocations.hasOwnProperty(lightid)) {
lightLocation = groupLightsLocations[lightid];
var x = lightLocation[0];
var y = lightLocation[1];
var z = lightLocation[2];
var xval = (x < 0) ? "left" : "right";
- if(z != 1 && x >= -0.25 && x <= 0.25 ) xval = "";
- switch (z)
- {
+ if (z != 1 && x >= -0.25 && x <= 0.25) xval = "";
+ switch (z) {
case 1: // top / Ceiling height
pos = "top" + xval;
break;
@@ -1176,45 +1131,40 @@ function get_hue_lights(){
}
}
var options = "";
- for(var opt in lightOptions)
- {
+ for (var opt in lightOptions) {
var val = lightOptions[opt];
var txt = (val != 'entire' && val != 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
- options+= ''+$.i18n(txt+val)+' ';
+ options += '' + $.i18n(txt + val) + ' ';
}
- $('.lidsb').append(createTableRow([lightid+' ('+r[lightid].name+')', ''
- + options
- + ' ',''+$.i18n('wiz_hue_blinkblue',lightid)+' ']));
+ $('.lidsb').append(createTableRow([lightid + ' (' + r[lightid].name + ')', ''
+ + options
+ + ' ', '' + $.i18n('wiz_hue_blinkblue', lightid) + ' ']));
}
- if(hueType != 'philipshueentertainment')
- {
- $('.hue_sel_watch').bind("change", function(){
+ if (hueType != 'philipshueentertainment') {
+ $('.hue_sel_watch').bind("change", function () {
var cC = 0;
- for(var key in lightIDs)
- {
- if($('#hue_'+key).val() != "disabled")
- {
+ for (var key in lightIDs) {
+ if ($('#hue_' + key).val() != "disabled") {
cC++;
}
}
- cC == 0 ? $('#btn_wiz_save').attr("disabled",true) : $('#btn_wiz_save').attr("disabled",false);
+ (cC == 0) ? $('#btn_wiz_save').attr("disabled", true) : $('#btn_wiz_save').attr("disabled", false);
});
}
$('.hue_sel_watch').trigger('change');
}
- else
- {
- var txt = ''+$.i18n('wiz_hue_noids')+'
';
+ else {
+ var txt = '' + $.i18n('wiz_hue_noids') + '
';
$('#wizp2_body').append(txt);
}
}
});
}
-function abortConnection(UserInterval){
+function abortConnection(UserInterval) {
clearInterval(UserInterval);
$('#wizp1').toggle(false);
$('#wizp2').toggle(true);
@@ -1226,16 +1176,15 @@ function abortConnection(UserInterval){
// Wizard WLED
//****************************
var lights = null;
-function startWizardWLED(e)
-{
+function startWizardWLED(e) {
//create html
var wled_title = 'wiz_wled_title';
var wled_intro1 = 'wiz_wled_intro1';
- $('#wiz_header').html(' '+$.i18n(wled_title));
- $('#wizp1_body').html(''+$.i18n(wled_title)+' '+$.i18n(wled_intro1)+'
');
- $('#wizp1_footer').html(' '+$.i18n('general_btn_continue')+' '+$.i18n('general_btn_cancel')+' ');
+ $('#wiz_header').html(' ' + $.i18n(wled_title));
+ $('#wizp1_body').html('' + $.i18n(wled_title) + ' ' + $.i18n(wled_intro1) + '
');
+ $('#wizp1_footer').html(' ' + $.i18n('general_btn_continue') + ' ' + $.i18n('general_btn_cancel') + ' ');
/*$('#wizp2_body').html('
');
@@ -1249,254 +1198,235 @@ function startWizardWLED(e)
*/
//open modal
$("#wizard_modal").modal({
- backdrop : "static",
+ backdrop: "static",
keyboard: false,
show: true
});
//listen for continue
- $('#btn_wiz_cont').off().on('click',function() {
+ $('#btn_wiz_cont').off().on('click', function () {
+ /* For testing only
-// For testing only
- discover_wled();
+ discover_wled();
- var hostAddress = conf_editor.getEditor("root.specificOptions.host").getValue();
- if(hostAddress != "")
- {
- getProperties_wled(hostAddress,"info");
- identify_wled(hostAddress)
- }
-
-// For testing only
+ var hostAddress = conf_editor.getEditor("root.specificOptions.host").getValue();
+ if(hostAddress != "")
+ {
+ getProperties_wled(hostAddress,"info");
+ identify_wled(hostAddress)
+ }
+ For testing only */
});
}
-async function discover_wled(){
+async function discover_wled() {
+ const res = await requestLedDeviceDiscovery('wled');
- const res = await requestLedDeviceDiscovery ('wled');
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info
+ // Process devices returned by discovery
+ console.log(r);
- // Process devices returned by discovery
- console.log(r);
+ if (r.devices.length == 0)
+ $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
+ else {
+ for (const device of r.devices) {
+ console.log("Device:", device);
- if(r.devices.length == 0)
- $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
- else
- {
- for(const device of r.devices)
- {
- console.log("Device:", device);
+ var ip = device.hostname + ":" + device.port;
+ console.log("Host:", ip);
- var ip = device.hostname + ":" + device.port;
- console.log("Host:", ip);
-
- //wledIPs.push({internalipaddress : ip});
- }
- }
- }
+ //wledIPs.push({internalipaddress : ip});
+ }
+ }
+ }
}
-async function getProperties_wled(hostAddress, resourceFilter){
+async function getProperties_wled(hostAddress, resourceFilter) {
+ let params = { host: hostAddress, filter: resourceFilter };
- let params = { host: hostAddress, filter: resourceFilter};
+ const res = await requestLedDeviceProperties('wled', params);
- const res = await requestLedDeviceProperties ('wled', params);
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info
-
- // Process properties returned
- console.log(r);
- }
+ // Process properties returned
+ console.log(r);
+ }
}
-function identify_wled(hostAddress){
+function identify_wled(hostAddress) {
+ let params = { host: hostAddress };
- let params = { host: hostAddress };
-
- const res = requestLedDeviceIdentification ("wled", params);
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
-
- const r = res.info
- console.log(r);
- }
+ const res = requestLedDeviceIdentification("wled", params);
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
+ console.log(r);
+ }
}
//****************************
// Wizard Yeelight
//****************************
var lights = null;
-function startWizardYeelight(e)
-{
- //create html
+function startWizardYeelight(e) {
+ //create html
- var yeelight_title = 'wiz_yeelight_title';
- var yeelight_intro1 = 'wiz_yeelight_intro1';
+ var yeelight_title = 'wiz_yeelight_title';
+ var yeelight_intro1 = 'wiz_yeelight_intro1';
- $('#wiz_header').html(' '+$.i18n(yeelight_title));
- $('#wizp1_body').html(''+$.i18n(yeelight_title)+' '+$.i18n(yeelight_intro1)+'
');
+ $('#wiz_header').html(' ' + $.i18n(yeelight_title));
+ $('#wizp1_body').html('' + $.i18n(yeelight_title) + ' ' + $.i18n(yeelight_intro1) + '
');
- $('#wizp1_footer').html(' '
- +$.i18n('general_btn_continue')+' '
- +$.i18n('general_btn_cancel')+' ');
+ $('#wizp1_footer').html(' '
+ + $.i18n('general_btn_continue') + ' '
+ + $.i18n('general_btn_cancel') + ' ');
- $('#wizp2_body').html('
');
+ $('#wizp2_body').html('
');
- $('#wh_topcontainer').append('
');
+ $('#wh_topcontainer').append('
');
- $('#wizp2_body').append(''+$.i18n('wiz_yeelight_desc2')+'
');
+ $('#wizp2_body').append('' + $.i18n('wiz_yeelight_desc2') + '
');
- createTable("lidsh", "lidsb", "yee_ids_t");
- $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lights_title'),$.i18n('wiz_pos'),$.i18n('wiz_identify')], true));
- $('#wizp2_footer').html(' '
- +$.i18n('general_btn_save')+' '
- +$.i18n('general_btn_cancel')+'');
+ createTable("lidsh", "lidsb", "yee_ids_t");
+ $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lights_title'), $.i18n('wiz_pos'), $.i18n('wiz_identify')], true));
+ $('#wizp2_footer').html(' '
+ + $.i18n('general_btn_save') + ' '
+ + $.i18n('general_btn_cancel') + '');
- //open modal
- $("#wizard_modal").modal({backdrop : "static", keyboard: false, show: true });
+ //open modal
+ $("#wizard_modal").modal({ backdrop: "static", keyboard: false, show: true });
- //listen for continue
- $('#btn_wiz_cont').off().on('click',function() {
- beginWizardYeelight();
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
- });
+ //listen for continue
+ $('#btn_wiz_cont').off().on('click', function () {
+ beginWizardYeelight();
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ });
}
-function beginWizardYeelight()
-{
- lights = [];
- configuredLights = conf_editor.getEditor("root.specificOptions.lights").getValue();
+function beginWizardYeelight() {
+ lights = [];
+ configuredLights = conf_editor.getEditor("root.specificOptions.lights").getValue();
- discover_yeelight_lights();
+ discover_yeelight_lights();
- $('#btn_wiz_save').off().on("click", function(){
- var yeelightLedConfig = [];
- var finalLights = [];
+ $('#btn_wiz_save').off().on("click", function () {
+ var yeelightLedConfig = [];
+ var finalLights = [];
- //create yeelight led config
- for(var key in lights)
- {
- if($('#yee_'+key).val() !== "disabled")
- {
- //delete lights[key].model;
+ //create yeelight led config
+ for (var key in lights) {
+ if ($('#yee_' + key).val() !== "disabled") {
+ //delete lights[key].model;
- // Set Name to layout-position, if empty
- if ( lights[key].name === "" )
- {
- lights[key].name = $.i18n( 'conf_leds_layout_cl_'+$('#yee_'+key).val() );
- }
+ // Set Name to layout-position, if empty
+ if (lights[key].name === "") {
+ lights[key].name = $.i18n('conf_leds_layout_cl_' + $('#yee_' + key).val());
+ }
- finalLights.push( lights[key]);
+ finalLights.push(lights[key]);
- var name = lights[key].host;
- if ( lights[key].name !== "")
- name += '_'+lights[key].name;
+ var name = lights[key].host;
+ if (lights[key].name !== "")
+ name += '_' + lights[key].name;
- var idx_content = assignLightPos(key, $('#yee_'+key).val(), name);
- yeelightLedConfig.push(JSON.parse(JSON.stringify(idx_content)));
- }
- }
+ var idx_content = assignLightPos(key, $('#yee_' + key).val(), name);
+ yeelightLedConfig.push(JSON.parse(JSON.stringify(idx_content)));
+ }
+ }
- //LED layout
- window.serverConfig.leds = yeelightLedConfig;
+ //LED layout
+ window.serverConfig.leds = yeelightLedConfig;
- //LED device config
- //Start with a clean configuration
- var d = {};
+ //LED device config
+ //Start with a clean configuration
+ var d = {};
- d.type = 'yeelight';
- d.hardwareLedCount = finalLights.length;
- d.colorOrder = conf_editor.getEditor("root.generalOptions.colorOrder").getValue();
- d.colorModel = parseInt(conf_editor.getEditor("root.specificOptions.colorModel").getValue());
+ d.type = 'yeelight';
+ d.hardwareLedCount = finalLights.length;
+ d.colorOrder = conf_editor.getEditor("root.generalOptions.colorOrder").getValue();
+ d.colorModel = parseInt(conf_editor.getEditor("root.specificOptions.colorModel").getValue());
- d.transEffect = parseInt(conf_editor.getEditor("root.specificOptions.transEffect").getValue());
- d.transTime = parseInt(conf_editor.getEditor("root.specificOptions.transTime").getValue());
- d.extraTimeDarkness = parseInt(conf_editor.getEditor("root.specificOptions.extraTimeDarkness").getValue());
+ d.transEffect = parseInt(conf_editor.getEditor("root.specificOptions.transEffect").getValue());
+ d.transTime = parseInt(conf_editor.getEditor("root.specificOptions.transTime").getValue());
+ d.extraTimeDarkness = parseInt(conf_editor.getEditor("root.specificOptions.extraTimeDarkness").getValue());
- d.brightnessMin = parseInt(conf_editor.getEditor("root.specificOptions.brightnessMin").getValue());
- d.brightnessSwitchOffOnMinimum = JSON.parse(conf_editor.getEditor("root.specificOptions.brightnessSwitchOffOnMinimum").getValue());
- d.brightnessMax = parseInt(conf_editor.getEditor("root.specificOptions.brightnessMax").getValue());
- d.brightnessFactor = parseFloat(conf_editor.getEditor("root.specificOptions.brightnessFactor").getValue());
+ d.brightnessMin = parseInt(conf_editor.getEditor("root.specificOptions.brightnessMin").getValue());
+ d.brightnessSwitchOffOnMinimum = JSON.parse(conf_editor.getEditor("root.specificOptions.brightnessSwitchOffOnMinimum").getValue());
+ d.brightnessMax = parseInt(conf_editor.getEditor("root.specificOptions.brightnessMax").getValue());
+ d.brightnessFactor = parseFloat(conf_editor.getEditor("root.specificOptions.brightnessFactor").getValue());
- d.latchTime = parseInt(conf_editor.getEditor("root.specificOptions.latchTime").getValue());;
- d.debugLevel = parseInt(conf_editor.getEditor("root.specificOptions.debugLevel").getValue());
+ d.latchTime = parseInt(conf_editor.getEditor("root.specificOptions.latchTime").getValue());;
+ d.debugLevel = parseInt(conf_editor.getEditor("root.specificOptions.debugLevel").getValue());
- d.lights = finalLights;
+ d.lights = finalLights;
- window.serverConfig.device = d;
+ window.serverConfig.device = d;
- //smoothing off
- window.serverConfig.smoothing.enable = false;
+ //smoothing off
+ window.serverConfig.smoothing.enable = false;
- requestWriteConfig(window.serverConfig, true);
- resetWizard();
- });
+ requestWriteConfig(window.serverConfig, true);
+ resetWizard();
+ });
- $('#btn_wiz_abort').off().on('click', resetWizard);
+ $('#btn_wiz_abort').off().on('click', resetWizard);
}
function getHostInLights(hostname) {
- return lights.filter(
- function(lights) {
- return lights.host === hostname
- }
- );
+ return lights.filter(
+ function (lights) {
+ return lights.host === hostname
+ }
+ );
}
-async function discover_yeelight_lights(){
-
+async function discover_yeelight_lights() {
var light = {};
// Get discovered lights
- const res = await requestLedDeviceDiscovery ('yeelight');
+ const res = await requestLedDeviceDiscovery('yeelight');
// TODO: error case unhandled
// res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
+ if (res && !res.error) {
const r = res.info;
- // Process devices returned by discovery
- for(const device of r.devices)
- {
- //console.log("Device:", device);
+ // Process devices returned by discovery
+ for (const device of r.devices) {
+ //console.log("Device:", device);
- if( device.hostname !== "")
- {
- if ( getHostInLights ( device.hostname ).length === 0 )
- {
- light = {};
- light.host = device.hostname;
- light.port = device.port;
+ if (device.hostname !== "") {
+ if (getHostInLights(device.hostname).length === 0) {
+ light = {};
+ light.host = device.hostname;
+ light.port = device.port;
- light.name = device.other.name;
- light.model = device.other.model;
- lights.push(light);
- }
- }
- }
+ light.name = device.other.name;
+ light.model = device.other.model;
+ lights.push(light);
+ }
+ }
+ }
// Add additional items from configuration
- for(var keyConfig in configuredLights)
- {
-
- var [host, port]= configuredLights[keyConfig].host.split(":", 2);
+ for (var keyConfig in configuredLights) {
+ var [host, port] = configuredLights[keyConfig].host.split(":", 2);
//In case port has been explicitly provided, overwrite port given as part of hostname
- if ( configuredLights[keyConfig].port !== 0 )
+ if (configuredLights[keyConfig].port !== 0)
port = configuredLights[keyConfig].port;
- if ( host !== "" )
- if ( getHostInLights ( host ).length === 0 )
- {
+ if (host !== "")
+ if (getHostInLights(host).length === 0) {
light = {};
light.host = host;
light.port = port;
@@ -1510,476 +1440,434 @@ async function discover_yeelight_lights(){
}
}
-function assign_yeelight_lights(){
+function assign_yeelight_lights() {
+ var models = ['color', 'color1', 'color2', 'color4', 'stripe', 'strip1'];
- var models = ['color', 'color1', 'color2', 'color4', 'stripe', 'strip1'];
+ // If records are left for configuration
+ if (Object.keys(lights).length > 0) {
+ $('#wh_topcontainer').toggle(false);
+ $('#yee_ids_t,#btn_wiz_save').toggle(true);
- // If records are left for configuration
- if(Object.keys(lights).length > 0)
- {
- $('#wh_topcontainer').toggle(false);
- $('#yee_ids_t, #btn_wiz_save').toggle(true);
+ var lightOptions = [
+ "top", "topleft", "topright",
+ "bottom", "bottomleft", "bottomright",
+ "left", "lefttop", "leftmiddle", "leftbottom",
+ "right", "righttop", "rightmiddle", "rightbottom",
+ "entire"
+ ];
- var lightOptions = [
- "top", "topleft", "topright",
- "bottom", "bottomleft", "bottomright",
- "left", "lefttop", "leftmiddle", "leftbottom",
- "right", "righttop", "rightmiddle", "rightbottom",
- "entire"
- ];
+ lightOptions.unshift("disabled");
- lightOptions.unshift("disabled");
+ $('.lidsb').html("");
+ var pos = "";
- $('.lidsb').html("");
- var pos = "";
+ for (var lightid in lights) {
+ var lightHostname = lights[lightid].host;
+ var lightPort = lights[lightid].port;
+ var lightName = lights[lightid].name;
- for(var lightid in lights)
- {
- var lightHostname = lights[lightid].host;
- var lightPort = lights[lightid].port;
- var lightName = lights[lightid].name;
+ if (lightName === "")
+ lightName = $.i18n('edt_dev_spec_lights_itemtitle');
- if ( lightName === "" )
- lightName = $.i18n('edt_dev_spec_lights_itemtitle');
+ var options = "";
+ for (var opt in lightOptions) {
+ var val = lightOptions[opt];
+ var txt = (val !== 'entire' && val !== 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
+ options += '' + $.i18n(txt + val) + ' ';
+ }
- var options = "";
- for(var opt in lightOptions)
- {
- var val = lightOptions[opt];
- var txt = (val !== 'entire' && val !== 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
- options+= ''+$.i18n(txt+val)+' ';
- }
+ var enabled = 'enabled'
+ if (!models.includes(lights[lightid].model)) {
+ var enabled = 'disabled';
+ options = '' + $.i18n('wiz_yeelight_unsupported') + ' ';
+ }
- var enabled = 'enabled';
- if (! models.includes (lights[lightid].model) )
- {
- var enabled = 'disabled';
- options = ''+$.i18n('wiz_yeelight_unsupported')+' ';
- }
+ $('.lidsb').append(createTableRow([(parseInt(lightid, 10) + 1) + '. ' + lightName + ' (' + lightHostname + ')', ''
+ + options
+ + ' ', ''
+ + $.i18n('wiz_identify_light', lightName) + ' ']));
+ }
- $('.lidsb').append(createTableRow([(parseInt(lightid, 10) + 1)+'. '+lightName+' ('+lightHostname+')', ''
- + options
- + ' ',''
- + $.i18n('wiz_identify_light',lightName)+' ']));
- }
-
- $('.yee_sel_watch').bind("change", function(){
- var cC = 0;
- for(var key in lights)
- {
- if($('#yee_'+key).val() !== "disabled")
- {
- cC++;
- }
- }
- if ( cC === 0)
- $('#btn_wiz_save').attr("disabled",true);
- else
- $('#btn_wiz_save').attr("disabled",false);
- });
- $('.yee_sel_watch').trigger('change');
- }
- else
- {
- var noLightsTxt = ''+$.i18n('wiz_yeelight_noLights')+'
';
- $('#wizp2_body').append(noLightsTxt);
- }
+ $('.yee_sel_watch').bind("change", function () {
+ var cC = 0;
+ for (var key in lights) {
+ if ($('#yee_' + key).val() !== "disabled") {
+ cC++;
+ }
+ }
+ if (cC === 0)
+ $('#btn_wiz_save').attr("disabled", true);
+ else
+ $('#btn_wiz_save').attr("disabled", false);
+ });
+ $('.yee_sel_watch').trigger('change');
+ }
+ else {
+ var noLightsTxt = '' + $.i18n('wiz_yeelight_noLights') + '
';
+ $('#wizp2_body').append(noLightsTxt);
+ }
}
-async function getProperties_yeelight(hostname, port){
+async function getProperties_yeelight(hostname, port) {
+ let params = { hostname: hostname, port: port };
- let params = { hostname: hostname, port: port};
+ const res = await requestLedDeviceProperties('yeelight', params);
- const res = await requestLedDeviceProperties ('yeelight', params);
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info
-
- // Process properties returned
- console.log(r);
- }
+ // Process properties returned
+ console.log(r);
+ }
}
-function identify_yeelight_device(hostname, port){
+function identify_yeelight_device(hostname, port) {
+ let params = { hostname: hostname, port: port };
- let params = { hostname: hostname, port: port };
-
- const res = requestLedDeviceIdentification ("yeelight", params);
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- //const r = res.info;
- }
+ const res = requestLedDeviceIdentification("yeelight", params);
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ //const r = res.info;
+ }
}
//****************************
// Wizard AtmoOrb
//****************************
var lights = null;
-function startWizardAtmoOrb(e)
-{
- //create html
+function startWizardAtmoOrb(e) {
+ //create html
- var atmoorb_title = 'wiz_atmoorb_title';
- var atmoorb_intro1 = 'wiz_atmoorb_intro1';
+ var atmoorb_title = 'wiz_atmoorb_title';
+ var atmoorb_intro1 = 'wiz_atmoorb_intro1';
- $('#wiz_header').html(' '+$.i18n(atmoorb_title));
- $('#wizp1_body').html(''+$.i18n(atmoorb_title)+' '+$.i18n(atmoorb_intro1)+'
');
+ $('#wiz_header').html(' ' + $.i18n(atmoorb_title));
+ $('#wizp1_body').html('' + $.i18n(atmoorb_title) + ' ' + $.i18n(atmoorb_intro1) + '
');
- $('#wizp1_footer').html(' '
- +$.i18n('general_btn_continue')+' '
- +$.i18n('general_btn_cancel')+' ');
+ $('#wizp1_footer').html(' '
+ + $.i18n('general_btn_continue') + ' '
+ + $.i18n('general_btn_cancel') + ' ');
- $('#wizp2_body').html('
');
+ $('#wizp2_body').html('
');
- $('#wh_topcontainer').append('
');
+ $('#wh_topcontainer').append('
');
- $('#wizp2_body').append(''+$.i18n('wiz_atmoorb_desc2')+'
');
+ $('#wizp2_body').append('' + $.i18n('wiz_atmoorb_desc2') + '
');
- createTable("lidsh", "lidsb", "orb_ids_t");
- $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lights_title'),$.i18n('wiz_pos'),$.i18n('wiz_identify')], true));
- $('#wizp2_footer').html(' '
- +$.i18n('general_btn_save')+' '
- +$.i18n('general_btn_cancel')+'');
+ createTable("lidsh", "lidsb", "orb_ids_t");
+ $('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lights_title'), $.i18n('wiz_pos'), $.i18n('wiz_identify')], true));
+ $('#wizp2_footer').html(' '
+ + $.i18n('general_btn_save') + ' '
+ + $.i18n('general_btn_cancel') + '');
- //open modal
- $("#wizard_modal").modal({backdrop : "static", keyboard: false, show: true });
+ //open modal
+ $("#wizard_modal").modal({ backdrop: "static", keyboard: false, show: true });
- //listen for continue
- $('#btn_wiz_cont').off().on('click',function() {
- beginWizardAtmoOrb();
- $('#wizp1').toggle(false);
- $('#wizp2').toggle(true);
- });
+ //listen for continue
+ $('#btn_wiz_cont').off().on('click', function () {
+ beginWizardAtmoOrb();
+ $('#wizp1').toggle(false);
+ $('#wizp2').toggle(true);
+ });
}
-function beginWizardAtmoOrb()
-{
- lights = [];
- configuredLights = [];
+function beginWizardAtmoOrb() {
+ lights = [];
+ configuredLights = [];
- configruedOrbIds = conf_editor.getEditor("root.specificOptions.orbIds").getValue().trim();
- if ( configruedOrbIds.length !== 0 )
- {
- configuredLights = configruedOrbIds.split(",").map( Number );
- }
+ configruedOrbIds = conf_editor.getEditor("root.specificOptions.orbIds").getValue().trim();
+ if (configruedOrbIds.length !== 0) {
+ configuredLights = configruedOrbIds.split(",").map(Number);
+ }
- var multiCastGroup = conf_editor.getEditor("root.specificOptions.output").getValue();
- var multiCastPort = parseInt(conf_editor.getEditor("root.specificOptions.port").getValue());
+ var multiCastGroup = conf_editor.getEditor("root.specificOptions.output").getValue();
+ var multiCastPort = parseInt(conf_editor.getEditor("root.specificOptions.port").getValue());
- discover_atmoorb_lights(multiCastGroup, multiCastPort);
+ discover_atmoorb_lights(multiCastGroup, multiCastPort);
- $('#btn_wiz_save').off().on("click", function(){
- var atmoorbLedConfig = [];
- var finalLights = [];
+ $('#btn_wiz_save').off().on("click", function () {
+ var atmoorbLedConfig = [];
+ var finalLights = [];
- //create atmoorb led config
- for(var key in lights)
- {
- if($('#orb_'+key).val() !== "disabled")
- {
- // Set Name to layout-position, if empty
- if ( lights[key].name === "" )
- {
- lights[key].name = $.i18n( 'conf_leds_layout_cl_'+$('#orb_'+key).val() );
- }
+ //create atmoorb led config
+ for (var key in lights) {
+ if ($('#orb_' + key).val() !== "disabled") {
+ // Set Name to layout-position, if empty
+ if (lights[key].name === "") {
+ lights[key].name = $.i18n('conf_leds_layout_cl_' + $('#orb_' + key).val());
+ }
- finalLights.push( lights[key].id);
+ finalLights.push(lights[key].id);
- var name = lights[key].id;
- if ( lights[key].host !== "")
- name += ':' + lights[key].host;
+ var name = lights[key].id;
+ if (lights[key].host !== "")
+ name += ':' + lights[key].host;
- var idx_content = assignLightPos(key, $('#orb_'+key).val(), name);
- atmoorbLedConfig.push(JSON.parse(JSON.stringify(idx_content)));
- }
- }
+ var idx_content = assignLightPos(key, $('#orb_' + key).val(), name);
+ atmoorbLedConfig.push(JSON.parse(JSON.stringify(idx_content)));
+ }
+ }
- //LED layout
- window.serverConfig.leds = atmoorbLedConfig;
+ //LED layout
+ window.serverConfig.leds = atmoorbLedConfig;
- //LED device config
- //Start with a clean configuration
- var d = {};
+ //LED device config
+ //Start with a clean configuration
+ var d = {};
- d.type = 'atmoorb';
- d.hardwareLedCount = finalLights.length;
- d.colorOrder = conf_editor.getEditor("root.generalOptions.colorOrder").getValue();
+ d.type = 'atmoorb';
+ d.hardwareLedCount = finalLights.length;
+ d.colorOrder = conf_editor.getEditor("root.generalOptions.colorOrder").getValue();
- d.orbIds = finalLights.toString();
- d.useOrbSmoothing = (eV("useOrbSmoothing") == true);
+ d.orbIds = finalLights.toString();
+ d.useOrbSmoothing = (eV("useOrbSmoothing") == true);
- d.output = conf_editor.getEditor("root.specificOptions.output").getValue();
- d.port = parseInt(conf_editor.getEditor("root.specificOptions.port").getValue());
- d.latchTime = parseInt(conf_editor.getEditor("root.specificOptions.latchTime").getValue());;
+ d.output = conf_editor.getEditor("root.specificOptions.output").getValue();
+ d.port = parseInt(conf_editor.getEditor("root.specificOptions.port").getValue());
+ d.latchTime = parseInt(conf_editor.getEditor("root.specificOptions.latchTime").getValue());;
- window.serverConfig.device = d;
+ window.serverConfig.device = d;
- requestWriteConfig(window.serverConfig, true);
- resetWizard();
- });
+ requestWriteConfig(window.serverConfig, true);
+ resetWizard();
+ });
- $('#btn_wiz_abort').off().on('click', resetWizard);
+ $('#btn_wiz_abort').off().on('click', resetWizard);
}
function getIdInLights(id) {
- return lights.filter(
- function(lights) {
- return lights.id === id
- }
- );
+ return lights.filter(
+ function (lights) {
+ return lights.id === id
+ }
+ );
}
-async function discover_atmoorb_lights(multiCastGroup, multiCastPort){
-
+async function discover_atmoorb_lights(multiCastGroup, multiCastPort) {
var light = {};
- if ( multiCastGroup === "" )
- multiCastGroup = "239.255.255.250";
+ if (multiCastGroup === "")
+ multiCastGroup = "239.255.255.250";
- if ( multiCastPort === "")
+ if (multiCastPort === "")
multiCastPort = 49692;
- let params = { multiCastGroup : multiCastGroup, multiCastPort : multiCastPort};
+ let params = { multiCastGroup: multiCastGroup, multiCastPort: multiCastPort };
// Get discovered lights
- const res = await requestLedDeviceDiscovery ('atmoorb', params);
+ const res = await requestLedDeviceDiscovery('atmoorb', params);
// TODO: error case unhandled
// res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info;
+ if (res && !res.error) {
+ const r = res.info
- // Process devices returned by discovery
- for(const device of r.devices)
- {
- if( device.id !== "")
- {
- if ( getIdInLights ( device.id ).length === 0 )
- {
- light = {};
- light.id = device.id;
- light.ip = device.ip;
- light.host = device.hostname;
- lights.push(light);
- }
- }
- }
-
- // Add additional items from configuration
- for(const keyConfig in configuredLights)
- {
- if ( configuredLights[keyConfig] !== "" && !isNaN(configuredLights[keyConfig]) )
- {
- if ( getIdInLights ( configuredLights[keyConfig] ).length === 0 )
- {
- light = {};
- light.id = configuredLights[keyConfig];
- light.ip = "";
- light.host = "";
- lights.push(light);
- }
- }
+ // Process devices returned by discovery
+ for (const device of r.devices) {
+ if (device.id !== "") {
+ if (getIdInLights(device.id).length === 0) {
+ light = {};
+ light.id = device.id;
+ light.ip = device.ip;
+ light.host = device.hostname;
+ lights.push(light);
+ }
+ }
}
- lights.sort((a, b) => (a.id > b.id) ? 1 : -1);
+ // Add additional items from configuration
+ for (const keyConfig in configuredLights) {
+ if (configuredLights[keyConfig] !== "" && !isNaN(configuredLights[keyConfig])) {
+ if (getIdInLights(configuredLights[keyConfig]).length === 0) {
+ light = {};
+ light.id = configuredLights[keyConfig];
+ light.ip = "";
+ light.host = "";
+ lights.push(light);
+ }
+ }
+ }
+
+ lights.sort((a, b) => (a.id > b.id) ? 1 : -1);
assign_atmoorb_lights();
}
}
-function assign_atmoorb_lights(){
+function assign_atmoorb_lights() {
+ // If records are left for configuration
+ if (Object.keys(lights).length > 0) {
+ $('#wh_topcontainer').toggle(false);
+ $('#orb_ids_t, #btn_wiz_save').toggle(true);
- // If records are left for configuration
- if(Object.keys(lights).length > 0)
- {
- $('#wh_topcontainer').toggle(false);
- $('#orb_ids_t, #btn_wiz_save').toggle(true);
+ var lightOptions = [
+ "top", "topleft", "topright",
+ "bottom", "bottomleft", "bottomright",
+ "left", "lefttop", "leftmiddle", "leftbottom",
+ "right", "righttop", "rightmiddle", "rightbottom",
+ "entire"
+ ];
- var lightOptions = [
- "top", "topleft", "topright",
- "bottom", "bottomleft", "bottomright",
- "left", "lefttop", "leftmiddle", "leftbottom",
- "right", "righttop", "rightmiddle", "rightbottom",
- "entire"
- ];
+ lightOptions.unshift("disabled");
- lightOptions.unshift("disabled");
+ $('.lidsb').html("");
+ var pos = "";
- $('.lidsb').html("");
- var pos = "";
+ for (var lightid in lights) {
+ var orbId = lights[lightid].id;
+ var orbIp = lights[lightid].ip;
+ var orbHostname = lights[lightid].host;
- for(var lightid in lights)
- {
- var orbId = lights[lightid].id;
- var orbIp = lights[lightid].ip;
- var orbHostname = lights[lightid].host;
+ if (orbHostname === "")
+ orbHostname = $.i18n('edt_dev_spec_lights_itemtitle');
- if ( orbHostname === "" )
- orbHostname = $.i18n('edt_dev_spec_lights_itemtitle');
+ var options = "";
+ for (var opt in lightOptions) {
+ var val = lightOptions[opt];
+ var txt = (val !== 'entire' && val !== 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
+ options += '' + $.i18n(txt + val) + ' ';
+ }
- var options = "";
- for(var opt in lightOptions)
- {
- var val = lightOptions[opt];
- var txt = (val !== 'entire' && val !== 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
- options+= ''+$.i18n(txt+val)+' ';
- }
+ var enabled = 'enabled'
+ if (orbId < 1 || orbId > 255) {
+ enabled = 'disabled'
+ options = '' + $.i18n('wiz_atmoorb_unsupported') + ' ';
+ }
- var enabled = 'enabled';
- if ( orbId < 1 || orbId > 255 )
- {
- enabled = 'disabled';
- options = ''+$.i18n('wiz_atmoorb_unsupported')+' ';
- }
+ var lightAnnotation = "";
+ if (orbIp !== "") {
+ lightAnnotation = ': ' + orbIp + ' (' + orbHostname + ')';
+ }
- var lightAnnotation ="";
- if ( orbIp !== "" )
- {
- lightAnnotation = ': '+orbIp+' ('+orbHostname+')';
- }
+ $('.lidsb').append(createTableRow([orbId + lightAnnotation, ''
+ + options
+ + ' ', ''
+ + $.i18n('wiz_identify_light', orbId) + ' ']));
+ }
- $('.lidsb').append(createTableRow([orbId + lightAnnotation, ''
- + options
- + ' ',''
- + $.i18n('wiz_identify_light',orbId)+' ']));
- }
-
- $('.orb_sel_watch').bind("change", function(){
- var cC = 0;
- for(var key in lights)
- {
- if($('#orb_'+key).val() !== "disabled")
- {
- cC++;
- }
- }
- if ( cC === 0)
- $('#btn_wiz_save').attr("disabled",true);
- else
- $('#btn_wiz_save').attr("disabled",false);
- });
- $('.orb_sel_watch').trigger('change');
- }
- else
- {
- var noLightsTxt = ''+$.i18n('wiz_atmoorb_noLights')+'
';
- $('#wizp2_body').append(noLightsTxt);
- }
+ $('.orb_sel_watch').bind("change", function () {
+ var cC = 0;
+ for (var key in lights) {
+ if ($('#orb_' + key).val() !== "disabled") {
+ cC++;
+ }
+ }
+ if (cC === 0)
+ $('#btn_wiz_save').attr("disabled", true);
+ else
+ $('#btn_wiz_save').attr("disabled", false);
+ });
+ $('.orb_sel_watch').trigger('change');
+ }
+ else {
+ var noLightsTxt = '' + $.i18n('wiz_atmoorb_noLights') + '
';
+ $('#wizp2_body').append(noLightsTxt);
+ }
}
-function identify_atmoorb_device(orbId){
+function identify_atmoorb_device(orbId) {
+ let params = { id: orbId };
- let params = { id : orbId };
-
- const res = requestLedDeviceIdentification ("atmoorb", params);
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info
- }
+ const res = requestLedDeviceIdentification("atmoorb", params);
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
+ }
}
//****************************
// Wizard/Routines Nanoleaf
//****************************
-async function discover_nanoleaf(){
+async function discover_nanoleaf() {
+ const res = await requestLedDeviceDiscovery('nanoleaf');
- const res = await requestLedDeviceDiscovery ('nanoleaf');
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info
+ // Process devices returned by discovery
+ console.log(r);
- // Process devices returned by discovery
- console.log(r);
+ if (r.devices.length == 0)
+ $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
+ else {
+ for (const device of r.devices) {
+ console.log("Device:", device);
- if(r.devices.length == 0)
- $('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
- else
- {
- for(const device of r.devices)
- {
- console.log("Device:", device);
+ var ip = device.hostname + ":" + device.port;
+ console.log("Host:", ip);
- var ip = device.hostname + ":" + device.port;
- console.log("Host:", ip);
-
- //nanoleafIPs.push({internalipaddress : ip});
- }
- }
- }
+ //nanoleafIPs.push({internalipaddress : ip});
+ }
+ }
+ }
}
-async function getProperties_nanoleaf(hostAddress, authToken, resourceFilter){
+async function getProperties_nanoleaf(hostAddress, authToken, resourceFilter) {
+ let params = { host: hostAddress, token: authToken, filter: resourceFilter };
- let params = { host: hostAddress, token: authToken, filter: resourceFilter};
+ const res = await requestLedDeviceProperties('nanoleaf', params);
- const res = await requestLedDeviceProperties ('nanoleaf', params);
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info
-
- // Process properties returned
- console.log(r);
- }
+ // Process properties returned
+ console.log(r);
+ }
}
-function identify_nanoleaf(hostAddress, authToken){
+function identify_nanoleaf(hostAddress, authToken) {
+ let params = { host: hostAddress, token: authToken };
- let params = { host: hostAddress, token: authToken};
-
- const res = requestLedDeviceIdentification ("nanoleaf", params);
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
-
- const r = res.info
- console.log(r);
- }
+ const res = requestLedDeviceIdentification("nanoleaf", params);
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
+ console.log(r);
+ }
}
//****************************
// Wizard/Routines RS232-Devices
//****************************
-async function discover_providerRs232(rs232Type){
+async function discover_providerRs232(rs232Type) {
+ const res = await requestLedDeviceDiscovery(rs232Type);
- const res = await requestLedDeviceDiscovery (rs232Type);
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info
-
- // Process serialPorts returned by discover
- console.log(r);
- }
+ // Process serialPorts returned by discover
+ console.log(r);
+ }
}
//****************************
// Wizard/Routines HID (USB)-Devices
//****************************
-async function discover_providerHid(hidType){
+async function discover_providerHid(hidType) {
+ const res = await requestLedDeviceDiscovery(hidType);
+ console.log("discover_providerHid", res);
- const res = await requestLedDeviceDiscovery (hidType);
- console.log("discover_providerHid" ,res);
+ // TODO: error case unhandled
+ // res can be: false (timeout) or res.error (not found)
+ if (res && !res.error) {
+ const r = res.info
- // TODO: error case unhandled
- // res can be: false (timeout) or res.error (not found)
- if(res && !res.error){
- const r = res.info
-
- // Process HID returned by discover
- console.log(r);
- }
+ // Process HID returned by discover
+ console.log(r);
+ }
}
-
diff --git a/cmake/nsis/template/FindProcDLL.dll b/cmake/nsis/template/FindProcDLL.dll
new file mode 100644
index 00000000..0e66ac61
Binary files /dev/null and b/cmake/nsis/template/FindProcDLL.dll differ
diff --git a/cmake/nsis/template/NSIS.template.in b/cmake/nsis/template/NSIS.template.in
index 292c2ae9..e86adc24 100644
--- a/cmake/nsis/template/NSIS.template.in
+++ b/cmake/nsis/template/NSIS.template.in
@@ -384,7 +384,7 @@ Function un.RemoveFromPath
FunctionEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; Uninstall sutff
+; Uninstall stuff
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
###########################################
@@ -810,6 +810,15 @@ FunctionEnd
;--------------------------------
; determine admin versus local install
Function un.onInit
+ ; Check if Hyperion is running
+ loopIsRunningCheck:
+ FindProcDLL::FindProc "hyperiond.exe"
+ IntCmp $R0 1 0 notRunning
+ MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION "Hyperion is running.$\n$\nClose it and press Retry, or press Cancel to exit." IDRETRY loopIsRunningCheck IDCANCEL abortnow
+
+ abortnow:
+ Abort
+ notRunning:
ClearErrors
UserInfo::GetName
@@ -873,6 +882,16 @@ FunctionEnd
;Uninstaller Section
Section "Uninstall"
+ ; Check if Hyperion is running
+ loopIsRunningCheck:
+ FindProcDLL::FindProc "hyperiond.exe"
+ IntCmp $R0 1 0 notRunning
+ MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION "Hyperion is running.$\n$\nClose it and press Retry, or press Cancel to exit." IDRETRY loopIsRunningCheck IDCANCEL abortnow
+
+ abortnow:
+ Abort
+ notRunning:
+
ReadRegStr $START_MENU SHCTX \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu"
;MessageBox MB_OK "Start menu is in: $START_MENU"
@@ -970,6 +989,16 @@ SectionEnd
; "Program Files" for AllUsers, "My Documents" for JustMe...
Function .onInit
+ ; Check if Hyperion is running
+ loopIsRunningCheck:
+ FindProcDLL::FindProc "hyperiond.exe"
+ IntCmp $R0 1 0 notRunning
+ MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION "Hyperion is running.$\n$\nClose it and press Retry, or press Cancel to exit." IDRETRY loopIsRunningCheck IDCANCEL abortnow
+
+ abortnow:
+ Abort
+ notRunning:
+
StrCmp "@CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL@" "ON" 0 inst
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "UninstallString"
diff --git a/include/api/API.h b/include/api/API.h
index dd92b2a9..aa134ccc 100644
--- a/include/api/API.h
+++ b/include/api/API.h
@@ -112,8 +112,9 @@ protected:
/// @param dat The effect data
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
/// REQUIRED dat fields: effectName, priority, duration, origin
+ /// @return True on success else false
///
- void setEffect(const EffectCmdData &dat, hyperion::Components callerComp = hyperion::COMP_INVALID);
+ bool setEffect(const EffectCmdData &dat, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Set source auto select enabled or disabled
@@ -174,8 +175,10 @@ protected:
///
/// @brief Start instance
/// @param index The instance index
+ /// @param tan The tan
+ /// @return True on success else false
///
- void startInstance(quint8 index);
+ bool startInstance(quint8 index, int tan = 0);
///
/// @brief Stop instance
@@ -277,8 +280,9 @@ protected:
/// @brief Set a new token request
/// @param comment The comment
/// @param id The id
+ /// @param tan The tan
///
- void setNewTokenRequest(const QString &comment, const QString &id);
+ void setNewTokenRequest(const QString &comment, const QString &id, const int &tan);
///
/// @brief Cancel new token request
@@ -367,7 +371,7 @@ signals:
///
/// @brief Emits whenever a new Token request is pending. This signal is just active when ADMIN ACCESS has been granted
- /// @param id The id of the request
+ /// @param id The id of the request
/// @param comment The comment of the request; If the commen is EMPTY the request has been revoked by the caller. So remove it from the pending list
///
void onPendingTokenRequest(const QString &id, const QString &comment);
@@ -378,8 +382,15 @@ signals:
/// @param token The new token that is now valid
/// @param comment The comment that was part of the request
/// @param id The id that was part of the request
+ /// @param tan The tan that was part of the request
///
- void onTokenResponse(bool success, const QString &token, const QString &comment, const QString &id);
+ void onTokenResponse(bool success, const QString &token, const QString &comment, const QString &id, const int &tan);
+
+ ///
+ /// @brief Handle emits from HyperionIManager of startInstance request, just if QObject matches with this instance it will emit.
+ /// @param tan The tan that was part of the request
+ ///
+ void onStartInstanceResponse(const int &tan);
private slots:
///
@@ -388,16 +399,6 @@ private slots:
///
void requestActiveRegister(QObject *callerInstance);
- ///
- /// @brief See onTokenResponse(). Here we validate the caller instance and on success we will emit onTokenResponse()
- /// @param success If true the request was accepted else false and no token was created
- /// @param caller The origin caller instance who requested this token
- /// @param token The new token that is now valid
- /// @param comment The comment that was part of the request
- /// @param id The id that was part of the request
- ///
- void checkTokenResponse(bool success, QObject *caller, const QString &token, const QString &comment, const QString &id);
-
private:
void stopDataConnectionss();
diff --git a/include/api/JsonAPI.h b/include/api/JsonAPI.h
index 0601415d..d7009a27 100644
--- a/include/api/JsonAPI.h
+++ b/include/api/JsonAPI.h
@@ -65,8 +65,8 @@ public slots:
private slots:
///
/// @brief Handle emits from API of a new Token request.
- /// @param id The id of the request
- /// @param The comment which needs to be accepted
+ /// @param id The id of the request
+ /// @param comment The comment which needs to be accepted
///
void newPendingTokenRequest(const QString &id, const QString &comment);
@@ -76,8 +76,9 @@ private slots:
/// @param token The new token that is now valid
/// @param comment The comment that was part of the request
/// @param id The id that was part of the request
+ /// @param tan The tan that was part of the request
///
- void handleTokenResponse(bool success, const QString &token, const QString &comment, const QString &id);
+ void handleTokenResponse(bool success, const QString &token, const QString &comment, const QString &id, const int &tan);
///
/// @brief Handle whenever the state of a instance (HyperionIManager) changes according to enum instanceState
diff --git a/include/hyperion/AuthManager.h b/include/hyperion/AuthManager.h
index 41906465..1f22fb3a 100644
--- a/include/hyperion/AuthManager.h
+++ b/include/hyperion/AuthManager.h
@@ -29,6 +29,7 @@ public:
QString id;
QString comment;
QObject *caller;
+ int tan;
uint64_t timeoutTime;
QString token;
QString lastUse;
@@ -142,16 +143,16 @@ public slots:
/// @param caller The QObject of the caller to deliver the reply
/// @param comment The comment as ident helper
/// @param id The id created by the caller
+ /// @param tan The tan created by the caller
///
- void setNewTokenRequest(QObject *caller, const QString &comment, const QString &id);
+ void setNewTokenRequest(QObject *caller, const QString &comment, const QString &id, const int &tan = 0);
///
/// @brief Cancel a pending token request with the provided comment and id as identifier helper
/// @param caller The QObject of the caller to deliver the reply
- /// @param comment The comment as ident helper
/// @param id The id created by the caller
///
- void cancelNewTokenRequest(QObject *caller, const QString &comment, const QString &id);
+ void cancelNewTokenRequest(QObject *caller, const QString &, const QString &id);
///
/// @brief Handle a token request by id, generate token and inform token caller or deny
@@ -200,8 +201,9 @@ signals:
/// @param token The new token that is now valid
/// @param comment The comment that was part of the request
/// @param id The id that was part of the request
+ /// @param tan The tan that was part of the request
///
- void tokenResponse(bool success, QObject *caller, const QString &token, const QString &comment, const QString &id);
+ void tokenResponse(bool success, QObject *caller, const QString &token, const QString &comment, const QString &id, const int &tan);
///
/// @brief Emits whenever the token list changes
diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h
index 9b301e2f..90a76591 100644
--- a/include/hyperion/Hyperion.h
+++ b/include/hyperion/Hyperion.h
@@ -474,7 +474,7 @@ private slots:
void handleNewVideoMode(VideoMode mode) { _currVideoMode = mode; }
- void handlPriorityChangedLedDevice(const quint8& priority);
+ void handlePriorityChangedLedDevice(const quint8& priority);
private:
friend class HyperionDaemon;
diff --git a/include/hyperion/HyperionIManager.h b/include/hyperion/HyperionIManager.h
index 73b86654..c7b1fca9 100644
--- a/include/hyperion/HyperionIManager.h
+++ b/include/hyperion/HyperionIManager.h
@@ -28,6 +28,12 @@ class HyperionIManager : public QObject
Q_OBJECT
public:
+ struct PendingRequests
+ {
+ QObject *caller;
+ int tan;
+ };
+
// global instance pointer
static HyperionIManager* getInstance() { return HIMinstance; }
static HyperionIManager* HIMinstance;
@@ -54,11 +60,11 @@ public slots:
///
/// @brief Start a Hyperion instance
- /// @param instance Instance index
- /// @param block If true return when thread has been started
+ /// @param instance Instance index
+ /// @param block If true return when thread has been started
/// @return Return true on success, false if not found in db
///
- bool startInstance(quint8 inst, bool block = false);
+ bool startInstance(quint8 inst, bool block = false, QObject *caller = nullptr, int tan = 0);
///
/// @brief Stop a Hyperion instance
@@ -110,6 +116,13 @@ signals:
///
void change();
+ ///
+ /// @brief Emits when the user has requested to start a instance
+ /// @param caller The origin caller instance who requested
+ /// @param tan The tan that was part of the request
+ ///
+ void startInstanceResponse(QObject *caller, const int &tan);
+
signals:
///////////////////////////////////////
/// FROM HYPERIONDAEMON TO HYPERION ///
@@ -180,4 +193,6 @@ private:
const QString _rootPath;
QMap _runningInstances;
QList _startQueue;
+ /// All pending requests
+ QMap _pendingRequests;
};
diff --git a/include/ssdp/SSDPHandler.h b/include/ssdp/SSDPHandler.h
index dc20bd29..9f14cace 100644
--- a/include/ssdp/SSDPHandler.h
+++ b/include/ssdp/SSDPHandler.h
@@ -20,7 +20,7 @@ class SSDPHandler : public SSDPServer
{
Q_OBJECT
public:
- SSDPHandler(WebServer* webserver, quint16 flatBufPort, quint16 jsonServerPort, const QString &name, QObject * parent = nullptr);
+ SSDPHandler(WebServer* webserver, quint16 flatBufPort, quint16 protoBufPort, quint16 jsonServerPort, quint16 sslPort, const QString &name, QObject * parent = nullptr);
~SSDPHandler() override;
///
diff --git a/include/ssdp/SSDPServer.h b/include/ssdp/SSDPServer.h
index 9cff55d4..6bfe5d1c 100644
--- a/include/ssdp/SSDPServer.h
+++ b/include/ssdp/SSDPServer.h
@@ -85,16 +85,36 @@ public:
quint16 getFlatBufPort() const { return _fbsPort.toInt(); };
///
- /// @brief set new jsonserver server port
+ /// @brief set new protobuf server port
+ ///
+ void setProtoBufPort(quint16 port) { _pbsPort = QString::number(port); };
+
+ ///
+ /// @brief Get current protobuf server port
+ ///
+ quint16 getProtoBufPort() const { return _pbsPort.toInt(); };
+
+ ///
+ /// @brief set new json server port
///
void setJsonServerPort(quint16 port) { _jssPort = QString::number(port); };
///
- /// @brief get new jsonserver server port
+ /// @brief get new json server port
///
quint16 getJsonServerPort() const { return _jssPort.toInt(); };
- ///
+ ///
+ /// @brief set new ssl server port
+ ///
+ void setSSLServerPort(quint16 port) { _sslPort = QString::number(port); };
+
+ ///
+ /// @brief get new ssl server port
+ ///
+ quint16 getSSLServerPort() const { return _sslPort.toInt(); };
+
+ ///
/// @brief set new hyperion name
///
void setHyperionName(const QString &name) { _name = name; };
@@ -119,13 +139,15 @@ private:
Logger* _log;
QUdpSocket* _udpSocket;
- QString _serverHeader;
- QString _uuid;
- QString _fbsPort;
- QString _jssPort;
- QString _name;
- QString _descAddress;
- bool _running;
+ QString _serverHeader,
+ _uuid,
+ _fbsPort,
+ _pbsPort,
+ _jssPort,
+ _sslPort,
+ _name,
+ _descAddress;
+ bool _running;
private slots:
void readPendingDatagrams();
diff --git a/include/utils/QStringUtils.h b/include/utils/QStringUtils.h
index 52d245c0..6b302d0a 100644
--- a/include/utils/QStringUtils.h
+++ b/include/utils/QStringUtils.h
@@ -3,6 +3,8 @@
#include
#include
+#include
+#include
namespace QStringUtils {
@@ -13,11 +15,11 @@ enum class SplitBehavior {
inline QStringList split (const QString &string, const QString &sep, SplitBehavior behavior = SplitBehavior::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive)
{
- #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
return behavior == SplitBehavior::SkipEmptyParts ? string.split(sep, Qt::SkipEmptyParts , cs) : string.split(sep, Qt::KeepEmptyParts , cs);
- #else
+#else
return behavior == SplitBehavior::SkipEmptyParts ? string.split(sep, QString::SkipEmptyParts , cs) : string.split(sep, QString::KeepEmptyParts , cs);
- #endif
+#endif
}
inline QStringList split (const QString &string, QChar sep, SplitBehavior behavior = SplitBehavior::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive)
@@ -37,6 +39,34 @@ inline QStringList split (const QString &string, const QRegExp &rx, SplitBehavio
return behavior == SplitBehavior::SkipEmptyParts ? string.split(rx, QString::SkipEmptyParts) : string.split(rx, QString::KeepEmptyParts);
#endif
}
+
+inline QVector splitRef(const QString &string, const QString &sep, SplitBehavior behavior = SplitBehavior::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive)
+{
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
+ return string.splitRef(sep, behavior == SplitBehavior::SkipEmptyParts ? Qt::SkipEmptyParts : Qt::KeepEmptyParts , cs);
+#else
+ return string.splitRef(sep, behavior == SplitBehavior::SkipEmptyParts ? QString::SkipEmptyParts : QString::KeepEmptyParts, cs);
+#endif
+}
+
+inline QVector splitRef(const QString &string, QChar sep, SplitBehavior behavior = SplitBehavior::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive)
+{
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
+ return string.splitRef(sep, behavior == SplitBehavior::SkipEmptyParts ? Qt::SkipEmptyParts : Qt::KeepEmptyParts, cs);
+#else
+ return string.splitRef(sep, behavior == SplitBehavior::SkipEmptyParts ? QString::SkipEmptyParts : QString::KeepEmptyParts, cs);
+#endif
+}
+
+inline QVector splitRef(const QString &string, const QRegExp &rx, SplitBehavior behavior = SplitBehavior::KeepEmptyParts)
+{
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
+ return string.splitRef(rx,behavior == SplitBehavior::SkipEmptyParts ? Qt::SkipEmptyParts : Qt::KeepEmptyParts);
+#else
+ return string.splitRef(rx, behavior == SplitBehavior::SkipEmptyParts ? QString::SkipEmptyParts : QString::KeepEmptyParts);
+#endif
+}
+
}
#endif // QSTRINGUTILS_H
diff --git a/include/utils/hyperion.h b/include/utils/hyperion.h
index e930a71a..af650f63 100644
--- a/include/utils/hyperion.h
+++ b/include/utils/hyperion.h
@@ -234,12 +234,6 @@ namespace hyperion {
midPointsY.erase(std::unique(midPointsY.begin(), midPointsY.end()), midPointsY.end());
QSize gridSize( midPointsX.size(), midPointsY.size() );
- //Debug(_log, "LED layout grid size: %dx%d", gridSize.width(), gridSize.height());
-
- // Limit to 80px for performance reasons
- const int pl = 80;
- if(gridSize.width() > pl || gridSize.height() > pl)
- gridSize.scale(pl, pl, Qt::KeepAspectRatio);
// Correct the grid in case it is malformed in width vs height
// Expected is at least 50% of width <-> height
@@ -248,6 +242,13 @@ namespace hyperion {
else if((gridSize.width() / gridSize.height()) < 0.5)
gridSize.setWidth(qMax(1,gridSize.height()/2));
+ // Limit to 80px for performance reasons
+ const int pl = 80;
+ if(gridSize.width() > pl || gridSize.height() > pl)
+ {
+ gridSize.scale(pl, pl, Qt::KeepAspectRatio);
+ }
+
return gridSize;
}
};
diff --git a/libsrc/api/API.cpp b/libsrc/api/API.cpp
index 298ad334..7a22d9cc 100644
--- a/libsrc/api/API.cpp
+++ b/libsrc/api/API.cpp
@@ -56,7 +56,18 @@ API::API(Logger *log, bool localConnection, QObject *parent)
//connect(ApiSync::getInstance(), &ApiSync::requestActiveRegister, this, &API::requestActiveRegister, Qt::QueuedConnection);
// connect to possible token responses that has been requested
- connect(_authManager, &AuthManager::tokenResponse, this, &API::checkTokenResponse);
+ connect(_authManager, &AuthManager::tokenResponse, [=] (bool success, QObject *caller, const QString &token, const QString &comment, const QString &id, const int &tan)
+ {
+ if (this == caller)
+ emit onTokenResponse(success, token, comment, id, tan);
+ });
+
+ // connect to possible startInstance responses that has been requested
+ connect(_instanceManager, &HyperionIManager::startInstanceResponse, [=] (QObject *caller, const int &tan)
+ {
+ if (this == caller)
+ emit onStartInstanceResponse(tan);
+ });
}
void API::init()
@@ -211,16 +222,19 @@ void API::setVideoMode(VideoMode mode, hyperion::Components callerComp)
QMetaObject::invokeMethod(_hyperion, "setVideoMode", Qt::QueuedConnection, Q_ARG(VideoMode, mode));
}
-void API::setEffect(const EffectCmdData &dat, hyperion::Components callerComp)
+bool API::setEffect(const EffectCmdData &dat, hyperion::Components callerComp)
{
+ int res;
if (!dat.args.isEmpty())
{
- QMetaObject::invokeMethod(_hyperion, "setEffect", Qt::QueuedConnection, Q_ARG(QString, dat.effectName), Q_ARG(QJsonObject, dat.args), Q_ARG(int, dat.priority), Q_ARG(int, dat.duration), Q_ARG(QString, dat.pythonScript), Q_ARG(QString, dat.origin), Q_ARG(QString, dat.data));
+ QMetaObject::invokeMethod(_hyperion, "setEffect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, res), Q_ARG(QString, dat.effectName), Q_ARG(QJsonObject, dat.args), Q_ARG(int, dat.priority), Q_ARG(int, dat.duration), Q_ARG(QString, dat.pythonScript), Q_ARG(QString, dat.origin), Q_ARG(QString, dat.data));
}
else
{
- QMetaObject::invokeMethod(_hyperion, "setEffect", Qt::QueuedConnection, Q_ARG(QString, dat.effectName), Q_ARG(int, dat.priority), Q_ARG(int, dat.duration), Q_ARG(QString, dat.origin));
+ QMetaObject::invokeMethod(_hyperion, "setEffect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, res), Q_ARG(QString, dat.effectName), Q_ARG(int, dat.priority), Q_ARG(int, dat.duration), Q_ARG(QString, dat.origin));
}
+
+ return res >= 0;
}
void API::setSourceAutoSelect(bool state, hyperion::Components callerComp)
@@ -285,9 +299,14 @@ QVector API::getAllInstanceData()
return vec;
}
-void API::startInstance(quint8 index)
+bool API::startInstance(quint8 index, int tan)
{
- QMetaObject::invokeMethod(_instanceManager, "startInstance", Qt::QueuedConnection, Q_ARG(quint8, index));
+ bool res;
+ (_instanceManager->thread() != this->thread())
+ ? QMetaObject::invokeMethod(_instanceManager, "startInstance", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, res), Q_ARG(quint8, index), Q_ARG(bool, false), Q_ARG(QObject*, this), Q_ARG(int, tan))
+ : res = _instanceManager->startInstance(index, false, this, tan);
+
+ return res;
}
void API::stopInstance(quint8 index)
@@ -407,9 +426,9 @@ QString API::deleteToken(const QString &id)
return "";
}
-void API::setNewTokenRequest(const QString &comment, const QString &id)
+void API::setNewTokenRequest(const QString &comment, const QString &id, const int &tan)
{
- QMetaObject::invokeMethod(_authManager, "setNewTokenRequest", Qt::QueuedConnection, Q_ARG(QObject *, this), Q_ARG(QString, comment), Q_ARG(QString, id));
+ QMetaObject::invokeMethod(_authManager, "setNewTokenRequest", Qt::QueuedConnection, Q_ARG(QObject *, this), Q_ARG(QString, comment), Q_ARG(QString, id), Q_ARG(int, tan));
}
void API::cancelNewTokenRequest(const QString &comment, const QString &id)
@@ -465,12 +484,11 @@ bool API::getUserToken(QString &userToken)
bool API::isTokenAuthorized(const QString &token)
{
- bool res;
- QMetaObject::invokeMethod(_authManager, "isTokenAuthorized", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, res), Q_ARG(QString, token));
- if (res)
- _authorized = true;
+ (_authManager->thread() != this->thread())
+ ? QMetaObject::invokeMethod(_authManager, "isTokenAuthorized", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, _authorized), Q_ARG(QString, token))
+ : _authorized = _authManager->isTokenAuthorized(token);
- return res;
+ return _authorized;
}
bool API::isUserAuthorized(const QString &password)
@@ -503,12 +521,6 @@ void API::logout()
stopDataConnectionss();
}
-void API::checkTokenResponse(bool success, QObject *caller, const QString &token, const QString &comment, const QString &id)
-{
- if (this == caller)
- emit onTokenResponse(success, token, comment, id);
-}
-
void API::stopDataConnectionss()
{
}
diff --git a/libsrc/api/JsonAPI.cpp b/libsrc/api/JsonAPI.cpp
index a3b0d031..0bedbeac 100644
--- a/libsrc/api/JsonAPI.cpp
+++ b/libsrc/api/JsonAPI.cpp
@@ -243,9 +243,10 @@ void JsonAPI::handleEffectCommand(const QJsonObject &message, const QString &com
dat.data = message["imageData"].toString("").toUtf8();
dat.args = message["effect"].toObject()["args"].toObject();
- API::setEffect(dat);
-
- sendSuccessReply(command, tan);
+ if (API::setEffect(dat))
+ sendSuccessReply(command, tan);
+ else
+ sendErrorReply("Effect '" + dat.effectName + "' not found", command, tan);
}
void JsonAPI::handleCreateEffectCommand(const QJsonObject &message, const QString &command, int tan)
@@ -351,8 +352,10 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
item["value"] = LEDcolor;
}
- // priorities[priorities.size()] = item;
- priorities.append(item);
+
+ (priority == currentPriority)
+ ? priorities.prepend(item)
+ : priorities.append(item);
}
info["priorities"] = priorities;
@@ -1186,7 +1189,7 @@ void JsonAPI::handleAuthorizeCommand(const QJsonObject &message, const QString &
const QString &comment = message["comment"].toString().trimmed();
const bool &acc = message["accept"].toBool(true);
if (acc)
- API::setNewTokenRequest(comment, id);
+ API::setNewTokenRequest(comment, id, tan);
else
API::cancelNewTokenRequest(comment, id);
// client should wait for answer
@@ -1323,9 +1326,10 @@ void JsonAPI::handleInstanceCommand(const QJsonObject &message, const QString &c
if (subc == "startInstance")
{
- // silent fail
- API::startInstance(inst);
- sendSuccessReply(command + "-" + subc, tan);
+ connect(this, &API::onStartInstanceResponse, [=] (const int &tan) { sendSuccessReply(command + "-" + subc, tan); });
+ if (!API::startInstance(inst, tan))
+ sendErrorReply("Can't start Hyperion instance index " + QString::number(inst), command + "-" + subc, tan);
+
return;
}
@@ -1557,7 +1561,7 @@ void JsonAPI::newPendingTokenRequest(const QString &id, const QString &comment)
sendSuccessDataReply(QJsonDocument(obj), "authorize-tokenRequest", 1);
}
-void JsonAPI::handleTokenResponse(bool success, const QString &token, const QString &comment, const QString &id)
+void JsonAPI::handleTokenResponse(bool success, const QString &token, const QString &comment, const QString &id, const int &tan)
{
const QString cmd = "authorize-requestToken";
QJsonObject result;
@@ -1566,9 +1570,9 @@ void JsonAPI::handleTokenResponse(bool success, const QString &token, const QStr
result["id"] = id;
if (success)
- sendSuccessDataReply(QJsonDocument(result), cmd);
+ sendSuccessDataReply(QJsonDocument(result), cmd, tan);
else
- sendErrorReply("Token request timeout or denied", cmd, 5);
+ sendErrorReply("Token request timeout or denied", cmd, tan);
}
void JsonAPI::handleInstanceStateChange(InstanceState state, quint8 instance, const QString &name)
diff --git a/libsrc/boblightserver/BoblightClientConnection.cpp b/libsrc/boblightserver/BoblightClientConnection.cpp
index 485f2b52..e50a6dc9 100644
--- a/libsrc/boblightserver/BoblightClientConnection.cpp
+++ b/libsrc/boblightserver/BoblightClientConnection.cpp
@@ -3,11 +3,13 @@
#include
#include
#include
+#include
// stl includes
#include
#include
#include
+#include
// Qt includes
#include
@@ -54,18 +56,19 @@ BoblightClientConnection::~BoblightClientConnection()
void BoblightClientConnection::readData()
{
- _receiveBuffer += _socket->readAll();
+ _receiveBuffer.append(_socket->readAll());
int bytes = _receiveBuffer.indexOf('\n') + 1;
while(bytes > 0)
{
// create message string (strip the newline)
- QString message = QString::fromLatin1(_receiveBuffer.data(), bytes-1);
- // remove message data from buffer
- _receiveBuffer = _receiveBuffer.mid(bytes);
+ const QString message = readMessage(_receiveBuffer.data(), bytes);
// handle trimmed message
- handleMessage(message.trimmed());
+ handleMessage(message);
+
+ // remove message data from buffer
+ _receiveBuffer.remove(0, bytes);
// drop messages if the buffer is too full
if (_receiveBuffer.size() > 100*1024)
@@ -79,6 +82,31 @@ void BoblightClientConnection::readData()
}
}
+QString BoblightClientConnection::readMessage(const char *data, const size_t size) const
+{
+ char *end = (char *)data + size - 1;
+
+ // Trim left
+ while (data < end && std::isspace(*data))
+ {
+ ++data;
+ }
+
+ // Trim right
+ while (end > data && std::isspace(*end))
+ {
+ --end;
+ }
+
+ // create message string (strip the newline)
+ const int len = end - data + 1;
+ const QString message = QString::fromLatin1(data, len);
+
+ //std::cout << bytes << ": \"" << message.toUtf8().constData() << "\"" << std::endl;
+
+ return message;
+}
+
void BoblightClientConnection::socketClosed()
{
// clear the current channel
@@ -88,10 +116,11 @@ void BoblightClientConnection::socketClosed()
emit connectionClosed(this);
}
+
void BoblightClientConnection::handleMessage(const QString & message)
{
//std::cout << "boblight message: " << message.toStdString() << std::endl;
- QStringList messageParts = QStringUtils::split(message," ",QStringUtils::SplitBehavior::SkipEmptyParts);
+ const QVector messageParts = QStringUtils::splitRef(message, ' ', QStringUtils::SplitBehavior::SkipEmptyParts);
if (messageParts.size() > 0)
{
if (messageParts[0] == "hello")
@@ -122,32 +151,18 @@ void BoblightClientConnection::handleMessage(const QString & message)
if (messageParts.size() > 3 && messageParts[1] == "light")
{
bool rc;
- unsigned ledIndex = messageParts[2].toUInt(&rc);
+ const unsigned ledIndex = parseUInt(messageParts[2], &rc);
if (rc && ledIndex < _ledColors.size())
{
if (messageParts[3] == "rgb" && messageParts.size() == 7)
{
- // replace decimal comma with decimal point
- messageParts[4].replace(',', '.');
- messageParts[5].replace(',', '.');
- messageParts[6].replace(',', '.');
+ // custom parseByte accepts both ',' and '.' as decimal separator
+ // no need to replace decimal comma with decimal point
bool rc1, rc2, rc3;
- uint8_t red = qMax(0, qMin(255, int(255 * messageParts[4].toFloat(&rc1))));
-
- // check for correct locale should not be needed anymore - please check!
- if (!rc1)
- {
- // maybe a locale issue. switch to a locale with a comma instead of a dot as decimal seperator (or vice versa)
- _locale = QLocale((_locale.decimalPoint() == QChar('.')) ? QLocale::Dutch : QLocale::C);
- _locale.setNumberOptions(QLocale::OmitGroupSeparator | QLocale::RejectGroupSeparator);
-
- // try again
- red = qMax(0, qMin(255, int(255 * messageParts[4].toFloat(&rc1))));
- }
-
- uint8_t green = qMax(0, qMin(255, int(255 * messageParts[5].toFloat(&rc2))));
- uint8_t blue = qMax(0, qMin(255, int(255 * messageParts[6].toFloat(&rc3))));
+ const uint8_t red = parseByte(messageParts[4], &rc1);
+ const uint8_t green = parseByte(messageParts[5], &rc2);
+ const uint8_t blue = parseByte(messageParts[6], &rc3);
if (rc1 && rc2 && rc3)
{
@@ -181,7 +196,7 @@ void BoblightClientConnection::handleMessage(const QString & message)
else if (messageParts.size() == 3 && messageParts[1] == "priority")
{
bool rc;
- int prio = messageParts[2].toInt(&rc);
+ const int prio = static_cast(parseUInt(messageParts[2], &rc));
if (rc && prio != _priority)
{
if (_priority != 0 && _hyperion->getPriorityInfo(_priority).componentId == hyperion::COMP_BOBLIGHTSERVER)
@@ -223,6 +238,146 @@ void BoblightClientConnection::handleMessage(const QString & message)
Debug(_log, "unknown boblight message: %s", QSTRING_CSTR(message));
}
+/// Float values 10 to the power of -p for p in 0 .. 8.
+const float ipows[] = {
+ 1,
+ 1.0f / 10.0f,
+ 1.0f / 100.0f,
+ 1.0f / 1000.0f,
+ 1.0f / 10000.0f,
+ 1.0f / 100000.0f,
+ 1.0f / 1000000.0f,
+ 1.0f / 10000000.0f,
+ 1.0f / 100000000.0f};
+
+float BoblightClientConnection::parseFloat(const QStringRef& s, bool *ok) const
+{
+ // We parse radix 10
+ const char MIN_DIGIT = '0';
+ const char MAX_DIGIT = '9';
+ const char SEP_POINT = '.';
+ const char SEP_COMMA = ',';
+ const int NUM_POWS = 9;
+
+ /// The maximum number of characters we want to process
+ const int MAX_LEN = 18; // Chosen randomly
+
+ /// The index of the current character
+ int q = 0;
+
+ /// The integer part of the number
+ int64_t n = 0;
+
+ auto it = s.begin();
+
+#define STEP ((it != s.end()) && (q++ < MAX_LEN))
+
+ // parse the integer-part
+ while (it->unicode() >= MIN_DIGIT && it->unicode() <= MAX_DIGIT && STEP)
+ {
+ n = (n * 10) + (it->unicode() - MIN_DIGIT);
+ ++it;
+ }
+
+ /// The resulting float value
+ float f = static_cast(n);
+
+ // parse decimal part
+ if ((it->unicode() == SEP_POINT || it->unicode() == SEP_COMMA) && STEP)
+ {
+ /// The decimal part of the number
+ int64_t d = 0;
+
+ /// The exponent for the scale-factor 10 to the power -e
+ int e = 0;
+
+ ++it;
+ while (it->unicode() >= MIN_DIGIT && it->unicode() <= MAX_DIGIT && STEP)
+ {
+ d = (d * 10) + (it->unicode() - MIN_DIGIT);
+ ++e;
+ ++it;
+ }
+
+ const float h = static_cast(d);
+
+ // We want to use pre-calculated power whenever possible
+ if (e < NUM_POWS)
+ {
+ f += h * ipows[e];
+ }
+ else
+ {
+ f += h / std::pow(10.0f, e);
+ }
+ }
+
+ if (q >= MAX_LEN || q < s.length())
+ {
+ if (ok)
+ {
+ //std::cout << "FAIL L " << q << ": " << s.toUtf8().constData() << std::endl;
+ *ok = false;
+ }
+ return 0;
+ }
+
+ if (ok)
+ {
+ //std::cout << "OK " << d << ": " << s.toUtf8().constData() << std::endl;
+ *ok = true;
+ }
+
+ return f;
+}
+
+unsigned BoblightClientConnection::parseUInt(const QStringRef& s, bool *ok) const
+{
+ // We parse radix 10
+ const char MIN_DIGIT = '0';
+ const char MAX_DIGIT = '9';
+
+ /// The maximum number of characters we want to process
+ const int MAX_LEN = 10;
+
+ /// The index of the current character
+ int q = 0;
+
+ /// The integer part of the number
+ int n = 0;
+
+ auto it = s.begin();
+
+ // parse the integer-part
+ while (it->unicode() >= MIN_DIGIT && it->unicode() <= MAX_DIGIT && ((it != s.end()) && (q++ < MAX_LEN)))
+ {
+ n = (n * 10) + (it->unicode() - MIN_DIGIT);
+ ++it;
+ }
+
+ if (ok)
+ {
+ *ok = !(q >= MAX_LEN || q < s.length());
+ }
+
+ return n;
+}
+
+uint8_t BoblightClientConnection::parseByte(const QStringRef& s, bool *ok) const
+{
+ const int LO = 0;
+ const int HI = 255;
+
+#if defined(FAST_FLOAT_PARSE)
+ const float d = parseFloat(s, ok);
+#else
+ const float d = s.toFloat(ok);
+#endif
+
+ // Clamp to byte range 0 to 255
+ return static_cast(qBound(LO, int(HI * d), HI)); // qBound args are in order min, value, max; see: https://doc.qt.io/qt-5/qtglobal.html#qBound
+}
+
void BoblightClientConnection::sendLightMessage()
{
char buffer[256];
diff --git a/libsrc/boblightserver/BoblightClientConnection.h b/libsrc/boblightserver/BoblightClientConnection.h
index 54b89efc..46a3b0eb 100644
--- a/libsrc/boblightserver/BoblightClientConnection.h
+++ b/libsrc/boblightserver/BoblightClientConnection.h
@@ -4,11 +4,15 @@
#include
#include
#include
+#include
// utils includes
#include
#include
+/// Whether to parse floats with an eye on performance
+#define FAST_FLOAT_PARSE
+
class ImageProcessor;
class Hyperion;
@@ -70,6 +74,42 @@ private:
///
void sendLightMessage();
+ ///
+ /// Interpret the float value "0.0" to "1.0" of the QString byte values 0 .. 255
+ ///
+ /// @param s the string to parse
+ /// @param ok whether the result is ok
+ /// @return the parsed byte value in range 0 to 255, or 0
+ ///
+ uint8_t parseByte(const QStringRef& s, bool *ok = nullptr) const;
+
+ ///
+ /// Parse the given QString as unsigned int value.
+ ///
+ /// @param s the string to parse
+ /// @param ok whether the result is ok
+ /// @return the parsed unsigned int value
+ ///
+ unsigned parseUInt(const QStringRef& s, bool *ok = nullptr) const;
+
+ ///
+ /// Parse the given QString as float value, e.g. the 16-bit (wide char) QString "1" shall represent 1, "0.5" is 0.5 and so on.
+ ///
+ /// @param s the string to parse
+ /// @param ok whether the result is ok
+ /// @return the parsed float value, or 0
+ ///
+ float parseFloat(const QStringRef& s, bool *ok = nullptr) const;
+
+ ///
+ /// Read an incoming boblight message as QString
+ ///
+ /// @param data the char data buffer of the incoming message
+ /// @param size the length of the buffer buffer
+ /// @returns the incoming boblight message as QString
+ ///
+ QString readMessage(const char *data, const size_t size) const;
+
private:
/// Locale used for parsing floating point values
QLocale _locale;
diff --git a/libsrc/effectengine/EffectEngine.cpp b/libsrc/effectengine/EffectEngine.cpp
index e4a4bb06..14169890 100644
--- a/libsrc/effectengine/EffectEngine.cpp
+++ b/libsrc/effectengine/EffectEngine.cpp
@@ -141,8 +141,6 @@ int EffectEngine::runEffect(const QString &effectName, int priority, int timeout
int EffectEngine::runEffect(const QString &effectName, const QJsonObject &args, int priority, int timeout, const QString &pythonScript, const QString &origin, unsigned smoothCfg, const QString &imageData)
{
- Info( _log, "Run effect \"%s\" on channel %d", QSTRING_CSTR(effectName), priority);
-
if (pythonScript.isEmpty())
{
const EffectDefinition *effectDefinition = nullptr;
@@ -157,12 +155,14 @@ int EffectEngine::runEffect(const QString &effectName, const QJsonObject &args,
if (effectDefinition == nullptr)
{
// no such effect
- Error(_log, "Effect %s not found", QSTRING_CSTR(effectName));
+ Error(_log, "Effect \"%s\" not found", QSTRING_CSTR(effectName));
return -1;
}
+ Info( _log, "Run effect \"%s\" on channel %d", QSTRING_CSTR(effectName), priority);
return runEffectScript(effectDefinition->script, effectName, (args.isEmpty() ? effectDefinition->args : args), priority, timeout, origin, effectDefinition->smoothCfg);
}
+ Info( _log, "Run effect \"%s\" on channel %d", QSTRING_CSTR(effectName), priority);
return runEffectScript(pythonScript, effectName, args, priority, timeout, origin, smoothCfg, imageData);
}
diff --git a/libsrc/effectengine/EffectFileHandler.cpp b/libsrc/effectengine/EffectFileHandler.cpp
index 98ea45c2..d3d07dd5 100644
--- a/libsrc/effectengine/EffectFileHandler.cpp
+++ b/libsrc/effectengine/EffectFileHandler.cpp
@@ -208,7 +208,7 @@ void EffectFileHandler::updateEffects()
{
if(directory.mkpath(path))
{
- Info(_log, "New Effect path \"%s\" created successfull", QSTRING_CSTR(path) );
+ Info(_log, "New Effect path \"%s\" created successfully", QSTRING_CSTR(path) );
}
else
{
diff --git a/libsrc/hyperion/AuthManager.cpp b/libsrc/hyperion/AuthManager.cpp
index 996291d0..17f76706 100644
--- a/libsrc/hyperion/AuthManager.cpp
+++ b/libsrc/hyperion/AuthManager.cpp
@@ -150,18 +150,18 @@ bool AuthManager::resetHyperionUser()
return _authTable->resetHyperionUser();
}
-void AuthManager::setNewTokenRequest(QObject *caller, const QString &comment, const QString &id)
+void AuthManager::setNewTokenRequest(QObject *caller, const QString &comment, const QString &id, const int &tan)
{
if (!_pendingRequests.contains(id))
{
- AuthDefinition newDef{id, comment, caller, uint64_t(QDateTime::currentMSecsSinceEpoch() + 180000)};
+ AuthDefinition newDef{id, comment, caller, tan, uint64_t(QDateTime::currentMSecsSinceEpoch() + 180000)};
_pendingRequests[id] = newDef;
_timer->start();
emit newPendingTokenRequest(id, comment);
}
}
-void AuthManager::cancelNewTokenRequest(QObject *caller, const QString &comment, const QString &id)
+void AuthManager::cancelNewTokenRequest(QObject *caller, const QString &, const QString &id)
{
if (_pendingRequests.contains(id))
{
@@ -182,12 +182,12 @@ void AuthManager::handlePendingTokenRequest(const QString &id, bool accept)
{
const QString token = QUuid::createUuid().toString().remove("{").remove("}");
_authTable->createToken(token, def.comment, id);
- emit tokenResponse(true, def.caller, token, def.comment, id);
+ emit tokenResponse(true, def.caller, token, def.comment, id, def.tan);
emit tokenChange(getTokenList());
}
else
{
- emit tokenResponse(false, def.caller, QString(), def.comment, id);
+ emit tokenResponse(false, def.caller, QString(), def.comment, id, def.tan);
}
}
}
@@ -249,7 +249,7 @@ void AuthManager::checkTimeout()
const AuthDefinition &def = i.value();
if (def.timeoutTime <= now)
{
- emit tokenResponse(false, def.caller, QString(), def.comment, def.id);
+ emit tokenResponse(false, def.caller, QString(), def.comment, def.id, def.tan);
_pendingRequests.remove(i.key());
}
}
diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp
index b5b81003..2b5182f0 100644
--- a/libsrc/hyperion/Hyperion.cpp
+++ b/libsrc/hyperion/Hyperion.cpp
@@ -87,7 +87,7 @@ void Hyperion::start()
// connect Hyperion::update with Muxer visible priority changes as muxer updates independent
connect(&_muxer, &PriorityMuxer::visiblePriorityChanged, this, &Hyperion::update);
- connect(&_muxer, &PriorityMuxer::visiblePriorityChanged, this, &Hyperion::handlPriorityChangedLedDevice);
+ connect(&_muxer, &PriorityMuxer::visiblePriorityChanged, this, &Hyperion::handlePriorityChangedLedDevice);
connect(&_muxer, &PriorityMuxer::visibleComponentChanged, this, &Hyperion::handleVisibleComponentChanged);
// listens for ComponentRegister changes of COMP_ALL to perform core enable/disable actions
@@ -531,7 +531,7 @@ void Hyperion::handleVisibleComponentChanged(hyperion::Components comp)
_raw2ledAdjustment->setBacklightEnabled((comp != hyperion::COMP_COLOR && comp != hyperion::COMP_EFFECT));
}
-void Hyperion::handlPriorityChangedLedDevice(const quint8& priority)
+void Hyperion::handlePriorityChangedLedDevice(const quint8& priority)
{
quint8 previousPriority = _muxer.getPreviousPriority();
diff --git a/libsrc/hyperion/HyperionIManager.cpp b/libsrc/hyperion/HyperionIManager.cpp
index 255055e8..9613af25 100644
--- a/libsrc/hyperion/HyperionIManager.cpp
+++ b/libsrc/hyperion/HyperionIManager.cpp
@@ -67,7 +67,7 @@ void HyperionIManager::toggleStateAllInstances(bool pause)
}
}
-bool HyperionIManager::startInstance(quint8 inst, bool block)
+bool HyperionIManager::startInstance(quint8 inst, bool block, QObject* caller, int tan)
{
if(_instanceTable->instanceExist(inst))
{
@@ -104,6 +104,12 @@ bool HyperionIManager::startInstance(quint8 inst, bool block)
while(!hyperionThread->isRunning()){};
}
+ if (!_pendingRequests.contains(inst) && caller != nullptr)
+ {
+ PendingRequests newDef{caller, tan};
+ _pendingRequests[inst] = newDef;
+ }
+
return true;
}
Debug(_log,"Can't start Hyperion instance index '%d' with name '%s' it's already running or queued for start", inst, QSTRING_CSTR(_instanceTable->getNamebyIndex(inst)));
@@ -211,4 +217,11 @@ void HyperionIManager::handleStarted()
_runningInstances.insert(instance, hyperion);
emit instanceStateChanged(InstanceState::H_STARTED, instance);
emit change();
+
+ if (_pendingRequests.contains(instance))
+ {
+ PendingRequests def = _pendingRequests.take(instance);
+ emit startInstanceResponse(def.caller, def.tan);
+ _pendingRequests.remove(instance);
+ }
}
diff --git a/libsrc/hyperion/PriorityMuxer.cpp b/libsrc/hyperion/PriorityMuxer.cpp
index b7687e25..17cfe319 100644
--- a/libsrc/hyperion/PriorityMuxer.cpp
+++ b/libsrc/hyperion/PriorityMuxer.cpp
@@ -142,9 +142,11 @@ hyperion::Components PriorityMuxer::getComponentOfPriority(int priority) const
void PriorityMuxer::registerInput(int priority, hyperion::Components component, const QString& origin, const QString& owner, unsigned smooth_cfg)
{
// detect new registers
- bool newInput = false;
- if(!_activeInputs.contains(priority))
+ bool newInput, reusedInput = false;
+ if (!_activeInputs.contains(priority))
newInput = true;
+ else
+ reusedInput = true;
InputInfo& input = _activeInputs[priority];
input.priority = priority;
@@ -154,12 +156,15 @@ void PriorityMuxer::registerInput(int priority, hyperion::Components component,
input.smooth_cfg = smooth_cfg;
input.owner = owner;
- if(newInput)
+ if (newInput)
{
Debug(_log,"Register new input '%s/%s' with priority %d as inactive", QSTRING_CSTR(origin), hyperion::componentToIdString(component), priority);
- emit prioritiesChanged();
+ if (!_sourceAutoSelectEnabled) // emit 'prioritiesChanged' only on when _sourceAutoSelectEnabled is false
+ emit prioritiesChanged();
return;
}
+
+ if (reusedInput) emit prioritiesChanged();
}
bool PriorityMuxer::setInput(int priority, const std::vector& ledColors, int64_t timeout_ms)
@@ -339,7 +344,6 @@ void PriorityMuxer::setCurrentTime()
_prevVisComp = comp;
emit visibleComponentChanged(comp);
}
- emit prioritiesChanged();
}
}
diff --git a/libsrc/leddevice/LedDeviceTemplate.cpp b/libsrc/leddevice/LedDeviceTemplate.cpp
index ddfe1ebc..dd8ce3f4 100644
--- a/libsrc/leddevice/LedDeviceTemplate.cpp
+++ b/libsrc/leddevice/LedDeviceTemplate.cpp
@@ -3,10 +3,6 @@
LedDeviceTemplate::LedDeviceTemplate(const QJsonObject &deviceConfig)
: LedDevice()
{
- _devConfig = deviceConfig;
- _isDeviceReady = false;
-
- _activeDeviceType = deviceConfig["type"].toString("UNSPECIFIED").toLower();
}
LedDevice* LedDeviceTemplate::construct(const QJsonObject &deviceConfig)
diff --git a/libsrc/leddevice/dev_hid/LedDeviceLightpack.cpp b/libsrc/leddevice/dev_hid/LedDeviceLightpack.cpp
index e8fec221..bf8c217b 100644
--- a/libsrc/leddevice/dev_hid/LedDeviceLightpack.cpp
+++ b/libsrc/leddevice/dev_hid/LedDeviceLightpack.cpp
@@ -35,6 +35,7 @@ enum DATA_VERSION_INDEXES{
LedDeviceLightpack::LedDeviceLightpack(const QJsonObject &deviceConfig)
: LedDevice(deviceConfig)
, _libusbContext(nullptr)
+ , _device(nullptr)
, _deviceHandle(nullptr)
, _busNumber(-1)
, _addressNumber(-1)
@@ -80,17 +81,28 @@ bool LedDeviceLightpack::init(const QJsonObject &deviceConfig)
else
{
Debug(_log, "USB context initialized");
- //libusb_set_debug(_libusbContext, 3);
+
+ if ( _log->getMinLevel() == Logger::LogLevel::DEBUG )
+ {
+ int logLevel = LIBUSB_LOG_LEVEL_INFO;
+ #if LIBUSB_API_VERSION >= 0x01000106
+ libusb_set_option(_libusbContext, LIBUSB_OPTION_LOG_LEVEL, logLevel);
+ #else
+ libusb_set_debug(_libusbContext, logLevel);
+ #endif
+ }
// retrieve the list of USB devices
libusb_device ** deviceList;
ssize_t deviceCount = libusb_get_device_list(_libusbContext, &deviceList);
+ bool deviceFound = true;
// iterate the list of devices
for (ssize_t i = 0 ; i < deviceCount; ++i)
{
// try to open and initialize the device
- if (testAndOpen(deviceList[i], _serialNumber) == 0)
+ deviceFound = searchDevice(deviceList[i], _serialNumber);
+ if ( deviceFound )
{
_device = deviceList[i];
// a device was successfully opened. break from list
@@ -101,7 +113,7 @@ bool LedDeviceLightpack::init(const QJsonObject &deviceConfig)
// free the device list
libusb_free_device_list(deviceList, 1);
- if (_deviceHandle == nullptr)
+ if (!deviceFound)
{
QString errortext;
if (_serialNumber.isEmpty())
@@ -110,12 +122,16 @@ bool LedDeviceLightpack::init(const QJsonObject &deviceConfig)
}
else
{
- errortext = QString ("No Lightpack device has been found with serial %1").arg( _serialNumber);
+ errortext = QString ("No Lightpack device found with serial %1").arg( _serialNumber);
}
this->setInError( errortext );
}
else
{
+ // set the led buffer size (command + 6 bytes per led)
+ _ledBuffer = std::vector(1 + _hwLedCount * 6, 0);
+ _ledBuffer[0] = CMD_UPDATE_LEDS;
+
isInitOK = true;
}
}
@@ -128,18 +144,29 @@ int LedDeviceLightpack::open()
int retval = -1;
_isDeviceReady = false;
- if ( libusb_open(_device, &_deviceHandle) != LIBUSB_SUCCESS )
+ if ( _device != nullptr)
{
- QString errortext = QString ("Failed to open [%1]").arg(_serialNumber);
- this->setInError(errortext);
- }
- else
- {
- // Everything is OK -> enable device
- _isDeviceReady = true;
- retval = 0;
- }
+ openDevice(_device, &_deviceHandle);
+ if ( _deviceHandle == nullptr )
+ {
+ QString errortext = QString ("Failed to open device with serial [%1]").arg(_serialNumber);
+ this->setInError(errortext);
+ retval = -1;
+ }
+ else
+ {
+ disableSmoothing();
+ {
+ // Everything is OK
+ _isDeviceReady = true;
+ _isOpen = true;
+
+ Info(_log, "Lightpack device successfully opened");
+ retval = 0;
+ }
+ }
+ }
return retval;
}
@@ -147,75 +174,64 @@ int LedDeviceLightpack::close()
{
int retval = 0;
_isDeviceReady = false;
+ _isOpen = false;
- // LedDevice specific closing activities
- if (_deviceHandle != nullptr)
+ if ( _deviceHandle != nullptr)
{
- _isOpen = false;
- libusb_release_interface(_deviceHandle, LIGHTPACK_INTERFACE);
- libusb_attach_kernel_driver(_deviceHandle, LIGHTPACK_INTERFACE);
- libusb_close(_deviceHandle);
-
+ closeDevice(_deviceHandle);
_deviceHandle = nullptr;
}
+
return retval;
}
-int LedDeviceLightpack::testAndOpen(libusb_device * device, const QString & requestedSerialNumber)
+bool LedDeviceLightpack::searchDevice(libusb_device * device, const QString & requestedSerialNumber)
{
+ bool lightPackFound = false;
+
libusb_device_descriptor deviceDescriptor;
int error = libusb_get_device_descriptor(device, &deviceDescriptor);
if (error != LIBUSB_SUCCESS)
{
Error(_log, "Error while retrieving device descriptor(%d): %s", error, libusb_error_name(error));
- return -1;
+ return false;
}
+ #define UNO_VENDOR_ID 0x2341
+ #define UNO_PRODUCT_ID 0x43
+
if ((deviceDescriptor.idVendor == USB_VENDOR_ID && deviceDescriptor.idProduct == USB_PRODUCT_ID) ||
- (deviceDescriptor.idVendor == USB_OLD_VENDOR_ID && deviceDescriptor.idProduct == USB_OLD_PRODUCT_ID))
+ (deviceDescriptor.idVendor == USB_OLD_VENDOR_ID && deviceDescriptor.idProduct == USB_OLD_PRODUCT_ID))
{
Info(_log, "Found a Lightpack device. Retrieving more information...");
+ Debug(_log, "vendorIdentifier : %s", QSTRING_CSTR(QString("0x%1").arg(static_cast(deviceDescriptor.idVendor),0,16)));
+ Debug(_log, "productIdentifier: %s", QSTRING_CSTR(QString("0x%1").arg(static_cast(deviceDescriptor.idProduct),0,16)));
+ Debug(_log, "release_number : %s", QSTRING_CSTR(QString("0x%1").arg(static_cast(deviceDescriptor.bcdDevice),0,16)));
+ Debug(_log, "manufacturer : %s", QSTRING_CSTR(getProperty(device, deviceDescriptor.iManufacturer)));
+
// get the hardware address
int busNumber = libusb_get_bus_number(device);
int addressNumber = libusb_get_device_address(device);
// get the serial number
- QString serialNumber;
- if (deviceDescriptor.iSerialNumber != 0)
- {
- // TODO: Check, if exceptions via try/catch need to be replaced in Qt environment
- try
- {
- serialNumber = LedDeviceLightpack::getString(device, deviceDescriptor.iSerialNumber);
- }
- catch (int e)
- {
- Error(_log, "unable to retrieve serial number from Lightpack device(%d): %s", e, libusb_error_name(e));
- serialNumber = "";
- }
- }
-
+ QString serialNumber = LedDeviceLightpack::getProperty(device, deviceDescriptor.iSerialNumber);
Debug(_log,"Lightpack device found: bus=%d address=%d serial=%s", busNumber, addressNumber, QSTRING_CSTR(serialNumber));
// check if this is the device we are looking for
if (requestedSerialNumber.isEmpty() || requestedSerialNumber == serialNumber)
{
- // This is it!
- // TODO: Check, if exceptions via try/catch need to be replaced in Qt environment
- try
+ libusb_device_handle * deviceHandle;
+ if ( openDevice(device, &deviceHandle ) == 0 )
{
- _deviceHandle = openDevice(device);
_serialNumber = serialNumber;
_busNumber = busNumber;
_addressNumber = addressNumber;
- Info(_log, "Lightpack device successfully opened");
-
// get the firmware version
uint8_t buffer[256];
error = libusb_control_transfer(
- _deviceHandle,
+ deviceHandle,
static_cast( LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE),
0x01,
0x0100,
@@ -231,13 +247,12 @@ int LedDeviceLightpack::testAndOpen(libusb_device * device, const QString & requ
_firmwareVersion.minorVersion = buffer[INDEX_FW_VER_MINOR];
}
+ #if 0
// FOR TESTING PURPOSE: FORCE MAJOR VERSION TO 6
_firmwareVersion.majorVersion = 6;
+ #endif
- // disable smoothing of the chosen device
- disableSmoothing();
-
- // determine the number of leds
+ // determine the number of LEDs
if (_firmwareVersion.majorVersion == 4)
{
_hwLedCount = 8;
@@ -257,24 +272,20 @@ int LedDeviceLightpack::testAndOpen(libusb_device * device, const QString & requ
{
_bitsPerChannel = 8;
}
+ closeDevice(deviceHandle);
- // set the led buffer size (command + 6 bytes per led)
- _ledBuffer = std::vector(1 + _hwLedCount * 6, 0);
- _ledBuffer[0] = CMD_UPDATE_LEDS;
+ Debug(_log, "Lightpack device found: bus=%d address=%d serial=%s version=%d.%d.", _busNumber, _addressNumber, QSTRING_CSTR(_serialNumber), _firmwareVersion.majorVersion, _firmwareVersion.minorVersion );
+ lightPackFound = true;
- // return success
- Debug(_log, "Lightpack device opened: bus=%d address=%d serial=%s version=%d.%d.", _busNumber, _addressNumber, QSTRING_CSTR(_serialNumber), _firmwareVersion.majorVersion, _firmwareVersion.minorVersion );
- return 0;
}
- catch(int e)
+ else
{
- _deviceHandle = nullptr;
- Warning(_log, "Unable to open Lightpack device. Searching for other device(%d): %s", e, libusb_error_name(e));
+ Warning(_log, "Unable to open Lightpack device. Searching for other device");
}
}
}
- return -1;
+ return lightPackFound;
}
int LedDeviceLightpack::write(const std::vector &ledValues)
@@ -322,24 +333,23 @@ const QString &LedDeviceLightpack::getSerialNumber() const
int LedDeviceLightpack::writeBytes(uint8_t *data, int size)
{
-// std::cout << "Writing " << size << " bytes: ";
-// for (int i = 0; i < size ; ++i) printf("%02x ", data[i]);
-// std::cout << std::endl;
+ int rc = 0;
+ //Debug( _log, "[%s]", QSTRING_CSTR(uint8_t_to_hex_string(data, size, 32)) );
int error = libusb_control_transfer(_deviceHandle,
- static_cast( LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE ),
- 0x09,
- (2 << 8),
- 0x00,
- data, size, 1000);
+ static_cast( LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE ),
+ 0x09,
+ (2 << 8),
+ 0x00,
+ data, size, 1000);
- if (error == size)
+ if (error != size)
{
- return 0;
+ rc = -1;
+ Error(_log, "Unable to write %d bytes to Lightpack device(%d): %s", size, error, libusb_error_name(error));
}
- Error(_log, "Unable to write %d bytes to Lightpack device(%d): %s", size, error, libusb_error_name(error));
- return error;
+ return rc;
}
int LedDeviceLightpack::disableSmoothing()
@@ -354,15 +364,16 @@ int LedDeviceLightpack::disableSmoothing()
return rc;
}
-libusb_device_handle * LedDeviceLightpack::openDevice(libusb_device *device)
+int LedDeviceLightpack::openDevice(libusb_device *device, libusb_device_handle ** deviceHandle)
{
+ int rc = 0;
+
libusb_device_handle * handle = nullptr;
- Logger * log = Logger::getInstance("LedDevice");
int error = libusb_open(device, &handle);
if (error != LIBUSB_SUCCESS)
{
- Error(log, "unable to open device(%d): %s", error, libusb_error_name(error));
- throw error;
+ Error(_log, "unable to open device(%d): %s", error, libusb_error_name(error));
+ rc = -1;
}
// detach kernel driver if it is active
@@ -371,42 +382,65 @@ libusb_device_handle * LedDeviceLightpack::openDevice(libusb_device *device)
error = libusb_detach_kernel_driver(handle, LIGHTPACK_INTERFACE);
if (error != LIBUSB_SUCCESS)
{
- Error(log, "unable to detach kernel driver(%d): %s", error, libusb_error_name(error));
+ Error(_log, "unable to detach kernel driver(%d): %s", error, libusb_error_name(error));
libusb_close(handle);
- throw error;
+ rc = -1;
}
}
error = libusb_claim_interface(handle, LIGHTPACK_INTERFACE);
if (error != LIBUSB_SUCCESS)
{
- Error(log, "unable to claim interface(%d): %s", error, libusb_error_name(error));
+ Error(_log, "unable to claim interface(%d): %s", error, libusb_error_name(error));
libusb_attach_kernel_driver(handle, LIGHTPACK_INTERFACE);
libusb_close(handle);
- throw error;
+ rc = -1;
}
- return handle;
+ *deviceHandle = handle;
+ return rc;
}
-QString LedDeviceLightpack::getString(libusb_device * device, int stringDescriptorIndex)
+int LedDeviceLightpack::closeDevice(libusb_device_handle * deviceHandle)
{
- libusb_device_handle * handle = nullptr;
+ int rc = 0;
- int error = libusb_open(device, &handle);
+ int error = libusb_release_interface(deviceHandle, LIGHTPACK_INTERFACE);
if (error != LIBUSB_SUCCESS)
{
- throw error;
+ Debug(_log, "Error while releasing interface (%d): %s", error, libusb_error_name(error));
+ rc = -1;
}
- char buffer[256];
- error = libusb_get_string_descriptor_ascii(handle, stringDescriptorIndex, reinterpret_cast(buffer), sizeof(buffer));
- if (error <= 0)
+ error = libusb_attach_kernel_driver(deviceHandle, LIGHTPACK_INTERFACE);
+ if (error != LIBUSB_SUCCESS)
{
- libusb_close(handle);
- throw error;
+ Debug(_log, "Error while attaching kernel driver (%d): %s", error, libusb_error_name(error));
+ rc = -1;
}
- libusb_close(handle);
- return QString(QByteArray(buffer, error));
+ libusb_close(deviceHandle);
+
+ return rc;
+}
+
+QString LedDeviceLightpack::getProperty(libusb_device * device, int stringDescriptorIndex)
+{
+ QString value;
+
+ if ( stringDescriptorIndex != 0 )
+ {
+ libusb_device_handle * handle = nullptr;
+ if ( libusb_open(device, &handle) == LIBUSB_SUCCESS )
+ {
+ char buffer[256];
+ int error = libusb_get_string_descriptor_ascii(handle, stringDescriptorIndex, reinterpret_cast(buffer), sizeof(buffer));
+ if (error > 0)
+ {
+ value = QString(QByteArray(buffer, error));
+ }
+ libusb_close(handle);
+ }
+ }
+ return value;
}
diff --git a/libsrc/leddevice/dev_hid/LedDeviceLightpack.h b/libsrc/leddevice/dev_hid/LedDeviceLightpack.h
index 1e6a03f5..957550c5 100644
--- a/libsrc/leddevice/dev_hid/LedDeviceLightpack.h
+++ b/libsrc/leddevice/dev_hid/LedDeviceLightpack.h
@@ -105,11 +105,12 @@ protected:
private:
///
- /// Test if the device is a (or the) lightpack we are looking for
+ /// Search for a LightPack Device (first one found or matching a given serial number)
///
- /// @return Zero on succes else negative
+ /// @param[in] requestedSerialNumber serial number of Lightpack to be search
+ /// @return True on Lightpack found
///
- int testAndOpen(libusb_device * device, const QString & requestedSerialNumber);
+ bool searchDevice(libusb_device * device, const QString & requestedSerialNumber);
/// write bytes to the device
int writeBytes(uint8_t *data, int size);
@@ -123,8 +124,11 @@ private:
int minorVersion;
};
- static libusb_device_handle * openDevice(libusb_device * device);
- static QString getString(libusb_device * device, int stringDescriptorIndex);
+
+ int openDevice(libusb_device *device, libusb_device_handle ** deviceHandle);
+ int closeDevice(libusb_device_handle * deviceHandle);
+
+ QString getProperty(libusb_device * device, int stringDescriptorIndex);
/// libusb context
libusb_context * _libusbContext;
diff --git a/libsrc/leddevice/dev_hid/LedDeviceMultiLightpack.cpp b/libsrc/leddevice/dev_hid/LedDeviceMultiLightpack.cpp
deleted file mode 100644
index 7ddc1092..00000000
--- a/libsrc/leddevice/dev_hid/LedDeviceMultiLightpack.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-// stl includes
-#include
-#include
-#include
-
-// Local Hyperion includes
-#include "LedDeviceMultiLightpack.h"
-
-// from USB_ID.h (http://code.google.com/p/light-pack/source/browse/CommonHeaders/USB_ID.h)
-#define USB_OLD_VENDOR_ID 0x03EB
-#define USB_OLD_PRODUCT_ID 0x204F
-#define USB_VENDOR_ID 0x1D50
-#define USB_PRODUCT_ID 0x6022
-
-bool compareLightpacks(LedDeviceLightpack * lhs, LedDeviceLightpack * rhs)
-{
- return lhs->getSerialNumber() < rhs->getSerialNumber();
-}
-
-LedDeviceMultiLightpack::LedDeviceMultiLightpack(const QJsonObject &deviceConfig)
- : LedDevice(deviceConfig)
- , _lightpacks()
-{
-}
-
-LedDeviceMultiLightpack::~LedDeviceMultiLightpack()
-{
- for (LedDeviceLightpack * device : _lightpacks)
- {
- delete device;
- }
-}
-
-LedDevice* LedDeviceMultiLightpack::construct(const QJsonObject &deviceConfig)
-{
- return new LedDeviceMultiLightpack(deviceConfig);
-}
-
-bool LedDeviceMultiLightpack::init(const QJsonObject &deviceConfig)
-{
- bool isInitOK = false;
-
- // Initialise sub-class
- if ( LedDevice::init(deviceConfig) )
- {
- // retrieve a list with Lightpack serials
- QStringList serialList = getLightpackSerials();
-
- // sort the list of Lightpacks based on the serial to get a fixed order
- std::sort(_lightpacks.begin(), _lightpacks.end(), compareLightpacks);
-
- // open each Lightpack device
- for (auto serial : serialList)
- {
- QJsonObject devConfig;
- devConfig["serial"] = serial;
- devConfig["latchTime"] = deviceConfig["latchTime"];
- devConfig["rewriteTime"] = deviceConfig["rewriteTime"];
-
- LedDeviceLightpack * device = new LedDeviceLightpack(devConfig);
-
- device->start();
- if (device->open() == 0)
- {
- _lightpacks.push_back(device);
- }
- else
- {
- Error(_log, "Error while creating Lightpack device with serial %s", QSTRING_CSTR(serial));
- delete device;
- }
- }
-
- if (_lightpacks.empty())
- {
- //Warning(_log, "No Lightpack devices were found");
- QString errortext = QString ("No Lightpack devices were found");
- this->setInError(errortext);
- isInitOK = false;
- }
- else
- {
- Info(_log, "%d Lightpack devices were found", _lightpacks.size());
- isInitOK = true;
- }
- }
- return isInitOK;
-}
-
-int LedDeviceMultiLightpack::open()
-{
- int retval = -1;
- _isDeviceReady = false;
-
- int lightsInError = 0;
- // open each Lightpack device
- for (LedDeviceLightpack * device : _lightpacks)
- {
- if (device->open() < 0)
- {
- Error( _log, "Failed to open [%s]", QSTRING_CSTR(device->getSerialNumber()) );
- ++lightsInError;
- }
- }
-
- if ( lightsInError < static_cast(_lightpacks.size()) )
- {
- // Everything is OK -> enable device
- _isDeviceReady = true;
- retval = 0;
- }
- else
- {
- this->setInError( "All Lightpacks failed to be opened!" );
- }
- return retval;
-}
-
-int LedDeviceMultiLightpack::close()
-{
- _isDeviceReady = false;
-
- for (LedDeviceLightpack * device : _lightpacks)
- {
- device->close();
- }
- return 0;
-}
-
-int LedDeviceMultiLightpack::write(const std::vector &ledValues)
-{
- const ColorRgb * data = ledValues.data();
- int size = ledValues.size();
-
- for (LedDeviceLightpack * device : _lightpacks)
- {
- int count = qMin(static_cast( device->getLedCount()), size);
-
- if (count > 0)
- {
- if ( device->isOpen() )
- {
- device->write(data, count);
- }
-
- data += count;
- size -= count;
- }
- else
- {
- Warning(_log, "Unable to write data to Lightpack device: no more led data available");
- }
- }
-
- return 0;
-}
-
-bool LedDeviceMultiLightpack::powerOff()
-{
- for (LedDeviceLightpack * device : _lightpacks)
- {
- if ( device->isOpen() )
- {
- device->powerOff();
- }
- }
- return true;
-}
-
-QStringList LedDeviceMultiLightpack::getLightpackSerials()
-{
- QStringList serialList;
- Logger * log = Logger::getInstance("LedDevice");
- Debug(log, "Getting list of Lightpack serials");
-
- // initialize the USB context
- libusb_context * libusbContext;
- int error = libusb_init(&libusbContext);
- if (error != LIBUSB_SUCCESS)
- {
- Error(log,"Error while initializing USB context(%d): %s", error, libusb_error_name(error));
- libusbContext = nullptr;
- return serialList;
- }
- //libusb_set_debug(_libusbContext, 3);
- Info(log, "USB context initialized in multi Lightpack device");
-
- // retrieve the list of USB devices
- libusb_device ** deviceList;
- ssize_t deviceCount = libusb_get_device_list(libusbContext, &deviceList);
-
- // iterate the list of devices
- for (ssize_t i = 0 ; i < deviceCount; ++i)
- {
- libusb_device_descriptor deviceDescriptor;
- error = libusb_get_device_descriptor(deviceList[i], &deviceDescriptor);
- if (error != LIBUSB_SUCCESS)
- {
- Error(log, "Error while retrieving device descriptor(%d): %s", error, libusb_error_name(error));
- continue;
- }
-
- if ((deviceDescriptor.idVendor == USB_VENDOR_ID && deviceDescriptor.idProduct == USB_PRODUCT_ID) ||
- (deviceDescriptor.idVendor == USB_OLD_VENDOR_ID && deviceDescriptor.idProduct == USB_OLD_PRODUCT_ID))
- {
- Info(log, "Found a Lightpack device. Retrieving serial...");
-
- // get the serial number
- QString serialNumber;
- if (deviceDescriptor.iSerialNumber != 0)
- {
- // TODO: Check, if exceptions via try/catch need to be replaced in Qt environment
- try
- {
- serialNumber = LedDeviceMultiLightpack::getString(deviceList[i], deviceDescriptor.iSerialNumber);
- }
- catch (int e)
- {
- Error(log,"Unable to retrieve serial number(%d): %s", e, libusb_error_name(e));
- continue;
- }
- }
-
- Info(log, "Lightpack device found with serial %s", QSTRING_CSTR(serialNumber));
- serialList.append(serialNumber);
- }
- }
-
- // free the device list
- libusb_free_device_list(deviceList, 1);
- libusb_exit(libusbContext);
-
- return serialList;
-}
-
-QString LedDeviceMultiLightpack::getString(libusb_device * device, int stringDescriptorIndex)
-{
- libusb_device_handle * handle = nullptr;
-
- int error = libusb_open(device, &handle);
- if (error != LIBUSB_SUCCESS)
- {
- throw error;
- }
-
- char buffer[256];
- error = libusb_get_string_descriptor_ascii(handle, stringDescriptorIndex, reinterpret_cast(buffer), sizeof(buffer));
- if (error <= 0)
- {
- libusb_close(handle);
- throw error;
- }
-
- libusb_close(handle);
- return QString(QByteArray(buffer, error));
-}
diff --git a/libsrc/leddevice/dev_hid/LedDeviceMultiLightpack.h b/libsrc/leddevice/dev_hid/LedDeviceMultiLightpack.h
deleted file mode 100644
index 6ad69d56..00000000
--- a/libsrc/leddevice/dev_hid/LedDeviceMultiLightpack.h
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef LEDEVICEMULTILIGHTPACK_H
-#define LEDEVICEMULTILIGHTPACK_H
-
-// stl includes
-#include
-#include
-#include
-#include
-
-// libusb include
-#include
-
-// Hyperion includes
-#include
-#include "LedDeviceLightpack.h"
-
-///
-/// LedDevice implementation for multiple lightpack devices
-///
-class LedDeviceMultiLightpack : public LedDevice
-{
-public:
-
- ///
- /// @brief Constructs a LedDevice of multiple Lightpack LED-devices
- ///
- /// @param deviceConfig Device's configuration as JSON-Object
- ///
- explicit LedDeviceMultiLightpack(const QJsonObject &deviceConfig);
-
- ///
- /// @brief Destructor of the LedDevice
- ///
- ~LedDeviceMultiLightpack() override;
-
- ///
- /// @brief Constructs the LED-device
- ///
- /// @param[in] deviceConfig Device's configuration as JSON-Object
- /// @return LedDevice constructed
- ///
- static LedDevice* construct(const QJsonObject &deviceConfig);
-
-protected:
-
- ///
- /// @brief Initialise the device's configuration
- ///
- /// @param[in] deviceConfig the JSON device configuration
- /// @return True, if success
- ///
- bool init(const QJsonObject &deviceConfig) override;
-
- ///
- /// @brief Opens the output device.
- ///
- /// @return Zero on success (i.e. device is ready), else negative
- ///
- int open() override;
-
- ///
- /// @brief Closes the output device.
- ///
- /// @return Zero on success (i.e. device is closed), else negative
- ///
- int close() override;
-
- ///
- /// @brief Power-/turn off the Nanoleaf device.
- ///
- /// @return True if success
- ///
- bool powerOff() override;
-
- ///
- /// @brief Writes the RGB-Color values to the LEDs.
- ///
- /// @param[in] ledValues The RGB-color per LED
- /// @return Zero on success, else negative
- ///
- int write(const std::vector & ledValues) override;
-
-private:
-
- static QStringList getLightpackSerials();
- static QString getString(libusb_device * device, int stringDescriptorIndex);
-
- /// buffer for led data
- std::vector _lightpacks;
-};
-
-#endif // LEDEVICEMULTILIGHTPACK_H
diff --git a/libsrc/leddevice/dev_net/LedDeviceWled.h b/libsrc/leddevice/dev_net/LedDeviceWled.h
index bc195ff8..3d5a65b3 100644
--- a/libsrc/leddevice/dev_net/LedDeviceWled.h
+++ b/libsrc/leddevice/dev_net/LedDeviceWled.h
@@ -92,7 +92,7 @@ protected:
///
/// @brief Power-/turn on the WLED device.
///
- /// @brief Store the device's original state.
+ /// @return True if success
///
bool powerOn() override;
diff --git a/libsrc/leddevice/dev_net/ProviderRestApi.cpp b/libsrc/leddevice/dev_net/ProviderRestApi.cpp
index 2acd27a8..052250ba 100644
--- a/libsrc/leddevice/dev_net/ProviderRestApi.cpp
+++ b/libsrc/leddevice/dev_net/ProviderRestApi.cpp
@@ -38,10 +38,7 @@ ProviderRestApi::ProviderRestApi()
ProviderRestApi::~ProviderRestApi()
{
- if (_networkManager != nullptr)
- {
- delete _networkManager;
- }
+ delete _networkManager;
}
void ProviderRestApi::setUrl(const QUrl& url)
diff --git a/libsrc/leddevice/dev_serial/LedDeviceKarate.cpp b/libsrc/leddevice/dev_serial/LedDeviceKarate.cpp
index e7f17ff8..ccbd9598 100644
--- a/libsrc/leddevice/dev_serial/LedDeviceKarate.cpp
+++ b/libsrc/leddevice/dev_serial/LedDeviceKarate.cpp
@@ -18,10 +18,10 @@ bool LedDeviceKarate::init(const QJsonObject &deviceConfig)
// Initialise sub-class
if ( ProviderRs232::init(deviceConfig) )
{
- if (_ledCount != 16)
+ if (_ledCount != 8 && _ledCount != 16)
{
//Error( _log, "%d channels configured. This should always be 16!", _ledCount);
- QString errortext = QString ("%1 channels configured. This should always be 16!").arg(_ledCount);
+ QString errortext = QString ("%1 channels configured. This should always be 8 or 16!").arg(_ledCount);
this->setInError(errortext);
isInitOK = false;
}
diff --git a/libsrc/leddevice/schemas/schema-multilightpack.json b/libsrc/leddevice/schemas/schema-multilightpack.json
deleted file mode 100644
index babbb985..00000000
--- a/libsrc/leddevice/schemas/schema-multilightpack.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "type":"object",
- "required":true,
- "properties":{
- "latchTime": {
- "type": "integer",
- "title":"edt_dev_spec_latchtime_title",
- "default": 11,
- "append" : "edt_append_ms",
- "minimum": 0,
- "maximum": 1000,
- "access" : "expert",
- "propertyOrder" : 1
- },
- "rewriteTime": {
- "type": "integer",
- "title":"edt_dev_general_rewriteTime_title",
- "default": 1000,
- "append" : "edt_append_ms",
- "minimum": 0,
- "access" : "expert",
- "propertyOrder" : 2
- }
- },
- "additionalProperties": true
-}
diff --git a/libsrc/ssdp/SSDPDescription.h b/libsrc/ssdp/SSDPDescription.h
index 70b37da6..4bf3f76f 100644
--- a/libsrc/ssdp/SSDPDescription.h
+++ b/libsrc/ssdp/SSDPDescription.h
@@ -27,6 +27,12 @@ static const QString SSDP_DESCRIPTION = ""
"https://www.hyperion-project.org "
"%4 "
"uuid:%4 "
+ ""
+ "%5 "
+ "%6 "
+ "%7 "
+ "%8 "
+ " "
"index.html "
""
""
diff --git a/libsrc/ssdp/SSDPHandler.cpp b/libsrc/ssdp/SSDPHandler.cpp
index 48189fb1..62397cb3 100644
--- a/libsrc/ssdp/SSDPHandler.cpp
+++ b/libsrc/ssdp/SSDPHandler.cpp
@@ -15,14 +15,16 @@
static const QString SSDP_HYPERION_ST("urn:hyperion-project.org:device:basic:1");
-SSDPHandler::SSDPHandler(WebServer* webserver, quint16 flatBufPort, quint16 jsonServerPort, const QString& name, QObject * parent)
+SSDPHandler::SSDPHandler(WebServer* webserver, quint16 flatBufPort, quint16 protoBufPort, quint16 jsonServerPort, quint16 sslPort, const QString& name, QObject * parent)
: SSDPServer(parent)
, _webserver(webserver)
, _localAddress()
, _NCA(nullptr)
{
setFlatBufPort(flatBufPort);
+ setProtoBufPort(protoBufPort);
setJsonServerPort(jsonServerPort);
+ setSSLServerPort(sslPort);
setHyperionName(name);
}
@@ -85,6 +87,14 @@ void SSDPHandler::handleSettingsUpdate(settings::type type, const QJsonDocument&
}
}
+ if(type == settings::PROTOSERVER)
+ {
+ if(obj["port"].toInt() != SSDPServer::getProtoBufPort())
+ {
+ SSDPServer::setProtoBufPort(obj["port"].toInt());
+ }
+ }
+
if(type == settings::JSONSERVER)
{
if(obj["port"].toInt() != SSDPServer::getJsonServerPort())
@@ -93,6 +103,14 @@ void SSDPHandler::handleSettingsUpdate(settings::type type, const QJsonDocument&
}
}
+ if(type == settings::WEBSERVER)
+ {
+ if(obj["sslPort"].toInt() != SSDPServer::getSSLServerPort())
+ {
+ SSDPServer::setSSLServerPort(obj["sslPort"].toInt());
+ }
+ }
+
if (type == settings::GENERAL)
{
if (obj["name"].toString() != SSDPServer::getHyperionName())
@@ -199,7 +217,21 @@ QString SSDPHandler::buildDesc() const
/// %2 friendly name Hyperion 2.0.0 (192.168.0.177)
/// %3 modelNumber 2.0.0
/// %4 serialNumber / UDN (H ID) Fjsa723dD0....
- return SSDP_DESCRIPTION.arg(getBaseAddress(), QString("Hyperion (%1)").arg(_localAddress), QString(HYPERION_VERSION), _uuid);
+ /// %5 json port 19444
+ /// %6 ssl server port 8092
+ /// %7 protobuf port 19445
+ /// %8 flatbuf port 19400
+
+ return SSDP_DESCRIPTION.arg(
+ getBaseAddress(),
+ QString("Hyperion (%1)").arg(_localAddress),
+ QString(HYPERION_VERSION),
+ _uuid,
+ QString::number(SSDPServer::getJsonServerPort()),
+ QString::number(SSDPServer::getSSLServerPort()),
+ QString::number(SSDPServer::getProtoBufPort()),
+ QString::number(SSDPServer::getFlatBufPort())
+ );
}
void SSDPHandler::sendAnnounceList(bool alive)
diff --git a/libsrc/webserver/QtHttpClientWrapper.cpp b/libsrc/webserver/QtHttpClientWrapper.cpp
index 37b148a6..68bca8e0 100644
--- a/libsrc/webserver/QtHttpClientWrapper.cpp
+++ b/libsrc/webserver/QtHttpClientWrapper.cpp
@@ -153,7 +153,7 @@ void QtHttpClientWrapper::onClientDataReceived (void)
case RequestParsed: // a valid request has ben fully parsed
{
// Catch websocket header "Upgrade"
- if(m_currentRequest->getHeader(QtHttpHeader::Upgrade) == "websocket")
+ if(m_currentRequest->getHeader(QtHttpHeader::Upgrade).toLower() == "websocket")
{
if(m_websocketClient == Q_NULLPTR)
{
diff --git a/src/hyperion-osx/hyperion-osx.cpp b/src/hyperion-osx/hyperion-osx.cpp
index 4842c65d..bf2c08da 100644
--- a/src/hyperion-osx/hyperion-osx.cpp
+++ b/src/hyperion-osx/hyperion-osx.cpp
@@ -34,7 +34,7 @@ int main(int argc, char ** argv)
// create the option parser and initialize all parameters
Parser parser("OSX capture application for Hyperion. Will automatically search a Hyperion server if -a option isn't used. Please note that if you have more than one server running it's more or less random which one will be used.");
- Option & argDisplay = parser.add ('d', "display", "Set the display to capture [default: %1]", "0");
+ IntOption & argDisplay = parser.add ('d', "display", "Set the display to capture [default: %1]", "0");
IntOption & argFps = parser.add ('f', "framerate", "Capture frame rate [default: %1]", "10", 1, 25);
IntOption & argWidth = parser.add (0x0, "width", "Width of the captured image [default: %1]", "160", 160);
IntOption & argHeight = parser.add (0x0, "height", "Height of the captured image [default: %1]", "160", 160);
@@ -54,7 +54,7 @@ int main(int argc, char ** argv)
}
OsxWrapper osxWrapper
- (parser.isSet(argDisplay), argWidth.getInt(parser), argHeight.getInt(parser), 1000 / argFps.getInt(parser));
+ (argDisplay.getInt(parser), argWidth.getInt(parser), argHeight.getInt(parser), 1000 / argFps.getInt(parser));
if (parser.isSet(argScreenshot))
{
diff --git a/src/hyperion-qt/hyperion-qt.cpp b/src/hyperion-qt/hyperion-qt.cpp
index 8d1b0b82..5dff785d 100644
--- a/src/hyperion-qt/hyperion-qt.cpp
+++ b/src/hyperion-qt/hyperion-qt.cpp
@@ -34,7 +34,7 @@ int main(int argc, char ** argv)
// create the option parser and initialize all parameters
Parser parser("Qt interface capture application for Hyperion");
- Option & argDisplay = parser.add ('d', "display", "Set the display to capture [default: %1]","0");
+ IntOption & argDisplay = parser.add ('d', "display", "Set the display to capture [default: %1]", "0");
IntOption & argFps = parser.add ('f', "framerate", "Capture frame rate [default: %1]", "10", 1, 25);
IntOption & argCropLeft = parser.add (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
IntOption & argCropRight = parser.add (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)");
@@ -63,7 +63,7 @@ int main(int argc, char ** argv)
argCropTop.getInt(parser),
argCropBottom.getInt(parser),
argSizeDecimation.getInt(parser),
- parser.isSet(argDisplay));
+ argDisplay.getInt(parser));
if (parser.isSet(argScreenshot))
{
diff --git a/src/hyperiond/console.h b/src/hyperiond/console.h
index 52a76687..98469960 100644
--- a/src/hyperiond/console.h
+++ b/src/hyperiond/console.h
@@ -14,21 +14,5 @@ void CreateConsole()
freopen_s(&fDummy, "CONOUT$", "w", stdout);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONIN$", "r", stdin);
- //std::cout.clear();
- //std::clog.clear();
- //std::cerr.clear();
- //std::cin.clear();
-
-
- /*// std::wcout, std::wclog, std::wcerr, std::wcin
- HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- HANDLE hConIn = CreateFile(_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
- SetStdHandle(STD_ERROR_HANDLE, hConOut);
- SetStdHandle(STD_INPUT_HANDLE, hConIn);
- std::wcout.clear();
- std::wclog.clear();
- std::wcerr.clear();
- std::wcin.clear();
- */
+ SetConsoleTitle(TEXT("Hyperion"));
}
diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp
index 30fbe711..197518e5 100644
--- a/src/hyperiond/hyperiond.cpp
+++ b/src/hyperiond/hyperiond.cpp
@@ -302,7 +302,12 @@ void HyperionDaemon::startNetworkServices()
sslWsThread->start();
// Create SSDP server in thread
- _ssdp = new SSDPHandler(_webserver, getSetting(settings::FLATBUFSERVER).object()["port"].toInt(), getSetting(settings::JSONSERVER).object()["port"].toInt(), getSetting(settings::GENERAL).object()["name"].toString());
+ _ssdp = new SSDPHandler(_webserver,
+ getSetting(settings::FLATBUFSERVER).object()["port"].toInt(),
+ getSetting(settings::PROTOSERVER).object()["port"].toInt(),
+ getSetting(settings::JSONSERVER).object()["port"].toInt(),
+ getSetting(settings::WEBSERVER).object()["sslPort"].toInt(),
+ getSetting(settings::GENERAL).object()["name"].toString());
QThread *ssdpThread = new QThread(this);
ssdpThread->setObjectName("SSDPThread");
_ssdp->moveToThread(ssdpThread);