var isTest = (location.hostname === "localhost" || location.hostname === "127.0.0.1" || location.href.indexOf("file://") != -1); var controlInfos = { "version": 'https://github.com/gpeter62/ESP_UniClock', "maxDigits": "Number of tubes", "maxBrightness": "MAX Brightness", "currentDate": "Date", "currentTime": "Time", "temperature": "Temperature sensor #1", "temperature2": "Temperature sensor #2", "humidity": "Humidity sensor #1", "humidity2": "Humidity sensor #2", "pressure": "Pressure sensor #1", "lux": "Lux sensor current value", "rssi": "WiFi RSSI level dB (connection quality)", "wifiMode": "WiFi Client or Access Point", "alarmEnable": "Switch ON/OFF alarm", "alarmTime": "Alarm time (hour/minute)", "alarmPeriod": "Alarm maximum length (sec)", //Tube display settings "utc_offset": 'Timezone setting. https://en.wikipedia.org/wiki/List_of_time_zones_by_country', "enableDST": "Daylight Saving Time ON/OFF", "set12_24": "Clock display 12 / 24 hours", "showZero": "Show starting zero on hours", "enableBlink": "ON / OFF", "interval": "Cathode protect interval (minutes)", "enableAutoShutoff": "Enable automatic day/night switch", "dayTime": "Day starts (manual brightness control)", "nightTime": "Night starts (manual brightness control)", "dayBright": "Day brightness", "nightBright": "Night brightness", "manualOverride": "Manual Day/Night change", "animMode": "Tube animation mode: 0=OFF, 1-5: Animations 6-7: Random", "dateMode": "0:dd/mm/yyyy 1:mm/dd/yyyy 2:yyyy/mm/dd", "tempCF": "Celsius / Fahrenheit display", "enableTimeDisplay": "Enable time&date display (Use OFF for thermometers)" , "dateStart": "Date display start: Date is shown between Start/End seconds", "dateEnd": "Date display end", "tempStart": "Temperature display time slice start", "tempEnd": "Temperature display end", "humidStart": "Humidity display time slice start", "humidEnd": "Humidity display end", "dateRepeatMin": "Date is shown in every xx minutes. 0 = Disable date display", "tempRepeatMin": "Temperature/humidity is shown in every xx minutes. 0 = Disable temp/humid display", "enableDoubleBlink": "Enable both blinking dots", "enableAutoDim": "Enable auto brightness control (if sensor is installed)", "enableRadar": "Enable Radar/Pir tube switch (if sensor is installed)", "radarTimeout": "If Radar is used, automatic switch off after this timeout (minutes)", //RGB settings "rgbDir" : "RGB animation direction (left/right)", "rgbEffect": "RGB animation#", "rgbBrightness": "RGB leds brightness 0..255", "rgbFixColor": "RGB color, if FixColor Effect is used", "rgbSpeed": "RGB animation speed", "wledEnable": "Let SignalRGB control the LEDs: the clock shows up there as a WLED device", "wledDarkWithTubes": "LEDs stay dark while the tubes / backlight are off, also when SignalRGB is running", "wledUseBrightness": "Scale SignalRGB colours by RGB Brightness (and auto dim). Off: colours as sent", "wledLive": "SignalRGB is sending colours right now", //Wifi settings "wifiSsid": "WiFi network SSID to connect", "wifiPsw": "WiFI password", "ApSsid": "AccessPoint name, if standalone mode is used", "ApPsw": "AP password", "NtpServer": "Timeserver name, using WiFi. (Default is: pool.ntp.org)", "mqttBrokerAddr": "MQTT server address, if MQTT used", "mqttBrokerUser": "MQTT user", "mqttBrokerPsw": "MQTT password", "mqttBrokerRefresh": "MQTT send data in every xx sec", "mqttEnable": "Enable/Disable MQTT refresh", "firmware": "http server + firmware name to download new firmware", "corrT0": "Temperature sensor#1 correction", "corrT1": "Temperature sensor#2 correction", "corrH0": "Humidity sensor#1 correction", "corrH1": "Humidity sensor#2 correction" , "cathProtMin": "Cathode Protect procedure (minutes)", "FW": "firmware code", "tubeDriver": "Tube driver modul" }; //Example config that UI recieves var configuration = { //Main screen "version": "UniClock 3.0", "maxDigits": 6, "maxBrightness": 10, "currentDate": "2020.10.24", "currentTime": "15:01", "temperature": 22.1, "temperature2": 255, "humidity": 45, "humidity2": 255, "pressure": 255, "lux": 100, "rssi": 0, "wifiMode": true, "alarmEnable": false, "alarmTime": "6:30", "alarmPeriod": 15, "enableRadar": false, "radarTimeout": 5, //Tube display settings "utc_offset": 1, "enableDST": true, "set12_24": true, "showZero": true, "enableBlink": true, "interval": 15, "enableAutoShutoff": true, "dayTime": "7:00", "nightTime": "22:00", "dayBright": 10, "nightBright": 3, "manualOverride": true, "animMode": 6, "dateMode": 2, // 0:dd/mm/yyyy 1:mm/dd/yyyy 2:yyyy/mm/dd "tempCF": false, //Temperature Celsius / Fahrenheit "enableTimeDisplay": true, "dateStart": 45, "dateEnd": 50, "tempStart": 35, "tempEnd": 40, "humidStart": 40, "humidEnd": 45, "dateRepeatMin": 3, "tempRepeatMin": 1, "enableDoubleBlink": true, "enableAutoDim": false, //RGB settings "rgbDir" : true, "rgbEffect": 1, "rgbBrightness": 100, "rgbFixColor": 150, "rgbSpeed": 50, "wledEnable": false, "wledDarkWithTubes": true, "wledUseBrightness": true, "wledLive": false, //Wifi settings "wifiSsid": "mywifi", "wifiPsw": "mypsw", "ApSsid": "UniClock", "ApPsw": "uniclock", "NtpServer": "pool.ntp.org", "mqttBrokerAddr": "10.0.99.12", "mqttBrokerUser": "mqtt", "mqttBrokerPsw": "mqttPW", "mqttBrokerRefresh": 30, "mqttEnable": false, "firmware": "http://server/fw.bin", "corrT0": 0.0, "corrT1": 0.0, "corrH0": 0.0, "corrH1": 0.0, "cathProtMin": 5, "FW": "fw", "tubeDriver": "xxx" }; var isMouseDown = 0; //Runs, when HTML document is fully loaded $(document).ready(function(){ $(document).on('mousedown touchstart',function(event) { ++isMouseDown; }); $(document).on('mouseup touchend',function(event) { --isMouseDown; }); if(isTest){ Init(); setCurrentInfos(); } else{ getConfiguration(); //Set current infos, like time, humidity and temperature getCurrentInfos(); } }); function setLocalPagination(){ $('[page]').not('[hidden]').each(function(){ var page = $(this).attr('page'); $('#menu tr').append(''); }); } function getConfiguration(){ $.get('/getConfiguration/').done(function(data){ configuration = data; }).always(function(){ Init(); }); } function sendMsgToArduino(key,value) { if(isTest){ console.log(key + " " + value); } else{ $.post('/saveSetting/', {"key" : key ,"value" : value }).done(function(data){ console.log(data); }); } } var COLORSATURATION = 255; var WHITE_INDEX = 192; function getColorFrom(WheelPos){ if (WheelPos == WHITE_INDEX) return RgbColor(COLORSATURATION/2, COLORSATURATION/2, COLORSATURATION/2); WheelPos = 255 - WheelPos; if(WheelPos < 85) { return RgbColor(255 - WheelPos * 3, 0, WheelPos * 3); } else if(WheelPos < 170) { WheelPos -= 85; return RgbColor(0, WheelPos * 3, 255 - WheelPos * 3); } else { WheelPos -= 170; return RgbColor(WheelPos * 3, 255 - WheelPos * 3, 0); } } function RgbColor(r, g, b){ return 'rgb('+r+','+g+','+b+')'; } function setPreviewColor(){ var color = getColorFrom($('#rgbFixColor').val()); $('#selectedColor').css('background-color',color); } function setCurrentInfos(){ $('#currentTime').html(getCurrentDate(configuration["currentDate"]) + " " + configuration["currentTime"]); $('#lux').html(configuration["lux"]); $('#rssi').html(configuration["rssi"]); $('#wledLive').html(configuration["wledLive"] ? "yes" : "no"); $('#pressure').html(round(configuration["pressure"],1)); $('#humidity').html(round(configuration["humidity"],1)); $('#humidity2').html(round(configuration["humidity2"],1)); $('#temperature').html(getTemperature(configuration["temperature"])); $('#temperature2').html(getTemperature(configuration["temperature2"])); $('#temperature, #temperature2').toggleClass('fahrenheit',configuration["tempCF"]); } function round(value, decimals) { return parseFloat(value).toFixed(decimals); //return Number(Math.round(value+'e'+decimals)+'e-'+decimals); } function getTemperature(temperatureInC){ if(configuration["tempCF"]){ //Fahrenheit return round(temperatureInC * 1.8 + 32,1); } else{ return round(temperatureInC,1); } } function getControlInfo(index){ return controlInfos[index]; } //Contains the most important initializes function Init(){ $('#dayBright, #nightBright').attr('max',configuration['maxBrightness']); document.title = configuration['version']; $('#versionHeader').html(configuration['version']); setLocalPagination(); $('[pagemenu]').on('click',function(){ $('.menu-item.active').removeClass('active'); $('[page].active').removeClass('active'); $(this).addClass('active'); $('[page="'+$(this).attr('pagemenu')+'"]').addClass('active'); if($(this).attr('pagemenu') == 'settings'){ getClockDetails(); } }); $('.menu-item').eq(0).trigger('click'); $('#rgbFixColor').on('input',function(){ setPreviewColor(); }); var sliderFadeOutTimer; function setFadeOutTimer(element){ setTimeout(function(){ if(isMouseDown > 0){ clearTimeout(sliderFadeOutTimer); sliderFadeOutTimer = setFadeOutTimer(element); } else{ $(element).addClass('fading').fadeOut('slow',function(){ $(this).remove(); }); } },600); } $('input[type="range"]').on('mousedown touchstart input',function(){ clearTimeout(sliderFadeOutTimer); var id = $(this).attr('id'); var parent = $(this).closest('.control-holder'); $('[sliderfor]:not(.fading)').each(function(){ if($(this).attr('sliderfor') != id && !$(this).hasClass('fading')){ $(this).addClass('fading').fadeOut('slow',function(){ $(this).remove(); }); } }); if($(parent).children('.slider-info').length == 0){ $(parent).append('
'); $(parent).children('.slider-info').fadeIn(300); } var _this = $(parent).children('.slider-info').text($(this).val()); sliderFadeOutTimer = setFadeOutTimer(_this); }); $('.form label').on('click',function(){ var id = ''; if(!!$(this).attr('for')){ id = $(this).attr('for'); } else{ id = $(this).closest('.control-holder').find('input, select, .info').eq(0).attr('id'); } var info = getControlInfo(id); if(!!info){ showPopUp($(this).text(), info, 450, true); } }); $('#popup-close-btn, #info-popup').on('click',function(){ if($('#info-popup').hasClass('cantClose')){ return; } else{ $('#info-popup').fadeOut(450); } }); $("#popup-box").click(function(event){ event.stopPropagation(); }); //binds custom switch functionality $('.switcher').on('click',function(){ $('#'+$(this).attr('for')).prop('checked',!$('#'+$(this).attr('for')).is(":checked")).trigger('change'); }); //binds custom switch text functionality $('.switcher-text').on('click',function(){ $('#'+$(this).attr('for')).prop('checked',$(this).hasClass('right')).trigger('change'); }); //fills autogenerated select drop downs /* Possible css class: two-digit - fills with two digit values if value lower than 10 Possible attributes: min (mandatory) - auto generation's minimum value max (mandatory) - auto generation's maximum value step (optional) - auto generation's step, if not set, default is 1 prefix (optional) - concatanate this string before value suffix (optional) - concatanate this string after value */ $('.number-select').each(function(){ let from = $(this).attr('min')*1; let to = $(this).attr('max')*1; let step = !!$(this).attr('step') ? $(this).attr('step') : 1; for(let i = from; i < to+1; i){ let value = $(this).hasClass('two-digit') ? formatToTwoDigit(i) : i; let text_value = value; if($(this).attr('prefix') != null){ text_value = $(this).attr('prefix') + text_value } if($(this).attr('suffix') != null){ text_value += $(this).attr('suffix') } $(this).append(''); i += step*1; } }); //fills the inputs with configuration values for(var index in configuration){ let value = configuration[index]; if(index == 'dayTime' || index == 'nightTime' || index == 'alarmTime'){ value = value.split(':'); $('#'+index+'Hours').val(formatToTwoDigit(value[0])); $('#'+index+'Minutes').val(formatToTwoDigit(value[1])); } else if(index == 'version' ){ $('#'+index).html(value); } else if(index == 'utc_offset' || index == 'maxBrightness' || index == 'dayBright' || index == 'nightBright' || index == 'animMode' || index == 'rgbBrightness' || index == 'rgbFixColor' || index == 'rgbSpeed' || index == 'rgbEffect' || index == 'interval' || index == 'alarmPeriod' || index == 'radarTimeout' || index == 'dateRepeatMin' || index == 'dateMode' || index == 'dateStart' || index == 'dateEnd' || index == 'timeStart' || index == 'timeEnd' || index == 'tempStart' || index == 'tempEnd' || index == 'humidStart' || index == 'humidEnd' || index == 'mqttBrokerRefresh' || index == 'tempRepeatMin' || index == 'wifiSsid' || index == 'wifiPsw' || index == 'ApSsid' || index == 'ApPsw' || index == 'mqttBrokerAddr' || index == 'NtpServer' || index == 'mqttBrokerUser' || index =='mqttBrokerPsw' || index == 'firmware' || index == 'corrT0' || index == 'corrT1' || index == 'corrH0' || index == 'corrH1' || index == 'cathProtMin' ){ $('#'+index).val(value); } else if((index == 'enableDST' || index == 'set12_24' || index == 'showZero' || index == 'enableBlink' || index == 'enableAutoShutoff' || index == 'alarmEnable' || index == 'rgbDir' || index == 'manualOverride' || index == 'enableAutoDim' || index == 'enableRadar' || index == 'enableDoubleBlink' || index == 'enableTimeDisplay' || index == 'mqttEnable' || index == 'tempCF' || index == "wifiMode" || index == 'wledEnable' || index == 'wledDarkWithTubes' || index == 'wledUseBrightness' ) && !!value ){ $('#'+index).prop('checked',true); } else if(index == "maxDigits"){ //TODO } } $('.radar-holder').toggleClass('hidden',configuration['radarTimeout'] == 0); $('.mqtt-holder').toggleClass('hidden',configuration['mqttBrokerRefresh'] == 0); $('.lux-holder').toggleClass('hidden',configuration['lux'] == 255); $('.pressure-holder').toggleClass('hidden',configuration['pressure'] == 255); $('.humidity-holder').toggleClass('hidden',configuration['humidity'] == 255); $('.humidity-holder2').toggleClass('hidden',configuration['humidity2'] == 255); $('.temperature-holder').toggleClass('hidden',configuration['temperature'] == 255); $('.temperature-holder2').toggleClass('hidden',configuration['temperature2'] == 255); $('.rgb-holder').toggleClass('hidden',configuration['rgbEffect'] == 255); $('.wled-holder').toggleClass('hidden',configuration['wledEnable'] === undefined); //firmware without USE_WLED_REALTIME $('.tube-holder').toggleClass('hidden',configuration['tubeDriver'] == "DUMMY"); $('.wordclock-holder').toggleClass('hidden',configuration['tubeDriver'] == "WORDCLOCK"); $('.sensors-holder').toggleClass('hidden',configuration['temperature'] == 255); setPreviewColor(); //sets a possible good timezone, if not already set //if(!configuration['utc_offset']){ // //Intl.DateTimeFormat().resolvedOptions().timeZone <- I am in this Zone // var tryToFindCurrentZone = -(new Date().getTimezoneOffset() / 60); // $('#utc_offset').val(tryToFindCurrentZone); //} setTimeout(function(){ $('input, select').on('change',function(){ var value = ''; if($(this).attr('id').indexOf("Hours") == -1 || $(this).attr('id').indexOf("Minutes") == -1){ if($(this).attr('type') == 'checkbox'){ value = $(this).is(':checked'); } else{ value = $(this).val(); } sendMsgToArduino($(this).attr('id'), value); } else{ var key = $(this).attr('id').replace('Hours','').replace('Minutes',''); value = $('#'+key+'Hours').val() + ":" + $('#'+key+'Minutes').val(); sendMsgToArduino(key, value); } }); $('#dateMode').on('change',function(){ configuration["dateMode"] = $(this).val(); setCurrentInfos(); }); $('#tempCF').on('change',function(){ configuration["tempCF"] = !configuration["tempCF"]; setCurrentInfos(); }); },200); } function showPopUp(header, content, timeout, canClose){ $('#popup-box h2').text(header); $('#popup-box .content').html(content); $('#info-popup').toggleClass('cantClose',!canClose); $('#info-popup').fadeIn(timeout); } function areYouSure(fn){ if (confirm("Are you sure to run " + fn + "?")) { if(fn == "reset"){ callReset(); } else if(fn == "factoryreset"){ callFactoryReset(); } else if(fn == "firmwareupdate"){ callFirmwareUpdate(); } else if(fn == "cathodeProtect"){ callCathodeProtect(); } } } function callReset(){ if(isTest){return;} $.post('/reset/', {}).done(function(data){ location.reload(); }).always(function(){ }); } function callFactoryReset(){ if(isTest){return;} $.post('/factoryreset/', {}).done(function(data){ location.reload(); }).always(function(){ }); } function callFirmwareUpdate(){ if(isTest){return;} showPopUp("Firmware is updating", "Please do not turn off the clock", 300, false); $.post('/firmwareupdate/', {}).done(function(data){ if(!!data.header){ showPopUp(data.header, data.content, 300, data.canClose); } }).always(function(){ }); } function callCathodeProtect(){ if(isTest){return;} $.post('/cathodeProtect/', {}).done(function(data){ location.reload(); }).always(function(){ }); } function getClockDetails(){ if(isTest){return;} $.get('/getClockDetails/').done(function(data){ $('#clock-details').html(data); }).always(function(){ }); } function getCurrentInfos(){ if(isTest){return;} $.get('/getCurrentInfos/').done(function(data){ for(var i in data){ configuration[i] = data[i]; } if(!!data["popupMsg"] && data["popupMsg"].length > 0){ showPopUp("Info", data["popupMsg"], 300, true); } setCurrentInfos(); setTimeout(getCurrentInfos,20000); //refreshes time every 20 second by calling itself }).always(function(){ }); } function getCurrentDate(date){ var splittedDate = date.split('.'); var yyyy = splittedDate[0]; var mm = splittedDate[1]; var dd = splittedDate[2]; if(configuration["dateMode"] == 0){ return dd+"/"+mm+"/"+yyyy; } else if(configuration["dateMode"] == 1){ return mm+"/"+dd+"/"+yyyy; } else if(configuration["dateMode"] == 2){ return yyyy+"/"+mm+"/"+dd; } else{ return yyyy+"/"+mm+"/"+dd; //if dateMode?? // 0:dd/mm/yyyy 1:mm/dd/yyyy 2:yyyy/mm/dd } } //Gets the current time from browser and gives back as readable format function getCurrentTime(){ var today = new Date(); var dd = formatToTwoDigit(today.getDate()); var mm = formatToTwoDigit(today.getMonth()+1); var yyyy = today.getFullYear(); var hour = formatToTwoDigit(today.getHours()); var minute = formatToTwoDigit(today.getMinutes()); if(configuration["dateMode"] == 0){ return dd+"-"+mm+"-"+yyyy+" "+hour+":"+minute; } else if(configuration["dateMode"] == 1){ return mm+"-"+dd+"-"+yyyy+" "+hour+":"+minute; } else if(configuration["dateMode"] == 2){ return yyyy+"-"+mm+"-"+dd+" "+hour+":"+minute; } else{ return yyyy+"-"+mm+"-"+dd+" "+hour+":"+minute; //if dateMode?? // 0:dd/mm/yyyy 1:mm/dd/yyyy 2:yyyy/mm/dd } } //if number is lower than 10, adds a zero function formatToTwoDigit(number){ return ("0" + number).slice(-2); }