var ledsCustomCfgInitialized = false; var finalLedArray = []; var conf_editor = null; var aceEdt = null; function round(number) { var factor = Math.pow(10, 4); var tempNumber = number * factor; var roundedTempNumber = Math.round(tempNumber); return roundedTempNumber / factor; }; function createLedPreview(leds, origin){ if (origin == "classic"){ $('#previewcreator').html($.i18n('conf_leds_layout_preview_originCL')); $('#leds_preview').css("padding-top", "56.25%"); } else if(origin == "text"){ $('#previewcreator').html($.i18n('conf_leds_layout_preview_originTEXT')); $('#leds_preview').css("padding-top", "56.25%"); } else if(origin == "matrix"){ $('#previewcreator').html($.i18n('conf_leds_layout_preview_originMA')); $('#leds_preview').css("padding-top", "100%"); } $('#previewledcount').html($.i18n('conf_leds_layout_preview_totalleds', leds.length)); $('#previewledpower').html($.i18n('conf_leds_layout_preview_ledpower', ((leds.length * 0.06)*1.1).toFixed(1))); $('.st_helper').css("border", "8px solid grey"); var canvas_height = $('#leds_preview').innerHeight(); var canvas_width = $('#leds_preview').innerWidth(); var leds_html = ""; for(var idx=0; idx'+((led.name) ? led.name : idx)+''; } $('#leds_preview').html(leds_html); $('#ledc_0').css({"background-color":"black","z-index":"12"}); $('#ledc_1').css({"background-color":"grey","z-index":"11"}); $('#ledc_2').css({"background-color":"#A9A9A9","z-index":"10"}); if($('#leds_prev_toggle_num').hasClass('btn-success')) $('.led_prev_num').css("display", "inline"); // update ace Editor content aceEdt.set(finalLedArray); } function createClassicLedLayoutSimple( ledstop,ledsleft,ledsright,ledsbottom,position,reverse ){ let params = { ledstop: 0, ledsleft: 0, ledsright: 0, ledsbottom: 0, ledsglength: 0, ledsgpos: 0, position: 0, ledsHDepth: 0.08, ledsVDepth: 0.05, overlap: 0, edgeVGap: 0, ptblh: 0, ptblv: 1, ptbrh: 1, ptbrv: 1, pttlh: 0, pttlv: 0, pttrh: 1, pttrv: 0, reverse:false }; params.ledstop = ledstop; params.ledsleft = ledsleft; params.ledsright = ledsright; params.ledsbottom = ledsbottom; params.position = position; params.reverse = reverse; return createClassicLedLayout( params ); } function createClassicLedLayout( params ){ //helper var edgeHGap = params.edgeVGap/(16/9); var ledArray = []; function createFinalArray(array){ var finalLedArray = []; for(var i = 0; i 0){ while( times-- ){ array.push(array.shift()) } return array; } else { while( times++ ){ array.unshift(array.pop()) } return array; } } function valScan(val) { if(val > 1) return 1; if(val < 0) return 0; return val; } function ovl(scan,val) { if(scan == "+") return valScan(val += params.overlap); else return valScan(val -= params.overlap); } function createLedArray(hmin, hmax, vmin, vmax){ hmin = round(hmin); hmax = round(hmax); vmin = round(vmin); vmax = round(vmax); ledArray.push({ "hmin": hmin, "hmax": hmax, "vmin": vmin, "vmax": vmax }); } function createTopLeds(){ var steph = (params.pttrh - params.pttlh - (2*edgeHGap))/params.ledstop; var stepv = (params.pttrv - params.pttlv)/params.ledstop; for (var i = 0; i-1; i--){ var hmin = ovl("-",params.ptblh+(steph*Number([i]))+edgeHGap); var hmax = ovl("+",params.ptblh+(steph*Number([i+1]))+edgeHGap); var vmax= params.ptblv+(stepv*Number([i])); var vmin = vmax-params.ledsHDepth; createLedArray(hmin, hmax, vmin, vmax); } } function createLeftLeds(){ var steph = (params.ptblh - params.pttlh)/params.ledsleft; var stepv = (params.ptblv - params.pttlv - (2*params.edgeVGap))/params.ledsleft; for (var i = params.ledsleft-1; i>-1; i--){ var hmin = params.pttlh+(steph*Number([i])); var hmax = hmin+params.ledsVDepth; var vmin = ovl("-",params.pttlv+(stepv*Number([i]))+params.edgeVGap); var vmax = ovl("+",params.pttlv+(stepv*Number([i+1]))+params.edgeVGap); createLedArray(hmin, hmax, vmin, vmax); } } //rectangle createTopLeds(); createRightLeds(); createBottomLeds(); createLeftLeds(); //check led gap pos if (params.ledsgpos+params.ledsglength > ledArray.length) { var mpos = Math.max(0,ledArray.length-params.ledsglength); //$('#ip_cl_ledsgpos').val(mpos); ledsgpos = mpos; } //check led gap length if(params.ledsglength >= ledArray.length) { //$('#ip_cl_ledsglength').val(ledArray.length-1); params.ledsglength = ledArray.length-params.ledsglength-1; } if(params.ledsglength != 0){ ledArray.splice(params.ledsgpos, params.ledsglength); } if (params.position != 0){ rotateArray(ledArray, params.position); } if (params.reverse) ledArray.reverse(); return createFinalArray(ledArray); } function createClassicLeds(){ //get values let params = { ledstop : parseInt($("#ip_cl_top").val()), ledsbottom : parseInt($("#ip_cl_bottom").val()), ledsleft : parseInt($("#ip_cl_left").val()), ledsright : parseInt($("#ip_cl_right").val()), ledsglength : parseInt($("#ip_cl_glength").val()), ledsgpos : parseInt($("#ip_cl_gpos").val()), position : parseInt($("#ip_cl_position").val()), reverse : $("#ip_cl_reverse").is(":checked"), //advanced values ledsVDepth : parseInt($("#ip_cl_vdepth").val())/100, ledsHDepth : parseInt($("#ip_cl_hdepth").val())/100, edgeVGap : parseInt($("#ip_cl_edgegap").val())/100/2, //cornerVGap : parseInt($("#ip_cl_cornergap").val())/100/2, overlap : $("#ip_cl_overlap").val()/100, //trapezoid values % -> float ptblh : parseInt($("#ip_cl_pblh").val())/100, ptblv : parseInt($("#ip_cl_pblv").val())/100, ptbrh : parseInt($("#ip_cl_pbrh").val())/100, ptbrv : parseInt($("#ip_cl_pbrv").val())/100, pttlh : parseInt($("#ip_cl_ptlh").val())/100, pttlv : parseInt($("#ip_cl_ptlv").val())/100, pttrh : parseInt($("#ip_cl_ptrh").val())/100, pttrv : parseInt($("#ip_cl_ptrv").val())/100, } finalLedArray = createClassicLedLayout( params ); //check led gap pos if (params.ledsgpos+params.ledsglength > finalLedArray.length) { var mpos = Math.max(0,finalLedArray.length-params.ledsglength); $('#ip_cl_ledsgpos').val(mpos); } //check led gap length if(params.ledsglength >= finalLedArray.length) { $('#ip_cl_ledsglength').val(finalLedArray.length-1); } createLedPreview(finalLedArray, 'classic'); } function createMatrixLayout( ledshoriz, ledsvert, cabling, start){ // Big thank you to RanzQ (Juha Rantanen) from Github for this script // https://raw.githubusercontent.com/RanzQ/hyperion-audio-effects/master/matrix-config.js var parallel = false var leds = [] var hblock = 1.0 / ledshoriz var vblock = 1.0 / ledsvert if (cabling == "parallel"){ parallel = true } /** * Adds led to the hyperion config led array * @param {Number} x Horizontal position in matrix * @param {Number} y Vertical position in matrix */ function addLed (x, y) { var hscanMin = x * hblock var hscanMax = (x + 1) * hblock var vscanMin = y * vblock var vscanMax = (y + 1) * vblock hscanMin = round(hscanMin); hscanMax = round(hscanMax); vscanMin = round(vscanMin); vscanMax = round(vscanMax); leds.push({ hmin: hscanMin, hmax: hscanMax, vmin: vscanMin, vmax: vscanMax }) } var startYX = start.split('-') var startX = startYX[1] === 'right' ? ledshoriz - 1 : 0 var startY = startYX[0] === 'bottom' ? ledsvert - 1 : 0 var endX = startX === 0 ? ledshoriz - 1 : 0 var endY = startY === 0 ? ledsvert - 1 : 0 var forward = startX < endX var downward = startY < endY var x, y for (y = startY; downward && y <= endY || !downward && y >= endY; y += downward ? 1 : -1) { for (x = startX; forward && x <= endX || !forward && x >= endX; x += forward ? 1 : -1) { addLed(x, y) } if (!parallel) { forward = !forward var tmp = startX startX = endX endX = tmp } } return leds; } function createMatrixLeds(){ // Big thank you to RanzQ (Juha Rantanen) from Github for this script // https://raw.githubusercontent.com/RanzQ/hyperion-audio-effects/master/matrix-config.js //get values var ledshoriz = parseInt($("#ip_ma_ledshoriz").val()); var ledsvert = parseInt($("#ip_ma_ledsvert").val()); var cabling = $("#ip_ma_cabling").val(); var start = $("#ip_ma_start").val(); finalLedArray = createMatrixLayout(ledshoriz,ledsvert,cabling,start); createLedPreview(finalLedArray, 'matrix'); } function migrateLedConfig(slConfig){ var newLedConfig = {classic:{}, matrix:{}}; //Default Classic layout newLedConfig.classic = { "top" : 1, "bottom" : 0, "left" : 0, "right" : 0, "glength" : 0, "gpos" : 0, "position" : 0, "reverse" : false, "hdepth" : 8, "vdepth" : 5, "overlap" : 0, "edgegap" : 0 } //Move Classic layout newLedConfig.classic.top = slConfig.top; newLedConfig.classic.bottom = slConfig.bottom; newLedConfig.classic.left = slConfig.left; newLedConfig.classic.right = slConfig.right; newLedConfig.classic.glength = slConfig.glength; newLedConfig.classic.position = slConfig.position; newLedConfig.classic.reverse = slConfig.reverse; newLedConfig.classic.hdepth = slConfig.hdepth; newLedConfig.classic.vdepth = slConfig.vdepth; newLedConfig.classic.overlap = slConfig.overlap; //Default Matrix layout newLedConfig["matrix"] = { "ledshoriz": 1, "ledsvert" : 1, "cabling" : "snake", "start" : "top-left" } // Persit new structure requestWriteConfig({ledConfig:newLedConfig}) return newLedConfig } function isEmpty(obj) { for(var key in obj) { if(obj.hasOwnProperty(key)) return false; } return true; } $(document).ready(function() { // translate performTranslation(); //add intros if(window.showOptHelp) { createHintH("intro", $.i18n('conf_leds_device_intro'), "leddevice_intro"); createHintH("intro", $.i18n('conf_leds_layout_intro'), "layout_intro"); $('#led_vis_help').html('
'+$.i18n('conf_leds_layout_preview_l1')+'
'+$.i18n('conf_leds_layout_preview_l2')+'
'); } var slConfig = window.serverConfig.ledConfig; //Check, if structure is not aligned to expected -> migrate structure if ( isEmpty(slConfig.classic) ) { slConfig = migrateLedConfig( slConfig ); } //restore ledConfig - Classic for(var key in slConfig.classic) { if(typeof(slConfig.classic[key]) === "boolean") $('#ip_cl_'+key).prop('checked', slConfig.classic[key]); else $('#ip_cl_'+key).val(slConfig.classic[key]); } //restore ledConfig - Matrix for(var key in slConfig.matrix) { if(typeof(slConfig.matrix[key]) === "boolean") $('#ip_ma_'+key).prop('checked', slConfig.matrix[key]); else $('#ip_ma_'+key).val(slConfig.matrix[key]); } function saveValues() { var ledConfig = {classic:{}, matrix:{}}; for(var key in slConfig.classic) { if(typeof(slConfig.classic[key]) === "boolean") ledConfig.classic[key] = $('#ip_cl_'+key).is(':checked'); else if(Number.isInteger(slConfig.classic[key])) ledConfig.classic[key] = parseInt($('#ip_cl_'+key).val()); else ledConfig.classic[key] = $('#ip_cl_'+key).val(); } for(var key in slConfig.matrix) { if(typeof(slConfig.matrix[key]) === "boolean") ledConfig.matrix[key] = $('#ip_ma_'+key).is(':checked'); else if(Number.isInteger(slConfig.matrix[key])) ledConfig.matrix[key] = parseInt($('#ip_ma_'+key).val()); else ledConfig.matrix[key] = $('#ip_ma_'+key).val(); } requestWriteConfig({ledConfig}); } // check access level and adjust ui if(storedAccess == "default") { $('#texfield_panel').toggle(false); $('#previewcreator').toggle(false); } //Wiki link $('#leds_wl').append('

'+$.i18n('general_wiki_moreto',$.i18n('conf_leds_nav_label_ledlayout'))+buildWL("user/moretopics/ledarea","Wiki")+'

'); // bind change event to all inputs $('.ledCLconstr').bind("change", function() { valValue(this.id,this.value,this.min,this.max); createClassicLeds(); }); $('.ledMAconstr').bind("change", function() { valValue(this.id,this.value,this.min,this.max); createMatrixLeds(); }); // v4 of json schema with diff required assignment - remove when hyperion schema moved to v4 var ledschema = { "items": { "additionalProperties": false, "required": ["hmin", "hmax", "vmin", "vmax"], "properties": { "name": { "type": "string" }, "colorOrder": { "enum": ["rgb", "bgr", "rbg", "brg", "gbr", "grb"], "type": "string" }, "hmin": { "maximum": 1, "minimum": 0, "type": "number" }, "hmax": { "maximum": 1, "minimum": 0, "type": "number" }, "vmin": { "maximum": 1, "minimum": 0, "type": "number" }, "vmax": { "maximum": 1, "minimum": 0, "type": "number" } }, "type": "object" }, "type": "array" }; //create jsonace editor aceEdt = new JSONACEEditor(document.getElementById("aceedit"),{ mode: 'code', schema: ledschema, onChange: function(){ var success = true; try{ aceEdt.get(); } catch(err) { success = false; } if(success) { $('#leds_custom_updsim').attr("disabled", false); $('#leds_custom_save').attr("disabled", false); } else { $('#leds_custom_updsim').attr("disabled", true); $('#leds_custom_save').attr("disabled", true); } if ( window.readOnlyMode ) { $('#leds_custom_save').attr('disabled', true); } } }, window.serverConfig.leds); //TODO: HACK! No callback for schema validation - Add it! setInterval(function(){ if($('#aceedit table').hasClass('jsoneditor-text-errors')) { $('#leds_custom_updsim').attr("disabled", true); $('#leds_custom_save').attr("disabled", true); } },1000); $('.jsoneditor-menu').toggle(); // leds to finalLedArray finalLedArray = window.serverConfig.leds; // create and update editor $("#leddevices").off().on("change", function() { var generalOptions = window.serverSchema.properties.device; // Modified schema entry "hardwareLedCount" in generalOptions to minimum LedCount var ledType = $(this).val(); //philipshueentertainment backward fix if(ledType == "philipshueentertainment") ledType = "philipshue"; var specificOptions = window.serverSchema.properties.alldevices[ledType]; conf_editor = createJsonEditor('editor_container', { generalOptions : generalOptions, specificOptions : specificOptions, }); var values_general = {}; var values_specific = {}; var isCurrentDevice = (window.serverConfig.device.type == ledType); for(var key in window.serverConfig.device) { if (key != "type" && key in generalOptions.properties) values_general[key] = window.serverConfig.device[key]; }; conf_editor.getEditor("root.generalOptions").setValue( values_general ); if (isCurrentDevice) { var specificOptions_val = conf_editor.getEditor("root.specificOptions").getValue(); for(var key in specificOptions_val){ values_specific[key] = (key in window.serverConfig.device) ? window.serverConfig.device[key] : specificOptions_val[key]; }; conf_editor.getEditor("root.specificOptions").setValue( values_specific ); }; // change save button state based on validation result conf_editor.validate().length || window.readOnlyMode ? $('#btn_submit_controller').attr('disabled', true) : $('#btn_submit_controller').attr('disabled', false); conf_editor.on('change',function() { window.readOnlyMode ? $('#btn_cl_save').attr('disabled', true) : $('#btn_submit').attr('disabled', false); window.readOnlyMode ? $('#btn_ma_save').attr('disabled', true) : $('#btn_submit').attr('disabled', false); window.readOnlyMode ? $('#leds_custom_save').attr('disabled', true) : $('#btn_submit').attr('disabled', false); }); // led controller sepecific wizards $('#btn_wiz_holder').html(""); $('#btn_led_device_wiz').off(); if(ledType == "philipshue") { $('#root_specificOptions_useEntertainmentAPI').bind("change", function() { var ledWizardType = (this.checked) ? "philipshueentertainment" : ledType; var data = { type: ledWizardType }; var hue_title = (this.checked) ? 'wiz_hue_e_title' : 'wiz_hue_title'; changeWizard(data, hue_title, startWizardPhilipsHue); }); $("#root_specificOptions_useEntertainmentAPI").trigger("change"); } /* else if(ledType == "wled") { var ledWizardType = (this.checked) ? "wled" : ledType; var data = { type: ledWizardType }; var wled_title = 'wiz_wled_title'; changeWizard(data, wled_title, startWizardWLED); } */ else if(ledType == "atmoorb") { var ledWizardType = (this.checked) ? "atmoorb" : ledType; var data = { type: ledWizardType }; var atmoorb_title = 'wiz_atmoorb_title'; changeWizard(data, atmoorb_title, startWizardAtmoOrb); } else if(ledType == "cololight") { var ledWizardType = (this.checked) ? "cololight" : ledType; var data = { type: ledWizardType }; var cololight_title = 'wiz_cololight_title'; changeWizard(data, cololight_title, startWizardCololight); } else if(ledType == "yeelight") { var ledWizardType = (this.checked) ? "yeelight" : ledType; var data = { type: ledWizardType }; var yeelight_title = 'wiz_yeelight_title'; changeWizard(data, yeelight_title, startWizardYeelight); } function changeWizard(data, hint, fn) { $('#btn_wiz_holder').html("") createHint("wizard", $.i18n(hint), "btn_wiz_holder","btn_led_device_wiz"); $('#btn_led_device_wiz').off().on('click', data , fn); } }); //philipshueentertainment backward fix if(window.serverConfig.device.type == "philipshueentertainment") window.serverConfig.device.type = "philipshue"; // create led device selection var ledDevices = window.serverInfo.ledDevices.available; var devRPiSPI = ['apa102', 'apa104', 'ws2801', 'lpd6803', 'lpd8806', 'p9813', 'sk6812spi', 'sk6822spi', 'sk9822', 'ws2812spi']; var devRPiPWM = ['ws281x']; var devRPiGPIO = ['piblaster']; var devNET = ['atmoorb', 'cololight', 'fadecandy', 'philipshue', 'nanoleaf', 'tinkerforge', 'tpm2net', 'udpe131', 'udpartnet', 'udph801', 'udpraw', 'wled', 'yeelight']; var devUSB = ['adalight', 'dmx', 'atmo', 'hyperionusbasp', 'lightpack', 'paintpack', 'rawhid', 'sedu', 'tpm2', 'karate']; var optArr = [[]]; optArr[1]=[]; optArr[2]=[]; optArr[3]=[]; optArr[4]=[]; optArr[5]=[]; for (var idx=0; idx